URL: https://www.progressiverobot.com/recommended-steps-to-secure-a-cloud-provider-kubernetes-cluster-fr/

*L'auteur a choisi Open Sourcing Mental Illness pour recevoir un don dans le cadre du programme Write for DOnations.*

Introduction

Kubernetes, la plateforme open-source d'orchestration de conteneurs, devient progressivement la solution privilégiée pour l'automatisation, la mise à l'échelle et la gestion des clusters à haute disponibilité. En raison de sa popularité croissante, la sécurité de Kubernetes est devenue de plus en plus pertinente.

Compte tenu des pièces mobiles impliquées dans Kubernetes et de la variété des scénarios de déploiement, la sécurisation de Kubernetes peut parfois être complexe. Pour cette raison, l'objectif de cet article est de fournir une base de sécurité solide pour un cluster Kubernetes (DOKS). Veuillez noter que ce tutoriel couvre les mesures de sécurité de base pour Kubernetes, et se veut un point de départ plutôt qu'un guide exhaustif. Pour les étapes supplémentaires, voir la documentation officielle de Kubernetes.

Dans ce guide, vous prendrez les mesures de base pour sécuriser votre cluster Kubernetes the cloud provider. Vous devrez configurer une authentification locale sécurisée avec des certificats TLS/SSL, accorder des autorisations aux utilisateurs locaux avec des contrôles d'accès basés sur les rôles (RBAC), accorder des autorisations aux applications Kubernetes et aux déploiements avec des comptes de service, et définir des limites de ressources avec les contrôleurs d'admission ResourceQuota et LimitRange.

Conditions préalables

pour illustration for: Conditions préalables

Pour pouvoir compléter ce tutoriel, vous aurez besoin de :

  • Un cluster géré par Kubernetes (DOKS) avec 3 noeuds standard configurés avec au moins 2 Go de RAM et 1 vCPU chacun. Pour des instructions détaillées sur la façon de créer un cluster DOKS, lisez notre guide de démarrage rapide Kubernetes. Ce tutoriel utilise la version 1.16.2-do.1 de DOKS.
  • L'interface de ligne de commande kubectl installée sur votre machine locale. Vous pouvez en savoir plus sur l'installation et la configuration de kubectl dans sa documentation officielle. Ce tutoriel utilisera la version 1.17.0-00 de kubectl.
  • L'outil officiel de la ligne de commande the cloud provider, doctl. Pour savoir comment l'installer, voir la page doctl GitHub. Ce tutoriel utilisera la version 1.36.0 de doctl.

Étape 1 - Activation de l'authentification des utilisateurs à distance

Après avoir rempli les conditions préalables, vous vous retrouverez avec un super-utilisateur Kubernetes qui s'authentifiera grâce à un jeton du porteur the cloud provider prédéfini. Toutefois, le partage de ces identifiants n'est pas une bonne pratique de sécurité, car ce compte peut entraîner des modifications à grande échelle et éventuellement destructrices de votre cluster. Pour limiter cette possibilité, vous pouvez configurer des utilisateurs supplémentaires à authentifier à partir de leurs clients locaux respectifs.

Dans cette section, vous allez authentifier les nouveaux utilisateurs du cluster DOKS distant à partir de clients locaux en utilisant des certificats SSL/TLS sécurisés. Il s'agira d'un processus en trois étapes : Tout d'abord, vous allez créer des demandes de signature de certificats (CSR)) pour chaque utilisateur, puis vous approuverez ces certificats directement dans le cluster par l'intermédiaire de kubectl. Enfin, vous construirez pour chaque utilisateur un fichier kubeconfig avec les certificats appropriés. Pour plus d'informations sur les méthodes d'authentification supplémentaires prises en charge par Kubernetes, consultez la documentation sur l'authentification Kubernetes.

Création de demandes de signature de certificats pour les nouveaux utilisateurs

Avant de commencer, vérifiez la connexion au cluster DOKS depuis la machine locale configurée lors des prérequis :

				
					
kubectl cluster-info

				
			

En fonction de votre configuration, la sortie sera similaire à celle-ci :

				
					
[secondary_label Output]

Kubernetes master is running at https://www.progressiverobot.com/

CoreDNS is running at https://www.cloudflare.com/learning/dns/what-is-dns/



To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

				
			

Cela signifie que vous êtes connecté au cluster DOKS.

Ensuite, créez un dossier local pour les certificats des clients. Pour les besoins de ce guide,~/certs seront utilisés pour stocker tous les certificats :

				
					
mkdir ~/<^>certs<^>

				
			

