Isoler les charges de travail dans des pools de nœuds dédiés

Cette page explique comment réduire le risque d'attaques par élévation des privilèges dans votre cluster en configurant GKE sur Azure pour planifier vos charges de travail sur un pool de nœuds dédié distinct et éloigné des charges de travail gérées privilégiées.

Présentation

Les clusters GKE sur Azure utilisent des charges de travail privilégiées que nous gérons pour activer des fonctionnalités de cluster spécifiques, telles que la collecte de métriques. Ces charges de travail disposent d'autorisations spéciales pour s'exécuter correctement dans le cluster.

Les charges de travail que vous déployez sur vos nœuds peuvent être compromises par une entité malveillante. L'exécution de ces charges de travail parallèlement aux charges de travail privilégiées du système signifie qu'un pirate informatique qui sort d'un conteneur compromis peut utiliser les identifiants de la charge de travail privilégiée sur le nœud pour élever les privilèges dans votre cluster.

Empêcher la fuite des conteneurs

Votre principale défense doit être vos applications. GKE sur Azure comporte plusieurs fonctionnalités que vous pouvez utiliser pour renforcer vos clusters et vos pods. Dans la plupart des cas, nous vous recommandons vivement d'utiliser Policy Controller et les fonctionnalités de sécurité du noyau pour renforcer vos charges de travail. Pour obtenir d'autres recommandations sur la sécurité, consultez la Présentation des fonctionnalités de sécurité.

Éviter les attaques par élévation de privilèges

Si vous souhaitez bénéficier d'une couche d'isolation supplémentaire en plus d'autres mesures de renforcement, vous pouvez utiliser des rejets de nœuds et l'affinité de nœuds pour planifier vos charges de travail sur un pool de nœuds dédié.

Un rejet de nœud indique à GKE sur Azure d'éviter de planifier des charges de travail sans tolérance correspondante (comme GKE sur les charges de travail gérées par Azure) sur ces nœuds. L'affinité de nœuds sur vos propres charges de travail indique à GKE sur Azure de programmer vos pods sur les nœuds dédiés.

Limites de l'isolation des nœuds

  • Les pirates informatiques peuvent toujours lancer des attaques par déni de service (DoS) à partir du nœud compromis.
  • Les nœuds compromis peuvent toujours lire de nombreuses ressources, y compris tous les pods et espaces de noms du cluster.
  • Les nœuds compromis peuvent accéder aux secrets et aux identifiants utilisés par chaque pod exécuté sur ce nœud.
  • L'utilisation d'un pool de nœuds distinct pour isoler vos charges de travail peut avoir une incidence sur la rentabilité, l'autoscaling et l'utilisation des ressources.
  • Les nœuds compromis peuvent toujours contourner les règles de réseau de sortie.
  • Certaines charges de travail gérées par GKE sur Azure doivent s'exécuter sur chaque nœud de votre cluster et sont configurées pour tolérer tous les rejets.
  • Si vous déployez des DaemonSets disposant d'autorisations élevées et pouvant tolérer tout rejet, ces pods peuvent constituer une voie d'élévation des privilèges à partir d'un nœud compromis.

Fonctionnement de l'isolation des nœuds

Pour implémenter l'isolation des nœuds pour vos charges de travail, vous devez procéder comme suit :

  1. Ajoutez un rejet et un libellé au pool de nœuds pour vos charges de travail.
  2. Mettez à jour vos charges de travail avec la tolérance et la règle d'affinité de nœud correspondantes.

Dans ce guide, nous partons du principe que vous disposez d'un pool de nœuds dans votre cluster. L'utilisation de l'affinité des nœuds en plus des rejets de nœuds n'est pas obligatoire, mais nous vous recommandons de l'utiliser, car vous bénéficiez d'un meilleur contrôle sur la planification.

Avant de commencer

Pour effectuer les étapes décrites sur cette page, procédez comme suit :

Ajouter un rejet et un libellé à un pool de nœuds pour vos charges de travail

Créez un pool de nœuds pour vos charges de travail, puis appliquez un rejet de nœud et un libellé de nœud. Lorsque vous appliquez un rejet ou un libellé au niveau du pool de nœuds, il est appliqué automatiquement à tous les nouveaux nœuds, tels que ceux créés par l'autoscaling.

