介绍
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 ID或 name。
*第一个容器是hello-world
应用程序,运行在hello-world
pod
*第二个是运行在hello-world
pod中的 _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
开始,并以veth77f2275
或veth01
等独特标识符结束。
要做到这一点,我们将列出节点上的所有网络设备,然后列出节点的网络名称空间中的设备。
首先,请使用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的另一种方法是使用从节点的dig
和nsenter
。如果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文档。