K8s Metal LB Service Trafic Flow: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
Строка 203: Строка 203:
 
targetPort: https
 
targetPort: https
 
</PRE>
 
</PRE>
тут кажется что трафик должен идти на 443 порт (но дамп выше это не подтверждает - там порт
+
тут кажется что трафик должен идти на 443 порт (но дамп выше это не подтверждает - там порт <code>4180</code>)
  +
<BR>
   
 
На самом деле <code>https</code> тут это '''ИМЯ''' порта в поде
 
 
<PRE>
 
</PRE>
 
http тут это ИМЯ порта в поде
 
 
targetPort: https
 
targetPort: https
  +
</PRE>
как найти на какие поды - надо смотреть по меткам
 
  +
Что можно проверить:
selector:
 
  +
<PRE>
app.kubernetes.io/instance: iam-proxy-alertmanager
 
  +
</PRE>
app.kubernetes.io/name: iam-proxy
 
  +
childctl -n stacklight get pod -l "app.kubernetes.io/instance"="iam-proxy-alertmanager","app.kubernetes.io/name"="iam-proxy" -o wide
 
  +
=22=
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
 
iam-proxy-alertmanager-76997d95b-d9czm 1/1 Running 0 41d 192.168.105.143 stacklight-1 <none> <none>
 
iam-proxy-alertmanager-76997d95b-mqd2f 1/1 Running 0 41d 192.168.104.66 stacklight-3 <none> <none>
 
 
нашлось 2 пода
 
нашлось 2 пода
 
дальше на той ноде которая анонсирует мак сервиса должны увидеть трафик на один из подов
 
дальше на той ноде которая анонсирует мак сервиса должны увидеть трафик на один из подов

Версия 14:35, 25 сентября 2025

K8s Metal LB Service Trafic Flow

Заметка о пути трафика с MetalLB
Заметка появилась в процессе расследования почему на сервис можно ходить с некоторых адресов, а с других нельзя.
Для определнности "проблемный" сервис iam-proxy-alertmanager
"Проблемный" взят в кавычки так как не ясно в сервисе ли дело или в чем-то другом

Найти с какой ноды анонсируется адрес

Описание сервиса

kubectl -n stacklight get svc  iam-proxy-alertmanager
NAME                     TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
iam-proxy-alertmanager   LoadBalancer   10.232.100.189   10.80.8.102   443:30358/TCP   42d

Тут виден внешний адрес сервиса - 10.80.8.102

Поиск адреса в логах

Посмотреть все логи по всем подам можно например так:

kubectl -n metallb-system  logs daemonset/mcc-metallb-speaker --prefix

Icon-caution.gif

Обращать внимание на сообщения вроде

Found 3 pods, using pod/mcc-metallb-speaker-8k5wl

Если такое есть - то логи не полные и нужно смотреть по метке

Icon-caution.gif

Можно и нужно искать и по метке, а не только по принадлежности к daemonset

kubectl -n metallb-system  logs   -l "app.kubernetes.io/component"="speaker" --prefix

Icon-caution.gif

Не забывать что логи могут выводится не все
Правильно, что б найти то что нужно не забывать про

  • --prefix что бы видеть имя пода и контейнера
  • --since=24h время, что бы не выгребать вообще все логи, когда они не нужны
  • --tail=-1 показать все логи. Это важно так как часто k8s решает показать только часть, я не исследовал причин и настроек этого поведения
  • --timestamps обычно хочется меток времени (их может и не быть в логах приложения и по ним можно сортировать)
  • LC_ALL=C sort -k2,2 если хоется сортировку по времени а не по подам (обычно хочется)

Финальный запрос

kubectl childctl -n metallb-system  logs -l app.kubernetes.io/component=speaker  --prefix --since=5h --tail=-1 --timestamps  | LC_ALL=C sort -k2,2 | grep '10.80.8.102'
[pod/mcc-metallb-speaker-8k5wl/speaker] 2025-09-25T10:24:15.767871702Z {"caller":"main.go:409","event":"serviceAnnounced","ips":["10.80.8.102"],"level":"info","msg":"service has IP, announcing","pool":"default","protocol":"layer2","ts":"2025-09-25T10:24:15Z"}
[pod/mcc-metallb-speaker-8k5wl/speaker] 2025-09-25T10:26:10.381353840Z {"caller":"main.go:453","event":"serviceWithdrawn","ip":["10.80.8.102"],"ips":["10.80.8.102"],"level":"info","msg":"withdrawing service announcement","pool":"default","protocol":"layer2","reason":"notOwner","ts":"2025-09-25T10:26:10Z"}
[pod/mcc-metallb-speaker-hgksn/speaker] 2025-09-25T10:26:10.458269685Z {"caller":"main.go:409","event":"serviceAnnounced","ips":["10.80.8.102"],"level":"info","msg":"service has IP, announcing","pool":"default","protocol":"layer2","ts":"2025-09-25T10:26:10Z"}
[pod/mcc-metallb-speaker-hgksn/speaker] 2025-09-25T10:26:10.535686056Z {"caller":"main.go:409","event":"serviceAnnounced","ips":["10.80.8.102"],"level":"info","msg":"service has IP, announcing","pool":"default","protocol":"layer2","ts":"2025-09-25T10:26:10Z"}
root@nest:~/MOSK/CURRENT/003-K8S-Control-Machines-Objects#

Из этого лога можно понять какой POD анонсировал адрес

  • Сначала это был pod/mcc-metallb-speaker-8k5wl/speaker
  • Потом он прекратил обслуживание этого сервиса serviceWithdrawn notOwner
  • Сервис теперь анонсируется с mcc-metallb-speaker-hgksn


Получение адреса ноды


Зная имя POD можно получить ноду (k8s-control-3):

kubectl -n metallb-system get pod/mcc-metallb-speaker-hgksn -o wide
NAME                        READY   STATUS    RESTARTS   AGE    IP           NODE            NOMINATED NODE   READINESS GATES
mcc-metallb-speaker-hgksn   1/1     Running   0          102m   10.80.3.13   k8s-control-3   <none>           <none>

Путь прохождени трафика

Трафик на ноде

Тут мы уже знаем на какую ноду (k8s-control-3) прийдет запрос и можем на ней запустить tcpdump и для теста "дернуть" сервис curl https://10.80.8.102 -I -k

root@k8s-control-3:~# tcpdump  -n -i any  host 10.80.8.102
...
12:12:44.576113 mlb   In  IP 192.168.22.253.52582 > 10.80.8.102.443: Flags [S], seq 3953098481, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 1301733900 ecr 0,sackOK,eol], length 0
12:12:44.577625 mlb   Out IP 10.80.8.102.443 > 192.168.22.253.52582: Flags [S.], seq 1124290493, ack 3953098482, win 64308, options [mss 1410,sackOK,TS val 3194506911 ecr 1301733900,nop,wscale 7], length 0
12:12:44.579051 mlb   In  IP 192.168.22.253.52582 > 10.80.8.102.443: Flags [.], ack 1, win 2053, options [nop,nop,TS val 1301733903 ecr 3194506911], length 0
12:12:44.579593 mlb   In  IP 192.168.22.253.52582 > 10.80.8.102.443: Flags [P.], seq 1:302, ack 1, win 2053, options [nop,nop,TS val 1301733903 ecr 3194506911], length 301
...

