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

Google Kubernetes Engine(GKE)の Ingress に関する問題により、外部トラフィックまたは内部トラフィックがサービスに到達できない可能性があります。

このドキュメントでは、Ingress クラス、静的 IP アノテーション、証明書の鍵のサイズ、ネットワーク ティアとのインタラクションに関連するエラーの解決策について説明します。

この情報は、GKE で Ingress を使用して公開されたアプリケーションをデプロイして管理するプラットフォーム管理者、運用担当者、アプリケーション デベロッパーを対象としています。 Google Cloud のコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE ユーザーのロールとタスクをご覧ください。

Ingress クラスのアノテーションが正しくない

症状

Ingress を作成するときに、次のエラーが表示されることがあります。

Missing one or more resources. If resource creation takes longer than expected, you might have an invalid configuration.

考えられる原因

Ingress の作成時に、マニフェストで Ingress クラスが正しく構成されていない可能性があります。

解決策

Ingress クラスを指定するには、kubernetes.io/ingress.class アノテーションを使用する必要があります。spec.ingressClassName を使用して GKE Ingress を指定することはできません。

  • 内部アプリケーション ロードバランサをデプロイするには、kubernetes.io/ingress.class: gce-internal アノテーションを使用します。
  • 外部アプリケーション ロードバランサをデプロイするには、kubernetes.io/ingress.class: gce アノテーションを使用します。

静的 IP アドレスのアノテーションが正しくない

症状

静的 IP アドレスを使用するように外部 Ingress を構成すると、次のエラーが表示されることがあります。

Error syncing to GCP: error running load balancer syncing routine: loadbalancer <Name of load balancer> does not exist: the given static IP name <Static IP> doesn't translate to an existing static IP.

考えられる原因

  • Ingress をデプロイする前に静的外部 IP アドレスを作成していない。
  • ロードバランサのタイプに適したアノテーションを使用していません。

解決策

外部 Ingress を構成する場合:

  • Ingress をデプロイする前に、静的外部 IP アドレスを予約します。
  • Ingress リソースにアノテーション kubernetes.io/ingress.global-static-ip-name を使用します。

内部 Ingress を構成する場合:

  • Ingress をデプロイする前に、リージョン静的内部 IP アドレスを予約します。
  • Ingress リソースにアノテーション kubernetes.io/ingress.regional-static-ip-name を使用します。

静的 IP アドレスはすでに使用されています

症状

内部または外部の Ingress リソースをプロビジョニングするために静的 IP アドレスを指定するときに、次のエラーが表示されることがあります。

Error syncing to GCP: error running load balancer syncing
routine: loadbalancer <LB name> does not exist:
googleapi: Error 409: IP_IN_USE_BY_ANOTHER_RESOURCE - IP ''<IP address>'' is already being used by another resource.

考えられる原因

静的 IP アドレスは、別のリソースですでに使用されています。

HTTP を無効にして Google マネージド証明書を使用する際にエラーが発生する

症状

Google マネージド SSL 証明書を構成し、Ingress で HTTP トラフィックを無効にすると、次のエラーが表示されます。

Error syncing to GCP: error running load balancer syncing
routine: loadbalancer <Load Balancer name> does not exist:
googleapi: Error 404: The resource ''projects/<Project>/global/sslPolicies/<Policy name>' was not found, notFound

考えられる原因

Ingress を構成するときに、次のアノテーションを一緒に使用することはできません。

  • networking.gke.io/managed-certificates(Google マネージド証明書を Ingress に関連付ける場合)
  • kubernetes.io/ingress.allow-http: false(HTTP トラフィックを無効にする場合)

解決策

外部アプリケーション ロードバランサのプログラムが完全に作成された後でのみ、HTTP トラフィックを無効にします。Ingress を更新して、マニフェストにアノテーション kubernetes.io/ingress.allow-http: false を追加できます。

内部 Ingress にプロキシ専用サブネットがない

症状

内部アプリケーション ロードバランサ用の Ingress をデプロイすると、次のエラーが表示されることがあります。

