Usar Workload Identity con AWS

En este tema se describe cómo habilitar Workload Identity para tus cargas de trabajo de GKE en AWS y controlar su acceso a los recursos de AWS.

Para obtener información sobre cómo usar la identidad de carga de trabajo con cuentas de gestión de identidades y accesos (IAM) para controlar el acceso a los recursos de GCP, consulta Usar la identidad de carga de trabajo con Google Cloud. Google Cloud

Información general

Workload Identity usa los permisos de AWS IAM para controlar el acceso a los recursos de la nube. Con Workload Identity, puedes asignar diferentes roles de IAM a cada carga de trabajo. Este control pormenorizado de los permisos te permite seguir el principio de mínimos accesos. Si no usas Workload Identity, debes asignar roles de gestión de identidades y accesos de AWS a tus nodos de GKE en AWS, lo que significa que todas las cargas de trabajo del nodo tendrán los mismos permisos que el propio nodo.

Para habilitar Workload Identity en tu clúster, sigue estos pasos, que se agrupan según los roles de administrador que los llevan a cabo.

Administrador del clúster

  1. Crea un segmento de Cloud Storage para almacenar datos de descubrimiento de OIDC.
  2. Crea un rol de gestión de identidades y accesos para leer de ese segmento.
  3. Crea un clúster de usuarios con Workload Identity habilitado.
  4. Crea un webhook en tu clúster que aplique las credenciales de identidad de carga de trabajo a los pods cuando se creen. Si no quieres usar el webhook, puedes definir manualmente las variables de entorno en tus pods.
  5. Configura el proveedor de OIDC de AWS.
  6. Crea roles y políticas de gestión de identidades y accesos de AWS.
Administrador o desarrollador del clúster
  1. Crea cuentas de servicio de Kubernetes y vincula políticas de AWS a ellas.
Desarrollador
  1. Aplica las credenciales a tus pods.

Requisitos previos

Para completar los pasos de este documento, debe tener la siguiente configuración:

  • Un servicio de gestión de GKE on AWS.
  • Clústeres de usuario que ejecutan una versión de Kubernetes superior a 1.17.9.

  • Los siguientes permisos y herramientas.

Permisos

Para crear un clúster con Workload Identity habilitado, necesitas los siguientes permisos:

Google Cloud

  • Crea un segmento de Cloud Storage de lectura pública con el acceso uniforme a nivel de segmento habilitado.
  • Concede permisos de lectura y escritura a management-sa@PROJECT_NAME.iam.gserviceaccount.com en el segmento.

AWS

  • Crear un proveedor de OIDC de AWS
  • Crear roles de gestión de identidades y accesos de AWS

Herramientas

En tu máquina local, te recomendamos que tengas instalada la herramienta jq.

Crear el segmento de descubrimiento de OIDC

Esta sección está dirigida a administradores de clústeres.

Tu clúster de usuarios debe almacenar los datos de descubrimiento de OIDC en un segmento de Cloud Storage accesible públicamente. El segmento incluye la configuración de descubrimiento de OIDC y las claves públicas. AWS usa el contenido para autenticar las solicitudes de tus clústeres de usuarios.

Su contenedor debe tener los siguientes atributos:

Si no tiene ningún segmento con estos atributos, cree uno con los siguientes comandos 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

Sustituye BUCKET_NAME por el nombre del nuevo.

Conceder permisos a la cuenta de servicio de gestión

La cuenta de servicio de gestión de identidades y accesos del servicio de gestión de GKE en AWS necesita permisos para leer y escribir objetos en este segmento.

  1. Concede permisos a tu cuenta de servicio de gestión mediante el siguiente comando.

    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
    

    Sustituye PROJECT_NAME por tu Google Cloud proyecto.

  2. Crea un rol de gestión de identidades y accesos con permisos para gestionar este segmento. Para crear el rol, primero guarda la definición del rol en un archivo, luego crea el rol y vincúlalo a tu cuenta de servicio de gestión.

    Para completar estos pasos, ejecuta los siguientes 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
    

    Sustituye PROJECT_NAME por tu Google Cloud proyecto.

    Google Cloud CLI confirma que se ha creado la vinculación de la política.

