クラスタ セキュリティのトラブルシューティング


このページでは、Google Kubernetes Engine(GKE)Autopilot クラスタと Standard クラスタのセキュリティ構成に関連する問題を解決する方法について説明します。

RBAC と IAM

認証済みの IAM アカウントでクラスタ内アクションを実行できない

クラスタでアクションを実行しようとしたときに、GKE がアクションを認可する RBAC ポリシーを見つけられないと、次の問題が発生します。GKE は、同じ権限を付与する IAM ポリシーを見つけようとします。失敗した場合、次のようなエラー メッセージが表示されます。

Error from server (Forbidden): roles.rbac.authorization.k8s.io is forbidden:
User "example-account@example-project.iam.gserviceaccount.com" cannot list resource "roles" in
API group "rbac.authorization.k8s.io" in the namespace "kube-system": requires
one of ["container.roles.list"] permission(s).

この問題を解決するには、RBAC ポリシーを使用して、試行するアクションの権限を付与します。たとえば、前のサンプルの問題を解決するには、kube-system Namespace 内の roles オブジェクトに対する list 権限を持つロールを付与します。手順については、ロールベースのアクセス制御を使用してクラスタ内のアクションを認可するをご覧ください。

Workload Identity

Pod が Google Cloud に対して認証できない

アプリケーションが Google Cloud に対する認証を行えない場合は、次の設定が正しく構成されていることを確認してください。

  1. GKE クラスタを含むプロジェクトで IAM Service Account Credentials API が有効になっているかを確認します。

    IAM Credentials API を有効にする

  2. Workload Identity がクラスタで有効になっていることを確かにするには、Workload Identity プールが設定されていることを確認します。

    gcloud container clusters describe CLUSTER_NAME \
        --format="value(workloadIdentityConfig.workloadPool)"
    

    gcloud のデフォルト ゾーンまたはデフォルト リージョンをまだ指定していない場合は、このコマンドの実行時に --region フラグまたは --zone フラグも指定する必要があります。

  3. アプリケーションが動作しているノードプールで GKE メタデータ サーバーが構成されていることを確認します。

    gcloud container node-pools describe NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --format="value(config.workloadMetadataConfig.mode)"
    
  4. Kubernetes サービス アカウントに正しくアノテーションが付けられていることを確認します。

    kubectl describe serviceaccount \
        --namespace NAMESPACE KSA_NAME
    

    出力には、次のようなアノテーションが含まれます。

    iam.gke.io/gcp-service-account: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    
  5. IAM サービス アカウントが正しく構成されていることを確認します。

    gcloud iam service-accounts get-iam-policy \
        GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com
    

    出力には、次のようなバインディングが含まれます。

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]
      role: roles/iam.workloadIdentityUser
    
  6. クラスタ ネットワーク ポリシーを導入している場合は、1.21.0-gke.1000 より前のバージョンの GKE を実行しているクラスタのポート 988 で、127.0.0.1/32 への下り(外向き)が許可されていることを確認します。また、GKE バージョン 1.21.0-gke.1000 以降を実行しているクラスタのポート 988 で、169.254.169.252/32 への下り(外向き)が許可されていることを確認します。GKE Dataplane V2 を実行しているクラスタでは、ポート 80169.254.169.254/32 への下り(外向き)を許可していることを確認します。

    kubectl describe networkpolicy NETWORK_POLICY_NAME
    

Pod の起動時にタイムアウト エラーが発生する

GKE メタデータ サーバーが新しい Pod でリクエストの受信を開始できるようになるまでに数秒かかります。したがって、Pod の有効期間の最初の数秒以内に Workload Identity を使用して認証を試みると、短いタイムアウトが構成されているアプリケーションと Google Cloud クライアント ライブラリで失敗する可能性があります。

タイムアウト エラーが発生した場合は、次のことを試してください。

  • ワークロードが使用する Google Cloud クライアント ライブラリを更新します。
  • 数秒待ってから再試行するようにアプリケーション コードを変更します。
  • Pod のメインコンテナを実行する前に、GKE メタデータ サーバーの準備が完了するまで待機する initContainer をデプロイします。

    たとえば、次のマニフェストは initContainer を含む Pod 用です。

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-with-initcontainer
    spec:
      serviceAccountName: KSA_NAME
      initContainers:
      - image:  gcr.io/google.com/cloudsdktool/cloud-sdk:alpine
        name: workload-identity-initcontainer
        command:
        - '/bin/bash'
        - '-c'
        - |
          curl -sS -H 'Metadata-Flavor: Google' 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token' --retry 30 --retry-connrefused --retry-max-time 60 --connect-timeout 3 --fail --retry-all-errors > /dev/null && exit 0 || echo 'Retry limit exceeded. Failed to wait for metadata server to be available. Check if the gke-metadata-server Pod in the kube-system namespace is healthy.' >&2; exit 1
      containers:
      - image: gcr.io/your-project/your-image
        name: your-main-application-container
    

