Diagnostiquer un fort usage du CPU

Parfois, le démon Docker lui-même (dockerd) prend énormément de CPU tandis que les conteneurs sous-jacents sont plutôt calmes.

Une manière de diagnostiquer le souci est de demander au démon Docker un profil d’utilisation du CPU, par exemple avec la commande suivante :

snippet.bash
curl --unix-socket /var/run/docker.sock http://./debug/pprof/profile --output /tmp/profile

Note:

Docker utilise pprof, un outil permettant de générer et d’analyser des profils de performance.

Pour analyser le profil, il faut installer Golang :

snippet.bash
sudo apt install golang

On peut alors lancer la commande suivante pour voir les fonctions ayant le plus mobilisé le CPU sur le temps d’analyse :

snippet.sh
qduchemi@monitoring:/DATA/docker/services/monitoring$ go tool pprof -top /tmp/profile 
File: dockerd
Build ID: f6c42727f6e1033edb4342311e954f4788899cd2
Type: cpu
Time: Mar 22, 2023 at 3:01pm (CET)
Duration: 30.14s, Total samples = 33.04s (109.61%)
Showing nodes accounting for 28.44s, 86.08% of 33.04s total
Dropped 354 nodes (cum <= 0.17s)
      flat  flat%   sum%        cum   cum%
     5.37s 16.25% 16.25%     10.18s 30.81%  encoding/json.(*Decoder).readValue
     3.50s 10.59% 26.85%      4.12s 12.47%  encoding/json.unquoteBytes
     2.94s  8.90% 35.74%      3.04s  9.20%  encoding/json.stateInString
     1.83s  5.54% 41.28%      2.14s  6.48%  encoding/json.(*decodeState).rescanLiteral
     [...]

A Savoir:

Plein d’autres profils de performance et façon d’analyser sont imaginables. Voir la documentation Golang pour un point de départ).

Dans notre exemple, ce sont des fonction d’encodage/décodage d’objet JSON. Ce sont les logs de Docker qui sont en JSON, il y a donc un souci avec les logs. C’est cohérent avec ce thread sur le sujet.

Dans ce cas spécifique, c’est parce que Promtail lit très souvent les logs en JSON. Docker recommande d'utiliser le module de log local plutôt que JSON, qui a une rotation automatique et utilise un format de fichier plus efficient.

Note:

Seuls les nouveaux conteneurs sont pris en compte pour le changement de driver de log. On peut les recréer depuis /DATA/docker/services avec :

snippet.bash
find . -maxdepth 1 -mindepth 1 -type d -exec docker compose --project-directory {} up -d --force-recreate \;