Error syncing to GCP: error running load balancer syncing routine:
loadbalancer <LB name> does not exist: googleapi: Error 400: Invalid value for field 'resource.target': 'https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/<Region>/targetHttpsProxies/<Target proxy>'.
An active proxy-only subnetwork is required in the same region and VPC as
the forwarding rule.

考えられる原因

Ingress リソースを作成する前に、プロキシ専用サブネットを作成していない。内部アプリケーション ロードバランサにはプロキシ専用サブネットが必要です。

解決策

内部 Ingress をデプロイする前に、プロキシ専用サブネットを作成します。

SSL 証明書鍵が大きすぎる

症状

ロードバランサの SSL 証明書の鍵のサイズが大きすぎると、次のエラーが表示されることがあります。

Error syncing to GCP: error running load balancer syncing routine: loadbalancer gky76k70-load-test-trillian-api-ingress-fliismmb does not exist: Cert creation failures - k8s2-cr-gky76k70-znz6o1pfu3tfrguy-f9be3a4abbe573f7 Error:googleapi: Error 400: The SSL key is too large., sslCertificateKeyTooLarge

考えられる原因

Google Cloud では SSL 証明書鍵に 2,048 ビットの上限があります。

解決策

SSL 証明書鍵のサイズを 2,048 ビット以下に減らします。

スタンダード ティアで Ingress の作成中にエラーが発生する

症状

プロジェクトのデフォルト ネットワーク階層が Standard に設定されているプロジェクトに Ingress をデプロイすると、次のエラー メッセージが表示されます。

Error syncing to GCP: error running load balancer syncing routine: load balancer <LB Name> does not exist: googleapi: Error 400: STANDARD network tier (the project''s default network tier) is not supported: STANDARD network tier is not supported for global forwarding rule., badRequest

解決策

プロジェクトのデフォルトのネットワーク階層をプレミアムに構成します。

k8s-ingress-svc-acct-permission-check-probe の「Not Found」エラーが想定される

Ingress コントローラは、サービス アカウントの権限を定期的にチェックします プロジェクトからテストリソースを取得して、 Google Cloud この名前は、k8s-ingress-svc-acct-permission-check-probe という名の(実在しない)グローバル BackendServiceGET として表示されます。このリソースは通常は存在していないため、GET リクエストは「not found」を返します。これは想定された動作です。コントローラは、認証の問題により API 呼び出しが拒否されたことを確認しています。同じ名前の BackendService を作成すると、「not found」を返す代わりに GET が成功します。

コンテナ ネイティブのロード バランシングを使用する際のエラー

ネットワーク構成を確認する方法は次のとおりです。以降のセクションでは、コンテナ ネイティブのロード バランシングに関連する特定の問題の解決方法について説明します。

  • ネットワーク エンドポイント グループを一覧取得する方法については、ロード バランシングのドキュメントをご覧ください。

  • サービスの neg-status アノテーションのサービスに対応する NEG の名前とゾーンを確認できます。サービスの仕様を取得するには、次のコマンドを実行します。

    kubectl get svc SVC_NAME -o yaml
    

    metadata:annotations:cloud.google.com/neg-status アノテーションには、サービスの対応する NEG の名前と NEG のゾーンが一覧表示されます。

  • NEG に対応するバックエンド サービスのヘルスは、次のコマンドで確認できます。

    gcloud compute backend-services --project PROJECT_NAME \
        get-health BACKEND_SERVICE_NAME --global
    

    バックエンド サービスは NEG と同じ名前です。

  • サービスのイベントログを出力するには、次のコマンドを実行します。

    kubectl describe svc SERVICE_NAME
    

    サービスの名前文字列には、対応する GKE サービスの名前と名前空間が含まれます。

エイリアス IP を使用したクラスタを作成できない

現象

エイリアス IP を使用したクラスタを作成しようとすると、次のようなエラーが発生することがあります。

ResponseError: code=400, message=IP aliases cannot be used with a legacy network.
考えられる原因

作成しようとしているエイリアス IP 付きのクラスタでレガシー ネットワークも使用している場合、このエラーが発生します。

解決策

