Aísla tus cargas de trabajo en grupos de nodos dedicados

En este documento, se explica cómo mejorar la seguridad y la administración de tu clúster de Kubernetes mediante el aislamiento de las cargas de trabajo de contenedores dentro de grupos de nodos dedicados en Google Distributed Cloud (GDC) aislado. El aislamiento de tus cargas de trabajo te brinda un mayor control sobre tus pods y reduce el riesgo de ataques de elevación de privilegios en tu clúster de Kubernetes. Para obtener más información sobre los beneficios y las limitaciones de los grupos de nodos dedicados, consulta Descripción general del aislamiento de nodos.

Existen varios flujos de trabajo relacionados con el aislamiento de tus cargas de trabajo de contenedores, que incluyen los siguientes:

  • Aplica un taint y una etiqueta a un grupo de nodos: Aplica un taint y una etiqueta a un grupo de nodos para que repela los pods del grupo de nodos, a menos que estén etiquetados específicamente para ejecutarse allí.

  • Agrega una regla de tolerancia y afinidad de nodos: Aplica tolerancias y reglas a tus pods para obligarlos a ejecutarse solo en el grupo de nodos designado.

  • Verifica que la separación funcione: Confirma que tus grupos de nodos con taints solo ejecuten los pods que etiquetaste para que se ejecuten allí.

Estos flujos de trabajo están destinados a públicos como administradores de TI dentro del grupo de administradores de la plataforma, que son responsables de administrar los grupos de nodos de un clúster de Kubernetes, y desarrolladores de aplicaciones dentro del grupo de operadores de aplicaciones, que son responsables de administrar las cargas de trabajo de contenedores. Para obtener más información, consulta Públicos de la documentación de GDC aislado.

Antes de comenzar

Para completar las tareas de este documento, debes solicitar los permisos necesarios y preparar tu entorno.

Solicita roles de IAM

Debes tener roles específicos para obtener los permisos que necesitas para aislar las cargas de trabajo de contenedores en tu clúster de Kubernetes. Los roles que necesitas dependen de si trabajas en un clúster compartido con alcance de organización o en un clúster estándar con alcance de proyecto. Para obtener más información, consulta Configuraciones del clúster de Kubernetes.

Roles de clúster compartido

Comunícate con tu administrador de IAM de la organización para solicitar los siguientes roles para aplicar un taint y una etiqueta a un grupo de nodos en un clúster compartido:

  • Administrador del clúster de usuario (user-cluster-admin): Crea, borra, edita o visualiza los recursos de un clúster compartido alojado en el servidor de la API de administración. Este rol proporciona acceso a los grupos de nodos del clúster compartido.

  • Desarrollador del clúster de usuario (user-cluster-developer): Crea, borra, edita o visualiza un clúster compartido. Este rol proporciona acceso a las APIs del plano de datos alojadas dentro del clúster compartido.

Estos roles no están vinculados a un espacio de nombres.

Roles de clúster estándar

Comunícate con tu administrador de IAM del proyecto para solicitar los siguientes roles para aplicar un taint y una etiqueta a un grupo de nodos en un clúster estándar:

  • Administrador del clúster (cluster-admin): Crea, borra, edita o visualiza todos los recursos en un clúster estándar. Este rol proporciona acceso a las APIs del plano de datos alojadas dentro del clúster estándar que rigen los recursos del clúster.

  • Desarrollador del clúster (cluster-developer): Crea, borra, edita o visualiza un clúster estándar. Este rol proporciona acceso a las APIs del plano de datos alojadas dentro del clúster estándar que rigen el clúster.

  • Administrador del clúster estándar (standard-cluster-admin): Crea, borra, edita o visualiza los recursos de un clúster estándar alojado en el servidor de la API de administración. Este rol proporciona acceso a los grupos de nodos del clúster estándar.

Estos roles están vinculados al espacio de nombres de tu proyecto.

Prepara el entorno

Para ejecutar comandos en un clúster de Kubernetes con la API, asegúrate de tener los siguientes recursos:

  • Accede y genera el archivo kubeconfig para el clúster de Kubernetes.

  • Usa la ruta de kubeconfig del clúster de Kubernetes para reemplazar KUBERNETES_CLUSTER_KUBECONFIG en estas instrucciones.

  • Accede y genera el archivo kubeconfig para el servidor de la API de administración.

  • Usa la ruta de kubeconfig del servidor de la API de administración para reemplazar MANAGEMENT_API_SERVER en estas instrucciones.

  • Elige un nombre específico para el taint de nodo y la etiqueta de nodo que deseas usar para los grupos de nodos dedicados. Por ejemplo, workloadType=untrusted.

