Como usar a identidade da carga de trabalho com a AWS

Neste tópico, descrevemos como ativar a identidade da carga de trabalho para que as cargas de trabalho do GKE na AWS controlem o acesso aos recursos da AWS.

Para informações sobre como usar a identidade da carga de trabalho com as contas do Google Cloud Identity and Access Management (IAM) para controlar o acesso aos recursos do GCP, consulte Como usar a identidade da carga de trabalho com o Google Cloud.

Visão geral

A identidade da carga de trabalho usa as permissões do IAM da AWS para controlar o acesso aos recursos da nuvem. Com a identidade da carga de trabalho, é possível atribuir diferentes papéis de IAM a cada carga de trabalho. Esse controle refinado de permissões permite que você siga o princípio do privilégio mínimo. Sem a identidade da carga de trabalho, você precisa atribuir papéis do IAM da AWS aos nós do GKE na AWS, dando a todas as cargas de trabalho no nó as mesmas permissões que o próprio nó.

Para ativar a identidade da carga de trabalho para o cluster, conclua as etapas a seguir, agrupadas pelos papéis administrativos que as executam.

Administrador do cluster

  1. Crie um bucket do Cloud Storage para armazenar os dados de descoberta do OIDC.
  2. Criar um papel de gerenciamento de identidade e acesso para ler esse bucket.
  3. Crie um cluster de usuário com a identidade da carga de trabalho ativada.
  4. Crie um webhook no cluster que aplique credenciais de identidade de carga de trabalho aos pods na criação. Se você não quiser usar o webhook, defina variáveis de ambiente manualmente nos pods.
  5. Configure o provedor OIDC da AWS.
  6. Crie papéis e políticas do AWS IAM.
Administrador ou desenvolvedor do cluster
  1. Crie contas de serviço do Kubernetes e vincule as políticas da AWS a elas.
Desenvolvedor
  1. Aplique credenciais aos seus pods.

Pré-requisitos

Para concluir as etapas deste documento, você precisa ter a seguinte configuração:

  • Um serviço de gerenciamento do GKE na AWS.
  • Clusters de usuário que executam uma versão do Kubernetes posterior à 1.17.9.

  • As seguintes permissões e ferramentas.

Permissões

Para criar um cluster com a identidade da carga de trabalho ativada, você precisa das seguintes permissões:

Google Cloud

  • Crie um bucket do Cloud Storage publicamente legível com o acesso uniforme no nível do bucket ativado.
  • Conceda permissões de leitura/gravação management-sa@PROJECT_NAME.iam.gserviceaccount.com ao bucket.

AWS

  • Criar um provedor OIDC da AWS
  • Criar papéis de IAM da AWS

Ferramentas

Na máquina local, recomendamos que você tenha a ferramenta jq instalada.

Como criar o bucket de descoberta OIDC

Esta seção é destinada aos administradores de cluster.

O cluster de usuário precisa armazenar os dados de descoberta do OIDC em um bucket do Cloud Storage acessível publicamente. O bucket inclui a configuração de descoberta do OIDC e as chaves públicas. A AWS usa o conteúdo para autenticar solicitações dos clusters de usuário.

Seu bucket precisa ter os seguintes atributos:

Se você não tiver um bucket com esses atributos, crie um usando os seguintes comandos gsutil:

BUCKET=BUCKET_NAME
gsutil mb -b on gs://${BUCKET}
gsutil iam ch allUsers:objectViewer gs://${BUCKET}

Substitua BUCKET_NAME pelo nome do novo bucket.

Conceder permissões à conta de serviço de gerenciamento

A conta de serviço do Identity and Access Management do GKE no serviço de gerenciamento da AWS precisa de permissões para ler e gravar objetos neste bucket.

  1. Conceda as permissões da sua conta de serviço de gerenciamento usando o seguinte comando gsutil.

    MANAGEMENT_SA=management-sa@PROJECT_NAME.iam.gserviceaccount.com
    gsutil iam ch serviceAccount:${MANAGEMENT_SA}:admin gs://${BUCKET}
    

    Substitua PROJECT_NAME pelo ID do projeto do Google Cloud.

  2. Crie um novo papel do IAM com permissões para gerenciar esse bucket. Para criar o papel, primeiro salve a definição dele em um arquivo. Depois, crie o papel e vincule-o à conta de serviço de gerenciamento.

    Para concluir essas etapas, execute os seguintes comandos:

    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
    

    Substitua PROJECT_NAME pelo ID do projeto do Google Cloud.

    A Google Cloud CLI confirma se a vinculação de política foi criada.

