Изучение сети Kubernetes
Kubernetes – это система управления контейнерами, которая работает с контейнерными приложениями в кластере. Для поддержания надежного соединения между всеми контейнерами в кластере требуются некоторые усовершенствованные сетевые технологии. В этом мануале мы кратко рассмотрим некоторые инструменты и методы проверки сети.
Эти инструменты могут быть полезны при отладке подключения, исследовании пропускной способности сети или изучении Kubernetes в целом.
Читайте также:
Требования
Для работы вам нужен готовый кластер Kubernetes и локальная установка kubectl с доступом к этому кластеру.
Многие команды мануала следует запускать на нодах Kubernetes. Они будут выделены зеленым:
echo 'this is a node command'
Команды, которые нужно запускать на локальном компьютере, не будут выделяться:
echo 'this is a local command'
Примечание: Большинство команд в этом мануале нужно запускать как root. Если вместо этого на нодах Kubernetes вы запустите пользователя sudo, добавьте sudo в команду.
Определение IP-адреса пода в кластере
Чтобы узнать IP-адрес пода Kubernetes в кластере, используйте команду kubectl get pod на вашей локальной машине с опцией -о wide. Этот параметр выведет больше информации, включая ноду, на которой находится под, и сам IP-адрес в кластере.
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
hello-world-5b446dd74b-7c7pk 1/1 Running 0 22m 10.244.18.4 node-one
hello-world-5b446dd74b-pxtzt 1/1 Running 0 22m 10.244.3.4 node-two
Столбец IP будет содержать внутренний IP-адрес каждого пода.
Если в списке вы не видите нужный под, убедитесь, что вы находитесь в правильном пространстве имен. Чтобы вывести все контейнеры во всех пространствах имен, добавив флаг –all-namespaces.
Определение IP-адреса сервиса
Чтобы определить IP-адрес сервиса, можно также использовать kubectl. Чтобы запросить все сервисы во всех пространствах имен, введите:
kubectl get service --all-namespaces
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.32.0.1 <none> 443/TCP 6d
kube-system csi-attacher-doplugin ClusterIP 10.32.159.128 <none> 12345/TCP 6d
kube-system csi-provisioner-doplugin ClusterIP 10.32.61.61 <none> 12345/TCP 6d
kube-system kube-dns ClusterIP 10.32.0.10 <none> 53/UDP,53/TCP 6d
kube-system kubernetes-dashboard ClusterIP 10.32.226.209 <none> 443/TCP 6d
IP-адрес сервиса можно найти в столбце CLUSTER-IP.
Пространства имен подов в сети
Каждому поду Kubernetes присваивается собственное пространство имен. Сетевые пространства имен (или netns) являются примитивами сети Linux, которые обеспечивают изоляцию между сетевыми устройствами.
Иногда команды нужно запускать из netns пода – чтобы проверить DNS-разрешение или общее сетевое подключение. Для этого сначала нужно найти ID процесса одного из контейнеров в поде. К примеру, для Docker это можно сделать с помощью двух команд. Сначала запросите контейнеры, запущенные на ноде:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
173ee46a3926 gcr.io/google-samples/node-hello "/bin/sh -c 'node se…" 9 days ago Up 9 days k8s_hello-world_hello-world-5b446dd74b-pxtzt_default_386a9073-7e35-11e8-8a3d-bae97d2c1afd_0
11ad51cb72df k8s.gcr.io/pause-amd64:3.1 "/pause" 9 days ago Up 9 days k8s_POD_hello-world-5b446dd74b-pxtzt_default_386a9073-7e35-11e8-8a3d-bae97d2c1afd_0
. . .
Найдите ID или имя любого контейнера в интересующем вас поде. В приведенном выше примере есть два контейнера:
- Первый контейнер – приложение hello-world, работающее в поде hello-world.
- Второй – это контейнер pause, работающий в поде hello-world. Этот контейнер существует только для того, чтобы удержать сетевое пространство имен пода.
Чтобы узнать ID процесса любого контейнера, запишите ID или имя контейнера и используйте его в этой команде docker:
docker inspect --format '{{ .State.Pid }}' container-id-or-name
14552
На экране появится идентификатор процесса (или PID). Теперь можно использовать программу nsenter для запуска команды в сетевом пространстве имен этого процесса:
nsenter -t your-container-pid -n ip addr
Обязательно укажите свой PID и замените ip addr командой, которую вы хотите запустить в пространстве имен пода.
Примечание: Одно из преимуществ использования nsenter при запуске команд в пространстве имен пода вместо docker exec заключается в том, что у nsenter есть доступ ко всем командам на ноде, а не только к типично ограниченному набору команд, установленному в контейнерах.
Определение виртуального ethernet-интерфейса пода
Сетевое пространство имен каждого пода связывается с root netns ноды через виртуальный Ethernet-канал. На стороне ноды этот канал отображается как устройство, которое обычно начинается с veth и заканчивается уникальным идентификатором, например veth77f2275 или veth01. Внутри пода этот канал отображается как eth0.
Иногда бывает необходимо определить, какое устройство veth связано с тем или иным контейнером. Для этого нужно отобразить все сетевые устройства на ноде, а затем запросить устройства в сетевом пространстве имен пода. После этого можно сопоставить номера устройств в этих списках и установить соединение.
Сначала запустите ip addr в сетевом пространстве имен пода с помощью nsenter. В предыдущем разделе мы подробно рассказали о том, как это сделать.
nsenter -t your-container-pid -n ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether 02:42:0a:f4:03:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.244.3.4/24 brd 10.244.3.255 scope global eth0
valid_lft forever preferred_lft forever
Команда выведет список интерфейсов пода. Обратите внимание на номер if11 после eth0@ в полученном выводе. Это означает, что eth0 этого пода связан с 11-м интерфейсом ноды. Теперь запустите ip addr в пространстве имен ноды по умолчанию, чтобы отобразить интерфейсы:
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
. . .
7: veth77f2275@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master docker0 state UP group default
link/ether 26:05:99:58:0d:b9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::2405:99ff:fe58:db9/64 scope link
valid_lft forever preferred_lft forever
9: vethd36cef3@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master docker0 state UP group default
link/ether ae:05:21:a2:9a:2b brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::ac05:21ff:fea2:9a2b/64 scope link
valid_lft forever preferred_lft forever
11: veth4f7342d@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master docker0 state UP group default
link/ether e6:4d:7b:6f:56:4c brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::e44d:7bff:fe6f:564c/64 scope link
valid_lft forever preferred_lft forever
В данном примере 11-й интерфейс – это veth4f7342d. Это виртуальный ethernet-канал пода.
Отслеживание соединений conntrack
До версии 1.11 Kubernetes использовал iptables NAT и модуль ядра conntrack для отслеживания соединений. Чтобы просмотреть все отслеживаемые соединения, используйте команду conntrack:
conntrack -L
Чтобы просмотреть новые соединения, добавьте флаг –Е:
conntrack -E
Чтобы отобразить отслеживаемые conntrack соединения до определенного целевого адреса, добавьте флаг –d:
conntrack -L -d 10.32.0.1
Если у ваших нод возникают проблемы с установкой надежного подключения к сервисам, возможно, это потому, что таблица отслеживания соединений заполнена, а новые соединения будут удаляются. Если это так, вы можете увидеть в своих логах подобные сообщения:
Jul 12 15:32:11 worker-528 kernel: nf_conntrack: table full, dropping packet.
Параметр sysctl нужен для отображения максимального количества подключений. Вы можете узнать текущее значение с помощью следующей команды:
sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max = 131072
Чтобы установить новое значение, добавьте флаг –w:
sysctl -w net.netfilter.nf_conntrack_max=198000
Чтобы сделать значение постоянным, добавьте его в файл sysctl.conf:
. . .
net.ipv4.netfilter.ip_conntrack_max = 198000
Правила iptables
До версии 1.11 Kubernetes использовал iptables NAT для реализации виртуального IP-преобразования и балансировки нагрузки сервисов.
Чтобы сбросить все правила iptables на ноде, используйте команду iptables-save:
iptables-save
Вывод этой команды достаточно большой, потому его удобнее направить в файл (iptables-save > output.txt) или в less (iptables-save | less).
Чтобы отобразить только правила NAT сервиса Kubernetes, используйте команду iptables с флагом –L и укажите цепочку.
iptables -t nat -L KUBE-SERVICES
Chain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-SVC-TCOU7JCQXEZGVUNU udp -- anywhere 10.32.0.10 /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain
KUBE-SVC-ERIFXISQEP7F7OF4 tcp -- anywhere 10.32.0.10 /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:domain
KUBE-SVC-XGLOHA7QRQ3V22RZ tcp -- anywhere 10.32.226.209 /* kube-system/kubernetes-dashboard: cluster IP */ tcp dpt:https
. . .
Запрос DNS кластера
Одним из способов отладки разрешения DNS кластера является развертывание контейнера отладки со всеми необходимыми инструментами, а затем запуск nslookup с помощью kubectl. Это описано в официальной документации Kubernetes.
Другой способ запроса DNS-сервера кластера – использовать dig и nsenter на ноде. Если инструмент dig не установлен, его можно установить с помощью apt в дистрибутивах Linux на основе Debian:
apt install dnsutils
Сначала найдите IP-адрес сервиса kube-dns в кластере.
kubectl get service -n kube-system kube-dns
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
IP-адрес кластера выделен выше. Затем нужно использовать nsenter для запуска dig в пространстве имен контейнера.
nsenter -t 14346 -n dig kubernetes.default.svc.cluster.local @10.32.0.10
Эта команда dig выполняет поиск полного доменного имени Service-name.namespace.svc.cluster.local и указывает IP-адрес сервиса DNS кластера (@10.32.0.10).
Просмотр сведений о IPVS
Начиная с Kubernetes 1.11, kube-proxy может настраивать IPVS для преобразования виртуальных IP-адресов в IP-адреса подов. Вы можете запросить таблицу преобразования IP с помощью ipvsadm:
ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 100.64.0.1:443 rr
-> 178.128.226.86:443 Masq 1 0 0
TCP 100.64.0.10:53 rr
-> 100.96.1.3:53 Masq 1 0 0
-> 100.96.1.4:53 Masq 1 0 0
UDP 100.64.0.10:53 rr
-> 100.96.1.3:53 Masq 1 0 0
-> 100.96.1.4:53 Masq 1 0 0
Чтобы запросить преобразование IP конкретного сервиса, добавьте флаг –t и укажите этот IP-адрес.
ipvsadm -Ln -t 100.64.0.10:53
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 100.64.0.10:53 rr
-> 100.96.1.3:53 Masq 1 0 0
-> 100.96.1.4:53 Masq 1 0 0
Заключение
В этом мануале вы научились использовать некоторые команды и методы для изучения и проверки сведений сети кластера Kubernetes. Больше информации о Kubernetes можно найти в нашем Информатории и в официальной документацией Kubernetes.
Tags: Kubernetes