Restringe el acceso para modificar y seleccionar ComputeClasses

Puedes usar ComputeClasses de Google Kubernetes Engine (GKE) para crear nodos que cumplan con varios requisitos de carga de trabajo. Los Pods pueden usar ComputeClasses para crear hardware. Según la clase de procesamiento, es posible que ese hardware tenga una gran demanda, esté disponible de forma limitada o sea relativamente costoso para tu empresa. En este instructivo, se muestra cómo usar el RBAC de Kubernetes y las ValidatingAdmissionPolicies para restringir la creación, el borrado, la modificación y la selección de ComputeClasses.

Estas restricciones pueden ayudarte a evitar situaciones como las siguientes:

  • Los Pods que no necesitan hardware especializado, como GPU o TPU, seleccionan ComputeClasses que solicitan ese hardware.
  • Una entidad no autorizada crea o modifica ComputeClasses para obtener acceso al hardware reservado para cargas de trabajo críticas.

En este documento, se usa un ejemplo de ValidatingAdmissionPolicy que bloquea tipos comunes de uso inadecuado, como tolerancias de comodín de ComputeClass o la selección de ComputeClass específicas no permitidas. Puedes modificar la política ValidatingAdmissionPolicy para satisfacer los requisitos específicos de tu organización, como bloquear las cargas de trabajo de ciertos equipos para que no usen ComputeClasses.

Objetivos

  • Usa un ValidatingAdmissionPolicy para limitar las ComputeClasses que los Pods pueden seleccionar en cada espacio de nombres a una lista aprobada.
  • Usa el control de acceso basado en roles (RBAC) para restringir quién puede crear, modificar o borrar ComputeClasses en tus clústeres.

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.

Es posible que los usuarios de Google Cloud nuevos cumplan con los requisitos para acceder a una prueba gratuita.

Cuando completes las tareas que se describen en este documento, podrás borrar los recursos que creaste para evitar que se te siga facturando. Para obtener más información, consulta Realiza una limpieza.

Antes de comenzar

  1. Accede a tu cuenta de Google Cloud . Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  2. Instala Google Cloud CLI.

  3. Si usas un proveedor de identidad externo (IdP), primero debes acceder a la gcloud CLI con tu identidad federada.

  4. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  5. Crea o selecciona un Google Cloud proyecto.

    Roles necesarios para seleccionar o crear un proyecto

    • Selecciona un proyecto: Para seleccionar un proyecto, no se requiere un rol de IAM específico. Puedes seleccionar cualquier proyecto en el que se te haya otorgado un rol.
    • Crear un proyecto: Para crear un proyecto, necesitas el rol de Creador de proyectos (roles/resourcemanager.projectCreator), que contiene el permiso resourcemanager.projects.create. Obtén más información para otorgar roles.
    • Crea un Google Cloud proyecto:

      gcloud projects create PROJECT_ID

      Reemplaza PROJECT_ID por un nombre para el proyecto Google Cloud que estás creando.

    • Selecciona el proyecto Google Cloud que creaste:

      gcloud config set project PROJECT_ID

      Reemplaza PROJECT_ID por el nombre de tu proyecto de Google Cloud .

  6. Si usas un proyecto existente en esta guía, verifica que tengas los permisos necesarios para completarla. Si creaste un proyecto nuevo, ya tienes los permisos necesarios.

  7. Verifica que la facturación esté habilitada para tu proyecto de Google Cloud .

  8. Habilita la API de Kubernetes Engine:

    Roles necesarios para habilitar las APIs

    Para habilitar las APIs, necesitas el rol de IAM de administrador de Service Usage (roles/serviceusage.serviceUsageAdmin), que contiene el permiso serviceusage.services.enable. Obtén más información para otorgar roles.

    gcloud services enable container.googleapis.com
  9. Instala Google Cloud CLI.

  10. Si usas un proveedor de identidad externo (IdP), primero debes acceder a la gcloud CLI con tu identidad federada.

  11. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  12. Crea o selecciona un Google Cloud proyecto.

    Roles necesarios para seleccionar o crear un proyecto

    • Selecciona un proyecto: Para seleccionar un proyecto, no se requiere un rol de IAM específico. Puedes seleccionar cualquier proyecto en el que se te haya otorgado un rol.
    • Crear un proyecto: Para crear un proyecto, necesitas el rol de Creador de proyectos (roles/resourcemanager.projectCreator), que contiene el permiso resourcemanager.projects.create. Obtén más información para otorgar roles.
    • Crea un Google Cloud proyecto:

      gcloud projects create PROJECT_ID

      Reemplaza PROJECT_ID por un nombre para el proyecto Google Cloud que estás creando.

    • Selecciona el proyecto Google Cloud que creaste:

      gcloud config set project PROJECT_ID

      Reemplaza PROJECT_ID por el nombre de tu proyecto de Google Cloud .

  13. Si usas un proyecto existente en esta guía, verifica que tengas los permisos necesarios para completarla. Si creaste un proyecto nuevo, ya tienes los permisos necesarios.

  14. Verifica que la facturación esté habilitada para tu proyecto de Google Cloud .

  15. Habilita la API de Kubernetes Engine:

    Roles necesarios para habilitar las APIs

    Para habilitar las APIs, necesitas el rol de IAM de administrador de Service Usage (roles/serviceusage.serviceUsageAdmin), que contiene el permiso serviceusage.services.enable. Obtén más información para otorgar roles.

    gcloud services enable container.googleapis.com
  16. Si usas una shell local, instala el componente kubectl:
    gcloud components install kubectl
  17. Asegúrate de tener un clúster de GKE que use la versión 1.30 o posterior. También puedes crear un clúster de Autopilot para este instructivo.
  18. Configura tu clúster para Grupos de Google para RBAC:
    1. Configura el grupo gke-security-groups en tu dominio.
    2. Habilita Grupos de Google para RBAC en tu clúster.

    Para obtener más información, consulta Cómo configurar tus Grupos de Google.