Como criar um cluster de usuário

Esta seção é destinada aos administradores de cluster.

Criar um cluster de usuário com a identidade da carga de trabalho ativada

Crie um cluster de usuário que contenha detalhes sobre seu bucket de descoberta OIDC. Defina essas informações no campo spec.controlPlane.workloadIdentity.oidcDiscoveryGCSBucket de AWSCluster.

Neste exemplo, você cria um cluster manualmente a partir de CRDs AWSCluster e AWSNodePool.

  1. Mude para o diretório com o GKE na configuração da AWS. Você criou esse diretório ao instalar o serviço de gerenciamento.

    cd anthos-aws

  2. No diretório anthos-aws, use anthos-gke para alternar o contexto para o serviço de gerenciamento.

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

  3. Abra um editor de texto e copie a seguinte definição AWSCluster em um arquivo chamado 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
    

    Substitua:

    • CLUSTER_NAME: o nome do cluster.
    • AWS_REGION: a região da AWS em que o cluster é executado.

    • VPC_ID: O ID da VPC em que o cluster é executado.

    • POD_ADDRESS_CIDR_BLOCKS: o intervalo de endereços IPv4 usados pelos pods do cluster. Atualmente, apenas um intervalo é aceito. O intervalo não pode se sobrepor a nenhuma sub-rede acessível pela rede. É seguro usar o mesmo intervalo em vários objetos diferentes do AWSCluster. Por exemplo, 10.2.0.0/16.

    • SERVICE_ADDRESS_CIDR_BLOCKS: o intervalo de endereços IPv4 usados pelos serviços do cluster; Atualmente, apenas um intervalo é aceito. O intervalo não pode se sobrepor a nenhuma sub-rede acessível pela rede. É seguro usar o mesmo intervalo em vários objetos diferentes do AWSCluster. Por exemplo, 10.1.0.0/16.

    • SERVICE_LOAD_BALANCER_SUBNETS: os IDs de sub-rede em que o GKE na AWS pode criar balanceadores de carga públicos ou particulares.

    • CLUSTER_VERSION: uma versão do Kubernetes (em inglês) compatível com o GKE na AWS. A versão mais recente é 1.25.5-gke.2100.

    • AWS_INSTANCE_TYPE: um tipo de instância EC2 compatível.

    • SSH_KEY_NAME: um par de chaves do AWS EC2.

    • CONTROL_PLANE_SUBNET_IDS: os IDs de sub-rede nos AZs em que suas instâncias do plano de controle são executadas.

    • CONTROL_PLANE_SECURITY_GROUPS: um securityGroupID criado durante a instalação do serviço de gerenciamento. É possível personalizar isso adicionando qualquer securityGroupID necessário para se conectar ao plano de controle.

    • CONTROL_PLANE_IAM_PROFILE: nome do perfil da instância do AWS EC2 atribuído às réplicas do plano de controle.

    • ROOT_VOLUME_SIZE: o tamanho, em gibibyte (GiB), dos volumes raiz do seu plano de controle.

    • ROOT_VOLUME_TYPE pelo tipo de volume EBS. Por exemplo, gp3.

    • ROOT_VOLUME_IOPS pela quantidade de operações de E/S provisionadas por segundo (IOPS, na sigla em inglês) para o volume. Válido apenas quando volumeType for GP3. Para mais informações, consulte Volumes SSD de uso geral (gp3).

    • ROOT_VOLUME_KEY pelo nome de recurso da Amazon da chave de KMS da AWS que criptografa os volumes raiz da instância do plano de controle.

    • ETCD_VOLUME_SIZE: o tamanho dos volumes usados pelo etcd.

    • ETCD_VOLUME_TYPE pelo tipo de volume EBS. Por exemplo, gp3.

    • ETCD_VOLUME_IOPS pela quantidade de operações de E/S provisionadas por segundo (IOPS, na sigla em inglês) para o volume. Válido apenas quando volumeType for gp3. Para mais informações, consulte Volumes SSD de uso geral (gp3).

    • ETCD_VOLUME_KEY pelo nome de recurso da Amazon da chave de KMS da AWS que criptografa os volumes de dados etcd do plano de controle etc.

    • ARN_OF_KMS_KEY: a chave do AWS KMS usada para criptografar secrets do cluster.

    • O nome da assinatura do ANTHOS_CONNECT_NAMEConnect usado para registrar seu cluster. O nome da assinatura precisa ser exclusivo. Por exemplo, projects/YOUR_PROJECT/locations/global/memberships/CLUSTER_NAME, em que YOUR_PROJECT é o projeto do Google Cloud e CLUSTER_NAME é um nome exclusivo no projeto. Este campo é opcional.

    • YOUR_PROJECT: o ID do projeto.

    • GCP_REGION: a região do Google Cloud em que você quer armazenar os registros. Escolha uma região próxima à região da AWS. Para mais informações, consulte Locais globais: regiões e zonas. Por exemplo, us-central1.

    • ENABLE_LOGGING: true ou false, se o Cloud Logging está ativado nos nós do plano de controle.

    • ENABLE_MONITORING: true ou false, se o Cloud Monitoring está ativado nos nós do plano de controle.

    • WORKLOAD_IDENTITY_BUCKET: o nome do bucket do Cloud Storage que contém suas informações de descoberta de identidade da carga de trabalho. Este campo é opcional.

  4. Crie um ou mais AWSNodePools para o cluster. Abra um editor de texto e copie a seguinte definição de AWSCluster em um arquivo chamado 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 
    

    Substitua:

    • NODE_POOL_NAME: um nome exclusivo para o AWSNodePool.
    • AWSCLUSTER_NAME: O nome do seu AWSCluster. Por exemplo, staging-cluster.
    • CLUSTER_VERSION: uma versão compatível do GKE na AWS Kubernetes.
    • AWS_REGION: a mesma região da AWS do AWSCluster.
    • AWS_SUBNET_ID: uma sub-rede da AWS na mesma região do AWSCluster.
    • MINIMUM_NODE_COUNT: o número mínimo de nós no pool. Consulte Como escalonar clusters de usuários para mais informações.
    • MAXIMUM_NODE_COUNT: o número máximo de nós no pool.
    • MAXIMUM_PODS_PER_NODE_COUNT: o número máximo de pods que o GKE na AWS pode alocar em um nó.
    • AWS_NODE_TYPE: um tipo de instância do AWS EC2
    • KMS_KEY_PAIR_NAME: O par de chaves KMS da AWS atribuído a cada worker do pool de nós.
    • NODE_IAM_PROFILE: O nome do perfil da instância da AWS EC2 atribuída aos nós do pool.
    • ROOT_VOLUME_SIZE: o tamanho, em gibibyte (GiB), dos volumes raiz do seu plano de controle.
    • VOLUME_TYPE: o tipo de volume EBS da AWS do nó. Por exemplo, gp3.
    • IOPS: a quantidade de operações de E/S provisionadas por segundo (IOPS, na sigla em inglês) para volumes. Válido apenas quando volumeType for gp3.
    • NODE_VOLUME_KEY: o ARN da chave do KMS da AWS usado para criptografar o volume. Para mais informações, consulte Como usar uma CMK gerenciada pelo cliente para criptografar volumes.
  5. Aplique os manifestos ao seu serviço de gerenciamento.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f custom-cluster.yaml
    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f custom-nodepools.yaml
    

