Google Distributed Cloud のネットワークの問題をトラブルシューティングする

このページでは、Google Distributed Cloud のネットワーク関連の問題を解決する方法について説明します。一般的なトラブルシューティング情報とガイダンス、推奨されるツールを紹介します。DNS のトラブルシューティング情報と、MetalLB に関する一般的な問題も一部記載されています。

さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。

ネットワーク接続のトラブルシューティング

GKE Enterprise のネットワーキングは、物理的なネットワーク インフラストラクチャに依存しています。たとえば、MetalLB は Gratuitous ARP を使用するスイッチに依存し、Border Gateway Protocol(BGP)とのバンドル型ロード バランシングはルーターに依存していて、すべてのノードが相互に通信できる必要があります。GKE クラスタでネットワークの問題がある場合は、問題が GKE Enterprise コンポーネントにあるか、独自のインフラストラクチャにあるかを特定する必要があります。

まず問題の範囲を特定し、影響を受けるコンポーネントを特定します。問題の範囲は、サブジェクト(送信元)、ターゲット(宛先)、ネットワーク層のいずれかのカテゴリになります。

サブジェクトの範囲は次のいずれかになります。

  • クラスタ全体のすべてのノード(または hostNetwork Pod)。
  • クラスタ全体のすべての Pod。
  • 単一のノードまたは一連のノード上のすべての Pod。
  • 同じ Deployment または DaemonSet のすべての Pod。
  • クラスタ外のクライアント。

ターゲットの範囲は次のいずれかになります。

  • 同じクラスタの他のすべての Pod IP アドレス。
  • 同じノードの他のすべての Pod IP アドレス。
  • 同じクラスタの ClusterIP Service VIP。
  • 同じクラスタの LoadBalancer Service VIP。
  • Ingress レイヤ 7 LoadBalancer(Istio)。
  • 同じクラスタ内の他のノード。
  • 内部 DNS 名(*.svc.cluster.local など)。
  • 外部 DNS 名(google.com など)。
  • クラスタ外のエンティティ。
  • インターネット上のエンティティ。

ネットワーク層は、次のいずれかになります。

  • ネイバー システム、ARP、NDP などのレイヤ 2 リンクレイヤの問題。
  • レイヤ 3 IP アドレスのルーティングの問題。
  • レイヤ 4 TCP または UDP エンドポイントの問題。
  • レイヤ 7 の HTTP または HTTPS の問題。
  • DNS 解決に関する問題。

問題の範囲を把握することで、問題に関連するコンポーネントと、問題が発生しているレイヤを特定できます。問題の一部は一時的なものであり、システム復旧後のスナップショットには根本原因の分析に十分な情報が含まれてません。このため、問題発生時の情報収集が重要になります。

上り(内向き)の問題

サブジェクトがクラスタ外のクライアントで、LoadBalancer Service に接続できない場合は、North-South 接続に問題があります。次の図は実際の例を示しています。受信トラフィックがスタックを通過して左から右に向かい、戻りトラフィックがスタックを介して右から左に向かうことを示しています。

上り(内向き)トラフィックは、ユーザーから物理インフラストラクチャ、ロードバランサ、anetd / kube-proxy を経由してバックエンドに送信されます。

このトラフィック フローに問題がある場合は、次のトラブルシューティングのフローチャートを使用して、問題の発生元を特定します。

パケットが環境を通過する際の各ステップを確認して、ネットワーク上り(内向き)の問題のトラブルシューティングを行います。適切なアクションと接続性が存在していることを確認します。

このフローチャートでは、次のトラブルシューティングのガイダンスが問題の発生場所の特定に役立ちます。

  • パケットがクライアントから送信されているか。そうでない場合は、ネットワーク インフラストラクチャで問題が発生している可能性があります。
  • MetalLB を使用しているか。使用している場合、パケットが LB ノードに到達し、ARP が正しく送信されているか。そうでない場合は、ネットワーク インフラストラクチャで問題が発生している可能性があります。
  • F5 BIG-IP を使用していまるか。使用している場合は、F5 の問題を確認する。
  • ネットワーク アドレス変換(NAT)が正しく行われているか。そうでない場合は、kube-proxy / Dataplane V2 で問題が発生している可能性があります。
  • パケットがワーカーノードに到達しているか。そうでない場合は、Dataplane v2 の Pod 間で問題が発生している可能性があります。
  • パケットが Pod に到達しているか。そうでない場合は、Dataplane v2 のローカル転送で問題が発生している可能性があります。