Dans ce tutoriel, nous allons autoriser un nouvel utilisateur appelé sammy à accéder au cluster.  N'hésitez pas à modifier cela pour un utilisateur de votre choix. En utilisant la bibliothèque SSL et TLS OpenSSL, générez une nouvelle clé privée pour votre utilisateur en utilisant la commande suivante :

				
					
openssl genrsa -out ~/<^>certs<^>/<^>sammy<^>.key 4096

				
			

Le drapeau -out rendra le fichier de sortie ~/<^>certs<^>/<^>sammy<^>.key, et 4096 définit la clé comme 4096-bit. Pour plus d'informations sur OpenSSL, consultez notre guide Les essentiels d'OpenSSL.

Maintenant, créez un fichier de configuration de la demande de signature de certificat. Ouvrez le fichier suivant avec un éditeur de texte (pour ce tutoriel, nous utiliserons nano) :

				
					
nano ~/&lt;^&gt;certs/sammy.csr.cnf&lt;^&gt;

				
			

Ajoutez le contenu suivant dans le fichier <^>sammy.csr.cnf<^> pour spécifier dans le sujet le nom d'utilisateur souhaité comme nom commun (CN), et le groupe comme organisation (O) :

				
					
[label ~/certs/sammy.csr.cnf]

[ req ]

default_bits = 2048

prompt = no

default_md = sha256

distinguished_name = dn

[ dn ]

CN = &lt;^&gt;sammy&lt;^&gt;

O = &lt;^&gt;developers&lt;^&gt;

[ v3_ext ]

authorityKeyIdentifier=keyid,issuer:always

basicConstraints=CA:FALSE

keyUsage=keyEncipherment,dataEncipherment

extendedKeyUsage=serverAuth,clientAuth

				
			

Le fichier de configuration de la demande de signature de certificat contient toutes les informations nécessaires, l'identité de l'utilisateur et les paramètres d'utilisation appropriés pour l'utilisateur. Le dernier argument extendedKeyUsage=serverAuth,clientAuth permettra aux utilisateurs d'authentifier leurs clients locaux avec le cluster DOKS en utilisant le certificat une fois qu'il sera signé.

Ensuite, créez la demande de signature du certificat sammy :

				
					
openssl req -config ~/&lt;^&gt;certs&lt;^&gt;/&lt;^&gt;sammy&lt;^&gt;.csr.cnf -new -key ~/&lt;^&gt;certs&lt;^&gt;/&lt;^&gt;sammy&lt;^&gt;.key -nodes -out ~/&lt;^&gt;certs&lt;^&gt;/&lt;^&gt;sammy&lt;^&gt;.csr

				
			

Le paramètre -config vous permet de spécifier le fichier de configuration pour le CSR, et -new signale que vous créez une nouvelle CSR pour la clé spécifiée par -key.

Vous pouvez vérifier votre demande de signature de certificat en exécutant la commande suivante :

				
					
openssl req -in ~/&lt;^&gt;certs&lt;^&gt;/&lt;^&gt;sammy&lt;^&gt;.csr -noout -text

				
			

Ici vous passez dans le CSR avec -in et utilisez -text pour imprimer la demande de certificat en texte.

La sortie montrera la demande de certificat, dont le début ressemblera à ceci :

				
					
[secondary_label Output]

Certificate Request:

 Data:

 Version: 1 (0x0)

 Subject: CN = &lt;^&gt;sammy&lt;^&gt;, O = &lt;^&gt;developers&lt;^&gt;

 Subject Public Key Info:

 Public Key Algorithm: rsaEncryption

 RSA Public-Key: (4096 bit)

...

				
			

Répétez la même procédure pour créer des RSC pour tout utilisateur supplémentaire. Une fois que vous avez enregistré toutes les demandes de signature de certificats dans le dossier ~/certs de l'administrateur, passez à l'étape suivante pour les approuver.

Gérer les demandes de signature de certificats avec l'API Kubernetes

Vous pouvez soit approuver soit refuser les certificats TLS délivrés à l'API Kubernetes en utilisant l'outil de ligne de commande kubectl. Cela vous donne la possibilité de vous assurer que l'accès demandé est approprié pour l'utilisateur donné. Dans cette section, vous enverrez la demande de certificat pour sammy et l'approuverez.

Pour envoyer une CSR au cluster DOKS, utilisez la commande suivante cluster

				
					
cat &lt;&lt;EOF | kubectl apply -f -

apiVersion: certificates.k8s.io/v1beta1

kind: CertificateSigningRequest

metadata:

 name: &lt;^&gt;sammy-authentication&lt;^&gt;

spec:

 groups:

 - system:authenticated

 request: $(cat ~/&lt;^&gt;certs&lt;^&gt;/&lt;^&gt;sammy&lt;^&gt;.csr | base64 | tr -d '\n')

 usages:

 - digital signature

 - key encipherment

 - server auth

 - client auth