Criar um kubeconfig

Enquanto o cluster de usuários é iniciado, é possível criar um contexto kubeconfig para o novo cluster de usuários. Use o contexto para autenticar um usuário ou cluster de gerenciamento.

  1. Use anthos-gke aws clusters get-credentials para gerar um kubeconfig para o cluster de usuários em ~/.kube/config.

    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials CLUSTER_NAME
    

    Substitua CLUSTER_NAME pelo nome do cluster. Por exemplo, cluster-0.

  2. Use kubectl para se autenticar no novo cluster de usuário.

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

    Se o cluster estiver pronto, a saída incluirá os URLs dos componentes do Kubernetes no cluster.

Como visualizar o status do cluster

O serviço de gerenciamento provisiona recursos da AWS quando você aplica um AWSCluster ou AWSNodePool.

  1. No diretório anthos-aws, use anthos-gke para alternar o contexto para o serviço de gerenciamento.

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

  2. Para listar os clusters, use kubectl get AWSClusters.

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

    A saída inclui o nome, o estado, a idade, a versão e o endpoint de cada cluster.

    Por exemplo, a saída a seguir inclui apenas um AWSCluster chamado cluster-0:

    NAME        STATE          AGE     VERSION         ENDPOINT
    cluster-0   Provisioning   2m41s   1.25.5-gke.2100   gke-xyz.elb.us-east-1.amazonaws.com
    