コントロール プレーンが使用できないため Workload Identity が失敗する

クラスタ コントロール プレーンが使用できない場合、メタデータ サーバーは Workload Identity を返すことができません。メタデータ サーバーを呼び出すと、ステータス コード 500 が返されます。

ログ エクスプローラでは、ログエントリは次のようになります。

dial tcp 35.232.136.58:443: connect: connection refused

これにより、予想どおり、Workload Identity が利用できなくなることがあります。

IP のローテーション、コントロール プレーン VM のアップグレード、クラスタまたはノードプールのサイズ変更などのクラスタ メンテナンス時に、ゾーンクラスタでコントロール プレーンが使用できない場合があります。コントロール プレーンの可用性については、リージョンまたはゾーンのコントロール プレーンの選択をご覧ください。リージョン クラスタに切り替えることで、この問題がなくなります。

Workload Identity が失敗する

なんらかの理由で GKE メタデータ サーバーがブロックされていると、Workload Identity は失敗します。

Istio を使用している場合は、Workload Identity を使用するすべてのワークロードに次のアプリケーション レベルのアノテーションを追加する必要があります。

"traffic.sidecar.istio.io/excludeOutboundIPRanges=169.254.169.254/32"

global.proxy.excludeIPRanges Istio ConfigMap キーを変更して同じ処理を行うこともできます。

gke-metadata-server Pod がクラッシュしている

gke-metadata-server システム DaemonSet Pod により、ノードで Workload Identity を利用できるようになります。Pod は、クラスタ内の Kubernetes サービス アカウントの数に比例してメモリリソースを使用します。

gke-metadata-server Pod のリソース使用量が上限を超えると、次の問題が発生します。kubelet がメモリ不足エラーで Pod を強制排除します。クラスタに 3,000 を超える Kubernetes サービス アカウントがある場合、この問題が発生することがあります。

問題を特定する方法は次のとおりです。

  1. kube-system Namespace でクラッシュしている gke-metadata-server Pod を見つけます。

    kubectl get pods -n=kube-system | grep CrashLoopBackOff
    

    出力は次のようになります。

    NAMESPACE     NAME                        READY     STATUS             RESTARTS   AGE
    kube-system   gke-metadata-server-8sm2l   0/1       CrashLoopBackOff   194        16h
    kube-system   gke-metadata-server-hfs6l   0/1       CrashLoopBackOff   1369       111d
    kube-system   gke-metadata-server-hvtzn   0/1       CrashLoopBackOff   669        111d
    kube-system   gke-metadata-server-swhbb   0/1       CrashLoopBackOff   30         136m
    kube-system   gke-metadata-server-x4bl4   0/1       CrashLoopBackOff   7          15m
    
  2. クラッシュした Pod を調べて、原因がメモリ不足による強制排除であることを確認します。

    kubectl describe pod POD_NAME --namespace=kube-system | grep OOMKilled
    

GKE メタデータ サーバーを機能させるには、クラスタ内のサービス アカウントの数を 3,000 未満に減らします。

DeployPatch 失敗のエラー メッセージが表示され Workload Identity を有効にできない

GKE は、Google Cloud が管理する Kubernetes Engine サービス エージェントを使用して、クラスタ内で Workload Identity が機能できるようにします。Google Kubernetes Engine API を有効にすると、Google Cloud がプロジェクトに対する Kubernetes Engine サービス エージェントのロール(roles/container.serviceAgent)を、このサービス エージェントに自動的に付与します。

サービス エージェントに Kubernetes Engine サービス エージェントのロールがないプロジェクトの Workload Identity を有効にしようとすると、次のようなエラー メッセージが表示され、オペレーションが失敗します。

Error waiting for updating GKE cluster workload identity config: DeployPatch failed

この問題を解決するには、次のことを試してください。

  1. サービス エージェントがプロジェクトに存在し、正しく構成されていることを確認します。

    gcloud projects get-iam-policy PROJECT_ID \
        --flatten=bindings \
        --filter=bindings.role=roles/container.serviceAgent \
        --format="value[delimiter='\\n'](bindings.members)"
    

    PROJECT_ID は、実際の Google Cloud プロジェクト ID に置き換えます。

    サービス エージェントが正しく構成されている場合、出力にはサービス エージェントの完全な ID が表示されます。

    serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
    

    出力にサービス エージェントが含まれていない場合は、Kubernetes Engine サービス エージェントのロールを付与する必要があります。

  2. Google Cloud プロジェクト番号を取得します。

    gcloud projects describe PROJECT_ID \
        --format="value(projectNumber)"
    

    出力は次のようになります。

    123456789012
    
  3. サービス エージェントにロールを付与します。

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com \
        --role=roles/container.serviceAgent \
        --condition=None
    

    PROJECT_NUMBER は、実際の Google Cloud プロジェクトの番号に置き換えます。

Workload Identity をもう一度有効にしてみます。