以降のセクションでは、各ステージのトラブルシューティングを行い、トラフィックが正しく流れているかどうかを判断する手順について説明します。

パケットがクライアントから送信されているか。

パケットがクライアントから正しく送信され、物理ネットワーク インフラストラクチャに構成されたルーターを通過するかどうかを確認します。

  1. tcpdump を使用して、クライアントから宛先サービスに向かうパケットを確認します。

    tcpdump -ni any host SERVICE_VIP and port SERVICE_PORT
    

    送信されるトラフィックが確認できない場合は、ここが問題の発生源です。

パケットが LoadBalancer ノードに到達しているか。

ロードバランサとして MetalLB を使用する場合:

  1. metallb-controller ログを調べて、サービス VIP を提供するロードバランサ ノードを特定します。

    kubectl -n kube-system logs -l app=metallb --all-containers=true | grep SERVICE_VIP
    
  2. SSH を使用してノードに接続します。

  3. MetalLB ノードの場合は、tcpdump を使用してトラフィックを確認します。

    tcpdump -ni any host SERVICE_VIP and port SERVICE_PORT
    

    ManualLB の場合、トラフィックは任意のノードに到達します。ロードバランサの構成に応じて、1 つまたは複数のノードを選択できます。tcpdump を使用してトラフィックを確認します。

    tcpdump -ni any host NODE_IP and port NODE_PORT
    

    このコマンドは、ロードバランサの種類によって異なります。MetalLB はパケットをノードに転送する前に NAT を行いません。

    どのノードに向かうトラフィックも確認できない場合は、ここが問題の発生源です。

F5 BIG-IP に問題があるか。

F5 BIG-IP の問題をトラブルシューティングするには、F5 Service がトラフィックを受信しないで次のいずれかのセクションをご覧ください。

ARP は正しく送信されているか

MetalLB のロードバランサ ノードは、ARP を使用してサービス VIP をアドバタイズします。ARP レスポンスが正しく送信されていても、トラフィックが到達しない場合は、物理ネットワーク インフラストラクチャに問題があることを示しています。この問題の一般的な原因は、一部の高度なデータプレーン学習機能が、ソフトウェア定義ネットワーク(SDN)ソリューションの ARP 応答を無視することです。

  1. tcpdump を使用して ARP レスポンスを検出します。

    tcpdump -ni any arp
    

    問題が発生している VIP をアドバタイズしているメッセージを探します。

  2. MetalLB の場合、Gratuitous ARP は送信されません。レスポンスが確認される頻度は、トップオブラック(ToR)スイッチなどの別のデバイスが ARP リクエストを送信するタイミングによって異なります。

NAT は実行されているか。

Dataplane v2 / kube-proxy は、宛先ネットワーク アドレス変換(宛先 NAT または DNAT)を行い、宛先 VIP をバックエンド Pod の IP アドレスに変換します。ロードバランサのバックエンドのノードがわかっている場合は、SSH を使用してそのノードに接続します。

  1. tcpdump を使用して、Service VIP が正しく変換されているかどうかを確認します。

    tcpdump -ni any host BACKEND_POD_IP and port CONTAINER_PORT
    
  2. Dataplane v2 では、追加で anetd Pod に接続し、組み込みの Cilium デバッグツールを使用することもできます。

    cilium monitor --type=drop
    

詳細については、Dataplane v2 / Cilium の問題の次のいずれかのセクションをご覧ください。

パケットがワーカーノードに到達しているか。

ワーカーノードで、パケットは外部インターフェースに到達し、そこから Pod に配信されます。

  1. tcpdump を使用して、パケットが外部インターフェース(通常は eth0 または ens192)に到達しているかどうか確認します。

    tcpdump -ni any host BACKEND_POD_IP and port CONTAINER_PORT
    
Google Distributed Cloud の場合、パケットはトンネルでカプセル化されます。パケットは、カプセル化解除されると、cilium_geneve という名前のネットワーク インターフェースから送信されます。

通常の Service バックエンドには、さまざまなノードにわたる複数の Pod が含まれています。このため、問題のあるノードのトラブルシューティングが難しくなる場合があります。一般的な回避策としては、一部のパケットが最終的に到達するように、問題のキャプチャ期間を十分な長さにするか、バックエンドの数を 1 に制限します。

