Cloud Run for Anthos on Google Cloud のトラブルシューティング

このページでは、一般的な問題に対するトラブルシューティングの方法と解決策を説明します。

Cloud Run for Anthos on Google Cloud のトラブルシューティングで最初に行う作業は、コンテナ イメージをローカルで実行できるか確認することです。

アプリケーションがローカルで実行されていない場合は、その原因を突き止め、問題を修正する必要があります。デプロイされたプロジェクトをデバッグするには、Cloud Logging を使用します。

Cloud Run for Anthos on Google Cloud のトラブルシューティングについては、次のセクションで問題の解決方法をご覧ください。

コマンドラインの出力を確認する

gcloud コマンドライン ツールを使用する場合、コマンドの出力で結果を確認します。たとえば、デプロイが失敗した場合、失敗の理由を説明するエラー メッセージが表示されます。

デプロイが失敗する原因の多くは、マニフェストの構成ミスかコマンドの誤りです。次の出力の場合、ルート トラフィックの割合が合計で 100 になるように構成する必要があります。

Error from server (InternalError): error when applying patch:</p><pre>{"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"serving.knative.dev/v11\",\"kind\":\"Route\",\"metadata\":{\"annotations\":{},\"name\":\"route-example\",\"namespace\":\"default\"},\"spec\":{\"traffic\":[{\"configurationName\":\"configuration-example\",\"percent\":50}]}}\n"}},"spec":{"traffic":[{"configurationName":"configuration-example","percent":50}]}}
to:
&{0xc421d98240 0xc421e77490 default route-example STDIN 0xc421db0488 264682 false}
for: "STDIN": Internal error occurred: admission webhook "webhook.knative.dev" denied the request: mutation failed: The route must have traffic percent sum equal to 100.
ERROR: Non-zero return code '1' from command: Process exited with status 1

サービスのログを確認する

Cloud Console の Cloud Logging または Cloud Run for Anthos on Google Cloud ページで、リクエストログとコンテナログを確認できます。詳細については、ログの記録と表示をご覧ください。

Cloud Logging を使用する場合、フィルタするリソースは Kubernetes コンテナです。

サービスのステータスを確認する

デプロイされた Cloud Run for Anthos on Google Cloud サービスのステータスを取得するには、次のコマンドを実行します。

gcloud kuberun core services describe SERVICE

--format yaml(status) または --format json(status) を追加すると、完全なステータスを取得できます。次に例を示します。

gcloud kuberun core services describe SERVICE --format 'yaml(status)'

status の条件が、失敗の原因を特定する際に役立ちます。条件には、TrueFalseUnknown などがあります。

  • Ready: True は、サービスが構成され、トラフィックを受信できる状態であることを示します。
  • ConfigurationReady: True は、基盤となる構成の準備が完了していることを示します。False または「Unknown」の場合、最新のリビジョンのステータスを表示します。
  • RoutesReady: True は、基盤となるルートの準備が完了していることを示します。False または「Unknown」の場合は、ルートのステータスを表示します。

ステータス条件の詳細については、Knative のエラーシグナルをご覧ください。

ルートのステータスを確認する

Cloud Run for Anthos on Google Cloud サービスは、サービスのリビジョンに対する現在のルーティング状態を表すルートを管理します。

ルート全体のステータスを確認するには、サービスのステータスを確認します。

gcloud kuberun core services describe SERVICE --format 'yaml(status)'

statusRoutesReady 条件で、ルートのステータスを確認できます。

ルートのステータスをさらに診断するには、次のコマンドを実行します。

kubectl get route SERVICE -o yaml

