Как сервис в k8s распознает разные порты назначения через iptables?

Вопрос или проблема

Когда применяется служба k8s, как указано ниже, эта одна служба открывает два разных порта для двух подов.

apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  type: NodePort
  selector:
    app: products
    department: sales
  ports:
  - name: port-v1
    protocol: TCP
    port: 39090
    targetPort: 9090
  - name: port-v2
    protocol: TCP
    port: 49191
    targetPort: 9191

Служба будет сгенерирована с следующим результатом

root@cp01:~# kcds hello-service
Name:                     hello-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=products,department=sales
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.101.173.15
IPs:                      10.101.173.15
Port:                     port-v1  39090/TCP
TargetPort:               9090/TCP
NodePort:                 port-v1  30725/TCP
Endpoints:                192.168.189.15:9090
Port:                     port-v2  49191/TCP
TargetPort:               9191/TCP
NodePort:                 port-v2  31576/TCP
Endpoints:                192.168.189.15:9191
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

Затем я обнаружил, что kube-proxy добавит следующее правило в таблицу NAT iptables

-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 -d 10.101.173.15/32 -p tcp -m comment --comment "default/hello-service:port-v1 cluster IP" -j KUBE-SVC-R4PDB35TUPNR4CEW  # Нет порта назначения в качестве параметра
-A KUBE-SERVICES -d 10.101.173.15/32 -p tcp -m comment --comment "default/hello-service:port-v2 cluster IP" -j KUBE-SVC-P73F5K5MMQHXGZV7  # Нет порта назначения в качестве параметра
......
-A KUBE-SVC-P73F5K5MMQHXGZV7 -m comment --comment "default/hello-service:port-v2 -> 192.168.189.15:9191" -j KUBE-SEP-GZ2FT6XOW5XY6PQC
-A KUBE-SVC-R4PDB35TUPNR4CEW -m comment --comment "default/hello-service:port-v1 -> 192.168.189.15:9090" -j KUBE-SEP-AA54JU3D4RO26WUA
......
-A KUBE-SEP-GZ2FT6XOW5XY6PQC -s 192.168.189.15/32 -m comment --comment "default/hello-service:port-v2" -j KUBE-MARK-MASQ
-A KUBE-SEP-GZ2FT6XOW5XY6PQC -p tcp -m comment --comment "default/hello-service:port-v2" -m tcp -j DNAT --to-destination 192.168.189.15:9191
-A KUBE-SEP-AA54JU3D4RO26WUA -s 192.168.189.15/32 -m comment --comment "default/hello-service:port-v1" -j KUBE-MARK-MASQ
-A KUBE-SEP-AA54JU3D4RO26WUA -p tcp -m comment --comment "default/hello-service:port-v1" -m tcp -j DNAT --to-destination 192.168.189.15:9090
......

Что заставляет меня чувствовать себя странно, так это две правила в KUBE-SERVICES, их параметры совпадают, оба используют -d 10.101.173.15/32 -p tcp как параметр совпадения, и не используют порт назначения как основание для различия, только комментарии разные, как вы можете различить пакеты, отправленные на разные целевые адреса?

И фактический тест на самом деле совпал успешно, я дважды выполнил исходящий на 39090 и один раз на порт 49191 с следующими результатами

# дважды
curl -L -v http://10.101.173.15:39090
curl -L -v http://10.101.173.15:39090
# один раз
curl -L -v http://10.101.173.15:49191

root@cp01:~# iptables -t nat -L -v -n --line-number | grep 10.101.173.15
2        2   120 KUBE-SVC-R4PDB35TUPNR4CEW  tcp  --  *      *       0.0.0.0/0            10.101.173.15        /* defau                                        lt/hello-service:port-v1 cluster IP */
3        1    60 KUBE-SVC-P73F5K5MMQHXGZV7  tcp  --  *      *       0.0.0.0/0            10.101.173.15        /* defau                                        lt/hello-service:port-v2 cluster IP */

