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

En esta página se explica cómo reducir el riesgo de ataques de escalada de privilegios en tu clúster indicando a Google Kubernetes Engine (GKE) que programe tus cargas de trabajo en un grupo de nodos independiente y dedicado, lejos de las cargas de trabajo privilegiadas gestionadas por GKE. Solo debes usar este método si no puedes usar GKE Sandbox. GKE Sandbox es el método recomendado para aislar nodos. GKE Sandbox también ofrece otras ventajas de protección para tus cargas de trabajo.

Esta página está dirigida a especialistas en seguridad que necesitan una capa de aislamiento en las cargas de trabajo, pero no pueden usar GKE Sandbox. Para obtener más información sobre los roles habituales y las tareas de ejemplo a las que hacemos referencia en el contenido, consulta Roles y tareas habituales de los usuarios de GKE. Google Cloud

Esta página se aplica a los clústeres estándar sin aprovisionamiento automático de nodos. Para separar las cargas de trabajo en clústeres de Autopilot y en clústeres estándar con el aprovisionamiento automático de nodos habilitado, consulta Configurar la separación de cargas de trabajo en GKE.

Información general

Los clústeres de GKE usan cargas de trabajo privilegiadas gestionadas por GKE para habilitar funciones y características específicas del clúster, como la recogida de métricas. Estas cargas de trabajo tienen permisos especiales para ejecutarse correctamente en el clúster.

Las cargas de trabajo que despliegues en tus nodos pueden verse comprometidas por una entidad maliciosa. Si ejecutas estas cargas de trabajo junto con cargas de trabajo privilegiadas gestionadas por GKE, un atacante que salga de un contenedor vulnerado puede usar las credenciales de la carga de trabajo privilegiada del nodo para elevar los privilegios en tu clúster.

Evitar las fugas de contenedores

Tu defensa principal deben ser tus aplicaciones. GKE tiene varias funciones que puedes usar para reforzar la seguridad de tus clústeres y pods. En la mayoría de los casos, recomendamos encarecidamente usar GKE Sandbox para aislar tus cargas de trabajo. GKE Sandbox se basa en el proyecto de código abierto gVisor e implementa la API del kernel de Linux en el espacio de usuario. Cada pod se ejecuta en un kernel dedicado que pone en un espacio aislado las aplicaciones para evitar el acceso a llamadas al sistema privilegiadas en el kernel host. Las cargas de trabajo que se ejecutan en GKE Sandbox se programan automáticamente en nodos independientes, aislados de otras cargas de trabajo.

También debes seguir las recomendaciones que se indican en el artículo Endurecer la seguridad del clúster.

Evitar ataques de apropiación de privilegios

Si no puedes usar GKE Sandbox y quieres añadir una capa adicional de aislamiento a otras medidas de protección, puedes usar taints de nodos y afinidades de nodos para programar tus cargas de trabajo en un grupo de nodos dedicado. Un taint de nodo indica a GKE que evite programar cargas de trabajo sin una tolerancia correspondiente (como las cargas de trabajo gestionadas por GKE) en esos nodos. La afinidad de nodo de tus cargas de trabajo indica a GKE que programe tus pods en los nodos dedicados.

Limitaciones del aislamiento de nodos

  • Los atacantes pueden seguir iniciando ataques de denegación de servicio (DoS) desde el nodo vulnerado.
  • Los nodos vulnerados pueden seguir leyendo muchos recursos, incluidos todos los pods y los espacios de nombres del clúster.
  • Los nodos vulnerados pueden acceder a los secretos y las credenciales que usan todos los pods que se ejecutan en ese nodo.
  • Usar un grupo de nodos independiente para aislar tus cargas de trabajo puede afectar a la eficiencia de los costes, al autoescalado y al uso de los recursos.
  • Los nodos vulnerados pueden seguir eludiendo las políticas de red de salida.
  • Algunas cargas de trabajo gestionadas por GKE deben ejecutarse en todos los nodos de tu clúster y están configuradas para tolerar todos los taints.
  • Si implementas DaemonSets que tienen permisos elevados y pueden tolerar cualquier taint, esos pods pueden ser una vía para la escalada de privilegios desde un nodo vulnerado.

Cómo funciona el aislamiento de nodos

Para implementar el aislamiento de nodos en tus cargas de trabajo, debes hacer lo siguiente:

  1. Aplica un taint y una etiqueta a un grupo de nodos para tus cargas de trabajo.
  2. Actualiza tus cargas de trabajo con la regla de tolerancia y afinidad de nodo correspondiente.