パケットがワーカーノードに到達しない場合は、ネットワーク インフラストラクチャに問題があることを示しています。ネットワーク インフラストラクチャ チームに問い合わせて、LoadBalancer ノードとワーカーノード間でパケットがドロップされる理由を確認します。一般的な問題としては、次のようなものがあります。

  • ソフトウェア定義ネットワーク(SDN)のログを確認します。SDN は、セグメンテーション、誤ったチェックサム、なりすまし対策など、さまざまな理由でパケットをドロップすることがあります。
  • Geneve パケットの UDP ポート 6081 をフィルタするファイアウォール ルール。

パケットがノードの外部インターフェースまたはトンネル インターフェースに到達したら、それを宛先 Pod に転送する必要があります。Pod がホスト ネットワーキング Pod である場合、Pod はネットワーク Namespace をノードと共有するため、この手順は必要ありません。それ以外の場合は、追加のパケット転送が必要です。

各 Pod には、パイプのように機能する仮想イーサネット インターフェース ペアがあります。インターフェースの一方の端に送信されたパケットは、インターフェースのもう一方の端から受信されます。一方のインターフェースは Pod のネットワークの Namespace に移動し、名前が eth0 に変更されます。もう一方のインターフェースはホストの Namespace に残ります。CNI が異なればスキーマも異なります。Dataplane v2 の場合、インターフェースの名前は通常、lxcxxxx です。名前には連続するインターフェース番号が付きます(lxc17lxc18 など)。tcpdump を使用してパケットが Pod に到達しているかどうかを確認できます。インターフェースを指定することもできます。

tcpdump -ni lcxxxx host BACKEND_POD_IP and port CONTAINER_PORT

パケットがノードに到達しても Pod に到達できない場合は、次のようにルーティング テーブルを確認します。

ip route

通常、各 Pod には、Pod IP アドレスを lxc インターフェースにルーティングするルーティング エントリが必要です。エントリがない場合は通常、CNI データパスにエラーがあることを意味します。根本原因を特定するには、CNI DaemonSet のログを確認します。

下り(外向き)に関する問題

トラフィックが Pod に到達している場合は、Pod からの下り(外向き)のトラフィックで問題が発生している可能性があります。次の図は実際の例です。受信トラフィックがスタックを通過して、左から右に向かうことを示しています。

下り(外向き)トラフィックは、Pod からホストの外部インターフェース、物理インフラストラクチャを経由して外部サービスに送信されます。

  1. 送信パケットがノード IP アドレスとして正しくマスカレードされていることを確認するには、外部サービス(レイヤ 4)を確認します。

    パケットの送信元 IP アドレスは、送信元ネットワーク アドレス変換(送信元 NAT または SNAT)を使用して Pod IP アドレスからノード IP アドレスにマッピングする必要があります。Dataplane v2 では、このプロセスは外部インターフェースに読み込まれる ebpf で実現します。

    tcpdump を使用して、送信元 IP アドレスが Pod IP アドレスからノード IP アドレスに正しく変換されているかどうかを確認します。

    tcpdump -ni EXTERNAL_INTERFACE host EXTERNAL_IP and port EXTERNAL_PORT
    

    パケットが正しくマスカレードされていることを tcpdump が示していても、リモート サービスが応答しない場合は、インフラストラクチャの外部サービスへの接続を確認します。

  2. 送信パケットがノード IP アドレスとしてマスカレードされている場合は、tcpdump を使用して外部ホスト(レイヤ 3)の接続性を確認します。

    tcpdump -ni EXTERNAL_INTERFACE host EXTERNAL_IP and icmp
    

    tcpdump を実行すると同時に、いずれかの Pod から ping を実行します。

    kubectl exec POD_NAME ping EXTERNAL_IP
    

    ping の応答が表示されない場合は、インフラストラクチャの外部サービスへの接続を確認します。

クラスタ内の問題

Pod 間の接続の問題については、問題の範囲をノードにしてみてください。多くの場合、ノードグループは別のノードグループと通信できません。

  1. Dataplane v2 では、現在のノードから同じクラスタ内の他のすべてのノードに対するノード接続性を確認します。anetd Pod 内から、ヘルス ステータスをチェックします。

    cilium status --all-health
    

ネットワーク層の問題

