web-dev-qa-db-fra.com

Écart d'utilisation de la mémoire: cgroup memory.usage_in_bytes vs RSS dans le conteneur Docker

"Kubernetes" (v1.10.2) dit que mon pod (qui contient un conteneur) utilise environ 5 Go de mémoire. À l'intérieur du conteneur, RSS en dit plus comme 681 Mo. Anypony peut-il expliquer comment passer de 681 Mo à 5 Go avec les données suivantes (ou décrire comment combler la différence avec une autre commande que j'ai omise, à partir du conteneur ou de l'hôte docker qui exécute ce conteneur dans kubernetes)?

kubectl top pods dit 5 Go:

% kubectl top pods -l app=myapp
NAME                             CPU(cores)   MEMORY(bytes)
myapp-56b947bf6d-2lcr7           39m          5039Mi

Le conseiller signale un nombre similaire (peut-être d'une époque légèrement différente, veuillez donc ignorer les petites différences)

container_memory_usage_bytes{pod_name=~".*myapp.*"}      5309456384

5309456384 / 1024.0 / 1024 ~= 5063 ~= 5039

À l'intérieur du conteneur, ce fichier semble être l'endroit où le conseiller obtient ses données:

% kubectl exec -it myapp-56b947bf6d-2lcr7 bash
meme@myapp-56b947bf6d-2lcr7:/app# cat /sys/fs/cgroup/memory/memory.usage_in_bytes
5309456384

La taille de l'ensemble résident (RSS) à l'intérieur du conteneur ne correspond PAS (moins de 1 Go):

meme@myapp-56b947bf6d-2lcr7:/app# kb=$(ps aux | grep -v grep | grep -v 'ps aux' | grep -v bash | grep -v awk | grep -v RSS | awk '{print $6}' | awk '{s+=$1} END {printf "%.0f", s}'); mb=$(expr $kb / 1024); printf "Kb: $kb\nMb: $mb\n"
Kb: 698076
Mb: 681

Ps aux complet au cas où cela serait utile:

meme@myapp-56b947bf6d-2lcr7:/app# ps aux | grep -v grep | grep -v 'ps aux' | grep -v bash | grep -v awk
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
meme         1  0.0  0.0 151840 10984 ?        Ss   Jun04   0:29 /usr/sbin/Apache2 -D FOREGROUND
www-data    10  0.0  0.0 147340  4652 ?        S    Jun04   0:00 /usr/sbin/Apache2 -D FOREGROUND
www-data    11  0.0  0.0 148556  4392 ?        S    Jun04   0:16 /usr/sbin/Apache2 -D FOREGROUND
www-data    12  0.2  0.0 2080632 11348 ?       Sl   Jun04  31:58 /usr/sbin/Apache2 -D FOREGROUND
www-data    13  0.1  0.0 2080384 10980 ?       Sl   Jun04  18:12 /usr/sbin/Apache2 -D FOREGROUND
www-data    68  0.3  0.0 349048 94272 ?        Sl   Jun04  47:09 hotapp
www-data   176  0.2  0.0 349624 92888 ?        Sl   Jun04  43:11 hotapp
www-data   179  0.2  0.0 349196 94456 ?        Sl   Jun04  42:20 hotapp
www-data   180  0.3  0.0 349828 95112 ?        Sl   Jun04  44:14 hotapp
www-data   185  0.3  0.0 346644 91948 ?        Sl   Jun04  43:49 hotapp
www-data   186  0.3  0.0 346208 91568 ?        Sl   Jun04  44:27 hotapp
www-data   189  0.2  0.0 350208 95476 ?        Sl   Jun04  41:47 hotapp

Section mémoire de l'API de statistiques de conteneur de docker:

curl --unix-socket /var/run/docker.sock 'http:/v1.24/containers/a45fc651e7b12f527b677e6a46e2902786bee6620484922016a135e317a42b4e/stats?stream=false' | jq . # yields:

"memory_stats": {
  "usage": 5327712256,
  "max_usage": 5368344576,
  "stats": {
    "active_anon": 609095680,
    "active_file": 74457088,
    "cache": 109944832,
    "dirty": 28672,
    "hierarchical_memory_limit": 5368709120,
    "inactive_anon": 1687552,
    "inactive_file": 29974528,
    "mapped_file": 1675264,
    "pgfault": 295316278,
    "pgmajfault": 77,
    "pgpgin": 85138921,
    "pgpgout": 84964308,
    "rss": 605270016,
    "rss_huge": 0,
    "shmem": 5513216,
    "total_active_anon": 609095680,
    "total_active_file": 74457088,
    "total_cache": 109944832,
    "total_dirty": 28672,
    "total_inactive_anon": 1687552,
    "total_inactive_file": 29974528,
    "total_mapped_file": 1675264,
    "total_pgfault": 295316278,
    "total_pgmajfault": 77,
    "total_pgpgin": 85138921,
    "total_pgpgout": 84964308,
    "total_rss": 605270016,
    "total_rss_huge": 0,
    "total_shmem": 5513216,
    "total_unevictable": 0,
    "total_writeback": 0,
    "unevictable": 0,
    "writeback": 0
  },
  "limit": 5368709120
},

Un commentaire sur https://github.com/google/cadvisor/issues/638 affirme:

Total (memory.usage_in_bytes) = rss + cache

https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt dit:

usage_in_bytes: pour plus d'efficacité, comme d'autres composants du noyau, le groupe de mémoire utilise une certaine optimisation pour éviter le faux partage inutile de la cacheline. usage_in_bytes est affecté par la méthode et n'affiche pas la valeur "exacte" de l'utilisation de la mémoire (et du swap), c'est une valeur fuzz pour un accès efficace. (Bien sûr, lorsque cela est nécessaire, il est synchronisé.) Si vous voulez connaître l'utilisation de la mémoire plus exacte, vous devez utiliser la valeur RSS + CACHE (+ SWAP) dans memory.stat (voir 5.2).

https://docs.docker.com/engine/reference/commandline/stats/#parent-command dit:

Remarque: sous Linux, l'interface Docker CLI signale l'utilisation de la mémoire en soustrayant l'utilisation du cache de pages de l'utilisation totale de la mémoire. L'API n'effectue pas un tel calcul mais fournit plutôt l'utilisation totale de la mémoire et la quantité du cache de pages afin que les clients puissent utiliser les données selon les besoins.

Et en effet, la plupart des éléments dans /sys/fs/cgroup/memory/memory.stat dans le conteneur apparaissent dans la réponse api des statistiques de docker ci-dessus (de légères différences sont dues au prélèvement d'échantillons à un autre moment, désolé):

meme@myapp-56b947bf6d-2lcr7:/app# cat /sys/fs/cgroup/memory/memory.stat
cache 119492608
rss 607436800
rss_huge 0
shmem 5525504
mapped_file 1675264
dirty 69632
writeback 0
pgpgin 85573974
pgpgout 85396501
pgfault 296366011
pgmajfault 80
inactive_anon 1687552
active_anon 611213312
inactive_file 32800768
active_file 81166336
unevictable 0
hierarchical_memory_limit 5368709120
total_cache 119492608
total_rss 607436800
total_rss_huge 0
total_shmem 5525504
total_mapped_file 1675264
total_dirty 69632
total_writeback 0
total_pgpgin 85573974
total_pgpgout 85396501
total_pgfault 296366011
total_pgmajfault 80
total_inactive_anon 1687552
total_active_anon 611213312
total_inactive_file 32800768
total_active_file 81166336
total_unevictable 0

Informations sur la mémoire de kubectl describe pod <pod>:

Limits:
  memory:  5Gi
Requests:
  memory:   4Gi

Voici ce que pmap dit à l'intérieur du conteneur. Dans ce one-liner, j'obtiens tous les identifiants de processus, exécute pmap -x sur eux et tire la colonne Kbytes des résultats pmap. Le résultat total est de 256 mégaoctets (beaucoup moins que le RSS de ps, en partie, je pense, car de nombreux processus ne renvoient aucune sortie de pmap -x):

ps aux | awk '{print $2}' | grep -v PID | xargs Sudo pmap -x | grep total | grep -v grep | awk '{print $3}' | awk '{s+=$1} END {printf "%.0f", s}'; echo
256820

ps_mem.py est mentionné à https://stackoverflow.com/a/133444/6090676 . Il inspecte /proc/$pid/statm et /proc/$pid/smaps. Pas d'éclairage ici (encore une fois, il semble ignorer certains processus):

# python ps_mem.py
Private  +   Shared  =  RAM used    Program

  1.7 MiB +   1.0 MiB =   2.7 MiB   Apache2
  2.0 MiB +   1.0 MiB =   3.0 MiB   bash (3)
---------------------------------
                          5.7 MiB
=================================

Il y a une autre question similaire à celle-ci (mais avec moins d'informations) à Rapport incorrect de l'utilisation de la mémoire du conteneur par cadvisor . Merci!

15
burnettk

Une chose que je ne vous ai pas vue vérifier ici est la mémoire du noyau. Ceci est également comptabilisé dans le memory.usage_in_bytes figure, mais n'apparaît pas dans memory.stat. Vous pouvez le constater en consultant /sys/fs/cgroup/memory/memory.kmem.usage_in_bytes.

J'ai vu une chose similaire se produire pour l'une de nos applications .NET core, une fois, et je n'ai pas pu comprendre ce qui se passait exactement (peut-être une fuite de mémoire dans .NET core car c'est de la mémoire non gérée que notre application ne contrôle pas).

C'est peut-être un autre fil d'Ariane pour vous. Cela dépendrait de votre application, que cette utilisation soit normale ou non, mais en termes de groupes de contrôle, je pense que l'utilisation de la mémoire du noyau n'est pas limitée par défaut.

5
Chris Gilbert

Il semble qu'il utilise VSZ, la taille de la mémoire virtuelle, pas RSS. Kubernetes voit ceci:

% kubectl top pods -l app=myapp
NAME                             CPU(cores)   MEMORY(bytes)
myapp-7b4b4f84f8-fxbns           39m          7136Mi

ps à l'intérieur du conteneur, lors de la sommation de la 5ème colonne (VSZ), dit:

meme@myapp-7b4b4f84f8-fxbns:/app# kb=$(ps aux | grep -v grep | grep -v 'ps aux' | grep -v bash | grep -v awk | grep -v RSS | awk '{print $5}' | awk '{s+=$1} END {printf "%.0f", s}'); mb=$(expr $kb / 1024); printf "Kb: $kb\nMb: $mb\n"
Kb: 7032172
Mb: 6867

VSZ est dans le voisinage de 7 Go (ne correspond pas exactement, mais il est proche), tandis que RSS indique 665 Mo, donc cela me fait croire Kubernetes et /sys/fs/cgroup/memory/memory.usage_in_bytes utilise quelque chose comme VSZ, au moins dans ce cas.

1
burnettk