Uso de la identidad de la carga de trabajo con AWS

Este tema describe cómo habilitar la identidad de carga de trabajo para sus cargas de trabajo de GKE en AWS para controlar su acceso a los recursos de AWS.

Para obtener información sobre el uso de la identidad de carga de trabajo con Google CloudCuentas de administración de identidad y acceso (IAM) para controlar el acceso a los recursos de GCP, consulte Uso de la identidad de la carga de trabajo con Google Cloud .

Descripción general

La identidad de la carga de trabajo utiliza los permisos de AWS IAM para controlar el acceso a los recursos en la nube. Con la identidad de la carga de trabajo, puede asignar diferentes roles de IAM a cada carga de trabajo. Este control preciso de permisos le permite seguir el principio del mínimo privilegio . Sin la identidad de la carga de trabajo, debe asignar roles de AWS IAM a sus nodos de GKE en AWS, otorgando a todas las cargas de trabajo del nodo los mismos permisos que al propio nodo.

Para habilitar la identidad de carga de trabajo para su clúster, complete los siguientes pasos, que están agrupados por los roles administrativos que los realizan.

Administrador de clúster

  1. Cree un depósito de almacenamiento en la nube para almacenar datos de descubrimiento de OIDC .
  2. Cree un rol de administración de identidad y acceso para leer desde ese depósito.
  3. Cree un clúster de usuarios con la identidad de carga de trabajo habilitada .
  4. Cree un webhook en su clúster que aplique las credenciales de identidad de la carga de trabajo a los pods al crearlos. Si no desea usar el webhook, puede configurar manualmente las variables de entorno en sus pods.
  5. Configurar el proveedor AWS OIDC .
  6. Crear roles y políticas de AWS IAM .
Administrador o desarrollador de clúster
  1. Cree cuentas de servicio de Kubernetes y vincúlelas con políticas de AWS.
Revelador
  1. Aplicar credenciales a tus Pods .

Prerrequisitos

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

  • Un servicio de administración de GKE en AWS.
  • Clústeres de usuarios que ejecutan una versión de Kubernetes superior a 1.17.9.

  • Los siguientes permisos y herramientas.

Permisos

Para crear un clúster con la identidad de carga de trabajo habilitada, necesita los siguientes permisos:

Google Cloud

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

AWS

  • Crear un proveedor de AWS OIDC
  • Crear roles de AWS IAM

Herramientas

En su máquina local, le recomendamos tener instalada la herramienta jq .

Creación del depósito de descubrimiento de OIDC

Esta sección es para administradores de clúster .

Su clúster de usuarios debe almacenar los datos de descubrimiento de OIDC en un depósito de Cloud Storage de acceso público. Este depósito incluye la configuración de descubrimiento de OIDC y las claves públicas. AWS utiliza este contenido para autenticar las solicitudes de sus clústeres de usuarios.

Su depósito debe tener los siguientes atributos:

Si no tiene un depósito con estos atributos, cree uno utilizando 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

Reemplace BUCKET_NAME con el nombre de su nuevo depósito.

Otorgar permisos a la cuenta de servicio de administración

La cuenta de servicio de administración de identidad y acceso para el servicio de administración de GKE en AWS necesita permisos para leer y escribir objetos en este depósito.

  1. Otorgue permisos a su cuenta de servicio de administració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
    

    Reemplace PROJECT_NAME con su Google Cloud proyecto.

  2. Cree un nuevo rol de IAM con permisos para administrar este bucket. Para crear el rol, primero guarde la definición del rol en un archivo, luego créelo y vincúlelo a su cuenta de servicio de administración.

    Para completar estos pasos, ejecute 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
    

    Reemplace PROJECT_NAME con su Google Cloud proyecto.

    La CLI de Google Cloud confirma que se creó el enlace de política.

Creación de un clúster de usuarios

Esta sección es para administradores de clúster .

Crear un clúster de usuarios con la identidad de carga de trabajo habilitada

Cree un clúster de usuarios que contenga detalles sobre su bucket de descubrimiento de OIDC. Esta información se establece en el campo spec.controlPlane.workloadIdentity.oidcDiscoveryGCSBucket de su AWSCluster .

