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

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
 
(не показано 15 промежуточных версий этого же участника)
Строка 1: Строка 1:
[[Категория:Draft]]
+
[[Категория:K8s]]
  +
[[Категория:MetalLB]]
  +
 
=K8s Metal LB Service Trafic Flow=
 
=K8s Metal LB Service Trafic Flow=
 
Заметка о пути трафика с MetalLB
 
Заметка о пути трафика с MetalLB
Строка 11: Строка 13:
   
 
=Найти с какой ноды анонсируется адрес=
 
=Найти с какой ноды анонсируется адрес=
  +
==Если повезло==
  +
Если события логгируются то можно достать из логов
  +
<BR>
  +
[[Файл:OpenSearch MetalLB 250925155617.png|400px]]
  +
<BR>
  +
К сожалению этот простой путь доступен не всегда
  +
 
==Описание сервиса==
 
==Описание сервиса==
 
<PRE>
 
<PRE>
Строка 193: Строка 202:
 
sessionAffinity: None
 
sessionAffinity: None
 
</PRE>
 
</PRE>
  +
Такая настройка означает RoundRobin
   
 
===ports===
 
===ports===
  +
<PRE>
 
- name: https
 
- name: https
 
nodePort: 30358
 
nodePort: 30358
Строка 200: Строка 211:
 
protocol: TCP
 
protocol: TCP
 
targetPort: https
 
targetPort: https
 
 
 
 
 
</PRE>
 
</PRE>
  +
тут кажется что трафик должен идти на 443 порт (но дамп выше это не подтверждает - там порт <code>4180</code>)
http тут это ИМЯ порта в поде
 
  +
<BR>
  +
  +
На самом деле <code>https</code> тут это '''ИМЯ''' порта в поде
  +
<PRE>
 
targetPort: https
 
targetPort: https
  +
</PRE>
как найти на какие поды - надо смотреть по меткам
 
  +
Что можно проверить:
selector:
 
  +
<PRE>
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 yaml \
  +
| yq '.items[].spec.containers[].ports'
childctl -n stacklight get pod -l "app.kubernetes.io/instance"="iam-proxy-alertmanager","app.kubernetes.io/name"="iam-proxy" -o wide
 
  +
</PRE>
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
 
  +
<PRE>
iam-proxy-alertmanager-76997d95b-d9czm 1/1 Running 0 41d 192.168.105.143 stacklight-1 <none> <none>
 
  +
- containerPort: 4180
iam-proxy-alertmanager-76997d95b-mqd2f 1/1 Running 0 41d 192.168.104.66 stacklight-3 <none> <none>
 
  +
name: https
нашлось 2 пода
 
  +
protocol: TCP
дальше на той ноде которая анонсирует мак сервиса должны увидеть трафик на один из подов
 
  +
- containerPort: 4180
tcpdump -n -i any host 192.168.105.143 or host 192.168.104.66
 
  +
name: https
tcpdump: data link type LINUX_SLL2
 
  +
protocol: TCP
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
 
  +
</PRE>
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
 
  +
* <code>name: https</code> соответвует <code>containerPort: 4180</code> и совпадает с тем что видно в <code>tcpdump</code>:
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
 
  +
<PRE>
Если такой трафик есть - смотреть на подах доходит ли
 
  +
