Вопрос или проблема
Когда применяется служба 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 для обработки входящего трафика. Основные шаги следующие:
-
Разделение правил. Оба правила в цепочке KUBE-SERVICES имеют одну и ту же целевой IP-адрес (10.101.173.15) и протокол (TCP), но для каждого порта создаются отдельные цепочки (например, KUBE-SVC-R4PDB35TUPNR4CEW и KUBE-SVC-P73F5K5MMQHXGZV7). Эти цепочки предназначены для обработки логики маршрутизации.
-
Маршрутизация через конечные точки. Каждое правило перенаправляет трафик на соответствующие конечные точки. Например:
- Правило для
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, поскольку она дает возможность оптимизировать производительность приложений и устранять проблемы с сетью.