透過 AWS 使用 Workload Identity

本主題說明如何為 GKE on AWS 工作負載啟用 Workload Identity,以控管其 AWS 資源存取權。

如要瞭解如何搭配使用 Workload Identity 與 Google Cloud Identity and Access Management (IAM) 帳戶,控管 GCP 資源的存取權,請參閱「搭配使用 Workload Identity 與 Google Cloud」。

總覽

Workload Identity 會使用 AWS IAM 權限控管雲端資源的存取權。透過工作負載身分,您可以為每個工作負載指派不同的 IAM 角色。您可以透過這項精細的權限控管機制,遵循最低權限原則。如果沒有 Workload Identity,您必須將 AWS IAM 角色指派給 GKE on AWS 節點,讓節點上的所有工作負載都擁有與節點本身相同的權限。

如要為叢集啟用 Workload Identity,請完成下列步驟,這些步驟會依執行步驟的管理員角色分組。

叢集管理員

  1. 建立 Cloud Storage bucket,以儲存 OIDC 探索資料
  2. 建立 Identity and Access Management 角色,從該 bucket 讀取資料。
  3. 建立啟用 Workload Identity 的使用者叢集。
  4. 在叢集上建立Webhook,在建立 Pod 時套用 Workload Identity 憑證。如果不想使用 Webhook,可以在 Pod 中手動設定環境變數。
  5. 設定 AWS OIDC 提供者
  6. 建立 AWS IAM 角色和政策
叢集管理員或開發人員
  1. 建立 Kubernetes 服務帳戶,並將 AWS 政策繫結至這些帳戶。
開發人員
  1. 將憑證套用至 Pod

必要條件

如要完成本文中的步驟,您必須進行下列設定:

  • GKE on AWS 管理服務
  • 執行 Kubernetes 版本高於 1.17.9 的使用者叢集。

  • 下列權限和工具。

權限

如要建立啟用 Workload Identity 的叢集,您需要下列權限:

Google Cloud

  • 建立可公開讀取的 Cloud Storage bucket,並啟用統一 bucket 層級存取權。
  • 授予 bucket 讀取/寫入權限。management-sa@PROJECT_NAME.iam.gserviceaccount.com

AWS

  • 建立 AWS OIDC 供應商
  • 建立 AWS 身分與存取權管理角色

工具

建議在本機電腦上安裝 jq 工具

建立 OIDC 探索值區

本節適用於叢集管理員

使用者叢集必須將 OIDC 探索資料儲存在可公開存取的 Cloud Storage 值區中。這個 bucket 包含 OIDC 探索設定和公開金鑰。AWS 會使用這些內容驗證來自使用者叢集的要求。

值區必須具備下列屬性:

如果沒有具備這些屬性的值區,請使用下列 gcloud storage 指令建立一個:

BUCKET=BUCKET_NAME
gcloud storage buckets create gs://${BUCKET} --uniform-bucket-level-access
gcloud storage buckets add-iam-policy-binding gs://${BUCKET} \
    --member=allUsers --role=roles/storage.objectViewer

BUCKET_NAME 替換為新值區的名稱。

授予管理服務帳戶權限

GKE on AWS 管理服務的身分與存取權管理服務帳戶,需要具備在這個值區中讀取及寫入物件的權限。

  1. 使用下列指令授予管理服務帳戶權限。

    MANAGEMENT_SA=management-sa@PROJECT_NAME.iam.gserviceaccount.com
    gcloud storage buckets add-iam-policy-binding gs://${BUCKET} \
        --member=serviceAccount:${MANAGEMENT_SA} \
        --role=roles/storage.admin
    

    PROJECT_NAME 替換為您的 Google Cloud 專案。

  2. 建立新的 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 探索 bucket 的詳細資料。您可以在 AWSClusterspec.controlPlane.workloadIdentity.oidcDiscoveryGCSBucket 欄位中設定這項資訊。

在本範例中,您會從 AWSClusterAWSNodePool CRD 手動建立叢集。

  1. 切換至 GKE on AWS 設定所在的目錄。 您在安裝管理服務時建立了這個目錄。

    cd anthos-aws

  2. anthos-aws 目錄使用 anthos-gke 將環境切換至管理服務。

    cd anthos-aws
    anthos-gke aws management get-credentials

  3. 開啟文字編輯器,然後將下列 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:AWS 中的 GKE 支援的 Kubernetes 版本。最新版本為 1.25.5-gke.2100。

    • AWS_INSTANCE_TYPE支援的 EC2 執行個體類型

    • SSH_KEY_NAMEAWS EC2 金鑰組

    • CONTROL_PLANE_SUBNET_IDS:控制層執行個體所在可用區的子網路 ID。

    • CONTROL_PLANE_SECURITY_GROUPS:在管理服務安裝期間建立的 securityGroupID。您可以新增連線至控制層所需的任何 securityGroupIDs,藉此自訂這項設定。

    • CONTROL_PLANE_IAM_PROFILE:指派給控制層副本的 AWS EC2 執行個體設定檔名稱。

    • ROOT_VOLUME_SIZE:控制平面根磁碟區的大小,以 GiB 為單位。

    • ROOT_VOLUME_TYPE,並使用 EBS 磁碟區類型。 例如:gp3

    • ROOT_VOLUME_IOPS,並根據磁碟區每秒佈建的 IO 作業量 (IOPS) 計算。只有在 volumeTypeGP3 時才有效。詳情請參閱通用 SSD 磁碟區 (gp3)

    • ROOT_VOLUME_KEY 替換為AWS KMS 金鑰的 Amazon 資源名稱,該金鑰會加密控制層執行個體根磁碟區。

    • ETCD_VOLUME_SIZE:etcd 使用的磁碟區大小。

    • ETCD_VOLUME_TYPE,並使用 EBS 磁碟區類型。 例如:gp3

    • ETCD_VOLUME_IOPS,並根據磁碟區每秒佈建的 IO 作業量 (IOPS) 計算。只有在 volumeTypegp3 時才有效。詳情請參閱通用 SSD 磁碟區 (gp3)

    • ETCD_VOLUME_KEY,並提供用來加密控制平面 etcd 資料磁碟區的 AWS KMS 金鑰 Amazon Resource Name。

    • ARN_OF_KMS_KEY:用於加密叢集密鑰的 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_LOGGINGtruefalse,指出控制平面節點是否已啟用 Cloud Logging。

    • ENABLE_MONITORINGtruefalse,控制層節點是否已啟用 Cloud Monitoring。

    • WORKLOAD_IDENTITY_BUCKET:Cloud Storage bucket 名稱,其中包含工作負載身分探索資訊。這是選填欄位。

  4. 為叢集建立一或多個 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_TYPEAWS EC2 執行個體類型
    • KMS_KEY_PAIR_NAME:指派給每個節點集區工作站的 AWS KMS 金鑰組。
    • NODE_IAM_PROFILE:指派給集區中節點的 AWS EC2 執行個體設定檔名稱。
    • ROOT_VOLUME_SIZE:控制平面根磁碟區的大小,以 GiB 為單位。
    • VOLUME_TYPE:節點的 AWS EBS 磁碟區類型。 例如:gp3
    • IOPS:磁碟區每秒佈建的 IO 作業數 (IOPS)。只有在 volumeTypegp3 時才有效。
    • NODE_VOLUME_KEY:用於加密磁碟區的 AWS KMS 金鑰 ARN。詳情請參閱「使用客戶管理的 CMK 加密磁碟區」。
  5. 將資訊清單套用至管理服務。

    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 環境。您可以使用這個內容向使用者或管理叢集進行驗證。

  1. 使用 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

  2. 使用 kubectl 向新的使用者叢集進行驗證。

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl cluster-info
    

    如果叢集已準備就緒,輸出內容會包含叢集內 Kubernetes 元件的網址。