Crear un clúster de usuarios

Esta sección está dirigida a administradores de clústeres.

Crear un clúster de usuarios con Workload Identity habilitado

Crea un clúster de usuarios que contenga detalles sobre tu contenedor de descubrimiento de OIDC. Puede definir esta información en el campo AWSClusterspec.controlPlane.workloadIdentity.oidcDiscoveryGCSBucket.

En este ejemplo, crearás un clúster manualmente a partir de los CRDs AWSCluster y AWSNodePool.

  1. Cambia al directorio con tu configuración de GKE en AWS. Has creado este directorio al instalar el servicio de gestión.

    cd anthos-aws

  2. En tu directorio de anthos-aws, usa anthos-gke para cambiar el contexto a tu servicio de gestión.

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

  3. Abre un editor de texto y copia la siguiente definición de AWSCluster en un archivo llamado 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
    

    Haz los cambios siguientes:

    • CLUSTER_NAME: el nombre de tu clúster.
    • AWS_REGION: la región de AWS en la que se ejecuta el clúster.

    • VPC_ID: el ID de la VPC en la que se ejecuta el clúster.

    • POD_ADDRESS_CIDR_BLOCKS: el intervalo de direcciones IPv4 que usan los pods del clúster. Actualmente, solo se admite un intervalo. El intervalo no se puede solapar con ninguna subred accesible desde tu red. Es seguro usar el mismo intervalo en varios objetos AWSCluster diferentes. Por ejemplo, 10.2.0.0/16.

    • SERVICE_ADDRESS_CIDR_BLOCKS: el intervalo de direcciones IPv4 que usan los servicios del clúster. Actualmente, solo se admite un intervalo. El intervalo no debe solaparse con ninguna subred accesible desde tu red. Puedes usar el mismo intervalo en varios objetos AWSCluster sin problemas. Por ejemplo, 10.1.0.0/16.

    • SERVICE_LOAD_BALANCER_SUBNETS: los IDs de las subredes en las que GKE en AWS puede crear balanceadores de carga públicos o privados.

    • CLUSTER_VERSION: a versión de Kubernetes compatible con GKE en AWS. La versión más reciente es la 1.25.5-gke.2100.

    • AWS_INSTANCE_TYPE: un tipo de instancia de EC2 admitido.

    • SSH_KEY_NAME: un par de claves de AWS EC2.

    • CONTROL_PLANE_SUBNET_IDS: los IDs de subred de las zonas de disponibilidad en las que se ejecutan las instancias del plano de control.

    • CONTROL_PLANE_SECURITY_GROUPS: un securityGroupID creado durante la instalación del servicio de gestión. Para personalizarlo, añade los securityGroupIDs necesarios para conectarte al plano de control.

    • CONTROL_PLANE_IAM_PROFILE: nombre de la instancia de AWS EC2 perfil asignado a las réplicas del plano de control.

    • ROOT_VOLUME_SIZE: tamaño, en gibibytes (GiB), de los volúmenes raíz del plano de control.

    • ROOT_VOLUME_TYPE con el tipo de volumen de EBS. Por ejemplo, gp3.

    • ROOT_VOLUME_IOPS con la cantidad de operaciones de E/S aprovisionadas por segundo (IOPS) del volumen. Solo es válido cuando volumeType es GP3. Para obtener más información, consulta Volúmenes SSD de uso general (gp3).

    • ROOT_VOLUME_KEY con el nombre de recurso de Amazon de la clave de AWS KMS que cifra los volúmenes raíz de la instancia del plano de control.

    • ETCD_VOLUME_SIZE: el tamaño de los volúmenes que usa etcd.

    • ETCD_VOLUME_TYPE con el tipo de volumen de EBS. Por ejemplo, gp3.

    • ETCD_VOLUME_IOPS con la cantidad de operaciones de E/S aprovisionadas por segundo (IOPS) del volumen. Solo es válido cuando volumeType es gp3. Para obtener más información, consulta Volúmenes SSD de uso general (gp3).

    • ETCD_VOLUME_KEY con el nombre de recurso de Amazon de la clave de AWS KMS que cifra los volúmenes de datos de etcd del plano de control.

    • ARN_OF_KMS_KEY: la clave de KMS de AWS que se usa para cifrar los secretos del clúster.

    • ANTHOS_CONNECT_NAME: el nombre de miembro de Connect que se usa para registrar el clúster. El nombre de la suscripción debe ser único. Por ejemplo, projects/YOUR_PROJECT/locations/global/memberships/CLUSTER_NAME, donde YOUR_PROJECT es tu Google Cloud proyecto y CLUSTER_NAME es un nombre único en tu proyecto. Este campo es opcional.

    • YOUR_PROJECT: tu ID de proyecto.

    • GCP_REGION: la Google Cloud región en la que quieres almacenar los registros. Elige una región cercana a la región de AWS. Para obtener más información, consulta Ubicaciones globales: regiones y zonas, como us-central1.

    • ENABLE_LOGGING: true o false, si Cloud Logging está habilitado en los nodos del plano de control.

    • ENABLE_MONITORING: true o false, si Cloud Monitoring está habilitado en los nodos del plano de control.

    • WORKLOAD_IDENTITY_BUCKET: el nombre del segmento de Cloud Storage que contiene la información de detección de tu identidad de carga de trabajo. Este campo es opcional.

  4. Crea uno o varios AWSNodePools para tu clúster. Abre un editor de texto y copia la siguiente definición de AWSCluster en un archivo llamado 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 
    

    Haz los cambios siguientes:

    • NODE_POOL_NAME: nombre único de tu AWSNodePool.
    • AWSCLUSTER_NAME: el nombre de tu AWSCluster. Por ejemplo, staging-cluster.
    • CLUSTER_VERSION: una versión de Kubernetes compatible con GKE en AWS.
    • AWS_REGION: la misma región de AWS que tu AWSCluster.
    • AWS_SUBNET_ID: una subred de AWS en la misma región que tu AWSCluster.
    • MINIMUM_NODE_COUNT: número mínimo de nodos del grupo de nodos. Consulta más información sobre cómo escalar clústeres de usuarios.
    • MAXIMUM_NODE_COUNT: número máximo de nodos del grupo de nodos.
    • MAXIMUM_PODS_PER_NODE_COUNT: número máximo de pods que GKE en AWS puede asignar a un nodo.
    • AWS_NODE_TYPE: un tipo de instancia de AWS EC2.
    • KMS_KEY_PAIR_NAME: el par de claves de KMS de AWS asignado a cada trabajador del grupo de nodos.
    • NODE_IAM_PROFILE: nombre del perfil de instancia de AWS EC2 asignado a los nodos del grupo.
    • ROOT_VOLUME_SIZE: tamaño, en gibibytes (GiB), de los volúmenes raíz del plano de control.
    • VOLUME_TYPE: el tipo de volumen de EBS de AWS del nodo. Por ejemplo, gp3.
    • IOPS: la cantidad de operaciones de entrada/salida por segundo (IOPS) aprovisionadas para los volúmenes. Solo es válido cuando volumeType es gp3.
    • NODE_VOLUME_KEY: el ARN de la clave de KMS de AWS que se usa para cifrar el volumen. Para obtener más información, consulta Usar una CMK gestionada por el cliente para cifrar volúmenes.
  5. Aplica los manifiestos a tu servicio de gestión.

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