En este ejemplo, se crea un clúster manualmente a partir de los CRD AWSCluster y AWSNodePool .

  1. Vaya al directorio con su configuración de GKE en AWS. Este directorio se creó al instalar el servicio de administración .

    cd anthos-aws

  2. Desde su directorio anthos-aws , use anthos-gke para cambiar el contexto a su servicio de administración.

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

  3. Abra un editor de texto y copie la siguiente definición 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
    

    Reemplace lo siguiente:

    • CLUSTER_NAME : el nombre de su clúster.
    • AWS_REGION : la región de AWS donde se ejecuta su clúster.

    • VPC_ID : el ID de la VPC donde se ejecuta su clúster.

    • POD_ADDRESS_CIDR_BLOCKS : el rango de direcciones IPv4 que utilizan los pods del clúster. Actualmente, solo se admite un rango. Este rango no debe superponerse con ninguna subred accesible desde su red. Es seguro usar el mismo rango en varios objetos AWSCluster. Por ejemplo, 10.2.0.0/16 .

    • SERVICE_ADDRESS_CIDR_BLOCKS : el rango de direcciones IPv4 que utilizan los servicios del clúster. Actualmente, solo se admite un rango. Este rango no debe solaparse con ninguna subred accesible desde su red. Es seguro usar el mismo rango en varios objetos de AWSCluster. Por ejemplo, 10.1.0.0/16 .

    • SERVICE_LOAD_BALANCER_SUBNETS : los ID de subred donde GKE en AWS puede crear balanceadores de carga públicos o privados.

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

    • AWS_INSTANCE_TYPE : un tipo de instancia EC2 compatible .

    • SSH_KEY_NAME : un par de claves de AWS EC2 .

    • CONTROL_PLANE_SUBNET_IDS : los ID de subred en las AZ donde se ejecutan sus instancias del plano de control.

    • CONTROL_PLANE_SECURITY_GROUPS : ID de grupo de seguridad creado durante la instalación del servicio de administración. Puede personalizarlo añadiendo los ID de grupo de seguridad necesarios para conectarse al plano de control.

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

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

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

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

    • ROOT_VOLUME_KEY con el nombre de recurso de Amazon de la clave 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 utilizados por etcd.

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

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

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

    • ARN_OF_KMS_KEY : la clave AWS KMS utilizada para cifrar los secretos del clúster.

    • ANTHOS_CONNECT_NAME : el nombre de membresía de Connect usado para registrar su clúster. El nombre de membresía debe ser único. Por ejemplo, projects/ YOUR_PROJECT /locations/global/memberships/ CLUSTER_NAME , donde YOUR_PROJECT es su Google Cloud Proyecto y CLUSTER_NAME es un nombre único en el proyecto. Este campo es opcional.

    • YOUR_PROJECT : su ID de proyecto.

    • GCP_REGION : el Google Cloud Región donde desea almacenar registros. Elija una región cercana a la región de AWS. Para obtener más información, consulte Ubicaciones globales - Regiones y zonas ; por ejemplo, us-central1 .

    • ENABLE_LOGGING : true o false , si el registro en la nube 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 bucket de Cloud Storage que contiene la información de descubrimiento de la identidad de la carga de trabajo . Este campo es opcional.

  4. Cree uno o más AWSNodePools para su clúster. Abra un editor de texto y copie 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 
    

    Reemplace lo siguiente:

    • NODE_POOL_NAME : un nombre único para su AWSNodePool.
    • AWSCLUSTER_NAME : el nombre de su clúster de AWS. Por ejemplo, staging-cluster .
    • CLUSTER_VERSION : una versión compatible de GKE en AWS Kubernetes.
    • AWS_REGION : la misma región de AWS que su AWSCluster.
    • AWS_SUBNET_ID : una subred de AWS en la misma región que su AWSCluster.
    • MINIMUM_NODE_COUNT : el número mínimo de nodos en el grupo de nodos. Consulte Escalado de clústeres de usuarios para obtener más información.
    • MAXIMUM_NODE_COUNT : el número máximo de nodos en el grupo de nodos.
    • MAXIMUM_PODS_PER_NODE_COUNT : la cantidad máxima 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 AWS KMS asignado a cada trabajador del grupo de nodos.
    • NODE_IAM_PROFILE : el nombre del perfil de instancia de AWS EC2 asignado a los nodos del grupo.
    • ROOT_VOLUME_SIZE : el tamaño, en gibibytes (GiB), de los volúmenes raíz de su plano de control.
    • VOLUME_TYPE : tipo de volumen de AWS EBS del nodo. Por ejemplo, gp3 .
    • IOPS : cantidad de operaciones de E/S aprovisionadas por segundo (IOPS) para volúmenes. Solo válido cuando volumeType es gp3 .
    • NODE_VOLUME_KEY : ARN de la clave AWS KMS utilizada para cifrar el volumen. Para obtener más información, consulte "Uso de una CMK administrada por el cliente para cifrar volúmenes" .
  5. Aplique los manifiestos a su 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 kubeconfig

