このページでは、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 に対する認証を行えない場合は、次の設定が正しく構成されていることを確認してください。
GKE クラスタを含むプロジェクトで IAM Service Account Credentials API が有効になっているかを確認します。
Workload Identity がクラスタで有効になっていることを確かにするには、Workload Identity プールが設定されていることを確認します。
gcloud container clusters describe CLUSTER_NAME \ --format="value(workloadIdentityConfig.workloadPool)"
gcloud
のデフォルト ゾーンまたはデフォルト リージョンをまだ指定していない場合は、このコマンドの実行時に--region
フラグまたは--zone
フラグも指定する必要があります。アプリケーションが動作しているノードプールで GKE メタデータ サーバーが構成されていることを確認します。
gcloud container node-pools describe NODEPOOL_NAME \ --cluster=CLUSTER_NAME \ --format="value(config.workloadMetadataConfig.mode)"
Kubernetes サービス アカウントに正しくアノテーションが付けられていることを確認します。
kubectl describe serviceaccount \ --namespace NAMESPACE KSA_NAME
出力には、次のようなアノテーションが含まれます。
iam.gke.io/gcp-service-account: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
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
クラスタ ネットワーク ポリシーを導入している場合は、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 を実行しているクラスタでは、ポート80
で169.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 サービス アカウントがある場合、この問題が発生することがあります。
問題を特定する方法は次のとおりです。
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
クラッシュした 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
この問題を解決するには、次のことを試してください。
サービス エージェントがプロジェクトに存在し、正しく構成されていることを確認します。
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 サービス エージェントのロールを付与する必要があります。
Google Cloud プロジェクト番号を取得します。
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
出力は次のようになります。
123456789012
サービス エージェントにロールを付与します。
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 をもう一度有効にしてみます。