status の条件は、失敗の理由を表しています。まとめると次のようになります。

  • Ready は、サービスが構成され、利用可能なバックエンドがあるかどうかを示します。true の場合、ルートは正しく構成されています。

  • AllTrafficAssigned は、サービスが適切に構成され、使用可能なバックエンドがあるかどうかを示します。この条件の statusTrue でない場合:

    • サービスのリビジョン間で分割されたトラフィックの合計が 100% になるかどうかを確認します。

      gcloud kuberun core services describe SERVICE

      そうでない場合は、gcloud kuberun core services update-traffic コマンドを使用してトラフィック分割を調整します。

    • トラフィックを受信しているリビジョンについて、リビジョンのステータスを確認します。

  • IngressReady は Ingress の準備が完了しているかどうかを示します。この条件の statusTrue でない場合は、Ingress のステータスを確認します。

  • CertificateProvisioned は、Knative 証明書がプロビジョニングされたかどうかを示します。この条件の statusTrue ではない場合、マネージド TLS の問題のトラブルシューティングを行います。

ステータス条件の詳細については、Knative のエラー条件とレポートをご覧ください。

Ingress のステータスを確認する

Cloud Run for Anthos on Google Cloud は、ロードバランサの Kubernetes Service(istio-ingress)を使用して、クラスタの外部からのトラフィックを処理します。

Ingress の外部 IP アドレスを取得するには、次のコマンドを使用します。

kubectl get svc istio-ingress -n gke-system

EXTERNAL-IPpending の場合は、後述の EXTERNAL-IP が長時間 pending になっているをご覧ください。

リビジョンのステータスを確認する

Cloud Run for Anthos on Google Cloud サービスの最新リビジョンを入手するには、次のコマンドを実行します。

gcloud run services describe SERVICE --format='value(status.latestCreatedRevisionName)'

特定の Cloud Run for Anthos on Google Cloud のリビジョンのステータスを取得するには、次のコマンドを実行します。

gcloud kuberun core revisions describe REVISION

完全なステータスを取得するには、--format yaml(status) または --format json(status) を追加します。

gcloud kuberun core revisions describe REVISION --format yaml(status)

status の条件が失敗の理由を表しています。まとめると次のようになります。

  • Ready は、ランタイム リソースが使用可能かどうかを示します。これが true の場合、リビジョンは正しく構成されています。
  • ResourcesAvailable は、基盤となる Kubernetes リソースがプロビジョニングされたかどうかを示します。この条件の statusTrue でない場合は、Pod のステータスを確認してください。
  • ContainerHealthy は、リビジョン準備チェックが完了したかどうかを示します。この条件の statusTrue でない場合は、Pod のステータスを確認してください。
  • Active は、リビジョンがトラフィックを受信しているかどうかを示します。

次のいずれかの条件の statusTrue ではない場合は、Pod のステータスを確認してください。

Pod のステータスを確認する

すべてのデプロイのポッドを取得するには:

kubectl get pods

ポッドの一覧とステータスの概要が表示されます。例:

NAME                                                      READY     STATUS             RESTARTS   AGE
configuration-example-00001-deployment-659747ff99-9bvr4   2/2       Running            0          3h
configuration-example-00002-deployment-5f475b7849-gxcht   1/2       CrashLoopBackOff   2          36s

いずれかを選択して次のコマンドを使用すると、status の詳細情報が表示されます。conditionscontainerStatuses などのフィールドに重要な情報が含まれます。

kubectl get pod POD-NAME -o yaml

EXTERNAL-IP が長時間 <pending> になっている

クラスタの作成後すぐに外部 IP アドレスが取得されず、外部 IP が pending と表示される場合があります。たとえば、次のコマンドを呼び出すと、このような状況になることがあります。

Istio Ingress Gateway の外部 IP を取得するには:

kubectl get svc istio-ingress -n gke-system

次のような出力が生成されます。

NAME            TYPE           CLUSTER-IP     EXTERNAL-IP  PORT(S)
istio-ingress   LoadBalancer   XX.XX.XXX.XX   pending     80:32380/TCP,443:32390/TCP,32400:32400/TCP

ロードバランサの EXTERNAL-IP は、使用する必要がある IP アドレスです。

この場合、Google Cloud の外部 IP アドレスの割り当てが上限に達している可能性があります。次の呼び出しを行うと、考えられる原因を確認できます。

kubectl describe svc istio-ingress -n gke-system

これにより、次のような出力が生成されます。

