Renforcer l'isolation d'une charge de travail avec GKE Sandbox


Cette page explique comment utiliser GKE Sandbox pour protéger le noyau hôte sur vos nœuds lorsque les conteneurs du pod exécutent du code inconnu ou non approuvé ou qu'ils ont besoin d'être davantage isolés du nœud.

Disponibilité de GKE Sandbox

GKE Sandbox est prêt à être utilisé sur les clusters Autopilot exécutant les versions 1.27.4-gke.800 et ultérieures de GKE. Pour commencer à déployer des charges de travail Autopilot dans un bac à sable, passez à la section Utiliser GKE Sandbox.

Pour utiliser GKE Sandbox dans des clusters GKE Standard nouveaux ou existants, vous devez activer manuellement GKE Sandbox sur le cluster.

Les charges de travail GPU sont compatibles avec GKE Sandbox sur les versions 1.29.2-gke.11080000 et ultérieures.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  • Activez l'API Google Kubernetes Engine.
  • Activer l'API Google Kubernetes Engine
  • Si vous souhaitez utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé gcloud CLI, assurez-vous de disposer de la dernière version en exécutant la commande gcloud components update.

Activer GKE Sandbox sur un nouveau cluster Standard

Le pool de nœuds par défaut, créé lors de la création d'un nouveau cluster, ne peut pas utiliser GKE Sandbox s'il s'agit du seul pool de nœuds du cluster, car les charges de travail du système gérées par GKE doivent s'exécuter séparément des charges de travail non approuvées dans le bac à sable. Pour activer GKE Sandbox lors de la création du cluster, vous devez ajouter au moins un pool de nœuds supplémentaire au cluster.

Console

Pour afficher vos clusters, accédez au menu Google Kubernetes Engine de la console Google Cloud.

  1. Accédez à la page Google Kubernetes Engine dans Google Cloud Console.

    Accéder à Google Kubernetes Engine

  2. Cliquez sur Créer.

  3. Facultatif, mais recommandé : Dans le menu de navigation, sous Cluster, cliquez sur Fonctionnalités et cochez les cases suivantes pour que les messages gVisor soient enregistrés :

    • Cloud Logging
    • Cloud Monitoring
    • Service géré pour Prometheus
  4. Cliquez sur  Ajouter un pool de nœuds.

  5. Dans le menu de navigation, sous Pools de nœuds, développez le nouveau pool de nœuds, puis cliquez sur Nœuds.

  6. Configurez les paramètres suivants pour le pool de nœuds :

    1. Dans la liste déroulante Type d'image, sélectionnez Container-Optimized OS avec Containerd (cos_containerd). Il s'agit du seul type d'image compatible avec GKE Sandbox.
    2. Sous Configuration de la machine, sélectionnez une série et un type de machine.
    3. Si vous exécutez une version de GKE compatible, vous pouvez également sélectionner un type de GPU. Il doit être de l'un des types suivants :
      • nvidia-tesla-t4
      • nvidia-tesla-a100
      • nvidia-a100-80gb
      • nvidia-l4
      • nvidia-h100-80gb
    4. Si vous utilisez des GPU sur GKE Sandbox, sélectionnez ou installez la variante de pilote latest.
  7. Dans le menu de navigation, sous le nom du pool de nœuds que vous configurez, cliquez sur Sécurité, puis cochez la case Activer l'isolation en bac à sable avec gVisor.

  8. Continuez à configurer le cluster et les pools de nœuds selon vos besoins.

  9. Cliquez sur Créer.

gcloud

GKE Sandbox ne peut pas être activé pour le pool de nœuds par défaut, et il n'est pas possible de créer d'autres pools de nœuds en même temps que vous créez un cluster à l'aide de la commande gcloud. Au lieu de cela, créez votre cluster comme vous le feriez normalement. Bien que facultatif, il est recommandé d'activer Logging et Monitoring afin que les messages gVisor soient journalisés.

Ensuite, utilisez la commande gcloud container node-pools create et définissez l'option -- sandbox sur type=gvisor. Le type d'image de nœud doit être cos_containerd pour 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

Remplacez les variables suivantes :

  • NODE_POOL_NAME : nom de votre nouveau pool de nœuds.
  • CLUSTER_NAME : nom du cluster
  • NODE_VERSION : version à utiliser pour le pool de nœuds.
  • MACHINE_TYPE : type de machine à utiliser pour les nœuds.

Pour créer un pool de nœuds GPU avec GKE Sandbox, exécutez la commande suivante:

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

Remplacez les éléments suivants :

Activer GKE Sandbox sur un cluster Standard existant

Pour activer GKE Sandbox sur un cluster Standard existant, vous pouvez ajouter un nouveau pool de nœuds et activer la fonctionnalité pour ce pool.

Console

