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

En este documento se explica cómo mejorar la seguridad y la gestión de tu clúster de Kubernetes aislando las cargas de trabajo de los contenedores en grupos de nodos dedicados en Google Distributed Cloud (GDC) air-gapped. Aislar tus cargas de trabajo te permite tener un mayor control sobre tus pods y reduce el riesgo de ataques de apropiación de privilegios en tu clúster de Kubernetes. Para obtener más información sobre las ventajas y las limitaciones de los grupos de nodos dedicados, consulta el artículo Descripción general del aislamiento de nodos.

Hay varios flujos de trabajo relacionados con el aislamiento de las cargas de trabajo de los contenedores, entre los que se incluyen los siguientes:

  • Aplicar intolerancia y anotación a un grupo de nodos: Aplica una intolerancia y una anotación a un grupo de nodos para que rechace los pods, a menos que estén etiquetados específicamente para ejecutarse en él.

  • Añadir una tolerancia y una regla de afinidad de nodo: aplica tolerancias y reglas a tus pods para obligarlos a ejecutarse solo en el grupo de nodos designado.

  • Verifica que la separación funciona: confirma que tus grupos de nodos contaminados solo ejecutan los pods que has etiquetado para que se ejecuten en ellos.

Estos flujos de trabajo están dirigidos a usuarios como los administradores de TI del grupo de administradores de la plataforma, que se encargan de gestionar los grupos de nodos de un clúster de Kubernetes, y los desarrolladores de aplicaciones del grupo de operadores de aplicaciones, que se encargan de gestionar las cargas de trabajo de los contenedores. Para obtener más información, consulta Audiencias de la documentación aislada de GDC.

Antes de empezar

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

Solicitar roles de gestión de identidades y accesos

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

Roles de clúster compartidos

Ponte en contacto con el administrador de gestión de identidades y accesos de tu organización para solicitar los siguientes roles para etiquetar y contaminar un grupo de nodos en un clúster compartido:

  • Administrador de clúster de usuario (user-cluster-admin): crea, elimina, edita o consulta los recursos de un clúster compartido alojado en el servidor de la API Management. Este rol proporciona acceso a los grupos de nodos del clúster compartido.

  • Desarrollador de clúster de usuario (user-cluster-developer): crea, elimina, edita o consulta un clúster compartido. Este rol proporciona acceso a las APIs del plano de datos alojadas en el clúster compartido.

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

Roles de clúster estándar

Ponte en contacto con el administrador de IAM de tu proyecto para solicitar los siguientes roles para aplicar intolerancia y etiquetar un grupo de nodos en un clúster estándar:

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

  • Desarrollador de clústeres (cluster-developer): crea, elimina, edita o consulta un clúster estándar. Este rol proporciona acceso a las APIs del plano de datos alojadas en el clúster estándar que rigen el clúster.

  • Administrador de clúster estándar (standard-cluster-admin): crea, elimina, edita o consulta los recursos de un clúster estándar alojado en el servidor de la API de gestió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 tu entorno

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

  • Inicia sesión y genera el archivo kubeconfig del clúster de Kubernetes.

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

  • Inicia sesión y genera el archivo kubeconfig del servidor de la API de gestión.

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

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

Etiquetar y aplicar un taint a un nuevo grupo de nodos

Cuando apliques un taint o una etiqueta a un nuevo grupo de nodos, todos los nodos, incluidos los que se añadan más adelante, recibirán automáticamente los taints y las etiquetas especificados. No puedes quitar una intolerancia o una anotación de un grupo de nodos después de aplicarla.

Para añadir un taint y una etiqueta a un nuevo grupo de nodos, sigue estos pasos:

  1. Edita la sección nodePools del recurso personalizado Cluster directamente al crear 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
    

    Haz los cambios siguientes:

    • TAINT_KEY: la parte de la clave de intolerancia del par clave-valor asociado a una programación TAINT_EFFECT. Por ejemplo, workloadType.
    • TAINT_VALUE: la parte del valor de intolerancia del par clave-valor asociado a una programación TAINT_EFFECT. Por ejemplo, untrusted.
    • TAINT_EFFECT: uno de los siguientes valores de efecto:
      • NoSchedule: los pods que no toleran esta intolerancia no se programan en el nodo. Los pods que ya están en el nodo no se expulsan.
      • PreferNoSchedule: Kubernetes evita programar pods que no toleren esta intolerancia en el nodo.
      • NoExecute: el pod se expulsa del nodo si ya se está ejecutando en él y no se programa en el nodo si aún no se está ejecutando en él.
    • LABEL_KEY: LABEL_VALUE: los pares clave-valor de las etiquetas de nodo, que corresponden a los selectores que especifiques en los manifiestos de tu carga de trabajo.
  2. Aplica el recurso Cluster para crear el grupo de nodos:

    kubectl apply -f cluster.yaml --kubeconfig MANAGEMENT_API_SERVER
    

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

