本主题介绍如何为 GKE on AWS 工作负载启用工作负载身份来控制其对 AWS 资源的访问权限。
如需了解如何将工作负载身份与 Google Cloud Identity and Access Management (IAM) 账号搭配使用,以控制对 GCP 资源的访问权限,请参阅将工作负载身份与 Google Cloud 搭配使用。
概览
工作负载身份使用 AWS IAM 权限控制对云资源的访问权限。借助 Workload Identity,您可以为每个工作负载分配不同的 IAM 角色。通过这种精细权限控制,您可以遵循最小权限原则。 如果没有工作负载身份,您必须将 AWS IAM 角色分配给 GKE on AWS 节点,从而为该节点上的所有工作负载提供与节点本身相同的权限。
如需为集群启用工作负载身份,请完成以下步骤,这些步骤按执行它们的管理角色进行分组。
集群管理员
- 创建 Cloud Storage 存储分区以存储 OIDC 发现数据。
- 创建 Identity and Access Management 角色以从该存储桶读取数据。
- 创建启用了 Workload Identity 的用户集群。
- 在集群上创建网络钩子,该网络钩子会在创建时将工作负载身份凭据应用于 Pod。如果您不想使用网络钩子,则可以在 pod 中手动设置环境变量。
- 配置 AWS OIDC 提供方。
- 创建 AWS IAM 角色和政策。
- 创建 Kubernetes 服务账号,并向其绑定 AWS 政策。
前提条件
如要完成本文档中的步骤,您必须进行以下设置:
- GKE on AWS 管理服务。
运行高于 1.17.9 的 Kubernetes 版本的用户集群。
以下权限和工具。
权限
如要创建启用了 Workload Identity 的集群,您需要以下权限:
Google Cloud
- 创建一个可公开读取的 Cloud Storage 存储分区,并启用统一存储分区级访问权限。
- 授予
management-sa@PROJECT_NAME.iam.gserviceaccount.com
对存储分区的读取/写入权限。
AWS
- 创建 AWS OIDC 提供方
- 创建 AWS IAM 角色
工具
在本地机器上,建议安装 jq
工具。
创建 OIDC 发现存储分区
本部分面向集群管理员。
您的用户集群需要将 OIDC 发现数据存储在可公开访问的 Cloud Storage 存储分区中。存储分区包含 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 确认政策绑定已创建。
创建用户集群
本部分面向集群管理员。
创建启用了 Workload Identity 的用户集群。
创建一个包含您的 OIDC 发现存储分区详情的用户集群。您可以在 AWSCluster
的 spec.controlPlane.workloadIdentity.oidcDiscoveryGCSBucket
字段中设置此信息。
在此示例中,您将通过 AWSCluster
和 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 地址范围。目前仅支持单个范围。 此范围不得与从您的网络访问的任何子网重叠。您可以放心地在多个不同的 AWSCluster 对象中使用相同的范围。例如
10.2.0.0/16
。SERVICE_ADDRESS_CIDR_BLOCKS:集群的服务使用的 IPv4 地址范围。目前仅支持单个范围。 此范围不得与从您的网络访问的任何子网重叠。 您可以放心地在多个不同的 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 资源名称。
ETCD_VOLUME_SIZE:etcd 使用的卷的大小。
将 ETCD_VOLUME_TYPE 替换为 EBS 卷类型。例如
gp3
。将 ETCD_VOLUME_IOPS 替换为卷的每秒预配 IO 操作数 (IOPS)。仅在
volumeType
为gp3
时有效。如需了解详情,请参阅通用 SSD 卷 (gp3)。将 ETCD_VOLUME_KEY 替换为 AWS KMS 密钥的 Amazon 资源名称,以加密您的控制层面 etcd 数据卷。
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:包含您的 Workload Identity 发现信息的 Cloud Storage 存储分区名称。 此字段是可选字段。
为集群创建一个或多个 AWSNodePool。打开文本编辑器并将以下 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 组件的网址。
查看集群的状态
如果您应用 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
: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 凭据,您可以视需要在用户集群上创建网络钩子。此网络钩子会拦截 Pod 创建请求,然后将以下 AWS IAM 信息作为环境变量提供给 Pod:
AWS_ROLE_ARN
:IAM 角色的 Amazon 资源名称 (ARN)aws-iam-token
:用于交换 AWS IAM 凭据的令牌AWS_WEB_IDENTITY_TOKEN_FILE
:存储令牌的路径
通过这些变量,您的工作负载可以调用 AWS 命令行工具,或者 SDK 可以访问被授予 AWS 角色的资源。
创建网络钩子是可选操作。如果您决定不创建网络钩子,则需要设置之前在 Pod 中列出的环境变量。如需了解如何不使用网络钩子,请参阅在不使用网络钩子的情况下应用凭据。
为网络钩子创建 YAML 文件
如需部署网络钩子,请执行以下步骤:
在
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 映像和命名空间设置环境变量。
IDENTITY_IMAGE=amazon/amazon-eks-pod-identity-webhook:ed8c41f WEBHOOK_NAMESPACE=workload-identity-webhook
通过执行以下步骤,在名为
aws-webhook.yaml
的文件中生成网络钩子 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
的内容应用到您的集群了。
将网络钩子应用到用户集群
如需将网络钩子应用到您的用户集群,请执行以下步骤。
将
aws-webhook.yaml
文件应用到用户集群。env HTTPS_PROXY=http://localhost:8118 \ kubectl apply -f aws-webhook.yaml
应用清单时,网络钩子 Pod 将生成 Kubernetes 证书签名请求 (CSR)。使用
kubectl certificate approve
批准来自system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook
的所有请求。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 发现凭据存储在 storage.googleapis.com
上,该证书由一个名为 GTS CA 1C3
的中间 CA 签名。其中间 CA GTS CA 1C3
的 SHA-1 指纹为 08745487E891C19E3078C1F2A07E452950EF36F6
。
如要将 OIDC 发现存储分区注册为 AWS 的 OIDC 提供方,请执行以下步骤:
在
anthos-aws
目录中,使用anthos-gke
将上下文切换到管理服务。cd anthos-aws anthos-gke aws management get-credentials
将 OIDC 颁发者网址、颁发者主机路径和 Cloud Storage Thumbprint 保存在环境变量中。
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 资源名称 (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:运行工作负载的命名空间的名称
- AWS_ROLE_NAME:工作负载的新 AWS 角色的名称
- EXISTING_AWS_POLICY:现有 AWS IAM 政策的 Amazon 资源名称 (ARN),例如
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
。
在
anthos-aws
目录中,使用anthos-gke
将上下文切换到管理服务。cd anthos-aws anthos-gke aws management get-credentials
创建一个 AWS IAM 政策,该政策允许您的用户群集通过 AWS Security Token Service 采用临时安全凭证:
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
本部分面向开发者。
本部分假定您已部署 Workload Identity 网络钩子。如果您尚未部署网络钩子,请跳至再没有网络钩子的情况下应用凭据。
使用网络钩子应用凭据
本部分介绍如何配置 Pod 以读取网络钩子提供的凭据。
将服务账号添加到 Pod
如需将 Workload Identity 用于工作负载,请将 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:
...
再没有网络钩子的情况下应用凭据
如果您未部署 Workload Identity 网络钩子,则需要执行以下操作:
-
AWS_ROLE_ARN
:IAM 角色的 Amazon 资源名称 (ARN)AWS_WEB_IDENTITY_TOKEN_FILE
:存储令牌的路径
为 IAM 令牌 (
aws-iam-token
) 和与 AWS IAM 角色关联的服务账号创建装载点
使用 Workload Identity 的凭据创建 Pod
如需创建包含 Workload Identity 必要凭据的 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 资源
以下过程介绍了如何检查 Pod 是否收到了 Workload Identity 正常运行所需的凭据。
如要完成这些步骤,您需要满足以下条件:
拥有容器的
bash
shell 访问权限;大多数生产映像都没有 shell。以下示例展示了如何使用上一部分中指定的 Pod 来访问 AWS S3。您的 Pod 需要具有对互联网的出站访问权限才能下载 AWS 命令行界面。
如需检查 Pod 能否访问 S3 存储分区,请执行以下步骤:
使用
kubectl exec
在 Podsample-centos-pod-no-webhook
上启动交互式 bash shell:env HTTPS_PROXY=http://localhost:8118 \ kubectl exec -it --namespace ${WORKLOAD_NAMESPACE} sample-centos-pod-no-webhook -- bash
您的终端会打开 Pod 上的 bash shell。
使用
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 网络钩子版本为 release-0.2.2-gke.0
,则在升级到 Kubernetes 1.19 之前,您必须先升级网络钩子。
如需升级网络钩子,请执行以下步骤:
通过运行以下命令确认已安装网络钩子:
env HTTPS_PROXY=http://localhost:8118 \ kubectl get MutatingWebhookConfiguration
如果您的集群已部署 Webhook,则输出包含以下内容:
NAME WEBHOOKS AGE pod-identity-webhook 1 11m
如果您的集群上未部署网络钩子,则可以跳过以下步骤。
如果您保存了
aws-webhook.yaml
文件,则可以删除清单。如果您没有此文件,可以手动删除网络钩子的组件。从以下文件或组件中选择。文件
如果您仍有
aws-webhook.yaml
文件,请运行以下命令删除网络钩子:env HTTPS_PROXY=http://localhost:8118 \ kubectl delete -f aws-webhook.yaml
组件
如需手动删除网络钩子的组件,请运行以下命令:
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 网络钩子的命名空间。例如
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 网络钩子的命名空间。例如
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
shell 命令或 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 提供方已被删除的确认信息。
后续步骤
- 了解 AWS 适用于服务账号的 IAM 角色 (IRSA) ,GKE on AWS 将该角色用于 Workload Identity。
- 了解如何将工作负载身份与 Google Cloud 搭配使用。