Un cluster Kubernetes est composé d'un plan de contrôle et d'un ensemble de machines de travail, appelées nœuds, qui exécutent des applications conteneurisées.
Chaque cluster a besoin d'au moins un nœud de travail pour exécuter des Pods.
Les nœuds de travail hébergent les Pods qui sont les composants de la charge de travail de l'application.
Le plan de contrôle gère les nœuds de travail et les Pods du cluster. Dans les environnements de production,
le plan de contrôle s'exécute généralement sur plusieurs ordinateurs et un cluster
exécute généralement plusieurs nœuds, offrant une tolérance aux pannes et une haute disponibilité.
Ce document décrit les différents composants nécessaires pour avoir un cluster Kubernetes complet et fonctionnel.
Composants du plan de contrôle
Les composants du plan de contrôle prennent des décisions globales sur le cluster (par exemple, la planification),
ainsi que la détection et la réponse aux événements du cluster (par exemple, démarrer un nouveau
pod lorsque le champ replicas d'un déploiement
n'est pas satisfait).
Les composants du plan de contrôle peuvent s'exécuter sur n'importe quelle machine du cluster. Cependant, pour simplifier, les scripts d'installation
démarrent généralement tous les composants du plan de contrôle sur la même machine et n'exécutent pas de conteneurs utilisateur sur cette machine.
Consultez Création de clusters hautement disponibles avec kubeadm
pour un exemple de configuration du plan de contrôle s'exécutant sur plusieurs machines.
kube-apiserver
Composant sur le master qui expose l'API Kubernetes. Il s'agit du front-end pour le plan de contrôle Kubernetes.
Il est conçu pour une mise à l'échelle horizontale, ce qui veut dire qu'il met à l'échelle en déployant des instances supplémentaires. Voir Construire des Clusters en Haute Disponibilité.
etcd
Base de données clé-valeur consistante et hautement disponible utilisée comme mémoire de sauvegarde pour toutes les données du cluster.
Si votre cluster Kubernetes utilise etcd comme mémoire de sauvegarde, assurez-vous d'avoir un plan de
back up pour ces données.
Vous pouvez trouver plus d'informations à propos d'etcd dans la documentation officielle.
kube-scheduler
Composant sur le master qui surveille les pods nouvellement créés qui ne sont pas assignés à un nœud et sélectionne un nœud sur lequel ils vont s'exécuter.
Les facteurs pris en compte pour les décisions de planification (scheduling) comprennent les exigences individuelles et collectives en ressources, les contraintes matérielles/logicielles/politiques, les spécifications d'affinité et d'anti-affinité, la localité des données, les interférences entre charges de travail et les dates limites.
Logiquement, chaque contrôleur est un processus à part mais,
pour réduire la complexité, les contrôleurs sont tous compilés dans un seul binaire et s'exécutent dans un seul processus.
Il existe de nombreux types de contrôleurs différents. Voici quelques exemples :
Contrôleur de nœuds : Responsable de la détection et de la réponse lorsque les nœuds tombent en panne.
Contrôleur de tâches : Surveille les objets Job qui représentent des tâches ponctuelles, puis crée des Pods pour exécuter ces tâches jusqu'à leur achèvement.
Contrôleur EndpointSlice : Remplit les objets EndpointSlice (pour établir un lien entre les Services et les Pods).
Contrôleur ServiceAccount : Crée des comptes de service par défaut pour les nouveaux espaces de noms.
Ce qui précède n'est pas une liste exhaustive.
cloud-controller-manager
Le Cloud Controller Manager est une fonctionnalité alpha de la version 1.8. Dans les prochaines versions, il deviendra le moyen privilégié pour l'intégration de Kubernetes à n'importe quel cloud.
Le cloud-controller-manager exécute uniquement des contrôleurs spécifiques à votre fournisseur de cloud.
Si vous exécutez Kubernetes sur vos propres serveurs ou dans un environnement d'apprentissage sur votre
propre PC, le cluster n'a pas de cloud-controller-manager.
Comme pour kube-controller-manager, cloud-controller-manager combine plusieurs boucles de contrôle logiquement
indépendantes en un seul binaire que vous exécutez en tant que processus unique. Vous pouvez mettre à l'échelle
horizontalement (exécuter plusieurs copies) pour améliorer les performances ou pour aider à tolérer les pannes.
Les contrôleurs suivants peuvent avoir des dépendances vis-à-vis du fournisseur de cloud :
Contrôleur de nœuds : Pour vérifier auprès du fournisseur de cloud si un nœud a été
supprimé dans le cloud après avoir cessé de répondre
Contrôleur de routage : Pour configurer les routes dans l'infrastructure cloud sous-jacente
Contrôleur de service : Pour créer, mettre à jour et supprimer des équilibreurs de charge du fournisseur de cloud
Composants du nœud
Les composants du nœud s'exécutent sur chaque nœud, maintenant les Pods en cours d'exécution et fournissant l'environnement d'exécution Kubernetes.
kubelet
Un agent qui s'exécute sur chaque nœud du cluster. Il s'assure que les conteneurs fonctionnent dans un pod.
Le kubelet prend un ensemble de PodSpecs fournis par divers mécanismes et s'assure du fonctionnement et de la santé des conteneurs décrits dans ces PodSpecs. Le kubelet ne gère que les conteneurs créés par Kubernetes.
kube-proxy (optionnel)
kube-proxy est un
proxy réseau qui s'exécute sur chaque nœud du cluster et implémente une partie du
concept Kubernetes de Service.
kube-proxy maintient les règles réseau sur les nœuds. Ces règles réseau permettent
une communication réseau vers les Pods depuis des sessions réseau à l'intérieur ou à l'extérieur
du cluster.
kube-proxy utilise la couche de filtrage de paquets du système d'exploitation s'il y en a une et qu'elle est disponible. Sinon, kube-proxy transmet le trafic lui-même.
Si vous utilisez un plugin réseau qui implémente le transfert de paquets pour les Services
par lui-même, et fournissant un comportement équivalent à kube-proxy, alors vous n'avez pas besoin d'exécuter
kube-proxy sur les nœuds de votre cluster.
Runtime de conteneur
L'environnement d'exécution de conteneurs est le logiciel responsable de l'exécution des conteneurs.
Les add-ons utilisent des ressources Kubernetes (DaemonSet,
Déploiement, etc.) pour implémenter des fonctionnalités de cluster.
Étant donné qu'ils fournissent des fonctionnalités au niveau du cluster, les ressources des add-ons
appartiennent au namespace kube-system.
Certains add-ons sélectionnés sont décrits ci-dessous ; pour une liste étendue d'add-ons disponibles,
veuillez consulter Add-ons.
DNS
Bien que les autres add-ons ne soient pas strictement nécessaires, tous les clusters Kubernetes devraient avoir
DNS du cluster, car de nombreux exemples en dépendent.
Le DNS du cluster est un serveur DNS, en plus des autres serveur(s) DNS de votre environnement,
qui fournit des enregistrements DNS pour les services Kubernetes.
Les conteneurs démarrés par Kubernetes incluent automatiquement ce serveur DNS dans leurs recherches DNS.
Interface utilisateur Web (Dashboard)
Dashboard est une interface utilisateur basée sur le web,
générale, pour les clusters Kubernetes. Il permet aux utilisateurs de gérer et de résoudre les problèmes des applications
en cours d'exécution dans le cluster, ainsi que du cluster lui-même.
Surveillance des ressources des conteneurs
Surveillance des ressources des conteneurs
enregistre des métriques génériques de séries chronologiques sur les conteneurs dans une base de données centrale et fournit une interface utilisateur pour parcourir ces données.
Journalisation au niveau du cluster
Un mécanisme de journalisation au niveau du cluster est responsable
de l'enregistrement des journaux des conteneurs dans un magasin de journaux central avec une interface de recherche/parcours.
Plugins réseau
Les plugins réseau
sont des composants logiciels qui implémentent la spécification de l'interface réseau de conteneur (CNI).
Ils sont responsables de l'allocation des adresses IP aux pods et de leur permettre de communiquer
entre eux au sein du cluster.
Variations de l'architecture
Bien que les composants principaux de Kubernetes restent cohérents, la manière dont ils sont déployés et
gérés peut varier. Comprendre ces variations est crucial pour concevoir et maintenir
des clusters Kubernetes répondant à des besoins opérationnels spécifiques.
Options de déploiement du plan de contrôle
Les composants du plan de contrôle peuvent être déployés de plusieurs manières :
Déploiement traditionnel
Les composants du plan de contrôle s'exécutent directement sur des machines dédiées ou des machines virtuelles, souvent gérées en tant que services systemd.
Pods statiques
Les composants du plan de contrôle sont déployés en tant que Pods statiques, gérés par le kubelet sur des nœuds spécifiques.
Il s'agit d'une approche courante utilisée par des outils tels que kubeadm.
Auto-hébergé
Le plan de contrôle s'exécute en tant que Pods au sein du cluster Kubernetes lui-même, gérés par des déploiements
et des StatefulSets ou d'autres primitives Kubernetes.
Services Kubernetes gérés
Les fournisseurs de cloud abstraient souvent le plan de contrôle, en gérant ses composants dans le cadre de leur offre de services.
Considérations pour le placement de la charge de travail
Le placement des charges de travail, y compris les composants du plan de contrôle, peut varier en fonction de la taille du cluster,
des exigences de performance et des politiques opérationnelles :
Dans les clusters plus petits ou de développement, les composants du plan de contrôle et les charges de travail des utilisateurs peuvent s'exécuter sur les mêmes nœuds.
Les clusters de production plus importants dédient souvent des nœuds spécifiques aux composants du plan de contrôle,
les séparant des charges de travail des utilisateurs.
Certaines organisations exécutent des add-ons critiques ou des outils de surveillance sur les nœuds du plan de contrôle.
Outils de gestion de cluster
Des outils tels que kubeadm, kops et Kubespray offrent différentes approches pour le déploiement et la gestion des clusters,
chacun avec sa propre méthode de disposition et de gestion des composants.
La flexibilité de l'architecture de Kubernetes permet aux organisations d'adapter leurs clusters à des besoins spécifiques,
en équilibrant des facteurs tels que la complexité opérationnelle, les performances et la charge de gestion.
Personnalisation et extensibilité
L'architecture de Kubernetes permet une personnalisation significative :
Des ordonnanceurs personnalisés peuvent être déployés pour travailler aux côtés de l'ordonnanceur Kubernetes par défaut ou pour le remplacer entièrement.
Les serveurs API peuvent être étendus avec des CustomResourceDefinitions et une agrégation d'API.
Les fournisseurs de cloud peuvent s'intégrer profondément à Kubernetes en utilisant le cloud-controller-manager.
La flexibilité de l'architecture de Kubernetes permet aux organisations d'adapter leurs clusters à des besoins spécifiques,
en équilibrant des facteurs tels que la complexité opérationnelle, les performances et la charge de gestion.
Kubernetes exécute votre charge de travail
en plaçant des conteneurs dans des Pods pour s'exécuter sur des nœuds.
Un nœud peut être une machine virtuelle ou physique, selon le cluster. Chaque nœud
est géré par le
plan de contrôle
et contient les services nécessaires pour exécuter
Pods.
Typiquement, vous avez plusieurs nœuds dans un cluster ; dans un environnement d'apprentissage ou limité en ressources,
vous pourriez n'avoir qu'un seul nœud.
Il existe deux principales façons d'ajouter des nœuds au
serveur API :
Le kubelet sur un nœud s'enregistre automatiquement auprès du plan de contrôle.
Vous (ou un autre utilisateur humain) ajoutez manuellement un objet Nœud.
Après avoir créé un objet Nœud,
ou lorsque le kubelet sur un nœud s'enregistre automatiquement, le plan de contrôle vérifie si le nouvel objet Nœud
est valide. Par exemple, si vous essayez de créer un Nœud à partir du manifeste JSON suivant :
Kubernetes crée un objet Nœud en interne (la représentation). Kubernetes vérifie
qu'un kubelet s'est enregistré auprès du serveur API correspondant au champ metadata.name
du Nœud. Si le nœud est en bonne santé (c'est-à-dire que tous les services nécessaires sont en cours d'exécution),
alors il est éligible pour exécuter un Pod. Sinon, ce nœud est ignoré pour toute activité du cluster
jusqu'à ce qu'il redevienne en bonne santé.
Note:
Kubernetes conserve l'objet pour le Nœud invalide et continue de vérifier s'il devient en bonne santé.
Vous, ou un contrôleur, devez explicitement
supprimer l'objet Nœud pour arrêter cette vérification de santé.
Le nom identifie un Nœud. Deux Nœuds
ne peuvent pas avoir le même nom en même temps. Kubernetes suppose également qu'une ressource avec le même
nom est le même objet. Dans le cas d'un Nœud, on suppose implicitement qu'une instance utilisant le
même nom aura le même état (par exemple, les paramètres réseau, le contenu du disque racine) et les mêmes attributs tels que
les étiquettes du nœud. Cela peut entraîner des incohérences si une instance a été modifiée sans changer son nom.
Si le Nœud doit être remplacé ou mis à jour de manière significative, l'objet Nœud existant doit être
supprimé du serveur API en premier lieu, puis ré-ajouté après la mise à jour.
Auto-enregistrement des nœuds
Lorsque le drapeau kubelet --register-node est vrai (par défaut), le kubelet tente de
s'enregistrer auprès du serveur API. C'est le modèle préféré, utilisé par la plupart des distributions.
Pour l'auto-enregistrement, le kubelet est démarré avec les options suivantes :
--kubeconfig - Chemin vers les informations d'identification pour s'authentifier auprès du serveur API.
--cloud-provider - Comment communiquer avec un fournisseur de cloud
pour lire les métadonnées à son sujet.
--register-node - S'enregistrer automatiquement auprès du serveur API.
--register-with-taints - Enregistrer le nœud avec la liste donnée de
taints (séparées par des virgules <clé>=<valeur>:<effet>).
Ne fait rien si register-node est faux.
--node-ip - Liste facultative de adresses IP séparées par des virgules pour le nœud.
Vous ne pouvez spécifier qu'une seule adresse pour chaque famille d'adresses.
Par exemple, dans un cluster IPv4 à pile unique, vous définissez cette valeur comme l'adresse IPv4 que le
kubelet doit utiliser pour le nœud.
Consultez configurer une pile double IPv4/IPv6
pour plus de détails sur l'exécution d'un cluster à double pile.
Si vous ne fournissez pas cet argument, le kubelet utilise l'adresse IPv4 par défaut du nœud, le cas échéant ;
si le nœud n'a pas d'adresses IPv4, alors le kubelet utilise l'adresse IPv6 par défaut du nœud.
--node-labels - Étiquettes à ajouter lors de l'enregistrement du nœud
dans le cluster (voir les restrictions d'étiquettes appliquées par le
plugin d'admission NodeRestriction).
--node-status-update-frequency - Spécifie à quelle fréquence le kubelet envoie son état de nœud au serveur API.
Comme mentionné dans la section Unicité du nom du nœud,
lorsque la configuration du nœud doit être mise à jour, il est recommandé de ré-enregistrer
le nœud auprès du serveur API. Par exemple, si le kubelet est redémarré avec
un nouvel ensemble de --node-labels, mais le même nom de Nœud est utilisé, le changement ne sera
pas pris en compte, car les étiquettes sont uniquement définies (ou modifiées) lors de l'enregistrement du Nœud auprès du serveur API.
Les Pods déjà planifiés sur le Nœud peuvent se comporter de manière incorrecte ou causer des problèmes si la configuration du Nœud
est modifiée lors du redémarrage du kubelet. Par exemple, un Pod déjà en cours d'exécution
peut être affecté par les nouvelles étiquettes attribuées au Nœud, tandis que d'autres
Pods, incompatibles avec ce Pod, seront planifiés en fonction de cette nouvelle
étiquette. La ré-enregistrement du Nœud garantit que tous les Pods seront évacués et correctement
re-planifiés.
Administration manuelle des nœuds
Vous pouvez créer et modifier des objets Nœud en utilisant
kubectl.
Lorsque vous souhaitez créer manuellement des objets Nœud, définissez le drapeau kubelet --register-node=false.
Vous pouvez modifier des objets Nœud indépendamment du paramètre --register-node.
Par exemple, vous pouvez définir des étiquettes sur un Nœud existant ou le marquer comme non planifiable.
Vous pouvez utiliser des étiquettes sur les Nœuds en conjonction avec des sélecteurs de nœuds sur les Pods pour contrôler
la planification. Par exemple, vous pouvez restreindre un Pod à s'exécuter uniquement sur
un sous-ensemble des nœuds disponibles.
Le marquage d'un nœud comme non planifiable empêche le planificateur de placer de nouveaux pods sur
ce Nœud, mais n'affecte pas les Pods existants sur le Nœud. Cela est utile comme
étape préparatoire avant un redémarrage du nœud ou une autre opération de maintenance.
Pour marquer un Nœud comme non planifiable, exécutez :
Les Pods faisant partie d'un DaemonSet tolèrent
le fait d'être exécutés sur un Nœud non planifiable. Les DaemonSets fournissent généralement des services locaux au nœud
qui doivent s'exécuter sur le Nœud même s'il est vidé des applications de charge de travail.
État du nœud
L'état d'un Nœud contient les informations suivantes :
Les battements de cœur, envoyés par les nœuds Kubernetes, aident votre cluster à déterminer
la disponibilité de chaque nœud et à prendre des mesures en cas de détection de défaillances.
Pour les nœuds, il existe deux formes de battements de cœur :
Objets Lease
dans le namespace kube-node-lease.
Chaque Nœud a un objet Lease associé.
Contrôleur de nœud
Le contrôleur de nœud est un
composant du plan de contrôle Kubernetes qui gère différents aspects des nœuds.
Le contrôleur de nœud a plusieurs rôles dans la vie d'un nœud. Le premier est d'attribuer un
bloc CIDR au nœud lors de son enregistrement (si l'attribution CIDR est activée).
Le deuxième est de maintenir à jour la liste interne des nœuds du contrôleur de nœud avec
la liste des machines disponibles du fournisseur de cloud. Lorsqu'il s'exécute dans un environnement cloud
et chaque fois qu'un nœud est en mauvaise santé, le contrôleur de nœud demande au fournisseur de cloud si la VM pour ce nœud est toujours disponible.
Si ce n'est pas le cas, le contrôleur de nœud supprime le nœud de sa liste de nœuds.
Le troisième est de surveiller la santé des nœuds. Le contrôleur de nœud est
responsable de :
Dans le cas où un nœud devient injoignable, mettre à jour la condition Ready
dans le champ .status du Nœud. Dans ce cas, le contrôleur de nœud définit la
condition Ready à Unknown.
Si un nœud reste injoignable : déclencher
l'éviction initiée par l'API
pour tous les Pods sur le nœud injoignable. Par défaut, le contrôleur de nœud
attend 5 minutes entre le marquage du nœud comme Unknown et la soumission
de la première demande d'éviction.
Par défaut, le contrôleur de nœud vérifie l'état de chaque nœud toutes les 5 secondes.
Cette période peut être configurée à l'aide du drapeau --node-monitor-period sur le
composant kube-controller-manager.
Limites de taux sur l'éviction
Dans la plupart des cas, le contrôleur de nœud limite le taux d'éviction à
--node-eviction-rate (par défaut 0,1) par seconde, ce qui signifie qu'il n'évacuera pas les pods
de plus d'un nœud toutes les 10 secondes.
Le comportement d'éviction des nœuds change lorsqu'un nœud dans une zone de disponibilité donnée
devient en mauvaise santé. Le contrôleur de nœud vérifie quel pourcentage de nœuds dans la zone
sont en mauvaise santé (la condition Ready est Unknown ou False) en même temps :
Si la fraction de nœuds en mauvaise santé est d'au moins --unhealthy-zone-threshold
(par défaut 0,55), alors le taux d'éviction est réduit.
Si le cluster est petit (c'est-à-dire qu'il a moins ou égal à
--large-cluster-size-threshold nœuds - par défaut 50), alors les évictions sont arrêtées.
Sinon, le taux d'éviction est réduit à --secondary-node-eviction-rate
(par défaut 0,01) par seconde.
La raison pour laquelle ces politiques sont mises en œuvre par zone de disponibilité est que
une zone de disponibilité peut être isolée du plan de contrôle tandis que les autres restent
connectées. Si votre cluster ne s'étend pas sur plusieurs zones de disponibilité du fournisseur de cloud,
alors le mécanisme d'éviction ne prend pas en compte l'indisponibilité par zone.
Une raison clé de répartir vos nœuds sur plusieurs zones de disponibilité est de permettre
le déplacement de la charge de travail vers des zones saines lorsque toute une zone est hors service.
Par conséquent, si tous les nœuds d'une zone sont en mauvaise santé, alors le contrôleur de nœud évacue au
taux normal de --node-eviction-rate. Le cas particulier est lorsque toutes les zones sont
complètement en mauvaise santé (aucun des nœuds du cluster n'est en bonne santé). Dans un tel
cas, le contrôleur de nœud suppose qu'il y a un problème de connectivité
entre le plan de contrôle et les nœuds, et n'effectue aucune éviction.
(S'il y a eu une panne et que certains nœuds réapparaissent, le contrôleur de nœud évacue les pods
des nœuds restants qui sont en mauvaise santé ou injoignables).
Le contrôleur de nœud est également responsable de l'éviction des pods s'exécutant sur des nœuds avec
des taintsNoExecute, sauf si ces pods tolèrent cette taint.
Le contrôleur de nœud ajoute également des taints
correspondant aux problèmes du nœud, tels que le nœud injoignable ou non prêt. Cela signifie
que le planificateur ne placera pas de Pods sur des nœuds en mauvaise santé.
Suivi de la capacité des ressources du nœud
Les objets Nœud suivent des informations sur la capacité des ressources du Nœud : par exemple, la quantité
de mémoire disponible et le nombre de CPU.
Les nœuds qui s'enregistrent automatiquement rapportent leur capacité lors de
l'enregistrement. Si vous les ajoutez manuellement, alors
vous devez définir les informations de capacité du nœud lors de son ajout.
Les nœuds qui s'enregistrent automatiquement rapportent leur capacité lors de l'enregistrement. Si vous les ajoutez manuellement, alors vous devez définir les informations de capacité du nœud lors de son ajout.
Le planificateur Kubernetes s'assure qu'il y a suffisamment de ressources pour tous les Pods sur un Nœud. Le planificateur vérifie que la somme des demandes des conteneurs sur le nœud n'est pas supérieure à la capacité du nœud. Cette somme de demandes inclut tous les conteneurs gérés par le kubelet, mais exclut tout conteneur démarré directement par le runtime de conteneur, ainsi que tout processus s'exécutant en dehors du contrôle du kubelet.
Pour activer la mémoire swap sur un nœud, la fonctionnalité NodeSwap doit être activée sur le kubelet (par défaut, elle est activée), et le drapeau de ligne de commande --fail-swap-on ou le paramètre de configuration failSwapOnsetting doit être défini sur false. Pour permettre aux Pods d'utiliser la mémoire swap, swapBehavior ne doit pas être défini sur NoSwap (qui est le comportement par défaut) dans la configuration du kubelet.
Attention:
Lorsque la fonctionnalité de mémoire swap est activée, les données Kubernetes telles que le contenu des objets Secret qui ont été écrits dans tmpfs peuvent maintenant être échangées sur le disque.
Un utilisateur peut également configurer facultativement memorySwap.swapBehavior afin de spécifier comment un nœud utilisera la mémoire swap. Par exemple,
memorySwap:swapBehavior:LimitedSwap
NoSwap (par défaut) : Les charges de travail Kubernetes n'utiliseront pas la mémoire swap.
LimitedSwap : L'utilisation de la mémoire swap par les charges de travail Kubernetes est soumise à des limitations. Seuls les Pods de QoS Burstable sont autorisés à utiliser la mémoire swap.
Si la configuration pour memorySwap n'est pas spécifiée et que la fonctionnalité est activée, par défaut, le kubelet appliquera le même comportement que le paramètre NoSwap.
Avec LimitedSwap, les Pods qui ne relèvent pas de la classification QoS Burstable (c'est-à-dire les Pods QoS BestEffort/Guaranteed) sont interdits d'utiliser la mémoire swap. Pour maintenir les garanties de sécurité et de santé du nœud mentionnées ci-dessus, ces Pods ne sont pas autorisés à utiliser la mémoire swap lorsque LimitedSwap est en vigueur.
Avant de détailler le calcul de la limite d'échange, il est nécessaire de définir les termes suivants :
nodeTotalMemory : La quantité totale de mémoire physique disponible sur le nœud.
totalPodsSwapAvailable : La quantité totale de mémoire swap sur le nœud disponible pour une utilisation par les Pods (une partie de la mémoire swap peut être réservée à des fins système).
containerMemoryRequest : La demande de mémoire du conteneur.
La limitation d'échange est configurée comme suit :
(containerMemoryRequest / nodeTotalMemory) * totalPodsSwapAvailable.
Il est important de noter que, pour les conteneurs dans les Pods de QoS Burstable, il est possible de désactiver l'utilisation de l'échange en spécifiant des demandes de mémoire égales aux limites de mémoire. Les conteneurs configurés de cette manière n'auront pas accès à la mémoire swap.
L'échange est pris en charge uniquement avec cgroup v2, cgroup v1 n'est pas pris en charge.
2 - Communication entre les nœuds et le plan de contrôle
Ce document répertorie les chemins de communication entre le serveur API
et le cluster Kubernetes.
L'objectif est de permettre aux utilisateurs de personnaliser leur installation pour renforcer la configuration réseau
afin que le cluster puisse fonctionner sur un réseau non fiable (ou sur des adresses IP publiques complètement)
fournies par un fournisseur de cloud.
Nœud vers le plan de contrôle
Kubernetes utilise un modèle d'API de type "hub-et-spoke". Toutes les utilisations de l'API à partir des nœuds (ou des pods qu'ils exécutent)
se terminent au niveau du serveur API. Aucun des autres composants du plan de contrôle n'est conçu pour exposer
des services distants. Le serveur API est configuré pour écouter les connexions distantes sur un port HTTPS sécurisé
(généralement le port 443) avec une ou plusieurs formes d'authentification
client activées.
Une ou plusieurs formes d'autorisation devraient être
activées, en particulier si les requêtes anonymes
ou les jetons de compte de service
sont autorisés.
Les nœuds doivent être provisionnés avec le certificat racine public pour le cluster afin qu'ils puissent
se connecter de manière sécurisée au serveur API avec des informations d'identification client valides. Une bonne approche consiste à ce que les
informations d'identification client fournies au kubelet soient sous la forme d'un certificat client. Consultez
l'amorçage TLS du kubelet
pour la provision automatisée des certificats client du kubelet.
Les pods qui souhaitent se connecter au serveur API peuvent le faire de manière sécurisée en utilisant un compte de service de sorte
que Kubernetes injecte automatiquement le certificat racine public et un jeton d'accès valide
dans le pod lors de son instanciation.
Le service kubernetes (dans le namespace default) est configuré avec une adresse IP virtuelle qui est
redirigée (via kube-proxy) vers le point de terminaison HTTPS du serveur API.
Les composants du plan de contrôle communiquent également avec le serveur API via le port sécurisé.
Par conséquent, le mode de fonctionnement par défaut des connexions des nœuds et des pods exécutés sur les
nœuds vers le plan de contrôle est sécurisé par défaut et peut fonctionner sur des
réseaux non fiables et/ou publics.
Plan de contrôle vers le nœud
Il existe deux chemins de communication principaux du plan de contrôle (le serveur API) vers les nœuds.
Le premier est du serveur API au processus kubelet qui s'exécute sur chaque nœud du cluster.
Le deuxième est du serveur API vers n'importe quel nœud, pod ou service via la fonctionnalité de proxy du serveur API.
Serveur API vers kubelet
Les connexions du serveur API au kubelet sont utilisées pour :
Récupérer les journaux des pods.
Se connecter (généralement via kubectl) aux pods en cours d'exécution.
Fournir la fonctionnalité de transfert de port du kubelet.
Ces connexions se terminent au niveau du point de terminaison HTTPS du kubelet. Par défaut, le serveur API ne vérifie pas
le certificat de service du kubelet, ce qui rend la connexion vulnérable aux
attaques de l'homme du milieu et non sécurisée pour une utilisation
sur des réseaux non fiables et/ou publics.
Pour vérifier cette connexion, utilisez le paramètre --kubelet-certificate-authority
pour fournir au serveur API un ensemble de certificats racine à utiliser pour vérifier le certificat de service du kubelet.
Si cela n'est pas possible, utilisez le tunnel SSH entre le serveur API et le kubelet si
nécessaire pour éviter de se connecter via un
réseau non fiable ou public.
Serveur API vers les nœuds, les pods et les services
Les connexions du serveur API vers un nœud, un pod ou un service sont par défaut des connexions HTTP non sécurisées
et ne sont donc ni authentifiées ni chiffrées. Elles peuvent être exécutées via une connexion HTTPS sécurisée
en préfixant https: au nom du nœud, du pod ou du service dans l'URL de l'API, mais elles ne vérifieront pas
le certificat fourni par le point de terminaison HTTPS ni ne fourniront des informations d'identification client. Ainsi,
bien que la connexion soit chiffrée, elle ne garantira aucune intégrité. Ces
connexions ne sont actuellement pas sûres pour une utilisation sur des réseaux non fiables ou publics.
Tunnels SSH
Kubernetes prend en charge les tunnels SSH pour protéger les chemins de communication du plan de contrôle vers les nœuds. Dans cette
configuration, le serveur API initie un tunnel SSH vers chaque nœud du cluster (en se connectant à
le serveur SSH qui écoute sur le port 22) et fait passer tout le trafic destiné à un kubelet, un nœud, un pod ou
un service à travers le tunnel.
Ce tunnel garantit que le trafic n'est pas exposé en dehors du réseau dans lequel les nœuds sont
exécutés.
Note:
Les tunnels SSH sont actuellement obsolètes, vous ne devriez donc pas choisir de les utiliser à moins de savoir ce que vous
faites. Le service Konnectivity est un remplacement pour ce
canal de communication.
Service Konnectivity
FEATURE STATE:Kubernetes v1.18 [beta]
En remplacement des tunnels SSH, le service Konnectivity fournit un proxy de niveau TCP pour la
communication entre le plan de contrôle et le cluster. Le service Konnectivity se compose de deux parties : le
serveur Konnectivity dans le réseau du plan de contrôle et les agents Konnectivity dans le réseau des nœuds.
Les agents Konnectivity initient des connexions vers le serveur Konnectivity et maintiennent
les connexions réseau.
Après avoir activé le service Konnectivity, tout le trafic du plan de contrôle vers les nœuds passe
par ces connexions.
En robotique et automatisation, une boucle de contrôle est
une boucle non terminante qui régule l'état d'un système.
Voici un exemple de boucle de contrôle : un thermostat dans une pièce.
Lorsque vous réglez la température, vous indiquez au thermostat
votre état souhaité. La température réelle de la pièce est l'
état actuel. Le thermostat agit pour rapprocher l'état actuel
de l'état souhaité, en allumant ou éteignant l'équipement.
Boucle de contrôle surveillant l'état partagé du cluster à travers l'apiserver et effectuant des changements en essayant de déplacer l'état actuel vers l'état désiré.
Modèle de contrôleur
Un contrôleur suit au moins un type de ressource Kubernetes.
Ces objets
ont un champ spec qui représente l'état souhaité. Les
contrôleurs de cette ressource sont responsables de rapprocher l'état
actuel de cet état souhaité.
Le contrôleur peut effectuer lui-même l'action ; plus couramment, dans Kubernetes,
un contrôleur enverra des messages au
serveur API qui ont
des effets secondaires utiles. Vous verrez des exemples de cela ci-dessous.
Contrôle via le serveur API
Le contrôleur de Job est un exemple de contrôleur
intégré à Kubernetes. Les contrôleurs intégrés gèrent l'état en
interagissant avec le serveur API du cluster.
Job est une ressource Kubernetes qui exécute un
Pod, ou peut-être plusieurs Pods, pour effectuer
une tâche, puis s'arrête.
(Une fois planifiés, les objets Pod font partie de l'
état souhaité pour un kubelet).
Lorsque le contrôleur de Job voit une nouvelle tâche, il s'assure que, quelque part
dans votre cluster, les kubelets sur un ensemble de nœuds exécutent le bon
nombre de Pods pour effectuer le travail.
Le contrôleur de Job n'exécute aucun Pod ou conteneur
lui-même. Au lieu de cela, le contrôleur de Job demande au serveur API de créer ou supprimer
des Pods.
D'autres composants du
plan de contrôle
agissent sur les nouvelles informations (il y a de nouveaux Pods à planifier et à exécuter),
et finalement le travail est terminé.
Après avoir créé un nouveau Job, l'état souhaité est que ce Job soit terminé.
Le contrôleur de Job rapproche l'état actuel de ce Job de votre
état souhaité : en créant des Pods qui effectuent le travail que vous avez demandé pour ce Job, de sorte que
le Job soit plus proche de l'achèvement.
Les contrôleurs mettent également à jour les objets qui les configurent.
Par exemple : une fois le travail terminé pour un Job, le contrôleur de Job
met à jour cet objet Job pour le marquer comme Terminé.
(C'est un peu comme certains thermostats éteignent une lumière pour
indiquer que votre pièce est maintenant à la température que vous avez réglée).
Contrôle direct
Contrairement à Job, certains contrôleurs doivent apporter des modifications à
des éléments en dehors de votre cluster.
Par exemple, si vous utilisez une boucle de contrôle pour vous assurer qu'il y a
suffisamment de nœuds
dans votre cluster, alors ce contrôleur a besoin de quelque chose en dehors du
cluster actuel pour configurer de nouveaux nœuds lorsque cela est nécessaire.
Les contrôleurs qui interagissent avec un état externe trouvent leur état souhaité à partir
du serveur API, puis communiquent directement avec un système externe pour rapprocher
l'état actuel en ligne.
(Il existe en fait un contrôleur
qui met à l'échelle horizontalement les nœuds de votre cluster.)
Le point important ici est que le contrôleur apporte certaines modifications pour atteindre
votre état souhaité, puis rapporte l'état actuel à votre serveur API de cluster.
D'autres boucles de contrôle peuvent observer ces données rapportées et prendre leurs propres mesures.
Dans l'exemple du thermostat, si la pièce est très froide, un autre contrôleur
pourrait également allumer un radiateur de protection contre le gel. Avec les clusters Kubernetes, le plan de contrôle
fonctionne indirectement avec des outils de gestion des adresses IP, des services de stockage,
des API de fournisseurs de cloud et d'autres services en
étendant Kubernetes pour les implémenter.
État souhaité par rapport à l'état actuel
Kubernetes adopte une vision nativement cloud des systèmes et est capable de gérer
un changement constant.
Votre cluster peut changer à tout moment à mesure que le travail se déroule et que
les boucles de contrôle corrigent automatiquement les défaillances. Cela signifie que,
potentiellement, votre cluster n'atteint jamais un état stable.
Tant que les contrôleurs de votre cluster sont en cours d'exécution et capables de
effectuer des modifications utiles, il n'importe pas si l'état global est stable ou non.
Conception
En tant que principe de sa conception, Kubernetes utilise de nombreux contrôleurs qui gèrent chacun
un aspect particulier de l'état du cluster. Le plus souvent, une boucle de contrôle
(contrôleur) utilise un type de ressource comme état souhaité et gère un autre type
de ressource pour réaliser cet état souhaité. Par exemple,
un contrôleur pour les Jobs suit les objets Job (pour découvrir un nouveau travail) et les objets Pod
(pour exécuter les Jobs, puis voir quand le travail est terminé). Dans ce cas,
quelque chose d'autre crée les Jobs, tandis que le contrôleur de Job crée les Pods.
Il est utile d'avoir des contrôleurs simples plutôt qu'un ensemble monolithique de
boucles de contrôle interconnectées. Les contrôleurs peuvent échouer,
c'est pourquoi Kubernetes est conçu pour le permettre.
Note:
Il peut y avoir plusieurs contrôleurs qui créent ou mettent à jour le même type d'objet.
En coulisses, les contrôleurs Kubernetes s'assurent qu'ils ne prêtent attention qu'aux ressources
liées à leur ressource de contrôle.
Par exemple, vous pouvez avoir des Déploiements et des Jobs ; ceux-ci créent tous deux des Pods.
Le contrôleur de Job ne supprime pas les Pods créés par votre Déploiement,
car il existe des informations (étiquettes)
que les contrôleurs peuvent utiliser pour distinguer ces Pods.
Modes d'exécution des contrôleurs
Kubernetes est livré avec un ensemble de contrôleurs intégrés qui s'exécutent à l'intérieur
du kube-controller-manager. Ces
contrôleurs intégrés fournissent des comportements de base importants.
Le contrôleur de Déploiement et le contrôleur de Job sont des exemples de contrôleurs qui
font partie de Kubernetes lui-même (contrôleurs "intégrés").
Kubernetes vous permet d'exécuter un plan de contrôle résilient, de sorte que si l'un des contrôleurs intégrés
venait à échouer, une autre partie du plan de contrôle prendra en charge le travail.
Vous pouvez trouver des contrôleurs qui s'exécutent en dehors du plan de contrôle pour étendre Kubernetes.
Ou, si vous le souhaitez, vous pouvez écrire vous-même un nouveau contrôleur.
Vous pouvez exécuter votre propre contrôleur sous la forme d'un ensemble de Pods, ou en dehors de Kubernetes.
Ce qui convient le mieux dépendra de ce que ce contrôleur particulier fait.
Les systèmes distribués ont souvent besoin de Lease, qui fournissent un mécanisme pour verrouiller les ressources partagées
et coordonner l'activité entre les membres d'un ensemble.
Dans Kubernetes, le concept de bail est représenté par les objets Lease
dans le groupe d'API coordination.k8s.ioGroupe d'API,
qui sont utilisés pour des fonctionnalités critiques du système telles que les battements de cœur des nœuds et l'élection du leader au niveau des composants.
Battements de cœur des nœuds
Kubernetes utilise l'API Lease pour communiquer les battements de cœur des nœuds kubelet au serveur API Kubernetes.
Pour chaque Node, il existe un objet Lease avec un nom correspondant dans le namespace kube-node-lease.
Sous le capot, chaque battement de cœur kubelet est une demande de mise à jour de cet objet Lease, mettant à jour
le champ spec.renewTime pour le bail. Le plan de contrôle Kubernetes utilise le horodatage de ce champ
pour déterminer la disponibilité de ce Node.
Kubernetes utilise également des Lease pour s'assurer qu'une seule instance d'un composant est en cours d'exécution à tout moment.
Cela est utilisé par les composants du plan de contrôle tels que kube-controller-manager et kube-scheduler dans
les configurations HA, où une seule instance du composant doit être en cours d'exécution activement tandis que les autres
instances sont en attente.
Lisez élection coordonnée du leader
pour en savoir plus sur la façon dont Kubernetes s'appuie sur l'API Lease pour sélectionner quelle instance de composant
agit en tant que leader.
Identité du serveur API
FEATURE STATE:Kubernetes v1.26 [beta]
À partir de Kubernetes v1.26, chaque kube-apiserver utilise l'API Lease pour publier son identité au reste du système.
Bien que cela ne soit pas particulièrement utile en soi, cela fournit un mécanisme pour les clients afin de
découvrir combien d'instances de kube-apiserver opèrent sur le plan de contrôle Kubernetes.
L'existence des Lease kube-apiserver permet des fonctionnalités futures qui peuvent nécessiter une coordination entre
chaque kube-apiserver.
Vous pouvez inspecter les Lease détenus par chaque kube-apiserver en vérifiant les objets de bail dans le namespace kube-system
avec le nom kube-apiserver-<sha256-hash>. Alternativement, vous pouvez utiliser le sélecteur d'étiquettes apiserver.kubernetes.io/identity=kube-apiserver:
kubectl -n kube-system get lease -l apiserver.kubernetes.io/identity=kube-apiserver
Le hachage SHA256 utilisé dans le nom du bail est basé sur le nom d'hôte du système d'exploitation tel que vu par ce serveur API. Chaque kube-apiserver devrait être
configuré pour utiliser un nom d'hôte qui est unique dans le cluster. Les nouvelles instances de kube-apiserver qui utilisent le même nom d'hôte
prendront le contrôle des Lease existants en utilisant une nouvelle identité de détenteur, au lieu d'instancier de nouveaux objets de bail. Vous pouvez vérifier le
nom d'hôte utilisé par kube-apisever en vérifiant la valeur de l'étiquette kubernetes.io/hostname:
kubectl -n kube-system get lease apiserver-07a5ea9b9b072c4a5f3d1c3702 -o yaml
Les Lease expirés des kube-apiservers qui n'existent plus sont collectés par les nouveaux kube-apiservers après 1 heure.
Vous pouvez désactiver les Lease d'identité du serveur API en désactivant la fonctionnalité APIServerIdentityfeature gate.
Charges de travail
Votre propre charge de travail peut définir son propre usage des Lease. Par exemple, vous pouvez exécuter un
contrôleur personnalisé où un membre principal ou leader
effectue des opérations que ses pairs ne font pas. Vous définissez un bail afin que les réplicas du contrôleur puissent sélectionner
ou élire un leader, en utilisant l'API Kubernetes pour la coordination.
Si vous utilisez un bail, il est bon de pratiquer de définir un nom pour le bail qui est clairement lié au
produit ou au composant. Par exemple, si vous avez un composant nommé Example Foo, utilisez un bail nommé
example-foo.
Si un opérateur de cluster ou un autre utilisateur final peut déployer plusieurs instances d'un composant, sélectionnez un préfixe de nom
et choisissez un mécanisme (comme le hachage du nom du déploiement) pour éviter les collisions de noms
pour les Lease.
Vous pouvez utiliser une autre approche tant qu'elle atteint le même résultat : les différents produits logiciels ne
entrent pas en conflit les uns avec les autres.
5 - Gestionnaire du contrôleur de cloud
FEATURE STATE:Kubernetes v1.11 [beta]
Les technologies d'infrastructure cloud vous permettent d'exécuter Kubernetes sur des clouds publics, privés et hybrides.
Kubernetes croit en une infrastructure automatisée pilotée par API sans couplage
étroit entre les composants.
Le gestionnaire du contrôleur de cloud est le Cloud Controller Manager est une fonctionnalité alpha de la version 1.8. Dans les prochaines versions, il deviendra le moyen privilégié pour l'intégration de Kubernetes à n'importe quel cloud.
Kubernetes v1.6 contient un nouveau binaire appelé cloud-controller-manager. Le cloud-controller-manager est un service qui intègre des boucles de contrôle propres au cloud. Ces boucles de contrôle spécifiques au cloud se trouvaient à l'origine dans le kube-controller-manager. Étant donné que les fournisseurs de cloud développent et mettent à jour leurs produits à un rythme différent de celui du projet Kubernetes, l'abstraction du code spécifique au fournisseur, au niveau du binaire cloud-controller-manager, permet aux fournisseurs de cloud d'évoluer indépendamment du code principal de Kubernetes.
Le gestionnaire du contrôleur de cloud est structuré à l'aide d'un mécanisme de plugin
qui permet aux différents fournisseurs de cloud d'intégrer leurs plateformes à Kubernetes.
Conception
Le gestionnaire du contrôleur de cloud s'exécute dans le plan de contrôle en tant qu'ensemble répliqué de processus
(généralement, ce sont des conteneurs dans des Pods). Chaque gestionnaire du contrôleur de cloud implémente
plusieurs contrôleurs
dans un seul processus.
Note:
Vous pouvez également exécuter le gestionnaire du contrôleur de cloud en tant que
addon Kubernetes plutôt que
de le faire partie du plan de contrôle.
Fonctions du gestionnaire du contrôleur de cloud
Les contrôleurs à l'intérieur du gestionnaire du contrôleur de cloud comprennent :
Contrôleur de nœud
Le contrôleur de nœud est responsable de la mise à jour des objets Nœud
lorsque de nouveaux serveurs sont créés dans votre infrastructure cloud. Le contrôleur de nœud obtient des informations sur les
hôtes en cours d'exécution dans votre tenancy avec le fournisseur de cloud. Le contrôleur de nœud effectue les fonctions suivantes :
Mettre à jour un objet Nœud avec l'identifiant unique du serveur obtenu à partir de l'API du fournisseur de cloud.
Annoter et étiqueter l'objet Nœud avec des informations spécifiques au cloud, telles que la région dans laquelle le nœud
est déployé et les ressources (CPU, mémoire, etc.) dont il dispose.
Obtenir le nom d'hôte et les adresses réseau du nœud.
Vérifier la santé du nœud. Si un nœud devient non réactif, ce contrôleur vérifie
auprès de l'API de votre fournisseur de cloud si le serveur a été désactivé / supprimé / terminé.
Si le nœud a été supprimé du cloud, le contrôleur supprime l'objet Nœud
de votre cluster Kubernetes.
Certaines implémentations de fournisseurs de cloud divisent cela en un contrôleur de nœud
et un contrôleur de cycle de vie de nœud distinct.
Contrôleur de route
Le contrôleur de route est responsable de la configuration des routes dans le cloud
de manière appropriée afin que les conteneurs sur différents nœuds de votre cluster Kubernetes
puissent communiquer entre eux.
Selon le fournisseur de cloud, le contrôleur de route peut également allouer des blocs
d'adresses IP pour le réseau de Pod.
Contrôleur de service
Les services s'intègrent aux composants d'infrastructure cloud tels que les équilibreurs de charge gérés, les adresses IP, le filtrage des paquets réseau
et la vérification de l'état de la cible. Le contrôleur de service interagit avec les API de votre
fournisseur de cloud pour configurer les équilibreurs de charge et autres composants
d'infrastructure
lorsque vous déclarez une ressource Service qui les nécessite.
Autorisation
Cette section détaille l'accès requis par le gestionnaire du contrôleur de cloud
sur divers objets API pour effectuer ses opérations.
Contrôleur de nœud
Le contrôleur de nœud ne fonctionne qu'avec les objets Nœud. Il nécessite un accès complet
pour lire et modifier les objets Nœud.
v1/Node :
get
list
create
update
patch
watch
delete
Contrôleur de route
Le contrôleur de route écoute la création d'objets Nœud et configure
les routes de manière appropriée. Il nécessite un accès Get aux objets Nœud.
v1/Node :
get
Contrôleur de service
Le contrôleur de service surveille les événements de création, de mise à jour et de suppression des objets Service, puis
configure les Endpoints pour ces Services de manière appropriée (pour les EndpointSlices, le
kube-controller-manager les gère à la demande).
Pour accéder aux Services, il nécessite un accès list et watch. Pour mettre à jour les Services, il nécessite
un accès patch et update.
Pour configurer les ressources Endpoints pour les Services, il nécessite un accès create, list,
get, watch et update.
v1/Service :
list
get
watch
patch
update
Autres
La mise en œuvre du cœur du gestionnaire du contrôleur de cloud nécessite un accès pour créer des objets Event
et pour assurer un fonctionnement sécurisé, il nécessite un accès pour créer des comptes de service.
v1/Event :
create
patch
update
v1/ServiceAccount :
create
Le ClusterRole RBAC pour le gestionnaire du
contrôleur de cloud ressemble à ceci :
Vous voulez savoir comment implémenter votre propre gestionnaire du contrôleur de cloud ou étendre un projet existant ?
Le gestionnaire du contrôleur de cloud utilise des interfaces Go, en particulier, l'interface CloudProvider définie dans
cloud.go
de kubernetes/cloud-provider pour permettre
l'intégration de toutes les implémentations de cloud.
La mise en œuvre des contrôleurs partagés mis en évidence dans ce document (Nœud, Route et Service),
ainsi que certaines structures de base avec l'interface cloudprovider partagée, font partie du cœur de Kubernetes.
Les implémentations spécifiques aux fournisseurs de cloud se trouvent en dehors du cœur de Kubernetes et implémentent
l'interface CloudProvider.
Sur Linux, les groupes de contrôle
limitent les ressources allouées aux processus.
Le kubelet et le
runtime de conteneur sous-jacent doivent interagir avec les cgroups pour appliquer
la gestion des ressources pour les pods et les conteneurs, ce qui
inclut les demandes et les limites de CPU/mémoire pour les charges de travail conteneurisées.
Il existe deux versions de cgroups sur Linux : cgroup v1 et cgroup v2. cgroup v2 est
la nouvelle génération de l'API cgroup.
Qu'est-ce que cgroup v2 ?
FEATURE STATE:Kubernetes v1.25 [stable]
cgroup v2 est la prochaine version de l'API cgroup de Linux. cgroup v2 offre un
système de contrôle unifié avec des capacités de gestion des ressources améliorées.
cgroup v2 propose plusieurs améliorations par rapport à cgroup v1, telles que :
Conception d'une hiérarchie unifiée unique dans l'API
Délégation plus sûre des sous-arbres aux conteneurs
Gestion améliorée de l'allocation des ressources et de l'isolation sur plusieurs ressources
Comptabilité unifiée pour différents types d'allocations de mémoire (mémoire réseau, mémoire du noyau, etc.)
Comptabilité des modifications de ressources non immédiates, telles que les écritures de cache de pages
Certaines fonctionnalités de Kubernetes utilisent exclusivement cgroup v2 pour une
gestion des ressources et une isolation améliorées. Par exemple, la fonctionnalité
MemoryQoS améliore la QoS de la mémoire
et repose sur les primitives cgroup v2.
Utilisation de cgroup v2
La manière recommandée d'utiliser cgroup v2 est d'utiliser une distribution Linux qui
active et utilise cgroup v2 par défaut.
Vous pouvez également activer manuellement cgroup v2 sur votre distribution Linux en modifiant
les arguments de démarrage de la ligne de commande du noyau. Si votre distribution utilise GRUB,
systemd.unified_cgroup_hierarchy=1 doit être ajouté dans GRUB_CMDLINE_LINUX
sous /etc/default/grub, suivi de sudo update-grub.
Cependant, l'approche recommandée est d'utiliser une distribution qui active déjà cgroup v2 par
défaut.
Migration vers cgroup v2
Pour migrer vers cgroup v2, assurez-vous de respecter les exigences, puis mettez à jour
vers une version du noyau qui active cgroup v2 par défaut.
Le kubelet détecte automatiquement si le système d'exploitation utilise cgroup v2 et
agit en conséquence, sans nécessiter de configuration supplémentaire.
Il ne devrait pas y avoir de différence perceptible dans l'expérience utilisateur lors du
passage à cgroup v2, sauf si les utilisateurs accèdent directement au système de fichiers cgroup
soit sur le nœud, soit depuis les conteneurs.
cgroup v2 utilise une API différente de cgroup v1, donc si des
applications accèdent directement au système de fichiers cgroup, elles doivent être
mises à jour vers des versions plus récentes qui prennent en charge cgroup v2. Par exemple :
Certains agents de surveillance et de sécurité tiers peuvent dépendre du système de fichiers cgroup.
Mettez à jour ces agents vers des versions qui prennent en charge cgroup v2.
Si vous exécutez cAdvisor en tant que DaemonSet autonome
pour surveiller les pods et les conteneurs, mettez-le à jour vers la version 0.43.0 ou ultérieure.
Si vous déployez des applications Java, préférez utiliser des versions qui prennent en charge pleinement cgroup v2 :
Si vous utilisez le package uber-go/automaxprocs, assurez-vous
d'utiliser la version v1.5.1 ou supérieure.
Identifier la version de cgroup sur les nœuds Linux
La version de cgroup dépend de la distribution Linux utilisée et de la
version de cgroup par défaut configurée sur le système d'exploitation. Pour vérifier quelle version de cgroup votre
distribution utilise, exécutez la commande stat -fc %T /sys/fs/cgroup/ sur
le nœud :
Le CRI (Container Runtime Interface) est une interface de plugin qui permet au kubelet d'utiliser
une grande variété de runtimes de conteneurs, sans avoir besoin de recompiler les composants du cluster.
Vous avez besoin d'un
runtime de conteneur fonctionnel
sur chaque nœud de votre cluster, afin que le
kubelet puisse lancer
Pods et leurs conteneurs.
L'Interface de Runtime de Conteneur (CRI) est le protocole principal pour la communication entre le kubelet et le Runtime de Conteneur.
Le kubelet agit en tant que client lorsqu'il se connecte au runtime de conteneur via gRPC.
Les points de terminaison du service de runtime et d'image doivent être disponibles
dans le runtime de conteneur, ce qui peut être configuré séparément dans le kubelet
en utilisant les indicateurs de ligne de commande --image-service-endpoint (voir la référence des options du kubelet).
Pour Kubernetes v1.31, le kubelet préfère utiliser CRI v1.
Si un runtime de conteneur ne prend pas en charge v1 de CRI, alors le kubelet essaie de
négocier toute version plus ancienne prise en charge.
Le kubelet de v1.31 peut également négocier CRI v1alpha2, mais
cette version est considérée comme obsolète.
Si le kubelet ne peut pas négocier une version de CRI prise en charge, le kubelet abandonne
et ne s'enregistre pas en tant que nœud.
Mise à niveau
Lors de la mise à niveau de Kubernetes, le kubelet essaie de sélectionner automatiquement la
dernière version de CRI lors du redémarrage du composant. Si cela échoue, alors le fallback
aura lieu comme mentionné ci-dessus. Si une nouvelle connexion gRPC était nécessaire car le
runtime de conteneur a été mis à niveau, alors le runtime de conteneur doit également
prendre en charge la version initialement sélectionnée, sinon la reconnexion est censée échouer. Cela
nécessite un redémarrage du kubelet.
A suivre
En savoir plus sur la définition du protocole CRI ici
8 - Collecte des déchets
Le Garbage collection est un terme générique désignant les différents mécanismes utilisés par Kubernetes pour nettoyer les ressources du cluster. Cela permet le nettoyage des ressources suivantes :
De nombreux objets dans Kubernetes sont liés les uns aux autres par le biais de références de propriétaire.
Les références de propriétaire indiquent au plan de contrôle quels objets dépendent des autres.
Kubernetes utilise les références de propriétaire pour permettre au plan de contrôle et aux autres clients de l'API
de nettoyer les ressources associées avant de supprimer un objet. Dans la plupart des cas, Kubernetes gère automatiquement les références de propriétaire.
La propriété est différente du mécanisme étiquettes et sélecteurs
que certains ressources utilisent également. Par exemple, considérez un
Service qui crée des objets EndpointSlice.
Le Service utilise des étiquettes pour permettre au plan de contrôle de
déterminer quels objets EndpointSlice sont utilisés pour ce Service. En plus
des étiquettes, chaque EndpointSlice géré au nom d'un Service a
une référence de propriétaire. Les références de propriétaire aident les différentes parties de Kubernetes à éviter
d'interférer avec les objets qu'elles ne contrôlent pas.
Note:
Les références de propriétaire entre namespaces sont interdites par conception.
Les dépendants dans un namespace peuvent spécifier des propriétaires à portée de cluster ou à portée de namespace.
Un propriétaire à portée de namespace doit exister dans le même namespace que le dépendant.
S'il n'existe pas, la référence de propriétaire est considérée comme absente et le dépendant
est susceptible d'être supprimé une fois que tous les propriétaires sont vérifiés comme absents.
Les dépendants à portée de cluster ne peuvent spécifier que des propriétaires à portée de cluster.
À partir de la version 1.20, si un dépendant à portée de cluster spécifie un type à portée de namespace en tant que propriétaire,
il est considéré comme ayant une référence de propriétaire non résoluble et ne peut pas être collecté par le garbage collector.
À partir de la version 1.20, si le garbage collector détecte une référence de propriétaire non valide entre namespaces,
ou un dépendant à portée de cluster avec une référence de propriétaire faisant référence à un type à portée de namespace, un événement d'avertissement
avec une raison de OwnerRefInvalidNamespace et un involvedObject du dépendant non valide est signalé.
Vous pouvez vérifier ce type d'événement en exécutant
kubectl get events -A --field-selector=reason=OwnerRefInvalidNamespace.
Suppression en cascade
Kubernetes vérifie et supprime les objets qui n'ont plus de références de propriétaire,
comme les pods laissés derrière lors de la suppression d'un ReplicaSet. Lorsque vous
supprimez un objet, vous pouvez contrôler si Kubernetes supprime automatiquement les objets dépendants,
dans un processus appelé suppression en cascade. Il existe
deux types de suppression en cascade, comme suit :
Suppression en cascade en premier plan
Suppression en cascade en arrière-plan
Vous pouvez également contrôler comment et quand la collecte des déchets supprime les ressources qui ont
des références de propriétaire en utilisant les finalizers Kubernetes.
Suppression en cascade en premier plan
Dans la suppression en cascade en premier plan, l'objet propriétaire que vous supprimez entre d'abord dans
un état de suppression en cours. Dans cet état, les actions suivantes se produisent sur
l'objet propriétaire :
Le serveur API Kubernetes définit le champ metadata.deletionTimestamp de l'objet sur l'heure à laquelle l'objet a été marqué pour suppression.
Le serveur API Kubernetes définit également le champ metadata.finalizers sur foregroundDeletion.
L'objet reste visible via l'API Kubernetes jusqu'à ce que le processus de suppression soit terminé.
Après que l'objet propriétaire entre dans l'état de suppression en cours, le contrôleur supprime les dépendants. Après avoir supprimé tous les objets dépendants, le contrôleur
supprime l'objet propriétaire. À ce stade, l'objet n'est plus visible dans
l'API Kubernetes.
Pendant la suppression en cascade en premier plan, seuls les dépendants qui bloquent la suppression du propriétaire sont ceux qui ont le champ ownerReference.blockOwnerDeletion=true.
Consultez Utiliser la suppression en cascade en premier plan
pour en savoir plus.
Suppression en cascade en arrière-plan
Dans la suppression en cascade en arrière-plan, le serveur API Kubernetes supprime immédiatement l'objet propriétaire et le contrôleur nettoie les objets dépendants en
arrière-plan. Par défaut, Kubernetes utilise la suppression en cascade en arrière-plan, sauf si
vous utilisez manuellement la suppression en premier plan ou choisissez d'abandonner les objets dépendants.
Lorsque Kubernetes supprime un objet propriétaire, les dépendants laissés derrière sont appelés
objets orphelins. Par défaut, Kubernetes supprime les objets dépendants. Pour apprendre comment
outrepasser ce comportement, consultez Supprimer les objets propriétaires et les dépendants orphelins.
Collecte des déchets des conteneurs et des images inutilisés
Le kubelet effectue la collecte des déchets
sur les images inutilisées toutes les deux minutes et sur les conteneurs inutilisés toutes les
minutes. Vous devez éviter d'utiliser des outils de collecte des déchets externes, car ils peuvent
perturber le comportement du kubelet et supprimer des conteneurs qui devraient exister.
Pour configurer les options de collecte des déchets des conteneurs et des images inutilisés, ajustez le
kubelet en utilisant un fichier de configuration
et modifiez les paramètres liés à la collecte des déchets en utilisant le
type de ressource KubeletConfiguration.
Cycle de vie des images de conteneur
Kubernetes gère le cycle de vie de toutes les images via son gestionnaire d'images,
qui fait partie du kubelet, en collaboration avec
cadvisor. Le kubelet
prend en compte les limites d'utilisation du disque suivantes lors de la prise de décision de collecte des déchets :
HighThresholdPercent
LowThresholdPercent
Une utilisation du disque supérieure à la valeur configurée de HighThresholdPercent déclenche la collecte des déchets, qui supprime les images dans l'ordre en fonction de leur dernière utilisation,
en commençant par les plus anciennes en premier. Le kubelet supprime les images
jusqu'à ce que l'utilisation du disque atteigne la valeur LowThresholdPercent.
Collecte des déchets pour les images de conteneur inutilisées
FEATURE STATE:Kubernetes v1.30 [beta]
En tant que fonctionnalité bêta, vous pouvez spécifier la durée maximale pendant laquelle une image locale peut rester inutilisée,
indépendamment de l'utilisation du disque. Il s'agit d'un paramètre du kubelet que vous configurez pour chaque nœud.
Pour configurer le paramètre, activez la fonctionnalité ImageMaximumGCAgefeature gate pour le kubelet,
et définissez également une valeur pour le champ imageMaximumGCAge dans le fichier de configuration du kubelet.
La valeur est spécifiée en tant que durée Kubernetes ;
Les unités de temps valides pour le champ imageMaximumGCAge dans le fichier de configuration du kubelet sont :
"ns" pour les nanosecondes
"us" ou "µs" pour les microsecondes
"ms" pour les millisecondes
"s" pour les secondes
"m" pour les minutes
"h" pour les heures
Par exemple, vous pouvez définir le champ de configuration sur 12h45m,
ce qui signifie 12 heures et 45 minutes.
Note:
Cette fonctionnalité ne suit pas l'utilisation des images entre les redémarrages du kubelet. Si le kubelet
est redémarré, l'âge de l'image suivi est réinitialisé, ce qui fait que le kubelet attend la durée complète
imageMaximumGCAge avant de qualifier les images pour la collecte des déchets
en fonction de l'âge de l'image.
Collecte des déchets des conteneurs
Le kubelet collecte les conteneurs inutilisés en fonction des variables suivantes, que vous pouvez définir :
MinAge : l'âge minimum auquel le kubelet peut collecter les
conteneurs. Désactivez en définissant sur 0.
MaxPerPodContainer : le nombre maximum de conteneurs inactifs que chaque Pod
peut avoir. Désactivez en définissant sur une valeur inférieure à 0.
MaxContainers : le nombre maximum de conteneurs inactifs que le cluster peut avoir.
Désactivez en définissant sur une valeur inférieure à 0.
En plus de ces variables, le kubelet collecte les conteneurs non identifiés et
supprimés, généralement en commençant par les plus anciens.
MaxPerPodContainer et MaxContainers peuvent potentiellement entrer en conflit les uns avec les autres
dans des situations où le maintien du nombre maximum de conteneurs par Pod
(MaxPerPodContainer) dépasserait le total autorisé de conteneurs inactifs globaux (MaxContainers). Dans cette situation, le kubelet ajuste
MaxPerPodContainer pour résoudre le conflit. Le pire des cas serait de
réduire MaxPerPodContainer à 1 et d'évacuer les conteneurs les plus anciens.
De plus, les conteneurs appartenant à des pods qui ont été supprimés sont supprimés une fois
qu'ils sont plus anciens que MinAge.
Note:
Le kubelet ne collecte que les conteneurs qu'il gère.
Configuration de la collecte des déchets
Vous pouvez ajuster la collecte des déchets des ressources en configurant des options spécifiques aux
contrôleurs qui gèrent ces ressources. Les pages suivantes vous montrent comment
configurer la collecte des déchets :
Découvrez le contrôleur TTL qui nettoie les Jobs terminés.
9 - Proxy de version mixte
FEATURE STATE:Kubernetes v1.28 [alpha]
Kubernetes 1.31 inclut une fonctionnalité alpha qui permet à un
Serveur API
de faire proxy des demandes de ressources vers d'autres serveurs API pairs. Cela est utile lorsqu'il y a plusieurs
serveurs API exécutant différentes versions de Kubernetes dans un même cluster
(par exemple, pendant un déploiement à long terme vers une nouvelle version de Kubernetes).
Cela permet aux administrateurs de cluster de configurer des clusters hautement disponibles qui peuvent être mis à niveau
plus en toute sécurité, en redirigeant les demandes de ressources (effectuées pendant la mise à niveau) vers le kube-apiserver correct.
Ce proxy empêche les utilisateurs de voir des erreurs 404 Not Found inattendues qui découlent
du processus de mise à niveau.
Ce mécanisme est appelé le Proxy de Version Mixte.
Activation du Proxy de Version Mixte
Assurez-vous que la fonctionnalité UnknownVersionInteroperabilityProxyfeature gate
est activée lorsque vous démarrez le Serveur API :
kube-apiserver \
--feature-gates=UnknownVersionInteroperabilityProxy=true\
# arguments de ligne de commande requis pour cette fonctionnalité--peer-ca-file=<chemin vers le certificat CA de kube-apiserver>
--proxy-client-cert-file=<chemin vers le certificat proxy de l'agrégateur>,
--proxy-client-key-file=<chemin vers la clé proxy de l'agrégateur>,
--requestheader-client-ca-file=<chemin vers le certificat CA de l'agrégateur>,
# requestheader-allowed-names peut être laissé vide pour autoriser n'importe quel nom commun
--requestheader-allowed-names=<noms communs valides pour vérifier le certificat client du proxy>,
# indicateurs facultatifs pour cette fonctionnalité--peer-advertise-ip=`IP de ce kube-apiserver qui doit être utilisée par les pairs pour faire proxy des demandes`--peer-advertise-port=`port de ce kube-apiserver qui doit être utilisé par les pairs pour faire proxy des demandes`# ...et d'autres indicateurs comme d'habitude
Transport et authentification du proxy entre les serveurs API
Le kube-apiserver source réutilise les
indicateurs d'authentification client du serveur API existant--proxy-client-cert-file et --proxy-client-key-file pour présenter son identité qui
sera vérifiée par son pair (le kube-apiserver de destination). Le serveur API de destination
vérifie cette connexion pair en fonction de la configuration que vous spécifiez en utilisant l'argument de ligne de commande
--requestheader-client-ca-file.
Pour authentifier les certificats de service du serveur de destination, vous devez configurer un ensemble de certificats
d'autorité de certification en spécifiant l'argument de ligne de commande --peer-ca-file au serveur API source.
Configuration pour la connectivité des serveurs API pairs
Pour définir l'emplacement réseau d'un kube-apiserver que les pairs utiliseront pour faire proxy des demandes, utilisez les
arguments de ligne de commande --peer-advertise-ip et --peer-advertise-port pour kube-apiserver ou spécifiez
ces champs dans le fichier de configuration du serveur API.
Si ces indicateurs ne sont pas spécifiés, les pairs utiliseront la valeur de --advertise-address ou
--bind-address comme argument de ligne de commande pour le kube-apiserver.
Si ceux-ci ne sont pas définis non plus, l'interface par défaut de l'hôte est utilisée.
Proxy de version mixte
Lorsque vous activez le proxy de version mixte, la couche d'agrégation
charge un filtre spécial qui effectue les opérations suivantes :
Lorsqu'une demande de ressource atteint un serveur API qui ne peut pas servir cette API
(soit parce qu'il s'agit d'une version antérieure à l'introduction de l'API, soit parce que l'API est désactivée sur le serveur API),
le serveur API tente d'envoyer la demande à un serveur API pair qui peut servir l'API demandée.
Il le fait en identifiant les groupes d'API / versions / ressources que le serveur local ne reconnaît pas,
et essaie de faire proxy de ces demandes vers un serveur API pair capable de traiter la demande.
Si le serveur API pair ne parvient pas à répondre, le serveur API source répond avec une erreur 503 ("Service Unavailable").
Comment cela fonctionne en interne
Lorsqu'un serveur API reçoit une demande de ressource, il vérifie d'abord quels serveurs API peuvent
servir la ressource demandée. Cette vérification se fait en utilisant l'API interne
StorageVersion.
Si la ressource est connue du serveur API qui a reçu la demande
(par exemple, GET /api/v1/pods/quelque-pod), la demande est traitée localement.
S'il n'y a pas d'objet StorageVersion interne trouvé pour la ressource demandée
(par exemple, GET /my-api/v1/my-resource) et que l'APIService configuré spécifie le proxy
vers un serveur API d'extension, ce proxy se fait en suivant le flux habituel
flow pour les API d'extension.
Si un objet StorageVersion interne valide est trouvé pour la ressource demandée
(par exemple, GET /batch/v1/jobs) et que le serveur API qui essaie de traiter la demande
(le serveur API de traitement) a l'API batch désactivée, alors le serveur API de traitement
récupère les serveurs API pairs qui servent le groupe d'API / version / ressource pertinent
(api/v1/batch dans ce cas) en utilisant les informations de l'objet StorageVersion récupéré.
Le serveur API de traitement fait ensuite proxy de la demande vers l'un des serveurs kube-apiservers pairs correspondants
qui sont conscients de la ressource demandée.
S'il n'y a aucun pair connu pour ce groupe d'API / version / ressource, le serveur API de traitement
transmet la demande à sa propre chaîne de traitement qui devrait finalement renvoyer une réponse 404 ("Not Found").
Si le serveur API de traitement a identifié et sélectionné un serveur API pair, mais que ce pair échoue
à répondre (pour des raisons telles que des problèmes de connectivité réseau ou une course de données entre la demande
étant reçue et un contrôleur enregistrant les informations du pair dans le plan de contrôle), alors le serveur de traitement
API répond avec une erreur 503 ("Service Unavailable").