Azure Kubernetes Service ノードでの SNAT ポート不足のトラブルシューティング

この記事は、ソース ネットワーク アドレス変換 (SNAT) ポート不足が発生する Azure Kubernetes Service (AKS) ノードを見つけてトラブルシューティングするのに役立ちます。

Note

手順 1: SNAT ポートの枯渇が発生しているノードを見つける

  1. Azure portal からアクティブな SNAT ポート枯渇が発生する AKS ノードの IP アドレスを取得します。

    これを行うには、Azure portal で AKS クラスターに移動し、 Diagnose と解決の問題>接続の問題>SNAT 接続とポートの割り当てを選択します。 SNAT 接続と [ポートの割り当て] タブには、SNAT ポート不足が発生している AKS ノードのプライベート IP アドレスが表示されます。

    [問題の診断と解決] ウィンドウのスクリーンショット。

    [接続の問題] ウィンドウのスクリーンショット。

  2. 次の kubectl コマンドを実行して、AKS クラスターに接続し、ノード IP アドレスを使用してノード名を取得します。

    kubectl get nodes -o wide | grep <node IP>
    

手順 2: 送信接続が多い Linux ポッドを見つける

Note

  • Tcptracer は、Linux ノードにプレインストールされている BPF コンパイラ コレクション (BCC) ツール の 1 つです。 これにより、TCP 確立された接続 (connect()accept()、および close()) をトレースできます。 これを使用して、ポッドの送信元 IP アドレスとネットワーク名前空間 (netns) からの高い送信接続を見つけることができます。
  • BCC ツールにアクセスするには、 kubectl node-shell only を使用します。
  • このセクションの次のコマンドはすべて、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 アドレスをポッドにマップします。 動作しない場合は、続行できます。

  5. 前の出力からの接続数が最も多い SADDR または NETNS 値をメモし、次の lsns コマンドを実行して PID にマップします。 Lsns は、Linux プロセス ツリーで名前空間を一覧表示し、名前空間を PID にマップする Linux ツールです。

    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 の最初の 5 文字に注意してください。 これは、手順 7 で使用します。

  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
    

    POD ID と一致するには、前のコンテナー化された -id 値の最初の 5 文字を使用します。

  8. ノードで実行されているすべてのポッドを取得し、前の POD ID を使用して、コマンド出力からの送信接続が多いポッドと一致させます。

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

手順 3: アプリケーションによって行われたすべての送信ネットワーク接続を見つける

  1. 次のいずれかのコマンドを使用して、 Step 2 で高い送信接続を持つと識別されたポッドに対して実行します。

    • kubectl exec -it <pod name> -n <namespace> /bin/bash
      
    • kubectl exec -it <pod name> -n <namespace> /bin/sh
      
  2. 次のコマンドを実行して、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. netstat がポッドにインストールされたら、次のコマンドを実行します。

    netstat -ptn | grep -i established
    

    コマンド出力の例を次に示します。

    tcp        0      0 10.x.x.x:xxxx        20.x.x.x:443       ESTABLISHED xxxxx3/telnet
    

コマンド出力では、ローカル アドレスはポッドの IP アドレス、外部アドレスはアプリケーションが接続する IP です。 ESTABLISHED状態のパブリック IP 接続は、SNAT を利用する接続です。 パブリック IP アドレスへの ESTABLISHED 状態の接続のみをカウントし、 ESTABLISHED 状態のプライベート IP アドレスへの接続は無視してください。

ノードで実行されている他のすべてのポッドについて、このセクションの手順を繰り返します。 パブリック IP アドレスへの ESTABLISHED 状態の接続が最も多いポッドは、ノードで SNAT ポート枯渇の原因となるアプリケーションをホストします。 アプリケーション開発者と協力して、 Design 接続効率の高いアプリケーションで説明されている推奨事項を使用して、ネットワーク パフォーマンスを向上させるためにアプリケーションを調整します。 推奨事項を実装した後、SNAT ポートの枯渇が少ないことを確認します。

お問い合わせはこちらから

質問がある場合やヘルプが必要な場合は、サポート要求を作成するか、Azure コミュニティ サポートにお問い合わせください。 Azure フィードバック コミュニティに製品フィードバックを送信することもできます。