このページでは、Google Kubernetes Engine(GKE)クラスタで GKE Dataplane V2 を有効にしてトラブルシューティングする方法について説明します。
新しい Autopilot クラスタでは、バージョン 1.22.7-gke.1500 以降とバージョン 1.23.4-gke.1500 以降で GKE Dataplane V2 が有効になっています。GKE Dataplane V2 の使用に関する問題が発生した場合は、トラブルシューティングに進んでください。
GKE Dataplane V2 を使用して GKE クラスタを作成する
GKE バージョン 1.20.6-gke.700 以降で新しいクラスタを作成する場合は、gcloud CLI か Kubernetes Engine API を使用して、GKE Dataplane V2 を有効にできます。GKE バージョン 1.17.9 以降を使用した新しいクラスタを作成する場合は、GKE Dataplane V2 をプレビューで有効にすることもできます。
Console
GKE Dataplane V2 を使用して新しいクラスタを作成するには、次の作業を行います。
Google Cloud コンソールで Google Kubernetes Engine のページに移動します。
[add_box 作成] をクリックします。
[構成] をクリックして、Standard クラスタを構成します。
[ネットワーキング] セクションで、[Dataplane V2 を有効にする] チェックボックスをオンにします。GKE Dataplane V2 にはネットワーク ポリシーの適用が組み込まれているため、[Dataplane V2 を有効にする] を選択すると、[Kubernetes ネットワーク ポリシーを有効にする] オプションは無効になります。
[作成] をクリックします。
gcloud
GKE Dataplane V2 を使用して新しいクラスタを作成するには、次のコマンドを使用します。
gcloud container clusters create CLUSTER_NAME \
--enable-dataplane-v2 \
--enable-ip-alias \
--release-channel CHANNEL_NAME \
--location COMPUTE_LOCATION
次のように置き換えます。
CLUSTER_NAME
: 新しいクラスタの名前。CHANNEL_NAME
: GKE バージョン 1.20.6-gke.700 以降を含むリリース チャンネル。リリース チャンネルを使用しない場合は、--release-channel
ではなく--cluster-version
フラグを使用してバージョン 1.20.6-gke.700 以降を指定することもできます。COMPUTE_LOCATION
: 新しいクラスタの Compute Engine のロケーション。
API
GKE Dataplane V2 を使用して新しいクラスタを作成するには、create
リクエストで networkConfig
オブジェクトに datapathProvider
フィールドを指定します。
次の JSON スニペットは、GKE Dataplane V2 を有効にするために必要な構成を示しています。
"cluster":{
"initialClusterVersion":"VERSION",
"ipAllocationPolicy":{
"useIpAliases":true
},
"networkConfig":{
"datapathProvider":"ADVANCED_DATAPATH"
},
"releaseChannel":{
"channel":"CHANNEL_NAME"
}
}
次のように置き換えます。
- VERSION: クラスタのバージョン。GKE 1.20.6-gke.700 以降にする必要があります。
- CHANNEL_NAME: GKE バージョン 1.20.6-gke.700 以降を含むリリース チャンネル。
GKE Dataplane V2 に関する問題のトラブルシューティング
このセクションでは、GKE Dataplane V2 の問題を調査して解決する方法について説明します。
GKE Dataplane V2 が有効になっていることを確認します。
kubectl -n kube-system get pods -l k8s-app=cilium -o wide
GKE Dataplane V2 が実行中の場合、出力には接頭辞が
anetd-
の Pod が含まれます。anetd は GKE Dataplane V2 のネットワーク コントローラです。サービスまたはネットワーク ポリシーの適用に問題がある場合は、
anetd
の Pod ログを確認します。Cloud Logging で次のログセレクタを使用します。resource.type="k8s_container" labels."k8s-pod/k8s-app"="cilium" resource.labels.cluster_name="CLUSTER_NAME"
Pod の作成に失敗した場合は、kubelet のログで手がかりを探します。Cloud Logging で次のログセレクタを使用します。
resource.type="k8s_node" log_name=~".*/logs/kubelet" resource.labels.cluster_name="CLUSTER_NAME"
CLUSTER_NAME
は、クラスタの名前に置き換えます。または、すべてのクラスタのログを表示するには、完全に削除してください。
既知の問題
GKE Dataplane V2 クラスタの NodePort 範囲の競合に関連する接続の断続的な問題
GKE Dataplane V2 クラスタでは、マスカレード トラフィックまたはエフェメラル ポートの使用で、接続の問題が断続的に発生することがあります。これらの問題は、予約済みの NodePort 範囲とポートの競合が原因で発生します。通常、次のシナリオで発生します。
カスタム
ip-masq-agent
: カスタムip-masq-agent
(バージョン 2.10 以降)を使用している場合、クラスタに NodePort サービスまたは Load Balancer サービスが存在するため、NodePort の範囲との競合により、接続の断続が発生することがあります。バージョン 2.10 以降では、ip-masq-agent
に--random-fully
引数がデフォルトで内部的に実装されています。これを軽減するには、ip-masq-agent
構成の引数で--random-fully=false
(バージョン 2.11 以降で使用可能)を明示的に設定します。構成の詳細については、Standard クラスタでの IP マスカレード エージェントの構成をご覧ください。エフェメラル ポート範囲の重複: GKE ノードの
net.ipv4.ip_local_port_range
で定義されたエフェメラル ポート範囲が NodePort 範囲(30000~32767)と重複すると、接続の問題が発生することがあります。この問題を回避するには、これらの 2 つの範囲が重複しないようにします。
ip-masq-agent
構成とエフェメラル ポート範囲の設定を確認し、NodePort 範囲と競合していないことを確認します。接続が断続的に発生する場合は、これらの原因を検討し、構成を調整してください。
ネットワーク ポリシーのポート範囲が有効にならない
GKE Dataplane V2 が有効になっているクラスタのネットワーク ポリシーで endPort
フィールドを指定しても、有効になりません。
GKE 1.22 以降では、Kubernetes Network Policy API を使用して、ネットワーク ポリシーが適用されるポートの範囲を指定できます。この API は、Calico ネットワーク ポリシーを使用するクラスタでサポートされますが、GKE Dataplane V2 を使用するクラスタではサポートされません。
NetworkPolicy
オブジェクトを API サーバーに書き込んだ後、読み返すことで、このオブジェクトの動作を確認できます。オブジェクトに endPort
フィールドが含まれている場合、この機能が適用されます。endPort
フィールドがない場合、この機能は適用されません。いずれの場合も、API サーバーに格納されているオブジェクトがネットワーク ポリシーの信頼できる情報源になります。
詳細については、KEP-2079: Network Policy to Port Ranges をご覧ください。
Pod に failed to allocate for range 0: no IP addresses available in range set
エラー メッセージが表示される
影響を受ける GKE のバージョン: 1.22~1.25
containerd を使用し、GKE Dataplane V2 が有効になっているノードプールを実行している GKE クラスタでは、IP アドレスのリーク問題が発生し、ノード上のすべての Pod の IP アドレスが使い果たされる可能性があります。影響を受けるノードでスケジュールされた Pod には、次のようなエラー メッセージが表示されます。
failed to allocate for range 0: no IP addresses available in range set: 10.48.131.1-10.48.131.62
この問題の詳細については、containerd の問題 #5768 をご覧ください。
解決済みのバージョン
この問題を解決するには、次のいずれかの GKE バージョンにクラスタをアップグレードします。
- 1.22.17-gke.3100 以降
- 1.23.16-gke.200 以降
- 1.24.9-gke.3200 以降
- 1.25.6-gke.200 以降
GKE Standard クラスタの回避策
この問題を軽減するには、リークした Pod の IP アドレスをノードから削除します。
リークした Pod の IP アドレスを削除するには、クラスタの認証情報を取得し、次の手順で単一のノードをクリーンアップします(名前がわかっている場合)。
次のシェル スクリプトを
cleanup.sh
という名前のファイルに保存します。for hash in $(sudo find /var/lib/cni/networks/gke-pod-network -iregex '/var/lib/cni/networks/gke-pod-network/[0-9].*' -exec head -n1 {} \;); do hash="${hash%%[[:space:]]}"; if [ -z $(sudo ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then sudo grep -ilr $hash /var/lib/cni/networks/gke-pod-network; fi; done | sudo xargs -r rm
クラスタノードでスクリプトを実行します。
gcloud compute ssh --zone "ZONE" --project "PROJECT" NODE_NAME --command "$(cat cleanup.sh)"
NODE_NAME
は、ノードの名前に置き換えます。
このスクリプトの DaemonSet バージョンを実行し、すべてのノードで同時に実行することもできます。
次のマニフェストを
cleanup-ips.yaml
という名前のファイルに保存します。apiVersion: apps/v1 kind: DaemonSet metadata: name: cleanup-ipam-dir namespace: kube-system spec: selector: matchLabels: name: cleanup-ipam template: metadata: labels: name: cleanup-ipam spec: hostNetwork: true securityContext: runAsUser: 0 runAsGroup: 0 containers: - name: cleanup-ipam image: gcr.io/gke-networking-test-images/ubuntu-test:2022 command: - /bin/bash - -c - | while true; do for hash in $(find /hostipam -iregex '/hostipam/[0-9].*' -mmin +10 -exec head -n1 {} \; ); do hash="${hash%%[[:space:]]}" if [ -z $(ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then grep -ilr $hash /hostipam fi done | xargs -r rm echo "Done cleaning up /var/lib/cni/networks/gke-pod-network at $(date)" sleep 120s done volumeMounts: - name: host-ipam mountPath: /hostipam - name: host-ctr mountPath: /run/containerd volumes: - name: host-ipam hostPath: path: /var/lib/cni/networks/gke-pod-network - name: host-ctr hostPath: path: /run/containerd
クラスタで DaemonSet を実行します。
kubectl apply -f cleanup-ips.yaml
このコマンドを実行するには、クラスタの管理者として kubectl アクセス権が必要です。
実行中の DaemonSet のログを確認します。
kubectl -n kube-system logs -l name=cleanup-ipam
接続トラッキング ルックアップが正しくないため、ネットワーク ポリシーによって接続が切断される
クライアント Pod が Service または内部パススルー ネットワーク ロードバランサの仮想 IP アドレスを介して自身に接続する場合、データプレーンでの conntrack ルックアップが正しく行われず、応答パケットが既存の接続の一部として識別されません。つまり、Pod の上り(内向き)トラフィックを制限するネットワーク ポリシーが、誤ってパケットに適用されます。
この問題の影響は、Service に構成された Pod の数によって異なります。たとえば、Service にバックエンド Pod が 1 つある場合、接続は常に失敗します。Service にバックエンド Pod が 2 つある場合、接続は 50% の確率で失敗します。
解決済みのバージョン
この問題を解決するには、次のいずれかの GKE バージョンにクラスタをアップグレードします。
- 1.28.3-gke.1090000 以降
回避策
この問題は、Service マニフェストの port
と containerPort
を同じ値に構成すると軽減できます。
ヘアピン接続フローのパケット ドロップ
Pod が Service を使用して自身との TCP 接続を作成し、Pod が接続の送信元と宛先の両方である場合、GKE Dataplane V2 eBPF 接続トラッキングは接続状態を誤って追跡し、conntrack エントリがリークします。
接続タプル(プロトコル、送信元 / 宛先 IP、送信元 / 宛先ポート)がリークすると、同じ接続タプルを使用する新しい接続で、戻りパケットがドロップされる可能性があります。
解決済みのバージョン
この問題を解決するには、次のいずれかの GKE バージョンにクラスタをアップグレードします。
- 1.28.3-gke.1090000 以降
- 1.27.11-gke.1097000 以降
回避策
以下のいずれかの回避策を使用します。
Pod 内で実行され、Service を使用して自身と通信する可能性があるアプリケーションに対して TCP 再利用(キープアライブ)を有効にします。これにより、TCP FIN フラグが発行されなくなり、conntrack エントリのリークを回避できます。
短時間の接続を使用する場合は、Gateway などのプロキシ ロードバランサを使用して Pod を公開して、Service を公開します。これにより、接続リクエストの宛先がロードバランサの IP アドレスに設定され、GKE Dataplane V2 がループバック IP アドレスに対して SNAT を実行できなくなります。
次のステップ
- ネットワーク ポリシー ロギングを使用して、クラスタのネットワーク ポリシーによって Pod への接続が許可または拒否される時間を記録する。
- GKE Dataplane V2 の仕組みについて確認する。