Распространение памяти: cgroup memory.usage_in_bytes против RSS внутри контейнера докеров

"Кубернетес" (v1.10.2) говорит, что мой блок (который содержит один контейнер) использует около 5 ГБ памяти. Внутри контейнера RSS больше напоминает 681MiB. Может ли anypony объяснить, как получить от 681MiB до 5GB со следующими данными (или описать, как составить разницу с другой командой, которую я пропустил, либо из контейнера, либо из хоста докеров, который работает с этим контейнером в кубернетах)?

kubectl top pods говорит 5GB:

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

Cadvisor сообщает о том же количестве (возможно, было от немного другого времени, поэтому, пожалуйста, игнорируйте небольшие различия):

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

5309456384 / 1024.0 / 1024 ~= 5063 ~= 5039

Внутри контейнера этот файл, как представляется, содержит информацию о том, где кэдзизор получает свои данные:

% kubectl exec -it myapp-56b947bf6d-2lcr7 bash
[email protected]:/app# cat /sys/fs/cgroup/memory/memory.usage_in_bytes
5309456384

Размер резидентного набора (RSS) внутри контейнера НЕ совпадает (менее 1 ГБ):

[email protected]:/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 в случае, если это полезно:

[email protected]:/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

Раздел памяти из статистики контейнера докеров API:

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
},

Комментарий https://github.com/google/cadvisor/issues/638 утверждает:

Total (memory.usage_in_bytes) = rss + cache

https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt говорит:

usage_in_bytes: Для эффективности, как и другие компоненты ядра, в группе памяти используется определенная оптимизация, чтобы избежать ненужного общего доступа к кешине. use_in_bytes зависит от метода и не показывает "точное" значение использования памяти (и swap), это значение fuzz для эффективного доступа. (Конечно, когда это необходимо, оно синхронизируется.) Если вы хотите узнать более точное использование памяти, вы должны использовать значение RSS + CACHE (+SWAP) в памяти.stat (см. 5.2).

https://docs.docker.com/engine/reference/commandline/stats/#parent-command говорит:

Примечание. В Linux CLI Docker сообщает о потреблении памяти, вычитая использование кэша страниц из общего объема использования памяти. API не выполняет такой расчет, а скорее обеспечивает общее использование памяти и количество из кэша страниц, чтобы клиенты могли использовать данные по мере необходимости.

И действительно, большая часть материала в /sys/fs/cgroup/memory/memory.stat в контейнере отображается в вышеупомянутом ответе api apck apck (небольшие различия - от взятия образцов в другое время, извините):

[email protected]:/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

Информация о памяти от kubectl describe pod <pod>:

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

Вот что говорит pmap внутри контейнера. В этом однострочном я получаю все идентификаторы процессов, нажимаю на них pmap -x и вытаскиваю столбцы Kbytes из результатов pmap. Общий результат - 256 мегабайт (намного меньше, чем ps RSS, частично, я думаю, потому что многие из процессов не возвращают выход из 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 указан на qaru.site/info/13914/.... Он проверяет /proc/$pid/statm и /proc/$pid/smaps. Здесь нет освещения (опять же, кажется, что игнорируются некоторые процессы):

# 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
=================================

Существует еще один вопрос, подобный этому (но с меньшей информацией) при некорректном сообщении о потреблении памяти контейнера с помощью каддизора. Спасибо!

Ответ 1

Похоже, он использует VSZ, Virtual Memory Size, а не RSS. Куберне видит это:

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

ps внутри контейнера при суммировании 5-го столбца (VSZ), говорит:

[email protected]:/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 находится в районе 7 ГБ (не соответствует точно, но он близок), тогда как RSS говорит 665 МБ, поэтому это заставляет меня поверить, что Kubernetes и /sys/fs/cgroup/memory/memory.usage_in_bytes используют что-то в соответствии с VSZ, по крайней мере в этом случае.

Ответ 2

Одна вещь, которую я не видел, чтобы проверить здесь, - это память ядра. Это также учитывается в memory.usage_in_bytes фигуре, но не появляется в memory.stat. Вы можете найти это, посмотрев /sys/fs/cgroup/memory/memory.kmem.usage_in_bytes.

Однажды я увидел аналогичную вещь для одного из наших основных приложений.NET, и я не мог понять, что именно происходит (возможно, утечка памяти в ядре.NET, так как это неуправляемая память, которое наше приложение не контролирует).

Возможно, это еще одна сводка для вас. Это будет зависеть от вашего приложения, было ли это использование нормальным или нет, но с точки зрения групп. Я полагаю, что использование памяти ядра по умолчанию не ограничено.