Mientras se inicia el clúster de usuarios, puede crear un contexto kubeconfig para el nuevo clúster. Este contexto se usa para autenticarse en un clúster de usuarios o de administración.

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

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

    Reemplace CLUSTER_NAME con el nombre de su clúster. Por ejemplo, cluster-0 .

  2. Utilice kubectl para autenticarse en su nuevo clúster de usuarios.

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

    Si su clúster está listo, la salida incluye las URL de los componentes de Kubernetes dentro de su clúster.

Visualización del estado de su clúster

El servicio de administración aprovisiona recursos de AWS cuando aplica un AWSCluster o AWSNodePool .

  1. Desde su directorio anthos-aws , use anthos-gke para cambiar el contexto a su servicio de administración.

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

  2. Para enumerar sus clústeres, utilice kubectl get AWSClusters .

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

    La salida incluye el nombre, el estado, la edad, la versión y el punto final de cada clúster.

    Por ejemplo, la siguiente salida incluye solo 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 su clúster

Para ver eventos recientes de Kubernetes de su clúster de usuarios, use kubectl get events .

  1. Desde su directorio anthos-aws , use anthos-gke para cambiar el contexto a su servicio de administración.

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

  2. Ejecute kubectl get events .

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

La salida incluye información, advertencias y errores relacionados con su servicio de administración.

Creación del webhook de identidad de carga de trabajo

Esta sección es para administradores de clúster .

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

  • AWS_ROLE_ARN : el nombre de recurso de Amazon (ARN) del rol de IAM
  • 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, sus cargas de trabajo pueden llamar a la herramienta de línea de comandos de AWS o el SDK puede acceder a los recursos otorgados al rol de AWS.

La creación del webhook es opcional. Si decide no crearlo, deberá configurar las variables de entorno indicadas anteriormente en el pod. Para obtener información sobre cómo no usar un webhook, consulte "Aplicar credenciales sin el webhook" .

Crear archivos YAML para el webhook

Para implementar el webhook, realice los siguientes pasos:

  1. Desde su directorio anthos-aws , use anthos-gke para cambiar el contexto a su servicio de administración.

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

  2. Obtenga el nombre del clúster de usuarios con kubectl :

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

    kubectl muestra todos los clústeres de usuarios. Seleccione el clúster de usuarios que creó con la identidad de carga de trabajo habilitada .

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

    CLUSTER_NAME=CLUSTER_NAME
    

    Reemplace CLUSTER_NAME por el nombre de su clúster. Por ejemplo, cluster-0 .

  4. Establecer variables de entorno para la imagen y el espacio de nombres del pod de identidad de carga de trabajo.

    IDENTITY_IMAGE=amazon/amazon-eks-pod-identity-webhook:ed8c41f
    
    WEBHOOK_NAMESPACE=workload-identity-webhook
    
  5. Genere el manifiesto YAML del webhook en un archivo llamado aws-webhook.yaml realizando los siguientes 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 su clúster.

Aplique el webhook a su clúster de usuarios

Para aplicar el webhook a su clúster de usuarios, realice los siguientes pasos.

  1. Aplique el archivo aws-webhook.yaml a su clúster de usuarios.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f aws-webhook.yaml
    
  2. Al aplicar el manifiesto, el pod del webhook genera solicitudes de firma de certificado (CSR) de Kubernetes. Apruebe 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. Verificar que no existan CSR restantes sin aprobar.

    Utilice kubectl get csr para verificar que todos los CSR del system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook estén aprobados:

    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
    