Ver os eventos do cluster

Para ver os Eventos do Kubernetes recentes no cluster de usuário, use o kubectl get events.

  1. No diretório anthos-aws, use anthos-gke para alternar o contexto para o serviço de gerenciamento.

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

  2. Execute kubectl get events.

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

A saída inclui informações, aviso e erros relacionados ao seu serviço de gerenciamento.

Como criar o webhook da identidade da carga de trabalho

Esta seção é destinada aos administradores de cluster.

Para fornecer credenciais de identidade das cargas de trabalho sem configuração adicional, você pode criar um webhook nos clusters de usuário. Esse webhook intercepta solicitações de criação de pod e disponibiliza as seguintes informações sobre o IAM da AWS como variáveis de ambiente para o pod:

  • AWS_ROLE_ARN: o Amazon Resource Name (ARN) do papel do IAM
  • aws-iam-token: token trocado por credenciais do AWS IAM
  • AWS_WEB_IDENTITY_TOKEN_FILE: o caminho onde o token é armazenado.

Com essas variáveis, as cargas de trabalho podem chamar a ferramenta de linha de comando da AWS ou o SDK pode acessar os recursos concedidos à função da AWS.

A criação do webhook é opcional. Se você decidir não criar o webhook, precisará definir as variáveis de ambiente listadas anteriormente no pod. Para informações sobre como não usar um webhook, consulte Como aplicar credenciais sem o webhook.

Crie arquivos YAML para o webhook

Para implantar o webhook, execute as seguintes etapas:

  1. No diretório anthos-aws, use anthos-gke para alternar o contexto para o serviço de gerenciamento.

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

  2. Consiga o nome do cluster do usuário com kubectl:

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

    kubectl lista todos os clusters de usuário. Escolha o cluster de usuário criado com a identidade de carga de trabalho ativada.

  3. Defina o nome do cluster em uma variável de ambiente.

    CLUSTER_NAME=CLUSTER_NAME
    

    Substitua CLUSTER_NAME pelo nome do cluster. Por exemplo, cluster-0.

  4. Defina variáveis de ambiente para o namespace e a imagem do pod de identidade da carga de trabalho.

    IDENTITY_IMAGE=amazon/amazon-eks-pod-identity-webhook:ed8c41f
    
    WEBHOOK_NAMESPACE=workload-identity-webhook
    
  5. Gere o manifesto YAML do webhook em um arquivo chamado aws-webhook.yaml realizando estas etapas:

    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
    

    O conteúdo de aws-webhook.yaml está pronto para ser aplicado ao seu cluster.

Aplicar o webhook ao cluster do usuário

Para aplicar o webhook ao cluster do usuário, execute as etapas a seguir.

  1. Aplique o arquivo aws-webhook.yaml ao seu cluster de usuário.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f aws-webhook.yaml
    
  2. Quando você aplica o manifesto, o pod do webhook gera solicitações de assinatura de certificado (CSR, na sigla em inglês) do Kubernetes. Aprove todas as solicitações de system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook com 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. Verifique se não há CSRs não aprovados restantes.

    Use kubectl get csr para verificar se todas as CSRs do solicitante system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook foram aprovadas:

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

    Saída:

    NAME        AGE   REQUESTOR                                            CONDITION
    csr-mxrt8   10s   system:serviceaccount:default:pod-identity-webhook   Approved,Issued
    