Crear un archivo kubeconfig

Mientras se inicia el clúster de usuarios, puedes crear un contexto kubeconfig para el nuevo clúster de usuarios. El contexto se usa para autenticar a un usuario o a un clúster de gestión.

  1. Usa anthos-gke aws clusters get-credentials para generar un kubeconfig para tu clúster de usuarios en ~/.kube/config.

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

    Sustituye CLUSTER_NAME por el nombre de tu clúster. Por ejemplo, cluster-0.

  2. Usa kubectl para autenticarte en tu nuevo clúster de usuarios.

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

    Si el clúster está listo, el resultado incluye las URLs de los componentes de Kubernetes del clúster.

Ver el estado de un clúster

El servicio de gestión aprovisiona recursos de AWS cuando aplicas un AWSCluster o un AWSNodePool.

  1. En tu directorio de anthos-aws, usa anthos-gke para cambiar el contexto a tu servicio de gestión.

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

  2. Para enumerar tus clústeres, usa kubectl get AWSClusters.

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

    La salida incluye el nombre, el estado, la antigüedad, la versión y el endpoint de cada clúster.

    Por ejemplo, el siguiente resultado solo incluye un AWSCluster llamado 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 los eventos de un clúster

Para ver los eventos de Kubernetes recientes de tu clúster de usuario, usa kubectl get events.

  1. En tu directorio de anthos-aws, usa anthos-gke para cambiar el contexto a tu servicio de gestión.

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

  2. Ejecuta kubectl get events.

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

