Сервис (Service) в Kubernetes: виртуальные IP-адреса и сервисные прокси

Каждый узел в кластере Kubernetes запускает kube-proxy. kube-proxy отвечает за реализацию формы виртуального IP для Сервисов типа, отличного от ExternalName.

Почему бы не использовать циклический DNS (round-robin DNS)?

Время от времени возникает вопрос, почему Kubernetes использует прокси для пересылки входящего трафика на бэкенды. А как насчет других подходов? Например, можно ли настроить записи DNS, которые имеют несколько значений A (или AAAA для IPv6), и полагаться на разрешение имен циклическим перебором (round-robin)?

Существует несколько причин использования прокси для Сервисов:

  • Существует долгая история реализаций DNS, не учитывающих TTL записей и кэширующих результаты поиска имен после того, как они истекли.
  • Некоторые приложения выполняют поиск DNS только один раз и кэшируют результаты на неопределенный срок.
  • Даже если приложения и библиотеки выполнили правильное переразрешение, низкие или нулевые значения TTL в записях DNS могут вызвать высокую нагрузку на DNS, которой затем становится трудно управлять.

Совместимость версий

Начиная с Kubernetes v1.0 вы можете использовать прокси-режим в пользовательском пространстве. В Kubernetes v1.1 добавлен режим проксирования iptables, а в Kubernetes v1.2 режим iptables для kube-proxy стал режимом по умолчанию. В Kubernetes v1.8 добавлен режим ipvs proxy.

Режим прокси пространства пользователя

В этом режиме kube-proxy наблюдает, как мастер Kubernetes добавляет и удаляет объекты Service и Endpoint. Для каждого Сервиса он открывает порт (выбранный случайным образом) на локальном узле. Любые соединения с этим "прокси-портом" проксируются к одному из бекенд Pod'ов Сервиса (как сообщается через конечные точки). kube-proxy принимает во внимание настройку SessionAffinity Сервиса, когда решает, какой бэк-Pod использовать.

Наконец, прокси-сервер пользовательского пространства устанавливает правила iptables, которые захватывают трафик для clusterIP Сервиса (который является виртуальным) и порта. Правила перенаправляют этот трафик на порт прокси-сервера, который проксирует бэкенд Pod.

По умолчанию kube-proxy в режиме пространства пользователя выбирает бэкэнд с помощью алгоритма циклического перебора (round-robin algorithm).

Режим прокси iptables

В этом режиме kube-proxy наблюдает за уровнем управления Kubernetes для добавления и удаления объектов Service и Endpoint. Для каждого Сервиса он устанавливает правила iptables, которые собирают трафик на IP-адрес и порт кластера Сервиса и перенаправляют этот трафик на один из бэкенд наборов Сервиса. Для каждого объекта Endpoint он устанавливает правила iptables, которые выбирают бэкенд Pod.

По умолчанию kube-proxy в режиме iptables выбирает бэкенд случайным образом.

Использование iptables для обработки трафика снижает нагрузку на систему, так как трафик обрабатывается сетевым фильтром Linux без необходимости переключения между пространством пользователя и пространством ядра. Этот подход также, вероятно, будет более надежным.

Если kube-proxy работает в режиме iptables и первый выбранный Pod не отвечает, соединение не устанавливается. Это отличается от режима пользовательского пространства: в этом сценарии kube-proxy обнаружит, что соединение с первым Pod'ом не удалось, и автоматически выполнит попытку с другим бэкенд Pod'ом.

Вы можете использовать тесты готовности Pod'ов, чтобы убедиться, что Pod'ы работают нормально, поэтому kube-proxy в режиме iptables видит только те серверы, которые оцениваются тестами как работоспособные. Делая это, вы избегаете отправки трафика через kube-proxy на Pod, для которого известно, что он не прошел тесты.

Режим прокси IPVS

В режиме ipvs kube-proxy отслеживает службы и конечные точки Kubernetes, вызывает интерфейс netlink для соответствующего создания правил IPVS и периодически синхронизирует правила IPVS со службами и конечными точками Kubernetes. Этот цикл управления гарантирует, что состояние IPVS соответствует желаемому состоянию. При доступе к Сервису IPVS направляет трафик к одному из бэкенд Pod'ов.

Прокси-режим IPVS основан на функции ловушки netfilter, которая аналогична режиму iptables, но использует хэш-таблицу в качестве базовой структуры данных и работает в пространстве ядра. Это означает, что kube-proxy в режиме IPVS перенаправляет трафик с меньшей задержкой, чем kube-proxy в режиме iptables, с гораздо лучшей производительностью при синхронизации правил прокси. По сравнению с другими режимами прокси режим IPVS также поддерживает более высокую пропускную способность сетевого трафика.

IPVS предоставляет больше возможностей для балансировки трафика для бэкенд Pod'ов; это:

  • rr: round-robin
  • lc: least connection (наименьшее соединение (наименьшее количество открытых соединений))
  • dh: destination hashing (хэширование назначения)
  • sh: source hashing (хэширование источника)
  • sed: shortest expected delay (кратчайшая ожидаемая задержка)
  • nq: never queue (никогда не ставится в очередь)

Примечание: Чтобы запустить kube-proxy в режиме IPVS, вы должны сделать IPVS Linux доступным на узле, прежде чем запускать kube-proxy.

Когда kube-proxy запускается в режиме прокси IPVS, он проверяет, доступны ли модули ядра IPVS. Если модули ядра IPVS не обнаружены, то kube-proxy возвращается к работе в режиме iptables proxy.

В этих прокси-моделях трафик, связанный с IP:Port Сервиса, передается к соответствующему бэкенду, и клиенты ничего не знают о Kubernetes, Сервисах или Pod'ах.

Если вы хотите убедиться, что подключения от определенного клиента передаются одному и тому же Pod каждый раз, вы можете выбрать сходство сеанса на основе IP-адресов клиента, установив для service.spec.sessionAffinity значение “ClientIP” (по умолчанию установлено значение “None”). Вы также можете установить максимальное время ожидания сеанса, настроив service.spec.sessionAffinityConfig.clientIP.timeoutSeconds соответствующим образом. (значение по умолчанию - 10800, что составляет 3 часа).


Читайте также:


Комментарии

Популярные сообщения из этого блога

Контроллеры в Kubernetes: DaemonSet

Контроллеры в Kubernetes: ReplicaSet

Контроллеры в Kubernetes: StatefulSet