Endurece el aislamiento de las cargas de trabajo con GKE Sandbox


En esta página, se describe cómo usar GKE Sandbox para proteger el kernel del host en tus nodos cuando los contenedores del pod ejecutan un código desconocido o que no es de confianza, o necesitan un aislamiento extra del nodo.

Disponibilidad de GKE Sandbox

GKE Sandbox está listo para usarse en clústeres de Autopilot que ejecutan la versión 1.27.4-gke.800 y posteriores de GKE. Para comenzar a implementar cargas de trabajo de Autopilot en una zona de pruebas, ve a Trabaja con GKE Sandbox.

Para usar GKE Sandbox en clústeres nuevos o existentes de GKE Standard, debes habilitar GKE Sandbox de forma manual en el clúster.

Las cargas de trabajo de GPU son compatibles con GKE Sandbox en la versión 1.29.2-gke.11080000 y en versiones posteriores.

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

  • Habilita la API de Kubernetes Engine de Google.
  • Habilitar la API de Kubernetes Engine de Google
  • Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa gcloud CLI. Si ya instalaste gcloud CLI, ejecuta gcloud components update para obtener la versión más reciente.

Habilita GKE Sandbox en un clúster Standard nuevo

El grupo de nodos predeterminado, que se crea cuando creas un clúster nuevo, no puede usar GKE Sandbox si es el único grupo de nodos en el clúster, ya que las cargas de trabajo del sistema administradas por GKE deben ejecutarse por separado de las cargas de trabajo en zona de pruebas que no son de confianza. Para habilitar GKE Sandbox durante la creación del clúster, debes agregar al menos un grupo de nodos adicional al clúster.

Consola

Para ver tus clústeres, visita el menú de Google Kubernetes Engine en la consola de Google Cloud.

  1. Ve a la página de Google Kubernetes Engine en la consola de Google Cloud.

    Ir a Google Kubernetes Engine

  2. Haz clic en Crear.

  3. Opcional, pero recomendado: en el menú de navegación, en Clúster, haz clic en Funciones y selecciona las siguientes casillas de verificación para que se registren los mensajes de gVisor.

    • Cloud Logging
    • Cloud Monitoring
    • Servicio administrado para Prometheus
  4. Haz clic en Agregar grupo de nodos.

  5. Desde el menú de navegación, en Grupos de nodos, expande el grupo de nodos nuevo y haz clic en Nodos.

  6. Establece la siguiente configuración para el grupo de nodos:

    1. En la lista desplegable Tipo de imagen, selecciona Container-Optimized OS con Containerd (cos_containerd). Este es el único tipo de imagen compatible con GKE Sandbox.
    2. En Configuración de la máquina, selecciona una Serie y un Tipo de máquina.
    3. De manera opcional, si ejecutas una versión de GKE compatible, selecciona un tipo de GPU. Debe ser uno de los siguientes valores:
      • nvidia-tesla-t4
      • nvidia-tesla-a100
      • nvidia-a100-80gb
      • nvidia-l4
      • nvidia-h100-80gb
    4. Si usas GPU en GKE Sandbox, selecciona o instala la variante del controlador latest.
  7. En el menú de navegación, debajo del nombre del grupo de nodos que configuras, haz clic en Seguridad y selecciona la casilla de verificación Habilitar zona de pruebas con gVisor.

  8. Continúa configurando el clúster y los grupos de nodos como lo necesites.

  9. Haz clic en Crear.

gcloud

GKE Sandbox no se puede habilitar para el grupo de nodos predeterminado y no es posible crear grupos de nodos adicionales al mismo tiempo que creas un clúster nuevo con el comando gcloud. En su lugar, crea tu clúster como lo harías en condiciones normales. Aunque es opcional, se recomienda que habilites Logging y Monitoring para que se registren los mensajes de gVisor.

Luego, usa el comando gcloud container node-pools create y establece la marca -- sandbox en type=gvisor. El tipo de imagen del nodo debe ser cos_containerd para GKE Sandbox.

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --machine-type=MACHINE_TYPE \
  --image-type=cos_containerd \
  --sandbox type=gvisor

Reemplaza las siguientes variables:

  • NODE_POOL_NAME: es el nombre de tu grupo de nodos nuevo.
  • CLUSTER_NAME: El nombre de tu clúster.
  • NODE_VERSION: Es la versión que se usará para el grupo de nodos.
  • MACHINE_TYPE: Es el tipo de máquina que se usará para los nodos.