EOF

				
			

En utilisant un *document* Bash here, cette commande utilise cat pour transmettre la demande de certificat à kubectl apply.

Examinons de plus près la demande de certificat :

  • nom : <^>sammy-authentication<^> crée un identificateur de métadonnées, dans ce cas appelé sammy-authentication.
  • request : $(cat ~/<^>certs<^>/<^>sammy<^>.csr | base64 | tr -d '\n') envoie la demande de signature du certificat sammy.csr au cluster encodé en Base64.
  • L'autorisation du serveur et l'autorisation du client précisent l'utilisation prévue du certificat. Dans ce cas, l'objectif est l'authentification de l'utilisateur.

Le résultat sera similaire à celui-ci :

				
					
[secondary_label Output]

certificatesigningrequest.certificates.k8s.io/&lt;^&gt;sammy-authentication&lt;^&gt; created

				
			

Vous pouvez vérifier le statut de la demande de signature de certificat en utilisant la commande :

				
					
kubectl get csr

				
			

Selon la configuration de votre cluster, le résultat sera similaire à celui-ci :

				
					
[secondary_label Output]

NAME AGE REQUESTOR CONDITION

&lt;^&gt;sammy-authentication&lt;^&gt; 37s &lt;^&gt;your_DO_email&lt;^&gt; Pending

				
			

Ensuite, approuvez la CSR en utilisant la commande CSR

				
					
kubectl certificate approve &lt;^&gt;sammy-authentication&lt;^&gt;

				
			

Vous recevrez un message confirmant l'opération :

				
					
[secondary_label Output]

certificatesigningrequest.certificates.k8s.io/&lt;^&gt;sammy-authentication&lt;^&gt; approved

				
			

Remarque : En tant qu'administrateur, vous pouvez également refuser une CSR en utilisant la commande kubectl certificate deny <^>sammy-authentication<^>. Pour plus d'informations sur la gestion des certificats TLS, veuillez lire la documentation officielle de Kubernetes.

Maintenant que la RSE est approuvée, vous pouvez la télécharger sur la machine locale en exécutant :

				
					
kubectl get csr &lt;^&gt;sammy-authentication&lt;^&gt; -o jsonpath='{.status.certificate}' | base64 --decode &gt; ~/&lt;^&gt;certs&lt;^&gt;/&lt;^&gt;sammy&lt;^&gt;.crt

				
			

Cette commande décode le certificat Base64 pour une utilisation correcte par kubectl, puis l'enregistre sous la forme ~/<^>certs<^>/<^>sammy<^>.crt.

Avec le certificat signé sammy en main, vous pouvez maintenant construire le fichier kubeconfig de l'utilisateur.

Construire des utilisateurs distants Kubeconfig

Ensuite, vous allez créer un fichier kubeconfig spécifique pour l'utilisateur sammy. Cela vous permettra de mieux contrôler l'accès de l'utilisateur à votre cluster.

La première étape de la construction d'un nouveau kubeconfig consiste à faire une copie du fichier kubeconfig actuel. Pour les besoins de ce guide, le nouveau fichier kubeconfig s'appellera<^>config-sammy<^> :

				
					
cp ~/.kube/config ~/.kube/&lt;^&gt;config-sammy&lt;^&gt;

				
			

Ensuite, modifiez le nouveau fichier :

				
					
nano ~/.kube/&lt;^&gt;config-sammy&lt;^&gt;

				
			

Conservez les huit premières lignes de ce fichier, car elles contiennent les informations nécessaires à la connexion SSL/TLS avec le cluster. Ensuite, en partant du paramètre utilisateur, remplacez le texte par les lignes surlignées suivantes afin que le fichier ressemble à ce qui suit :

				
					
[label config-sammy]

apiVersion: v1

clusters:

- cluster:

 certificate-authority-data: certificate_data

 name: do-nyc1-do-cluster

contexts:

- context:

 cluster: do-nyc1-do-cluster

 user: &lt;^&gt;sammy&lt;^&gt;

 name: do-nyc1-do-cluster

current-context: do-nyc1-do-cluster

kind: Config

preferences: {}

users:

- name: &lt;^&gt;sammy&lt;^&gt;

 user:

 &lt;^&gt;client-certificate: /home/your_local_user/certs/sammy.crt&lt;^&gt;

 &lt;^&gt;client-key: /home/your_local_user/certs/sammy.key&lt;^&gt;

				
			

Remarque : pour le certificat-client et la clé-client, utilisez le chemin d'accès absolu à l'emplacement du certificat correspondant. Dans le cas contraire, kubectl produira une erreur.

