Ce document explique comment améliorer la sécurité et la gestion de votre cluster Kubernetes en isolant les charges de travail de conteneurs dans des pools de nœuds dédiés dans Google Distributed Cloud (GDC) air-gapped. L'isolation de vos charges de travail vous permet de mieux contrôler vos pods et de réduire le risque d'attaques par élévation des privilèges dans votre cluster Kubernetes. Pour en savoir plus sur les avantages et les limites des pools de nœuds dédiés, consultez Présentation de l'isolation des nœuds.
Plusieurs workflows sont impliqués dans l'isolation de vos charges de travail de conteneur, y compris les suivants :
Ajouter un rejet et un libellé à un pool de nœuds : appliquez un rejet et un libellé à un pool de nœuds pour qu'il repousse les pods, sauf s'ils sont spécifiquement libellés pour s'y exécuter.
Ajoutez une tolérance et une règle d'affinité de nœuds : appliquez des tolérances et des règles à vos pods pour les forcer à s'exécuter uniquement sur le pool de nœuds désigné.
Vérifiez que la séparation fonctionne : assurez-vous que vos pools de nœuds contaminés n'exécutent que les pods que vous avez étiquetés pour qu'ils s'y exécutent.
Ces workflows sont destinés à des audiences telles que les administrateurs informatiques du groupe d'administrateurs de plate-forme, qui sont chargés de gérer les pools de nœuds d'un cluster Kubernetes, et les développeurs d'applications du groupe d'opérateurs d'applications, qui sont chargés de gérer les charges de travail de conteneurs. Pour en savoir plus, consultez Audiences pour la documentation GDC air-gapped.
Avant de commencer
Avant de commencer, effectuez les tâches suivantes :
Choisissez un nom spécifique pour le rejet de nœud et le libellé de nœud que vous souhaitez utiliser pour les pools de nœuds dédiés. Par exemple,
workloadType=untrusted
.Si nécessaire, demandez à l'administrateur IAM de votre organisation de vous attribuer le rôle Développeur de cluster utilisateur (
user-cluster-developer
), qui n'est pas lié à un espace de noms.
Ajouter un rejet et un libellé à un pool de nœuds
Lorsque vous appliquez un rejet ou un libellé à un nouveau pool de nœuds, il est appliqué automatiquement à tous les nœuds, y compris ceux ajoutés ultérieurement.
Pour ajouter un rejet et un libellé à un nouveau pool de nœuds, procédez comme suit :
Modifiez directement la section
nodePools
de la ressource personnaliséeCluster
lorsque vous créez le pool de nœuds :nodePools: # Several lines of code are omitted here. - machineTypeName: n2-standard-2-gdc name: nodepool-1 nodeCount: 3 taints: - key: "TAINT_KEY" value: "TAINT_VALUE" effect: "TAINT_EFFECT" labels: LABEL_KEY: LABEL_VALUE
Remplacez les éléments suivants :
TAINT_KEY
: partie clé de la paire clé-valeur associée à unTAINT_EFFECT
de planification. Par exemple,workloadType
.TAINT_VALUE
: partie valeur du rejet de la paire clé-valeur associée à unTAINT_EFFECT
de planification. Par exemple,untrusted
.TAINT_EFFECT
: l'une des valeurs d'effet suivantes :NoSchedule
: les pods qui ne tolèrent pas ce rejet ne sont pas programmés sur le nœud ; les pods existants ne sont pas expulsés du nœud.PreferNoSchedule
: Kubernetes évite de programmer les pods qui ne tolèrent pas ce rejet sur le nœud.NoExecute
: si le pod est déjà en cours d'exécution sur le nœud, il est expulsé de celui-ci. Dans le cas contraire, il n'est pas programmé sur le nœud.
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.
Appliquez la ressource
Cluster
pour créer le pool de nœuds :kubectl apply -f cluster.yaml --kubeconfig MANAGEMENT_API_SERVER
Remplacez
MANAGEMENT_API_SERVER
par le chemin d'accès kubeconfig du serveur d'API zonal où est hébergé le cluster Kubernetes. Si vous n'avez pas encore généré de fichier kubeconfig pour le serveur d'API dans votre zone cible, consultez Ressources du serveur d'API de gestion zonale pour en savoir plus.
Ajouter un rejet et un libellé à un pool de nœuds existant
Pour appliquer un taint ou un libellé à un pool de nœuds existant, vous devez appliquer les modifications à chaque nœud existant. Vous ne pouvez pas mettre à jour dynamiquement les configurations de pool de nœuds.
Pour ajouter un rejet et un libellé à un pool de nœuds existant, procédez comme suit :
Répertoriez les nœuds du pool de nœuds dédié :
kubectl get node --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG \ -l baremetal.cluster.gke.io/node-pool=NODE_POOL_NAME
Remplacez les variables suivantes :
KUBERNETES_CLUSTER_KUBECONFIG
: chemin d'accès kubeconfig pour le cluster Kubernetes.NODE_POOL_NAME
: nom de votre pool de nœuds dédié.
Notez l'ID de chaque nœud du pool de nœuds à partir du résultat.
Pour chaque nœud du pool de nœuds, appliquez les taints :
kubectl taint nodes NODE_ID \ TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \ --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
Remplacez les variables suivantes :
NODE_ID
: ID du nœud de calcul dans le pool de nœuds dédié.TAINT_KEY=TAINT_VALUE
: paire clé-valeur associée à unTAINT_EFFECT
de planification. Exemple :workloadType=untrusted
.TAINT_EFFECT
: l'une des valeurs d'effet suivantes :NoSchedule
: les pods qui ne tolèrent pas ce rejet ne sont pas programmés sur le nœud ; les pods existants ne sont pas expulsés du nœud.PreferNoSchedule
: Kubernetes évite de programmer les pods qui ne tolèrent pas ce rejet sur le nœud.NoExecute
: si le pod est déjà en cours d'exécution sur le nœud, il est expulsé de celui-ci. Dans le cas contraire, il n'est pas programmé sur le nœud.
KUBERNETES_CLUSTER_KUBECONFIG
: chemin d'accès kubeconfig pour le cluster Kubernetes.
Pour chaque nœud du pool de nœuds, appliquez les libellés qui correspondent aux sélecteurs que vous définirez dans vos charges de travail de conteneur :
kubectl label NODE_ID \ LABEL_KEY:LABEL_VALUE \ --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
Remplacez les variables suivantes :
NODE_ID
: ID du nœud de calcul dans le pool de nœuds dédié.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.KUBERNETES_CLUSTER_KUBECONFIG
: chemin d'accès kubeconfig pour le cluster Kubernetes.
Ajouter une tolérance et une règle d'affinité de nœuds
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 attribué un libellé au pool de nœuds dédié, vous pouvez également ajouter une règle d'affinité de nœuds pour indiquer à GDC de ne planifier vos charges de travail que sur ce pool de nœuds.
Pour configurer votre charge de travail de conteneur afin qu'elle s'exécute dans le pool de nœuds dédié, procédez comme suit :
Ajoutez les sections suivantes à la section
.spec.template.spec
du fichier manifeste de votre charge de travail de conteneur, comme une ressource personnaliséeDeployment
:# Several lines of code are omitted here. spec: template: spec: tolerations: - key: TAINT_KEY operator: Equal value: TAINT_VALUE effect: TAINT_EFFECT affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: LABEL_KEY operator: In values: - "LABEL_VALUE" # Several lines of code are omitted here.
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é.TAINT_EFFECT
: l'une des valeurs d'effet suivantes :NoSchedule
: les pods qui ne tolèrent pas ce rejet ne sont pas programmés sur le nœud ; les pods existants ne sont pas expulsés du nœud.PreferNoSchedule
: Kubernetes évite de programmer les pods qui ne tolèrent pas ce rejet sur le nœud.NoExecute
: si le pod est déjà en cours d'exécution sur le nœud, il est expulsé de celui-ci. Dans le cas contraire, il n'est pas programmé sur le nœud.
LABEL_KEY
: clé du 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é.
Par exemple, la ressource
Deployment
suivante ajoute une tolérance au rejetworkloadType=untrusted:NoExecute
et une règle d'affinité de nœud pour le libellé de nœudworkloadType=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: workloadType operator: Equal value: untrusted effect: NoExecute affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: workloadType operator: In values: - "untrusted" containers: - name: my-app image: harbor-1.org-1.zone1.google.gdc.test/harborproject/my-app ports: - containerPort: 80 imagePullSecrets: - name: SECRET
Mettez à jour la charge de travail de votre conteneur :
kubectl apply -f deployment.yaml -n NAMESPACE \ --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
Remplacez les variables suivantes :
NAMESPACE
: espace de noms du projet de votre charge de travail de conteneur.KUBERNETES_CLUSTER_KUBECONFIG
: chemin d'accès kubeconfig pour le cluster Kubernetes.
GDC 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
Vérifiez que les pods que vous avez désignés s'exécutent sur le pool de nœuds libellé.
Répertoriez les pods dans l'espace de noms donné :
kubectl get pods -o=wide -n NAMESPACE \ --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
Remplacez les variables suivantes :
NAMESPACE
: espace de noms du projet de votre charge de travail de conteneur.KUBERNETES_CLUSTER_KUBECONFIG
: chemin d'accès kubeconfig pour le cluster Kubernetes.
La sortie ressemble à ceci :
pod/kube-abc-12tyuj pod/kube-abc-39oplef pod/kube-abc-95rzkap
Vérifiez que vos charges de travail s'exécutent dans le pool de nœuds dédié.
Étapes suivantes
- Charges de travail de conteneur dans GDC
- Déployer une application de conteneur à haute disponibilité
- Charges de travail Kubernetes pour la haute disponibilité