Para crear un grupo de nodos de GPU con GKE Sandbox, ejecuta el siguiente comando:

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --machine-type=MACHINE_TYPE \
  --accelerator=type=GPU_TYPE,gpu-driver-version=latest \
  --image-type=cos_containerd \
  --sandbox type=gvisor

Reemplaza lo siguiente:

Habilita GKE Sandbox en un clúster Standard existente

Puedes habilitar GKE Sandbox en un clúster Standard existente si agregas un grupo de nodos nuevo y habilitas la característica para este.

Consola

Para crear un grupo de nodos nuevo con GKE Sandbox habilitado, sigue estos pasos:

  1. Ve a la página de Google Kubernetes Engine en la consola de Google Cloud.

    Ir a Google Kubernetes Engine

  2. Haz clic en el nombre del clúster que deseas modificar.

  3. Haz clic en Agregar grupo de nodos.

  4. Configura la página de detalles del grupo de nodos como según la selección.

  5. En el menú de navegación, haz clic en Nodos y establece la siguiente configuración:

    1. En la lista desplegable Tipo de imagen, selecciona Container-Optimized OS con Containerd (cos_containerd). Este es el único tipo de imagen compatible con GKE Sandbox.
    2. En Configuración de la máquina, selecciona una Serie y un Tipo de máquina.
    3. De manera opcional, si ejecutas una versión de GKE compatible, selecciona un tipo de GPU. Debe ser uno de los siguientes valores:
      • nvidia-tesla-t4
      • nvidia-tesla-a100
      • nvidia-a100-80gb
      • nvidia-l4
      • nvidia-h100-80gb
    4. Si usas GPU en GKE Sandbox, selecciona o instala la variante del controlador latest.
  6. En el menú de navegación, haz clic en Seguridad y selecciona la casilla de verificación Habilitar zona de pruebas con gVisor.

  7. Haz clic en Crear.

gcloud

Para crear un grupo de nodos nuevo con GKE Sandbox habilitado, usa un comando como el siguiente:

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --machine-type=MACHINE_TYPE \
  --image-type=cos_containerd \
  --sandbox type=gvisor

El tipo de imagen del nodo debe ser cos_containerd para GKE Sandbox.

Para crear un grupo de nodos de GPU con GKE Sandbox, ejecuta el siguiente comando:

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --machine-type=MACHINE_TYPE \
  --accelerator=type=GPU_TYPE,gpu-driver-version=latest \
  --image-type=cos_containerd \
  --sandbox type=gvisor

Reemplaza lo siguiente:

Opcional: Habilita la supervisión y el registro

Es opcional, pero se recomienda que habilites Cloud Logging y Cloud Monitoring en el clúster para que se registren los mensajes de gVisor. Estos servicios están habilitados de forma predeterminada para clústeres nuevos.

Debes usar la consola de Google Cloud para habilitar estas funciones en un clúster existente.

  1. Ve a la página de Google Kubernetes Engine en la consola de Google Cloud.

    Ir a Google Kubernetes Engine

  2. Haz clic en el nombre del clúster que deseas modificar.

  3. En Funciones, en el campo Cloud Logging, haz clic en Editar Cloud Logging.

  4. Selecciona la casilla de verificación Habilitar Cloud Logging.

  5. Haz clic en Guardar cambios.

  6. Repite los mismos pasos para los campos de Cloud Monitoring y Managed Service para Prometheus para habilitar esas funciones.

Usa GKE Sandbox en Autopilot y Standard

En los clústeres de Autopilot y en los clústeres Standard con GKE Sandbox habilitado, debes solicitar un entorno de zona de pruebas para un pod a través de la especificación de RuntimeClass de gvisor en la especificación del pod.

Para los clústeres Autopilot, asegúrate de ejecutar la versión 1.27.4-gke.800 de GKE o una posterior.

Ejecuta una aplicación en una zona de pruebas

Para hacer que una implementación se ejecute en un nodo con GKE Sandbox habilitado, debes establecer su spec.template.spec.runtimeClassName en gvisor, como se muestra en el siguiente ejemplo:

# httpd.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
  labels:
    app: httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      runtimeClassName: gvisor
      containers:
      - name: httpd
        image: httpd

