Изучение сети 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: