如何检查 Kubernetes 网络

介绍

Kubernetes 是一个集装箱管制系统,可以在服务器节点的集群中管理集装箱应用程序.在集群中所有集装箱之间保持网络连接需要一些先进的网络技术。

如果您正在调试连接问题、调查网络输出问题或探索 Kubernetes 以了解其运作方式,这些工具可能很有用。

如果您想了解更多关于 Kubernetes 的一般情况,我们的指南 An Introduction to Kubernetes 涵盖了基本知识. 有关 Kubernetes 的网络具体概述,请阅读 Kubernetes Networking Under the Hood

如果您正在寻找一个管理的Kubernetes托管服务,请查看我们的简单的,用于增长的管理的Kubernetes服务(https://www.digitalocean.com/products/kubernetes)。

开始的

本教程将假设您有一个Kubernetes集群,在本地安装kubectl,并配置为连接到集群。

以下部分包含许多旨在在 Kubernetes 节点上运行的命令,它们将看起来像这样:

1echo 'this is a node command'

应该在本地机器上运行的命令将看起来如下:

1[environment local]
2echo 'this is a local command'

<$>[注] **注:**本教程中的大多数命令都需要作为 root用户运行。如果您在您的 Kubernetes 节点上使用 sudo 允许的用户,请在需要时添加sudo以运行命令。

寻找一个Pod的集群IP

要查找 Kubernetes pod 的集群 IP 地址,请在本地机器上使用kubectl get pod命令,并选择-o wide

1[environment local]
2kubectl get pod -o wide
1[environment local]
2[secondary_label Output]
3NAME READY STATUS RESTARTS AGE IP NODE
4hello-world-5b446dd74b-7c7pk 1/1 Running 0 22m 10.244.18.4 node-one
5hello-world-5b446dd74b-pxtzt 1/1 Running 0 22m 10.244.3.4 node-two

IP 列将包含每个 pod 的内部集群 IP 地址。

如果你看不到你正在寻找的pod,请确保你在正确的名称空间. 您可以通过添加旗帜 --all-namespaces 列出所有名称空间中的pods。

查找服务的IP

我們也可以使用「kubectl」找到服務的IP,在這種情況下,我們會列出所有服務的名稱空間:

1[environment local]
2kubectl get service --all-namespaces
1[environment local]
2[secondary_label Output]
3NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)         AGE
4default kubernetes ClusterIP 10.32.0.1       <none>        443/TCP 6d
5kube-system csi-attacher-doplugin ClusterIP 10.32.159.128   <none>        12345/TCP 6d
6kube-system csi-provisioner-doplugin ClusterIP 10.32.61.61     <none>        12345/TCP 6d
7kube-system kube-dns ClusterIP 10.32.0.10      <none>        53/UDP,53/TCP 6d
8kube-system kubernetes-dashboard ClusterIP 10.32.226.209   <none>        443/TCP 6d

服务 IP 可以在 ** CLUSTER-IP** 列中找到。

查找和输入Pod网络命名空间

每个Kubernetes pod都被分配到自己的网络名称空间,网络名称空间(或netns)是Linux网络原始,提供网络设备之间的隔离。

运行指令从一个pod的网络中,检查DNS分辨率或一般网络连接可能是有用的。 要做到这一点,我们首先需要查找一个pod中的一个集装箱的过程ID。

1docker ps
1[secondary_label Output]
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3173ee46a3926 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
411ad51cb72df 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
5. . .

在您感兴趣的pod中找到任何容器的 container IDname

*第一个容器是hello-world应用程序,运行在hello-worldpod *第二个是运行在hello-worldpod中的 _pause_容器。

要获取任何一个容器的进程 ID,请注意容器 ID 或名称,并在以下docker命令中使用它:

1docker inspect --format '{{ .State.Pid }}' container-id-or-name
1[secondary_label Output]
214552

一个进程ID(或PID)将是输出,现在我们可以使用nsenter程序在该进程的网络名空间中运行命令:

1nsenter -t your-container-pid -n ip addr

请确保使用自己的PID,并用您希望在pod的网络名称空间内运行的命令代替ip addr

<$>[注] **注:**使用nsenter在pod的命名空间中运行命令的一个优点,而不是使用docker exec这样的东西,是您可以访问节点上可用的所有命令,而不是通常在容器中安装的有限的命令集。

寻找一个Pod的虚拟以太网接口

每个pod的网络名称空间通过虚拟以太网管道与节点的根网进行通信. 在节点侧,这个管道通常以veth开始,并以veth77f2275veth01等独特标识符结束。

要做到这一点,我们将列出节点上的所有网络设备,然后列出节点的网络名称空间中的设备。

首先,请使用nsenter在pod的网络名称空间中运行ip addr。请参阅上一节(#finding-and-entering-pod-network-namespaces)以获取有关如何执行的详细信息:

1nsenter -t your-container-pid -n ip addr
1[secondary_label Output]
21: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
3    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4    inet 127.0.0.1/8 scope host lo
5       valid_lft forever preferred_lft forever
610: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
7    link/ether 02:42:0a:f4:03:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
8    inet 10.244.3.4/24 brd 10.244.3.255 scope global eth0
9       valid_lft forever preferred_lft forever

该命令将输出一个pod的界面列表。在示例输出中记住eth0@之后的if11号码,这意味着这个pod的eth0链接到节点的第11个界面,现在在节点的默认名称空间中运行ip addr,列出其界面:

1ip addr
 1[secondary_label Output]
 21: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
 3    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 4    inet 127.0.0.1/8 scope host lo
 5       valid_lft forever preferred_lft forever
 6    inet6 ::1/128 scope host
 7       valid_lft forever preferred_lft forever
 8
 9. . .
10
117: veth77f2275@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master docker0 state UP group default
12    link/ether 26:05:99:58:0d:b9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
13    inet6 fe80::2405:99ff:fe58:db9/64 scope link
14       valid_lft forever preferred_lft forever
159: vethd36cef3@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master docker0 state UP group default
16    link/ether ae:05:21:a2:9a:2b brd ff:ff:ff:ff:ff:ff link-netnsid 1
17    inet6 fe80::ac05:21ff:fea2:9a2b/64 scope link
18       valid_lft forever preferred_lft forever
1911: veth4f7342d@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master docker0 state UP group default
20    link/ether e6:4d:7b:6f:56:4c brd ff:ff:ff:ff:ff:ff link-netnsid 2
21    inet6 fe80::e44d:7bff:fe6f:564c/64 scope link
22       valid_lft forever preferred_lft forever

在本示例输出中,第11个接口是veth4f7342d,这是我们正在调查的虚拟以太网管道。

检查Conntrack连接跟踪

在版本 1.11 之前,Kubernetes 使用 iptables NAT 和 conntrack 内核模块来跟踪连接。

1conntrack -L

若要连续查看新连接,请使用-E旗:

1conntrack -E

若要列出跟踪到特定目的地地址的连接,请使用-d旗:

1conntrack -L -d 10.32.0.1

如果您的节点出现了与服务进行可靠连接的问题,则您的连接跟踪表可能已经满了,并且新连接正在被丢弃。

1[label /var/log/syslog]
2Jul 12 15:32:11 worker-528 kernel: nf_conntrack: table full, dropping packet.

有一个 sysctl 设置,用于追踪的连接的最大数目. 您可以使用以下命令列出当前值:

1sysctl net.netfilter.nf_conntrack_max
1[secondary_label Output]
2net.netfilter.nf_conntrack_max = 131072

要设置新的值,请使用w旗:

1sysctl -w net.netfilter.nf_conntrack_max=198000

要将此设置永久化,请将其添加到 sysctl.conf 文件中:

1[label /etc/sysctl.conf]
2. . .
3net.ipv4.netfilter.ip_conntrack_max = 198000

检查可行的规则

在版本 1.11 之前,Kubernetes 使用 iptables NAT 来实现服务 IP 的虚拟 IP 翻译和负载平衡。

要将所有 iptables 规则投放到一个节点上,请使用iptables-save命令:

1iptables-save

由于输出可能很长,所以你可能要管到一个文件(iptables-save > output.txt)或一个页面(iptables-savewyan less)以更容易地查看规则。

若要仅列出 Kubernetes 服务 NAT 规则,请使用iptables命令和-L标志来指定正确的链条:

1iptables -t nat -L KUBE-SERVICES
1[secondary_label Output]
2Chain KUBE-SERVICES (2 references)
3target prot opt source destination
4KUBE-SVC-TCOU7JCQXEZGVUNU udp  --  anywhere 10.32.0.10           /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain
5KUBE-SVC-ERIFXISQEP7F7OF4 tcp  --  anywhere 10.32.0.10           /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:domain
6KUBE-SVC-XGLOHA7QRQ3V22RZ tcp  --  anywhere 10.32.226.209        /* kube-system/kubernetes-dashboard: cluster IP */ tcp dpt:https
7. . .

寻找集群DNS

调试您的集群DNS分辨率的一种方法是部署一个调试容器,配备您所需的所有工具,然后使用kubectl对其执行nslookup

查询集群DNS的另一种方法是使用从节点的dignsenter。如果dig没有安装,则可以在基于Debian的Linux发行版上安装apt:

1apt install dnsutils

首先,找到 kube-dns 服务的集群 IP:

1[environment local]
2kubectl get service -n kube-system kube-dns
1[environment local]
2[secondary_label Output]
3NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)         AGE
4kube-dns ClusterIP 10.32.0.10   <none>        53/UDP,53/TCP 15d

下面我们将使用nsenter在一个集装箱的名称空间中运行挖掘。 请参阅 Finding and Entering Pod Network Namespaces部分,以获取有关更多信息:

1nsenter -t 14346 -n dig kubernetes.default.svc.cluster.local @10.32.0.10

扫描命令查看服务的完整域名 service-name.namespace.svc.cluster.local,并指定集群 DNS 服务 IP(`@10.32.0.10)的 IP。

查看IPVS细节

从 Kubernetes 1.11 开始,‘kube-proxy’ 可以配置 IPVS 来处理虚拟服务 IP 转换为 pod IP。

1ipvsadm -Ln
 1[secondary_label Output]
 2IP Virtual Server version 1.2.1 (size=4096)
 3Prot LocalAddress:Port Scheduler Flags
 4  -> RemoteAddress:Port Forward Weight ActiveConn InActConn
 5TCP 100.64.0.1:443 rr
 6  -> 178.128.226.86:443 Masq 1 0 0
 7TCP 100.64.0.10:53 rr
 8  -> 100.96.1.3:53 Masq 1 0 0
 9  -> 100.96.1.4:53 Masq 1 0 0
10UDP 100.64.0.10:53 rr
11  -> 100.96.1.3:53 Masq 1 0 0
12  -> 100.96.1.4:53 Masq 1 0 0

若要显示单个服务 IP,请使用-t选项并指定所需的 IP:

1ipvsadm -Ln -t 100.64.0.10:53
1[secondary_label Output]
2Prot LocalAddress:Port Scheduler Flags
3  -> RemoteAddress:Port Forward Weight ActiveConn InActConn
4TCP 100.64.0.10:53 rr
5  -> 100.96.1.3:53 Masq 1 0 0
6  -> 100.96.1.4:53 Masq 1 0 0

结论

在本文中,我们已经审查了探索和检查您的Kubernetes集群网络的详细信息的一些命令和技术。 有关Kubernetes的更多信息,请参阅 我们的Kubernetes教程标签官方Kubernetes文档

Published At
Categories with 技术
comments powered by Disqus