Vous pouvez également ajouter des rejets de nœuds et des libellés de nœuds à des pools de nœuds existants. Si vous utilisez l'effet NoExecute, GKE sur Azure évince tous les pods exécutés sur les nœuds qui n'ont pas de tolérance au nouveau rejet.

Pour ajouter un rejet et un libellé à un nouveau pool de nœuds, exécutez la commande suivante :

gcloud container azure node-pools create POOL_NAME \
    --cluster CLUSTER_NAME \
    --node-taints TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
    --node-labels LABEL_KEY=LABEL_VALUE

Remplacez les éléments suivants :

  • POOL_NAME : nom du nouveau pool de nœuds pour vos charges de travail.
  • CLUSTER_NAME: nom de votre cluster GKE sur Azure.
  • TAINT_KEY=TAINT_VALUE : paire clé-valeur associée à un TAINT_EFFECT de planification. Exemple : workloadType=untrusted.
  • TAINT_EFFECT : l'une des valeurs d'effet suivantes : NoSchedule, PreferNoSchedule ou NoExecute. NoExecute fournit une meilleure garantie d'éviction que NoSchedule.
  • LABEL_KEY=LABEL_VALUE : paires clé/valeur pour les libellés de nœud, qui correspondent aux sélecteurs que vous spécifiez dans vos fichiers manifestes de charge de travail.

Ajouter une tolérance et une règle d'affinité de nœuds aux charges de travail

Une fois que vous avez ajouté un rejet au pool de nœuds dédié, aucune charge de travail ne peut y être programmée, à moins qu'elle ne dispose d'une tolérance correspondant au rejet que vous avez ajouté. Ajoutez la tolérance à la spécification de vos charges de travail afin de permettre la programmation de ces pods sur votre pool de nœuds rejeté.

Si vous avez ajouté un libellé au pool de nœuds dédié, vous pouvez également ajouter une règle d'affinité de nœuds pour indiquer à GKE sur Azure de ne planifier vos charges de travail que sur ce pool de nœuds.

L'exemple suivant ajoute une tolérance au rejet workloadType=untrusted:NoExecute et une règle d'affinité de nœud pour le libellé de nœud workloadType=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: TAINT_KEY
        operator: Equal
        value: TAINT_VALUE
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: LABEL_KEY
                operator: In
                values:
                - "LABEL_VALUE"
      containers:
      - name: sleep
        image: ubuntu
        command: ["/bin/sleep", "inf"]

Remplacez les éléments suivants :

  • TAINT_KEY : clé de rejet que vous avez appliquée à votre pool de nœuds dédié.
  • TAINT_VALUE : valeur de rejet que vous avez appliquée à votre pool de nœuds dédié.
  • LABEL_KEY : clé de libellé de nœud que vous avez appliquée à votre pool de nœuds dédié.
  • LABEL_VALUE : valeur du libellé de nœud que vous avez appliquée à votre pool de nœuds dédié.

Lorsque vous mettez à jour votre déploiement avec kubectl apply, GKE sur Azure recrée les pods concernés. La règle d'affinité de nœuds force l'application des pods sur le pool de nœuds dédié que vous avez créé. La tolérance ne permet de placer ces pods que sur les nœuds.

Vérifier que la séparation fonctionne

Pour vérifier que la planification fonctionne correctement, exécutez la commande suivante et vérifiez si vos charges de travail se trouvent dans le pool de nœuds dédié :

kubectl get pods -o=wide

Recommandations et bonnes pratiques

Après avoir configuré l'isolation des nœuds, nous vous recommandons d'effectuer les opérations suivantes :

  • Limitez des pools de nœuds spécifiques à GKE sur les charges de travail gérées par Azure uniquement en ajoutant le rejet components.gke.io/gke-managed-components. L'ajout de ce rejet empêche la planification de vos pods sur ces nœuds, améliorant ainsi l'isolation.
  • Lorsque vous créez des pools de nœuds, empêchez la plupart des charges de travail gérées par GKE sur Azure de s'exécuter sur ces nœuds en ajoutant votre propre rejet à ces pools de nœuds.
  • Chaque fois que vous déployez de nouvelles charges de travail sur votre cluster, par exemple lors de l'installation d'outils tiers, vérifiez les autorisations requises par les pods. Dans la mesure du possible, évitez de déployer des charges de travail qui utilisent des autorisations avec privilèges élevés sur des nœuds partagés.

Étapes suivantes