La salida incluye información, advertencias y errores relacionados con tu servicio de gestión.

Crear el webhook de Workload Identity

Esta sección está dirigida a administradores de clústeres.

Para proporcionar credenciales de Workload Identity a tus cargas de trabajo sin necesidad de realizar ninguna configuración adicional, puedes crear un webhook en tus clústeres de usuarios. Este webhook intercepta las solicitudes de creación de pods y, a continuación, pone la siguiente información de AWS IAM a disposición del pod como variables de entorno:

  • AWS_ROLE_ARN: el nombre de recurso de Amazon (ARN) del rol de gestión de identidades y accesos
  • aws-iam-token: el token intercambiado por las credenciales de AWS IAM
  • AWS_WEB_IDENTITY_TOKEN_FILE: la ruta donde se almacena el token

Con estas variables, tus cargas de trabajo pueden llamar a la herramienta de línea de comandos de AWS o el SDK puede acceder a los recursos concedidos al rol de AWS.

Crear el webhook es opcional. Si decides no crear el webhook, debes definir las variables de entorno que se han indicado anteriormente en el pod. Para obtener información sobre cómo no usar un webhook, consulta Aplicar credenciales sin el webhook.

Crear archivos YAML para el webhook

Para implementar el webhook, sigue estos pasos:

  1. En tu directorio de anthos-aws, usa anthos-gke para cambiar el contexto a tu servicio de gestión.

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

  2. Obtén el nombre del clúster de usuarios con kubectl:

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

    kubectl muestra todos tus clústeres de usuarios. Elige el clúster de usuarios que has creado con Workload Identity habilitado.

  3. Define el nombre del clúster en una variable de entorno.

    CLUSTER_NAME=CLUSTER_NAME
    

    Sustituye CLUSTER_NAME por el nombre de tu clúster. Por ejemplo, cluster-0.

  4. Define las variables de entorno de la imagen del pod y del espacio de nombres de la identidad de carga de trabajo.

    IDENTITY_IMAGE=amazon/amazon-eks-pod-identity-webhook:ed8c41f
    
    WEBHOOK_NAMESPACE=workload-identity-webhook
    
  5. Genera el manifiesto YAML del webhook en un archivo llamado aws-webhook.yaml siguiendo estos pasos:

    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
    

    El contenido de aws-webhook.yaml está listo para aplicarse a tu clúster.

Aplica el webhook a tu clúster de usuarios

Para aplicar el webhook a tu clúster de usuarios, sigue estos pasos.

  1. Aplica el archivo aws-webhook.yaml a tu clúster de usuarios.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f aws-webhook.yaml
    
  2. Cuando apliques el manifiesto, el pod de webhook generará solicitudes de firma de certificado (CSR) de Kubernetes. Aprobar todas las solicitudes de system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook con 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. Verifica que no queden CSRs sin aprobar.

    Usa kubectl get csr para comprobar que todas las CSRs del solicitante system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook estén aprobadas:

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

    Respuesta:

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