Configuración del proveedor AWS OIDC

Esta sección es para administradores de clúster .

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

Para registrar su bucket de descubrimiento de OIDC como proveedor de OIDC con AWS, realice los siguientes pasos:

  1. Desde su directorio anthos-aws , use anthos-gke para cambiar el contexto a su servicio de administración.

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

  2. Guarde 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. Utilice la herramienta de línea de comandos aws para crear un proveedor 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 para storage.googleapis.com , ejecute los siguientes comandos:

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

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

Creación de roles y políticas de AWS IAM

Esta sección es para administradores de clúster .

Cree un rol de IAM de AWS para vincularlo a una cuenta de servicio de Kubernetes. El rol de IAM tiene permisos para sts:AssumeRoleWithWebIdentity .

Para crear el rol, realice los siguientes pasos:

  1. Busque o cree una política de AWS IAM que otorgue los permisos necesarios para sus cargas de trabajo.

    Necesita el nombre de recurso de Amazon (ARN) de la política de AWS IAM . Por ejemplo, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess .

  2. Establezca variables de entorno con su 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
    

    Reemplace lo siguiente:

    • 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 sus cargas de trabajo
    • EXISTING_AWS_POLICY : el nombre de recurso de Amazon (ARN) de una política de AWS IAM existente. Por ejemplo, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess .
  3. Desde su directorio anthos-aws , use anthos-gke para cambiar el contexto a su servicio de administración.

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

  4. Cree una política de AWS IAM que permita que su clúster de usuarios asuma credenciales de seguridad temporales con el servicio de token 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 AWS IAM con esta política y adjuntar su política existente al rol, ejecute 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 su rol.

Creación de cuentas de servicio de Kubernetes para cargas de trabajo

Esta sección es para desarrolladores o administradores de clúster .

Para crear cuentas de servicio de Kubernetes vinculadas a la función de AWS IAM que se especificó anteriormente, realice los siguientes pasos:

  1. Desde su directorio anthos-aws , use anthos-gke para cambiar el contexto a su clúster de usuarios.

    cd anthos-aws
    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials CLUSTER_NAME
    Reemplace CLUSTER_NAME con el nombre de su clúster de usuarios.

  2. Cree 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}
    

    Reemplace lo siguiente:

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

Aplicar credenciales a sus pods

Esta sección es para desarrolladores .

En esta sección se asume que ha implementado el webhook de identidad de la carga de trabajo. Si no lo ha implementado, vaya a "Aplicación de credenciales sin el webhook" .

Aplicar credenciales con el webhook

Esta sección describe cómo configurar sus Pods para leer las credenciales disponibles mediante el webhook.

Agregar la cuenta de servicio al Pod

Para usar la identidad de carga de trabajo con una carga de trabajo, agregue la cuenta de servicio de Kubernetes a los siguientes campos:

  • Para una implementación: spec.template.spec.serviceAccountName
  • Para un pod: spec.serviceAccount

El siguiente manifiesto de Pod lanza 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

Reemplace lo siguiente:

  • 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 creó anteriormente

Comprueba si los pods tienen las variables de entorno configuradas

Para comprobar si los Pods tienen las variables de entorno configuradas, ejecute el siguiente comando para obtener la información del Pod:

kubectl get pod --namespace WORKLOAD_IDENTITY_NAMESPACE POD_NAME -o yaml

Reemplace lo siguiente:

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

La salida 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 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 el webhook

Si no implementa el webhook de identidad de carga de trabajo, deberá hacer lo siguiente:

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

Para crear un pod que incluya las credenciales necesarias para la identidad de la carga de trabajo, realice los siguientes pasos:

  1. Copia el siguiente manifiesto del pod en un archivo llamado sample-pod-no-webhook.yaml . La configuración lanza 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
    

    Reemplace lo siguiente:

    • WORKLOAD_IDENTITY_NAMESPACE : el nombre del espacio de nombres donde se ejecutan las cargas de trabajo.
    • IAM_ROLE_ARN : ARN del rol de IAM asignado al pod. Por ejemplo, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess .
    • KUBERNETES_SERVICE_ACCOUNT : el nombre de la cuenta de servicio de Kubernetes que creó anteriormente.
  2. Aplique el manifiesto del pod a su clúster usando 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