エイリアス IP と以前のネットワークを同時に有効にしたクラスタを作成しないでください。エイリアス IP の使用方法については、VPC ネイティブ クラスタを作成するをご覧ください。

トラフィックがエンドポイントに到達しない

現象
502 / 503 エラーが発生するか、接続が拒否されます。
考えられる原因

新しいエンドポイントは、通常ロードバランサへの接続後に到達可能になりますが、そのためにはヘルスチェックにレスポンスを返す必要があります。トラフィックがエンドポイントに到達しない場合、502 エラーが発生することがあります。また、接続が拒否されることもあります。

502 エラーと接続の拒否は SIGTERM を処理しないコンテナが原因である可能性もあります。コンテナが SIGTERM を明示的に処理しない場合は、直ちに終了し、リクエストの処理を停止します。ロードバランサは、終了したコンテナに受信トラフィックを送信し続け、エラーにつながります。

コンテナ ネイティブのロードバランサには、バックエンドのエンドポイントが 1 つだけ含まれます。ローリング アップデート中は、新しいエンドポイントがプログラムされる前に古いエンドポイントがプログラム解除されます。

コンテナ ネイティブのロードバランサのプロビジョニング後、バックエンド Pod が初めて新しいゾーンにデプロイされます。ゾーンに 1 つ以上のエンドポイントがある場合、ロードバランサのインフラストラクチャはゾーンでプログラムされます。 ゾーンに新しいエンドポイントが追加されると、ロードバランサ インフラストラクチャがプログラムされ、サービスの中断が発生します。

解決策

コンテナを構成して SIGTERM を処理し、終了猶予期間中はリクエストへの応答を続行します。デフォルトでは 30 秒です。SIGTERM を受信したときにヘルスチェックが失敗するように Pod を構成します。これにより、エンドポイントのデプログラミング中に、Pod へのトラフィックの送信を停止するようにロードバランサに通知します。

エンドポイントのプログラム解除中に SIGTERM を受け取ったとき、アプリケーションが正常にシャットダウンせず、リクエストへの応答を停止している場合は、preStop フックを使用して SIGTERM を処理し、トラフィックの処理を継続できます。

lifecycle:
  preStop:
    exec:
      # if SIGTERM triggers a quick exit; keep serving traffic instead
      command: ["sleep","60"]

Pod の終了に関する ドキュメントをご覧ください。

ロードバランサのバックエンドにインスタンスが 1 つしかない場合は、新しいインスタンスが完全にプログラムされる前にそのインスタンスを破棄しないようにロールアウト手順を構成してください。Deployment ワークロードが管理するアプリケーション Pod では、 maxUnavailable パラメータが 0 に設定されているロールアウト 手順 を構成することでこれを実現できます。

strategy:
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0

エンドポイントに到達しないトラフィックをトラブルシューティングするには、ファイアウォール ルールで 130.211.0.0/2235.191.0.0/16 の範囲のエンドポイントへの受信 TCP トラフィックが許可されていることを確認します。詳細については、Cloud Load Balancing ドキュメントのヘルスチェックの追加をご覧ください。

プロジェクトのバックエンド サービスを確認します。関連するバックエンド サービスの名前文字列には、対応する GKE サービスの名前と名前空間が含まれます。

gcloud compute backend-services list

バックエンド サービスからバックエンドのヘルス ステータスを取得します。

gcloud compute backend-services get-health BACKEND_SERVICE_NAME

すべてのバックエンドでヘルス ステータスが異常な場合は、ファイアウォール、Ingress、Service のいずれかの構成が不適切である可能性があります。

一部のバックエンドで短期間ヘルス ステータスが異常な場合は、ネットワーク プログラミングのレイテンシが原因である可能性があります。

一部のバックエンドがバックエンド サービスのリストに表示されない場合は、プログラミングのレイテンシが原因である可能性があります。これは、次のコマンドを実行して確認できます。ここで、NEG_NAME はバックエンド サービスの名前です (NEG とバックエンド サービスは同じ名前を共有します)。

gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME

予期されるすべてのエンドポイントが NEG に存在することを確認します。

