Отказоустойчивость DHCP с помощью PXE

Отказоустойчивость DHCP с помощью PXE

Я пытаюсь настроить отказоустойчивость DHCP с загрузкой PXE, разрешенной с одного из серверов DHCP. Как того требует спецификация DHCP, я настроил отдельные пулы для «обычного» DHCP и для загрузки PXE. Моя конфигурация отказоустойчивости работает нормально, но конфигурация DHCP, которая должна отвечать на запросы PXE, больше не работает.

Предыстория: Я недавно обновился до AlmaLinux 9 (с CentOS 7), который работает на ISC DHCP 4.4. В старой конфигурации у меня не было DHCP failover, и я разрешил загрузку PXE со всего пула. Из-за истории аппаратных сбоев на нашем сайте я хочу настроить DHCP failover.

Для целей этой конфигурации давайте назовем систему, которая должна отвечать на запросы PXE, «первичным» DHCP-сервером. Вот фрагмент с /etc/dhcp/dhcpd/confэтого сервера. Обратите внимание, что я настроил отдельный пул только для обработки запросов PXE/BOOTP. (Извините за назидательный тон комментариев. Они предназначены для меня, поскольку я занимаюсь своими делами системного администратора.)

authoritative; # Send out acknowledgements to DHCP client queries.

failover peer "dhcp-failover" {
  primary; # declare this to be the primary server
  address 10.4.7.9;
  port 647;
  peer address 10.4.7.210;
  peer port 647;
  # How many seconds to wait before we assume that the other has failed.
  max-response-delay 30;
  # How many BNDUPD messages to send before receiving BNDACK.
  max-unacked-updates 10;
  # How many seconds to wait before disabling load balancing.
  load balance max seconds 3;
  # Maximum Client Lead Time = How long a lease may be renewed
  # without contacting the other DHCP peer.
  mclt 1800;
  # The split between primary and secondary. 128 means a
  # 50% split between peers; 255 means the primary handles
  # everything until it fails. 
  split 128;
}

# This is the primary DHCP server. Respond to BOOTP requests.
allow booting;
allow bootp;

option domain-name "company.example.com";
option time-offset -18000; # Eastern Standard Time

# Is this a DHCP query (as opposed to a BOOTP query)?
class "dhcp" {
      match if exists dhcp-message-type;
}
class "pxe" {
      match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
}

subnet 10.4.0.0 netmask 255.255.0.0 {
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "company.example.com";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;

    pool {
         failover peer "dhcp-failover";
         deny dynamic bootp clients;
         deny members of "pxe";
         range 10.4.45.1 10.4.45.250; # DHCP pool on private network
    }
    # A separate pool for BOOTP services.
    pool {
         range dynamic-bootp 10.4.45.251 10.4.45.255; # DHCP pool on private network
         allow dynamic bootp clients;
         deny members of "dhcp";
         allow members of "pxe";
         next-server 10.4.7.9;    # On which system the bootp filename is located.

         if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {

            if substring(option vendor-class-identifier,15,5) = "00007" {
               log(info,"UEFI PXE Boot - private network");
               filename "pxelinux/grubx64.efi"; # The file to load for EFI systems.
               }
            else {
                log(info,"BIOS PXE Boot - private network");
                filename "pxelinux.0"; # The file to load via bootp for BIOS systems.
                }
        }
    }
}

Это с /etc/dhcp/dhcpd.confрезервного/вторичного/не-PXE сервера:

authoritative; # Send out acknowledgements to DHCP client queries. 

failover peer "dhcp-failover" {
  secondary; # declare this to be the secondary server
  address 10.4.7.210;
  port 647;
  peer address 10.4.7.9;
  peer port 647;
  # How many seconds to wait before we assume that the other has failed.
  max-response-delay 30;
  # How many BNDUPD messages to send before receiving BNDACK.
  max-unacked-updates 10;
  # How many seconds to wait before disabling load balancing.
  load balance max seconds 3;
}

# Make sure that this failover DHCP server does _not_
# respond to bootp.
deny bootp;

option domain-name "company.example.com";
option time-offset -18000; # Eastern Standard Time

# Is this a DHCP query (as opposed to a BOOTP query)?
class "dhcp" {
      match if exists dhcp-message-type;
}
class "pxe" {
      match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
}

subnet 10.4.0.0 netmask 255.255.0.0 {
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "company.example.com";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;

    # Note that there are a few IP addresses in the range of the primary
    # server that are not included here. This is for BOOTP, which is
    # not handled by the secondary server.
    pool {
         failover peer "dhcp-failover";
         deny dynamic bootp clients;     
         deny members of "pxe";
         range 10.4.45.1 10.4.45.250; # DHCP pool on private network
    }
}

Я знаю, что переусердствовал с классами "dhcp" и "pxe". Я добавил их, когда пытался исправить проблему. Они не оказали никакого эффекта, за исключением появления peer holds all free leasesсообщений журнала ниже.

