Devriez-vous définir des limites de processeur Kubernetes ?
La gestion des ressources disponibles pour vos pods et conteneurs est une bonne pratique pour l’administration de Kubernetes. Vous devez empêcher les pods de consommer avidement le processeur et la mémoire de votre cluster. Une utilisation excessive par un ensemble de pods peut entraîner des conflits de ressources qui ralentissent les conteneurs voisins et déstabilisent vos hôtes.
Cependant, la gestion des ressources Kubernetes est souvent mal comprise. Deux mécanismes sont fournis pour contrôler les allocations : les demandes et les limites. Cela conduit à quatre paramètres possibles par pod, si vous définissez une demande et une limite pour le processeur et la mémoire.
Suivre ce chemin simple est généralement sous-optimal : les limites du processeur sont mieux omises car elles nuisent aux performances et gaspillent la capacité de réserve. Cet article explique le problème afin que vous puissiez exécuter un cluster plus efficace.
Sommaire
Fonctionnement des demandes et des limites
Les demandes sont utilisées pour la planification. Les nouveaux pods ne seront attribués qu’aux nœuds qui peuvent satisfaire leurs demandes. S’il n’y a pas de nœud correspondant, le pod restera dans l’état En attente jusqu’à ce que les ressources soient disponibles.
Les limites définissent l’utilisation maximale des ressources autorisée pour le pod. Lorsque la limite est atteinte, le pod ne peut plus utiliser la ressource, même s’il y a de la capacité de réserve sur son nœud. L’effet réel de l’atteinte de la limite dépend de la ressource concernée : le dépassement d’une contrainte CPU entraîne une limitation, tandis que le dépassement d’une limite de mémoire entraînera l’arrêt des processus de conteneur par le tueur de MOO de pod.
Dans l’exemple suivant, un Pod avec ces contraintes seulement programme aux nœuds pouvant fournir 500 m (équivalent à 0,5 cœurs de processeur). Sa consommation d’exécution maximale peut aller jusqu’à 1 000 m avant l’étranglement si le nœud a de la capacité disponible.
resources: requests: cpu: 500m limits: cpu: 1000m
Pourquoi les limites du processeur sont dangereuses
Pour comprendre pourquoi les limites de CPU sont problématiques, réfléchissez à ce qui se passe si un pod avec les paramètres de ressources indiqués ci-dessus (requête de 500 m, limite de 1 000 m) est déployé sur un nœud quadricœur avec une capacité de CPU totale de 4 000 m. Par souci de simplicité, il n’y a pas d’autres pods en cours d’exécution sur le nœud.
$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE demo-pod 1/1 Running 0 1m 10.244.0.185 quad-core-node
Le Pod planifie immédiatement sur le Node car la demande de 500m est immédiatement satisfaite. Le pod passe à l’état Running. La charge pourrait être faible avec une utilisation du processeur d’environ quelques centaines de millicœurs.
Ensuite, il y a un pic de trafic soudain : les demandes affluent et l’utilisation effective du processeur du pod grimpe jusqu’à 2 000 m. En raison de la limite du processeur, cela est limité à 1000 m. Cependant, le nœud n’exécute aucun autre pod, il pourrait donc fournir les 2000 m complets, si le pod n’était pas limité par sa limite.
La capacité du nœud a été gaspillée et les performances du pod réduites inutilement. L’omission de la limite de CPU permettrait au Pod d’utiliser la totalité des 4000 m, répondant potentiellement à toutes les demandes jusqu’à quatre fois plus rapidement.
Aucune limite empêche toujours l’accaparement des ressources de pod
L’omission des limites de CPU ne compromet pas la stabilité, à condition que vous ayez défini des requêtes appropriées sur chaque pod. Lorsque plusieurs pods sont déployés, la part de temps CPU de chaque pod est mise à l’échelle proportionnellement à sa demande.
Voici un exemple de ce qui arrive à deux pods sans limites lorsqu’ils sont déployés sur un nœud à 8 cœurs (8 000 m) et que chacun nécessite simultanément une consommation de processeur de 100 % :
1 | 500m | 100% | 2000m |
2 | 1500m | 100% | 6000m |
Si le Pod 1 est dans une période plus calme, alors le Pod 2 est libre d’utiliser encore plus de cycles CPU :
1 | 500m | 20% | 400m |
2 | 1500m | 100% | 7600m |
Les requêtes CPU sont toujours importantes
Ces exemples montrent pourquoi les requêtes CPU sont importantes. La définition de requêtes appropriées empêche les conflits en garantissant que les pods ne planifient que les nœuds qui peuvent les prendre en charge. Il garantit également une distribution pondérée des cycles de processeur disponibles lorsque plusieurs pods connaissent une demande accrue.
Les limites du processeur n’offrent pas ces avantages. Ils ne sont utiles que dans les situations où vous souhaitez limiter un pod au-dessus d’un certain seuil de performances. C’est presque toujours un comportement indésirable; vous affirmez que vos autres pods seront toujours occupés, alors qu’ils pourraient être inactifs et créer des cycles de processeur de rechange dans le cluster.
Ne pas fixer de limites permet à ces cycles d’être utilisés par toute charge de travail qui en a besoin. Cela se traduit par de meilleures performances globales car le matériel disponible n’est jamais gaspillé.
Qu’en est-il de la mémoire ?
La mémoire est gérée dans Kubernetes en utilisant les mêmes concepts de demande et de limite. Cependant, la mémoire est une ressource physiquement différente de l’utilisation du processeur qui nécessite sa propre méthode d’allocation. La mémoire est non compressible : elle ne peut pas être révoquée une fois allouée à un processus de conteneur. Les processus partagent le processeur au fur et à mesure qu’il devient disponible, mais ils reçoivent des portions de mémoire individuelles.
La définition d’une demande et d’une limite identiques est l’approche recommandée pour la gestion de la mémoire Kubernetes. Cela vous permet d’anticiper de manière fiable la consommation totale de mémoire de tous les pods de votre cluster.
Il peut sembler logique de définir une demande relativement faible avec une limite beaucoup plus élevée. Cependant, utiliser cette technique pour de nombreux pods peut avoir un effet déstabilisant : si plusieurs pods dépassent leurs requêtes, la capacité de mémoire de votre cluster pourrait être épuisée. Le tueur de MOO interviendra pour mettre fin aux processus de conteneur, ce qui pourrait perturber vos charges de travail. N’importe lequel de vos pods pourrait être ciblé pour l’expulsion, pas seulement celui qui a provoqué l’épuisement de la mémoire.
L’utilisation de demandes et de limites égales empêche un pod de planifier à moins que le nœud ne puisse fournir la mémoire dont il a besoin. Il impose également que le pod ne puisse pas utiliser plus de mémoire que son allocation explicite, éliminant ainsi le risque de surutilisation lorsque plusieurs pods dépassent leurs demandes. La surutilisation deviendra apparente lorsque vous essayez de planifier un pod et qu’aucun nœud ne peut satisfaire la demande de mémoire. L’erreur se produit plus tôt et de manière plus prévisible, sans impact sur les autres pods.
Sommaire
Kubernetes vous permet de distinguer la quantité de ressources qu’un conteneur a besoinet une borne supérieure qu’il est autorisé à mettre à l’échelle mais ne peut pas dépasser. Cependant, ce mécanisme est moins utile en pratique qu’il n’y paraît à première vue.
La définition de limites de CPU empêche vos processus d’utiliser la capacité de CPU disponible au fur et à mesure qu’elle devient disponible. Cela limite inutilement les performances lorsqu’un pod peut utiliser temporairement des cycles dont aucun voisin n’a besoin.
Utilisez une requête CPU raisonnable pour empêcher la planification des pods sur des nœuds déjà trop occupés pour fournir de bonnes performances. Laissez le champ de limite non défini afin que les pods puissent accéder à des ressources supplémentaires lors de l’exécution de tâches exigeantes à des moments où la capacité est disponible. Enfin, attribuez à chaque pod une demande et une limite de mémoire, en veillant à utiliser la même valeur pour les deux champs. Cela empêchera l’épuisement de la mémoire, créant un environnement de cluster plus stable et prévisible.