Aplica un taint y una etiqueta a un grupo de nodos nuevo

Cuando aplicas un taint o una etiqueta a un grupo de nodos nuevo, todos los nodos, incluidos los que se agreguen más adelante, obtendrán automáticamente los taints y las etiquetas especificados. No puedes quitar un taint o una etiqueta de un grupo de nodos después de que se aplica.

Para agregar un taint y una etiqueta a un grupo de nodos nuevo, completa los siguientes pasos:

  1. Edita la sección nodePools del recurso personalizado Cluster directamente cuando crees el grupo de nodos:

    nodePools:
      # Several lines of code are omitted here.
      - machineTypeName: n2-standard-2-gdc
        name: nodepool-1
        nodeCount: 3
        taints:
        - key: "TAINT_KEY"
          value: "TAINT_VALUE"
          effect: "TAINT_EFFECT"
        labels:
          LABEL_KEY: LABEL_VALUE
    

    Reemplaza lo siguiente:

    • TAINT_KEY: Es la parte de la clave de taint del par clave-valor asociado con una programación de TAINT_EFFECT. Por ejemplo, workloadType.
    • TAINT_VALUE: Es la parte del valor de taint del par clave-valor asociado con una programación TAINT_EFFECT. Por ejemplo, untrusted.
    • TAINT_EFFECT: Es uno de los siguientes valores de efecto :
      • NoSchedule: Los pods que no toleran este taint no están programados en el nodo. Los pods existentes no se expulsan del nodo.
      • PreferNoSchedule: Kubernetes evita programar pods que no toleran este taint en el nodo.
      • NoExecute: El pod se desaloja del nodo si ya está en ejecución en este y no está programado en el nodo si aún no está en ejecución en él.
    • LABEL_KEY: LABEL_VALUE: Son los pares clave-valor para las etiquetas de nodo, que corresponden a los selectores que especificas en los manifiestos de cargas de trabajo.
  2. Aplica el recurso Cluster para crear el grupo de nodos nuevo:

    kubectl apply -f cluster.yaml --kubeconfig MANAGEMENT_API_SERVER
    

    Reemplaza MANAGEMENT_API_SERVER por la ruta de kubeconfig del servidor de la API zonal donde se aloja el clúster de Kubernetes.

Aplica un taint y una etiqueta a un grupo de nodos existente

Para aplicar un taint o una etiqueta a un grupo de nodos existente, debes aplicar los cambios a cada nodo existente. No puedes actualizar de forma dinámica las configuraciones del grupo de nodos.

No puedes quitar un taint o una etiqueta de un grupo de nodos después de que se aplica.

Para agregar un taint y una etiqueta a un grupo de nodos existente, completa los siguientes pasos:

  1. Obtén una lista de los nodos del grupo de nodos dedicado:

    kubectl get node --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG \
        -l baremetal.cluster.gke.io/node-pool=NODE_POOL_NAME
    

    Reemplaza las siguientes variables:

    • KUBERNETES_CLUSTER_KUBECONFIG: Es la ruta de kubeconfig para el clúster de Kubernetes.
    • NODE_POOL_NAME: Es el nombre de tu grupo de nodos dedicado.

    Anota cada ID de nodo de todos los nodos del grupo de nodos del resultado.

  2. Para cada nodo del grupo de nodos, aplica los taints:

    kubectl taint nodes NODE_ID \
        TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Reemplaza las siguientes variables:

    • NODE_ID: Es el ID del nodo trabajador en el grupo de nodos dedicado.
    • TAINT_KEY=TAINT_VALUE: Es un par clave-valor asociado con una programación de TAINT_EFFECT. Por ejemplo, workloadType=untrusted.
    • TAINT_EFFECT: Es uno de los siguientes valores de efecto:
      • NoSchedule: Los pods que no toleran este taint no están programados en el nodo. Los pods existentes no se expulsan del nodo.
      • PreferNoSchedule: Kubernetes evita programar pods que no toleran este taint en el nodo.
      • NoExecute: El pod se desaloja del nodo si ya está en ejecución en este y no está programado en el nodo si aún no está en ejecución en él.
    • KUBERNETES_CLUSTER_KUBECONFIG: Es la ruta de kubeconfig para el clúster de Kubernetes.
  3. Para cada nodo del grupo de nodos, aplica las etiquetas que corresponden a los selectores que definirás en tus cargas de trabajo de contenedores:

    kubectl label NODE_ID \
        LABEL_KEY:LABEL_VALUE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Reemplaza las siguientes variables:

    • NODE_ID: Es el ID del nodo trabajador en el grupo de nodos dedicado.
    • LABEL_KEY:LABEL_VALUE: los pares clave-valor para las etiquetas de nodo, que corresponden a los selectores que especificas en los manifiestos de cargas de trabajo.
    • KUBERNETES_CLUSTER_KUBECONFIG: Es la ruta de kubeconfig para el clúster de Kubernetes.

