En esta página se muestra cómo aislar las cargas de trabajo de tu contenedor en grupos de nodos dedicados en Google Distributed Cloud (GDC) con air gap para que tengas más control sobre tus pods. El aislamiento de cargas de trabajo ofrece algunas ventajas, como las siguientes:
- Se reduce el riesgo de ataques de apropiación de privilegios en tu clúster de Kubernetes.
- Más control sobre los pods que requieren recursos adicionales.
En estos casos, te recomendamos que aísles las cargas de trabajo de tus contenedores para tener más control y optimización.
¿Por qué debería aislar mis cargas de trabajo?
No es obligatorio aislar las cargas de trabajo en grupos de nodos dedicados, pero puede ser una medida prudente para evitar posibles problemas. Sin embargo, ten en cuenta que gestionar grupos de nodos dedicados requiere más supervisión y, muchas veces, no es necesario.
Los clústeres de Kubernetes usan cargas de trabajo privilegiadas gestionadas por GDC para habilitar funciones y características específicas del clúster, como la recogida de métricas. Estas cargas de trabajo reciben 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 GDC, un atacante que se escape de un contenedor vulnerado puede usar las credenciales de la carga de trabajo privilegiada del nodo para aumentar los privilegios en tu clúster.
Los grupos de nodos dedicados también son útiles cuando debes programar pods que requieren más recursos que otros, como más memoria o más espacio en disco local.
Puede usar los siguientes mecanismos para programar sus cargas de trabajo en un grupo de nodos dedicado:
- Intolerancias de nodos: https://cloud.google.com/kubernetes-engine/docs/how-to/node-taints
- Afinidad de nodo: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/
Una intolerancia de nodo informa a tu clúster de Kubernetes de que debe evitar programar cargas de trabajo sin una tolerancia correspondiente, como las cargas de trabajo gestionadas por GDC, en esos nodos. La afinidad de nodo de tus cargas de trabajo indica al clúster 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 GDC deben ejecutarse en todos los nodos de tu clúster y están configuradas para tolerar todos los taints.
Si implementas recursos de
DaemonSet
que tienen permisos elevados y pueden tolerar cualquier taint, esos pods podrían 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:
Aplica un taint y una etiqueta a un grupo de nodos para tus cargas de trabajo.
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 haber realizado las siguientes tareas:
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
.Si es necesario, pide al administrador de gestión de identidades y accesos de tu organización que te conceda el rol Desarrollador de clústeres de usuarios (
user-cluster-developer
), que no está vinculado a un espacio de nombres.
Contaminar y etiquetar 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.
Para añadir un taint y una etiqueta a un nuevo grupo de nodos, sigue estos pasos:
Edita la sección
nodePools
del recurso personalizadoCluster
directamente al crear el grupo de nodos:nodePools: ... - machineTypeName: n2-standard-2-gdc name: nodepool-1 nodeCount: 3 taints: TAINT_KEY=TAINT_VALUE:TAINT_EFFECT labels: LABEL_KEY=LABEL_VALUE
Haz los cambios siguientes:
TAINT_KEY=TAINT_VALUE
: un par clave-valor asociado a una programaciónTAINT_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 marca 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.
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. Si aún no has generado un archivo kubeconfig para el servidor de la API en la zona de destino, consulta Iniciar sesión para obtener más información.
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.
Para añadir un taint y una etiqueta a un grupo de nodos, sigue estos pasos:
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.
Aplica las intolerancias a cada nodo del grupo de nodos:
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ónTAINT_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 marca 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.
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:
Añade las siguientes secciones a la sección
.spec.template.spec
de la carga de trabajo del contenedor:kind: Deployment apiVersion: apps/v1 ... spec: ... template: spec: 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 marca 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 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 dedicados.
Por ejemplo, el siguiente recurso
Deployment
añade una tolerancia para el taintworkloadType=untrusted:NoExecute
y una regla de afinidad de nodo para la etiqueta de nodoworkloadType=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
Actualiza tu despliegue:
kubectl apply -f deployment.yaml -n NAMESPACE \ --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
Sustituye las siguientes variables:
NAMESPACE
: el espacio de nombres del proyecto de tu carga de trabajo del contenedor.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
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 -n NAMESPACE \
--kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
Recomendaciones y prácticas recomendadas
Después de configurar el aislamiento de nodos, te recomendamos que hagas lo siguiente:
- Cuando crees grupos de nodos, evita que la mayoría de las cargas de trabajo gestionadas por GDC 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.