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.

Habilita GKE Sandbox

Puedes habilitar GKE Sandbox en un clúster nuevo o en un clúster existente.

Antes de comenzar

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

Establece la configuración de gcloud predeterminada mediante uno de los siguientes métodos:

  • Usa gcloud init si deseas ver una explicación sobre cómo configurar parámetros predeterminados.
  • Usa gcloud config para establecer el ID, la zona y la región del proyecto de manera individual.

Usa gcloud init

Si recibes el error One of [--zone, --region] must be supplied: Please specify location, completa esta sección.

  1. Ejecuta gcloud init y sigue las instrucciones:

    gcloud init

    Si usas SSH en un servidor remoto, usa la marca --console-only para evitar que el comando abra un navegador:

    gcloud init --console-only
  2. Sigue las instrucciones a fin de autorizar a gcloud para que use tu cuenta de Google Cloud.
  3. Crea una configuración nueva o selecciona una existente.
  4. Elige un proyecto de Google Cloud.
  5. Elige una zona predeterminada de Compute Engine para clústeres zonales o una región para clústeres regionales o de Autopilot.

Usa gcloud config

  • Establece tu ID del proyecto predeterminado:
    gcloud config set project PROJECT_ID
  • Si trabajas con clústeres zonales, establece tu zona de procesamiento predeterminada:
    gcloud config set compute/zone COMPUTE_ZONE
  • Si trabajas con clústeres de Autopilot o regionales, configura tu región de procesamiento predeterminada:
    gcloud config set compute/region COMPUTE_REGION
  • Actualiza gcloud a la versión más reciente:
    gcloud components update
  • GKE Sandbox requiere la versión 1.13.5-gke.15 o posterior de GKE para el plano de control y los nodos del clúster.
  • Asegúrate de que el comando de gcloud sea de la versión 243.0.0 o posterior.

En un clúster nuevo

Para habilitar GKE Sandbox, configura un grupo de nodos. El grupo de nodos predeterminado (el primer grupo de nodos en tu clúster, creado junto con este) no puede usar GKE Sandbox. Para habilitar GKE Sandbox durante la creación del clúster, debes agregar un segundo grupo de nodos durante la creación.

Console

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

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

    Ir a Google Kubernetes Engine

  2. Haz clic en Crear.

  3. Opcional, pero recomendado: en el panel de navegación, en Clúster, haz clic en Funciones y habilita operaciones de Cloud para GKE, de modo que los mensajes de gVisor se registren.

  4. Haz clic en Agregar grupo de nodos.

  5. Desde el panel 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).
    2. En Configuración de la máquina, selecciona una Serie y un Tipo de máquina.

  7. En el panel 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 desees.

  9. Haga 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. Es opcional, pero se recomienda que agregues la marca --enable-stackdriver-kubernetes para habilitar Stackdriver Logging y Stackdriver Monitoring. Los mensajes de gVisor se registran.

Luego, usa el comando gcloud container node-pools create y establece la marca --sandbox en type=gvisor. Reemplaza los valores entre corchetes con los tuyos.

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 \

Antes de 1.18.4-gke.1300, se crea una instancia de RuntimeClass gvisor durante la creación del nodo. Antes de que se programen las cargas de trabajo en el nodo, verifica la existencia de la RuntimeClass gvisor con el siguiente comando:

kubectl get runtimeclasses
NAME     AGE
gvisor   19s

Si ejecutas una versión anterior a la versión 1.17.9-gke.1500 o una versión 1.18 anterior a 1.18.6-gke.600, también debes esperar a que se cree una instancia para gvisor.config.common-webhooks.networking.gke.io. Para la verificación, usa el siguiente comando:

kubectl get mutatingwebhookconfiguration gvisor.config.common-webhooks.networking.gke.io
NAME                                              CREATED AT
gvisor.config.common-webhooks.networking.gke.io   2020-04-06T17:07:17Z

En un clúster existente

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

Console

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

  1. Ve al menú de Google Kubernetes Engine en Cloud Console.

    Ir al menú 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 desees.

  5. En el panel 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).
    2. En Configuración de la máquina, selecciona una Serie y un Tipo de máquina.

  6. En el panel de navegación, haz clic en Seguridad y selecciona la casilla de verificación Habilitar zona de pruebas con gVisor.

  7. Haga 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

Antes de 1.18.4-gke.1300, se crea una instancia de RuntimeClass gvisor durante la creación del nodo. Antes de que se programen las cargas de trabajo en el nodo, verifica la existencia de la RuntimeClass gvisor con el siguiente comando:

kubectl get runtimeclasses
NAME     AGE
gvisor   19s

Si ejecutas una versión anterior a la versión 1.17.9-gke.1500 o una versión 1.18 anterior a 1.18.6-gke.600, también debes esperar a que se cree una instancia para gvisor.config.common-webhooks.networking.gke.io. Para la verificación, usa el siguiente comando:

kubectl get mutatingwebhookconfiguration gvisor.config.common-webhooks.networking.gke.io
NAME                                              CREATED AT
gvisor.config.common-webhooks.networking.gke.io   2020-04-06T17:07:17Z

Opcional: habilita Cloud Operations para GKE

Es opcional, pero se recomienda que habilites Cloud Operations para GKE en el clúster, de modo que se registren los mensajes de gVisor. Cloud Operations para GKE están habilitadas de forma predeterminada para clústeres nuevos.

Puedes usar Google Cloud Console para habilitar estas funciones en un clúster existente.

  1. Ve al menú de Google Kubernetes Engine en Cloud Console.

    Ir al menú Google Kubernetes Engine

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

  3. En Funciones, en el campo Operaciones de la nube para GKE, haz clic en Editar operaciones de Cloud para GKE.

  4. Selecciona la casilla de verificación Habilitar operaciones de Cloud para GKE.

  5. En la lista desplegable, selecciona Registros y supervisión del sistema y la carga de trabajo.

  6. Haz clic en Save Changes.

Trabaja con GKE Sandbox

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 este manifiesto para una implementación:

# 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

Para crear la implementación, usa el comando kubectl create:

kubectl create -f httpd.yaml

El pod se implementa en un nodo de un grupo de nodos con GKE Sandbox habilitado. Para verificar la implementación, usa el siguiente comando a fin de buscar el nodo en el que se implementa el pod:

kubectl get pods

El resultado es similar a lo siguiente:

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

Busca el nombre del pod en el resultado y, luego, ejecuta el siguiente comando a fin de verificar su valor para RuntimeClass:

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

Este es el resultado:

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}'

El resultado es el siguiente:

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 regular junto con pods de zona de pruebas

Después de habilitar GKE Sandbox en un grupo de nodos, puedes ejecutar aplicaciones confiables en esos nodos sin usar una zona de pruebas mediante 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 Workload Identity.

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 nodo anteriores 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 a fin de 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 anteriores.

# 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 mediante 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 mediante 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://metadata.google.internal/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 a fin de desconectarte del pod.

  5. Quita la línea RuntimeClass del manifiesto YAML y vuelve a implementar el pod mediante 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 mediante 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

En la actualidad, no es posible actualizar un grupo de nodos para inhabilitar GKE Sandbox. Para inhabilitar GKE Sandbox en un grupo de nodos existente, puedes realizar uno de los procedimientos siguientes:

¿Qué sigue?