接続性の問題が発生しているネットワーク層を特定することは、重要なステップです。「ソースから宛先への接続の問題」のようなエラー メッセージは、アプリケーション エラー、ルーティングの問題、DNS の問題など、問題の解決に十分な情報ではありません。どのレイヤで問題が発生しているかを把握することで、適切なコンポーネントを修正できます。

多くの場合、エラー メッセージは問題が発生している層を直接示しています。ネットワーク層に関する問題のトラブルシューティングに役立つ例を以下に紹介します。

  • HTTP エラーは、レイヤ 7 の問題であることを示します。
    • HTTP コード 40x50x、TLS handshake のエラーは、レイヤ 4 ではすべてが正常に機能していることを意味します。
  • 「ピアによる接続のリセット」エラーは、レイヤ 4 に問題があることを示しています。
    • 多くの場合、リモート ソケットは接続の現在の状態に一致しないため、RESET パケットを送信します。このような動作は、接続トラッキングや NAT の間違いである可能性があります。
  • 「ホストへのルートがない」エラーと「接続タイムアウト」エラーは通常、レイヤ 3 またはレイヤ 2 の問題です。
    • これらのエラーは、パケットを宛先に正しく転送できないことを示しています。

トラブルシューティングに役立つツール

ネットワーク関連の DaemonSet はノード上で実行されるため、接続の問題の原因となる可能性があります。ただし、ノード、トップオブラック(ToR)スイッチ、スパイン ルーター、ファイアウォールの構成ミスでも問題が発生する可能性があります。次のツールを使用して、問題の範囲またはレイヤを特定し、GKE Enterprise ノードの問題か、物理インフラストラクチャの問題かを判断できます。

Ping

Ping はレイヤ 3(IP レイヤ)で動作し、送信元と宛先間のルートをチェックします。ping が宛先に到達しない場合、多くはレイヤ 3 に問題があります。

ただし、すべての IP アドレスが ping に応答するわけではありません。たとえば、レイヤ 4 のロードバランサの場合、一部のロードバランサ VIP は ping に応答しません。VIP が ping レスポンスを返さない可能性がある例としては、ClusterIP Service があります。レイヤ 4 では、VIP:port などのポート番号が指定された場合にのみ、この Service から ping のレスポンスが返されます。

Google Distributed Cloud の BGPLB ロードバランサと MetalLB ロードバランサはすべてレイヤ 3 で動作します。ping を使用して接続性を確認できます。F5 は異なりますが、ICMP もサポートしています。ping を使用して F5 VIP への接続性を確認できます。

arping

arping は ping と似ていますが、レイヤ 2 で動作する点が異なります。レイヤ 2 とレイヤ 3 の問題の多くは、アプリケーションからのエラー メッセージが似ています。arping と ping は問題を区別する際に役立ちます。たとえば、送信元と宛先が同じサブネット内にあり、宛先に arping できない場合は、レイヤ 2 の問題です。

arping <ip> が成功すると、宛先の MAC アドレスが返されます。レイヤ 2 では多くの場合、このアドレスは物理インフラストラクチャの問題を示しています。多くの場合、この問題はノード間の物理的な切り替えです。

arping は、IP アドレスの競合も検出できます。IP アドレスの競合は、2 つのマシンが同じサブネット上で同じ IP アドレスを使用するように構成されている場合や、VIP が別の物理マシンによって使用されている場合に発生します。IP アドレスの競合により、トラブルシューティングしにくい断続的な問題が発生する可能性があります。arping <ip> が複数の MAC アドレス エントリを返す場合は、IP アドレスの競合があることを示しています。

arping で MAC アドレスを取得したら、https://maclookup.app/ でその MAC アドレスのメーカーを検索できます。すべてのメーカーが MAC プレフィックスを所有しているため、この情報を使用して、同じ IP アドレスを使用しようとしているデバイスを特定できます。たとえば、VMware が 00:50:56 ブロックを所有している場合、MAC アドレス 00:50:56:xx:yy:zz は vSphere 環境内の VM です。

iproute2

iproute2ip CLI には、次のような便利なサブコマンドがあります。

  • ip r: ルートテーブルを出力します。
  • ip n: IP アドレスから MAC アドレスへのマッピングのネイバー テーブルを出力します。
  • ip a: マシン上のすべてのインターフェースを出力します。

ネイバー テーブルにルートがないか、エントリがないと、ノードからの接続で問題が発生する可能性があります。anetd は、ルートテーブルとネイバー テーブルを管理します。これらのテーブルの構成ミスで、接続の問題が発生する可能性があります。