Enregistrez et quittez le fichier.

Vous pouvez tester la connexion du nouvel utilisateur en utilisant kubectl cluster-info :

				
					
kubectl --kubeconfig=/home/&lt;^&gt;your_local_user&lt;^&gt;/.kube/&lt;^&gt;config-sammy&lt;^&gt; cluster-info

				
			

Vous verrez une erreur similaire à celle-ci :

				
					
[secondary_label Output]

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Error from server (Forbidden): services is forbidden: User "&lt;^&gt;sammy&lt;^&gt;" cannot list resource "services" in API group "" in the namespace "kube-system"

				
			

Cette erreur est attendue car l'utilisateur sammy n'a pas encore l'autorisation de lister une ressource sur le cluster. L'octroi d'autorisations aux utilisateurs sera abordé dans la prochaine étape. Pour l'instant, le résultat confirme que la connexion SSL/TLS a réussi et que l'API Kubernetes a accepté les références d'authentification sammy.

Étape 2 - Autorisation des utilisateurs par le biais du contrôle d'accès basé sur les rôles (RBAC)

Une fois qu'un utilisateur est authentifié, l'API détermine ses autorisations en utilisant le modèle de contrôle d'accès basé sur les rôles (RBAC) intégré à Kubernetes. Le RBAC est une méthode efficace pour restreindre les droits des utilisateurs en fonction du rôle qui leur est attribué. Du point de vue de la sécurité, le RBAC permet de définir des autorisations précises pour limiter l'accès des utilisateurs à des données sensibles ou l'exécution de commandes au niveau du super-utilisateur. Pour des informations plus détaillées sur les rôles des utilisateurs, veuillez consulter la documentation relative à Kubernetes RBAC.

Dans cette étape, vous utiliserez kubectl pour attribuer le rôle d'édition prédéfini à l'utilisateur sammy dans l'espace de noms par défaut. Dans un environnement de production, vous souhaiterez peut-être utiliser des rôles personnalisés et/ou des liens de rôles personnalisés.

Accorder des autorisations

Dans Kubernetes, accorder des autorisations signifie attribuer le rôle souhaité à un utilisateur. Attribuez des droits d'édition à l'utilisateur sammy dans l'espace de noms par défaut en utilisant la commande suivante :

				
					
kubectl create rolebinding &lt;^&gt;sammy-edit-role&lt;^&gt; --clusterrole=edit --user=&lt;^&gt;sammy&lt;^&gt; --namespace=default

				
			

Cela donnera un résultat similaire à ce qui suit :

				
					
[secondary_label Output]

rolebinding.rbac.authorization.k8s.io/&lt;^&gt;sammy-edit-role&lt;^&gt; created

				
			

Analysons cette commande plus en détail :

  • créer une liaison de rôle <^>sammy-edit-role<^> crée une nouvelle liaison de rôle, dans ce cas appelée <^>sammy-edit-role<^>.
  • --clusterrole=edit attribue le rôle prédéfini d'édition à une portée globale (rôle de cluster).
  • --user=<^>sammy<^> spécifie à quel utilisateur lier le rôle.
  • --namespace=default accorde à l'utilisateur des autorisations de rôle dans l'espace de noms spécifié, dans ce cas par défaut.

Ensuite, vérifiez les autorisations des utilisateurs en listant les pods dans l'espace de noms par défaut. Vous pouvez savoir si l'autorisation RBAC fonctionne comme prévu si aucune erreur n'est affichée.

				
					
kubectl --kubeconfig=/home/&lt;^&gt;your_local_user&lt;^&gt;/.kube/&lt;^&gt;config-sammy&lt;^&gt; auth can-i get pods

				
			

Vous aurez le résultat suivant :

				
					
[secondary_label Output]

yes

				
			

Maintenant que vous avez attribué des autorisations à sammy, vous pouvez vous entraîner à les révoquer dans la section suivante.

Révoquer les autorisations

La révocation des autorisations dans Kubernetes se fait en supprimant le rôle obligatoire de l'utilisateur.

Pour ce tutoriel, supprimez le rôle d'édition de l'utilisateur sammy en exécutant la commande suivante :

				
					
kubectl delete rolebinding &lt;^&gt;sammy-edit-role&lt;^&gt;

				
			

Vous aurez le résultat suivant :

				
					
[secondary_label Output]

rolebinding.rbac.authorization.k8s.io "&lt;^&gt;sammy-edit-role&lt;^&gt;" deleted

				
			

Vérifiez si les autorisations des utilisateurs ont été révoquées comme prévu en listant les pods d'espace de noms par défaut :

				
					