Я не понимаю, как это делает K8S?

По моему представлению, kube-proxy достигает управления трафиком на уровне компьютера, создавая различные правила в iptables, что означает, что любое управление пакетами должно осуществляться через механизм управления iptables, но какое дело с вышеупомянутым явлением? iptables, похоже, не может контролировать перенаправление пакетов через содержимое комментариев, и K8S не должен вмешиваться в механизм iptables таким образом.

Я действительно запутался, пожалуйста, помогите мне!

Ответ или решение

Когда вы создаете сервис в Kubernetes, как указано в вашем примере с hello-service, он действует как абстракция, позволяющая доступ к набору подов через одну точку входа, в данном случае — через виртуальный IP-адрес и порты. Давайте подробно рассмотрим, как Kubernetes определяет и обрабатывает разные порты назначения с помощью iptables.

Архитектура Kubernetes Service

В вашем случае сервис hello-service был настроен на использование двух портов:

  • Порт port-v1 (39090) с целевым портом 9090.
  • Порт port-v2 (49191) с целевым портом 9191.

Каждый из этих портов соответствует определенному поду с метками app: products и department: sales. Kubernetes использует kube-proxy для управления сетевым трафиком и маршрутизации запросов к подам.

Работа kube-proxy и iptables

Когда kube-proxy создает правила в таблице NAT iptables, это важно для маршрутизации трафика. Правила, которые вы видите, показывают, как Kubernetes использует iptables для обработки входящего трафика. Основные шаги следующие:

  1. Разделение правил. Оба правила в цепочке KUBE-SERVICES имеют одну и ту же целевой IP-адрес (10.101.173.15) и протокол (TCP), но для каждого порта создаются отдельные цепочки (например, KUBE-SVC-R4PDB35TUPNR4CEW и KUBE-SVC-P73F5K5MMQHXGZV7). Эти цепочки предназначены для обработки логики маршрутизации.

  2. Маршрутизация через конечные точки. Каждое правило перенаправляет трафик на соответствующие конечные точки. Например:

    • Правило для port-v1 перенаправляет трафик на 192.168.189.15:9090.
    • Правило для port-v2 перенаправляет трафик на 192.168.189.15:9191.

Как iptables обрабатывает порты

В вашем вопросе вы упоминаете, что правила не используют порт назначения в самом правиле KUBE-SERVICES. Это действительно так, и вот как это работает:

  • Обработка по цепочкам. После того, как пакеты поступают в обрабатываемую цепочку KUBE-SERVICES, iptables не использует исключительно комментарии для обработки маршрутизации. Вместо этого, как только пакет попадает в соответствующую цепочку (например, KUBE-SVC-R4PDB35TUPNR4CEW для port-v1), он передается дальше в KUBE-SEP-AA54JU3D4RO26WUA, где происходит окончательная маршрутизация с использованием DNAT для перенаправления на нужный под.

  • Отделение маршрутизации от обработки. Таким образом, iptables обрабатывает детали маршрутизации через специфические цепочки KUBE-SVC и KUBE-SEP, которые уже отслеживают порты назначения на более глубоком уровне. Фактически, обработка комментариев помогает людям понять, что происходит, но сама маршрутизация управляется через цепочки.

Заключение

Таким образом, несмотря на то, что на первый взгляд кажется, что правила KUBE-SERVICES не включают различия в портах, на самом деле маршрутизация управляется в более специфичных цепочках (KUBE-SVC и KUBE-SEP), которые обеспечивают правильный маршрут для каждого пакета в зависимости от конечных точек.

Эта модульная иерархия правил в iptables позволяет Kubernetes эффективно обрабатывать трафик для различных сервисов, обеспечивая гибкость и масштабируемость приложений. Понимание этой архитектуры критически важно для администраторов и разработчиков, работающих с Kubernetes, поскольку она дает возможность оптимизировать производительность приложений и устранять проблемы с сетью.

Оцените материал
Добавить комментарий

Капча загружается...