Cilium / Hubble CLI for Dataplane v2

anetd Pod には、接続性の問題に役立つデバッグツールがいくつか用意されています。

  • cilium monitor --type=drop
    • anetd / Cilium によってドロップされたすべてのパケットのログを出力します。
  • hubble observe
    • anetd の ebpf スタックを通過するすべてのパケットを出力します。
  • cilium status --all-health
    • ノード間の接続ステータスなど、Cilium のステータスを出力します。各 anetd Pod は、クラスタ内の他のすべてのノードの状態をチェックします。これは、ノード間の接続の問題を特定する際に役立ちます。

iptables

iptables は、多くの Kubernetes コンポーネントとサブシステムで使用されています。kube-proxy は iptables を使用してサービスの解決を実装します。

  1. iptables レベルでネットワークの問題をトラブルシューティングするには、次のコマンドを使用します。

    iptables -L -v | grep DROP
    

    ドロップルールを確認し、パケット数とバイト数が時間とともに増加するかどうかを確認します。

tcpdump

tcpdump は、大量のネットワーク トラフィック データを生成する強力なパケット キャプチャ ツールです。一般的には、送信元と宛先の両方から tcpdump を実行します。パケットが送信元ノードから送信されるときにキャプチャされ、宛先ノードではキャプチャされない場合、その間でパケットがドロップされています。この動作は通常、物理インフラストラクチャでパケットが誤ってドロップされたことを示しています。

DNS のトラブルシューティング

DNS 解決の問題は、主に次の 2 つのカテゴリに分類されます。

  • クラスタ内の DNS サーバーを使用する通常の Pod。
  • クラスタ内の DNS サーバーを使用しないホスト ネットワークの Pod またはノード。

以降のセクションでは、クラスタ DNS アーキテクチャについて説明し、これらのカテゴリのいずれかのトラブルシューティングを始める前に役立つヒントを紹介します。

クラスタ DNS アーキテクチャ

クラスタ DNS サービスは、クラスタ内の Pod の DNS リクエストを解決します。CoreDNS は、Google Distributed Cloud のすべてのバージョンにこのサービスを提供します。

各クラスタには 2 つ以上の coredns Pod と、クラスタサイズに基づいて DNS Pod の数を調整するオートスケーラーがあります。また、すべてのバックエンド coredns Pod 間でリクエストのロード バランシングを行う kube-dns というサービスもあります。

ほとんどの Pod はアップストリーム DNS が kube-dns Service IP アドレスに構成されます。Pod は DNS リクエストをいずれかの coredns Pod に送信します。DNS リクエストは、次のいずれかの宛先にグループ化できます。

  • cluster.local ドメインに対するリクエストの場合、これはクラスタ内の Service または Pod を参照するクラスタ内の DNS 名です。
    • CoreDNS は、クラスタ内のすべての Service と Pod に対して api-server を監視し、有効な cluster.local ドメインへのリクエストに応答します。
  • リクエストが cluster.local ドメイン用でない場合、そのリクエストは外部ドメイン用です。
    • CoreDNS は、リクエストをアップストリーム ネームサーバーに転送します。デフォルトでは、CoreDNS は、実行されているノードに構成されているアップストリーム ネームサーバーを使用します。

詳細については、DNS の仕組みと Kubernetes における構成の概要に関するページをご覧ください。

DNS のトラブルシューティングのヒント

DNS の問題をトラブルシューティングするには、dig ツールと nslookup ツールを使用します。これらのツールを使用すると、DNS リクエストを送信して、DNS 解決が正常に機能するかどうかをテストできます。次の例は、dignslookup を使用して DNS 解決の問題を確認する方法を示しています。

  • dig または nslookup を使用して google.com のリクエストを送信します。

    dig google.com
    nslookup google.com
    
  • dig を使用して、kubernetes.default.svc.cluster.local のリクエストをサーバー 192.168.0.10 に送信します。

    dig @192.168.0.10 kubernetes.default.svc.cluster.local
    
  • nslookup を使用して、前の dig コマンドと同じ DNS ルックアップを実行することもできます。

    nslookup kubernetes.default.svc.cluster.local 192.168.0.10
    

    dig コマンドまたは nslookup コマンドの出力を確認します。誤ったレスポンスが返された場合や、レスポンスが返されなかった場合は、DNS 解決の問題が発生しています。

通常の Pod