コンテナ ネイティブのロードバランサによって少数のバックエンド(たとえば 1 つの Pod)が選択される場合、レプリカの数を増やし、GKE クラスタがまたがるすべてのゾーンにバックエンド Pod を分散することを検討してください。これにより、基盤となるロードバランサのインフラストラクチャが完全にプログラムされます。それ以外の場合は、バックエンド Pod を単一のゾーンに制限することを検討してください。

エンドポイントのネットワーク ポリシーを構成する場合は、プロキシ専用サブネットからの上り(内向き)が許可されていることを確認します。

停滞時のロールアウト

現象
更新した Deployment がロールアウトし、最新のレプリカの数が選択されたレプリカの数と一致しません。
考えられる原因

デプロイのヘルスチェックが失敗しています。コンテナ イメージが不適切であるか、ヘルスチェックが正しく構成されていない可能性があります。Pod のローリング置換は、新しく開始した Pod が Pod の readiness ゲートを通過してから行います。これは、Pod がロードバランサのヘルスチェックに応答している場合にのみ発生します。Pod が応答しない場合、またはヘルスチェックが正しく構成されていない場合は、readiness ゲートの条件を満たせず、ロールアウトを続行できません。

kubectl 1.13 以降を使用している場合は、次のコマンドで Pod の readiness ゲートのステータスを確認できます。

kubectl get pod POD_NAME -o wide

READINESS GATES 列を確認します。

この列は、kubectl 1.12 以下には存在しません。READY 状態であるとマークされた Pod は、readiness ゲートに失敗した可能性があります。これを確認するには、次のコマンドを使用します。

kubectl get pod POD_NAME -o yaml

readiness ゲートとそのステータスが出力に一覧表示されます。

解決策

Deployment の Pod の仕様のコンテナ イメージが正しく機能し、ヘルスチェックに応答できることを確認します。ヘルスチェックが正しく構成されていることを確認します。

デグレード モードのエラー

現象

GKE バージョン 1.29.2-gke.1643000 以降では、NEG が更新されると、ログ エクスプローラ でサービスに関して次の警告が表示されることがあります。

Entering degraded mode for NEG <service-namespace>/<service-name>-<neg-name>... due to sync err: endpoint has missing nodeName field
考えられる原因

これらの警告は、EndpointSlice オブジェクトに基づく NEG の更新中に GKE がエンドポイントの構成ミスを検出し、より詳細な計算プロセス(デグレード モード)をトリガーしたことを示します。 GKE は、構成の誤りを修正するか、無効なエンドポイントを NEG の更新から除外することで、引き続きベスト エフォート方式で NEG を更新します。

よくあるエラーには、次のようなものがあります。

  • endpoint has missing pod/nodeName field
  • endpoint corresponds to an non-existing pod/node
  • endpoint information for attach/detach operation is incorrect
解決策

通常、これは一時的な状態が原因で発生するイベントであり、自動的に修正されます。ただし、カスタム EndpointSlice オブジェクトの誤った構成によってイベントが発生した場合は解決されません。構成の誤りを確認するには、サービスに対応する EndpointSlice オブジェクトを調べます。

kubectl get endpointslice -l kubernetes.io/service-name=<service-name>

イベントのエラーに基づいてエンドポイントを検証します。

この問題を解決するには、EndpointSlice オブジェクトを手動で変更する必要があります。 更新によって NEG がトリガーされ、再度更新されます。誤った構成がなくなると、出力は次のようになります。

NEG <service-namespace>/<service-name>-<neg-name>... is no longer in degraded mode

Google マネージド SSL 証明書を使用する際のエラー

このセクションでは、Google マネージド証明書の問題を解決する方法について説明します。

ManagedCertificate と Ingress リソースでイベントを確認する

許可されている証明書の数を超えると、TooManyCertificates の理由を含むイベントが ManagedCertificate に追加されます。ManagedCertificate オブジェクトのイベントは、次のコマンドを使用して確認できます。

kubectl describe managedcertificate CERTIFICATE_NAME

CERTIFICATE_NAME は、ManagedCertificate の名前で置き換えます。

