Surprisingly this was an extremely hard to find piece of information on the topic. At least one that fit my need. There were lots of questions in various online posts, but no completely working answers with all the relevant details in one place.
I am going to document it here.
Aggregation router is a pair of Cisco 6506E in VSS mode, active-active. They have ip helper pointing to my DHCP server.
There was a pretty useful post about single DHCP server, multiple subnets on one interface here. But this does not work for my situation. He’s using a fairly simple network, and his DHCP server run on the gateway.
I have a gateway/router that aggregates multiple VLANs, one of which is a management VLAN that my DHCP server sits on. All the other VLANs has the DHCP relay helper address pointing to my DHCP server (see graph above).
Using the “shared-network” statement in dhcpd.conf does not work as that will pool all of the subnet declaration into that single network. This is why the blog post uses the classes along with “match if” statements to put DHCP client requests into the correct subnets. I have anywhere from 200 to 300+ servers in each VLAN, and they are a mix of gears/vendors. There is no way that I can use hardware (MAC) address, without it getting very complicated, not to mention the horror of maintaining that mapping.
ISC DHCP actually supports what I wanted out of the box. The trick was to make all the subnet declaration, but don’t use the “shared-network” statement. Make sure the DHCP relay are setup correctly, and when client make DHCP requests, they will arrive at the DHCP server with the relay address in it as the GIADDR (gateway IP address). The DHCP server will see that and know which subnet it should provide addresses from.
Here is the dhcpd.conf portion of the working config. Note that I also do PXE and kickstart boot from this dhcpd server.
authoritative;
# this is the most important line. It specifies the method
# to use to connect to the DNS server and update it.
ddns-update-style none;
ddns-domainname "example.com";
ignore client-updates;
option host-name = config-option server.ddns-hostname;
include "/etc/rndc.key";
option domain-name "example.com";
option domain-name-servers 10.1.14.10,10.1.14.11,10.1.14.12;
option time-offset -18000; # Pacific Standard Time
option ntp-servers 10.1.14.11;
one-lease-per-client off;
default-lease-time 86400;
max-lease-time 604800;
option ip-forwarding off;
# PXE
next-server install;
filename "/linux-install/pxelinux.0";
# Subnet for internal hosts
subnet 10.1.0.0 netmask 255.255.254.0 {
range 10.1.1.200 10.1.1.253;
option routers 10.1.0.1;
option subnet-mask 255.255.254.0;
#failover peer "dhcp";
}
subnet 10.1.2.0 netmask 255.255.254.0 {
range 10.1.3.200 10.1.3.253;
option routers 10.1.2.1;
option subnet-mask 255.255.254.0;
#failover peer "dhcp";
}
subnet 10.1.4.0 netmask 255.255.254.0 {
range 10.1.5.200 10.1.5.253;
option routers 10.1.4.1;
option subnet-mask 255.255.254.0;
#failover peer "dhcp";
}
....and so on....