Roles obligatorios

Para obtener los permisos que necesitas para crear políticas de RBAC y objetos de Kubernetes en tu clúster, pídele a tu administrador que te otorgue el rol de IAM de administrador de Kubernetes Engine (role/container.admin) en tu proyecto. Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios a través de roles personalizados o cualquier otro rol predefinido.

Prepare el entorno

Para preparar tu clúster para las tareas de creación y verificación de este instructivo, sigue estos pasos:

  1. Conéctate a tu clúster:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    Reemplaza lo siguiente:

    • CLUSTER_NAME: El nombre de tu clúster.
    • CONTROL_PLANE_LOCATION: Es la región o zona del plano de control del clúster, como us-central1 o us-central1-a.
  2. Crea un espacio de nombres para usar en este instructivo. También puedes usar cualquier espacio de nombres existente en el clúster.

    kubectl create namespace computeclass-vap-tutorial
    
  3. Crea una política de RBAC que otorgue acceso para administrar ValidatingAdmissionPolicies y ValidatingAdmissionPolicyBindings:

    1. Guarda el siguiente manifiesto como validatingadmissionpolicy-editor.yaml:

      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: validatingadmissionpolicy-editor
      rules:
      - apiGroups: ["admissionregistration.k8s.io"]
        resources: ["validatingadmissionpolicies","validatingadmissionpolicybindings"]
        verbs: ["get", "list", "create", "update", "patch", "delete"]
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: edit-validatingadmissionpolicies
      subjects:
      - kind: User
        name: USER_ACCOUNT
        apiGroup: rbac.authorization.k8s.io
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: validatingadmissionpolicy-editor
      

      Reemplaza USER_ACCOUNT por la dirección de correo electrónico de tu cuenta de usuario.

    2. Crea la política de RBAC:

      kubectl apply -f validatingadmissionpolicy-editor.yaml
      
  4. Crea un objeto ComputeClass en tu clúster. Si el clúster ya tiene un ComputeClass, omite este paso.

    1. Guarda el siguiente manifiesto como access-computeclass.yaml:

      apiVersion: cloud.google.com/v1
      kind: ComputeClass
      metadata:
        name: access-restriction-class
      spec:
        priorities:
        - machineFamily: e2
        nodePoolAutoCreation:
          enabled: true
        whenUnsatisfiable: ScaleUpAnyway
      
    2. Crea la ComputeClass:

      kubectl apply -f access-computeclass.yaml
      

Crea una ValidatingAdmissionPolicy