Aplicar un taint y una etiqueta a un grupo de nodos

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

No puedes quitar una intolerancia o una anotación de un grupo de nodos después de aplicarla.

Para añadir un taint y una etiqueta a un grupo de nodos, sigue estos pasos:

  1. Lista los nodos del grupo de nodos dedicado:

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

    Sustituye las siguientes variables:

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

    Anota el ID de cada nodo del grupo de nodos en la salida.

  2. En cada nodo del grupo de nodos, aplica las intolerancias:

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

    Sustituye las siguientes variables:

    • NODE_ID: el ID del nodo de trabajador del grupo de nodos dedicado.
    • TAINT_KEY=TAINT_VALUE: un par clave-valor asociado a una programación. TAINT_EFFECT Por ejemplo, workloadType=untrusted.
    • TAINT_EFFECT: uno de los siguientes valores de efecto:
      • NoSchedule: los pods que no toleran esta intolerancia no se programan en el nodo. Los pods que ya están en el nodo no se expulsan.
      • PreferNoSchedule: Kubernetes evita programar pods que no toleren esta intolerancia en el nodo.
      • NoExecute: el pod se expulsa del nodo si ya se está ejecutando en él y no se programa en el nodo si aún no se está ejecutando en él.
    • KUBERNETES_CLUSTER_KUBECONFIG: la ruta de kubeconfig del clúster de Kubernetes.
  3. En cada nodo del grupo de nodos, aplique las etiquetas que correspondan a los selectores que definirá en sus cargas de trabajo de contenedor:

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

    Sustituye las siguientes variables:

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

Añadir una tolerancia y una regla de afinidad de nodo

Después de aplicar un taint al grupo de nodos dedicado, no se podrá programar ninguna carga de trabajo en él a menos que tenga una tolerancia correspondiente al taint que hayas añadido. Añade la tolerancia a la especificación de tus cargas de trabajo para que esos pods se programen en tu grupo de nodos con intolerancias.

Si has etiquetado el grupo de nodos dedicado, también puedes añadir una regla de afinidad de nodos para indicar a GDC que solo programe tus cargas de trabajo en ese grupo de nodos.

Para configurar la carga de trabajo del contenedor de forma que se ejecute en el grupo de nodos dedicado, sigue estos pasos:

  1. Añade las siguientes secciones a la sección .spec.template.spec del archivo de manifiesto de la carga de trabajo del contenedor, 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"
    

    Haz los cambios siguientes:

    • TAINT_KEY: la clave de taint que has aplicado a tu grupo de nodos dedicado.
    • TAINT_VALUE: el valor de taint que has aplicado a tu grupo de nodos dedicado.
    • TAINT_EFFECT: uno de los siguientes valores de efecto:
      • NoSchedule: los pods que no toleran esta intolerancia no se programan en el nodo. Los pods que ya están en el nodo no se expulsan.
      • PreferNoSchedule: Kubernetes evita programar pods que no toleren esta intolerancia en el nodo.
      • NoExecute: el pod se expulsa del nodo si ya se está ejecutando en él y no se programa en el nodo si aún no se está ejecutando en él.
    • LABEL_KEY: la clave de anotación que has aplicado a tu grupo de nodos dedicado.
    • LABEL_VALUE: el valor de la etiqueta de nodo que has aplicado a tu grupo de nodos dedicado.

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

    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 la carga de trabajo del contenedor:

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

    Sustituye las siguientes variables:

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

GDC vuelve a crear los pods afectados. La regla de afinidad de nodo fuerza a los pods a usar el grupo de nodos dedicado que has creado. La tolerancia permite que solo esos pods se coloquen en los nodos.

Verificar que la separación funciona

Comprueba que los pods que has designado se estén ejecutando en el grupo de nodos etiquetado.

  • Lista los pods del espacio de nombres indicado:

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

    Sustituye las siguientes variables:

    • NAMESPACE: el espacio de nombres de la carga de trabajo del contenedor. En el caso de los clústeres compartidos, debe ser un espacio de nombres de proyecto. En el caso de los clústeres estándar, puede ser cualquier espacio de nombres.
    • KUBERNETES_CLUSTER_KUBECONFIG: la ruta de kubeconfig del 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 están ejecutando en el grupo de nodos dedicado.

Siguientes pasos