DNS の問題をデバッグする最初のステップは、リクエストが coredns Pod に到達するかどうかを確認することです。多くの場合、DNS リクエストはワークロードが送信するトラフィックの最初のタイプであるため、一般的なクラスタの接続の問題は DNS の問題として表示されます。

アプリケーションのエラー メッセージを確認します。io timeout などのエラーは、レスポンスがなく、一般的なネットワーク接続の問題があることを示しています。

NXDOMAINSERVFAIL などの DNS エラーコードを含むエラー メッセージは、クラスタ内の DNS サーバーに接続していても、サーバーがドメイン名を解決できなかったことを示しています。

  • NXDOMAIN エラーは、ドメインが存在しないことを DNS サーバーが報告していることを示しています。アプリケーションがリクエストするドメイン名が有効であることを確認します。
  • SERVFAIL または REFUSED エラーは、DNS サーバーがレスポンスを送信したものの、ドメインを解決できなかったか、ドメインの存在を検証できなかったことを示しています。詳細については、coredns Pod のログを確認してください。

kube-dns サービスの IP アドレスは、次のコマンドを使用して確認できます。

kubectl -n kube-system get svc kube-dns

前のセクションで説明したように、DNS が機能していない Pod から、dig または nslookup を使用してこの IP アドレスに DNS リクエストを送信してみます。

  • これらのリクエストが機能しない場合は、各 coredns Pod の IP アドレスにリクエストを送信してみてください。
  • 一部の Pod が機能しても他の Pod が機能しない場合は、DNS の解決が coredns Pod と同じノードの Pod に機能し、ノード間では機能しないなど、識別可能なパターンがあるかどうかを確認します。この動作は、クラスタ内の接続の問題を示している可能性があります。

CoreDNS が外部のドメイン名を解決できない場合は、次のセクションでホスト ネットワークの Pod のトラブルシューティングを行ってください。CoreDNS は、ホスト ネットワークの Pod のように動作し、名前解決にノードのアップストリーム DNS サーバーを使用します。

ホスト ネットワークの Pod またはノード

ホスト ネットワークの Pod とノードは、DNS の解決用にノードに構成されたネームサーバーを使用します。クラスタ内の DNS サービスは使用しません。OS に応じて、このネームサーバーは /etc/resolv.conf または /run/systemd/resolve/resolv.conf のいずれかに構成されます。この構成では、cluster.local ドメイン名を解決できません。

ホスト ネットワーク名の解決に問題がある場合は、前のセクションのトラブルシューティングの手順に沿って、アップストリーム ネームサーバーで DNS が正しく機能しているかどうかをテストします。

すべてのノードに同じ一連のサーバーが構成されていることを確認します。異なるネームサーバーが構成されている場合、異なるノード上の DNS の解決に不整合が生じる可能性があります。dig または nslookup を使用して各ネームサーバーにリクエストを送信し、各ネームサーバーが個別に機能していることを確認します。一部のネームサーバーは機能しても他のネームサーバーは機能しない場合、このような DNS の解決の不一致が発生します。

ネットワークに関する一般的な問題

以降のセクションでは、ネットワークで発生する可能性のある一般的な問題について説明します。問題を解決するには、適切なトラブルシューティング ガイダンスに沿って対応してください。さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。

Dataplane v2 / Cilium

一般的なエラー: [PUT /endpoint/{id}][429] putEndpointIdTooManyRequests

このエラーは、レート制限により Pod 作成イベントが Cilium エージェントによって拒否されたことを意味します。Cilium の PUT エンドポイントへの同時リクエストの上限は、ノードあたり 4 です。1 つのノードへのリクエストが急増した場合、この動作が行われる可能性があります。Cilium エージェントは、遅延したリクエストに対応する必要があります。

GKE Enterprise 1.14 以降では、レート上限はノード容量に合わせて自動的に調整されます。レート制限はより合理的な数に収束し、より強力なノードに対するレート制限が高くなります。

一般的なエラー: Ebpf map size is full