Como configurar o provedor da AWS OIDC

Esta seção é destinada aos administradores de cluster.

Para criar um provedor OIDC na AWS, a AWS exige uma autoridade de certificação (CA, na sigla em inglês) intermediária ou uma impressão digital de certificado do servidor. Suas credenciais de descoberta do OIDC são armazenadas em storage.googleapis.com, com um certificado assinado por uma CA intermediária chamada GTS CA 1C3. A impressão digital SHA-1 da sua CA intermediária GTS CA 1C3 é 08745487E891C19E3078C1F2A07E452950EF36F6.

Para registrar seu bucket de descoberta OIDC como provedor OIDC na AWS, siga estas etapas:

  1. No diretório anthos-aws, use anthos-gke para alternar o contexto para o serviço de gerenciamento.

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

  2. Salve o URL do emissor OIDC, o caminho do host do emissor e a impressão digital do Cloud Storage nas variáveis de ambiente.

    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. Use a ferramenta de linha de comando aws para criar um provedor OIDC na AWS.

    aws iam create-open-id-connect-provider \
      --url ${ISSUER_URL} \
      --thumbprint-list ${CA_THUMBPRINT} \
      --client-id-list sts.amazonaws.com
    

Atualizar impressão digital

Se o Google girar a CA para storage.googleapis.com, execute os seguintes comandos:

  1. Copie a impressão digital atualizada do certificado, 08745487E891C19E3078C1F2A07E452950EF36F6.

  2. Siga as instruções para o comando aws iam update-open-id-connect-provider-thumbprint. Use storage.googleapis.com como o nome do host de destino e 08745487E891C19E3078C1F2A07E452950EF36F6 como impressão digital.

Como criar papéis e políticas do AWS IAM

Esta seção é destinada aos administradores de cluster.

Criar um papel do AWS IAM para vincular a uma conta de serviço do Kubernetes. O papel do IAM tem permissões para sts:AssumeRoleWithWebIdentity.

Para criar o papel, execute as etapas a seguir:

  1. Encontre ou crie uma política do IAM da AWS que conceda as permissões necessárias às cargas de trabalho.

    Você precisa da política de IAM da AWS do nome de recurso da Amazon (ARN) da política. Por exemplo, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess.

  2. Defina as variáveis de ambiente com as informações de autenticação.

    KSA_NAME=KUBERNETES_SERVICE_ACCOUNT
    WORKLOAD_NAMESPACE=WORKLOAD_IDENTITY_NAMESPACE
    
    AWS_ROLE_NAME=AWS_ROLE_NAME
    AWS_POLICY=EXISTING_AWS_POLICY
    

    Substitua:

    • KUBERNETES_SERVICE_ACCOUNT: o nome da nova conta de serviço do Kubernetes.
    • WORKLOAD_IDENTITY_NAMESPACE: o nome do namespace em que as cargas de trabalho são executadas.
    • AWS_ROLE_NAME: o nome de um novo papel da AWS para as cargas de trabalho
    • EXISTING_AWS_POLICY: o nome do recurso da Amazon (ARN) de uma política do IAM da AWS. Por exemplo, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess.
  3. No diretório anthos-aws, use anthos-gke para alternar o contexto para o serviço de gerenciamento.

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

  4. Crie uma política do IAM da AWS que permita ao cluster de usuário assumir credenciais de segurança temporárias com o Serviço de token de segurança da AWS:

    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. Para criar um papel do IAM da AWS com essa política e anexar a política existente ao papel, execute os seguintes comandos:

    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}
    

    A ferramenta de linha de comando aws confirma se a política está anexada ao papel.

Como criar contas de serviço do Kubernetes para cargas de trabalho

Esta seção é destinada a desenvolvedores ou administradores de clusters.