Para restringir las ComputeClasses que pueden seleccionar los Pods, crea una ValidatingAdmissionPolicy y aplícala en un espacio de nombres específico. Usas la especificación de ValidatingAdmissionPolicy para controlar cómo los Pods pueden seleccionar ComputeClasses. En los siguientes pasos, se muestra cómo crear y aplicar esta política:

  1. Guarda el siguiente manifiesto de ValidatingAdmissionPolicy como restrict-computeclass-usage-vap.yaml:

    apiVersion: admissionregistration.k8s.io/v1
    kind: ValidatingAdmissionPolicy
    metadata:
      name: restrict-computeclass-usage
    spec:
      failurePolicy: Fail # If an internal error occurs, deny the request.
      variables:
      # Check whether the admission request is for a Deployment.
      - name: isDeployment
        expression: "object.kind == 'Deployment'"
      # Get the Pod specification from the admission request by reading the
      # spec.template.spec field for Deployments or the spec field for static Pods.
      - name: podSpec
        expression: "variables.isDeployment ? object.spec.template.spec : object.spec"
      # Check whether a node selector or an affinity rule that explicitly requests a
      # disallowed ComputeClass.
      - name: hasForbiddenNodeSelectorOrAffinity
        expression: >-
          (has(variables.podSpec.nodeSelector) &&
          variables.podSpec.nodeSelector['cloud.google.com/compute-class'] == 'COMPUTECLASS_NAME') ||
          (has(variables.podSpec.affinity) &&
          has(variables.podSpec.affinity.nodeAffinity) &&
          has(variables.podSpec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution) &&
          variables.podSpec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.exists(term, has(term.matchExpressions) &&
            term.matchExpressions.exists(
              exp, exp.key == 'cloud.google.com/compute-class' &&
              exp.operator == 'In' && exp.values.exists(v, v == 'COMPUTECLASS_NAME')
            )
          ))
    
      # Check whether the Pod has a toleration for the taint that corresponds to a
      # disallowed ComputeClass.
      - name: hasForbiddenComputeClassToleration
        expression: >-
          has(variables.podSpec.tolerations) &&
          variables.podSpec.tolerations.exists(t, 
            t.key == 'cloud.google.com/compute-class' &&
            (t.operator == 'Exists' || (t.operator == 'Equal' && t.value == 'COMPUTECLASS_NAME')) &&
            has(t.effect) && t.effect == 'NoSchedule')
    
      # Check whether the Pod has a toleration that could match any taint.
      - name: hasWildcardToleration
        expression: >-
          has(variables.podSpec.tolerations) &&
          variables.podSpec.tolerations.exists(t, 
            (t.operator == 'Exists' && !(has(t.key) && t.key != ''))
          )
    
      # Trigger the ValidatingAdmissionPolicy when Pods or Deployments are created or
      # updated.
      matchConstraints:
        resourceRules:
        - apiGroups: [""]
          apiVersions: ["v1"]
          operations: ["CREATE", "UPDATE"]
          resources: ["pods"]
        - apiGroups: ["apps"]
          apiVersions: ["v1"]
          operations: ["CREATE", "UPDATE"]
          resources: ["deployments"]
    
      # Validate whether any of the expressions in the variables section evaluate to
      # true.
      validations:
        - expression: >-
            !(variables.hasForbiddenNodeSelectorOrAffinity ||
              variables.hasForbiddenComputeClassToleration ||
              variables.hasWildcardToleration)
          message: >-
            Pods and Deployments in this namespace cannot request ComputeClass
            COMPUTECLASS_NAME or use wildcard
            tolerations.
    

    Reemplaza COMPUTECLASS_NAME por el nombre de un ComputeClass que deseas evitar que seleccionen los Pods.

    Esta ValidatingAdmissionPolicy tiene las siguientes propiedades:

    • Son activadores para Pods estáticos o Pods en objetos Deployment.
    • Busca Pods que hagan cualquiera de las siguientes acciones:

      • Usa un selector de nodos o una regla de afinidad de nodos para seleccionar de forma explícita una ComputeClass específica no permitida.
      • Usa una tolerancia que corresponda a un taint de nodo para una ComputeClass específica no permitida.
      • Usa una tolerancia que coincida con todos los taints de nodos del clúster.

    Esta ValidatingAdmissionPolicy es un ejemplo. Puedes usar expresiones para activar la política según tus propias condiciones, como impedir que los Pods que tienen etiquetas específicas seleccionen ciertas ComputeClasses.

  2. Crea el objeto ValidatingAdmissionPolicy:

    kubectl apply -f restrict-computeclass-usage-vap.yaml
    
  3. Guarda el siguiente ValidatingAdmissionPolicyBinding como restrict-computeclass-usage-binding.yaml:

    apiVersion: admissionregistration.k8s.io/v1
    kind: ValidatingAdmissionPolicyBinding
    metadata:
      name: restrict-computeclass-usage-binding
    spec:
      policyName: restrict-computeclass-usage
      validationActions: ["Deny","Audit"]
      matchResources:
        namespaceSelector:
          matchLabels:
            kubernetes.io/metadata.name: computeclass-vap-tutorial # Replace with the name of any namespace in the cluster.
    

    Este ValidatingAdmissionPolicyBinding aplica la ValidatingAdmissionPolicy del paso anterior en el espacio de nombres computeclass-vap-tutorial. Los valores del campo validationActions rechazan los Pods o las implementaciones que incumplen la ValidatingAdmissionPolicy y agregan una entrada al registro de auditoría de Kubernetes.

  4. Crea el ValidatingAdmissionPolicyBinding:

    kubectl apply -f restrict-computeclass-usage-binding.yaml
    

