K8s Metal LB Service Trafic Flow: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
| (не показаны 44 промежуточные версии этого же участника) | |||
| Строка 1: | Строка 1: | ||
| − | [[Категория: |
+ | [[Категория: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> |
||
kubectl -n stacklight get svc iam-proxy-alertmanager |
kubectl -n stacklight get svc iam-proxy-alertmanager |
||
| Строка 17: | Строка 27: | ||
</PRE> |
</PRE> |
||
Тут виден внешний адрес сервиса - <code>10.80.8.102</code> |
Тут виден внешний адрес сервиса - <code>10.80.8.102</code> |
||
| + | <BR> |
||
| + | ==Поиск адреса в логах== |
||
| + | Посмотреть все логи по всем подам можно например так: |
||
<PRE> |
<PRE> |
||
kubectl -n metallb-system logs daemonset/mcc-metallb-speaker --prefix |
kubectl -n metallb-system logs daemonset/mcc-metallb-speaker --prefix |
||
</PRE> |
</PRE> |
||
| + | {{caution|text= |
||
| + | Обращать внимание на сообщения вроде |
||
| + | <PRE> |
||
| + | Found 3 pods, using pod/mcc-metallb-speaker-8k5wl |
||
| + | </PRE> |
||
| + | Если такое есть - то логи не полные и нужно смотреть по метке |
||
| + | }} |
||
| + | {{caution|text= |
||
| + | Можно и нужно искать и по метке, а не только по принадлежности к <code>daemonset</code> |
||
| + | <PRE> |
||
| + | kubectl -n metallb-system logs -l "app.kubernetes.io/component"="speaker" --prefix |
||
| + | </PRE> |
||
| + | }} |
||
| + | {{caution|text= |
||
| + | Не забывать что логи могут выводится не все |
||
| + | <BR> |
||
| + | Правильно, что б найти то что нужно не забывать про |
||
| + | * <code>--prefix</code> что бы видеть имя пода и контейнера |
||
| + | * <code>--since=24h</code> время, что бы не выгребать вообще все логи, когда они не нужны |
||
| + | * <code>--tail=-1</code> показать все логи. Это важно так как часто k8s решает показать только часть, я не исследовал причин и настроек этого поведения |
||
| + | * <code>--timestamps</code> обычно хочется меток времени (их может и не быть в логах приложения и по ним можно сортировать) |
||
| + | * <code>LC_ALL=C sort -k2,2 </code> если хоется сортировку по времени а не по подам (обычно хочется) |
||
| + | }} |
||
| + | ==Финальный запрос== |
||
| − | =На= |
||
| + | <PRE> |
||
| + | 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' |
||
| + | </PRE> |
||
| + | <PRE> |
||
| + | [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#</PRE> |
||
| + | |||
| + | Из этого лога можно понять какой <code>POD</code> анонсировал адрес |
||
| + | * Сначала это был <code>pod/mcc-metallb-speaker-8k5wl/speaker</code> |
||
| + | * Потом он прекратил обслуживание этого сервиса <code> serviceWithdrawn</code> <code> notOwner</code> |
||
| + | * Сервис теперь анонсируется с <code>mcc-metallb-speaker-hgksn</code> |
||
| + | <BR> |
||
| + | ==Получение адреса ноды== |
||
| + | <BR> |
||
| + | Зная имя <code>POD</code> можно получить ноду (<code>k8s-control-3</code>): |
||
| + | <PRE> |
||
| + | kubectl -n metallb-system get pod/mcc-metallb-speaker-hgksn -o wide |
||
| + | </PRE> |
||
| + | <PRE> |
||
| + | 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> |
||
| + | </PRE> |
||
| + | |||
| + | =Путь прохождени трафика= |
||
| + | ==Трафик на ноде== |
||
| + | Тут мы уже знаем на какую ноду (<code>k8s-control-3</code>) прийдет запрос и можем на ней запустить <code>tcpdump</code> и для теста "дернуть" сервис <code>curl https://10.80.8.102 -I -k</code> |
||
| + | |||
| + | <PRE> |
||
| + | root@k8s-control-3:~# tcpdump -n -i any host 10.80.8.102 |
||
| + | </PRE> |
||
| + | <PRE> |
||
| + | ... |
||
| + | 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 |
||
| + | ... |
||
| + | </PRE> |
||
| + | <code>192.168.22.253</code> адрес хоста откуда запускался <code>curl https://10.80.8.102 -I -k</code> |
||
| + | <code>10.80.8.102</code> адрес сервиса |
||
| + | |||
| + | ==Разбор сервиса== |
||
| + | Для того что бы проследить дальнейший путь трафика нужно подробно разобрать сервис |
||
| + | <PRE> |
||
kubectl -n stacklight get svc iam-proxy-alertmanager -o yaml |
kubectl -n stacklight get svc iam-proxy-alertmanager -o yaml |
||
| + | </PRE> |
||
| + | |||
| + | {{#spoiler:show=Полный вывод команды| |
||
| + | <PRE> |
||
| + | apiVersion: v1 |
||
| + | kind: Service |
||
| + | metadata: |
||
| + | annotations: |
||
| + | meta.helm.sh/release-name: iam-proxy-alertmanager |
||
| + | meta.helm.sh/release-namespace: stacklight |
||
| + | metallb.universe.tf/ip-allocated-from-pool: default |
||
| + | creationTimestamp: "2025-08-14T08:14:35Z" |
||
| + | labels: |
||
| + | app.kubernetes.io/instance: iam-proxy-alertmanager |
||
| + | app.kubernetes.io/managed-by: Helm |
||
| + | app.kubernetes.io/name: iam-proxy |
||
| + | helm.sh/chart: iam-proxy-0.2.23 |
||
| + | name: iam-proxy-alertmanager |
||
| + | namespace: stacklight |
||
| + | resourceVersion: "565165" |
||
| + | uid: fc467ca1-03a3-437b-883c-e5acdc127a21 |
||
| + | spec: |
||
| + | allocateLoadBalancerNodePorts: true |
||
| + | clusterIP: 10.232.100.189 |
||
| + | clusterIPs: |
||
| + | - 10.232.100.189 |
||
| + | externalTrafficPolicy: Cluster |
||
| + | internalTrafficPolicy: Cluster |
||
| + | ipFamilies: |
||
| + | - IPv4 |
||
| + | ipFamilyPolicy: SingleStack |
||
ports: |
ports: |
||
- name: https |
- name: https |
||
| Строка 29: | Строка 143: | ||
protocol: TCP |
protocol: TCP |
||
targetPort: https |
targetPort: https |
||
| − | http тут это ИМЯ порта в поде |
||
| − | targetPort: https |
||
| − | как найти на какие поды - надо смотреть по меткам |
||
selector: |
selector: |
||
app.kubernetes.io/instance: iam-proxy-alertmanager |
app.kubernetes.io/instance: iam-proxy-alertmanager |
||
app.kubernetes.io/name: iam-proxy |
app.kubernetes.io/name: iam-proxy |
||
| + | sessionAffinity: None |
||
| − | childctl -n stacklight get pod -l "app.kubernetes.io/instance"="iam-proxy-alertmanager","app.kubernetes.io/name"="iam-proxy" -o wide |
||
| + | type: LoadBalancer |
||
| − | NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES |
||
| + | status: |
||
| − | iam-proxy-alertmanager-76997d95b-d9czm 1/1 Running 0 41d 192.168.105.143 stacklight-1 <none> <none> |
||
| + | loadBalancer: |
||
| − | iam-proxy-alertmanager-76997d95b-mqd2f 1/1 Running 0 41d 192.168.104.66 stacklight-3 <none> <none> |
||
| + | ingress: |
||
| − | нашлось 2 пода |
||
| + | - ip: 10.80.8.102 |
||
| − | дальше на той ноде которая анонсирует мак сервиса должны увидеть трафик на один из подов |
||
| + | </PRE> |
||
| − | 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 |
||
| + | ===selector=== |
||
| − | 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 |
||
| + | <PRE> |
||
| − | Если такой трафик есть - смотреть на подах доходит ли |
||
| + | selector: |
||
| − | Для этого для обоих подов действия (пример 192.168.104.66 на ноде stacklight-3 |
||
| + | app.kubernetes.io/instance: iam-proxy-alertmanager |
||
| + | app.kubernetes.io/name: iam-proxy |
||
| + | </PRE> |
||
| + | Их можно найти командой |
||
| + | <PRE> |
||
| + | kubectl get pod -A -l app.kubernetes.io/name=iam-proxy,app.kubernetes.io/instance=iam-proxy-alertmanager -o wide |
||
| + | </PRE> |
||
| + | <PRE> |
||
| + | 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> |
||
| + | </PRE> |
||
| + | |||
| + | {{caution|text= |
||
| + | * ключ <code>-A</code> оставлен намеренно что б показать что поиск по меткам работает сразу во всех <code>namespace</code> |
||
| + | }} |
||
| + | Тут видно что трафик будет направлен на 2 пода с адресами |
||
| + | * <code>192.168.105.143</code> |
||
| + | * <code>192.168.104.66</code> |
||
| + | Что можно проверить используя <code>tcpdump</code> |
||
| + | <PRE> |
||
| + | tcpdump -n -i any host 192.168.105.143 or host 192.168.104.66 |
||
| + | </PRE> |
||
| + | Вывод сокращен, до нескольких пакетов что бы показать что трафик идет поочередно на один или второй <code>POD</code> |
||
| + | <PRE> |
||
| + | 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 |
||
| + | ... |
||
| + | </PRE> |
||
| + | Вопросом доставки трафика до пода далее занимается <code>Calico</code> и обзор прохождения трафика через <code>VxLAN</code> сейчас не важен (что то есть тут: [[Calico_Kubernetes_the_hard_way_v2_How_packet_goes_from_pod]]) |
||
| + | <BR> |
||
| + | В данный момент важно то что видны запросы и ответы |
||
| + | |||
| + | ===sessionAffinity: None=== |
||
| + | <PRE> |
||
| + | sessionAffinity: None |
||
| + | </PRE> |
||
| + | Такая настройка означает RoundRobin |
||
| + | |||
| + | ===ports=== |
||
| + | <PRE> |
||
| + | - name: https |
||
| + | nodePort: 30358 |
||
| + | port: 443 |
||
| + | protocol: TCP |
||
| + | targetPort: https |
||
| + | </PRE> |
||
| + | тут кажется что трафик должен идти на 443 порт (но дамп выше это не подтверждает - там порт <code>4180</code>) |
||
| + | <BR> |
||
| + | |||
| + | На самом деле <code>https</code> тут это '''ИМЯ''' порта в поде |
||
| + | <PRE> |
||
| + | targetPort: https |
||
| + | </PRE> |
||
| + | Что можно проверить: |
||
| + | <PRE> |
||
| + | 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' |
||
| + | </PRE> |
||
| + | <PRE> |
||
| + | - containerPort: 4180 |
||
| + | name: https |
||
| + | protocol: TCP |
||
| + | - containerPort: 4180 |
||
| + | name: https |
||
| + | protocol: TCP |
||
| + | </PRE> |
||
| + | * <code>name: https</code> соответвует <code>containerPort: 4180</code> и совпадает с тем что видно в <code>tcpdump</code>: |
||
| + | <PRE> |
||
| + | 192.168.106.0.36057 > 192.168.105.143.4180 |
||
| + | </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 |
||
| Строка 58: | Строка 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 |
||
| Строка 73: | Строка 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 |
||
| Строка 92: | Строка 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
"Проблемный" взят в кавычки так как не ясно в сервисе ли дело или в чем-то другом
Найти с какой ноды анонсируется адрес
Если повезло
Если события логгируются то можно достать из логов
К сожалению этот простой путь доступен не всегда
Описание сервиса
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
|
Обращать внимание на сообщения вроде Found 3 pods, using pod/mcc-metallb-speaker-8k5wl Если такое есть - то логи не полные и нужно смотреть по метке |
|
Можно и нужно искать и по метке, а не только по принадлежности к kubectl -n metallb-system logs -l "app.kubernetes.io/component"="speaker" --prefix |
|
Не забывать что логи могут выводится не все
|
Финальный запрос
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 - Потом он прекратил обслуживание этого сервиса
serviceWithdrawnnotOwner - Сервис теперь анонсируется с
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>
|
Тут видно что трафик будет направлен на 2 пода с адресами
192.168.105.143192.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