En esta guía se presupone que empiezas con un grupo de nodos en tu clúster. No es obligatorio usar la afinidad de nodos junto con los taints de nodos, pero te recomendamos que lo hagas porque te permite tener un mayor control sobre la programación.

Antes de empezar

Antes de empezar, asegúrate de que has realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si quieres usar Google Cloud CLI para esta tarea, instálala y, a continuación, inicialízala. Si ya has instalado la gcloud CLI, obtén la versión más reciente ejecutando gcloud components update.
  • Elige un nombre específico para el taint y la etiqueta de nodo que quieras usar en los grupos de nodos dedicados.

Taint y etiqueta de un grupo de nodos para tus cargas de trabajo

Crea un grupo de nodos para tus cargas de trabajo y aplica un taint y una etiqueta de nodo. Cuando aplicas un taint o una etiqueta a nivel del grupo de nodos, los nodos nuevos, como los que se crean mediante el escalado automático, obtendrán automáticamente los taints y las etiquetas especificados.

También puedes añadir taints y etiquetas de nodo a grupos de nodos que ya tengas. Si usas el efecto NoExecute, GKE expulsa los pods que se ejecutan en esos nodos y que no tienen una tolerancia para el nuevo taint.

Para aislar las cargas de trabajo, utilice siempre el prefijo node-restriction.kubernetes.io/ para las etiquetas de los nodos y para los selectores correspondientes en los manifiestos de los pods. Este prefijo evita que un atacante use la credencial del nodo para definir o modificar las etiquetas que usan este prefijo. Para obtener más información, consulta el artículo sobre aislamiento o restricción de nodos en la documentación de Kubernetes.

Para añadir un taint y una etiqueta a un grupo de nodos nuevo, ejecuta el siguiente comando:

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --node-taints=TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
    --node-labels=node-restriction.kubernetes.io/LABEL_KEY=LABEL_VALUE

Haz los cambios siguientes:

  • POOL_NAME: el nombre del nuevo grupo de nodos para tus cargas de trabajo.
  • CLUSTER_NAME: el nombre de tu clúster de GKE.
  • 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, PreferNoSchedule o NoExecute. NoExecute ofrece una garantía de desalojo mejor que NoSchedule.
  • node-restriction.kubernetes.io/LABEL_KEY=LABEL_VALUE: pares clave-valor de las etiquetas de nodo, que corresponden a los selectores que especificas en los manifiestos de carga de trabajo. El prefijo node-restriction.kubernetes.io/ evita que se usen las credenciales del nodo para definir estos pares clave-valor en los nodos.

Añadir una tolerancia y una regla de afinidad de nodos a tus cargas de trabajo

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 GKE que solo programe tus cargas de trabajo en ese grupo de nodos.

En el siguiente ejemplo se 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: TAINT_KEY
        operator: Equal
        value: TAINT_VALUE
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: node-restriction.kubernetes.io/LABEL_KEY
                operator: In
                values:
                - "LABEL_VALUE"
      containers:
      - name: sleep
        image: ubuntu
        command: ["/bin/sleep", "inf"]

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.
  • LABEL_KEY: la clave de la etiqueta de nodo 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.

Cuando actualizas tu Deployment con kubectl apply, GKE vuelve a crear los pods afectados. La regla de afinidad de nodos 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

Para verificar que la programación funciona correctamente, ejecuta el siguiente comando y comprueba si tus cargas de trabajo están en el grupo de nodos dedicado:

kubectl get pods -o=wide

Recomendaciones y prácticas recomendadas

Después de configurar el aislamiento de nodos, te recomendamos que hagas lo siguiente:

  • Restringe grupos de nodos específicos a cargas de trabajo gestionadas por GKE añadiendo el components.gke.io/gke-managed-components. Añadir esta marca evita que tus pods se programen en esos nodos, lo que mejora el aislamiento.
  • Cuando crees grupos de nodos, evita que la mayoría de las cargas de trabajo gestionadas por GKE se ejecuten en esos nodos añadiendo tu propio taint a esos grupos de nodos.
  • Cada vez que implementes nuevas cargas de trabajo en tu clúster, como cuando instales herramientas de terceros, audita los permisos que requieren los pods. Cuando sea posible, evite desplegar cargas de trabajo que usen permisos elevados en nodos compartidos.

Siguientes pasos