kubectl --kubeconfig=/home/&lt;^&gt;localuser&lt;^&gt;/.kube/&lt;^&gt;config-sammy&lt;^&gt; --namespace=default get pods

				
			

Vous recevrez l'erreur suivante :

				
					
[secondary_label Output]

Error from server (Forbidden): pods is forbidden: User "&lt;^&gt;sammy&lt;^&gt;" cannot list resource "pods" in API group "" in the namespace "default"

				
			

Cela montre que l'autorisation a été révoquée.

Du point de vue de la sécurité, le modèle d'autorisation Kubernetes donne aux administrateurs de clusters la flexibilité nécessaire pour modifier les droits des utilisateurs à la demande. De plus, le contrôle d'accès basé sur les rôles n'est pas limité à un utilisateur physique ; vous pouvez également accorder et retirer des autorisations aux services de cluster, comme vous l'apprendrez dans la section suivante.

Pour plus d'informations sur l'autorisation RBAC et sur la manière de créer des rôles personnalisés, veuillez lire la documentation officielle.

Étape 3 - Gestion des autorisations de demande à l'aide de comptes de service

Comme mentionné dans la section précédente, les mécanismes d'autorisation du RBAC s'étendent au-delà des utilisateurs humains. Les utilisateurs de clusters non humains, tels que les applications, services et processus s'exécutant à l'intérieur des pods, s'authentifient auprès du serveur API en utilisant ce que Kubernetes appelle des *comptes de service*. Lorsqu'un pod est créé dans un espace de noms, vous pouvez soit le laisser utiliser le compte de service par défaut, soit définir un compte de service de votre choix. La possibilité d'affecter des SAS individuels aux demandes et aux processus donne aux administrateurs la liberté d'accorder ou de révoquer des autorisations selon les besoins. En outre, l'affectation de SAS spécifiques à des applications critiques pour la production est considérée comme une meilleure pratique de sécurité. Comme les comptes de service sont utilisés pour l'authentification, et donc pour les contrôles d'autorisation RBAC, les administrateurs de clusters pourraient contenir les menaces de sécurité en modifiant les droits d'accès aux comptes de service et en isolant le processus incriminé.

Pour démontrer les comptes de service, ce tutoriel utilisera un serveur web Nginx comme exemple d'application.

Avant d'attribuer une SA particulière à votre application, vous devez créer la SA. Créez un nouveau compte de service appelé <^>nginx-sa<^> dans l'espace de noms par défaut :

				
					
kubectl create sa &lt;^&gt;nginx-sa&lt;^&gt;

				
			

Vous obtiendrez :

				
					
[secondary_label Output]

serviceaccount/&lt;^&gt;nginx-sa&lt;^&gt; created

				
			

Vérifiez que le compte de service a été créé en exécutant ce qui suit :

				
					
kubectl get sa

				
			

Vous obtiendrez ainsi une liste de vos comptes de service :

				
					
[secondary_label Output]

NAME SECRETS AGE

default 1 22h

&lt;^&gt;nginx-sa&lt;^&gt; 1 80s

				
			

Vous allez maintenant attribuer un rôle au compte de service <^>nginx-sa<^>. Pour cet exemple, accordez <^>nginx-sa<^> les mêmes permissions que l'utilisateur sammy :

				
					
kubectl create rolebinding &lt;^&gt;nginx-sa-edit&lt;^&gt; \

 --clusterrole=edit \

 --serviceaccount=default:&lt;^&gt;nginx-sa&lt;^&gt; \

 --namespace=default

				
			

L'exécution de cette opération donnera les résultats suivants :

				
					
[secondary_label Output]

rolebinding.rbac.authorization.k8s.io/&lt;^&gt;nginx-sa-edit&lt;^&gt; created

				
			

Cette commande utilise le même format que pour l'utilisateur sammy, à l'exception du drapeau --serviceaccount=default:nginx-sa, où vous attribuez le compte de service <^>nginx-sa<^> dans l'espace de noms par défaut.

Vérifiez que la liaison de rôle a réussi à l'aide de cette commande :

				
					
kubectl get rolebinding

				
			

Cela donnera le résultat suivant :

				
					
[secondary_label Output]

NAME AGE

&lt;^&gt;nginx-sa-edit&lt;^&gt; 23s

				
			

Une fois que vous avez confirmé que le rôle obligatoire pour le compte de service a été configuré avec succès, vous pouvez affecter le compte de service à une application. L'attribution d'un compte de service particulier à une application vous permettra de gérer ses droits d'accès en temps réel et donc de renforcer la sécurité du cluster.

Pour les besoins de ce tutoriel, un pod nginx servira d'exemple d'application. Créez le nouveau pod et spécifiez le compte de service <^>nginx-sa<^> avec la commande suivante :

				
					