Configura políticas de RBAC

Además de usar un ValidatingAdmissionPolicy para evitar que las cargas de trabajo usen ciertas ComputeClasses, usa RBAC para evitar que las entidades principales no autorizadas creen y modifiquen las ComputeClasses en tu clúster. En los siguientes pasos, se muestra cómo otorgar acceso a ComputeClasses a un grupo específico de usuarios con Grupos de Google para RBAC:

  1. Crea un grupo para los editores de ComputeClass:

    1. En la Consola del administrador de Google, ve a la página Grupos.

      Ir a Grupos

    2. Haz clic en Crear grupo.

    3. En la página Detalles del grupo, haz lo siguiente:

      1. En el campo Nombre del grupo, especifica computeclass-editors.
      2. En el campo Correo electrónico del grupo, especifica computeclass-editors.
      3. Selecciona la casilla de verificación Seguridad.
      4. Haz clic en Siguiente.
    4. En la página Tipo de acceso, en la columna Miembros del grupo, verifica que esté seleccionada la casilla de verificación Quién puede ver a los miembros.

    5. Haz clic en Crear grupo.

    6. En el menú de navegación, haz clic en Directorio > Grupos.

    7. Coloca el cursor sobre la fila gke-security-groups y, luego, haz clic en Agregar miembros.

    8. En el cuadro de diálogo Add members to gke-security-groups, especifica computeclass-editors y selecciona ese grupo en los resultados.

    9. Haz clic en Agregar al grupo.

  2. Agrega las direcciones de correo electrónico de los usuarios autorizados al grupo computeclass-editors.

  3. Guarda el siguiente ClusterRole como computeclass-editor-clusterrole.yaml:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: computeclass-editor
    rules:
    -   apiGroups: ["cloud.google.com"]
      resources: ["computeclasses"]
      verbs: ["create","update"]
    
  4. Crea el ClusterRole:

    kubectl apply -f computeclass-editor-clusterrole.yaml
    
  5. Guarda el siguiente ClusterRoleBinding como computeclass-editor-role-binding.yaml:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: computeclass-editor-role-binding
    subjects:
    - kind: Group
      name: computeclass-editors@GROUP_DOMAIN
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: computeclass-editor
      apiGroup: rbac.authorization.k8s.io # Required for role references
    

    Reemplaza GROUP_DOMAIN por el nombre de dominio del grupo computeclass-editors.

  6. Crea el ClusterRoleBinding:

    kubectl apply -f computeclass-editor-role-binding.yaml
    

Verifica tus restricciones

En las siguientes secciones, se muestra cómo verificar que las restricciones que configuraste en las secciones anteriores funcionen según lo previsto. Si configuras tus propias restricciones en ValidatingAdmissionPolicies o políticas de RBAC, prueba las restricciones creando una carga de trabajo que incumpla esas políticas.