Configurar el proveedor de OIDC de AWS

Esta sección está dirigida a administradores de clústeres.

Para crear un proveedor de OIDC en AWS, AWS requiere una autoridad de certificación (CA) intermedia o una huella digital del certificado de servidor. Tus credenciales de descubrimiento de OIDC se almacenan en storage.googleapis.com, con un certificado firmado por una CA intermedia llamada GTS CA 1C3. La huella digital SHA-1 de su CA intermedia GTS CA 1C3 es 08745487E891C19E3078C1F2A07E452950EF36F6.

Para registrar tu bucket de descubrimiento de OIDC como proveedor de OIDC en AWS, sigue estos pasos:

  1. En tu directorio de anthos-aws, usa anthos-gke para cambiar el contexto a tu servicio de gestión.

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

  2. Guarda la URL del emisor de OIDC, la ruta del host del emisor y la huella digital de Cloud Storage en variables de entorno.

    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. Usa la herramienta de línea de comandos aws para crear un proveedor de OIDC en AWS.

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

Actualizar la huella digital

Si Google rota la CA de storage.googleapis.com, ejecuta los siguientes comandos:

  1. Copia la huella digital del certificado actualizado, 08745487E891C19E3078C1F2A07E452950EF36F6.

  2. Sigue las instrucciones del comando aws iam update-open-id-connect-provider-thumbprint. Usa storage.googleapis.com como nombre de host de destino y 08745487E891C19E3078C1F2A07E452950EF36F6 como huella digital.

Crear roles y políticas de gestión de identidades y accesos de AWS

Esta sección está dirigida a administradores de clústeres.

Crea un rol de gestión de identidades y accesos de AWS para vincularlo a una cuenta de servicio de Kubernetes. El rol de gestión de identidades y accesos tiene permisos para sts:AssumeRoleWithWebIdentity.

Para crear el rol, sigue estos pasos:

  1. Busca o crea una política de gestión de identidades y accesos de AWS que conceda los permisos necesarios para tus cargas de trabajo.

    Necesitas el nombre de recurso de Amazon (ARN) de la política Política de gestión de identidades y accesos de AWS. Por ejemplo, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess.

  2. Define variables de entorno con tu información de autenticación.

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

    Haz los cambios siguientes:

    • KUBERNETES_SERVICE_ACCOUNT: el nombre de la nueva cuenta de servicio de Kubernetes
    • WORKLOAD_IDENTITY_NAMESPACE: el nombre del espacio de nombres donde se ejecutan las cargas de trabajo
    • AWS_ROLE_NAME: el nombre de un nuevo rol de AWS para tus cargas de trabajo
    • EXISTING_AWS_POLICY: el nombre de recurso de Amazon (ARN) de una política de gestión de identidades y accesos de AWS. Por ejemplo, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess.
  3. En tu directorio de anthos-aws, usa anthos-gke para cambiar el contexto a tu servicio de gestión.

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

  4. Crea una política de gestión de identidades y accesos de AWS que permita a tu clúster de usuarios asumir credenciales de seguridad temporales con el servicio de tokens de seguridad de 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 crear un rol de gestión de identidades y accesos de AWS con esta política y adjuntar tu política al rol, ejecuta los siguientes 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}
    

    La herramienta de línea de comandos aws confirma que la política está asociada a tu rol.

Crear cuentas de servicio de Kubernetes para cargas de trabajo

Esta sección está dirigida a desarrolladores o administradores de clústeres.

Para crear cuentas de servicio de Kubernetes vinculadas al rol de gestión de identidades y accesos de AWS que se ha especificado anteriormente, sigue estos pasos:

  1. En tu directorio de anthos-aws, usa anthos-gke para cambiar el contexto a tu clúster de usuarios.

    cd anthos-aws
    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials CLUSTER_NAME
    Sustituye CLUSTER_NAME por el nombre de tu clúster de usuario.

  2. Crea la cuenta de servicio de Kubernetes ejecutando los siguientes 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}
    

    Haz los cambios siguientes:

    • AWS_ROLE_NAME: nombre del rol de AWS IAM que se va a aplicar a tus cargas de trabajo
    • WORKLOAD_IDENTITY_NAMESPACE: el nombre del espacio de nombres donde se ejecutan las cargas de trabajo

