En esta página, se muestra cómo aislar tus cargas de trabajo de contenedores en grupos de nodos dedicados en Google Distributed Cloud (GDC) aislados para brindarte más control sobre tus pods. El aislamiento de la carga de trabajo proporciona algunos beneficios, como los siguientes:
- Se reduce el riesgo de ataques de elevación de privilegios en tu clúster de Kubernetes.
- Más control sobre los Pods que requieren recursos adicionales
En estos casos, considera aislar tus cargas de trabajo de contenedores para tener más control y optimización.
¿Por qué debería aislar mis cargas de trabajo?
No es necesario aislar tus cargas de trabajo en grupos de nodos dedicados, pero puede ser una acción prudente para evitar posibles problemas. Sin embargo, ten en cuenta que administrar grupos de nodos dedicados requiere más supervisión y, muchas veces, es innecesario.
Los clústeres de Kubernetes usan cargas de trabajo administradas por GDC con privilegios 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 administradas por GDC 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.
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 el disco local.
Puedes usar los siguientes mecanismos para programar tus cargas de trabajo en un grupo de nodos dedicado:
- Aislamiento 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/
Un taint de nodo le indica a tu clúster de Kubernetes que evite programar cargas de trabajo sin una tolerancia correspondiente, como las cargas de trabajo administradas por GDC, en esos nodos. La afinidad de nodos en tus propias cargas de trabajo le indica al clúster 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 GDC deben ejecutarse en cada nodo del clúster y están configuradas para tolerar todos los taints.
Si implementas recursos
DaemonSet
que tienen permisos elevados y pueden tolerar cualquier taint, esos Pods pueden 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:
Aplica un taint y una etiqueta a un grupo de nodos para las cargas de trabajo.
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
Antes de comenzar, asegúrate de haber realizado las siguientes tareas:
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
.Si es necesario, pídele al administrador de IAM de la organización que te otorgue el rol de desarrollador de clúster de usuario (
user-cluster-developer
), que no está vinculado a un espacio de nombres.
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.
Para agregar un taint y una etiqueta a un grupo de nodos nuevo, completa los siguientes pasos:
Edita la sección
nodePools
del recurso personalizadoCluster
directamente cuando crees 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
Reemplaza lo siguiente:
TAINT_KEY=TAINT_VALUE
: Es un par clave-valor asociado con una programación deTAINT_EFFECT
. Por ejemplo,workloadType=untrusted
.TAINT_EFFECT
: Uno de los siguientes valores de efecto:NoSchedule
: Los Pods que no toleran este taint no se programan en el nodo. Los Pods existentes no se desalojan del nodo.PreferNoSchedule
: Kubernetes evita la programación de pods que no toleran este taint en el nodo.NoExecute
: El pod se desaloja del nodo si ya se está ejecutando en este y no se programa en el nodo si aún no se está ejecutando 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.
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 acceso al archivo kubeconfig del servidor de la API zonal en el que se aloja el clúster de Kubernetes. Si aún no generaste un archivo kubeconfig para el servidor de la API en la zona de destino, consulta Accede para obtener más detalles.
Aplica un taint y una etiqueta a un grupo de nodos existente
Para aplicar una asociación o etiqueta a un grupo de nodos existente, debes aplicar los cambios a cada nodo existente. No puedes actualizar de forma dinámica la configuración de los grupos de nodos.
Para agregar un taint y una etiqueta a un grupo de nodos existente, completa los siguientes pasos:
Enumera 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 acceso a kubeconfig del clúster de Kubernetes.NODE_POOL_NAME
: Es el nombre de tu grupo de nodos dedicados.
Toma nota del ID de cada nodo del grupo de nodos a partir del resultado.
Aplica los contaminantes a cada nodo del grupo de nodos:
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 deTAINT_EFFECT
. Por ejemplo,workloadType=untrusted
.TAINT_EFFECT
: Uno de los siguientes valores de efecto:NoSchedule
: Los Pods que no toleran este taint no se programan en el nodo. Los Pods existentes no se desalojan del nodo.PreferNoSchedule
: Kubernetes evita la programación de pods que no toleran este taint en el nodo.NoExecute
: El pod se desaloja del nodo si ya se está ejecutando en este y no se programa en el nodo si aún no se está ejecutando en él.
KUBERNETES_CLUSTER_KUBECONFIG
: Es la ruta de acceso a kubeconfig del clúster de Kubernetes.
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
: Son 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 acceso a kubeconfig del 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 indicarle a GDC que solo programe tus cargas de trabajo en ese grupo de nodos.
Para configurar tu carga de trabajo de contenedor para que se ejecute en el grupo de nodos dedicado, completa los siguientes pasos:
Agrega 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" ...
Reemplaza lo siguiente:
TAINT_KEY
: 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
: Uno de los siguientes valores de efecto:NoSchedule
: Los Pods que no toleran este taint no se programan en el nodo. Los Pods existentes no se desalojan del nodo.PreferNoSchedule
: Kubernetes evita la programación de pods que no toleran este taint en el nodo.NoExecute
: El pod se desaloja del nodo si ya se está ejecutando en este y no se programa en el nodo si aún no se está ejecutando 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 recurso
Deployment
agrega una tolerancia para el taintworkloadType=untrusted:NoExecute
y una regla de afinidad de nodos 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 implementación:
kubectl apply -f deployment.yaml -n NAMESPACE \ --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
Reemplaza las siguientes variables:
NAMESPACE
: Es el espacio de nombres del proyecto de tu carga de trabajo de contenedor.KUBERNETES_CLUSTER_KUBECONFIG
: Es la ruta de acceso a kubeconfig del 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
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 -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 nuevos, evita que la mayoría de las cargas de trabajo administradas por GDC 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.