Table of Contents
Введение
Kubernetes — это система организации контейнеров, способная управлять контейнерными приложениями в кластере серверных узлов. Для обеспечения доступа к сети для всех контейнеров в кластере требуются сложные схемы сетевых подключений. В этой статье мы кратко расскажем о некоторых инструментах и методиках для проверки используемой схемы сетевых подключений.
Эти инструменты могут быть полезны для отладки проблем со связью, расследования проблем с пропускной способностью сети или изучения принципов работы Kubernetes.
Если вы хотите узнать больше о Kubernetes, вам поможет наше руководство _«Введение в Kubernetes»_. Для обзора сетевых возможностей Kubernetes прочитайте статью _«Сети в Kubernetes: под капотом»_.
Начало работы
В этом обучающем модуле предполагается, что у вас имеется кластер Kubernetes с установленным локальным компонентом kubectl, настроенным для подключения к кластеру.
В следующих разделах содержатся различные команды, которые предполагается выполнять на узлах Kubernetes. Они выглядят примерно так:
echo 'this is a node command'
Команды для выполнения на локальном компьютере будут выглядеть так:
[environment local]
echo 'this is a local command'
Примечание. Большнство команд в этом обучающем модуле должно выполняться от имени пользователя root Если вы используете пользователя с привилегиями sudo на узлах Kubernetes, добавьте sudo для запуска команд, когда это требуется.
Поиск IP-адреса кластера пода
Чтобы найти IP-адрес кластера пода Kubernetes, запустите на локальном компьютере команду kubectl get pod с опцией -o wide. Эта опция выводит больше информации, включая узел размещения пода и IP-адрес кластера пода.
[environment local]
kubectl get pod -o wide
[environment local]
[secondary_label Output]
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-адреса службы
С помощью команды kubectl также можно определить IP-адрес службы. В данном случае мы выводим список всех служб во всех пространствах имен:
[environment local]
kubectl get service --all-namespaces
[environment local]
[secondary_label Output]
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 или общей работоспособности сети. Для этого нужно предварительно посмотреть идентификатор процесса одного из контейнеров в поде. Для Docker мы можем сделать это с помощью серии из двух команд. Вначала выведите список контейнеров, запущенных на узле:
docker ps
[secondary_label Output]
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
. . .
Найдите идентификатор контейнера или имя любого контейнера в поде, который вас интересует. В показанных выше результатах отображается два контейнера:
- Первый контейнер — это приложение
hello-world, запущенное в подеhello-world
- Второй — это контейнер _pause_, запущенный в поде
hello-world. Этот контейнер используется исключительно для захвата сетевого пространства имен пода
Чтобы получить идентификатор процесса любого из контейнеров, запишите идентификатор контейнера или имя и используйте его в следующей команде docker:
docker inspect --format '{{ .State.Pid }}' <^>container-id-or-name<^>
[secondary_label Output]
<^>14552<^>
Будет выведен идентификатор процесса (или PID). Теперь мы можем использовать программу nsenter для запуска команды в сетевом пространстве имен этого процесса:
nsenter -t <^>your-container-pid<^> -n <^>ip addr<^>
Обязательно используйте собственный PID и замените ip addr командой, которую вы хотите запустить в сетевом пространстве имен пода.
Примечание. Использование nsenter для запуска команд в пространстве имен пода дает преимущества по сравнению с такими программами как docker exec. Это преимущество заключается в том, что у вас имеется доступ ко всем командам, поддерживаемым узлом, а не только к ограниченному набору команд, установленному в контейнерах.
Поиск интерфейса виртуальной сети Ethernet пода
Каждое пространство имен пода взаимодействует с пространством root netns через виртуальный конвейер ethernet. Со стороны узла этот конвейер выглядит как устройство, которое обычно начинается с veth и заканчивается уникальным идентификатором, например veth77f2275 или veth01. Внутри пода этот конвейер выглядит как eth0.
Его можно использовать для корреляции устройств veth, сопряженных с конкретными подами. Для этого мы выводим список всех сетевых устройств в узле, а затем выводим список устройств в сетевом пространстве имен пода. Для получения связи мы можем провести корреляцию номеров устройств в двух списках.
Запустите команду ip addr в сетевом пространстве имен пода, используя nsenter. Более подробную информацию об этом можно найти в предыдущем разделе [_«Поиск и ввод пространств имен подов»_](#finding-and-entering-pod-network-namespaces):
nsenter -t <^>your-container-pid<^> -n ip addr
[secondary_label Output]
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
[secondary_label Output]
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 для отслеживания соединений использовались таблицы NAT iptables и модуль ядра conntrack. Для вывода списка всех отслеживаемых соединений используйте команду conntrack:
conntrack -L
Чтобы постоянно отслеживать новые соединения, используйте флаг -E:
conntrack -E
Чтобы вывести отслеживаемые conntrack соединения на определенный адрес назначения, используйте флаг -d:
conntrack -L -d <^>10.32.0.1<^>
Если у ваших узлов возникают проблемы с установлением надежных соединений со службами, это может означать, что ваша таблица отслеживания подключений полная, и что новые соединения отбрасываются. В этом случае вы можете увидеть в системных журналах сообщения следующего вида:
[label /var/log/syslog]
Jul 12 15:32:11 worker-528 kernel: <^>nf_conntrack: table full, dropping packet.<^>
Это настройка sysctl для отслеживания максимального количества соединений. Вы можете вывести список текущих значений с помощью следующей команды:
sysctl net.netfilter.nf_conntrack_max
[secondary_label Output]
net.netfilter.nf_conntrack_max = 131072
Используйте флаг -w для установки нового значения:
sysctl -w net.netfilter.nf_conntrack_max=<^>198000<^>
Чтобы сделать этот параметр постоянным. добавьте его в файл sysctl.conf:
[label /etc/sysctl.conf]
. . .
<^>net.ipv4.netfilter.ip_conntrack_max = 198000<^>
Проверка правил таблиц Iptables
До выпуска версии 1.11 в Kubernetes использовались таблицы NAT iptables для преобразования виртуальных IP-адресов и балансировки нагрузки служебных IP-адресов.
Чтобы сохранить все правила таблиц iptables на узле, используйте команду iptables-save:
iptables-save
Поскольку результаты могут быть длинными, вы можете отправить результаты через конвейер в файл (iptables-save > output.txt) или на пейджер (iptables-save | less) для большего удобства просмотра.
Чтобы вывести только правила NATдля службы Kubernetes, используйте команду iptables и флаг -L для указания правильной цепочки:
iptables -t nat -L KUBE-SERVICES
[secondary_label Output]
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 кластера заключается в развертывании контейнера отладки с помощью всех необходимых инструментов и использование kubectl для выполнения команды nslookup. Это описывается в официальной документации по Kubernetes.
Еще один способ запроса DNS кластера заключается в том, чтобы использовать dig и nsenter с узла. Если dig не установлен, его можно установить с помощью apt в дистрибутивах Linux на базе Debian:
apt install dnsutils
Вначале найдите IP-адрес кластера службы kube-dns:
[environment local]
kubectl get service -n kube-system kube-dns
[environment local]
[secondary_label Output]
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP <^>10.32.0.10<^> <none> 53/UDP,53/TCP 15d
IP-адрес кластера подсвечен выше. Теперь мы используем nsenter для запуска dig в пространстве имен контейнера. Дополнительную информацию об этом можно найти в разделе [_«Поиск и ввод сетевых пространств имен подов»_](#finding-and-entering-pod-network-namespaces):
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
[secondary_label Output]
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<^>
[secondary_label Output]
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 и официальной документации по Kubernetes.