存在しない ManagedCertificate を Ingress に接続すると、MissingCertificate の理由を含むイベントが Ingress に追加されます。次のコマンドを使用して、Ingress でイベントを確認できます。

kubectl describe ingress INGRESS_NAME

INGRESS_NAME は実際の Ingress 名で置き換えます。

ドメインが複数のロードバランサの IP アドレスに解決される場合、マネージド証明書がプロビジョニングされない

ドメインが複数のロードバランサ(複数の Ingress オブジェクト)の IP アドレスに解決される場合は、ManagedCertificate オブジェクトを 1 つ作成して、すべての Ingress オブジェクトに接続する必要があります。ManagedCertificate オブジェクトを複数作成してそれぞれを個別の Ingress に接続すると、認証局がドメインの所有権を確認できず、一部の証明書がプロビジョニングされないことがあります。所有権の確認を成功させるには、ドメイン解決されるすべての IP アドレスの下に証明書が表示されている必要があります。

具体的には、ドメインが IPv4 アドレスと IPv6 アドレスに解決され、それぞれが異なる Ingress オブジェクトで構成されている場合、ManagedCertificate オブジェクトを 1 つ作成し、両方の Ingress に接続します。

Google マネージド証明書と Ingress 間の通信の中断

マネージド証明書は、ingress.gcp.kubernetes.io/pre-shared-cert アノテーションを使用して Ingress と通信します。この通信が中断するのは、たとえば次のような場合です。

  • ingress.gcp.kubernetes.io/pre-shared-cert アノテーションを消去する自動プロセスを実行する場合。
  • Ingress のスナップショットを保存した後、スナップショットから Ingress を削除して復元する場合。その間に ingress.gcp.kubernetes.io/pre-shared-cert アノテーションの SslCertificate リソースが削除された可能性があります。Ingress に接続された証明書がない場合、Ingress は動作しません。

Google マネージド証明書と Ingress 間の通信が中断された場合、ingress.gcp.kubernetes.io/pre-shared-cert アノテーションの内容を削除し、システムによる調整が完了するまで待ちます。再発防止のため、アノテーションが誤って変更または削除されないようにしてください。

Google マネージド証明書の作成時の検証エラー

ManagedCertificate オブジェクトを作成する前に ManagedCertificate 定義を検証します。検証で不合格になると、ManagedCertificate オブジェクトは作成されず、エラー メッセージが出力されます。エラー メッセージとその理由の説明は次のとおりです。

spec.domains in body should have at most 100 items

ManagedCertificate マニフェストで、spec.domains フィールドに 100 を超えるドメインがリストされています。Google マネージド証明書でサポートされるドメインは 100 までです。

spec.domains in body should match '^(([a-zA-Z0-9]+|[a-zA-Z0-9][-a-zA-Z0-9]*[a-zA-Z0-9])\.)+[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]\.?$'

spec.domains フィールドに無効なドメイン名またはワイルドカード ドメイン名が指定されています。ManagedCertificate オブジェクトは、ワイルドカード ドメイン(*.example.com など)をサポートしません。

spec.domains in body should be at most 63 chars long

指定したドメイン名が長すぎます。Google マネージド証明書は最長 63 文字までのドメイン名をサポートします。

Google マネージド証明書の手動更新

新しいドメインの証明書がプロビジョニングされるまで古いドメインの証明書が引き続き機能するように、証明書を手動で更新する手順は次のとおりです。

  1. 新しいドメインに ManagedCertificate を作成します。
  2. カンマ区切りリストを使用して、ManagedCertificate の名前を Ingress の networking.gke.io/managed-certificates アノテーションに追加します。古い証明書名を削除しないでください。
  3. ManagedCertificate が Active になるまで待ちます。
  4. 古い証明書を Ingress から切断し、この証明書を削除します。

ManagedCertificate を作成すると、 Google Cloud が Google マネージド SSL 証明書を作成します。この証明書は更新できません。ManagedCertificate を更新すると、 Google Cloud は Google マネージド SSL 証明書を削除し、再作成します。

GKE クラスタに安全な HTTPS で暗号化された Ingress を提供するには、Ingress の保護の例をご覧ください。

次のステップ