kubectl run nginx --image=nginx --port 80 --serviceaccount="&lt;^&gt;nginx-sa&lt;^&gt;"

				
			

La première partie de la commande crée un nouveau pod faisant tourner un serveur web nginx sur le port :80, et la dernière partie --serviceaccount="<^>nginx-sa<^>" indique que ce pod doit utiliser le compte de service <^>nginx-sa<^> et non le SA par défaut.

Vous obtiendrez ainsi un résultat similaire à celui qui suit :

				
					
[secondary_label Output]

deployment.apps/nginx created

				
			

Vérifiez que la nouvelle demande utilise le compte de service en utilisant kubectl describe :

				
					
kubectl describe deployment nginx

				
			

Cela donnera lieu à une longue description des paramètres de déploiement. Sous la section Modèle de Pod, vous verrez un résultat similaire à celui-ci :

				
					
[secondary_label Output]

...

Pod Template:

 Labels: run=nginx

 Service Account: &lt;^&gt;nginx-sa&lt;^&gt;

...

				
			

Dans cette section, vous avez créé le compte de service <^>nginx-sa<^> dans l'espace de noms par défaut et l'avez attribué au serveur web nginx. Vous pouvez désormais contrôler les autorisations de nginx en temps réel en modifiant son rôle si besoin est. Vous pouvez également regrouper les demandes en attribuant le même compte de service à chacune d'entre elles, puis apporter des modifications en masse aux autorisations. Enfin, vous pourriez isoler les applications critiques en leur attribuant un SA unique.

En résumé, l'idée qui sous-tend l'attribution des rôles à vos applications/déploiements est d'affiner les autorisations. Dans les environnements de production du monde réel, vous pouvez avoir plusieurs déploiements nécessitant différentes autorisations allant de la lecture seule à des privilèges administratifs complets. L'utilisation du RBAC vous donne la possibilité de restreindre l'accès au cluster selon vos besoins.

Ensuite, vous mettrez en place des contrôleurs d'admission pour contrôler les ressources et se prémunir contre les attaques de privation de ressources.

Étape 4 - Mise en place des contrôleurs d'admission

Les contrôleurs d'admission Kubernetes sont des plug-ins optionnels qui sont compilés dans le binaire kube-apiserver pour élargir les options de sécurité. Les contrôleurs d'admission interceptent les demandes après qu'elles aient passé la phase d'authentification et d'autorisation. Une fois que la demande est interceptée, les contrôleurs d'admission exécutent le code spécifié juste avant que la demande ne soit appliquée.

Si le résultat d'un contrôle d'authentification ou d'autorisation est un booléen qui autorise ou refuse la demande, les contrôleurs d'admission peuvent être beaucoup plus divers. Les contrôleurs d'admission peuvent valider les demandes de la même manière que l'authentification, mais ils peuvent également *faire muter* ou modifier les demandes et modifier les objets avant de les admettre.

Dans cette étape, vous utiliserez les contrôleurs d'admission ResourceQuota et LimitRange pour protéger votre cluster en faisant muter les demandes qui pourraient contribuer à une pénurie de ressources ou à une attaque par déni de service. Le contrôleur d'admission ResourceQuota permet aux administrateurs de restreindre les ressources informatiques, les ressources de stockage et la quantité de tout objet dans un espace de noms, tandis que le contrôleur d'admission LimitRange limitera le nombre de ressources utilisées par les conteneurs. En utilisant ces deux contrôleurs d'admission ensemble, vous protégerez votre cluster contre les attaques qui rendent vos ressources indisponibles.

Pour montrer comment fonctionne ResourceQuota, vous allez mettre en place quelques restrictions dans l'espace de noms par défaut. Commencez par créer un nouveau fichier objet ResourceQuota :

				
					
nano &lt;^&gt;resource-quota-default&lt;^&gt;.yaml

				
			

Ajoutez la définition d'objet suivante pour définir les contraintes de consommation de ressources dans l'espace de noms par défaut. Vous pouvez ajuster les valeurs selon les besoins en fonction des ressources physiques de vos nœuds :

				
					
[label resource-quota-default.yaml]

apiVersion: v1

kind: ResourceQuota

metadata:

 name: &lt;^&gt;resource-quota-default&lt;^&gt;

