Kubernetes - Отслеживание соединения не перенаправляет пакеты обратно на исходный IP-адрес назначения (DNAT) - PullRequest
0 голосов
/ 24 октября 2018

У нас есть настройка кластера Kubernetes с использованием экземпляров AWS EC2, которые мы создали с помощью KOPS.У нас возникли проблемы с внутренней связью модулей через службы Kubernetes (которые будут загружать трафик баланса между модулями назначения).Проблема возникает, когда исходный и целевой модуль находятся в одном и том же экземпляре EC2 (узле).Kubernetes настроен с фланелевой связью для межузловой связи с использованием vxlan, а службы kubernetes управляются через kube-proxy с использованием iptables.

В сценарии, где:

  • PodA работает на экземпляре EC2 1 (ip-172-20-121-84, us-east-1c): 100.96.54.240
  • PodB, работающий на экземпляре 1 EC2 (ip-172-20-121-84, us-east-1c):100.96.54.247
  • ServiceB (служба, в которой PodB - возможная конечная точка назначения): 100.67.30.133

Если мы зайдем внутрь PodA и выполним "curl -v http://ServiceB/",ответ не получен, и, наконец, время ожидания истекло.

Когда мы проверяем трафик (интерфейс cni0 в экземпляре 1), мы наблюдаем:

  1. PodA отправляет пакет SYN в ServiceBIP
  2. Пакет поврежден, и IP-адрес назначения изменяется с IP-адреса ServiceB на IP-адрес PodB
  3. Регистры Conntrack, которые изменяются:

    root@ip-172-20-121-84:/home/admin# conntrack -L|grep 100.67.30.133
    tcp      6 118 SYN_SENT src=100.96.54.240 dst=100.67.30.133 sport=53084 dport=80 [UNREPLIED] src=100.96.54.247 dst=100.96.54.240 sport=80 dport=43534 mark=0 use=1
    
  4. PodB отправляет пакет SYN + ACK в PodA

  5. Исходный IP-адрес для пакета SYN + ACKне возвращен обратно с IP-адреса PodB на IP-адрес ServiceB
  6. PodA получает пакет SYN + ACK от PodB, который не ожидался, и отправляет обратно пакет RESET
  7. PodA отправляет пакет SYNServiceB снова после истечения времени ожидания, и весь процесс повторяется

Здесь аннотированные подробности tcpdump:

root@ip-172-20-121-84:/home/admin# tcpdump -vv -i cni0 -n "src host 100.96.54.240 or dst host 100.96.54.240"
TCP SYN:
15:26:01.221833 IP (tos 0x0, ttl 64, id 2160, offset 0, flags [DF], proto TCP (6), length 60)
    100.96.54.240.43534 > 100.67.30.133.80: Flags [S], cksum 0x1e47 (incorrect -> 0x3e31), seq 506285654, win 26733, options [mss 8911,sackOK,TS val 153372198 ecr 0,nop,wscale 9], length 0
15:26:01.221866 IP (tos 0x0, ttl 63, id 2160, offset 0, flags [DF], proto TCP (6), length 60)
    100.96.54.240.43534 > 100.96.54.247.80: Flags [S], cksum 0x36d6 (incorrect -> 0x25a2), seq 506285654, win 26733, options [mss 8911,sackOK,TS val 153372198 ecr 0,nop,wscale 9], length 0

Level 2:
15:26:01.221898 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 100.96.54.240 tell 100.96.54.247, length 28
15:26:01.222050 ARP, Ethernet (len 6), IPv4 (len 4), Reply 100.96.54.240 is-at 0a:58:64:60:36:f0, length 28

TCP SYN+ACK:
15:26:01.222151 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    100.96.54.247.80 > 100.96.54.240.43534: Flags [S.], cksum 0x36d6 (incorrect -> 0xc318), seq 2871879716, ack 506285655, win 26697, options [mss 8911,sackOK,TS val 153372198 ecr 153372198,nop,wscale 9], length 0

TCP RESET:
15:26:01.222166 IP (tos 0x0, ttl 64, id 32433, offset 0, flags [DF], proto TCP (6), length 40)
    100.96.54.240.43534 > 100.96.54.247.80: Flags [R], cksum 0x6256 (correct), seq 506285655, win 0, length 0

