Nous avons récemment transféré notre environnement de production à Kubernetes. Je voudrais appliquer les limites du processeur sur les conteneurs. Je reçois des métriques de CPU conflictuelles qui ne vont pas ensemble. Voici ma configuration:
- Agents DataDog s'exécutant en tant que
Daemonset
- Applications existantes fonctionnant sans limites de CPU
- Les conteneurs en question sont des applications Ruby multithread
- Deux mesures:
kubernetes.cpu.usage.{avg,max}
etdocker.cpu.usage
c4.xlarge
nœuds de cluster (4 vCPU ou 4000 m en termes de Kubernetes)
kubernetes.cpu.usage.max
signale ~ 600m pour les conteneurs en question. docker.cpu.usage
rapports ~ 60%. Il s'ensuit qu'une limite de 1 000 m de processeur serait plus que suffisante en fonctionnement normal.
J'ai fixé la limite à 1000m. Puis docker.container.throttles
monte de manière significative tout kubernetes.cpu.usage.max
et docker.cpu.usage
reste le même. Le système tombe à genoux pendant cette période. Cela n'a pas de sens pour moi.
J'ai recherché les statistiques de Docker. Il semble que docker stats
(et l'API sous-jacente) normalisent la charge en fonction des cœurs de processeur. Donc dans mon cas, docker.cpu.usage
de 60% vient (4000m * 0,60) à 2400m en termes Kubernetes. Cependant, cela ne correspond à aucun nombre de Kubernetes. J'ai fait une autre expérience pour tester mon hypothèse que les nombres de Kubernetes sont incorrects. J'ai fixé la limite à 2600 m (pour une marge supplémentaire). Cela n'a entraîné aucun étranglement. Cependant, Kubernetes a observé que l'utilisation du processeur n'a pas changé. Cela me laisse confus.
Mes questions sont donc:
- Est-ce que cela ressemble à un bug dans Kubernetes (ou quelque chose dans la pile?)
- Ma compréhension est-elle correcte?
Ma question de suivi concerne la façon de déterminer correctement le CPU pour les applications Ruby. Un conteneur utilise Puma. Il s'agit d'un serveur Web multithread avec une quantité configurable de threads. Les requêtes HTTP sont gérées par l'un des threads. La deuxième application est un serveur d'épargne utilisant le serveur fileté. Chaque connexion TCP entrante est gérée par son propre thread. Le thread se ferme à la fermeture de la connexion. Ruby comme GIL (Global Interpreter Lock) donc un seul thread peut exécuter du code Ruby à la fois. Cela permet à plusieurs threads d'exécuter des E / S et des choses comme ça.
Je pense que la meilleure approche est de limiter le nombre de threads en cours d'exécution dans chaque application et d'approcher les limites du processeur Kubernetes en fonction du nombre de threads. Les processus ne bifurquent pas, donc l'utilisation totale du processeur est plus difficile à prévoir.
La question ici est: comment prévoir correctement l'utilisation du processeur et les limites de ces applications?