spec:

 hard:

 pods: "&lt;^&gt;2&lt;^&gt;"

 requests.cpu: "&lt;^&gt;500m&lt;^&gt;"

 requests.memory: &lt;^&gt;1Gi&lt;^&gt;

 limits.cpu: "&lt;^&gt;1000m&lt;^&gt;"

 limits.memory: &lt;^&gt;2Gi&lt;^&gt;

 configmaps: "&lt;^&gt;5&lt;^&gt;"

 persistentvolumeclaims: "&lt;^&gt;2&lt;^&gt;"

 replicationcontrollers: "&lt;^&gt;10&lt;^&gt;"

 secrets: "&lt;^&gt;3&lt;^&gt;"

 services: "&lt;^&gt;4&lt;^&gt;"

 services.loadbalancers: "&lt;^&gt;2&lt;^&gt;"

				
			

Cette définition utilise le mot-clé hard pour fixer des contraintes strictes, telles que le nombre maximum de pods, les configmaps, les PersistentVolumeClaims, les ReplicationController, les secrets, les services et les loadbalancers. Cela impose également des contraintes en matière de ressources informatiques, par exemple :

  • requests.cpu, qui fixe la valeur CPU maximale des requêtes en *milliCPU*, soit un millième d'un noyau CPU.
  • requests.memory, qui fixe la valeur maximale de la mémoire des requêtes en octets.
  • limits.cpu, qui fixe la valeur CPU maximale des limites en milliCPU.
  • limits.memory, qui fixe la valeur maximale de la mémoire des limites en octets.

Enregistrez et quittez le fichier.

Maintenant, créez l'objet dans l'espace de noms en exécutant la commande suivante :

				
					
kubectl create -f &lt;^&gt;resource-quota-default.yaml&lt;^&gt; --namespace=default

				
			

Il en résultera ce qui suit :

				
					
[secondary_label Output]

resourcequota/&lt;^&gt;resource-quota-default&lt;^&gt; created

				
			

Notez que vous utilisez le drapeau -f pour indiquer à Kubernetes l'emplacement du fichier ResourceQuota et le drapeau --namespace pour préciser quel espace de noms sera mis à jour.

Une fois l'objet créé, votre ResourceQuota sera actif. Vous pouvez vérifier les quotas d'espace de noms par défaut avec le quota de description :

				
					
kubectl describe quota --namespace=default

				
			

La sortie sera similaire à celle-ci, avec les limites strictes que vous avez définies dans le fichier <^>resource-quota-default<^>.yaml :

				
					
[secondary_label Output]

Name: &lt;^&gt;resource-quota-default&lt;^&gt;

Namespace: default

Resource Used Hard

-------- ---- ----

configmaps 0 &lt;^&gt;5&lt;^&gt;

limits.cpu 0 &lt;^&gt;1&lt;^&gt;

limits.memory 0 &lt;^&gt;2Gi&lt;^&gt;

persistentvolumeclaims 0 &lt;^&gt;2&lt;^&gt;

pods 1 &lt;^&gt;2&lt;^&gt;

replicationcontrollers 0 &lt;^&gt;10&lt;^&gt;

requests.cpu 0 &lt;^&gt;500m&lt;^&gt;

requests.memory 0 &lt;^&gt;1Gi&lt;^&gt;

secrets 2 &lt;^&gt;3&lt;^&gt;

services 1 &lt;^&gt;4&lt;^&gt;

services.loadbalancers 0 &lt;^&gt;2&lt;^&gt;

				
			

Les quotas de ressources sont exprimés en unités absolues, de sorte que l'ajout de nœuds supplémentaires n'augmentera pas automatiquement les valeurs définies ici. Si d'autres nœuds sont ajoutés, vous devrez modifier manuellement les valeurs ici pour proportionner les ressources. Les quotas de ressources peuvent être modifiés aussi souvent que nécessaire, mais ils ne peuvent être supprimés que si l'espace de noms entier est supprimé.

Si vous devez modifier un quota de ressources particulier, mettez à jour le fichier .yaml correspondant et appliquez les modifications à l'aide de la commande suivante :

				
					
kubectl apply -f &lt;^&gt;resource-quota-default&lt;^&gt;.yaml --namespace=default

				
			

Pour plus d'informations sur le ResourceQuota Admission Controller, reportez-vous à la documentation officielle.

Maintenant que votre quota de ressources est configuré, vous allez passer à la configuration du LimitRange Admission Controller. De la même manière que le ResourceQuota fait respecter les limites des espaces de noms, le LimitRange fait respecter les limites déclarées en validant et en faisant muter les conteneurs.

De la même manière qu'auparavant, commencez par créer le fichier objet :

				
					
nano &lt;^&gt;limit-range-default&lt;^&gt;.yaml

				
			

Maintenant, vous pouvez utiliser l'objet LimitRange pour restreindre l'utilisation des ressources selon les besoins. Ajoutez le contenu suivant comme exemple d'un cas d'utilisation typique :

				
					
[label limit-ranges-default.yaml]

apiVersion: v1

kind: LimitRange

