排查 Azure Kubernetes 服务 节点上的 SNAT 端口耗尽问题
本文可帮助你查找并排查遇到源网络地址转换(SNAT)端口耗尽的Azure Kubernetes 服务(AKS)节点的问题。
注意
- 若要对运行 Kubernetes 作业的 AKS 群集中的 AKS 节点上的 SNAT 端口耗尽进行故障排除,请仅在作业在 AKS 节点上主动运行时执行以下步骤。
- 若要详细了解 SNAT 端口及其每个虚拟机的分配,请参阅 什么是 SNAT 端口。
步骤 1:找到遇到 SNAT 端口耗尽的节点
获取 AKS 节点的 IP 地址,该节点在Azure 门户中遇到活动 SNAT 端口耗尽。
为此,请导航到Azure 门户中的 AKS 群集,然后选择“诊断并解决连接问题 SNAT 连接和端口分配问题>>”。 SNAT 连接和端口分配 选项卡显示体验 SNAT 端口耗尽的 AKS 节点的专用 IP 地址。
连接到 AKS 群集并使用节点 IP 地址通过
kubectl
运行以下命令获取节点名称:kubectl get nodes -o wide | grep <node IP>
步骤 2:找到具有高出站连接的 Linux Pod
注意
- Tcptracer 是 Linux 节点上预安装的 BPF 编译器集合 (BCC) 工具之一。 它允许跟踪 TCP 建立的连接(
connect()
accept()
和close()
)。 可以使用它从 Pod 的源 IP 地址和网络命名空间(netns)查找高出站连接。 - 若要访问 BCC 工具,请仅使用 kubectl node-shell。
- 本部分中的所有命令都作为已安装 BCC 工具的 Linux 节点上的根用户运行。
在遇到 SNAT 端口耗尽的 Linux 节点上,安装 kubectl node-shell:
curl -LO https://github.com/kvaps/kubectl-node-shell/raw/master/kubectl-node_shell chmod +x ./kubectl-node_shell sudo mv ./kubectl-node_shell /usr/local/bin/kubectl-node_shell
使用 SSH 连接到体验 SNAT 端口耗尽的节点,并用于
tcptracer
跟踪 TCP 建立的连接:kubectl node-shell <node name> cd /usr/share/bcc/tools /usr/share/bcc/tools# python3 tcptracer -t4v
下面是命令输出示例:
Tracing TCP established connections. Ctrl-C to end. TIME(ns) TYPE PID COMM IP SADDR DADDR SPORT DPORT NETNS 0 connect 18627 curl 4 1.2.3.4 5.6.7.8 53746 80 4026532785 3xxx9 close 18627 curl 4 1.2.3.4 5.6.7.8 53746 80 4026532785 1xxxx4 connect 18629 curl 4 1.2.3.4 9.10.11.12 35686 80 4026532785 2xxxx9 close 18629 curl 4 1.2.3.4 9.10.11.12 35686 80 4026532785 4xxxx5 connect 18631 curl 4 1.2.3.4 9.10.11.12 35688 80 4026532785 4xxxx8 close 18631 curl 4 1.2.3.4 9.10.11.12 35688 80 4026532785 7xxxx3 connect 18633 curl 4 1.2.3.4 13.14.15.16 35690 80 4026532785 9xxxx7 close 18633 curl 4 1.2.3.4 13.14.15.16 35690 80 4026532785
将上一个命令输出写入日志文件,然后对输出进行排序,以查看高连接列表:
python3 tcptracer -t4v > log head -n +2 log | tail -n 1 | awk '{print "Count",$6,$10}'; awk '{print $6,$10}' log | sort | uniq -c | sort -nrk 1 | column -t
下面是命令输出示例:
Count SADDR NETNS 387 1.2.3.4 4026532785 8 11.22.33.44 4026532184 8 55.66.77.88 4026531992
将具有上一个输出中最多连接的 IP 地址映射到 Pod。 如果不起作用,可以继续操作。
SADDR
请注意具有上一个输出中大多数连接的或NETNS
值,然后运行以下 lsns 命令将其映射到 PID。 Lsns 是一种 Linux 工具,用于列出命名空间并将命名空间映射到 Linux 进程树中的 PID。lsns -t net
下面是命令输出示例:
NS TYPE NPROCS PID USER COMMAND 4026532785 net 3 19832 root bash
使用 pstree 将以前的 PID 映射到容器进程。 Pstree 是一种 Linux 工具,它以树格式列出进程以便可读性。
pstree -aps 19832
下面是命令输出示例:
systemd,1 `-containerd-shim,20946 -namespace k8s.io -id 2xxxf...
请注意命令输出中容器
-id
的前五个字符。 它将在步骤 7 中使用。使用 crictl 将以前的容器
-id
值映射到 POD ID。 Crictl 为与 CRI 兼容的容器运行时提供 CLI。crictl ps -a
下面是命令输出示例:
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD 6b5xxxxb fbxxxxx1 6 hours ago Running ubuntu 0 2xxxxxxxxf nginx
使用上一容器
-id
值的前五个字符来匹配 POD ID。获取节点上运行的所有 Pod,并使用以前的 POD ID 来匹配命令输出中具有高出站连接的 Pod:
kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=<nodename>
步骤 3:查找应用程序建立的所有出站网络连接
使用以下命令之一,执行到在步骤 2 中标识为具有高出站连接的 Pod:
-
kubectl exec -it <pod name> -n <namespace> /bin/bash
-
kubectl exec -it <pod name> -n <namespace> /bin/sh
-
运行以下命令,在 Pod 中安装 netstat 命令行工具。 Netstat 是仅限管理员的网络故障排除工具。
在 Debian、Ubuntu 或 Linux Mint 上
apt update apt install net-tools
在 RHEL、CentOS、Fedora、AlmaLinux 或 Rocky Linux 上
yum update yum install net-tools
在 Gentoo Linux 上
emerge -a sys-apps/net-tools
在 Alpine Linux 上
apk add net-tools
在 Arch Linux 上
pacman -S net-tools
在 OpenSUSE 上
zypper install net-tools
在 Pod 中安装 netstat 后,运行以下命令:
netstat -ptn | grep -i established
下面是命令输出示例:
tcp 0 0 10.x.x.x:xxxx 20.x.x.x:443 ESTABLISHED xxxxx3/telnet
在命令输出中,本地地址是 Pod 的 IP 地址,外地址是应用程序连接到的 IP。 状态中的 ESTABLISHED
公共 IP 连接是使用 SNAT 的连接。 确保仅对状态中的 ESTABLISHED
公共 IP 地址的连接进行计数,并忽略状态中 ESTABLISHED
与专用 IP 地址的任何连接。
对节点上运行的其他所有 Pod 重复本部分中的步骤。 与公共 IP 地址建立最多连接的 ESTABLISHED
Pod 托管导致节点上 SNAT 端口耗尽的应用程序。 与应用程序开发人员协作,使用设计连接高效应用程序中所述的建议优化应用程序以提高网络性能。 实施建议后,请验证是否看到较少的 SNAT 端口耗尽。
联系我们寻求帮助
如果你有任何疑问或需要帮助,请创建支持请求或联系 Azure 社区支持。 你还可以将产品反馈提交到 Azure 反馈社区。