TCP SYN (2nd time):
15:26:02.220815 IP (tos 0x0, ttl 64, id 2161, offset 0, flags [DF], proto TCP (6), length 60)
    100.96.54.240.43534 > 100.67.30.133.80: Flags [S], cksum 0x1e47 (incorrect -> 0x3d37), seq 506285654, win 26733, options [mss 8911,sackOK,TS val 153372448 ecr 0,nop,wscale 9], length 0
15:26:02.220855 IP (tos 0x0, ttl 63, id 2161, offset 0, flags [DF], proto TCP (6), length 60)
    100.96.54.240.43534 > 100.96.54.247.80: Flags [S], cksum 0x36d6 (incorrect -> 0x24a8), seq 506285654, win 26733, options [mss 8911,sackOK,TS val 153372448 ecr 0,nop,wscale 9], length 0
15:26:02.220897 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    100.96.54.247.80 > 100.96.54.240.43534: Flags [S.], cksum 0x36d6 (incorrect -> 0x91f0), seq 2887489130, ack 506285655, win 26697, options [mss 8911,sackOK,TS val 153372448 ecr 153372448,nop,wscale 9], length 0
15:26:02.220915 IP (tos 0x0, ttl 64, id 32492, offset 0, flags [DF], proto TCP (6), length 40)
    100.96.54.240.43534 > 100.96.54.247.80: Flags [R], cksum 0x6256 (correct), seq 506285655, win 0, length 0

Соответствующие правила iptable (автоматически управляемые kube-proxy) в экземпляре 1(ip-172-20-121-84, us-east-1c):

-A INPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

-A KUBE-SERVICES ! -s 100.96.0.0/11 -d 100.67.30.133/32 -p tcp -m comment --comment "prod/export: cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 100.67.30.133/32 -p tcp -m comment --comment "prod/export: cluster IP" -m tcp --dport 80 -j KUBE-SVC-3IL52ANAN3BQ2L74

-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -m statistic --mode random --probability 0.10000000009 -j KUBE-SEP-4XYJJELQ3E7C4ILJ
-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -m statistic --mode random --probability 0.11110999994 -j KUBE-SEP-2ARYYMMMNDJELHE4
-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -m statistic --mode random --probability 0.12500000000 -j KUBE-SEP-OAQPXBQCZ2RBB4R7
-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -m statistic --mode random --probability 0.14286000002 -j KUBE-SEP-SCYIBWIJAXIRXS6R
-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -m statistic --mode random --probability 0.16667000018 -j KUBE-SEP-G4DTLZEMDSEVF3G4
-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -m statistic --mode random --probability 0.20000000019 -j KUBE-SEP-NXPFCT6ZBXHAOXQN
-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -m statistic --mode random --probability 0.25000000000 -j KUBE-SEP-7DUMGWOXA5S7CFHJ
-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-LNIY4F5PIJA3CQPM
-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-SLBETXT7UIBTZCPK
-A KUBE-SVC-3IL52ANAN3BQ2L74 -m comment --comment "prod/export:" -j KUBE-SEP-FMCOTKNLEICO2V37

-A KUBE-SEP-OAQPXBQCZ2RBB4R7 -s 100.96.54.247/32 -m comment --comment "prod/export:" -j KUBE-MARK-MASQ
-A KUBE-SEP-OAQPXBQCZ2RBB4R7 -p tcp -m comment --comment "prod/export:" -m tcp -j DNAT --to-destination 100.96.54.247:80

-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE

Это определение сервиса:

root@adsvm010:/yamls# kubectl describe service export
Name:              export
Namespace:         prod
Labels:            <none>
Annotations:       <none>
Selector:          run=export
Type:              ClusterIP
IP:                100.67.30.133
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         100.96.5.44:80,100.96.54.235:80,100.96.54.247:80 + 7 more...
Session Affinity:  None
Events:            <none>

Если вместо сервиса мы используем напрямуюPodB IP (поэтому нет необходимости манипулировать пакетами), соединение работает.