Pour créer un pool de nœuds avec GKE Sandbox activé :

  1. Accédez à la page Google Kubernetes Engine dans Google Cloud Console.

    Accéder à Google Kubernetes Engine

  2. Cliquez sur le nom du cluster que vous souhaitez modifier.

  3. Cliquez sur  Ajouter un pool de nœuds.

  4. Configurez la page Détails du pool de nœuds selon vos besoins.

  5. Dans le menu de navigation, cliquez sur Nœuds et configurez les paramètres suivants :

    1. Dans la liste déroulante Type d'image, sélectionnez Container-Optimized OS avec Containerd (cos_containerd). Il s'agit du seul type d'image compatible avec GKE Sandbox.
    2. Sous Configuration de la machine, sélectionnez une série et un type de machine.
    3. Si vous exécutez une version de GKE compatible, vous pouvez également sélectionner un type de GPU. Il doit être de l'un des types suivants :
      • nvidia-tesla-t4
      • nvidia-tesla-a100
      • nvidia-a100-80gb
      • nvidia-l4
      • nvidia-h100-80gb
    4. Si vous utilisez des GPU sur GKE Sandbox, sélectionnez ou installez la variante de pilote latest.
  6. Dans le menu de navigation, cliquez sur Sécurité, puis cochez la case Activer l'isolation en bac à sable avec gVisor.

  7. Cliquez sur Créer.

gcloud

Pour créer un pool de nœuds avec GKE Sandbox activé, exécutez une commande telle que celle-ci :

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

Le type d'image de nœud doit être cos_containerd pour GKE Sandbox.

Pour créer un pool de nœuds GPU avec GKE Sandbox, exécutez la commande suivante:

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

Remplacez les éléments suivants :

Facultatif : Activer la surveillance et la journalisation

Il est facultatif mais recommandé d'activer Cloud Logging et Cloud Monitoring sur le cluster afin d'enregistrer les messages gVisor. Ces services sont activés par défaut pour les nouveaux clusters.

Sur un cluster existant, vous pouvez utiliser la console Google Cloud pour activer ces fonctionnalités.

  1. Accédez à la page Google Kubernetes Engine dans Google Cloud Console.

    Accéder à Google Kubernetes Engine

  2. Cliquez sur le nom du cluster que vous souhaitez modifier.

  3. Sous Fonctionnalités, dans le champ Cloud Logging, cliquez sur Modifier Cloud Logging.

  4. Cochez la case Activer Cloud Logging.

  5. Cliquez sur Save Changes (Enregistrer les modifications).

  6. Répétez les mêmes étapes pour les champs Cloud Monitoring et Managed Service pour Prometheus afin d'activer ces fonctionnalités.

Utiliser GKE Sandbox dans des clusters Autopilot et Standard

Dans les clusters Autopilot et les clusters Standard avec GKE Sandbox activé, vous demandez un environnement de bac à sable pour un pod en spécifiant la RuntimeClass gvisor dans la spécification du pod.

Pour les clusters Autopilot, assurez-vous d'exécuter la version 1.27.4-gke.800 ou une version ultérieure de GKE.

Exécuter une application dans un bac à sable

Pour forcer un déploiement à s'exécuter sur un nœud sur lequel GKE Sandbox est activé, définissez le paramètre spec.template.spec.runtimeClassName sur gvisor, comme indiqué dans l'exemple suivant :

# 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

Créez le déploiement :

kubectl apply -f httpd.yaml

Le pod est déployé sur un nœud avec GKE Sandbox activé. Pour vérifier le déploiement, recherchez le nœud sur lequel le pod est déployé :

kubectl get pods

Le résultat ressemble à ce qui suit :

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

Recherchez le nom du pod dans le résultat, puis vérifiez la valeur de RuntimeClass :

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

Le résultat est gvisor.

Vous pouvez également répertorier la valeur RuntimeClass de chaque pod et rechercher ceux qui affichent la valeur gvisor :

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

Le résultat est le suivant :

POD_NAME: gvisor

Cette méthode permettant de vérifier que le pod s'exécute dans un bac à sable est fiable, car elle ne repose sur aucune donnée contenue dans le bac à sable. Tout ce qui provient du bac à sable est considéré comme à risque, car il peut contenir des éléments défaillants ou malveillants.

Exécuter un pod avec des GPU sur GKE Sandbox

Pour exécuter une charge de travail GPU sur GKE Sandbox, ajoutez le champ runtimeClassName: gvisor à votre fichier manifeste, comme dans les exemples suivants:

  • Exemple de fichier manifeste pour les pods de GPU en mode 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
    
  • Exemple de fichier manifeste pour les pods de GPU en mode 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
    

Vous pouvez exécuter tous les pods de GPU en mode Autopilot ou Standard qui répondent aux exigences de version et de type de GPU sur GKE Sandbox en ajoutant le champ runtimeClassName: gvisor au fichier manifeste. Pour savoir comment exécuter des pods GPU dans GKE, consultez les ressources suivantes:

Exécution d'un pod standard avec des pods en bac à sable