Agrega una regla de tolerancia y afinidad de nodos

Después de aplicar un taint al grupo de nodos dedicado, ninguna carga de trabajo puede programarlo, a menos que tenga una tolerancia correspondiente al taint que agregaste. Agrega la tolerancia a la especificación de tus cargas de trabajo para permitir que esos pods se programen en tu grupo de nodos con taints.

Si etiquetaste el grupo de nodos dedicado, también puedes agregar una regla de afinidad de nodos para indicar a GDC que solo programe las cargas de trabajo en ese grupo de nodos.

Para configurar tu carga de trabajo de contenedores para que se ejecute en el grupo de nodos dedicado, completa los siguientes pasos:

  1. Agrega las siguientes secciones a la sección .spec.template.spec de tu archivo de manifiesto de carga de trabajo de contenedores, como un recurso personalizado Deployment:

    tolerations:
    - key: TAINT_KEY
      operator: Equal
      value: TAINT_VALUE
      effect: TAINT_EFFECT
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: LABEL_KEY
              operator: In
              values:
              - "LABEL_VALUE"
    

    Reemplaza lo siguiente:

    • TAINT_KEY: Es la clave de taint que aplicaste al grupo de nodos dedicado.
    • TAINT_VALUE: Es el valor de taint que aplicaste a tu grupo de nodos dedicado.
    • TAINT_EFFECT: Es uno de los siguientes valores de efecto:
      • NoSchedule: Los pods que no toleran este taint no están programados en el nodo. Los pods existentes no se expulsan del nodo.
      • PreferNoSchedule: Kubernetes evita programar pods que no toleran este taint en el nodo.
      • NoExecute: El pod se desaloja del nodo si ya está en ejecución en este y no está programado en el nodo si aún no está en ejecución en él.
    • LABEL_KEY: Es la clave de etiqueta de nodo que aplicaste a tu grupo de nodos dedicado.
    • LABEL_VALUE: Es el valor de la etiqueta de nodo que aplicaste a tu grupo de nodos dedicado.

    Por ejemplo, el siguiente Deployment recurso agrega una tolerancia para el workloadType=untrusted:NoExecute taint y una regla de afinidad de nodos para la workloadType=untrusted etiqueta de nodo:

    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: my-app
      namespace: default
      labels:
        app: my-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-app
      template:
        metadata:
          labels:
            app: my-app
        spec:
          tolerations:
          - key: workloadType
            operator: Equal
            value: untrusted
            effect: NoExecute
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: workloadType
                    operator: In
                    values:
                    - "untrusted"
          containers:
          - name: my-app
            image: harbor-1.org-1.zone1.google.gdc.test/harborproject/my-app
            ports:
            - containerPort: 80
          imagePullSecrets:
          - name: SECRET
    
  2. Actualiza tu carga de trabajo de contenedores:

    kubectl apply -f deployment.yaml -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Reemplaza las siguientes variables:

    • NAMESPACE: Es el espacio de nombres de tu carga de trabajo de contenedores. Para los clústeres compartidos, debe ser un espacio de nombres del proyecto. Para los clústeres estándar, puede ser cualquier espacio de nombres.
    • KUBERNETES_CLUSTER_KUBECONFIG: Es la ruta de kubeconfig para el clúster de Kubernetes.

GDC vuelve a crear los pods afectados. La regla de afinidad de nodos fuerza a los pods al grupo de nodos dedicado que creaste. La tolerancia solo permite que se coloquen esos pods en los nodos.

Verifica que la separación funcione

Verifica que los pods que designaste se ejecuten en el grupo de nodos etiquetado.

  • Obtén una lista de los pods del espacio de nombres determinado:

    kubectl get pods -o=wide -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Reemplaza las siguientes variables:

    • NAMESPACE: Es el espacio de nombres de tu carga de trabajo de contenedores. Para los clústeres compartidos, debe ser un espacio de nombres del proyecto. Para los clústeres estándar, puede ser cualquier espacio de nombres.
    • KUBERNETES_CLUSTER_KUBECONFIG: Es la ruta de kubeconfig para el clúster de Kubernetes.

    El resultado es similar al siguiente:

    pod/kube-abc-12tyuj
    pod/kube-abc-39oplef
    pod/kube-abc-95rzkap
    

    Confirma que tus cargas de trabajo se ejecuten en el grupo de nodos dedicado.

¿Qué sigue?