Dockerコンテナの/var/lib/docker/overlay配下の容量が大きくなって起動できない事象に遭遇したので周辺知識を調べた。
業務でとあるサーバー上のDockerコンテナが立ち上がらなくなってしまう事象に出会った。
原因を先にいうと、Dockerコンテナ内のvar/lib/docker/overlay
配下の容量が肥大化してコンテナのデータ容量が100%になってしまっていた。
色々やって結局先輩エンジニア方が解決してくれたんだけど「そもそもoverlayって何?」って感じで調べたら、この間勉強したLPICの内容も少し絡んでいて面白かったのでまとめてみた。
原因
先程も書いたが、今回の事象の原因は、var/lib/docker/overlay
の容量が大きくなってしまって、データ領域が足りなくなりコンテナが立ち上がらなくなってしまっていた。*1
overlayって何?
で、「overlayってなんぞ?」となったのだけど、やっぱり公式を見るのが一番ということで調べてみたら、DockerのドキュメントにoverlayFS driver
というのがあった。
overlayFSのTL;DR
Dockerイメージはread onlyなlayerを束ねたものなんだけど、それらlayer(一つ一つがファイルシステム)のデータ情報などはoverlayFSという技術を使って管理されている。*2
overlayFSの実態は/var/lib/docker/overlay
もしくは/var/lib/docker/overlay2
配下に集約されていて、一度システムを読み込んでしまえば、キャッシュによるシステム起動も早くなるし、iノードの節約にも繋がって容量がエコになるらしい。
概要を自分用にまとめたのが以下。
- DockerのoverlayFileSystem(以降、overlayFSと略す)はDockerコンテナ上のデータ領域やイメージの情報を管理するファイルシステムのこと。
- OverlayFSという技術自体はDocker特有の物というよりもシステム関連の技術っぽくて、こちらの記事が簡単なまとめをしてくださっていてわかりやすかった。既存で存在しているaufsというものの類似技術で、複数のシステムのファイルとかディレクトリなどを階層構造上に持ち、それぞれを透過的に重ねてマージして一つのシステムとして管理できるシステムのことを言うみたい。
- overlayFSはxfsをサポートしている。LPICにも出てくるのだけど、xfsはシステム操作をjournalに保存する仕組みになっているファイルシステム。つまり、システム操作ログなどはjournalctlコマンドで見れる。
- まあ、正直ふーんという感じだけど、Dockerの公式ドキュメントのイメージ画像がわかりやすかった。
- aufsよりも早くて実装がシンプルらしい。aufsをよく知らないからふーんという感じだけど、まあすごいみたい。
ちなみに現状は
overlay
とoverlay2
の2つのバージョンがあり、自分のコンテナのがどっちを使っているかはdocker info
で見れる。「階層構造上に持つ」とは具体的には、一つのLinuxホストに
upper dir
,lower dir
という2つのディレクトリ構造を持っていて、その2つを統合した(merged
)ディレクトリという構成になっている。このmerged
されたのが一つのシステムとしてマウントされてるらしい。ちなみに、このディレクトリをlayer
と呼んでいる。- で、この階層構造の実態は
/var/lib/docker/overlay
で、ここにlayer
が保存されている。つまり今回はこのlayer
が肥大化したのが原因と言い換えられる。lower dir
: 読み込み専用upper dir
: 書き込み可能merged
: 上2つを統合したレイヤ。効率的なマウントポイント。
- この機能によって何が嬉しいのか?と言うと、Dockerドキュメントにはよると、docker buildやdocker commitなどのレイヤー関連のDockerコマンドのパフォーマンスが向上し、ファイルシステムで消費するiノードが少なくなる。
- ちなみに
iノード
はLPICでも習った。*3 - パフォーマンス向上に関しては、一度mergedされたファイルを読み出してしまえば、システムがキャッシュを使ってくれるので、次からの起動が早くなるということらしい。
- iノードについては、merged layerにあるシステムのiノードに、残りの
lower dir
,upper dir
にあるシステムがハードリンクがされている。ハードリンクされているということはiノードが同じなので、layerが増えてもmerged layerにあるノードだけで済んでiノードの節約ができるという原理みたい。*4 - ちなみに、
df -i
でiノードの利用状況を確認することができる。
- ちなみに
dockerで触ってたときに、モヤモヤしてた所が少しわかった
ここまでまとめて見て、いままでdockerを触っていたときにモヤモヤしていた所が少しだけ分かってきた気がした。
確かにdocker pullとかしたとき、
$ docker pull centos latest: Pulling from centos f1b103484249: Pull complete 23456d61e65: Pull complete 12322fbe74aa5: Already exists centos:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security. Digest: sha256:as334436c65123532ecb7bb790b1db0279668d3763c3b81f31bc6c4e60eooa112 Status: Downloaded newer image for centos:latest
みたいに複数のハッシュ値みたいなのがログに出ていたけど、これがそれぞれlayer
っぽい。なるほどな〜。
ちなみに、このlayerたちはdocker imageの履歴としてdocker history
で確認できる。
で、結局今回の問題はどうやって対処したか?
ドキュメントに不要なオブジェクトの排除方法みたいなのが載っていた。
他にも同じような事象になる質問があって、これらにある情報と同じ感じで先輩エンジニアが docker container prune overlay
で対処してくれて、事なきを得た。
対処後の疑問
この後に「layerがどんどん増えていったら、また将来的にoverlayが肥大化しちゃうから、うまい具合にoverlayを自動で消してくれないかな」とか思ったけど、ドキュメントをよく見ると、
Docker takes a conservative approach to cleaning up unused objects (often referred to as “garbage collection”), such as images, containers, volumes, and networks: these objects are generally not removed unless you explicitly ask Docker to do so.
「dockerは諸々のオブジェクトを掃除してくれるアプローチを持っているけど、それは明示的にコマンドを叩くなどして要求しないと駄目よ」的なことが書いてあった。なるほど。容量がでかくなったら、docker hogehoge prune
するなどしてくれる自動化するのが今後の再発防止策なのかもしれないな〜とか思ったりした。
あとはこちらのスライドも参考にさせてもらったのだけど、overlaysのディレクトリを別システムに移してそちらで管理するとかもできるらしい。なるほどな〜。色々アプローチはありそう。
ちなみに、調べた感じoverlayFSは制限がないので、運用上の注意が必要とのこと。なるほど。容量制限もできないのか。
難しいdockerについてちょっとだけ詳しくなれた日だった。
*1:この記事とよく似た状況と原因だった。
*2:overlayFS以外にもストレージ管理の技術はあるようで、これはそのうちの一つ。cf: Use the OverlayFS storage driver | Docker Documentation
*3:iノートとはファイル属性を格納するもので、ディスク上にファイル情報(アクセス権や所有権)が記録される。すべてのファイルにはこのiノードがあり、これが枯渇すると新しいファイルを作成するなどができなくなります。例えディスクに空き容量があってもiノードが残っていなければ駄目。小さなファイルをたくさん作ると、iノードが枯渇することがある。