El siguiente procedimiento describe cómo verificar si el Pod ha recibido las credenciales necesarias para que la identidad de la carga de trabajo funcione.

Para completar los pasos, necesitas tener lo siguiente:

  • Acceso al contenedor mediante shell bash ; la mayoría de las imágenes de producción no tienen un shell disponible. El siguiente ejemplo muestra cómo usar el pod especificado en la sección anterior para acceder a AWS S3.

  • Su 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 S3, realice los siguientes pasos:

  1. Utilice 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
    

    Su terminal abre el shell bash en el Pod.

  2. Verifique los permisos y credenciales de AWS IAM mediante 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 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 ve el siguiente mensaje, verifique que el depósito sea de acceso público: An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: Couldn't retrieve verification key from your identity provider, please reference AssumeRoleWithWebIdentity documentation for requirements

Actualización del webhook

Si creó un clúster de Kubernetes 1.18 o anterior con la identidad de carga de trabajo habilitada y la versión del webhook de identidad de carga de trabajo release-0.2.2-gke.0 , debe actualizar el webhook antes de actualizar a Kubernetes 1.19.

Para actualizar el webhook, realice los siguientes pasos:

  1. Confirme que el webhook esté instalado ejecutando los siguientes comandos:

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

    Si su clúster tiene el webhook implementado, la salida incluye lo siguiente:

    NAME                   WEBHOOKS   AGE
    pod-identity-webhook   1          11m
    

    Si el webhook no está implementado en su clúster, puede omitir los siguientes pasos.

  2. Si guardó el archivo aws-webhook.yaml , puede eliminar el manifiesto. Si no tiene este archivo disponible, puede eliminar los componentes del webhook manualmente. Elija entre el archivo o los componentes a continuación.

    Archivo

    Si aún tiene el archivo aws-webhook.yaml , ejecute 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, ejecute 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
    

    Reemplace WEBHOOK_NAMESPACE con el espacio de nombres donde instaló el webhook de identidad de carga de trabajo. Por ejemplo workload-identity-webhook .

  3. Compruebe si tiene solicitudes de firma de certificado (CSR) restantes ejecutando el siguiente comando:

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

    Si la salida está en blanco, vaya al siguiente paso. Si quedan CSR, el comando kubectl listará las CSR existentes. Para eliminarlas, ejecute 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}")
    

    Reemplace WEBHOOK_NAMESPACE con el espacio de nombres donde instaló el webhook de identidad de carga de trabajo. Por ejemplo workload-identity-webhook .

  4. Siga los pasos en Crear el webhook para implementar la nueva versión del webhook.

    Después de implementar la nueva versión del webhook, debe reiniciar los pods que lo usan. Puede reiniciar los pods actualizando un clúster de usuarios .

Limpiando

Esta sección le muestra cómo eliminar recursos que creó anteriormente en este documento.

Limpiar la cuenta de servicio y su rol IAM asociado

Para eliminar la cuenta de servicio y su rol de IAM asociado, realice los siguientes pasos:

  1. Limpiar la cuenta de servicio:

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

    Reemplace lo siguiente:

    • 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. Limpie la función de AWS IAM. Elija una de las siguientes opciones:

    • Eliminar la función de AWS IAM con la consola de AWS .

    • Elimine la función con la herramienta de línea de comandos de AWS utilizando 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 su clúster de usuarios

Para eliminar su clúster de usuarios, realice los pasos que se indican en Desinstalación de GKE en AWS .

Limpiar el proveedor de AWS OIDC

Una vez eliminado el clúster de usuarios, cancele el registro y elimine el proveedor OIDC en AWS mediante el siguiente comando de shell bash o la consola de AWS.

  1. Desde su directorio anthos-aws , use anthos-gke para cambiar el contexto a su servicio de administración.

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

  2. Elimine la función 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á la confirmación de que se eliminó el proveedor de AWS OIDC.

¿Qué sigue?