查看叢集狀態

當您套用 AWSClusterAWSNodePool 時,管理服務會佈建 AWS 資源。

  1. anthos-aws 目錄使用 anthos-gke 將環境切換至管理服務。

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. 如要列出叢集,請使用 kubectl get AWSClusters

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get AWSClusters
    

    輸出結果包含每個叢集的名稱、狀態、存在時間、版本和端點。

    舉例來說,下列輸出內容只包含一個名為 cluster-0AWSCluster

    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

  1. anthos-aws 目錄使用 anthos-gke 將環境切換至管理服務。

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. 執行 kubectl get events

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get events
    

輸出內容包括與管理服務相關的資訊、警告和錯誤。

建立 Workload Identity Webhook

本節適用於叢集管理員

如要為工作負載提供工作負載身分憑證,且不需額外設定,您可以在使用者叢集上建立 Webhook。這個 Webhook 會攔截 Pod 建立要求,然後將下列 AWS IAM 資訊做為 Pod 的環境變數:

  • 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,請執行下列步驟:

  1. anthos-aws 目錄使用 anthos-gke 將環境切換至管理服務。

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. 使用 kubectl 取得使用者叢集名稱:

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get awscluster
    

    kubectl 會列出所有使用者叢集。選擇您建立的已啟用 Workload Identity 使用者叢集。

  3. 在環境變數中設定叢集名稱。

    CLUSTER_NAME=CLUSTER_NAME
    

    CLUSTER_NAME 替換為叢集名稱。例如:cluster-0

  4. 為工作負載身分 Pod 映像檔和命名空間設定環境變數。

    IDENTITY_IMAGE=amazon/amazon-eks-pod-identity-webhook:ed8c41f
    
    WEBHOOK_NAMESPACE=workload-identity-webhook
    
  5. 執行下列步驟,在名為 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 套用至使用者叢集,請按照下列步驟操作。

  1. aws-webhook.yaml 檔案套用到使用者叢集。

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f aws-webhook.yaml
    
  2. 套用資訊清單時,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}")
    
  3. 確認沒有未核准的 CSR。

    使用 kubectl get csr 檢查要求者的所有 CSR 是否已獲核准:system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook

    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 的 SHA-1 指紋 GTS CA 1C308745487E891C19E3078C1F2A07E452950EF36F6

如要向 AWS 註冊 OIDC 探索 bucket 做為 OIDC 供應商,請執行下列步驟:

  1. anthos-aws 目錄使用 anthos-gke 將環境切換至管理服務。

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. 將 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
    
  3. 使用 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,請執行下列指令:

  1. 複製更新後的憑證指紋 08745487E891C19E3078C1F2A07E452950EF36F6

  2. 按照 aws iam update-open-id-connect-provider-thumbprint 指令的操作說明操作。使用 storage.googleapis.com 做為目標主機名稱,並使用 08745487E891C19E3078C1F2A07E452950EF36F6 做為指紋。

建立 AWS IAM 角色和政策

本節適用於叢集管理員

建立要繫結至 Kubernetes 服務帳戶的 AWS IAM 角色。IAM 角色具有 sts:AssumeRoleWithWebIdentity 的權限。

如要建立角色,請按照下列步驟操作:

  1. 找出或建立 AWS IAM 政策,授予工作負載所需的權限。

    您需要政策的 Amazon 資源名稱 (ARN) AWS IAM 政策。例如:arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

  2. 使用驗證資訊設定環境變數。

    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
  3. anthos-aws 目錄使用 anthos-gke 將環境切換至管理服務。

    cd anthos-aws
    anthos-gke aws management get-credentials

  4. 建立 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
    
  5. 如要使用這項政策建立 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 服務帳戶,請執行下列步驟:

  1. anthos-aws 目錄中,使用 anthos-gke 將環境切換至使用者叢集。

    cd anthos-aws
    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials CLUSTER_NAME
    CLUSTER_NAME 替換為使用者叢集名稱。

  2. 執行下列指令,建立 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 webhook。如果尚未部署 Webhook,請跳到「不使用 Webhook 套用憑證」。

