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

En esta página, se muestra cómo reducir el riesgo de ataques de elevación de privilegios en tu clúster mediante la configuración de GKE on AWS para programar tus cargas de trabajo en un grupo de nodos dedicado y separado de las cargas de trabajo administradas con privilegios.

Descripción general

Los clústeres de GKE on AWS usan cargas de trabajo con privilegios que administramos para habilitar funciones y características específicas del clúster, como la recopilación de métricas. Estas cargas de trabajo tienen permisos especiales para ejecutarse de forma correcta en el clúster.

Las cargas de trabajo que implementas en tus nodos pueden tener el potencial de verse comprometidas por una entidad maliciosa. Ejecutar estas cargas de trabajo junto con cargas de trabajo del sistema significa que un atacante que sale de un contenedor vulnerado puede usar las credenciales de la carga de trabajo con privilegios en el nodo para escalar privilegios en tu clúster.

Evita interrupciones de contenedores

Tu defensa principal deben ser las aplicaciones. GKE on AWS tiene varias funciones que puedes usar para endurecer los clústeres y Pods. En la mayoría de los casos, recomendamos usar Policy Controller y las funciones de seguridad del kernel para endurecer las cargas de trabajo. Para obtener más recomendaciones de seguridad, consulta la Descripción general de seguridad.

Evita ataques de elevación de privilegios

Si deseas una capa adicional de aislamiento, además de otras medidas de endurecimiento, puedes usar los taints de nodos y la afinidad de nodos para programar tus cargas de trabajo en un grupo de nodos dedicado.

Un taint de nodo le indica a GKE en AWS que evite programar cargas de trabajo sin una tolerancia correspondiente (como las cargas de trabajo administradas por GKE en AWS) en esos nodos. La afinidad de nodos en tus propias cargas de trabajo le indica a GKE en AWS que programe tus Pods en los nodos dedicados.

Limitaciones del aislamiento de nodos

  • Los atacantes aún pueden iniciar ataques de denegación del servicio (DoS) desde el nodo vulnerado.
  • Los nodos vulnerados aún pueden leer muchos recursos, incluidos todos los Pods y los espacios de nombres en el clúster.
  • Los nodos vulnerados pueden acceder a los objetos Secret y a las credenciales que usan todos los Pods que se ejecutan en ese nodo.
  • El uso de un grupo de nodos separado para aislar las cargas de trabajo puede afectar la rentabilidad, el ajuste de escala automático y el uso de recursos.
  • Los nodos vulnerados aún pueden omitir las políticas de red de salida.
  • Algunas cargas de trabajo administradas por GKE en AWS deben ejecutarse en cada nodo del 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 podrían ser una ruta para la elevación de privilegios desde un nodo vulnerado.

Cómo funciona el aislamiento de nodos

A fin de implementar el aislamiento de nodos para las cargas de trabajo, debes hacer lo siguiente:

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

En esta guía, se da por sentado que comienzas con un grupo de nodos en el clúster. No es obligatorio usar la afinidad de nodos además de los taints de nodo, pero te lo recomendamos porque te beneficiarás de un mayor control sobre la programación.

Antes de comenzar

Para realizar los pasos de esta página, primero completa lo siguiente:

Aplica un taint y una etiqueta a un grupo de nodos para las cargas de trabajo

Crea un grupo de nodos nuevo para tus cargas de trabajo y aplica un taint de nodo y una etiqueta de nodo. Cuando aplicas un taint o una etiqueta a nivel del grupo de nodos, cualquier nodo nuevo, como los creados por el ajuste de escala automático, obtendrá automáticamente los taints y las etiquetas especificados.

También puedes agregar taints de nodos y etiquetas de nodos a los grupos de nodos existentes. Si usas el efecto NoExecute, GKE en AWS expulsa los Pods que se ejecutan en esos nodos que no tienen una tolerancia para el taint nuevo.

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

gcloud container aws node-pools create POOL_NAME \
    --cluster CLUSTER_NAME \
    --node-taints TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
    --node-labels LABEL_KEY=LABEL_VALUE

Reemplaza lo siguiente:

  • POOL_NAME: el nombre del grupo de nodos nuevo para las cargas de trabajo.
  • CLUSTER_NAME: Es el nombre del clúster de GKE en AWS.
  • TAINT_KEY=TAINT_VALUE: un par clave-valor asociado con una programación de TAINT_EFFECT. Por ejemplo, workloadType=untrusted.
  • TAINT_EFFECT: uno de los siguientes valores de efectos: NoSchedule, PreferNoSchedule o NoExecute. NoExecute proporciona una garantía de expulsión mejor que NoSchedule.
  • 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.

Agrega una regla de tolerancia y afinidad de nodos a tus cargas de trabajo

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

En el siguiente ejemplo, se agrega una tolerancia para el taint workloadType=untrusted:NoExecute y una regla de afinidad de nodos 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: LABEL_KEY
                operator: In
                values:
                - "LABEL_VALUE"
      containers:
      - name: sleep
        image: ubuntu
        command: ["/bin/sleep", "inf"]

Reemplaza lo siguiente:

  • TAINT_KEY: La clave de taint que aplicaste al grupo de nodos dedicado.
  • TAINT_VALUE: El valor de taint que aplicaste a tu grupo de nodos dedicado.
  • 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.

Cuando actualizas el objeto Deployment con kubectl apply, GKE en AWS 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

Para verificar que la programación funcione correctamente, ejecuta el siguiente comando y verifica 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 administradas por GKE en AWS solo mediante la adición del taint components.gke.io/gke-managed-components. Agregar este taint evita que tus propios Pods se programen en esos nodos, lo que mejora el aislamiento.
  • Cuando crees grupos de nodos nuevos, evita que la mayoría de las cargas de trabajo administradas por GKE en AWS se ejecuten en esos nodos; para ello, agrega tu propio taint a esos grupos.
  • Cuando implementes cargas de trabajo nuevas en el clúster, como cuando se instalan herramientas de terceros, audita los permisos que requieren los Pods. Cuando sea posible, evita implementar cargas de trabajo que usen permisos elevados en los nodos compartidos.

¿Qué sigue?