192.168.22.253 адрес хоста откуда запускался curl https://10.80.8.102 -I -k 10.80.8.102 адрес сервиса

Разбор сервиса

Для того что бы проследить дальнейший путь трафика нужно подробно разобрать сервис

kubectl  -n stacklight get svc iam-proxy-alertmanager  -o yaml

selector

Селектор определяет на какие поды будет направлен трафик

 selector:
    app.kubernetes.io/instance: iam-proxy-alertmanager
    app.kubernetes.io/name: iam-proxy

Их можно найти командой

kubectl get pod -A -l app.kubernetes.io/name=iam-proxy,app.kubernetes.io/instance=iam-proxy-alertmanager -o wide
NAMESPACE    NAME                                     READY   STATUS    RESTARTS   AGE   IP                NODE           NOMINATED NODE   READINESS GATES
stacklight   iam-proxy-alertmanager-76997d95b-d9czm   1/1     Running   0          42d   192.168.105.143   stacklight-1   <none>           <none>
stacklight   iam-proxy-alertmanager-76997d95b-mqd2f   1/1     Running   0          42d   192.168.104.66    stacklight-3   <none>           <none>

Icon-caution.gif

  • ключ -A оставлен намеренно что б показать что поиск по меткам работает сразу во всех namespace

Тут видно что трафик будет направлен на 2 пода с адресами

  • 192.168.105.143
  • 192.168.104.66

