このページでは、Google Kubernetes Engine(GKE)Autopilot クラスタと Standard クラスタのセキュリティ構成に関連する問題を解決する方法について説明します。
さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。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 Federation for GKE
Pod が Google Cloud で認証されない
アプリケーションが Google Cloud で認証されない場合は、次の設定が正しく構成されていることを確認してください。
GKE クラスタを含むプロジェクトで IAM Service Account Credentials API が有効になっていることを確認します。
Workload Identity プールが設定されていることを確認して、クラスタで GKE 用 Workload Identity 連携が有効になっていることを確認します。
gcloud container clusters describe CLUSTER_NAME \ --format="value(workloadIdentityConfig.workloadPool)"
CLUSTER_NAME
は GKE クラスタの名前に置き換えます。gcloud
のデフォルト ゾーンまたはデフォルト リージョンをまだ指定していない場合は、このコマンドの実行時に--region
フラグまたは--zone
フラグも指定する必要があります。アプリケーションが動作しているノードプールで GKE メタデータ サーバーが構成されていることを確認します。
gcloud container node-pools describe NODEPOOL_NAME \ --cluster=CLUSTER_NAME \ --format="value(config.workloadMetadataConfig.mode)"
次のように置き換えます。
NODEPOOL_NAME
は、ノードプールの名前に置き換えます。CLUSTER_NAME
は GKE クラスタの名前に置き換えます。
Kubernetes サービス アカウントにアノテーションが正しく設定されていることを確認します。
kubectl describe serviceaccount \ --namespace NAMESPACE KSA_NAME
次のように置き換えます。
NAMESPACE
は、GKE クラスタの Namespace に置き換えます。KSA
は、Kubernetes サービス アカウントの名前に置き換えます。
出力には、次のようなアノテーションが含まれているはずです。
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
NETWORK_POLICY_NAME
は、GKE ネットワーク ポリシーの名前に置き換えます。
IAM サービス アカウントのアクセスが拒否される
IAM ロール バインディングを追加した直後は、Pod が Workload Identity Federation for GKE を使用してリソースにアクセスできない場合があります。IAM 許可ポリシー、ロール バインディング、Kubernetes Pod などのリソースが同時に作成されるデプロイ パイプラインや宣言型の Google Cloud 構成では、アクセス障害が発生する可能性が高くなります。Pod ログに次のエラー メッセージが表示されます。
HTTP/403: generic::permission_denied: loading: GenerateAccessToken("SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com", ""): googleapi: Error 403: Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist).
このエラーは、IAM のアクセス権の変更の伝播が原因で発生することがあります。つまり、ロールの付与などのアクセス権の変更がシステム全体に伝播されるまでに時間がかかるということです。ロールの付与の場合、通常は反映に 2 分ほどかかりますが、7 分以上かかることもあります。詳細については、アクセス権の変更の伝播をご覧ください。
このエラーを解決するには、Pod が作成された後、Google Cloud リソースにアクセスする前に遅延を追加することを検討してください。
DNS 解決に関する問題
一部の Google Cloud クライアント ライブラリは、DNS 名 metadata.google.internal
を解決することで GKE と Compute Engine のメタデータ サーバーに接続するように構成されています。これらのライブラリの場合、Google Cloud サービスに対するワークロードの認証には、正常なクラスタ内の DNS 解決が重要な依存関係となります。
この問題を検出する方法は、デプロイしたアプリケーションの詳細(ロギング構成など)によって異なります。次のようなエラー メッセージがないか確認します。
- GOOGLE_APPLICATION_CREDENTIALS の構成を求めるエラー メッセージ、または
- Google Cloud サービスへのリクエストが、認証情報がリクエストになかったために拒否されたことを示すエラー メッセージ。
metadata.google.internal
の DNS 解決で問題が発生した場合は、環境変数 GCE_METADATA_HOST
を 169.254.169.254
に設定することで、一部の Google Cloud クライアント ライブラリで DNS 解決をスキップするように指示できます。
apiVersion: v1
kind: Pod
metadata:
name: example-pod
namespace: default
spec:
containers:
- image: debian
name: main
command: ["sleep", "infinity"]
env:
- name: GCE_METADATA_HOST
value: "169.254.169.254"
これは、Google Cloud コンピューティング プラットフォームでメタデータ サービスを常に使用できる、ハードコードされた IP アドレスです。
サポートされている Google Cloud ライブラリ:
Pod の起動時にタイムアウト エラーが発生する
GKE メタデータ サーバーが新しい Pod でリクエストの受信を開始できるようになるまでに数秒かかります。Pod が有効になってから最初の数秒間に GKE 用 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 Federation for GKE が失敗する
クラスタ コントロール プレーンが利用できない場合、メタデータ サーバーは Workload Identity Federation for GKE を返すことができません。メタデータ サーバーを呼び出すと、ステータス コード 500 が返されます。
ログ エクスプローラに、次のようなログエントリが表示されます。
dial tcp 35.232.136.58:443: connect: connection refused
この動作により、GKE 用 Workload Identity 連携が使用できなくなります。
IP のローテーション、コントロール プレーン VM のアップグレード、クラスタまたはノードプールのサイズ変更などのクラスタ メンテナンス時に、ゾーンクラスタでコントロール プレーンが使用できない場合があります。コントロール プレーンの可用性については、リージョンまたはゾーンのコントロール プレーンの選択をご覧ください。リージョン クラスタに切り替えると、この問題は解消されます。
Istio を使用するクラスタで Workload Identity Federation for GKE の認証が失敗する
なんらかの理由で GKE メタデータ サーバーがブロックされている場合、Workload Identity Federation for GKE の認証は失敗します。
Istio または Cloud Service Mesh を使用している場合は、Workload Identity Federation for GKE を使用するすべてのワークロードに次の Pod レベルのアノテーションを追加して、リダイレクトから IP を除外します。
traffic.sidecar.istio.io/excludeOutboundIPRanges: 169.254.169.254/32
global.proxy.excludeIPRanges
Istio ConfigMap キーを変更して同じ処理を行うことができます。
また、GKE 用 Workload Identity 連携を使用するすべてのワークロードに次の Pod レベルのアノテーションを追加して、サイドカーの準備が整うまでアプリケーション コンテナの起動を遅らせることもできます。
proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
global.proxy.holdApplicationUntilProxyStarts
Istio ConfigMap キーを変更して同じ処理を行うことができます。
gke-metadata-server
Pod がクラッシュしている
gke-metadata-server
システム DaemonSet Pod により、ノードで GKE 用 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
POD_NAME
は、確認する Pod の名前に置き換えます。
GKE メタデータ サーバーを機能させるには、クラスタ内のサービス アカウントの数を 3,000 未満に減らします。
DeployPatch 失敗のエラー メッセージが表示され、Workload Identity Federation for GKE を有効にできない
GKE は、Google Cloud が管理する Kubernetes Engine サービス エージェントを使用して、クラスタ内の GKE 用 Workload Identity 連携が機能できるようにします。Google Kubernetes Engine API を有効にすると、Google Cloud がプロジェクトに対する Kubernetes Engine サービス エージェントのロール(roles/container.serviceAgent
)を、このサービス エージェントに自動的に付与します。
サービス エージェントに Kubernetes Engine サービス エージェントのロールがないプロジェクトのクラスタで GKE 用 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 プロジェクトの番号に置き換えます。GKE 用 Workload Identity 連携をもう一度有効にしてみます。