Name:                     istio-ingress
Namespace:                gke-system
Labels:                   addonmanager.kubernetes.io/mode=Reconcile
                          app=istio-ingress
                          chart=gateways-1.0.3
                          heritage=Tiller
                          istio=ingress-gke-system
                          k8s-app=istio
                          kubernetes.io/cluster-service=true
                          release=istio
Annotations:              kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"addonmanager.kubernetes.io/mode":"Reconcile","app":"istio-ingressgateway","...
Selector:                 app=ingressgateway,istio=ingress-gke-system,release=istio
Type:                     LoadBalancer
IP:                       10.XX.XXX.XXX
LoadBalancer Ingress:     35.XXX.XXX.188
Port:                     http2  80/TCP
TargetPort:               80/TCP
NodePort:                 http2  31380/TCP
Endpoints:                XX.XX.1.6:80
Port:                     https  443/TCP
TargetPort:               443/TCP
NodePort:                 https  3XXX0/TCP
Endpoints:                XX.XX.1.6:XXX
Port:                     tcp  31400/TCP
TargetPort:               3XX00/TCP
NodePort:                 tcp  3XX00/TCP
Endpoints:                XX.XX.1.6:XXXXX
Port:                     tcp-pilot-grpc-tls  15011/TCP
TargetPort:               15011/TCP
NodePort:                 tcp-pilot-grpc-tls  32201/TCP
Endpoints:                XX.XX.1.6:XXXXX
Port:                     tcp-citadel-grpc-tls  8060/TCP
TargetPort:               8060/TCP
NodePort:                 tcp-citadel-grpc-tls  31187/TCP
Endpoints:                XX.XX.1.6:XXXX
Port:                     tcp-dns-tls  853/TCP
TargetPort:               XXX/TCP
NodePort:                 tcp-dns-tls  31219/TCP
Endpoints:                10.52.1.6:853
Port:                     http2-prometheus  15030/TCP
TargetPort:               XXXXX/TCP
NodePort:                 http2-prometheus  30944/TCP
Endpoints:                10.52.1.6:15030
Port:                     http2-grafana  15031/TCP
TargetPort:               XXXXX/TCP
NodePort:                 http2-grafana  31497/TCP
Endpoints:                XX.XX.1.6:XXXXX
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason                Age                  From                Message
  ----    ------                ----                 ----                -------
  Normal  EnsuringLoadBalancer  7s (x4318 over 15d)  service-controller  Ensuring load balancer

IN_USE_ADDRESSES 割り当てを超過したことを示す項目が出力に含まれている場合は、Google Cloud Console の [IAM と管理] ページへ移動して、追加の割り当てをリクエストしてください。

外部 IP アドレスが割り当てられるまで、ゲートウェイは再試行を繰り返します。これには数分かかることがあります。

マネージド TLS の問題のトラブルシューティング

マネージド TLS 証明書機能の一般的な問題を解決するには、以下のトラブルシューティング手順を確認してください。

特定のドメイン マッピングのステータスを確認する

特定のドメイン マッピングのステータスを確認するには:

  1. 次のコマンドを実行します。

    gcloud kuberun core domain-mappings describe DOMAIN --namespace NAMESPACE

    次のように置き換えます。

    • DOMAIN は、使用しているドメインの名前に置き換えます。
    • NAMESPACE は、ドメイン マッピングに使用する Namespace に置き換えます。
  2. このコマンドからの yaml の結果で、CertificateProvisioned フィールドの条件を確認して、エラーの性質を判断します。

  3. エラーが表示される場合は、次の表のいずれかのエラーと一致するはずです。表の指示に従って問題を解決してください。

ユーザー構成エラー

エラーコード 詳細なメッセージ トラブルシューティングの手順
DNSErrored DNS record is not configured correctly. Need to map domain [XXX] to IP XX.XX.XX.XX 指定された手順に従って、DNS レコードを正しく構成してください。
RateLimitExceeded acme: urn:ietf:params:acme:error:rateLimited: Error creating new order

:: too many certificates already issued for exact set of domains:

test.example.com:

see https://letsencrypt.org/docs/rate-limits/

