針對 Azure Kubernetes Service 節點上的 SNAT 埠耗盡進行疑難解答
本文可協助您尋找並針對體驗來源網路位址轉換 (SNAT) 埠耗盡的 Azure Kubernetes Service (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 節點殼層。
- 本節中的所有命令都會以已安裝 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位址與上一個輸出中最多連線的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標識碼。 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 識別碼。取得節點上執行的所有 Pod,並使用先前的 POD 識別碼來比對命令輸出中具有高輸出連線的 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 重複本節中的步驟。 狀態中連線最多 ESTABLISHED
且公用IP位址的Pod裝載導致節點上 SNAT 埠耗盡的應用程式。 請與應用程式開發人員合作,使用設計有效率的應用程式中所述的建議來調整應用程式,以改善網路效能。 實作建議之後,請確認您看到較少的 SNAT 埠耗盡。
與我們連絡,以取得說明
如果您有問題或需要相關協助,請建立支援要求,或詢問 Azure community 支援。 您也可以向 Azure 意見反應社群提交產品意見反應。