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.

Activer GKE Sandbox

Vous pouvez activer GKE Sandbox sur un nouveau cluster ou un cluster existant.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  • Assurez-vous d'avoir activé l'API Google Kubernetes Engine.
  • Activer l'API Google Kubernetes Engine
  • Assurez-vous d'avoir installé le SDK Cloud.
  • Configurez les paramètres de l'outil de ligne de commande gcloud par défaut pour votre projet en utilisant l'une des méthodes suivantes:
    • Utilisez gcloud init si vous souhaitez suivre les étapes de définition des paramètres par défaut du projet.
    • Utilisez gcloud config pour définir individuellement l'ID, la zone et la région de votre projet.

    gcloud init

    1. Exécutez gcloud init et suivez les instructions :

      gcloud init

      Si vous utilisez SSH sur un serveur distant, utilisez l'option --console-only pour empêcher la commande d'ouvrir un navigateur :

      gcloud init --console-only
    2. Suivez les instructions pour autoriser l'outil gcloud à utiliser votre compte Google Cloud.
    3. Créez ou sélectionnez une configuration.
    4. Choisissez un projet Google Cloud.
    5. Choisissez une zone Compute Engine par défaut.
    6. Choisissez une région Compute Engine par défaut.

    gcloud config

    1. Définissez votre ID de projet par défaut :
      gcloud config set project PROJECT_ID
    2. Définissez votre région Compute Engine par défaut (par exemple, us-central1):
      gcloud config set compute/region COMPUTE_REGION
    3. Définissez votre zone Compute Engine par défaut (par exemple, us-central1-c):
      gcloud config set compute/zone COMPUTE_ZONE
    4. Mettez à jour gcloud vers la dernière version :
      gcloud components update

    En définissant des emplacements par défaut, vous pouvez éviter les erreurs dans l'outil gcloud, telles que les suivantes: One of [--zone, --region] must be supplied: Please specify location.

  • Pour le plan de contrôle et les nœuds du cluster, GKE Sandbox nécessite GKE version 1.13.5-gke.15 ou une version ultérieure.
  • Assurez-vous que la version du SDK Cloud est 243.0.0 ou ultérieure.

Sur un nouveau cluster

Pour activer GKE Sandbox, vous configurez un pool de nœuds. Le pool de nœuds par défaut (le premier pool de nœuds de votre cluster, créé lors de la création du cluster) ne peut pas utiliser GKE Sandbox. Pour activer GKE Sandbox lors de la création du cluster, vous devez ajouter un deuxième pool de nœuds lorsque vous créez le cluster.

Console

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

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

    Accéder à Google Kubernetes Engine

  2. Cliquez sur Créer.

  3. Facultatif, mais recommandé : Dans le volet de navigation, sous Cluster, cliquez sur Fonctionnalités et activez la suite Cloud Operations pour GKE, afin que les messages gVisor soient journalisés.

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

  5. Dans le volet 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.

  7. Dans le volet 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 Create (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 Cloud Operations pour GKE 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. Remarque : GKE Sandbox n'est pas compatible avec les types de machines e2-micro, e2-small et e2-medium.

Avant 1.18.4-gke.1300, le paramètre RuntimeClass gvisor est instancié lors de la création du nœud. Avant de programmer des charges de travail sur le nœud, vérifiez la présence du paramètre RuntimeClass gvisor à l'aide de la commande suivante :

kubectl get runtimeclasses

Le résultat ressemble à ce qui suit :

NAME     AGE
gvisor   19s

Si vous exécutez une version antérieure à 1.17.9-gke.1500 ou une version 1.18 antérieure à 1.18.1-gke.600, vous devez également attendre que le paramètre gvisor.config.common-webhooks.networking.gke.io soit instancié. Pour le vérifier, exécutez la commande suivante :

kubectl get mutatingwebhookconfiguration gvisor.config.common-webhooks.networking.gke.io

Le résultat ressemble à ce qui suit :

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

Sur un cluster existant

Pour activer GKE Sandbox sur un cluster 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 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 volet 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.

  6. Dans le volet de navigation, cliquez sur Sécurité, puis cochez la case Activer l'isolation en bac à sable avec gVisor.

  7. Cliquez sur Create (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.

Avant 1.18.4-gke.1300, le paramètre RuntimeClass gvisor est instancié lors de la création du nœud. Avant de programmer des charges de travail sur le nœud, vérifiez la présence du paramètre RuntimeClass gvisor à l'aide de la commande suivante :

kubectl get runtimeclasses
NAME     AGE
gvisor   19s

Si vous exécutez une version antérieure à 1.17.9-gke.1500 ou une version 1.18 antérieure à 1.18.1-gke.600, vous devez également attendre que le paramètre gvisor.config.common-webhooks.networking.gke.io soit instancié. Pour le vérifier, exécutez la commande suivante :

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

Facultatif : Activer la suite d'opérations Cloud pour GKE

Il est facultatif mais recommandé d'activer la suite d'opérations Cloud pour GKE sur le cluster afin que les messages gVisor soient journalisés. La suite d'opérations Cloud pour GKE est activée par défaut pour les nouveaux clusters.

Vous pouvez utiliser Google Cloud Console pour activer ces fonctionnalités sur un cluster existant.

  1. Accédez à la page Google Kubernetes Engine dans 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 Suite d'opérations Cloud pour GKE, cliquez sur Modifier la suite d'opérations Cloud pour GKE.

  4. Cochez la case Activer la suite Cloud Operations pour GKE.

  5. Dans la liste déroulante, sélectionnez Journalisation et surveillance du système et de la charge de travail.

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

Utiliser GKE Sandbox

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 le fichier manifeste de déploiement ci-dessous :

# 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

Pour créer le déploiement, utilisez la commande kubectl create :

kubectl create -f httpd.yaml

Le pod est déployé sur un nœud d'un pool de nœuds sur lequel GKE Sandbox est activé. Pour vérifier le déploiement, utilisez la commande suivante pour trouver 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 exécutez la commande suivante pour vérifier sa valeur pour 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écution d'un pod standard avec des pods en bac à sable

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 Workload Identity.

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 ci-dessus dans votre fichier manifeste de 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.

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 ci-dessus 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://metadata.google.internal/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

Il n'est actuellement pas possible de mettre à jour un pool de nœuds pour désactiver GKE Sandbox. Pour désactiver GKE Sandbox sur un pool de nœuds existant, vous pouvez effectuer l'une des opérations suivantes :

Étape suivante