Трансляция исходного IP-адреса для внутрикластерного трафика
Я пытаюсь погрузиться в сетевую модель K8s и думаю, что до сих пор хорошо понимаю ее, но есть одна вещь, которую я не могу понять. В руководстве Cluster Networking упоминается следующее:
Kubernetes предъявляет следующие фундаментальные требования к любой сетевой реализации (за исключением любых политик преднамеренной сегментации сети):
- все контейнеры могут связываться со всеми другими контейнерами без NAT
- все узлы могут общаться со всеми контейнерами (и наоборот) без NAT
- IP-адрес, который контейнер видит сам как тот же IP-адрес, который другие видят как
Второй пункт указывает, что связь контейнера x-узла должна быть возможна без NAT. Это, однако, не так, когда работает Kube-прокси iptables
Режим. Это дамп iptables с одного из моих узлов:
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
KUBE-POSTROUTING all -- anywhere anywhere /* kubernetes postrouting rules */
Chain KUBE-POSTROUTING (1 references)
target prot opt source destination
MASQUERADE all -- anywhere anywhere /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000
/* sample target pod chain being marked for MASQ */
Chain KUBE-SEP-2BKJZA32HM354D5U (1 references)
target prot opt source destination
KUBE-MARK-MASQ all -- xx.yyy.zzz.109 anywhere /* kube-system/heapster: */
DNAT tcp -- anywhere anywhere /* kube-system/heapster: */ tcp to:xx.yyy.zzz.109:8082
Chain KUBE-MARK-MASQ (156 references)
target prot opt source destination
MARK all -- anywhere anywhere MARK or 0x4000
Похоже, K8s меняет исходный IP-адрес отмеченных исходящих пакетов на IP-адрес узла (для службы ClusterIP). И они даже явно упоминают это в Source IP для сервисов с Type = ClusterIP:
Пакеты, отправляемые в ClusterIP из кластера, никогда не будут исходными NAT, если вы запускаете kube-proxy в режиме iptables, который используется по умолчанию начиная с Kubernetes 1.2. Если клиентский модуль и серверный модуль находятся в одном узле, то client_address является IP-адресом клиентского модуля. Однако, если клиентский модуль и серверный модуль находятся в разных узлах, client_address является фланцевым IP-адресом узла клиентского модуля.
Это начинается с того, что пакеты внутри кластера никогда не обрабатываются по SNAT, но затем переходит к сообщению, что пакеты, отправляемые модулям в других узлах, фактически являются SNAT. Я запутался по этому поводу - неправильно ли я понимаю, что все узлы могут взаимодействовать со всеми контейнерами (и наоборот) без требования NAT?
1 ответ
Если вы прочитали пункт 2:
Связь "от одного к другому": это основная цель этого документа.
Это все еще относится ко всем контейнерам и модулям, работающим в вашем кластере, потому что все они находятся в PodCidr
:
- все контейнеры могут связываться со всеми другими контейнерами без NAT
- все узлы могут связываться со всеми контейнерами (и наоборот)
- без NAT IP, который видит себя контейнером, является тем же IP, что другие видят его как
По сути, все модули имеют уникальные IP-адреса и находятся в одном и том же пространстве и могут общаться с каждым на уровне IP.
Кроме того, если вы посмотрите на маршруты на одном из ваших узлов Kubernetes, вы увидите что-то вроде этого для Calico, где podCidr 192.168.0.0/16
:
default via 172.0.0.1 dev ens5 proto dhcp src 172.0.1.10 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.31.0.0/20 dev ens5 proto kernel scope link src 172.0.1.10
172.31.0.1 dev ens5 proto dhcp scope link src 172.0.1.10 metric 100
blackhole 192.168.0.0/24 proto bird
192.168.0.42 dev calixxxxxxxxxxx scope link
192.168.0.43 dev calixxxxxxxxxxx scope link
192.168.4.0/24 via 172.0.1.6 dev tunl0 proto bird onlink
192.168.7.0/24 via 172.0.1.55 dev tunl0 proto bird onlink
192.168.8.0/24 via 172.0.1.191 dev tunl0 proto bird onlink
192.168.9.0/24 via 172.0.1.196 dev tunl0 proto bird onlink
192.168.11.0/24 via 172.0.1.147 dev tunl0 proto bird onlink
Вы видите пакеты с 192.168.x.x
напрямую перенаправляются на туннельный интерфейс, подключенный к узлам, поэтому там нет NAT.
Теперь, когда вы подключаетесь извне к PodCidr, ваши пакеты определенно являются NAT, скажем, через сервисы через внешний хост. Вы также определенно видите такие правила:
# Completed on Sat Oct 27 00:22:39 2018
# Generated by iptables-save v1.6.1 on Sat Oct 27 00:22:39 2018
*nat
:PREROUTING ACCEPT [65:5998]
:INPUT ACCEPT [1:60]
:OUTPUT ACCEPT [28:1757]
:POSTROUTING ACCEPT [61:5004]
:DOCKER - [0:0]
:KUBE-MARK-DROP - [0:0]