Dockerized環境で実行されているWebサーバーが予想以上に多くのメモリを消費する理由を確認しようとしています。この問題の調査中に理解できない次の動作が見つかりました。
- Dockerコンテナを作成し、
docker run -d --name test ubuntu:22.04 tail -f /dev/null
- 確認すると、
docker stats
メモリ使用量が次のように報告されます。400KiB / 62.68GiB
- 確認してください
docker top test
。 1つのプロセスのみが実行されています(tail -f /dev/null
)。 - これで、実行中のコンテナに多数のファイルとディレクトリを作成します。
docker exec -it test sh -c 'apt update && apt install -y git && git clone https://git.savannah.gnu.org/git/emacs.git'
- もう一度確認すると、
docker stats
メモリ使用量が次のように報告されます。494.9MiB / 62.68GiB
docker top test
まだ1つのプロセスのみが実行されていることを確認してください()tail -f /dev/null
。
では、Dockerコンテナ内の約500MBのメモリはどのような用途に使用されますか?私の考えでは、プロセスはメモリを消費しますが、コンテナにはプロセスが1つだけあり、責任を負うことはできません。
ファイルシステムでメモリ使用量が発生しますか?ホストシステムがbtrfsを実行しています。 Dockerのデフォルトのストレージドライバを使用しておりoverlay2
、ファイルシステムのオーバーライドに関する情報は次のとおりです。
% docker inspect test | jq '.[].GraphDriver.Data.MergedDir' -r
/var/lib/docker/overlay2/559d41c89d074c45a1ae89109ebec145e8fd4d929151819f08aaae26f73f7bda/merged
% mount | grep overlay
overlay on /var/lib/docker/overlay2/559d41c89d074c45a1ae89109ebec145e8fd4d929151819f08aaae26f73f7bda/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/JADZ5UYJDWI5EDAAGALCRWUM3B:/var/lib/docker/overlay2/l/JK3H4JAYNUAUSN2W3V2DQ6TB6C,upperdir=/var/lib/docker/overlay2/559d41c89d074c45a1ae89109ebec145e8fd4d929151819f08aaae26f73f7bda/diff,workdir=/var/lib/docker/overlay2/559d41c89d074c45a1ae89109ebec145e8fd4d929151819f08aaae26f73f7bda/work)
% sudo ls -lAd /var/lib/docker/overlay2/l/JADZ5UYJDWI5EDAAGALCRWUM3B/emacs
ls: cannot access '/var/lib/docker/overlay2/l/JADZ5UYJDWI5EDAAGALCRWUM3B/emacs': No such file or directory
% sudo ls -lAd /var/lib/docker/overlay2/l/JK3H4JAYNUAUSN2W3V2DQ6TB6C/emacs
ls: cannot access '/var/lib/docker/overlay2/l/JK3H4JAYNUAUSN2W3V2DQ6TB6C/emacs': No such file or directory
% sudo ls -lAd /var/lib/docker/overlay2/559d41c89d074c45a1ae89109ebec145e8fd4d929151819f08aaae26f73f7bda/diff/emacs
drwxr-xr-x 1 root root 602 Feb 25 16:08 /var/lib/docker/overlay2/559d41c89d074c45a1ae89109ebec145e8fd4d929151819f08aaae26f73f7bda/diff/emacs
% sudo ls -lAd /var/lib/docker/overlay2/559d41c89d074c45a1ae89109ebec145e8fd4d929151819f08aaae26f73f7bda/merged/emacs
drwxr-xr-x 1 root root 602 Feb 25 16:08 /var/lib/docker/overlay2/559d41c89d074c45a1ae89109ebec145e8fd4d929151819f08aaae26f73f7bda/merged/emacs
/var/lib/docker/overlay2/559d41c89d074c45a1ae89109ebec145e8fd4d929151819f08aaae26f73f7bda/diff
私のデフォルトのファイルシステムはbtrfsなので、複製されたGitストレージは特別なボリュームマウントの内部ではないため、メモリを消費しないbtrfs(btrfsの下)のディスクにあると予想しています。
たとえば、追加されたファイルとディレクトリを削除すると、docker exec test rm -rf emacs
メモリ使用量はすぐに68.16 MiB / 62.68GiB
。
質問:
- このメモリを消費するものは何ですか?
overlay2
作業階層にファイルとディレクトリを追加すると、メモリを消費しないようにするDockerコンテナまたはファイルシステムについてどのような誤解がありますか? - Dockerデーモンまたはコンテナ化されたワークロードを使用して構成を変更して、プロセスRAM以外のソースからDockerコンテナで消費されるメモリ量を減らす方法はありますか?
UNIX Stack Exchangeの[docker]タグの下にある既存の質問を調べましたが、理解するのに役立つ質問が見つかりませんでした。私も読んだoverlayfsの公式Dockerドキュメントそして簡単にレビューしましたLinuxカーネルのoverlayfsに関するドキュメントただし、メモリ使用量を説明できる項目が見つかりませんでした。
私の究極の目標は、CPUとメモリ使用量に基づいて課金されるため、本番環境で実行されるアイドルDockerizedワークロードのリソース消費を減らすことです。実稼働指標によれば、そのメモリを使用するプロセスが終了したにもかかわらず、アイドル状態でワークロードがメモリを大量に確保できないことがわかりました。
上記のテストは、btrfsを使用してDocker CE 23.0.1およびLinuxカーネル6.0.12がインストールされているPop!_OS 22.04で行われました。
私のbtrfsのシステムパラメータ
/etc/fstab
ファイルシステムのマウントオプションを表示します。デフォルトでは、すべての項目のデフォルト値は次のとおりです。
UUID=ee43bc7e-1d9d-4300-a46a-5d2d772a1e0f / btrfs defaults,subvol=@ 0 0
UUID=ee43bc7e-1d9d-4300-a46a-5d2d772a1e0f /.snapshots btrfs defaults,subvol=@snapshots 0 0
UUID=127d5704-324b-4a50-97bf-9f5f4646ddd5 /home/raxod502 btrfs defaults,subvol=@ 0 0
UUID=127d5704-324b-4a50-97bf-9f5f4646ddd5 /home/raxod502/.snapshots btrfs defaults,subvol=@snapshots 0 0
以下を使用して自動的にスナップショットを撮ります。ドミ、私の保存方針は合計約100を維持します。
% sudo snapper -c system list | wc -l
41
% sudo snapper -c home list | wc -l
44
私は引用リンクを明示的に使用したことがなく、自動的に引用リンクを生成するソフトウェアもありません。上記のように、btrfsの最も進化した用途はスナッパーです。
出力は次のとおりですsudo slaptop -o
。https://gist.github.com/raxod502/843a6580dc6fa0f9949d2f4dc03b5c23
役立つ可能性がある追加のシステム構成の詳細を提供します。
ext4比較
他のLinuxシステムのext4で同じテストを実行しましたが、ほぼ同じ結果が得られました。複製前のメモリ使用量はです328KiB / 969.4MiB
。複製後のメモリ使用量はです233.5MiB / 969.4MiB
。複製されたストレージを削除した後のメモリ使用量はです16.84MiB / 969.4MiB
。
ベストアンサー1
これはファイルシステムに関連するのではなく、ファイルキャッシュに関連しているようです。この正確な状況を再現するために、まずEmacsリポジトリを/usr/src/emacs
。
$ docker run --mount type=bind,source=/usr/src/emacs/.git,destination=/mnt/emacs.git,ro -d --rm --name test debian tail -f /dev/null
$ docker exec -it test sh -c 'apt update && apt install -y git && git clone /mnt/emacs.git'
$ docker stats --no-stream test
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c468a203b9d2 test 0.00% 46.91MiB / 15.52GiB 0.30% 30.5MB / 667kB 0B / 786MB 1
私の場合、約500MiBのメモリ使用量を取得できませんでした。ファイルシステムに関連していると推測されます。ただし、要点は、最終メモリ使用量がネットワーク上で複製するときとほぼ同じであることです。次に作成されたディレクトリを削除する/emacs
と、メモリ使用量が減少しました。
$ docker exec -it test rm -rf /emacs
$ docker stats --no-stream test
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c468a203b9d2 test 0.00% 15.84MiB / 15.52GiB 0.10% 30.5MB / 667kB 0B / 786MB 1
これがファイルシステムに関連しているかどうかをテストするために、レプリケーション部分をスキップし、同じインストール内の別のディレクトリからmv
そのディレクトリにアクセスしてみました。コンテナのオーバーレイ親ディレクトリと同じブロックデバイスマウントにあるとemacs
します。/usr/src/emacs
$ docker run -d --rm --name test debian tail -f /dev/null
$ TEST_UPPER=$(docker container inspect --format '{{.GraphDriver.Data.UpperDir}}' test)
$ mv -v /usr/src/emacs "$TEST_UPPER/emacs"
renamed '/usr/src/emacs' -> '/var/lib/docker/overlay2/dc228a74029510c61ce454549248132bec806686c4da9eac8909d89595ff5a32/diff/emacs'
$ docker stats --no-stream test
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
e700998acb86 test 0.00% 400KiB / 15.52GiB 0.00% 3.79kB / 866B 0B / 0B 1
繰り返しますが、docker cp
ルートのコンテナディレクトリに-ingします。
$ docker run -d --rm --name test debian tail -f /dev/null
$ docker exec -it test mkdir /emacs
$ tar -C /usr/src/emacs -c . | docker cp - test:/emacs
$ docker exec -i ls -la /emacs | wc -l
42
$ docker stats --no-stream test
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
4ea520193998 test 0.00% 444KiB / 15.52GiB 0.00% 3.79kB / 866B 0B / 0B 1
これに基づいて、すべてのメモリ使用量はapt
キャッシュメモリを使用したようですgit
。アドバイスは簡単です。実行時にコンテナを変更しないでください。