metadata:

 name: &lt;^&gt;limit-range-default&lt;^&gt;

spec:

 limits:

 - max:

 cpu: "&lt;^&gt;400m&lt;^&gt;"

 memory: "&lt;^&gt;1Gi&lt;^&gt;"

 min:

 cpu: "&lt;^&gt;100m&lt;^&gt;"

 memory: "&lt;^&gt;100Mi&lt;^&gt;"

 default:

 cpu: "&lt;^&gt;250m&lt;^&gt;"

 memory: "&lt;^&gt;800Mi&lt;^&gt;"

 defaultRequest:

 cpu: "&lt;^&gt;150m&lt;^&gt;"

 memory: "&lt;^&gt;256Mi&lt;^&gt;"

 type: Container

				
			

Les valeurs d'échantillon utilisées dans <^>limit-ranges-default<^>.yaml limitent la mémoire du conteneur à un maximum de 1Gi et limitent l'utilisation du CPU à un maximum de 400m, ce qui est une métrique de Kubernetes équivalente à 400 milliCPU, ce qui signifie que le conteneur est limité à utiliser presque la moitié de son cœur.

Ensuite, déployez l'objet sur le serveur API à l'aide de la commande suivante :

				
					
kubectl create -f &lt;^&gt;limit-range-default&lt;^&gt;.yaml --namespace=default

				
			

Cela donnera le résultat suivant :

				
					
[secondary_label Output]

limitrange/&lt;^&gt;limit-range-default&lt;^&gt; created

				
			

Vous pouvez maintenant vérifier les nouvelles limites avec la commande suivante :

				
					
kubectl describe limits --namespace=default

				
			

Votre résultat sera similaire à celui-ci :

				
					
[secondary_label Output]

Name: &lt;^&gt;limit-range-default&lt;^&gt;

Namespace: default

Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio

---- -------- --- --- --------------- ------------- -----------------------

Container cpu &lt;^&gt;100&lt;^&gt;m &lt;^&gt;400&lt;^&gt;m &lt;^&gt;150&lt;^&gt;m &lt;^&gt;250&lt;^&gt;m -

Container memory &lt;^&gt;100&lt;^&gt;Mi &lt;^&gt;1&lt;^&gt;Gi &lt;^&gt;256&lt;^&gt;Mi &lt;^&gt;800&lt;^&gt;Mi -

				
			

Pour voir LimitRanger en action, déployez un conteneur nginx standard avec la commande suivante :

				
					
kubectl run nginx --image=nginx --port=80 --restart=Never

				
			

Cela donnera le résultat suivant :

				
					
[secondary_label Output]

pod/nginx created

				
			

Vérifiez comment le contrôleur d'admission a fait muter le conteneur en exécutant la commande suivante :

				
					
kubectl get pod nginx -o yaml

				
			

Cela donnera de nombreuses lignes de résultats. Consultez la section sur les spécifications des conteneurs pour trouver les limites de ressources spécifiées dans le LimitRange Admission Controller :

				
					
[secondary_label Output]

...

spec:

 containers:

 - image: nginx

 imagePullPolicy: IfNotPresent

 name: nginx

 ports:

 - containerPort: 80

 protocol: TCP

 &lt;^&gt;resources:&lt;^&gt;

 &lt;^&gt;limits:&lt;^&gt;

 &lt;^&gt;cpu: 250m&lt;^&gt;

 &lt;^&gt;memory: 800Mi&lt;^&gt;

 &lt;^&gt;requests:&lt;^&gt;

 &lt;^&gt;cpu: 150m&lt;^&gt;

 &lt;^&gt;memory: 256Mi&lt;^&gt;

...

				
			

Ce serait la même chose que si vous déclariez manuellement les ressources et les demandes dans la spécification du conteneur.

Dans cette étape, vous avez utilisé les contrôleurs d'admission ResourceQuota et LimitRange pour vous protéger contre les attaques malveillantes envers les ressources de votre cluster. Pour plus d'informations sur le contrôleur d'admission LimitRange, consultez la documentation officielle.

Conclusion

Tout au long de ce guide, vous avez configuré un modèle de sécurité Kubernetes de base. Cela a permis d'établir l'authentification et l'autorisation des utilisateurs, les privilèges des applications et la protection des ressources des clusters. En combinant toutes les suggestions couvertes dans cet article, vous aurez une base solide pour le déploiement du cluster de production Kubernetes. A partir de là, vous pouvez commencer à renforcer les différents aspects de votre cluster en fonction de votre scénario.

Si vous souhaitez en savoir plus sur Kubernetes, consultez notre page de ressources Kubernetes, ou suivez notre cours autogéré Kubernetes pour les développeurs Full-Stack.