Para criar contas de serviço do Kubernetes vinculadas ao papel de IAM da AWS especificado anteriormente, execute as etapas a seguir:

  1. No diretório anthos-aws, use anthos-gke para alternar o contexto para o cluster de usuário.

    cd anthos-aws
    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials CLUSTER_NAME
    Substitua CLUSTER_NAME pelo nome do cluster de usuário.

  2. Crie a conta de serviço do Kubernetes executando os seguintes comandos:

    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}
    

    Substitua:

    • AWS_ROLE_NAME: o nome do papel de IAM da AWS a ser aplicado às cargas de trabalho.
    • WORKLOAD_IDENTITY_NAMESPACE: o nome do namespace em que as cargas de trabalho são executadas.

Como aplicar credenciais aos pods

Esta seção é destinada a desenvolvedores.

Nesta seção, supomos que você implantou o webhook de identidade de carga de trabalho. Se você não implantou o webhook, pule para Como aplicar credenciais sem o webhook.

Aplicar credenciais com o webhook

Nesta seção, descrevemos como configurar os pods para ler as credenciais disponibilizadas pelo webhook.

Adicione a conta de serviço ao pod

Para usar a identidade da carga de trabalho com uma carga de trabalho, adicione a conta de serviço do Kubernetes aos seguintes campos:

  • Para uma implantação: spec.template.spec.serviceAccountName
  • Para um pod: spec.serviceAccount

O manifesto de pod a seguir inicia uma imagem CentOS básica e contém o campo 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

Substitua:

  • WORKLOAD_IDENTITY_NAMESPACE: o nome do namespace em que as cargas de trabalho são executadas.
  • KUBERNETES_SERVICE_ACCOUNT: o nome da conta de serviço do Kubernetes criada anteriormente

Verificar se os pods têm variáveis de ambiente definidas

Para verificar se os pods têm as variáveis de ambiente definidas, execute o seguinte comando para ver as informações do pod:

kubectl get pod --namespace WORKLOAD_IDENTITY_NAMESPACE POD_NAME -o yaml

Substitua:

  • WORKLOAD_IDENTITY_NAMESPACE: o nome do namespace em que as cargas de trabalho são executadas.
  • POD_NAME: o nome do pod a ser verificado

A saída contém os valores da variável de ambiente em spec.containers.command.env e o ponto de ativação do token IAM da AWS. Veja a seguir um exemplo de manifesto de 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:
  ...

Aplicar credenciais sem o webhook

Se você não implantar o webhook de identidade de carga de trabalho, precisará fazer o seguinte:

Crie um pod com credenciais para a identidade da carga de trabalho

Para criar um pod que inclua as credenciais necessárias para a identidade da carga de trabalho, execute as etapas a seguir:

  1. Copie o seguinte manifesto de pod em um arquivo chamado sample-pod-no-webhook.yaml. A configuração inicia uma imagem básica do CentOS com as credenciais necessárias.

    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
    

    Substitua:

    • WORKLOAD_IDENTITY_NAMESPACE: o nome do namespace em que as cargas de trabalho são executadas.
    • IAM_ROLE_ARN: o ARN do papel de IAM concedido ao pod. Por exemplo, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess.
    • KUBERNETES_SERVICE_ACCOUNT: o nome da conta de serviço do Kubernetes criada anteriormente;
  2. Aplique o manifesto do pod ao cluster usando kubectl:

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

Verifique se os pods podem acessar os recursos da AWS

O procedimento a seguir descreve como verificar se o pod recebeu as credenciais necessárias para a identidade da carga de trabalho funcionar.

Para concluir as etapas, você precisa ter:

  • bash acesso do shell ao contêiner. a maioria das imagens de produção não tem um shell disponível. O exemplo a seguir mostra como usar o pod especificado na seção anterior para acessar o AWS S3.

  • O pod precisa ter acesso de saída à Internet para fazer o download da interface de linha de comando da AWS.

Para verificar se o pod pode acessar um bucket S3, execute as seguintes etapas:

  1. Use kubectl exec para iniciar um shell bash interativo no pod sample-centos-pod-no-webhook:

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

    Seu terminal abre o shell bash no pod.

  2. Verifique as permissões e as credenciais de IAM da AWS usando a ferramenta aws:

    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
    

    A ferramenta aws imprime informações de credenciais semelhantes às seguintes:

    {
        "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"
        }
    }
    

    Se a mensagem a seguir for exibida, verifique se o bucket está acessível publicamente: An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: Couldn't retrieve verification key from your identity provider, please reference AssumeRoleWithWebIdentity documentation for requirements