Aplicar credenciales a tus pods

Esta sección está dirigida a desarrolladores.

En esta sección se presupone que ha implementado el webhook de Workload Identity. Si no has implementado el webhook, ve a la sección Aplicar credenciales sin el webhook.

Aplicar credenciales con el webhook

En esta sección se describe cómo configurar tus pods para que lean las credenciales que el webhook pone a su disposición.

Añadir la cuenta de servicio al pod

Para usar Workload Identity con una carga de trabajo, añade la cuenta de servicio de Kubernetes a los siguientes campos:

  • En una implementación: spec.template.spec.serviceAccountName
  • En un pódcast: spec.serviceAccount

El siguiente manifiesto de Pod inicia una imagen base de CentOS y contiene el 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

Haz los cambios siguientes:

  • WORKLOAD_IDENTITY_NAMESPACE: el nombre del espacio de nombres donde se ejecutan las cargas de trabajo
  • KUBERNETES_SERVICE_ACCOUNT: el nombre de la cuenta de servicio de Kubernetes que has creado anteriormente

Comprobar si los pods tienen las variables de entorno definidas

Para comprobar si los pods tienen definidas las variables de entorno, ejecuta el siguiente comando para obtener la información del pod:

kubectl get pod --namespace WORKLOAD_IDENTITY_NAMESPACE POD_NAME -o yaml

Haz los cambios siguientes:

  • WORKLOAD_IDENTITY_NAMESPACE: el nombre del espacio de nombres donde se ejecutan las cargas de trabajo
  • POD_NAME: el nombre del pod que se va a comprobar

El resultado contiene los valores de las variables de entorno en spec.containers.command.env y el punto de montaje del token de AWS IAM. A continuación, se muestra un ejemplo de archivo de manifiesto 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 credenciales sin la webhook

Si no implementas el webhook de Workload Identity, debes hacer lo siguiente:

Crear un pod con credenciales para la identidad de carga de trabajo

Para crear un Pod que incluya las credenciales necesarias para la identidad de carga de trabajo, sigue estos pasos:

  1. Copia el siguiente manifiesto de Pod en un archivo llamado sample-pod-no-webhook.yaml. La configuración inicia una imagen base de CentOS con las credenciales necesarias.

    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
    

    Haz los cambios siguientes:

    • WORKLOAD_IDENTITY_NAMESPACE: el nombre del espacio de nombres en el que se ejecutan las cargas de trabajo.
    • IAM_ROLE_ARN: el ARN del rol de gestión de identidades y accesos concedido al pod. Por ejemplo, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess.
    • KUBERNETES_SERVICE_ACCOUNT: el nombre de la cuenta de servicio de Kubernetes que has creado anteriormente.
  2. Aplica el manifiesto de Pod a tu clúster con kubectl:

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

Comprobar si los pods pueden acceder a los recursos de AWS

En el siguiente procedimiento se describe cómo comprobar si el pod ha recibido las credenciales necesarias para que funcione la identidad de carga de trabajo.

Para completar los pasos, necesitas lo siguiente:

  • bash acceso a la shell del contenedor; la mayoría de las imágenes de producción no tienen una shell disponible. En el siguiente ejemplo se muestra cómo usar el pod especificado en la sección anterior para acceder a AWS S3.

  • Tu Pod debe tener acceso saliente a Internet para descargar la interfaz de línea de comandos de AWS.

Para comprobar si el pod puede acceder a un bucket de S3, sigue estos pasos:

  1. Usa kubectl exec para iniciar un shell bash interactivo en el pod sample-centos-pod-no-webhook:

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

    Tu terminal abre el shell bash en el pod.

  2. Comprueba los permisos y las credenciales de AWS IAM con la herramienta 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
    

    La herramienta aws imprime información de las credenciales similar a la siguiente:

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

    Si ves el siguiente mensaje, comprueba que el contenedor sea accesible públicamente: An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: Couldn't retrieve verification key from your identity provider, please reference AssumeRoleWithWebIdentity documentation for requirements