Вот что я вижу в журналах "основного" сервера. Обратите внимание, что 52:54:00:31:f2:7fэто MAC-адрес тестовой системы, которую я настроил на загрузку через PXE, прежде чем она "сдалась" и загрузилась с диска.

Sep  8 14:20:46 dhcpd dhcpd[17922]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:20:49 dhcpd dhcpd[17922]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:20:57 dhcpd dhcpd[17922]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:21:13 dhcpd dhcpd[17922]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases

Это из журнала на «вторичном» сервере. Это соответствует примерно минутной задержке с момента первой загрузки клиента, когда он пытается найти PXE-сервер, до момента, когда он переключается с загрузки из ОС и получает DHCP-адрес обычным способом.

Sep  8 14:20:46 dhcpdsec dhcpd[67768]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:20:46 dhcpdsec dhcpd[67768]: bind update on 10.4.45.183 from dhcp-failover rejected: incoming update is less critical than outgoing update
Sep  8 14:20:49 dhcpdsec dhcpd[67768]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:20:57 dhcpdsec dhcpd[67768]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:21:13 dhcpdsec dhcpd[67768]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:22:03 dhcpdsec dhcpd[67768]: DHCPREQUEST for 10.4.45.183 from 52:54:00:31:f2:7f via enp7s0
Sep  8 14:22:04 dhcpdsec dhcpd[67768]: DHCPACK on 10.4.45.183 to 52:54:00:31:f2:7f via enp7s0

Проведя предыдущие тесты, я убедился, что значение substring (option vendor-class-identifier, 0, 9)действительно равно PXEClient.

Я уже пробовал останавливать демон dhcpd на обеих машинах и вручную редактировать записи для 52:54:00:31:f2:7fin /var/lib/dhcpd/dhcpd.leases. Никаких изменений.

Есть идеи?

Редактировать: Мне пришло в голову, что может помочь публикация моей предыдущей конфигурации DHCP без отказоустойчивости. Загрузка PXE прошла нормально:

subnet 10.4.0.0 netmask 255.255.0.0 {
    range dynamic-bootp 10.4.45.1 10.4.45.254; # DCHP pool on private network
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "nevis.columbia.edu";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;
    next-server 10.4.7.9;    # On which system the bootp filename is located.

    if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {

        if substring(option vendor-class-identifier,15,5) = "00007" {
            log(info,"UEFI PXE Boot - private network");
            filename "pxelinux/grubx64.efi"; # The file to load for EFI systems.
            }
        else {
            log(info,"BIOS PXE Boot - private network");
            filename "pxelinux.0"; # The file to load via bootp for BIOS systems.
        }
    }
}

решение1

После долгих экспериментов я нашел ответ: оказывается, порядок операторов контроля доступа в пуле имеет значение.

Вот повтор определений классов из моего оригинального поста:

class "dhcp" {
      match if exists dhcp-message-type;
}
class "pxe" {
      match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
}

Вот subnetопределение, которое работает на моем основном DHCP-сервере. Главное отличие между этим и конфигурацией в моем исходном посте заключается в том, что порядок операторов rangeпо сравнению с любыми allowили denyоператорами и что я "pxe"сначала определяю пул. Исходные строки отказоустойчивости не изменяются.

subnet 10.4.0.0 netmask 255.255.0.0 {
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "company.example.com";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;
    next-server 10.4.7.9;    # On which system the bootp filename is located.

    if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {
        if option architecture-type =  00:07 {
           filename "uefi/grubx64.efi"; # The file to load for EFI systems.
        }
        else {
           filename "pxelinux/pxelinux.0"; # The file to load via bootp for BIOS systems.
        }
    }

    # A separate pool for PXE services.
    pool {
         range dynamic-bootp 10.4.45.251 10.4.45.255; # DHCP pool on private network
         allow dynamic bootp clients;
         allow members of "pxe";
    }

    # The "regular" DHCP pool.
    pool {
         failover peer "dhcp-failover";
         range 10.4.45.1 10.4.45.250; # DHCP pool on private network
         deny dynamic bootp clients;
         deny members of "pxe";
    }
}

Вот измененные subnetстроки в конфигурации моего вторичного DHCP-сервера, хотя эти изменения, вероятно, не имеют значения:

subnet 10.4.0.0 netmask 255.255.0.0 {
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "company.example.com";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;

    # Note that there are a few IP addresses in the range of the primary
    # server that are not included here. This is for PXE, which is
    # not handled by the secondary server.
    pool {
         failover peer "dhcp-failover";
         deny dynamic bootp clients;     
         range 10.4.45.1 10.4.45.250; # DCHP pool on private network
    }
}

Теперь у меня есть настройка с DHCP failover и PXE-загрузкой для установки/восстановления ОС, которая поддерживает как BIOS, так и EFI-системы. Надеюсь, кто-то еще найдет приведенные выше строки полезными!

Связанный контент