Crea el Deployment:

kubectl apply -f httpd.yaml

El Pod se implementa en un nodo con GKE Sandbox habilitado. Para verificar la implementación, busca el nodo en el que se implementa el Pod:

kubectl get pods

El resultado es similar a este:

NAME                    READY   STATUS    RESTARTS   AGE
httpd-db5899bc9-dk7lk   1/1     Running   0          24s

Busca el nombre del Pod en el resultado y, luego, verifica el valor de RuntimeClass:

kubectl get pods POD_NAME -o jsonpath='{.spec.runtimeClassName}'

El resultado es gvisor.

También puedes enumerar los objetos RuntimeClass de cada Pod y buscar los que están configurados como gvisor:

kubectl get pods -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'

Esta es la salida:

POD_NAME: gvisor

Este método para verificar que el pod se ejecute en una zona de pruebas es confiable, ya que no depende de ningún dato dentro de la zona de pruebas. Todo lo que se informe desde la zona de pruebas no es confiable, ya que podría ser defectuoso o malicioso.

Ejecuta un Pod con GPU en GKE Sandbox

Para ejecutar una carga de trabajo de GPU en GKE Sandbox, agrega el campo runtimeClassName: gvisor a tu manifiesto, como en los siguientes ejemplos:

  • Manifiesto de ejemplo para Pods de GPU de modo Standard:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-gpu-pod
    spec:
      runtimeClassName: gvisor
      containers:
      - name: my-gpu-container
        image: nvidia/samples:vectoradd-cuda10.2
        resources:
          limits:
          nvidia.com/gpu: 1
    
  • Manifiesto de ejemplo para Pods de GPU del modo Autopilot:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-gpu-pod
    spec:
      runtimeClassName: gvisor
      nodeSelector:
        cloud.google.com/compute-class: "Accelerator"
        cloud.google.com/gke-accelerator: nvidia-tesla-t4
      - name: my-gpu-container
        image: nvidia/samples:vectoradd-cuda10.2
        resources:
          limits:
            nvidia.com/gpu: 1
    

Puedes ejecutar cualquier Pod de GPU de modo Autopilot o Standard que cumpla con los requisitos de versión y tipo de GPU en GKE Sandbox. Para ello, agrega el campo runtimeClassName: gvisor al manifiesto. Si deseas obtener instrucciones para ejecutar Pods de GPU en GKE, consulta los siguientes recursos:

Ejecuta un pod común junto con pods de zona de pruebas

Los pasos de esta sección se aplican a las cargas de trabajo del modo Standard. No es necesario ejecutar Pods regulares junto con los Pods de la zona de pruebas en el modo Autopilot, ya que el modelo de precios de Autopilot elimina la necesidad de optimizar de forma manual la cantidad de Pods programada en los nodos.

Después de habilitar GKE Sandbox en un grupo de nodos, puedes ejecutar aplicaciones confiables en esos nodos sin usar una zona de pruebas a través de tolerancias y taints de nodo. Estos pods se denominan “pods regulares” para distinguirlos de los pods de zona de pruebas.

Los pod normales, al igual que los pods de zona de pruebas, no pueden acceder a otros servicios de Google Cloud ni a los metadatos del clúster. Esta prevención es parte de la configuración del nodo. Si tus Pods normales o Pods de zona de pruebas requieren acceso a los servicios de Google Cloud, usa la federación de identidades para cargas de trabajo para GKE.

GKE Sandbox agrega la siguiente etiqueta y taint a los nodos que pueden ejecutar pods de zona de pruebas:

labels:
  sandbox.gke.io/runtime: gvisor
taints:
- effect: NoSchedule
  key: sandbox.gke.io/runtime
  value: gvisor

Además de cualquier configuración de tolerancia y afinidad de nodo en tu manifiesto de pod, GKE Sandbox aplica la siguiente tolerancia y afinidad de nodo a todos los pods con RuntimeClass establecido en gvisor:

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: sandbox.gke.io/runtime
          operator: In
          values:
          - gvisor
tolerations:
  - effect: NoSchedule
    key: sandbox.gke.io/runtime
    operator: Equal
    value: gvisor

