共用方式為


針對 Azure Kubernetes Service 節點上的 SNAT 埠耗盡進行疑難解答

本文可協助您尋找並針對體驗來源網路位址轉換 (SNAT) 埠耗盡的 Azure Kubernetes Service (AKS) 節點進行疑難解答。

注意

  • 若要針對執行 Kubernetes 作業之 AKS 叢集中 AKS 節點上的 SNAT 埠耗盡進行疑難解答,請只在 AKS 節點上主動執行作業時,才執行下列步驟。
  • 若要深入瞭解 SNAT 埠及其每個虛擬機的配置,請參閱 什麼是 SNAT 埠

步驟 1:找出體驗 SNAT 埠耗盡的節點

  1. 取得 AKS 節點的 IP 位址,該節點會從 Azure 入口網站 遇到作用中的 SNAT 連接埠耗盡。

    若要這樣做,請流覽至 Azure 入口網站 中的 AKS 叢集,然後選取 [診斷並解決連線問題 SNAT 連線和埠配置問題>>]。 [ SNAT 連線] 和 [埠配置 ] 索引標籤會顯示遇到 SNAT 連接埠耗盡之 AKS 節點的私人 IP 位址。

    [診斷和解決問題] 窗格的螢幕快照。

    [連線問題] 窗格的螢幕快照。

  2. 線上到您的 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 節點上的根使用者身分執行。
  1. 在遇到 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
    
  2. 使用 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
    
  3. 將先前的命令輸出寫入記錄檔,然後排序輸出以檢閱高連線清單:

    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
    
  4. 將IP位址與上一個輸出中最多連線的IP位址對應至Pod。 如果無法運作,您可以繼續。

  5. 請注意具有 SADDR 上一個輸出中最多連線的 或 NETNS 值,然後執行下列 lsns 命令,將它對應至 PID。 Lsns 是一種 Linux 工具,可列出命名空間,並將命名空間對應至 Linux 進程樹狀結構中的 PID。

    lsns -t net
    

    以下是命令輸出範例:

    NS         TYPE NPROCS PID   USER  COMMAND
    4026532785 net  3      19832 root  bash
    
  6. 使用 pstree 將先前的 PID 對應至容器化進程。 Pstree 是一種 Linux 工具,可列出樹狀結構格式的處理程式,以取得可讀性。

    pstree -aps 19832
    

    以下是命令輸出範例:

    systemd,1
      `-containerd-shim,20946 -namespace k8s.io -id 2xxxf...
    

    請注意命令輸出中容器 -id 的前五個字元。 它會用於步驟 7。

  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 識別碼。

  8. 取得節點上執行的所有 Pod,並使用先前的 POD 識別碼來比對命令輸出中具有高輸出連線的 Pod:

    kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=<nodename>
    

步驟 3:尋找應用程式建立的所有輸出網路連線

  1. 使用下列其中一個命令,在步驟 2執行識別為具有高輸出連線的 Pod:

    • kubectl exec -it <pod name> -n <namespace> /bin/bash
      
    • kubectl exec -it <pod name> -n <namespace> /bin/sh
      
  2. 執行下列命令,在 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
      
  3. 在 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 意見反應社群提交產品意見反應。