Les étapes de cette section s'appliquent aux charges de travail en mode Standard. Vous n'avez pas besoin d'exécuter des pods Standard avec des pods de bac à sable en mode Autopilot, car le modèle de tarification Autopilot élimine le besoin d'optimiser manuellement le nombre de pods programmés sur les nœuds.

Après avoir activé GKE Sandbox sur un pool de nœuds, vous pouvez exécuter des applications approuvées sur ces nœuds sans utiliser de bac à sable, à l'aide des paramètres de rejet et de tolérance de nœud. Ces pods sont appelés "pods standards" pour les distinguer des pods en bac à sable.

Les pods standards, tout comme les pods en bac à sable, ne peuvent pas accéder aux autres services Google Cloud ni aux métadonnées du cluster. Cette protection fait partie de la configuration du nœud. Si vos pods standards ou en bac à sable nécessitent un accès aux services Google Cloud, utilisez la fédération d'identité de charge de travail pour GKE.

GKE Sandbox ajoute les étiquettes et les rejets suivants aux nœuds qui peuvent exécuter des pods en bac à sable :

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

En plus des paramètres d'affinité et de tolérance des nœuds dans votre fichier manifeste de pod, GKE Sandbox applique les paramètres d'affinité et de tolérance suivants à tous les pods dont la valeur RuntimeClass est définie sur 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

Pour programmer un pod standard sur un nœud avec GKE Sandbox activé, appliquez manuellement les paramètres d'affinité et de tolérance de nœud décrits précédemment dans le fichier manifeste de votre pod.

  • Si le pod peut s'exécuter sur des nœuds avec GKE Sandbox activé, ajoutez la tolérance.
  • Si votre pod doit s'exécuter sur des nœuds avec GKE Sandbox activé, ajoutez à la fois l'affinité et la tolérance de nœud.

Ainsi, le fichier manifeste suivant modifie le fichier manifeste utilisé dans la section Exécuter une application dans un bac à sable afin qu'il s'exécute comme un pod standard sur un nœud contenant des pods en bac à sable. Ici, la valeur runtimeClass est supprimée et les paramètres de rejet et de tolérance décrits précédemment sont ajoutés.

# 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

Tout d'abord, vérifiez que le déploiement ne s'exécute pas dans un bac à sable :

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

Le résultat est semblable à :

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

Le déploiement httpd créé précédemment s'exécute dans un bac à sable, car son runtimeClass est gvisor. Le déploiement httpd-no-sandbox n'affiche pas de valeur runtimeClass. Il ne s'exécute donc pas dans un bac à sable.

Ensuite, vérifiez que le déploiement hors bac à sable s'exécute sur un nœud avec GKE Sandbox à l'aide de la commande suivante :

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

Le nom du pool de nœuds est intégré dans la valeur de nodeName. Vérifiez que le pod s'exécute sur un nœud dans un pool de nœuds avec GKE Sandbox activé.

Valider la protection des métadonnées

Pour valider la déclaration selon laquelle les métadonnées sont protégées des nœuds pouvant exécuter des pods en bac à sable, vous pouvez effectuer le test suivant :

  1. Créez un déploiement en bac à sable à partir du fichier manifeste suivant, en utilisant kubectl apply -f. Cette fonction utilise l'image fedora, qui inclut la commande curl. Le pod exécute la commande /bin/sleep pour s'assurer que le déploiement s'exécute pendant 10 000 secondes.

    # 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. Récupérez le nom du pod en utilisant kubectl get pods, puis connectez-vous au pod de manière interactive à l'aide de kubectl exec.

    kubectl exec -it POD_NAME /bin/sh
    

    Vous êtes connecté à un conteneur s'exécutant dans le pod, dans une session /bin/sh.

  3. Dans la session interactive, essayez d'accéder à une URL qui renvoie des métadonnées de cluster :

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

    La commande se bloque et finit par expirer, car les paquets sont ignorés.

  4. Appuyez sur Ctrl+C pour terminer la commande curl et saisissez exit pour vous déconnecter du pod.

  5. Supprimez la ligne RuntimeClass du fichier manifeste YAML et redéployez le pod à l'aide de kubectl apply -f FILENAME. Le pod en bac à sable est arrêté et recréé sur un nœud sans GKE Sandbox.

  6. Obtenez le nouveau nom du pod, connectez-vous à l'aide de kubectl exec et exécutez à nouveau la commande curl. Cette fois, les résultats sont renvoyés. Cet exemple de sortie est tronqué.

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

    Saisissez exit pour vous déconnecter du pod.

  7. Supprimez le déploiement :

    kubectl delete deployment fedora
    

Désactiver GKE Sandbox

Vous ne pouvez pas désactiver GKE Sandbox dans des clusters GKE Autopilot ou dans des pools de nœuds GKE Standard. Si vous souhaitez cesser d'utiliser GKE Sandbox, supprimez le pool de nœuds.

Étapes suivantes