Kubernetes 是一个开源工具,在 容器编排 中至关重要。Kubernetes 有助于在各种云环境甚至本地服务器上大规模编排和管理集群。集群是一组用于运行容器化应用程序和服务的宿主机。一个集群至少需要两个节点才能工作 – 一个主节点和一个工作节点。您可以通过添加更多工作节点来扩展您的 Kubernetes 基础设施。主节点及其工作节点必须能够通过网络进行通信,基础设施才能正常工作。有关 Kubernetes 最重要功能的概述,请参考我们的教程:了解 Kubernetes.
在本教程中,我们将向您展示 几种有助于检查和排查 Kubernetes 网络故障的工具和技术。
前提条件
-
要学习本教程,您应该有一个 Kubernetes 集群。我们有一个教程解释了 如何在 Ubuntu 20.04 上安装和使用 Kubernetes,可以指导您完成用于演示的基础集群的搭建。
-
您还应该在本地安装 kubectl。根据您的本地环境,请遵循官方文档关于 安装 Kubernetes 工具 的说明。 kubectl 应该配置为连接到您的集群。我们将在下面的章节中进一步解释。
我们将在本地和 Kubernetes 节点上运行几个命令。让我们开始吧!
配置本地 kubectl 以连接到远程 Kubernetes 集群
让我们首先安装 kubectl。我们的本地环境运行的是 Ubuntu,如果您运行的是其他本地环境,请访问 此链接。要在使用 kubectl 工具的 Ubuntu/Debian 本地环境上,使用 apt 包管理器进行安装,请运行以下命令来更新 apt 软件源并安装必要的软件包:
|
1 2 |
sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl |
接下来,运行以下命令下载 Google 云端公开签名密钥:
|
1 |
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg |
然后,添加 Kubernetes apt 软件源:
|
1 |
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list |
之后,使用以下命令更新 apt 索引并安装 kubectl:
|
1 2 |
sudo apt-get update sudo apt-get install -y kubectl |
然后,通过使用以下命令检查版本来验证 kubectl 是否已安装:
|
1 |
kubectl version |
如果您刚刚在本地安装了 kubectl,输出如下:

在上面的截图中, kubectl 正在尝试连接 to 本地 Kubernetes 集群。但是,连接失败了,因为我们的本地机器上还没有运行 Kubernetes 集群。
要连接到远程 Kubernetes 集群,您首先需要从远程集群下载 Kubernetes 凭据。以下是从主节点复制凭据的命令:
|
1 |
scp -r hackins@178.22.66.253:/home/hackins/.kube . |
将突出显示的部分替换为您的 ssh 用户名和主节点的公网 IP。凭据下载完成后,将凭据复制到您的家目录:
|
1 |
cp -r .kube $HOME/ |
就这么简单。您的本地 kubectl 应该能够连接到您的远程 Kubernetes 集群并向其发出命令。要确认您的本地 kubectl 已连接到远程集群,请再次使用 version 命令进行检查:
|
1 |
kubectl version --output='json' |
以下是输出,显示连接成功:

(可选)您可以执行 get nodes 命令,如下所示:

获取 Pod 的 Cluster IP
您可以通过在本地计算机上运行 kubectl get pod 命令来获取 Pod 的 Cluster IP。要列出更多信息(例如托管 Pod 的节点以及 Pod 的 Cluster IP),请将标志 -o wide 添加到命令中:
|
1 |
kubectl get pod -o wide |
以下是我们的 Kubernetes 集群的输出。如您所见,在前提条件教程中,我们已经创建了一个 Nginx Web 服务器部署:

IP 列显示了单个 Pod 的内部 IP 地址。如果您寻找的 Pod 没有出现在列表中,您可能处于不同的命名空间中。您可以发出以下命令来列出所有 namespaces:
|
1 |
kubectl get pod -o wide --all-namespaces |
获取 Service 的 IP 地址
您还可以获取集群上 Service 的 IP 地址。通过添加 --all-namespaces 标志,您可以获取集群上运行的所有服务:
|
1 |
kubectl get service --all-namespaces |
上述命令的输出如下。Service IP 位于 cluster-ip 列中:

获取和访问 Pod 网络命名空间
每个 Kubernetes Pod 都分配有一个网络命名空间。网络命名空间(也称为 netns)是 Linux 中的原生网络库,用于提供网络设备之间的隔离。
要检查 DNS 解析或常规网络连接,您可以在 Pod 的网络命名空间内运行命令。为此,您首先需要查找 Pod 中某个容器的进程 ID。您可以在 Docker 中使用 Docker 特定的命令轻松完成此操作。第一个命令列出了节点上运行的容器。登录到您的一个工作节点并运行以下命令:
|
1 |
docker ps |

在输出中,我们关注的是容器 ID 或 Names(名称)列。请注意我们在前提条件教程中部署的 Nginx Nginx 容器 如何在 Ubuntu 20.04 上安装和使用 Kubernetes.
接下来,复制容器 ID 或名称,因为我们将在下一个命令中使用它来查找进程 ID:
|
1 |
docker inspect --format '{{ .State.Pid }}' container-id-或-name |
将突出显示的部分替换为您从上一个命令中复制的值。以下是我们得到的输出,即进程 ID:

现在我们有了进程 ID,可以使用它在进程的网络命名空间内运行 nsenter 命令:
|
1 |
sudo nsenter -t container-pid -n ip addr |
将突出显示的部分替换为您在上一个命令中获取的进程 ID。然后,在 ip addr 的位置,您可以输入任何您想在 Pod 的网络命名空间内运行的命令。如果遇到权限被拒绝的错误,您也可以使用 sudo 来运行它。
使用 nsenter 命令允许您运行节点上可用的更广泛的命令,相比之下,使用 docker exec 命令仅限制您使用容器内安装的命令。
检索 Pod 的虚拟以太网接口
Pod 上的网络命名空间通过虚拟以太网管道与节点的根 netns 进行通信。在节点端,此管道显示为一个名称以 veth 开头并以唯一标识符结尾的设备,例如 veth742f721 或 veth90。而在 Pod 内部,该管道标识为 eth0.
您可能想知道哪个 veth 设备与哪个 Pod 配对。您可以先列出节点上的所有网络设备,然后列出 Pod 网络中的所有设备。要识别哪个 veth 设备与特定 Pod 配对,您可以关联这两个列表之间的设备编号。
使用 nsenter 命令在 Pod 的网络命名空间中运行 ip addr 命令。您需要知道其中一个容器的进程 ID。为此,请参阅上一节关于 获取和访问 Pod 网络命名空间.
接下来,在工作节点的终端上执行以下命令,并相应地替换突出显示的部分:
|
1 |
sudo nsenter -t container-pid -n ip addr |
该命令输出 Pod 的接口列表:

注意 if7 字符,在 之后eth0@ (在上述输出中)。这意味着 Pod 的 eth0 与节点的第 7 个接口配对。接下来,通过运行 ip addr 命令列出节点默认命名空间内的接口:
|
1 |
ip addr |
该命令列出的接口如下所示:

在输出中,第 7 个接口是 veth254b50e6@if3 – 与我们正在测试的 Pod 配对的虚拟以太网管道。
审查 Iptables 规则
您可以执行命令 iptables-save 来列出节点上的所有 iptables:
|
1 |
iptables-save |
该命令的输出可能会很长,因此您可以将其保存到文件中以便稍后检查:
|
1 |
iptables-save > iptables.txt |
您也可以使用 less 对输出进行分页:
|
1 |
iptables-save | less |
由于我们只对 Kubernetes NAT 规则感兴趣,请添加 -L 标志来指定正确的目标:
|
1 |
sudo iptables -t nat -L KUBE-SERVICES |
以下是输出:

检查 IPVS 详情
Kube-proxy 是运行在 Kubernetes 集群中每个节点上的网络代理。它可用于配置 IPVS,以处理虚拟 Service IP 到 Pod IP 的转换。要列出 IP 转换表,您可以使用 ipvsadm 命令。首先,您需要在节点上安装它:
|
1 |
sudo apt install ipvsadm |
现在您可以执行以下命令:
|
1 |
sudo ipvsadm -Ln |
要显示单个 Service IP,请添加 -t 标志,并指定所需的 IP 地址:
|
1 |
ipvsadm -Ln -t 10.244.1.255 |
查询集群 DNS
有几种方法可以用来调试集群 DNS 解析。官方文档 描述的一种方法是部署一个包含所有必要工具的调试容器,然后使用 kubectl 来执行 nslookup.
或者,您也可以直接从节点本身使用 dig 和 nsenter 命令来查询 DNS。首先,您必须在主节点上安装 dig。对于 Ubuntu,请使用 apt 命令进行安装:
|
1 |
sudo apt install dnsutils |

返回本地机器上的终端,运行以下命令以查找 kube-dns 服务的集群 IP:
|
1 |
kubectl get service -n kube-system kube-dns |
该命令输出:

The cluster-ip 列包含我们需要的值。现在我们可以使用 nsenter 来在容器命名空间中运行 dig 。但是,您需要一个容器进程 ID 才能访问其命名空间。请参阅上面的 获取和访问 Pod 网络命名空间 部分以获取指导。
一旦您获得了 container-id,请在主节点上执行以下命令:
|
1 |
sudo nsenter -t 27168 -n dig kubernetes.default.svc.cluster.local @10.96.0.10 |
The dig 命令接收集群 DNS 服务的 IP( @10.96.0.10)并查找服务的完整域名 service-name.namespace.svc.cluster.local:

有关查找服务名称 and 命名空间的信息,请参阅 获取服务的 IP 地址.
审查 Conntrack 连接跟踪
您可以使用 conntrack 命令来查看当前正在跟踪的所有连接:
|
1 |
sudo conntrack -L |
它的输出类似于屏幕截图:

添加 -E 标志以持续监视传入的连接:
|
1 |
sudo conntrack -E |
要查看跟踪到特定目标地址的连接,请添加 -d 标志并指定目标地址:
|
1 |
sudo conntrack -L -d 80.45.6.4 |
有时连接跟踪表会被填满,导致新连接被丢弃。这会导致一些问题,阻止您的节点建立可靠的连接。如果发生这种情况,您将在系统日志的以下位置看到类似以下的信息: /var/log/syslog:
|
1 |
Mar 07 19:12:11 worker-105 kernel: nf_conntrack: 表 满, 丢弃 数据包. |
存在一个用于跟踪最大连接数的系统设置。使用以下命令列出您的当前值:
|
1 |
sysctl net.netfilter.nf_conntrack_max |
它输出:

您可以通过使用 -w 标志:
|
1 |
sudo sysctl -w net.netfilter.nf_conntrack_max=231074 |
您可能需要修改您的 /etc/sysctl.conf 文件以使该值永久生效,并确保其在重启后依然存在。使用 nano 打开该文件:
|
1 |
sudo nano /etc/sysctl.conf |
接下来,如果该行存在则修改其值,或者在文件末尾添加该行,并指定新值:
|
1 |
net.netfilter.nf_conntrack_max=231074 |
结论
在部署多个容器化服务时,您将从 Kubernetes 中获益匪浅,因为它为您提供了一个集中管理点。为了确保各个 Kubernetes Pod 之间的连通性,我们向您展示了一些网络检查命令,您可以使用这些命令来排查 Kubernetes 基础设施中的任何问题。
要了解更多关于 Kubernetes 及其优势、在 Kubernetes 上设置和部署应用程序的信息,请查看我们的各种 Kubernetes 教程.
祝您使用愉快!
评论
暂无评论。发表第一条评论吧。