Let's Encrypt に連絡して、そのホストの証明書の割り当てを増やしてください。
InvalidDomainMappingName DomainMapping name %s cannot be the same as Route URL host %s. DomainMapping の名前は、マップ先の Route のホストと同一にすることはできません。DomainMapping の名前には別のドメインを使用してください。
ChallengeServingErrored システムが HTTP01 リクエストを処理できませんでした。 このエラーは、istio-ingress サービスが Let's Encrypt からのリクエストに対応してドメインの所有権を確認できない場合に発生します。
  1. Virtual Private Cloud を使用せずに、公共のインターネットから istio-ingress サービスにアクセスできることを確認します。
  2. istio-ingress サービスが DOMAIN が検証されているドメインである URL http://DOMAIN/.well-known/acme-challenge/... からのリクエストを受け付けることを確認します。

システムエラー

エラーコード 詳細なメッセージ トラブルシューティングの手順
OrderErrored

AuthzErrored

ChallengeErrored

この 3 種類のエラーは、Let's Encrypt によるドメイン所有権の確認が失敗した場合に発生します。

通常、これらのエラーは一時的なエラーであり、Cloud Run for Anthos によって再試行されます。

再試行の遅延時間は、最小 8 秒から最大 8 時間まで指数関数的に変動します。

このエラーを手動で再試行する場合は、失敗した Order を手動で削除します。

kubectl delete order DOMAIN -n NAMESPACE

ACMEAPIFailed この種類のエラーは、Cloud Run for Anthos による Let's Encrypt の呼び出しが失敗したときに発生します。通常は一時的なエラーであり、Cloud Run for Anthos によって再試行されます。

このエラーを手動で再試行する場合は、失敗した Order を手動で削除します。

kubectl delete order DOMAIN -n NAMESPACE

UnknownErrored 不明なシステムエラーを示しています。GKE クラスタではめったに発生しません。このエラーが表示された場合は、Cloud サポートに問い合わせて、デバッグの支援を依頼してください。

Order ステータスを確認する

Order ステータスは、Let's Encrypt との対話プロセスを記録するため、Let's Encrypt に関連する問題のデバッグに使用できます。必要に応じて、次のコマンドを実行して Order ステータスを確認します。

kubectl get order DOMAIN -n NAMESPACE -oyaml

次のように置き換えます。

  • DOMAIN は、使用しているドメインの名前に置き換えます。
  • NAMESPACE は、ドメイン マッピングに使用する Namespace に置き換えます。

Order が成功した場合は、結果に発行された証明書とその他の情報が含まれます。

Let's Encrypt の割り当ての超過

DomainMapping のステータスを確認します。次のように、Let's Encrypt の割り当てを超過すると、DomainMapping にエラー メッセージが表示されます。

acme: urn:ietf:params:acme:error:rateLimited: Error creating new order
:: too many certificates already issued for exact set of domains:
test.example.com:
see https://letsencrypt.org/docs/rate-limits/'

証明書の割り当てを増やすには、Let's Encrypt のレート制限に関するドキュメントをご覧ください。

Order のタイムアウト

証明書を取得できない場合、Order オブジェクトは 20 分後にタイムアウトします。

  1. ドメイン マッピングのステータスを確認します。タイムアウトした場合は、ステータス出力で次のようなエラー メッセージを探します。

    order (test.example.com) timed out (20.0 minutes)
  2. タイムアウトの問題の一般的な原因は、使用しているドメインを gke-system の下にある istio-ingress サービスの IP アドレスにマッピングするように DNS レコードが適切に構成されていないことです。次のコマンドを実行して DNS レコードを確認します。

    host DOMAIN
  3. 次のコマンドを実行して、gke-system の下にある istio-ingress サービスの外部 IP アドレスを確認します。

    kubectl get svc istio-ingress -n gke-system

    ドメインの外部 IP アドレスが上り(内向き)IP アドレスと一致しない場合は、DNS レコードを再構成して正しい IP アドレスにマッピングします。

  4. (更新された)DNS レコードが有効になった後、次のコマンドを実行して Order オブジェクトを削除し、TLS 証明書の要求プロセスを再度トリガーします。

    kubectl delete order DOMAIN -n NAMESPACE

    次のように置き換えます。

    • DOMAIN は、使用しているドメインの名前に置き換えます。
    • NAMESPACE は、使用する Namespace に置き換えます。