Verifica el ValidatingAdmissionPolicy

  1. Guarda cualquiera de los siguientes manifiestos, cada uno de los cuales incumple una condición diferente de ValidatingAdmissionPolicy:

    • Deployment que usa un selector de nodos para seleccionar una ComputeClass no permitida:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: disallowed-computeclass-deployment
        namespace: computeclass-vap-tutorial
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: forbidden-selector-app
        template:
          metadata:
            labels:
              app: forbidden-selector-app
          spec:
            containers:
            - name: my-app-container
              image: nginx:latest
            # The node selector triggers the policy.
            nodeSelector:
              cloud.google.com/compute-class: COMPUTECLASS_NAME
      
    • Deployment que tiene una tolerancia para una ComputeClass no permitida:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: disallowed-computeclass-deployment-toleration
        namespace: computeclass-vap-tutorial
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: forbidden-selector-app
        template:
          metadata:
            labels:
              app: forbidden-selector-app
          spec:
            containers:
            - name: my-app-container
              image: nginx:latest
            tolerations:
            - key: cloud.google.com/compute-class
              operator: Equal
              value: COMPUTECLASS_NAME
              effect: NoSchedule
      
    • Deployment que tiene una regla de afinidad de nodos para una ComputeClass no permitida:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: disallowed-computeclass-deployment-toleration
        namespace: computeclass-vap-tutorial
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: forbidden-selector-app
        template:
          metadata:
            labels:
              app: forbidden-selector-app
          spec:
            containers:
            - name: my-app-container
              image: nginx:latest
            affinity:
              nodeAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  nodeSelectorTerms:
                  - matchExpressions:
                    - key: cloud.google.com/compute-class
                      operator: In
                      values:
                      - COMPUTECLASS_NAME
      
    • Pod que tiene una tolerancia para cualquier taint de nodo en el clúster:

      apiVersion: v1
      kind: Pod
      metadata:
        name: disallowed-computeclass-deployment-toleration
        namespace: computeclass-vap-tutorial
      spec:
        containers:
        - name: my-app-container
          image: nginx:latest
        tolerations:
        - operator: Exists
          effect: NoSchedule
      
  2. Crea la carga de trabajo de prueba:

    kubectl apply -f PATH_TO_WORKLOAD_MANIFEST
    

    El resultado es similar a lo siguiente:

    Error from server (BadRequest): admission webhook "validation-policy.kubernetes.io" denied the request: Pods and Deployments in this namespace cannot request ComputeClass COMPUTECLASS_NAME or use wildcard tolerations.
    

Verifica la configuración de RBAC

Para verificar tu configuración de RBAC, sigue estos pasos:

  1. Autentícate en el clúster con las credenciales de un usuario que sea miembro del grupo computeclass-editors.

  2. Verifica si el usuario puede crear una ComputeClass:

    kubectl auth can-i create computeclasses.cloud.google.com \
        --as=MEMBER_USER
    

    Reemplaza MEMBER_USER por la dirección de correo electrónico de un usuario que sea miembro del grupo.

    El resultado es yes.

  3. Autentícate en el clúster con las credenciales de un usuario que no sea miembro del grupo computeclass-editors.

  4. Verifica si el usuario puede crear una ComputeClass:

    kubectl auth can-i create computeclasses.cloud.google.com \
        --as=NON_MEMBER_USER
    

    Reemplaza NON_MEMBER_USER por la dirección de correo electrónico de un usuario que no sea miembro del grupo.

    El resultado es no.

Si el resultado del comando kubectl auth can-i es yes para un usuario que no es miembro del grupo, verifica lo siguiente:

  • El grupo computeclass-editors es miembro del grupo gke-security-groups.
  • La dirección de correo electrónico del grupo en tu ClusterRoleBinding es la dirección de correo electrónico exacta del grupo, como computeclass-editors@example.com.

Realiza una limpieza

Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.

Si implementas las políticas de ValidatingAdmissionPolicy y RBAC de este instructivo en un clúster de producción, GKE bloqueará los Pods entrantes y las solicitudes a la API que incumplan las políticas. Para mantener activas estas políticas, omite esta sección. En las siguientes secciones, se muestra cómo borrar el proyecto o los recursos individuales si seguiste este instructivo en un entorno de aprendizaje o pruebas.

Borra el proyecto

    Borra un Google Cloud proyecto:

    gcloud projects delete PROJECT_ID

Borra los recursos individuales

  1. Borra la ComputeClass que creaste:

    kubectl delete computeclass access-restriction-class
    
  2. Borra ValidatingAdmissionPolicy y ValidatingAdmissionPolicyBinding:

    kubectl delete validatingadmissionpolicy restrict-computeclass-usage
    kubectl delete validatingadmissionpolicybinding restrict-computeclass-usage-binding
    
  3. Borra los ClusterRoles y los ClusterRoleBindings:

    kubectl delete clusterroles \
        computeclass-editor validatingadmissionpolicy-editor
    kubectl delete clusterrolebindings \
        computeclass-editor-role-binding edit-validatingadmissionpolicies
    
  4. Borra el espacio de nombres de ejemplo:

    kubectl delete namespace computeclass-vap-tutorial
    

¿Qué sigue?