Généralement en raison d’un manque de ressources dans Kubernetes, les pods sont évincés (Evicted Pods). Mais pourquoi cela arrive-t-il ? Et qu’est-ce que ca signifie ?
L’expulsion est un processus par lequel un nœud résilie un pod lui est affecter . L’un des cas les plus courants dans Kubernetes est la préemption , où pour planifier un nouveau pod dans un nœud avec des ressources limitées, un autre pod est résilier pour laisser des ressources au premier.
De plus, Kubernetes vérifie constamment les ressources et expulse les Pods si nécessaire, un processus appelé Node-pressure eviction .
Les Raisons d’expulsions des pods : ( préemption et pression de nœud )
Il existe plusieurs raisons pour lesquelles l’éviction d’un pod (Evicted Pods) peut se produire dans Kubernetes. Les plus importants sont :
- Préemption
- Éviction par pression de nœud
Expulsion par préemption
La préemption est le processus suivant : si un nouveau pod doit être planifié mais qu’il n’y a pas de nœud approprié avec suffisamment de ressources, kube-scheduler vérifiera si en évinçant (terminant) certains pods avec une priorité inférieure, le nouveau pod peut faire partie de ce nœud.
Comprenons d’abord comment fonctionne la planification Kubernetes.
Planification des pods ( Pod Scheduling )
L’ordonnancement Kubernetes est le processus par lequel les pods sont affectés aux nœuds.
Par défaut, une entité Kubernetes responsable de l’ordonnancement, appelée kube-scheduler, s’exécute dans le plan de contrôle. Le pod démarre dans l’état Pending jusqu’à ce qu’un nœud correspondant soit trouvé.
Le processus d’affectation d’un Pod à un Node suit cette séquence :
Filtrage
Notation
Filtration ( Filtering )
Au cours de l’étape de filtrage, kube-scheduler sélectionne tous les nœuds où placer le pod. Avec la prise en compte des caractéristiques comme les Taints et les Tolerations.
Une fois cette étape terminée, il obtiendra une liste de nœuds appropriés pour ce pod.
Notation ( Scoring )
Au cours de l’étape de notation, kube-scheduler prend la liste obtenue à l’étape précédente et attribue un score à chacun des nœuds. De cette façon, les nœuds candidats se classe du plus approprié au moins. Dans le cas où deux nœuds ont le même score, kube-scheduler les ordonne de manière aléatoire.
Mais que se passe-t-il s’il n’y a pas de nœuds appropriés pour l’exécution d’un pod ? Dans ce cas, Kubernetes lance le processus de préemption, en essayant d’expulser les Pods de moindre priorité afin d’attribuer le nouveau Pod.
Pod Priority Classes
Comment puis-je empêcher l’éviction d’un pod (Evicted Pods) particulier en cas de processus de préemption ? Il y a de fortes chances qu’un Pod spécifique soit critique pour vous et ne doive jamais être éliminé.
C’est pourquoi Kubernetes propose des classes de priorité.
Une classe de priorité est un objet Kubernetes qui nous permet d’associer des valeurs numériques de priorité à des pods spécifiques. Ceux qui ont une valeur plus élevée sont classés comme plus importants et moins susceptibles d’être expulsés.
Vous pouvez interroger les classes de priorité actuelles en utilisant :
kubectl get priorityclasses kubectl get pc NOM VALEUR GLOBAL-DEFAULT AGE system-cluster-critical 2000000000 false 2d system-node-critical 2000001000 false 2d
Exemple de classe prioritaire
Faisons un exemple pratique en utilisant les fruits et legumes :
Il y a trois Cosse représentant la tomate, le poivre et la fraise :
NAME READY STATUS RESTARTS AGE poivre 1/1 Running 0 4h41m fraise 1/1 Running 0 58m tomate 1/1 Running 0 5h22m
Et il y a deux classes de priorité : truefruit et falsefruit. La première aura une valeur plus élevée indiquant une plus grande priorité.
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: truefruit value: 1000000 globalDefault: false description: "This is a true fruit" apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: falsefruit value: 5000 globalDefault: false description: "This is a false fruit"
La fraise aura la classe de priorité truefruit (valeur = 1000000).
La tomate et le poivre auront toutes deux la classe de priorité falseberry (valeur = 5000).
Cela signifie qu’en cas de préemption, tomate et poivre sont plus susceptibles d’être expulsées pour laisser la place à des Pods plus prioritaires.
Attribuez ensuite les classes de priorité aux Pods en ajoutant ceci à la définition du Pod :
priorityClassName: truefruit
Essayons maintenant d’ajouter trois autres fruits, mais avec une particularité. Tous les nouveaux fruits contiendront la classe de priorité supérieure appelée truefruit.
Comme les trois nouveaux fruits ont des besoins en mémoire ou en CPU que le nœud ne peut satisfaire, kubelet expulse tous les Pods ayant une priorité inférieure à celle des nouveaux fruits. Fraise reste en fonctionnement car il a la classe de priorité la plus élevée.
NAME READY STATUS RESTARTS AGE ananas 0/1 ContainerCreating 0 2s fraise 1/1 Running 0 4h42m tomate 0/1 Terminating 0 59m poivre 0/1 Terminating 0 5h23m banane 0/1 ContainerCreating 0 2s orange 0/1 ContainerCreating 0 2s
Voilà le résultat final :
NAME READY STATUS RESTARTS AGE banane 1/1 Running 0 3s fraise 1/1 Running 0 4h43m ananas 1/1 Running 0 3s orange 1/1 Running 0 3s
Node-pressure eviction
Outre la préemption, Kubernetes vérifie constamment les ressources du nœud, comme la pression du disque, le CPU ou l’absence de mémoire (OOM).
Si la consommation d’une ressource (comme le CPU ou la mémoire) dans le nœud atteint un certain seuil, Kubelet commence à expulser des pods (Evicted Pods) afin de libérer la ressource. La qualité de service (QoS) sera prise en compte pour déterminer l’ordre d’éviction.
Quality of Service Classes
Dans Kubernetes, les pods se voient attribuer l’une des trois classes de qualité de service, qui définissent la probabilité qu’ils soient expulsés en cas de manque de ressources, de la moins probable à la plus probable :
- Guaranteed
- Burstable
- BestEffort
Comment ces classes de QoS sont-elles attribuées aux Pods ? Cette attribution est basée sur les limites et les demandes de CPU et de mémoire. Pour rappel :
- Limits: quantité maximale d’une ressource qu’un conteneur peut utiliser.
- Requests: quantité minimale de ressources souhaitée pour qu’un conteneur puisse fonctionner.
Guaranteed
Un pod se voit attribuer une classe de QoS de Guaranteed if :
- Tous les conteneurs du Pod ont à la fois des Limites et des Requêtes définies pour le CPU et la mémoire.
- Tous les conteneurs du Pod ont la même valeur pour la limite de CPU et la demande de CPU.
- Tous les conteneurs du Pod ont la même valeur pour la limite de mémoire et la demande de mémoire.
Un Pod garanti ne sera pas expulser dans des circonstances normales pour allouer un autre Pod dans le nœud.
Burstable
Un Pod est assigner avec une classe de QoS de Burstable si :
- Il n’a pas la classe de QoS de Guaranteed.
- Des limites ou des requêtes sont définies pour un conteneur dans le pod.
Un Pod Burstable peut ce faire expulser, mais moins probablement que la catégorie suivante.
BestEffort
Un Pod se verra attribuer une classe de QoS de BestEffort si :
- Aucune limite ni demande n’est définie pour aucun conteneur du Pod.
Les pods BestEffort ont le plus de chances de ce faire expulser en cas de processus de pression sur le nœud.
Comme mentionner, les classes de QoS sont prises en compte pour l’éviction de la pression des nœuds. Voici le processus qui se déroule en interne.
Le kubelet classe les pods à évincer dans l’ordre suivant :
- Pods BestEffort ou Pods Burstables dont l’utilisation dépasse les demandes.
- Pods stables dont l’utilisation est inférieure aux demandes ou Pods garantis.
Kubernetes essaiera d’expulser les pods du groupe 1 avant ceux du groupe 2.
Quelques points à retenir de ce qui précède :
- Si vous ajoutez des demandes très faibles dans vos conteneurs, leur Pod sont probablement affecter au groupe 1, ce qui signifie qu’il est plus susceptible ce faire évincer.
- Vous ne pouvez pas savoir quel Pod spécifique est expulser, mais Kubernetes essaiera d’expulser ceux du groupe 1 avant ceux du groupe 2.
- Les pods garantis sont généralement à l’abri de l’expulsion : Kubelet ne les expulsera pas pour programmer d’autres pods. Mais si certains services du système ont besoin de plus de ressources, la kubelet mettra fin aux pods garantis si nécessaire, toujours avec la priorité la plus basse.
Autres types d’expulsion
Cet article se concentre sur la préemption et l’expulsion par pression des nœuds, mais les pods sont expulser (Evicted Pods) d’autres manières. En voici quelques exemples :
API-initiated eviction
Vous pouvez demander l’éviction à la demande d’un pod dans l’un de vos nœuds en utilisant l’API d’éviction Kubernetes.
Taint-based eviction
Les taches et les tolérances de Kubernetes vous permettent de déterminer comment vos pods seront affecter aux nœuds. Mais si vous appliquez une tare NoExecute à un nœud existant, tous les pods qui ne la tolèrent pas sont immédiatement expulser.
Node drain
Il arrive que des nœuds deviennent inutilisables ou que vous ne vouliez plus travailler dessus. La commande kubectl cordon empêche de programmer de nouveaux Pods dessus, mais il y a aussi la possibilité de vider complètement tous les Pods actuels en une seule fois. Si vous exécutez kubectl drain nom de nœud, tous les Pods du nœud vont être expulser, en respectant sa période de terminaison gracieuse.
Conclusion
Comme vous pouvez le constater, l’éviction est une autre fonctionnalité de Kubernetes qui vous permet de contrôler des ressources limitées : dans ce cas, les nœuds que les Pods utiliseront.
Pendant la préemption, Kubernetes va essayer de libérer des ressources en expulsant les Pods (Evicted Pods) moins prioritaires pour en programmer un nouveau. Avec les classes de priorité, vous pouvez contrôler quels Pods sont les plus susceptibles de continuer à fonctionner après la préemption, car il y a moins de chance qu’ils soient expulsés.
Pendant l’exécution, Kubernetes vérifie la pression des nœuds et expulse les pods si nécessaire. Avec les classes QoS, vous pouvez contrôler quels Pods sont les plus susceptibles d’être expulsés en cas de pression sur les nœuds.
La mémoire et le CPU sont des ressources importantes dans vos nœuds, et vous devez configurer vos pods, conteneurs et nœuds pour qu’ils en utilisent la bonne quantité. Si vous gérez ces ressources en conséquence, vous pourrez non seulement réduire les coûts, mais aussi vous assurer que les processus importants continueront à fonctionner, quoi qu’il arrive.