Dataplane v2 は、eBFP マップに状態を保存します。状態には、Service、接続トラッキング、Pod の ID、ネットワーク ポリシーのルールが含まれます。マップがいっぱいの場合、エージェントはエントリを挿入できません。これにより、コントロール プレーンとデータプレーンの間に不一致が生じます。たとえば、Service マップのエントリ数の上限は 64k です。

  1. eBFP マップエントリとその現在のサイズを確認するには、bpftool を使用します。次の例では、ロードバランサ マップをチェックします。

    bpftool map dump pinned \
    /sys/fs/bpf/tc/globals/cilium_lb4_services_v2 | tail -n -1
    
    bpftool map dump pinned \ /sys/fs/bpf/tc/globals/cilium_lb4_backends_v2 | tail -n -1
    
  2. マップが 64,000 個の上限に近づいている場合は、マップをクリーンアップします。次の例では、ロードバランサ マップをクリーンアップしています。

    bpftool map dump pinned /sys/fs/bpf/tc/globals/cilium_lb4_services_v2 | \
        awk '{ print "0x"$2, "0x"$3, "0x"$4, "0x"$5, "0x"$6, "0x"$7, "0x"$8, "0x"$9, "0x"$10, "0x"$11, "0x"$12, "0x"$13}' | \
        head -n -1 | \
        xargs -L 1 bpftool map delete pinned /sys/fs/bpf/tc/globals/cilium_lb4_services_v2 key
    
    bpftool map dump pinned /sys/fs/bpf/tc/globals/cilium_lb4_backends_v2 | \
        awk '{ print "0x"$2, "0x"$3, "0x"$4, "0x"$5 }' | \
        head -n -1 | \
        xargs -L 1 bpftool map delete pinned /sys/fs/bpf/tc/globals/cilium_lb4_backends_v2 key
    
  3. 状態を eBFP マップに再入力するには、anetd を再起動します。

NetworkPluginNotReady エラーが原因でノードが未準備状態になる

CNI Pod がノードで実行されていない場合、次のようなエラーが表示されることがあります。

  "Container runtime network not ready" networkReady="NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized

ノードが未準備状態になり、次のようなエラーが発生することがあります。

  "Network plugin not installed"

ノードが初期化されると、kubelet は複数のイベントが発生するまで待機してから、ノードを Ready としてマークします。kubelet が確認するイベントとしては、Container Network Interface(CNI)プラグインのインストール状態などがあります。CNI プラグインは、CNI バイナリと CNI 構成の両方を必要なホスト ディレクトリにインストールするために、init コンテナを使用し、anetd によってインストールする必要があります。

この問題のトラブルシューティングを行うには、こうした Pod がノードで実行されていない理由を確認します。通常、このエラーはネットワークの問題によるものではありません。これらの Pod はホスト ネットワークで実行されるため、ネットワークの依存関係はありません。

  1. anetd Pod の状態を確認します。次のトラブルシューティング手順を確認すると、問題の原因の特定に役立ちます。

    • Pod が Crashlooping 状態の場合は、ログを調べて、Pod が正しく動作していない理由を確認します。
    • Pod が Pending 状態の場合は、kubectl describe を使用して Pod イベントを確認します。たとえば、Pod に Volume などのリソースが不足している可能性があります。
    • Pod が Running 状態の場合は、ログと構成を確認します。Cilium など、一部の CNI 実装には CNI のインストールを無効にするオプションが用意されています。
    • anetd には custom-cni-conf という構成オプションがあります。この設定が true として構成されている場合、anetd は CNI バイナリをインストールしません。

古い ARP エントリが原因でノードが準備完了状態になっていない

管理クラスタのコントロール プレーン ノードにある古い ARP エントリが原因で、MAC アドレスの不一致が生じることがあります。このアドレスの不一致により、マネージド ユーザー クラスタのコントロール プレーン VIP への接続タイムアウトが発生する可能性があります。接続タイムアウトにより、古い ARP エントリを持つノードが NOT READY としてマークされる可能性があります。NOT READY とマークされたノードは、クラスタのインストールとアップグレードを停止する可能性があります。

この場合、古い ARP エントリを持つノードの kubelet ログには、次のような TLS handshake タイムアウト エラーが含まれます。

failed to get API group resources: unable to retrieve the complete list of server APIs: v1: Get "https://128.160.252.101:443/api/v1": net/http: TLS handshake timeout

