このトピックでは、GKE on AWS ワークロードの Workload Identity を有効にして AWS リソースへのアクセスを制御する方法について説明します。
Google Cloud Identity and Access Management(IAM)アカウントで Workload Identity を使用して GCP リソースへのアクセスを制御する方法については、Google Cloud での Workload Identity の使用 をご覧ください。
概要
Workload Identity は、AWS IAM 権限を使用して、クラウド リソースへのアクセスを制御します。ワークロード ID を使用すると、各ワークロードに異なる IAM のロールを割り当てることができます。権限をきめ細かく制御することで、最小権限の原則に準拠できます。ワークロード ID を使用しない場合は、GKE on AWS ノードに AWS IAM ロールを割り当て、ノード上のすべてのワークロードにノード自体と同じ権限を付与する必要があります。
クラスタのワークロード ID を有効にするには次の操作を行います。以下の手順は、操作を行う管理者のロールごとにグループ化されます。
クラスタ管理者
- OIDC 検出データを格納する Cloud Storage バケットを作成します。
- そのバケットから読み取るための Identity and Access Management ロールを作成します。
- ワークロード ID を有効にしてユーザー クラスタを作成します。
- 作成時に Pod にワークロード ID 認証情報を適用する Webhook をクラスタに作成します。Webhook を使用しない場合は、Pod に環境変数を手動で設定できます。
- AWS OIDC プロバイダを構成します。
- AWS IAM のロールとポリシーを作成します。
- Kubernetes サービス アカウントを作成し、AWS ポリシーをバインドします。
前提条件
このドキュメントの手順を完了するには、以下の設定が必要です。
- GKE on AWS 管理サービス。
1.17.9 以降の Kubernetes バージョンを実行しているユーザー クラスタ。
以下の権限とツール。
権限
ワークロード ID を有効にしてクラスタを作成するには、次の権限が必要です。
Google Cloud
- 均一なバケットレベルのアクセスを有効にして、一般公開可能な Cloud Storage バケットを作成します。
management-sa@PROJECT_NAME.iam.gserviceaccount.com
の読み取り / 書き込み権限をバケットに付与します。
AWS
- AWS OIDC プロバイダを作成します。
- AWS IAM のロールを作成します。
ツール
ローカルマシンに jq
ツールをインストールすることをおすすめします。
OIDC ディスカバリ バケットを作成する
このセクションは、クラスタ管理者を対象としています。
ユーザー クラスタは、一般公開されている Cloud Storage バケットに OIDC ディスカバリ データを保存する必要があります。バケットには OIDC ディスカバリ構成と公開鍵が格納されています。AWS は、コンテンツを使用してユーザー クラスタからのリクエストを認証します。
バケットには次の属性を持たせる必要があります。
- 一般公開されること。
- 均一なバケットレベルのアクセスが有効になっていること。
上記の属性を持つバケットがない場合は、次の gsutil
コマンドを使用してバケットを作成します。
BUCKET=BUCKET_NAME
gsutil mb -b on gs://${BUCKET}
gsutil iam ch allUsers:objectViewer gs://${BUCKET}
BUCKET_NAME
は、新しいバケット名に置き換えます。
管理サービス アカウントに権限を付与する
GKE on AWS 管理サービス用の Identity and Access Management サービス アカウントには、オブジェクトの読み取りとこのバケットへのオブジェクト書き込みを行うための権限が必要です。
次の
gsutil
コマンドを使用して、管理サービス アカウントに権限を付与します。MANAGEMENT_SA=management-sa@PROJECT_NAME.iam.gserviceaccount.com gsutil iam ch serviceAccount:${MANAGEMENT_SA}:admin gs://${BUCKET}
PROJECT_NAME
は、Google Cloud プロジェクトに置き換えます。このバケットの管理権限を含む新しい IAM ロールを作成します。ロールを作成するには、まず、ロール定義をファイルに保存し、ロールを作成して管理サービス アカウントにバインドします。
これらの手順を完了するには、次のコマンドを実行します。
cat << EOF > anthos-oidc-role.yaml title: anthosAwsOidcStorageAdmin description: permissions to manage the OIDC buckets stage: GA includedPermissions: - storage.buckets.get EOF gcloud iam roles create anthosAwsOidcStorageAdmin --project=PROJECT_NAME \ --file=anthos-oidc-role.yaml gcloud projects add-iam-policy-binding \ PROJECT_NAME \ --member=serviceAccount:${MANAGEMENT_SA} \ --role=projects/PROJECT_NAME/roles/anthosAwsOidcStorageAdmin
PROJECT_NAME
は、Google Cloud プロジェクトに置き換えます。Google Cloud CLI によって、ポリシー バインディングが作成されたことを確認できます。
ユーザー クラスタの作成
このセクションは、クラスタ管理者を対象としています。
ワークロード ID を有効にしてユーザー クラスタを作成する
OIDC 検出バケットの詳細を含むユーザー クラスタを作成します。この情報は、AWSCluster
の spec.controlPlane.workloadIdentity.oidcDiscoveryGCSBucket
フィールドに設定します。
この例では、AWSCluster
CRD と AWSNodePool
CRD からクラスタを手動で作成します。
GKE on AWS 構成のディレクトリに移動します。このディレクトリは、管理サービスをインストールしたときに作成したものです。
cd anthos-aws
anthos-aws
ディレクトリからanthos-gke
を使用して、コンテキストを管理サービスに切り替えます。cd anthos-aws anthos-gke aws management get-credentials
テキスト エディタを開き、次の
AWSCluster
定義をcustom-cluster.yaml
という名前のファイルにコピーします。apiVersion: multicloud.cluster.gke.io/v1 kind: AWSCluster metadata: name: CLUSTER_NAME spec: region: AWS_REGION networking: vpcID: VPC_ID podAddressCIDRBlocks: POD_ADDRESS_CIDR_BLOCKS serviceAddressCIDRBlocks: SERVICE_ADDRESS_CIDR_BLOCKS ServiceLoadBalancerSubnetIDs: SERVICE_LOAD_BALANCER_SUBNETS controlPlane: version: CLUSTER_VERSION # Latest version is 1.25.5-gke.2100 instanceType: AWS_INSTANCE_TYPE keyName: SSH_KEY_NAME subnetIDs: - CONTROL_PLANE_SUBNET_IDS securityGroupIDs: - CONTROL_PLANE_SECURITY_GROUPS iamInstanceProfile: CONTROL_PLANE_IAM_ROLE rootVolume: sizeGiB: ROOT_VOLUME_SIZE volumeType: ROOT_VOLUME_TYPE # Optional iops: ROOT_VOLUME_IOPS # Optional kmsKeyARN: ROOT_VOLUME_KEY # Optional etcd: mainVolume: sizeGiB: ETCD_VOLUME_SIZE volumeType: ETCD_VOLUME_TYPE # Optional iops: ETCD_VOLUME_IOPS # Optional kmsKeyARN: ETCD_VOLUME_KEY # Optional databaseEncryption: kmsKeyARN: ARN_OF_KMS_KEY hub: # Optional membershipName: ANTHOS_CONNECT_NAME cloudOperations: # Optional projectID: YOUR_PROJECT location: GCP_REGION enableLogging: ENABLE_LOGGING enableMonitoring: ENABLE_MONITORING workloadIdentity: # Optional oidcDiscoveryGCSBucket: WORKLOAD_IDENTITY_BUCKET
以下を置き換えます。
- CLUSTER_NAME: クラスタの名前。
AWS_REGION: クラスタが稼働している AWS リージョン。
VPC_ID: クラスタが稼働している VPC の ID。
POD_ADDRESS_CIDR_BLOCKS: クラスタの Pod で使用される IPv4 アドレスの CIDR 範囲。現時点では 1 つの範囲のみがサポートされています。この範囲は、ネットワークから到達可能なサブネットと重複してはなりません。複数の異なる AWSCluster オブジェクト間では、同じ範囲を使用できます。例:
10.2.0.0/16
SERVICE_ADDRESS_CIDR_BLOCKS: クラスタの Service で使用される IPv4 アドレスの範囲。現時点では 1 つの範囲のみがサポートされています。この範囲は、ネットワークから到達可能なサブネットと重複してはなりません。複数の異なる AWSCluster オブジェクト間では、同じ範囲を使用できます。例:
10.1.0.0/16
SERVICE_LOAD_BALANCER_SUBNETS: GKE on AWS がパブリック ロードバランサまたはプライベート ロードバランサを作成できるサブネット ID で置き換えます。
CLUSTER_VERSION: GKE on AWS でサポートされている Kubernetes バージョン。最新バージョンは 1.25.5-gke.2100 です。
AWS_INSTANCE_TYPE: サポートされている EC2 インスタンス タイプ。
SSH_KEY_NAME: AWS EC2 鍵ペア。
CONTROL_PLANE_SUBNET_IDS: コントロール プレーン インスタンスが実行される AZ のサブネット ID。
CONTROL_PLANE_SECURITY_GROUPS: 管理サービスのインストール中に作成された securityGroupID。これをカスタマイズするには、コントロール プレーンへの接続に必要な securityGroupID を追加します。
CONTROL_PLANE_IAM_PROFILE: コントロール プレーンのレプリカに割り当てられた AWS EC2 インスタンス プロファイルの名前。
ROOT_VOLUME_SIZE: コントロール プレーン ルート ボリュームのサイズ(GiB)。
ROOT_VOLUME_TYPE は EBS ボリューム タイプに置き換えます。例:
gp3
。ROOT_VOLUME_IOPS は、ボリューム用にプロビジョニングされた IO オペレーション/秒(IOPS)の量に置き換えます。
volumeType
がGP3
の場合のみ有効です。詳細については、汎用 SSD ボリューム(gp3)をご覧ください。ROOT_VOLUME_KEY は、コントロール プレーン インスタンスのルート ボリュームを暗号化する AWS KMS 鍵の Amazon Resource Name に置き換えます。
ETCD_VOLUME_SIZE: etcd が使用するボリュームのサイズ。
ETCD_VOLUME_TYPE は EBS ボリューム タイプに置き換えます。例:
gp3
。ETCD_VOLUME_IOPS は、ボリューム用にプロビジョニングされた IO オペレーション/秒(IOPS)の量に置き換えます。
volumeType
がgp3
の場合のみ有効です。詳細については、汎用 SSD ボリューム(gp3)をご覧ください。ETCD_VOLUME_KEY は、コントロール プレーン etcd のデータ ボリュームを暗号化する AWS KMS 鍵の Amazon Resource Name に置き換えます。
ARN_OF_KMS_KEY: クラスタ Secret の暗号化に使用される AWS KMS 鍵。
ANTHOS_CONNECT_NAME: クラスタの登録に使用する Connect メンバーシップ名。メンバーシップ名は一意である必要があります。たとえば、
projects/YOUR_PROJECT/locations/global/memberships/CLUSTER_NAME
の場合、YOUR_PROJECT
は Google Cloud プロジェクト、CLUSTER_NAME
はプロジェクト内の一意の名前です。このフィールドは省略可能です。YOUR_PROJECT: プロジェクト ID。
GCP_REGION: ログを保存する Google Cloud リージョン。AWS リージョンに近接したリージョンを選択します。詳細については、グローバル ロケーション - リージョンとゾーンをご覧ください。例:
us-central1
ENABLE_LOGGING:
true
またはfalse
。コントロール プレーン ノードで Cloud Logging が有効かどうか。ENABLE_MONITORING:
true
またはfalse
。コントロール プレーン ノードで Cloud Monitoring が有効かどうか。WORKLOAD_IDENTITY_BUCKET: ワークロード ID ディスカバリ情報を含む Cloud Storage バケット名。このフィールドは省略可能です。
クラスタに 1 つ以上の AWSNodePools を作成します。テキスト エディタを開き、次の AWSCluster 定義を
custom-nodepools.yaml
という名前のファイルにコピーします。apiVersion: multicloud.cluster.gke.io/v1 kind: AWSNodePool metadata: name: NODE_POOL_NAME spec: clusterName: AWSCLUSTER_NAME version: CLUSTER_VERSION # latest version is 1.25.5-gke.2100 region: AWS_REGION subnetID: AWS_SUBNET_ID minNodeCount: MINIMUM_NODE_COUNT maxNodeCount: MAXIMUM_NODE_COUNT maxPodsPerNode: MAXIMUM_PODS_PER_NODE_COUNT instanceType: AWS_NODE_TYPE keyName: KMS_KEY_PAIR_NAME iamInstanceProfile: NODE_IAM_PROFILE proxySecretName: PROXY_SECRET_NAME rootVolume: sizeGiB: ROOT_VOLUME_SIZE volumeType: VOLUME_TYPE # Optional iops: IOPS # Optional kmsKeyARN: NODE_VOLUME_KEY # Optional
以下を置き換えます。
- NODE_POOL_NAME: AWSNodePool の一意の名前。
- AWSCLUSTER_NAME: AWSCluster の名前。例:
staging-cluster
。 - CLUSTER_VERSION: サポートされている GKE on AWS Kubernetes のバージョン。
- AWS_REGION: AWSCluster と同じ AWS リージョン。
- AWS_SUBNET_ID: AWSCluster と同じリージョン内の AWS サブネット。
- MINIMUM_NODE_COUNT: ノードプール内のノードの最小数。詳しくは、ユーザー クラスタのスケーリングをご覧ください。
- MAXIMUM_NODE_COUNT: ノードプール内のノードの最大数。
- MAXIMUM_PODS_PER_NODE_COUNT: GKE on AWS がノードに割り当てることができる Pod の最大数。
- AWS_NODE_TYPE: AWS EC2 インスタンス タイプ。
- KMS_KEY_PAIR_NAME: 各ノードプールのワーカーに割り当てられる AWS KMS 鍵ペア。
- NODE_IAM_PROFILE: プール内のノードに割り当てられる AWS EC2 インスタンス プロファイルの名前。
- ROOT_VOLUME_SIZE: コントロール プレーン ルート ボリュームのサイズ(GiB)。
- VOLUME_TYPE: ノードの AWS EBS ボリューム タイプ。例:
gp3
。 - IOPS: ボリュームに対してプロビジョニングされた IO オペレーション/秒(IOPS)の量。
volumeType
がgp3
の場合のみ有効です。 - NODE_VOLUME_KEY: ボリュームの暗号化に使用される AWS KMS 鍵の ARN。詳細については、顧客管理の CMK を使用したボリュームの暗号化をご覧ください。
マニフェストを管理サービスに適用します。
env HTTPS_PROXY=http://localhost:8118 \ kubectl apply -f custom-cluster.yaml env HTTPS_PROXY=http://localhost:8118 \ kubectl apply -f custom-nodepools.yaml
kubeconfig を作成する
ユーザー クラスタが起動している間、新しいユーザー クラスタの kubeconfig
コンテキストを作成できます。このコンテキストを使用して、ユーザー クラスタまたは管理クラスタに対する認証を行います。
anthos-gke aws clusters get-credentials
を使用して、~/.kube/config
にユーザー クラスタのkubeconfig
を生成します。env HTTPS_PROXY=http://localhost:8118 \ anthos-gke aws clusters get-credentials CLUSTER_NAME
CLUSTER_NAME をクラスタ名に置き換えます。例:
cluster-0
kubectl
を使用して、新しいユーザー クラスタに対する認証を行います。env HTTPS_PROXY=http://localhost:8118 \ kubectl cluster-info
クラスタの準備が整っている場合は、出力にクラスタ内の Kubernetes コンポーネントの URL が含まれます。
クラスタのステータスの表示
管理サービスは、AWSCluster
または AWSNodePool
を適用するとき、AWS リソースをプロビジョニングします。
anthos-aws
ディレクトリからanthos-gke
を使用して、コンテキストを管理サービスに切り替えます。cd anthos-aws anthos-gke aws management get-credentials
クラスタをリストするために、
kubectl get AWSClusters
を使用します。env HTTPS_PROXY=http://localhost:8118 \ kubectl get AWSClusters
出力には、各クラスタの名前、状態、経過時間、バージョン、エンドポイントが含まれます。
たとえば、次の出力には
cluster-0
という名前のAWSCluster
が 1 つだけ含まれています。NAME STATE AGE VERSION ENDPOINT cluster-0 Provisioning 2m41s 1.25.5-gke.2100 gke-xyz.elb.us-east-1.amazonaws.com
クラスタのイベントを表示する
ユーザー クラスタの最近の Kubernetes イベントを表示するには、kubectl get events
を使用します。
anthos-aws
ディレクトリからanthos-gke
を使用して、コンテキストを管理サービスに切り替えます。cd anthos-aws anthos-gke aws management get-credentials
kubectl get events
を実行します。env HTTPS_PROXY=http://localhost:8118 \ kubectl get events
出力には、管理サービスからの情報、警告、関連エラーが含まれます。
Workload Identity Webhook の作成
このセクションは、クラスタ管理者を対象としています。
追加構成なしで Workload Identity の認証情報をワークロードに提供するために、ユーザー クラスタ上に Webhook を作成することもできます。この Webhook は、Pod の作成リクエストをインターセプトし、Pod で環境変数として次の AWS IAM 情報を使用できるようにします。
AWS_ROLE_ARN
: IAM のロールの Amazon Resource Name(ARN)aws-iam-token
: AWS IAM 認証情報と交換されるトークンAWS_WEB_IDENTITY_TOKEN_FILE
: トークンが保存されるパス
これらの変数を使用すると、ワークロードで AWS コマンドライン ツールを呼び出すか、SDK で AWS ロールに付与されたリソースにアクセスできます。
Webhook の作成は省略可能です。Webhook を作成しない場合は、以前に Pod に一覧表示した環境変数を設定する必要があります。Webhook を使用しない方法については、Webhook を使用せず認証情報を適用するをご覧ください。
Webhook の YAML ファイルを作成する
Webhook をデプロイするには、次の操作を行います。
anthos-aws
ディレクトリからanthos-gke
を使用して、コンテキストを管理サービスに切り替えます。cd anthos-aws anthos-gke aws management get-credentials
kubectl
でユーザー クラスタ名を取得します。env HTTPS_PROXY=http://localhost:8118 \ kubectl get awscluster
kubectl
は、すべてのユーザー クラスタを一覧表示します。Workload Identity が有効な状態で作成したユーザー クラスタを選択します。環境変数にクラスタの名前を設定します。
CLUSTER_NAME=CLUSTER_NAME
CLUSTER_NAME
は、使用するクラスタの名前に置き換えます。例:cluster-0
Workload Identity の Pod イメージと Namespace の環境変数を設定します。
IDENTITY_IMAGE=amazon/amazon-eks-pod-identity-webhook:ed8c41f WEBHOOK_NAMESPACE=workload-identity-webhook
次の手順に沿って、
aws-webhook.yaml
という名前のファイルに Webhook YAML マニフェストを生成します。env HTTPS_PROXY=http://localhost:8118 \ anthos-gke aws clusters get-credentials ${CLUSTER_NAME} CLUSTER_CA=$(env HTTPS_PROXY=http://localhost:8118 \ kubectl config view --raw -o json | jq -r '.clusters[] | select(.name == "'$(kubectl config current-context)'") | .cluster."certificate-authority-data"') cat << EOF > aws-webhook.yaml apiVersion: v1 kind: Namespace metadata: name: ${WEBHOOK_NAMESPACE} --- apiVersion: v1 kind: ServiceAccount metadata: name: pod-identity-webhook namespace: ${WEBHOOK_NAMESPACE} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-identity-webhook namespace: ${WEBHOOK_NAMESPACE} rules: - apiGroups: [''] resources: ['secrets'] verbs: ['create'] - apiGroups: [''] resources: ['secrets'] verbs: ['get', 'update', 'patch'] resourceNames: - pod-identity-webhook --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: pod-identity-webhook namespace: ${WEBHOOK_NAMESPACE} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: pod-identity-webhook subjects: - kind: ServiceAccount name: pod-identity-webhook namespace: ${WEBHOOK_NAMESPACE} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: pod-identity-webhook rules: - apiGroups: [''] resources: ['serviceaccounts'] verbs: ['get', 'watch', 'list'] - apiGroups: ['certificates.k8s.io'] resources: ['certificatesigningrequests'] verbs: ['create', 'get', 'list', 'watch'] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: pod-identity-webhook roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: pod-identity-webhook subjects: - kind: ServiceAccount name: pod-identity-webhook namespace: ${WEBHOOK_NAMESPACE} --- apiVersion: apps/v1 kind: Deployment metadata: name: pod-identity-webhook namespace: ${WEBHOOK_NAMESPACE} spec: replicas: 1 selector: matchLabels: app: pod-identity-webhook template: metadata: labels: app: pod-identity-webhook spec: serviceAccountName: pod-identity-webhook containers: - name: pod-identity-webhook image: ${IDENTITY_IMAGE} imagePullPolicy: Always command: - /webhook - --in-cluster - --namespace=${WEBHOOK_NAMESPACE} - --service-name=pod-identity-webhook - --tls-secret=pod-identity-webhook - --annotation-prefix=eks.amazonaws.com - --token-audience=sts.amazonaws.com - --logtostderr volumeMounts: - name: webhook-certs mountPath: /var/run/app/certs readOnly: false volumes: - name: webhook-certs emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: pod-identity-webhook namespace: ${WEBHOOK_NAMESPACE} annotations: prometheus.io/port: '443' prometheus.io/scheme: https prometheus.io/scrape: 'true' spec: ports: - port: 443 targetPort: 443 selector: app: pod-identity-webhook --- apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: pod-identity-webhook namespace: ${WEBHOOK_NAMESPACE} webhooks: - name: pod-identity-webhook.amazonaws.com failurePolicy: Ignore sideEffects: 'None' admissionReviewVersions: ['v1beta1'] clientConfig: service: name: pod-identity-webhook namespace: ${WEBHOOK_NAMESPACE} path: /mutate caBundle: ${CLUSTER_CA} rules: - operations: ['CREATE'] apiGroups: [''] apiVersions: ['v1'] resources: ['pods'] EOF
aws-webhook.yaml
のコンテンツをクラスタに適用する準備ができました。
Webhook をユーザー クラスタに適用する
Webhook をユーザー クラスタに適用するには、次の手順を行います。
aws-webhook.yaml
ファイルをユーザー クラスタに適用します。env HTTPS_PROXY=http://localhost:8118 \ kubectl apply -f aws-webhook.yaml
マニフェストを適用すると、Webhook Pod によって Kubernetes 証明書署名リクエスト(CSR)が生成されます。
system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook
からのリクエストをすべてkubectl certificate approve
で承認します。env HTTPS_PROXY=http://localhost:8118 \ kubectl certificate approve $(env HTTPS_PROXY=http://localhost:8118 \ &&\ kubectl get csr -o \ jsonpath="{.items[?(@.spec.username==\"system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook\")].metadata.name}")
承認されていない CSR が残っていないかを確認します。
kubectl get csr
を使用して、リクエスト元のsystem:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook
のすべての CSR が承認されているかを確認します。env HTTPS_PROXY=http://localhost:8118 \ kubectl get csr
レスポンス:
NAME AGE REQUESTOR CONDITION csr-mxrt8 10s system:serviceaccount:default:pod-identity-webhook Approved,Issued
AWS OIDC プロバイダを構成する
このセクションは、クラスタ管理者を対象としています。
AWS で OIDC プロバイダを作成するには、AWS で中間認証局(CA)またはサーバー証明書のサムプリントが必要です。OIDC ディスカバリ認証情報は、GTS CA 1C3
という名前の中間 CA によって署名された証明書とともに storage.googleapis.com
に保存されます。中間 CA GTS CA 1C3
の SHA-1 サムプリントは 08745487E891C19E3078C1F2A07E452950EF36F6
です。
AWS で OIDC ディスカバリ バケットを OIDC プロバイダとして登録するには、次の操作を行います。
anthos-aws
ディレクトリからanthos-gke
を使用して、コンテキストを管理サービスに切り替えます。cd anthos-aws anthos-gke aws management get-credentials
OIDC 発行者 URL、発行者のホストパス、Cloud Storage サムプリントを環境変数に保存します。
ISSUER_URL=$(env HTTPS_PROXY=http://localhost:8118 \ kubectl get awscluster ${CLUSTER_NAME} -o jsonpath='{.status.workloadIdentityInfo.issuerURL}') ISSUER_HOSTPATH=${ISSUER_URL#"https://"} CA_THUMBPRINT=08745487E891C19E3078C1F2A07E452950EF36F6
aws
コマンドライン ツールを使用して、AWS で OIDC プロバイダを作成します。aws iam create-open-id-connect-provider \ --url ${ISSUER_URL} \ --thumbprint-list ${CA_THUMBPRINT} \ --client-id-list sts.amazonaws.com
サムプリントを更新する
Google が storage.googleapis.com
の CA をローテーションする場合は、次のコマンドを実行します。
更新された証明書のサムプリント
08745487E891C19E3078C1F2A07E452950EF36F6
をコピーします。aws iam update-open-id-connect-provider-thumbprint
コマンドの手順に沿って操作します。ターゲット ホスト名としてstorage.googleapis.com
を使用し、サムプリントとして08745487E891C19E3078C1F2A07E452950EF36F6
を使用します。
AWS IAM のロールとポリシーを作成する
このセクションは、クラスタ管理者を対象としています。
Kubernetes サービス アカウントにバインドする AWS IAM ロールを作成します。IAM ロールには、sts:AssumeRoleWithWebIdentity
の権限が付与されています。
ロールを作成する手順は次のとおりです。
ワークロードに必要な権限を付与する AWS IAM ポリシーを検索するか作成します。
ポリシーの Amazon Resource Name(ARN)の AWS IAM ポリシーが必要です。例:
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
認証情報で環境変数を設定します。
KSA_NAME=KUBERNETES_SERVICE_ACCOUNT WORKLOAD_NAMESPACE=WORKLOAD_IDENTITY_NAMESPACE AWS_ROLE_NAME=AWS_ROLE_NAME AWS_POLICY=EXISTING_AWS_POLICY
次のように置き換えます。
- KUBERNETES_SERVICE_ACCOUNT: 新しい Kubernetes サービス アカウントの名前
- WORKLOAD_IDENTITY_NAMESPACE: ワークロードが実行される Namespace の名前
- AWS_ROLE_NAME: ワークロードに対する新しい AWS ロールの名前
- EXISTING_AWS_POLICY: 既存の AWS IAM ポリシーの Amazon Resource Name(ARN)。例:
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
。
anthos-aws
ディレクトリからanthos-gke
を使用して、コンテキストを管理サービスに切り替えます。cd anthos-aws anthos-gke aws management get-credentials
ユーザー クラスタが AWS セキュリティ トークン サービスを使用して一時的なセキュリティ認証情報を引き継ぐことができる AWS IAM ポリシーを作成します。
CLUSTER_ID=$(env HTTPS_PROXY=http://localhost:8118 \ kubectl get awscluster ${CLUSTER_NAME} -o jsonpath='{.status.clusterID}') # Get the ID Provider ARN PROVIDER_ARN=$(aws iam list-open-id-connect-providers \ | jq '.OpenIDConnectProviderList' \ | jq ".[] | select(.Arn | contains(\"${CLUSTER_ID}\"))" \ | jq '.Arn' | tr -d '"') # Create AWS role and policy cat > irp-trust-policy.json << EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "${PROVIDER_ARN}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "${ISSUER_HOSTPATH}:sub": "system:serviceaccount:${WORKLOAD_NAMESPACE}:${KSA_NAME}" } } } ] } EOF
このポリシーで AWS IAM のロールを作成し、既存のポリシーをロールに接続するには、次のコマンドを実行します。
aws iam create-role \ --role-name ${AWS_ROLE_NAME} \ --assume-role-policy-document file://irp-trust-policy.json aws iam update-assume-role-policy \ --role-name ${AWS_ROLE_NAME} \ --policy-document file://irp-trust-policy.json aws iam attach-role-policy \ --role-name ${AWS_ROLE_NAME} \ --policy-arn ${AWS_POLICY}
aws
コマンドライン ツールによって、ポリシーがロールに接続されていることを確認できます。
ワークロード用の Kubernetes サービス アカウントを作成する
このセクションは、開発者またはクラスタ管理者を対象としています。
事前に指定された AWS IAM ロールにバインドされた Kubernetes サービス アカウントを作成するには、次の手順を行います。
anthos-aws
ディレクトリからanthos-gke
を使用して、コンテキストをユーザー クラスタに切り替えます。cd anthos-aws env HTTPS_PROXY=http://localhost:8118 \ anthos-gke aws clusters get-credentials CLUSTER_NAME
CLUSTER_NAME は、ユーザー クラスタ名に置き換えます。次のコマンドを実行して Kubernetes サービス アカウントを作成します。
S3_ROLE_ARN=$(aws iam get-role \ --role-name AWS_ROLE_NAME \ --query Role.Arn --output text) cat << EOF > k8s-service-account.yaml apiVersion: v1 kind: ServiceAccount metadata: name: ${KSA_NAME} namespace: WORKLOAD_IDENTITY_NAMESPACE EOF env HTTPS_PROXY=http://localhost:8118 \ kubectl apply -f k8s-service-account.yaml env HTTPS_PROXY=http://localhost:8118 \ kubectl annotate sa --namespace ${WORKLOAD_NAMESPACE} ${KSA_NAME} eks.amazonaws.com/role-arn=${S3_ROLE_ARN}
以下を置き換えます。
AWS_ROLE_NAME
: ワークロードに適用する AWS IAM ロールの名前WORKLOAD_IDENTITY_NAMESPACE
: ワークロードが実行される名前空間の名前
Pod に認証情報を適用する
このセクションはデベロッパーを対象としています。
このセクションは、ワークロード ID Webhook をデプロイしていることを前提としています。Webhook をデプロイしていない場合は、Webhook を使用せずに認証情報を適用するに進んでください。
Webhook を使用して認証情報を適用する
このセクションでは、Webhook で使用可能な認証情報を読み取るように Pod を構成する方法について説明します。
Pod にサービス アカウントを追加する
ワークロードでワークロード ID を使用するには、次のフィールドに Kubernetes サービス アカウントを追加します。
- Deployment の場合:
spec.template.spec.serviceAccountName
- Pod の場合:
spec.serviceAccount
次の Pod マニフェストは、基本の CentOS イメージを起動し、spec.serviceAccount
フィールドを含みます。
apiVersion: v1
kind: Pod
metadata:
name: sample-centos-pod
namespace: WORKLOAD_IDENTITY_NAMESPACE
spec:
containers:
- command:
- /bin/bash
- -ec
- while :; do echo '.'; sleep 500 ; done
image: amazon/aws-cli
name: centos
serviceAccount: KUBERNETES_SERVICE_ACCOUNT
以下を置き換えます。
WORKLOAD_IDENTITY_NAMESPACE
: ワークロードが実行される名前空間の名前KUBERNETES_SERVICE_ACCOUNT
: 事前に作成した Kubernetes サービス アカウントの名前
Pod に環境変数が設定されているかどうかを確認する
Pod に環境変数が設定されているかどうかを確認するには、次のコマンドを実行して Pod の情報を取得します。
kubectl get pod --namespace WORKLOAD_IDENTITY_NAMESPACE POD_NAME -o yaml
以下を置き換えます。
WORKLOAD_IDENTITY_NAMESPACE
: ワークロードが実行される名前空間の名前POD_NAME
: 確認する Pod の名前
出力には、spec.containers.command.env
の環境変数値と、AWS IAM トークンのマウント ポイントが含まれます。Pod マニフェストの例を次に示します。
apiVersion: v1
kind: Pod
metadata:
...
spec:
containers:
- command:
- /bin/bash
- -ec
- while :; do echo '.'; sleep 500 ; done
env:
- name: AWS_ROLE_ARN
value: arn:aws:iam::1234567890:role/my-example-workload-role-1
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
image: amazon/aws-cli
imagePullPolicy: IfNotPresent
name: centos
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: my-k8s-serviceaccount-token-d4nz4
readOnly: true
- mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
name: aws-iam-token
readOnly: true
serviceAccount: my-k8s-serviceaccount
serviceAccountName: my-k8s-serviceaccount
volumes:
- name: aws-iam-token
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: sts.amazonaws.com
expirationSeconds: 86400
path: token
- name: my-k8s-serviceaccount-token-d4nz4
secret:
defaultMode: 420
secretName: my-k8s-serviceaccount-token-d4nz4
...
status:
...
Webhook なしで認証情報を適用する
ワークロード ID の Webhook をデプロイしない場合は、次のことを行う必要があります。
-
AWS_ROLE_ARN
: IAM のロールの Amazon Resource Name(ARN)AWS_WEB_IDENTITY_TOKEN_FILE
: トークンが保存されるパス
IAM トークン(
aws-iam-token
)のマウント ポイントと AWS IAM ロールに関連付けられたサービス アカウントを作成します。
Workload Identity の認証情報を持つ Pod を作成する
ワークロード ID に必要な認証情報を含む Pod を作成するには、以下の手順を行います。
次の Pod マニフェストを
sample-pod-no-webhook.yaml
という名前のファイルにコピーします。この構成により、必要な認証情報を含む基本の CentOS イメージが起動されます。apiVersion: v1 kind: Pod metadata: name: sample-centos-pod-no-webhook namespace: WORKLOAD_IDENTITY_NAMESPACE spec: containers: - command: - /bin/bash - -ec - while :; do echo '.'; sleep 500 ; done image: centos:7 name: centos env: - name: AWS_ROLE_ARN value: IAM_ROLE_ARN - name: AWS_WEB_IDENTITY_TOKEN_FILE value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token volumeMounts: - mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount name: aws-iam-token readOnly: true volumes: - name: aws-iam-token projected: defaultMode: 420 sources: - serviceAccountToken: audience: sts.amazonaws.com expirationSeconds: 86400 path: token serviceAccount: KUBERNETES_SERVICE_ACCOUNT
以下を置き換えます。
WORKLOAD_IDENTITY_NAMESPACE
: ワークロードが実行される名前空間の名前。IAM_ROLE_ARN
: Pod に付与された IAM ロールの ARN。例:arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
KUBERNETES_SERVICE_ACCOUNT
: 事前に作成した Kubernetes サービス アカウントの名前。
kubectl
を使用して、Pod マニフェストをクラスタに適用します。env HTTPS_PROXY=http://localhost:8118 \ kubectl apply -f sample-pod-no-webhook.yaml
Pod が AWS リソースにアクセスできるかどうかを確認する
以下の手順では、ワークロード ID が機能するために必要な認証情報を Pod が受信したかどうかを確認する方法について説明します。
手順を完了するには、以下が必要です。
コンテナに対する
bash
シェルアクセス。ほとんどの本番環境イメージには利用可能なシェルがありません。次の例は、前のセクションで指定されている Pod を使用して AWS S3 にアクセスする方法を示しています。AWS コマンドライン インターフェースをダウンロードするには、Pod にインターネットへの送信アクセス権を設定する必要があります。
Pod が S3 バケットにアクセスできるかどうかを確認する手順は次のとおりです。
kubectl exec
を使用して、Podsample-centos-pod-no-webhook
でインタラクティブ bash シェルを起動します。env HTTPS_PROXY=http://localhost:8118 \ kubectl exec -it --namespace ${WORKLOAD_NAMESPACE} sample-centos-pod-no-webhook -- bash
ターミナルが Pod の bash シェルを開きます。
aws
ツールを使用して、AWS IAM の権限と認証情報を確認します。aws sts assume-role-with-web-identity \ --role-arn ${AWS_ROLE_ARN} \ --role-session-name mh9test \ --web-identity-token file:///var/run/secrets/eks.amazonaws.com/serviceaccount/token \ --duration-seconds 1000
aws
ツールによって、次のような認証情報が出力されます。{ "AssumedRoleUser": { "AssumedRoleId": "AROAR2ZZZLEXVSDCDJ37N:mh9test", "Arn": "arn:aws:sts::126285863215:assumed-role/my-example-workload-role-1/mh9test" }, "Audience": "sts.amazonaws.com", "Provider": "arn:aws:iam::126285863215:oidc-provider/storage.googleapis.com/gke-issuer-cec6c353", "SubjectFromWebIdentityToken": "system:serviceaccount:default:my-s3-reader-ksa", "Credentials": { "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "SessionToken": "MY_TOKEN", "Expiration": "2020-08-14T22:46:36Z", "AccessKeyId": "AKIAIOSFODNN7EXAMPLE" } }
「
An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: Couldn't retrieve verification key from your identity provider, please reference AssumeRoleWithWebIdentity documentation for requirements
」というメッセージが表示されたら、バケットが一般公開されていることを確認します。
Webhook のアップグレード
Workload Identity を有効にして Kubernetes 1.18 以前のクラスタと Workload Identity の Webhook バージョン release-0.2.2-gke.0
を作成した場合は、Kubernetes 1.19 にアップグレードする前に Webhook をアップグレードする必要があります。
Webhook をアップグレードするには、次の操作を行います。
次のコマンドを実行して、Webhook がインストールされていることを確認します。
env HTTPS_PROXY=http://localhost:8118 \ kubectl get MutatingWebhookConfiguration
クラスタに Webhook がデプロイされている場合、出力には次のものが含まれます。
NAME WEBHOOKS AGE pod-identity-webhook 1 11m
Webhook がクラスタにデプロイされていない場合は、次の手順をスキップできます。
aws-webhook.yaml
ファイルを保存した場合は、マニフェストを削除できます。このファイルを使用できない場合は、Webhook のコンポーネントを手動で削除できます。以下のファイルまたはコンポーネントから選択します。ファイル
aws-webhook.yaml
ファイルを引き続き保持している場合は、次のコマンドを実行して Webhook を削除します。env HTTPS_PROXY=http://localhost:8118 \ kubectl delete -f aws-webhook.yaml
コンポーネント
Webhook のコンポーネントを手動で削除するには、次のコマンドを実行します。
env HTTPS_PROXY=http://localhost:8118 \ kubectl delete namespace WEBHOOK_NAMESPACE env HTTPS_PROXY=http://localhost:8118 \ kubectl delete clusterrole pod-identity-webhook env HTTPS_PROXY=http://localhost:8118 \ kubectl delete clusterrolebinding pod-identity-webhook env HTTPS_PROXY=http://localhost:8118 \ kubectl delete mutatingwebhookconfiguration pod-identity-webhook
WEBHOOK_NAMESPACE は、Workload Identity Webhook をインストールした Namespace に置き換えます。例:
workload-identity-webhook
次のコマンドを実行して、残りの証明書署名リクエスト(CSR)があるかどうかを確認します。
env HTTPS_PROXY=http://localhost:8118 \ kubectl get csr |grep pod-identity-webhook
出力が空白の場合は、次の手順に進みます。CSR がまだ存在する場合は、
kubectl
コマンドによって既存の CSR が一覧表示されます。CSR を削除するには、次のコマンドを実行します。env HTTPS_PROXY=http://localhost:8118 \ kubectl delete csr $(kubectl get csr -o \ jsonpath="{.items[?(@.spec.username==\"system:serviceaccount:WEBHOOK_NAMESPACE:pod-identity-webhook\")].metadata.name}")
WEBHOOK_NAMESPACE は、Workload Identity Webhook をインストールした Namespace に置き換えます。例:
workload-identity-webhook
Webhook を作成するの手順に沿って、新しいバージョンの Webhook をデプロイします。
新しいバージョンの Webhook をデプロイした後、その Webhook を使用する Pod を再起動する必要があります。ユーザー クラスタをアップグレードすることで、Pod を再起動できます。
クリーンアップ
このセクションでは、このドキュメントの前の部分で作成したリソースを削除する方法を説明します。
サービス アカウントとそれに関連する IAM のロールをクリーンアップする
サービス アカウントとそれに関連する IAM ロールを削除するには、次の手順を行います。
サービス アカウントをクリーンアップします。
env HTTPS_PROXY=http://localhost:8118 \ kubectl delete sa KUBERNETES_SERVICE_ACCOUNT --namespace WORKLOAD_IDENTITY_NAMESPACE
以下を置き換えます。
KUBERNETES_SERVICE_ACCOUNT
: 新しい Kubernetes サービス アカウントの名前WORKLOAD_IDENTITY_NAMESPACE
: ワークロードが実行される名前空間の名前
AWS IAM ロールをクリーンアップします。次のいずれかの方法を選択します。
AWS コンソールで AWS の IAM ロールを削除する。
次のコマンドを使用して、AWS コマンドライン ツールでロールを削除する。
aws iam detach-role-policy \ --role-name=${AWS_ROLE_NAME} \ --policy-arn=${AWS_POLICY} aws iam delete-role --role-name=${AWS_ROLE_NAME}
ユーザー クラスタを削除する
ユーザー クラスタを削除するには、GKE on AWS のアンインストール手順に沿って操作します。
AWS OIDC プロバイダをクリーンアップする
ユーザー クラスタを削除したら、次の bash
シェルコマンドまたは AWS コンソールを使用して、AWS で OIDC プロバイダの登録を解除して削除します。
anthos-aws
ディレクトリからanthos-gke
を使用して、コンテキストを管理サービスに切り替えます。cd anthos-aws anthos-gke aws management get-credentials
次のコマンドを使用して、AWS コマンドライン ツールでロールを削除します。
CLUSTER_ID=$(env HTTPS_PROXY=http://localhost:8118 \ kubectl get awscluster ${CLUSTER_NAME} -o jsonpath='{.status.clusterID}') PROVIDER_ARN=$(aws iam list-open-id-connect-providers \ | jq '.OpenIDConnectProviderList' \ | jq ".[] | select(.Arn | contains(\"${CLUSTER_ID}\"))" \ | jq '.Arn' | tr -d '"') aws iam delete-open-id-connect-provider \ --open-id-connect-provider-arn=${PROVIDER_ARN}
AWS OIDC プロバイダが削除されたことを示す確認メッセージが表示されます。
次のステップ
- GKE on AWS が Workload Identity に使用する AWS のサービス アカウントの IAM ロール(IRSA)について学習する。
- Google Cloud での Workload Identity の使用について学習する。