Распространение памяти: 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, так как это неуправляемая память, которое наше приложение не контролирует).
Возможно, это еще одна сводка для вас. Это будет зависеть от вашего приложения, было ли это использование нормальным или нет, но с точки зрения групп. Я полагаю, что использование памяти ядра по умолчанию не ограничено.