Ограничения стандартного балансировщика Service

В Kubernetes за внутреннюю и внешнюю балансировку запросов отвечает ресурс типа Service. Он распределяет запросы между рабочими подами приложения и исключает из балансировки повреждённые экземпляры. Для проверки способности пода обрабатывать входящие запросы применяются readiness-пробы, которые указываются в спецификации контейнеров, входящих в этот под.

Стандартный инструмент балансировки Service подходит для большинства задач облачных приложений, но имеет два ограничения:

  • Если хотя бы один контейнер в поде не проходит проверку готовности (readiness-пробу), весь под отмечается как NotReady и исключается из балансировки всех сервисов, с которыми он связан.
  • Для каждого контейнера можно настроить только одну пробу, поэтому невозможно создать отдельные пробы для проверки, например, доступности чтения и записи.

Примеры сценариев, где стандартного балансировщика недостаточно:

  • База данных:
    • Работает в трёх подах — db-0, db-1 и db-2, каждый из которых содержит один контейнер с запущенным процессом базы данных.
    • Необходимо создать два сервиса (Service) — db-write для записи и db-read для чтения.
    • Запросы на чтение должны балансироваться между всеми подами.
    • Запросы на запись балансируются только на тот под, который назначен мастером средствами самой базы данных.
  • Виртуальная машина:
    • Под содержит единственный контейнер, в котором запущен процесс qemu, выполняющий роль гипервизора для гостевой виртуальной машины.
    • В гостевой виртуальной машине запущены независимые процессы, например, веб-сервер и SMTP-сервер.
    • Требуется создать два Service — web и smtp, каждый из которых которых будет иметь свои readiness-пробы.

Возможности балансировщика ServiceWithHealthcheck

В отличие от стандартного балансировщика, где readiness-пробы привязаны к состоянию контейнеров, ServiceWithHealthcheck позволяет настраивать активные пробы на отдельные TCP-порты. Таким образом, каждый балансировщик, обслуживающий один и тот же под, может работать независимо от других.

Настроить данный способ балансировки можно при помощи ресурса ServiceWithHealthchecks:

  • Его спецификация идентична стандартному Service с добавлением раздела healthcheck, который содержит набор проверок.
  • На данный момент поддерживается три вида проб:
    • TCP — обычная проверка с помощью установки TCP-соединения.
    • HTTP — возможность отправить HTTP-запрос и ожидать определённый код ответа.
    • PostgreSQL — возможность отправить SQL-запрос и ожидать его успешного завершения.

Ознакомиться с примерами можно в документации.

Внутреннее устройство балансировщика ServiceWithHealthcheck

Балансировщик состоит из двух компонентов:

  • контроллер — работает на мастер-узлах кластера и управляет ресурсами ServiceWithHealthcheck,
  • агенты — работают на каждом узле кластера и выполняют пробы для подов, запущенных на этом узле.

Балансировщик ServiceWithHealthcheck спроектирован так, чтобы не зависеть от реализации CNI, используя при этом стандартные ресурсы Service и EndpointSlice:

  • Контроллер при создании ресурса ServiceWithHealthcheck автоматически создает одноименный ресурс Service в том же пространстве имен с пустым полем selector. Это позволяет избежать создания стандартным контроллером EndpointSlice, которые используются для настройки балансировки.
  • Каждый агент при появлении на своём узле подов, которые попадают под управление ServiceWithHealthcheck, осуществляет настроенные пробы и создаёт для них EndpointSlice со списком проверенных IP-адресов и портов. Данный EndpointSlice привязан к дочернему ресурсу Service, созданному выше.
  • CNI сопоставит все EndpointSlice со стандартными сервисами, созданными выше и осуществит балансировку по проверенным IP-адресам и портам на всех узлах кластера.

Миграция с Service на ресурс ServiceWithHealthchecks, например в рамках CI/CD, не должна вызвать затруднений. Спецификация ServiceWithHealthchecks в основе своей повторяет спецификацию Service, но содержит дополнительный раздел healthchecks. Во время жизненного цикла ресурса ServiceWithHealthchecks создается одноименный сервис в том же namespace, чтобы привычным способом (kube-proxy или cni) направить трафик на рабочие нагрузки в кластере.