Что можно проверить используя tcpdump

tcpdump  -n -i any  host 192.168.105.143 or host 192.168.104.66

Вывод сокращен, до нескольких пакетов что бы показать что трафик идет поочередно на один или второй POD

12:26:50.893669 vxlan.calico Out IP 192.168.106.0.36057 > 192.168.105.143.4180: Flags [S], seq 2888292147, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 976299430 ecr 0,sackOK,eol], length 0
12:26:50.894698 vxlan.calico In  IP 192.168.105.143.4180 > 192.168.106.0.36057: Flags [S.], seq 1236287622, ack 2888292148, win 64308, options [mss 1410,sackOK,TS val 3195353228 ecr 976299430,nop,wscale 7], length 0
12:26:50.896305 vxlan.calico Out IP 192.168.106.0.36057 > 192.168.105.143.4180: Flags [.], ack 1, win 2053, options [nop,nop,TS val 976299433 ecr 3195353228], length 0
12:26:50.896972 vxlan.calico Out IP 192.168.106.0.36057 > 192.168.105.143.4180: Flags [P.], seq 1:302, ack 1, win 2053, options [nop,nop,TS val 976299433 ecr 3195353228], length 301
...
12:27:00.868844 vxlan.calico In  IP 192.168.104.66.4180 > 192.168.106.0.22319: Flags [S.], seq 2502063474, ack 1294456302, win 64308, options [mss 1410,sackOK,TS val 931778658 ecr 3753725410,nop,wscale 7], length 0
12:27:00.881856 vxlan.calico Out IP 192.168.106.0.22319 > 192.168.104.66.4180: Flags [.], ack 1, win 2053, options [nop,nop,TS val 3753725424 ecr 931778658], length 0
12:27:00.882748 vxlan.calico Out IP 192.168.106.0.22319 > 192.168.104.66.4180: Flags [P.], seq 1:302, ack 1, win 2053, options [nop,nop,TS val 3753725424 ecr 931778658], length 301
...

Вопросом доставки трафика до пода далее занимается Calico и обзор прохождения трафика через VxLAN сейчас не важен (что то есть тут: Calico_Kubernetes_the_hard_way_v2_How_packet_goes_from_pod)
В данный момент важно то что видны запросы и ответы

sessionAffinity: None

sessionAffinity: None

Такая настройка означает RoundRobin

ports

  - name: https
    nodePort: 30358
    port: 443
    protocol: TCP
    targetPort: https

тут кажется что трафик должен идти на 443 порт (но дамп выше это не подтверждает - там порт 4180)

На самом деле https тут это ИМЯ порта в поде

targetPort: https

Что можно проверить:


22