Como fazer upgrade do webhook

Se você criou um cluster do Kubernetes 1.18 ou inferior com a identidade da carga de trabalho ativada e a versão release-0.2.2-gke.0 do webhook da identidade da carga de trabalho, faça upgrade do webhook antes de fazer upgrade para o Kubernetes 1.19.

Para implantar o webhook, execute as seguintes etapas:

  1. Confira se o webhook está instalado executando os seguintes comandos:

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

    Se o webhook tiver sido implantado no cluster, a saída incluirá o seguinte:

    NAME                   WEBHOOKS   AGE
    pod-identity-webhook   1          11m
    

    Se o webhook não estiver implantado no cluster, pule estas etapas.

  2. Se você salvou o arquivo aws-webhook.yaml, é possível excluir o manifesto. Se você não tiver esse arquivo disponível, exclua os componentes do webhook manualmente. Escolha um arquivo ou componentes abaixo.

    arquivo

    Se você ainda tiver o arquivo aws-webhook.yaml, execute o comando a seguir para excluir o webhook:

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl delete -f aws-webhook.yaml
    

    Componentes

    Para excluir os componentes do webhook manualmente, execute os seguintes comandos:

    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
    

    Substitua WEBHOOK_NAMESPACE pelo namespace em que você instalou o webhook da identidade da carga de trabalho. Por exemplo: workload-identity-webhook.

  3. Verifique se você tem alguma solicitação de assinatura de certificado (CSRs, na sigla em inglês) pendente, executando o seguinte comando:

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get csr |grep pod-identity-webhook
    

    Se a saída estiver em branco, passe para a próxima etapa. Se houver CSRs pendentes, o comando kubectl listará os CSRs atuais. Para remover os CSRs, execute o seguinte comando:

    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}")
    

    Substitua WEBHOOK_NAMESPACE pelo namespace em que você instalou o webhook da identidade da carga de trabalho. Por exemplo: workload-identity-webhook.

  4. Siga as etapas em Criar o webhook para implantar a nova versão do webhook.

    Depois de implantar a nova versão do webhook, reinicie os pods que usam o webhook. Reinicie os pods consultando Como fazer upgrade de um cluster de usuários.

Limpeza

Nesta seção, mostramos como remover recursos que foram criados anteriormente neste documento.

Limpar a conta de serviço e o papel do IAM associado

Para excluir a conta de serviço e o papel de IAM associado, execute as seguintes etapas:

  1. Limpe a conta de serviço:

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

    Substitua:

    • KUBERNETES_SERVICE_ACCOUNT: o nome da nova conta de serviço do Kubernetes.
    • WORKLOAD_IDENTITY_NAMESPACE: o nome do namespace em que as cargas de trabalho são executadas.
  2. Limpe o papel do AWS IAM. Escolha uma das seguintes opções:

    • Exclua o papel de IAM da AWS com o console da AWS.

    • Exclua o papel com a ferramenta de linha de comando da AWS usando os comandos a seguir:

      aws iam  detach-role-policy \
        --role-name=${AWS_ROLE_NAME} \
        --policy-arn=${AWS_POLICY}
      aws iam delete-role --role-name=${AWS_ROLE_NAME}
      

Excluir o cluster de usuários

Para excluir o cluster de usuários, siga as etapas em Como desinstalar o GKE na AWS.

Limpar o provedor OIDC da AWS

Depois que o cluster de usuários for excluído, cancele o registro e exclua o provedor OIDC na AWS usando o seguinte comando de shell bash ou a IU da Web da AWS.

  1. No diretório anthos-aws, use anthos-gke para alternar o contexto para o serviço de gerenciamento.

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

  2. Exclua o papel com a ferramenta de linha de comando da AWS com os comandos a seguir:

    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}
    

    Você receberá a confirmação de que o provedor AWS OIDC foi excluído.

A seguir