Вступление
Kubernetes - это система управления контейнером, которая может управлять контейнеризованными приложениями в кластере узлов сервера. Поддержание сетевого подключения между всеми контейнерами в кластере требует некоторых передовых сетевых методов. В этой статье мы кратко рассмотрим некоторые инструменты и методы для проверки этой сетевой установки.
Эти инструменты могут быть полезны, если вы отлаживаете проблемы с подключением, исследуете проблемы с пропускной способностью сети или изучаете Kubernetes, чтобы узнать, как она работает.
Если вы хотите узнать больше о Kubernetes в целом, наше руководствоAn Introduction to Kubernetes охватывает основы. Для обзора Kubernetes, специфичного для сетей, прочтитеKubernetes Networking Under the Hood.
Начиная
В этом руководстве предполагается, что у вас есть кластер Kubernetes, гдеkubectl
установлен локально и настроен для подключения к кластеру.
В следующих разделах содержится много команд, предназначенных для запуска на узле Kubernetes. Они будут выглядеть так:
echo 'this is a node command'
Команды, которые должны выполняться на вашем локальном компьютере, будут иметь следующий вид:
echo 'this is a local command'
[.note] #Note: Большинство команд в этом руководстве нужно будет запускать от имени пользователяroot. Если вместо этого вы используете пользователя с поддержкой sudo на своих узлах Kubernetes, добавьтеsudo
для запуска команд при необходимости.
#
Поиск IP-адреса кластера модуля
Чтобы узнать IP-адрес кластера модуля Kubernetes, используйте командуkubectl get pod
на локальном компьютере с опцией-o wide
. Эта опция выведет дополнительную информацию, включая узел, на котором находится модуль, и IP-адрес кластера модуля.
kubectl get pod -o wide
OutputNAME 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
OutputNAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.32.0.1 443/TCP 6d
kube-system csi-attacher-doplugin ClusterIP 10.32.159.128 12345/TCP 6d
kube-system csi-provisioner-doplugin ClusterIP 10.32.61.61 12345/TCP 6d
kube-system kube-dns ClusterIP 10.32.0.10 53/UDP,53/TCP 6d
kube-system kubernetes-dashboard ClusterIP 10.32.226.209 443/TCP 6d
IP-адрес службы можно найти в столбцеCLUSTER-IP.
Поиск и вход в пространства имен сети Pod
Каждому модулю Kubernetes назначается свое собственное пространство имен сети. Сетевые пространства имен (или netns) - это сетевой примитив Linux, обеспечивающий изоляцию между сетевыми устройствами.
Может быть полезно запускать команды из сети модуля, чтобы проверить разрешение DNS или общее сетевое подключение. Для этого сначала нужно найти идентификатор процесса одного из контейнеров в модуле. Для Docker мы можем сделать это с помощью серии из двух команд. Сначала перечислите контейнеры, работающие на узле:
docker ps
OutputCONTAINER 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
. . .
Найдитеcontainer ID илиname любого контейнера в интересующем вас модуле. В приведенном выше выводе мы показываем два контейнера:
-
Первый контейнер - это приложение
hello-world
, работающее в модулеhello-world
. -
Второй - контейнерpause, работающий в модуле
hello-world
. Этот контейнер существует исключительно для хранения в пространстве имен сети модуля
Чтобы получить идентификатор процесса любого контейнера, запишите идентификатор или имя контейнера и используйте его в следующей командеdocker
:
docker inspect --format '{{ .State.Pid }}' container-id-or-name
Output14552
Идентификатор процесса (или PID) будет выведен. Теперь мы можем использовать программуnsenter
для выполнения команды в сетевом пространстве имен этого процесса:
nsenter -t your-container-pid -n ip addr
Обязательно используйте свой собственный PID и заменитеip addr
на команду, которую вы хотите запустить в пространстве имен сети модуля.
[.note] #Note: Одно из преимуществ использованияnsenter
для запуска команд в пространстве имён модуля - по сравнению с использованием чего-то вродеdocker exec
- заключается в том, что у вас есть доступ ко всем командам, доступным на node вместо обычно ограниченного набора команд, установленных в контейнерах.
#
Поиск виртуального интерфейса Ethernet модуля
Сетевое пространство имен каждого модуля связывается с корневыми сетями узла через виртуальный канал Ethernet. На стороне узла этот канал выглядит как устройство, которое обычно начинается сveth
и заканчивается уникальным идентификатором, напримерveth77f2275
илиveth01
. Внутри модуля эта труба отображается какeth0
.
Может быть полезно сопоставить, какое устройствоveth
сопряжено с конкретным модулем. Для этого мы перечислим все сетевые устройства на узле, а затем перечислим устройства в сетевом пространстве имен модуля. Затем мы можем сопоставить номера устройств между двумя списками, чтобы установить соединение.
Сначала запуститеip addr
в пространстве имен сети модуля, используяnsenter
. Обратитесь к предыдущему разделуFinding and Entering Pod Network Namespaces
для получения подробной информации о том, как это сделать:
nsenter -t your-container-pid -n ip addr
Output1: lo: 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: 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
Output1: lo: 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: 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: 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: 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
Чтобы постоянно следить за новыми подключениями, используйте флаг-E
:
conntrack -E
Чтобы перечислить отслеживаемые conntrack соединения с конкретным адресом назначения, используйте флаг-d
:
conntrack -L -d 10.32.0.1
Если у ваших узлов возникают проблемы с установлением надежных подключений к службам, возможно, таблица отслеживания подключений заполнена и новые подключения сбрасываются. В этом случае вы можете увидеть сообщения, подобные следующим в журналах вашей системы:
/var/log/syslog
Jul 12 15:32:11 worker-528 kernel: nf_conntrack: table full, dropping packet.
Существует настройка sysctl для максимального количества отслеживаемых соединений. Вы можете перечислить ваше текущее значение с помощью следующей команды:
sysctl net.netfilter.nf_conntrack_max
Outputnet.netfilter.nf_conntrack_max = 131072
Чтобы установить новое значение, используйте флаг-w
:
sysctl -w net.netfilter.nf_conntrack_max=198000
Чтобы сделать этот параметр постоянным, добавьте его в файлsysctl.conf
:
/etc/sysctl.conf
. . .
net.ipv4.netfilter.ip_conntrack_max = 198000
Проверка правил Iptables
До версии 1.11 Kubernetes использовал iptables NAT для реализации виртуального преобразования IP-адресов и балансировки нагрузки для служебных IP-адресов.
Чтобы сбросить все правила iptables на узел, используйте командуiptables-save
:
iptables-save
Поскольку вывод может быть длинным, вы можете передать по конвейеру файл (iptables-save > output.txt
) или пейджер (iptables-save | less
), чтобы упростить просмотр правил.
Чтобы перечислить только правила NAT службы Kubernetes, используйте командуiptables
и флаг-L
, чтобы указать правильную цепочку:
iptables -t nat -L KUBE-SERVICES
OutputChain 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
. Это описано вthe official Kubernetes documentation.
Другой способ запросить DNS кластера - использоватьdig
иnsenter
с узла. Еслиdig
не установлен, его можно установить с помощьюapt
в дистрибутивах Linux на основе Debian:
apt install dnsutils
Сначала найдите IP-адрес кластера службыkube-dns:
kubectl get service -n kube-system kube-dns
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.32.0.10 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
OutputIP 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
OutputProt 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 см. Вour Kubernetes tutorials tag иthe official Kubernetes documentation.