нашлось 2 пода дальше на той ноде которая анонсирует мак сервиса должны увидеть трафик на один из подов tcpdump -n -i any host 192.168.105.143 or host 192.168.104.66 tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes 16:06:08.104697 vxlan.calico Out IP 192.168.107.192.5013 > 192.168.105.143.4180: Flags [S], seq 2027178047, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 2603473557 ecr 0,sackOK,eol], length 0 Если такой трафик есть - смотреть на подах доходит ли Для этого для обоих подов действия (пример 192.168.104.66 на ноде stacklight-3 Для начала определить контейнер - но сделать это может быть сложно по тому заходим в под и запускаем там top (процессов /bin/oauth2-proxy может быть несколько а top скорее всего - один) childctl -n stacklight exec -ti iam-proxy-alertmanager-76997d95b-mqd2f -- sh top Дальше найти PID ps auxfw | grep top root 8244 0.0 0.0 2788 1712 ? S< Aug14 38:36 /usr/sbin/atopacctd root 1921049 0.0 0.0 7008 2200 pts/1 S+ 16:10 0:00 \_ grep --color=auto top nobody 1920805 0.0 0.0 1596 968 pts/0 S+ 16:10 0:00 \_ top root 796509 0.8 0.0 19616 19452 ? S<Ls 01:00 7:54 /usr/bin/atop -R -w /var/log/atop/atop_20250924 60 Интересует 1920805 nobody 1920805 0.0 0.0 1596 968 pts/0 S+ 16:10 0:00 \_ top 19:11 Далее по PID провалиться в NameSpace nsenter -t 1886583 -n 19:12 root@stacklight-3:~# nsenter -t 1920805 -n root@stacklight-3:~# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450

       inet 192.168.104.66  netmask 255.255.255.255  broadcast 0.0.0.0
       ether fe:cd:df:e1:24:d3  txqueuelen 1000  (Ethernet)
       RX packets 12212837  bytes 1400942826 (1.4 GB)
       RX errors 0  dropped 0  overruns 0  frame 0
       TX packets 10131352  bytes 3843343988 (3.8 GB)
       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536

       inet 127.0.0.1  netmask 255.0.0.0
       loop  txqueuelen 1000  (Local Loopback)
       RX packets 0  bytes 0 (0.0 B)
       RX errors 0  dropped 0  overruns 0  frame 0
       TX packets 0  bytes 0 (0.0 B)
       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ifconfig нужен для контроля - сравнить IP тот ли тут тот - 192.168.104.66 что и iam-proxy-alertmanager-76997d95b-mqd2f 1/1 Running 0 41d 192.168.104.66 19:15 Далее в поде (в 2-х !!!! одновременно!!!!) запускать tcpdump (трафик есть постоянно но не много) и дергать курлом tcpdump -n -i eth0 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes 16:12:45.747433 IP 192.168.107.192.64528 > 192.168.104.66.4180: Flags [S], seq 1723519164, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 3632424568 ecr 0,sackOK,eol], length 0 16:12:45.747474 IP 192.168.104.66.4180 > 192.168.107.192.64528: Flags [S.], seq 3246211835, ack 1723519165, win 64308, options [mss 1410,sackOK,TS val 1325901618 ecr 3632424568,nop,wscale 7], length 0 16:12:45.749724 IP 192.168.107.192.64528 > 192.168.104.66.4180: Flags [.], ack 1, win 2053, options [nop,nop,TS val 3632424571 ecr 1325901618], length 0 16:12:45.751215 IP 192.168.107.192.64528 > 192.168.104.66.4180: Flags [P.], seq 1:302, ack 1, win 2053, options [nop,nop,TS val 3632424571 ecr 1325901618], length 301 Сначала с другой ноды - должны быть запросы и ответы Потом откуда (c локальной машины клиента) не работат - и тут надо понимать есть ли запросы Если нет то проверить childctl -n stacklight get networkpolicy iam-proxy-alertmanager -o yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:

 annotations:
   meta.helm.sh/release-name: iam-proxy-alertmanager
   meta.helm.sh/release-namespace: stacklight
 creationTimestamp: "2025-08-14T08:14:35Z"
 generation: 1
 labels:
   app.kubernetes.io/managed-by: Helm
 name: iam-proxy-alertmanager
 namespace: stacklight
 resourceVersion: "565154"
 uid: ab15862b-b7a9-45b3-ba2d-b378fce80d4c

spec:

 egress:
 - {}
 ingress:
 - from:
   - ipBlock:
       cidr: 0.0.0.0/0
   ports:
   - port: 4180
     protocol: TCP
 podSelector:
   matchLabels:
     app.kubernetes.io/instance: iam-proxy-alertmanager
     app.kubernetes.io/name: iam-proxy
 policyTypes:
 - Ingress
 - Egress

status: {}