承認エラー

承認エラーは、DNS レコードが時間内にグローバルに伝播されない場合に発生することがあります。その結果、Let's Encrypt はドメインの所有権の検証に失敗します。

  1. Order ステータスを確認します。ステータス acmeAuthorizations フィールドで authz リンクを確認します。URL は次のようになります。

    https://acme-v02.api.letsencrypt.org/acme/authz-v3/1717011827
  2. リンクを開きます。次のようなメッセージが表示される場合があります。

    urn:ietf:params:acme:error:dns

    この問題は、DNS の不完全な伝播が原因です。

  3. DNS の伝播エラーを解決するには、次の手順を行います。

    1. 次のコマンドを実行して、gke-system の下の istio-ingress サービスの外部 IP を取得します。
      kubectl get svc istio-ingress -n gke-system
    2. 次のコマンドを実行して、ドメインの DNS レコードを確認します。

      host DOMAIN

      DNS レコードの IP アドレスが gke-system の下の istio-ingress サービスの外部 IP と一致しない場合は、ユーザーのドメインを外部 IP にマッピングするように DNS レコードを構成します。

    3. (更新された)DNS レコードが有効になった後、次のコマンドを実行して Order オブジェクトを削除し、TLS 証明書の要求プロセスを再度トリガーします。

      kubectl delete order DOMAIN -n NAMESPACE

    次のように置き換えます。

    • DOMAIN は、使用しているドメインの名前に置き換えます。
    • NAMESPACE は、ドメイン マッピングに使用する Namespace に置き換えます。

限定公開クラスタのデプロイ失敗: Webhook エラーの呼び出しに失敗。

限定公開クラスタへのデプロイが次のメッセージで失敗した場合、ファイアウォールが正しく設定されていない可能性があります。

Error: failed calling webhook "webhook.serving.knative.dev": Post
https://webhook.knative-serving.svc:443/?timeout=30s: context deadline exceeded (Client.Timeout
exceeded while awaiting headers)

限定公開クラスタへのデプロイをサポートするために必要なファイアウォールの変更については、限定公開クラスタでのデプロイの有効化をご覧ください。

サービス レポートのステータスが IngressNotConfigured になる

サービス ステータスに IngressNotConfigured が表示される場合は、gke-system Namespace で istio-pilot Deployment を再起動する必要があります。kubernetes 1.14 で頻繁に見られるこのエラーは、istio_pilotVirtualServices を調整して Envoy 構成を Ingress ゲートウェイに push する準備が整う前にサービスが作成された場合に発生する可能性があります。

この問題を解決するには、次のようなコマンドを使用して Deployment をスケールインし、再度スケールアウトします。

kubectl scale deployment istio-pilot -n gke-system --replicas=0
kubectl scale deployment istio-pilot -n gke-system --replicas=1

リクエスト数とリクエストのレイテンシの指標がない

Workload Identity を有効にしていて、サービスで使用するサービス アカウントに特定の権限が付与されていない場合、サービスはリビジョン リクエスト数とリクエストのレイテンシの指標をレポートしないことがあります。

この問題を修正するには、Workload Identity を使用したクラスタでの指標の有効化セクションの手順を行います。

カスタム ドメインで WebSocket を使用する

デフォルトでは、カスタム ドメイン マッピングに対する WebSocket は無効になっています。

カスタム ドメインで Websocket を有効にするには、次のコマンドを実行して allow_connect: true で Istio EnvoyFilter オブジェクトを作成します。

cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: allowconnect-cluser-local-gateway
  namespace: gke-system
spec:
  workloadSelector:
    labels:
      app: cluster-local-gateway
  configPatches:
  - applyTo: NETWORK_FILTER
    match:
      listener:
        portNumber: 80
        filterChain:
          filter:
            name: "envoy.http_connection_manager"
    patch:
      operation: MERGE
      value:
        typed_config:
          "@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager"
          http2_protocol_options:
            allow_connect: true
EOF