Para programar un pod regular en un nodo con GKE Sandbox habilitado, aplica de forma manual la tolerancia y la afinidad de nodos descritas antes en el manifiesto de tu pod.

  • Si el pod puede ejecutarse en nodos con GKE Sandbox habilitado, agrega la tolerancia.
  • Si tu pod debe ejecutarse en nodos con GKE Sandbox habilitado, agrega la tolerancia y la afinidad de nodo.

Por ejemplo, con el siguiente manifiesto se modifica el manifiesto usado en Ejecuta una aplicación en una zona de pruebas para que se ejecute como un pod regular en un nodo con pods de zona de pruebas, para esto, se quita la runtimeClass y se agrega el taint y la tolerancia descritos antes.

# httpd-no-sandbox.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-no-sandbox
  labels:
    app: httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: httpd
        image: httpd
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: sandbox.gke.io/runtime
                operator: In
                values:
                - gvisor
      tolerations:
        - effect: NoSchedule
          key: sandbox.gke.io/runtime
          operator: Equal
          value: gvisor

Primero, verifica que el objeto Deployment no se ejecute en una zona de pruebas:

kubectl get pods -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'

El resultado es similar a lo siguiente:

httpd-db5899bc9-dk7lk: gvisor
httpd-no-sandbox-5bf87996c6-cfmmd:

El Deployment httpd que se creó antes se ejecuta en una zona de pruebas, porque su runtimeClass es gvisor. La implementación httpd-no-sandbox no tiene valor para runtimeClass, por lo que no está en ejecución en una zona de pruebas.

A continuación, comprueba que la implementación sin zona de pruebas se ejecute en un nodo con GKE Sandbox a través de la ejecución del siguiente comando:

kubectl get pod -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.nodeName}\n{end}'

El nombre del grupo de nodos está incorporado en el valor de nodeName. Verifica que el pod se ejecute en un nodo de un grupo de nodos con GKE Sandbox habilitado.

Verifica la protección de metadatos

Para validar la afirmación de que los metadatos están protegidos de los nodos que pueden ejecutar pods de zona de pruebas, puedes realizar una prueba:

  1. Crea una implementación de zona de pruebas del siguiente manifiesto con kubectl apply -f. Usa la imagen fedora, que incluye el comando curl. El pod ejecuta el comando /bin/sleep para garantizar que la implementación se ejecute durante 10,000 segundos.

    # sandbox-metadata-test.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: fedora
      labels:
        app: fedora
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: fedora
      template:
        metadata:
          labels:
            app: fedora
        spec:
          runtimeClassName: gvisor
          containers:
          - name: fedora
            image: fedora
            command: ["/bin/sleep","10000"]
    
  2. Obtén el nombre del pod con kubectl get pods y, luego, usa kubectl exec para conectarte al pod de manera interactiva.

    kubectl exec -it POD_NAME /bin/sh
    

    Estás conectado a un contenedor que se ejecuta en el pod, en una sesión /bin/sh.

  3. Dentro de la sesión interactiva, intenta acceder a una URL que muestre metadatos de clúster:

    curl -s "http://169.254.169.254/computeMetadata/v1/instance/attributes/kube-env" -H "Metadata-Flavor: Google"
    

    El comando se cuelga y, por último, se agota el tiempo de espera, porque los paquetes se descartan en silencio.

  4. Presiona Ctrl+C para terminar el comando curl y escribe exit para desconectarte del pod.

  5. Quita la línea RuntimeClass del manifiesto YAML y vuelve a implementar el pod con kubectl apply -f FILENAME. El pod de zona de pruebas se termina y se vuelve a crear en un nodo sin GKE Sandbox.

  6. Obtén el nombre de pod nuevo, conéctate a él con kubectl exec y vuelve a ejecutar el comando curl. Esta vez, se muestran resultados. Este resultado de ejemplo está truncado.

    ALLOCATE_NODE_CIDRS: "true"
    API_SERVER_TEST_LOG_LEVEL: --v=3
    AUTOSCALER_ENV_VARS: kube_reserved=cpu=60m,memory=960Mi,ephemeral-storage=41Gi;...
    ...
    

    Escribe exit para desconectarte del pod.

  7. Quita la implementación:

    kubectl delete deployment fedora
    

Inhabilita GKE Sandbox

No puedes inhabilitar GKE Sandbox en clústeres de GKE Autopilot ni en grupos de nodos de GKE Standard. Si quieres dejar de usar GKE Sandbox, borra el grupo de nodos.

¿Qué sigue?