web-dev-qa-db-ja.com

メモリ使用量の不一致:cgroup memory.usage_in_bytesとdockerコンテナー内のRSS

「Kubernetes」(v1.10.2)は、私のポッド(1つのコンテナーを含む)が約5GBのメモリを使用していることを示しています。コンテナー内では、RSSは681MiBのように言っています。次のデータで681MiBから5GBに取得する方法を説明できますか(または、コンテナーから、またはこのコンテナーをkubernetesで実行しているDockerホストから、省略した別のコマンドで違いを補う方法を説明できますか)?

kubectlのトップポッドは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

コンテナ内では、このファイルはcadvisorがデータを取得する場所にあるように見えます。

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

コンテナー内の常駐セットサイズ(RSS)が一致しません(1 GB未満):

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:

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

Dockerのコンテナー統計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 に関するコメントは、次のように表明します。

合計(memory.usage_in_bytes)= rss +キャッシュ

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

usage_in_bytes:他のカーネルコンポーネントと同様に、メモリcgroupは、最適化を使用して不要なキャッシュラインの誤った共有を回避します。 usage_in_bytesはメソッドの影響を受け、メモリ(およびスワップ)使用の「正確な」値を表示しません。効率的なアクセスのためのファズ値です。 (もちろん、必要な場合は同期されます。)より正確なメモリ使用量を知りたい場合は、memory.statのRSS + CACHE(+ SWAP)値を使用する必要があります(5.2を参照)。

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

注:Linuxでは、Docker CLIは合計メモリ使用量からページキャッシュ使用量を差し引いてメモリ使用量を報告します。 APIはこのような計算を実行せず、クライアントが必要に応じてデータを使用できるように、合計メモリ使用量とページキャッシュからの量を提供します。

実際、コンテナ内の/sys/fs/cgroup/memory/memory.statにあるもののほとんどは、上記のdocker stats api応答に表示されます(わずかな違いは、別の時間にサンプルを取得することによるものです。申し訳ありません)。

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

kubectl describe pod <pod>のメモリ情報:

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

これがpmapがコンテナ内で言うことです。このワンライナーでは、すべてのプロセスIDを取得し、それらに対してpmap -xを実行して、pmapの結果からKbytes列を取得します。全体の結果は256メガバイトです(多くのプロセスがpmap -xからの出力を返さないため、部分的にはpsのRSSよりもはるかに少ないと思います)。

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.pyhttps://stackoverflow.com/a/133444/6090676 で言及されています。 /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
=================================

cadvisorによるコンテナーメモリ使用量の誤ったレポート に、これと同様の(ただし情報は少ない)別の質問があります。ありがとう!

19
burnettk

ここで確認しなかったのは、カーネルメモリです。これはmemory.usage_in_bytesの図でも説明されていますが、memory.statには含まれていません。 /sys/fs/cgroup/memory/memory.kmem.usage_in_bytesを見るとわかります。

.NETコアアプリケーションの1つで同じようなことが起こっているのを一度見たところ、何が起こっているのか正確に理解できませんでした(おそらく、.NETコアではメモリリークが発生します。

多分それはあなたのためのもう一つのパンくずです。その使用が正常かどうかはアプリケーションに依存しますが、cgroupsに関しては、カーネルメモリの使用はデフォルトでは制約されていないと思います。

5
Chris Gilbert

RSSではなく、VSZ、仮想メモリサイズを使用しているようです。 Kubernetesはこれを認識します。

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

コンテナー内のpsは、5番目の列(VSZ)を合計すると、次のようになります。

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は7GB前後(正確には一致しませんが、近いです)ですが、RSSは665MBと言っているため、Kubernetesと/sys/fs/cgroup/memory/memory.usage_in_bytesは、少なくともこのケースでは、VSZに沿って何かを使用しています。

1
burnettk