この問題の解決手順は次のとおりです。

  1. SSH を使用して、ユーザー クラスタのコントロール プレーン ノードに接続します。

  2. VIP アドレスがバインドされているインターフェースの MAC アドレスを確認します。

    ip a | grep DEVICE_NAME: -A 6
    

    DEVICE_NAME は、コントロール プレーン ノードのネットワーク デバイス名に置き換えます。

  3. SSH を使用して、管理クラスタのコントロール プレーン ノードに接続します。

  4. 管理クラスタ コントロール プレーンの ARP キャッシュで、ユーザー クラスタ コントロール プレーンの VIP アドレスを確認します。

    ip n | grep VIP_ADDRESS
    

    VIP_ADDRESS は、ユーザー クラスタのコントロール プレーン VIP(controlPlaneVIP)の IP アドレスに置き換えます。

    2 つの ip コマンドが異なる MAC アドレスを返す場合は、この問題の影響を受けています。

  5. この問題を解決するには、管理クラスタのコントロール プレーン ノードで ARP キャッシュをフラッシュします。

    ip n flush all
    

F5 Service がトラフィックを受信しない

F5 Service にトラフィックが届かない場合は、次のトラブルシューティング手順を確認してください。

  1. F5 BIG-IP のすべてのパーティションが、管理クラスタまたはユーザー クラスタの 1 つのクラスタに構成されていることを確認します。1 つのパーティションを複数の異なるクラスタで共有すると、接続が断続的に中断されます。これは、2 つのクラスタが同じパーティションの制御を奪い、他のクラスタから Service を削除しようとするために発生します。

  2. 次の 2 つの Pod が実行されていることを確認します。実行されていない Pod はエラーを示します。

    Load-balancer-f5
    K8s-bigip-ctlr-deployment-577d57985d-vk9wj
    

    GKE Enterprise が所有する Load-balancer-f5 は、LoadBalancer タイプの Service ごとに ConfigMap を作成します。ConfigMap は、最終的に bigip コントローラによって使用されます。

  3. 各 Service の各ポートに ConfigMap が存在することを確認します。たとえば、次のポートを使用します。

    Kube-server-443-tcp     2   31h
    Kube-server-8132-tcp        2   31h
    

    kube-server Service は次の例のようになります。

    Kube-server LoadBalancer  10.96.232.96  21.1.7.16   443:30095/TCP,8132:32424/TCP  31h
    

    ConfigMap の data セクションには、次の例に示すように、フロントエンド VIP とポートが必要です。

    data: '{"virtualServer":{"backend":{"serviceName":"kube-apiserver","servicePort":443,"healthMonitors":[{"protocol":"tcp","interval":5,"timeout":16}]},"frontend":{"virtualAddress":{"bindAddr":"21.1.7.16","port":443},"partition":"herc-b5bead08c95b-admin","balance":"ratio-member","mode":"tcp"}}}'
      schema: f5schemadb://bigip-virtual-server_v0.1.7.json
    
  4. BIG-IP インスタンスのログと指標を確認します。ConfigMap が正しく構成されていても BIG-IP インスタンスが構成を適用できない場合は、F5 の問題である可能性があります。BIG-IP インスタンス内で発生した問題については、F5 サポートにお問い合わせのうえ、問題の診断とトラブルシューティングを行ってください。

並列接続が多すぎる NAT のエラー

クラスタ内の特定のノードでは、ノードの IP アドレスによって、クラスタ外のアドレスにルーティングされるパケットに対してネットワーク アドレス変換(NAT)が提供されます。同様に、受信パケットがバンドル型ロード バランシング(spec.loadBalancer.mode: bundled)を使用するように構成された負荷分散ノードに入ると、送信元ネットワーク アドレス変換(SNAT)により、バックエンド Pod に転送される前にノード IP アドレスにパケットがルーティングされます。

Google Distributed Cloud で使用される NAT のポート範囲は 32768-65535 です。この範囲により、並列接続の数はそのノードのプロトコルあたり 32,767 に制限されます。各接続には、conntrack テーブルのエントリが必要です。有効期間が短い接続数が多すぎると、conntrack テーブルが NAT のポートを使い果たします。ガベージ コレクタは古いエントリをクリーンアップしますが、クリーンアップは直ちには行われません。

ノード上の接続数が 32,767 に近づくと、NAT を必要とする接続のパケット ドロップが発生し始めます。

この問題の影響を受けるかどうかを判断するには:

  1. 問題のあるノードの anetd Pod で次のコマンドを実行します。

    kubectl -n kube-system anetd-XXX -- hubble observe \
        --from-ip $IP --to-ip $IP -f
    

    次のようなエラーが表示されます。

    No mapping for NAT masquerade DROPPED
    

この問題を回避するには、トラフィックを他のノードに再分散します。

次のステップ

さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。