192.168.106.0.36057 > 192.168.105.143.4180
Для этого для обоих подов действия (пример 192.168.104.66 на ноде stacklight-3
 
  +
</PRE>
  +
  +
==Трафик в <code>POD</code>==
  +
Для этого для обоих подов действия (пример 192.168.104.66 на ноде stacklight-3)
  +
<BR>
 
Для начала определить контейнер - но сделать это может быть сложно
 
Для начала определить контейнер - но сделать это может быть сложно
  +
<BR>
по тому заходим в под и запускаем там top (процессов /bin/oauth2-proxy может быть несколько а top скорее всего - один)
 
  +
по тому заходим в под и запускаем там <code>top</code> (процессов <code>/bin/oauth2-proxy</code> может быть несколько а top скорее всего - один, но метод косвенный)
childctl -n stacklight exec -ti iam-proxy-alertmanager-76997d95b-mqd2f -- sh
 
  +
<PRE>
  +
kubectl -n stacklight exec -ti iam-proxy-alertmanager-76997d95b-mqd2f -- sh
  +
 
top
 
top
  +
</PRE>
Дальше найти PID
 
  +
Дальше найти PID процесса <code>top</code>
  +
<PRE>
 
ps auxfw | grep top
 
ps auxfw | grep top
 
root 8244 0.0 0.0 2788 1712 ? S< Aug14 38:36 /usr/sbin/atopacctd
 
root 8244 0.0 0.0 2788 1712 ? S< Aug14 38:36 /usr/sbin/atopacctd
Строка 234: Строка 255:
 
nobody 1920805 0.0 0.0 1596 968 pts/0 S+ 16:10 0:00 \_ 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
 
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
  +
</PRE>
Интересует 1920805
 
  +
Интересует <code>1920805</code>
  +
<PRE>
 
nobody 1920805 0.0 0.0 1596 968 pts/0 S+ 16:10 0:00 \_ top
 
nobody 1920805 0.0 0.0 1596 968 pts/0 S+ 16:10 0:00 \_ top
  +
</PRE>
19:11
 
  +
Далее по PID провалиться в NameSpace
 
  +
Далее по PID провалиться в <code>network namespace</code>
  +
<PRE>
 
nsenter -t 1886583 -n
 
nsenter -t 1886583 -n
  +
</PRE>
19:12
 
  +
Проверить что находимся внутри <code>network namespace</code>
root@stacklight-3:~# nsenter -t 1920805 -n
 
  +
<PRE>
root@stacklight-3:~# ifconfig
 
  +
ifconfig
  +
</PRE>
  +
<PRE>
 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
 
inet 192.168.104.66 netmask 255.255.255.255 broadcast 0.0.0.0
 
inet 192.168.104.66 netmask 255.255.255.255 broadcast 0.0.0.0
Строка 249: Строка 277:
 
TX packets 10131352 bytes 3843343988 (3.8 GB)
 
TX packets 10131352 bytes 3843343988 (3.8 GB)
 
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
 
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  +
</PRE>
  +
* Адрес <code>192.168.104.66</code> совпадает с тем что было в описании <code>POD</code>: <code>iam-proxy-alertmanager-76997d95b-mqd2f 1/1 Running 0 41d 192.168.104.66</code>
   
  +
Далее в <code>POD</code>запускать <code>tcpdump</code>
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
 
  +
<PRE>
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 -n -i eth0
  +
</PRE>
  +
<PRE>
 
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
 
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
 
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
 
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
Строка 268: Строка 291:
 
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.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
 
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
  +
</PRE>
Сначала с другой ноды - должны быть запросы и ответы
 
Потом откуда (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: {}
 

Текущая версия на 09:34, 26 сентября 2025


K8s Metal LB Service Trafic Flow

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

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

Если повезло

Если события логгируются то можно достать из логов
OpenSearch MetalLB 250925155617.png
К сожалению этот простой путь доступен не всегда

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

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

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

kubectl get pod -A -l app.kubernetes.io/name=iam-proxy,app.kubernetes.io/instance=iam-proxy-alertmanager -o yaml \
    | yq '.items[].spec.containers[].ports'
- containerPort: 4180
  name: https
  protocol: TCP
- containerPort: 4180
  name: https
  protocol: TCP
  • name: https соответвует containerPort: 4180 и совпадает с тем что видно в tcpdump:
192.168.106.0.36057 > 192.168.105.143.4180

Трафик в POD

Для этого для обоих подов действия (пример 192.168.104.66 на ноде stacklight-3)
Для начала определить контейнер - но сделать это может быть сложно
по тому заходим в под и запускаем там top (процессов /bin/oauth2-proxy может быть несколько а top скорее всего - один, но метод косвенный)

kubectl  -n stacklight  exec -ti iam-proxy-alertmanager-76997d95b-mqd2f  -- sh

top

Дальше найти PID процесса top

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

Далее по PID провалиться в network namespace

nsenter -t 1886583 -n

Проверить что находимся внутри network namespace

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
  • Адрес 192.168.104.66 совпадает с тем что было в описании POD: iam-proxy-alertmanager-76997d95b-mqd2f 1/1 Running 0 41d 192.168.104.66

Далее в PODзапускать 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