Kubernetes использует iptables для распределения трафика по набору пакетов, как официально объясняет kubernetes.io .В основном, когда вы создаете объект kind: service
, K8s создает виртуальный ClusterIP и инструктирует демон-демон kube-proxy обновить iptables на каждом узле, чтобы запросы, совпадающие с этим виртуальным IP-адресом, были сбалансированы по нагрузке для набора IP-пакетов.Слово «виртуальный» в данном случае означает, что ClusterIP, в отличие от IP-пакетов, не являются реальными IP-адресами, выделяемыми сетевым интерфейсом, а просто используются в качестве «фильтра» для сопоставления трафика и пересылки их в нужное место назначения.
* 1007В документации Kubernetes говорится, что по умолчанию метод балансировки нагрузки является циклическим, но это не совсем точно.Если вы посмотрите на iptables на любом из рабочих узлов, то увидите, что для данной службы
foo
с ClusterIP из 172.20.86.5 и 3 модулями [чрезмерно упрощенные] правила iptables выглядят следующим образом:
$ kubectl get service foo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
foo ClusterIP 172.20.86.5 <none> 443:30937/TCP 12m
Chain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-SVC-4NIQ26WEGJLLPEYD tcp -- anywhere 172.20.86.5 /* default/foo:https cluster IP */ tcp dpt:https
Это правило цепочки KUBE-SERVICES
ищет весь трафик, для которого destination
равно 172.20.86.5, и применяет правила, определенные в другой цепочке с именем KUBE-SVC-4NIQ26WEGJLLPEYD
:
Chain KUBE-SVC-4NIQ26WEGJLLPEYD (2 references)
target prot opt source destination
KUBE-SEP-4GQBH7D5EV5ANHLR all -- anywhere anywhere /* default/foo:https */ statistic mode random probability 0.33332999982
KUBE-SEP-XMNJYETXA5COSMOZ all -- anywhere anywhere /* default/foo:https */ statistic mode random probability 0.50000000000
KUBE-SEP-YGQ22DTWGVO4D4MM all -- anywhere anywhere /* default/foo:https */
В этой цепочке используется statistic mode random probability
для случайной отправки трафика в одну из трех определенных цепочек (поскольку у меня три модуля, у меня здесь три цепочки, каждая с 33,3% вероятностью выбора для получения трафика).Каждая из этих цепочек является окончательным правилом при отправке трафика на IP-адрес внутреннего модуля.Например, посмотрим на первый:
Chain KUBE-SEP-4GQBH7D5EV5ANHLR (1 references)
target prot opt source destination
DNAT tcp -- anywhere anywhere /* default/foo:https */ tcp to:10.100.1.164:12345
директива DNAT
перенаправляет пакеты на IP-адрес 10.100.1.164 (реальный IP-адрес) и порт 12345 (то, что foo
прослушивает).Две другие цепочки (KUBE-SEP-XMNJYETXA5COSMOZ
и KUBE-SEP-YGQ22DTWGVO4D4MM
) похожи, за исключением того, что у каждой будет свой IP-адрес.
Аналогично, если ваш тип сервиса NodePort
, Kubernetes назначает случайный порт (от 30000 до32767 по умолчанию) на узле.Здесь интересно то, что на рабочем узле нет процесса, активно прослушивающего этот порт - вместо этого это еще одно правило iptables для сопоставления трафика и отправки его на правильный набор модулей:
Chain KUBE-NODEPORTS (1 references)
target prot opt source destination
KUBE-SVC-4NIQ26WEGJLLPEYD tcp -- anywhere anywhere /* default/foo:https */ tcp dpt:30937
Этоправило соответствует входящему трафику, идущему на порт 30937 (tcp dpt:30937
), и перенаправляет его в цепочку KUBE-SVC-4NIQ26WEGJLLPEYD
.Но угадайте, что: KUBE-SVC-4NIQ26WEGJLLPEYD
- это та же самая цепочка, с которой совпадает IP-адрес кластера 172.20.86.5 и отправляет трафик, как показано выше.