透過 Webhook 套用憑證

本節說明如何設定 Pod,以便讀取 Webhook 提供的憑證。

將服務帳戶新增至 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:
  ...

不使用 Webhook 即可套用憑證

如果沒有部署 workload identity webhook,請執行下列操作:

建立具有工作負載身分憑證的 Pod

如要建立包含工作負載身分識別必要憑證的 Pod,請按照下列步驟操作:

  1. 將下列 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 服務帳戶名稱。
  2. 使用 kubectl 將 Pod 資訊清單套用至叢集:

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f sample-pod-no-webhook.yaml
    

檢查 Pod 是否可以存取 AWS 資源

以下程序說明如何檢查 Pod 是否已收到工作負載身分識別運作所需的憑證。

如要完成這些步驟,您必須具備下列條件:

  • bash 容器的殼層存取權;大多數的正式版映像檔都沒有可用的殼層。以下範例說明如何使用前一節中指定的 Pod 存取 AWS S3。

  • Pod 必須能連出網際網路,才能下載 AWS 指令列介面。

如要檢查 Pod 是否可以存取 S3 bucket,請執行下列步驟:

  1. 使用 kubectl exec 在 Pod 上啟動互動式 Bash 殼層 sample-centos-pod-no-webhook

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl exec -it --namespace ${WORKLOAD_NAMESPACE} sample-centos-pod-no-webhook -- bash
    

    終端機會在 Pod 上開啟 bash 殼層。

  2. 使用 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

如果您建立的 Kubernetes 1.18 以下版本叢集已啟用 Workload Identity,且 Workload Identity Webhook 版本為 release-0.2.2-gke.0,則必須先升級 Webhook,才能升級至 Kubernetes 1.19。

如要升級 Webhook,請執行下列步驟:

  1. 執行下列指令,確認已安裝 Webhook:

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get MutatingWebhookConfiguration
    

    如果叢集已部署 Webhook,輸出內容會包含下列項目:

    NAME                   WEBHOOKS   AGE
    pod-identity-webhook   1          11m
    

    如果叢集未部署 Webhook,可以略過下列步驟。

  2. 如果已儲存 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 的命名空間。例如:workload-identity-webhook

  3. 執行下列指令,檢查是否還有任何憑證簽署要求 (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 的命名空間。例如:workload-identity-webhook

  4. 按照「建立 Webhook」一文的步驟操作,部署新版 Webhook。

    部署新版 Webhook 後,您需要重新啟動使用 Webhook 的 Pod。你可以透過升級使用者叢集的方式重新啟動 Pod。

正在清除所用資源

本節說明如何移除您在本文件稍早建立的資源。

清除服務帳戶及其相關聯的 IAM 角色

如要刪除服務帳戶及其相關聯的 IAM 角色,請按照下列步驟操作:

  1. 清除服務帳戶:

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl delete sa KUBERNETES_SERVICE_ACCOUNT --namespace WORKLOAD_IDENTITY_NAMESPACE
    

    更改下列內容:

    • KUBERNETES_SERVICE_ACCOUNT:新的 Kubernetes 服務帳戶名稱
    • WORKLOAD_IDENTITY_NAMESPACE:工作負載執行的命名空間名稱
  2. 清除 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}
      

刪除使用者叢集

如要刪除使用者叢集,請按照「在 AWS 中解除安裝 GKE」一文中的步驟操作。

清除 AWS OIDC 供應商

刪除使用者叢集後,請使用下列 bash shell 指令或 AWS 控制台,取消註冊並刪除 AWS 上的 OIDC 提供者。

  1. anthos-aws 目錄使用 anthos-gke 將環境切換至管理服務。

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. 使用 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 提供者。

後續步驟