Actualizar el webhook

Si has creado un clúster de Kubernetes 1.18 o una versión anterior con Workload Identity habilitado y la versión release-0.2.2-gke.0 del webhook de Workload Identity, debes actualizar el webhook antes de actualizar a Kubernetes 1.19.

Para actualizar el webhook, sigue estos pasos:

  1. Para confirmar que el webhook está instalado, ejecuta los siguientes comandos:

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

    Si el webhook está implementado en tu clúster, el resultado incluye lo siguiente:

    NAME                   WEBHOOKS   AGE
    pod-identity-webhook   1          11m
    

    Si el webhook no se ha implementado en tu clúster, puedes saltarte los pasos siguientes.

  2. Si has guardado el archivo aws-webhook.yaml, puedes eliminar el manifiesto. Si no tienes este archivo disponible, puedes eliminar los componentes del webhook manualmente. Elige entre los archivos o componentes que aparecen a continuación.

    Archivo

    Si aún tienes el archivo aws-webhook.yaml, ejecuta el siguiente comando para eliminar el webhook:

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

    Componentes

    Para eliminar manualmente los componentes del webhook, ejecuta los siguientes 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
    

    Sustituye WEBHOOK_NAMESPACE por el espacio de nombres en el que has instalado el webhook de Workload Identity. Por ejemplo: workload-identity-webhook.

  3. Comprueba si te queda alguna solicitud de firma de certificado (CSR) ejecutando el siguiente comando:

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

    Si el resultado está en blanco, ve al paso siguiente. Si queda alguna CSR, el comando kubectl mostrará las CSRs existentes. Para eliminar los CSRs, ejecuta el siguiente 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}")
    

    Sustituye WEBHOOK_NAMESPACE por el espacio de nombres en el que has instalado el webhook de Workload Identity. Por ejemplo, workload-identity-webhook.

  4. Sigue los pasos que se indican en Crear el webhook para implementar la nueva versión del webhook.

    Después de implementar la nueva versión del webhook, debes reiniciar los pods que lo usen. Puedes reiniciar tus pods actualizando un clúster de usuarios.

Eliminar los recursos utilizados

En esta sección se explica cómo eliminar los recursos que has creado anteriormente en este documento.

Eliminar la cuenta de servicio y el rol de gestión de identidades y accesos asociado

Para eliminar la cuenta de servicio y el rol de gestión de identidades y accesos asociado, sigue estos pasos:

  1. Limpiar la cuenta de servicio:

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

    Haz los cambios siguientes:

    • KUBERNETES_SERVICE_ACCOUNT: el nombre de la nueva cuenta de servicio de Kubernetes
    • WORKLOAD_IDENTITY_NAMESPACE: el nombre del espacio de nombres donde se ejecutan las cargas de trabajo
  2. Elimina el rol de gestión de identidades y accesos de AWS. Elige una de estas opciones:

    • Elimina el rol de gestión de identidades y accesos de AWS con la consola de AWS.

    • Elimina el rol con la herramienta de línea de comandos de AWS mediante los siguientes comandos:

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

Eliminar un clúster de usuarios

Para eliminar tu clúster de usuario, sigue los pasos que se indican en Desinstalar GKE en AWS.

Limpiar el proveedor de OIDC de AWS

Una vez que se haya eliminado el clúster de usuario, anula el registro y elimina el proveedor de OIDC en AWS mediante el siguiente comando de shell bash o la consola de AWS.

  1. En tu directorio de anthos-aws, usa anthos-gke para cambiar el contexto a tu servicio de gestión.

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

  2. Elimina el rol con la herramienta de línea de comandos de AWS con los siguientes comandos:

    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}
    

    Recibirás una confirmación de que se ha eliminado el proveedor de OIDC de AWS.

Siguientes pasos