Если мы используем сервис, но случайно выбранный модуль назначения работает в другом экземпляре, то механизм отслеживания соединений работает правильно, и онвозвращает пакет обратно, так что PodA видит пакет SYN + ACK так, как он ожидал (исходя из IP ServiceB).В этом случае трафик проходит через интерфейсы cni0 и flannel.0.

Такое поведение началось несколько недель назад, до того как мы не наблюдали никаких проблем (более года), и мы не помним каких-либо серьезных изменений в настройке кластера.или к стручкам мы бежим.У кого-нибудь есть идеи, объясняющие, почему пакет SYN + ACK не перенаправлен на ожидаемые IP-адреса src / dst?

1 Ответ

0 голосов
/ 26 октября 2018

Я наконец нашел ответ.Интерфейс cni0 находится в режиме моста со всеми виртуальными интерфейсами модуля (по одному veth0 на модуль, работающий на этом узле):

root@ip-172-20-121-84:/home/admin# brctl show
bridge name bridge id       STP enabled interfaces
cni0        8000.0a5864603601   no      veth05420679
                                        veth078b53a1
                                        veth0a60985d
...


root@ip-172-20-121-84:/home/admin# ip addr
5: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 8951 qdisc noqueue state UP group default qlen 1000
    link/ether 0a:58:64:60:36:01 brd ff:ff:ff:ff:ff:ff
    inet 100.96.54.1/24 scope global cni0
       valid_lft forever preferred_lft forever
    inet6 fe80::1c66:76ff:feb6:2122/64 scope link
       valid_lft forever preferred_lft forever

Трафик, который идет от / к мостовому интерфейсу к / от какого-либо другого интерфейса,обрабатывается netfilter / iptables, но трафик, который не покидает мостовой интерфейс (например, от одного veth0 к другому, оба принадлежат одному мосту), НЕ обрабатывается netfilter / iptables.

В примере, который я представилв этом вопросе PodA (100.96.54.240) отправляет пакет SYN в ServiceB (100.67.30.133), который не находится в подсети cni0 (100.96.54.1/24), поэтому этот пакет не будет оставаться в мостовом интерфейсе cni0 и iptable обрабатывает его,Вот почему мы видим, что DNAT произошел, и он был зарегистрирован в контратаке.Но если выбранный модуль назначения находится в том же узле, например PodB (100.96.54.247), то PodB видит пакет SYN и отвечает SYN + ACK, где источником является 100.96.54.247, а пунктом назначения является 100.96.54.240.Это IP-адреса внутри подсети cni0, и их не нужно покидать, следовательно, netfilter / iptables не обрабатывает их и не обрабатывает пакет обратно на основе информации о conntrack (т. Е. Реальный источник 100.96.54.247 не заменяется ожидаемым источником100.67.30.133).

К счастью, есть модуль ядра bridge-netfilter , который позволяет netfilter / iptables обрабатывать трафик, который происходит в мостовых интерфейсах:

root@ip-172-20-121-84:/home/admin# modprobe br_netfilter
root@ip-172-20-121-84:/home/admin# cat /proc/sys/net/bridge/bridge-nf-call-iptables
1

Чтобы исправить это в настройке кластера Kubernetes с KOPS ( кредиты ), отредактируйте манифест кластера с помощью kops edit cluster и в поле spec: включите:

hooks:
- name: fix-bridge.service
  roles:
  - Node
  - Master
  before:
  - network-pre.target
  - kubelet.service
  manifest: |
    Type=oneshot
    ExecStart=/sbin/modprobe br_netfilter
    [Unit]
    Wants=network-pre.target
    [Install]
    WantedBy=multi-user.target

Это создастСлужба systemd в /lib/systemd/system/fix-bridge.service в ваших узлах, которая будет работать при запуске, и она будет гарантировать, что модуль br_netfilter загружен до запуска kubernetes (то есть, kubelet).Если мы этого не сделаем, то, что мы испытали с экземплярами AWS EC2 (образы Debian Jessie), это то, что иногда модуль загружается во время запуска, а иногда нет (я не знаю, почему существует такая изменчивость), поэтому в зависимости от этогопроблема может проявиться или нет.

...