新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。気づけば社会人3年目に突入。

学習記録:Docker

第4章 Dockerの内部構造と関連ツール

Atomic Hostの利用

Atomic Hostの特徴

Atomic Hostは,Docker専用のホストLinux環境である。これまではCentOS7にDockerをインストールして使ってきたが,Docker以外のアプリケーションを利用しないならば,ホストLinuxはDockerだけ利用できる環境があればいいことになる。Atomic Hostは,Dockerの実行に最適化された最小構成のホスト環境を提供します。

Atomic Hostの第一の特徴は,インストールが非常に簡単ということだ。以下のリンクからインストーラをダウンロードし,インストール先のディスクの選択とネットワークの設定だけでインストールが完了する。また,仮想マシン用のディスクイメージも公開されており,クラウド環境にアップロードすればインストールせずに使うこともできる。
Index of /centos/7/atomic/images

Dockerを利用するための専用環境として最低限のパッケージのみ導入されるため,ルートファイルシステムの使用量は約800M,メモリ使用量も100M以下と必要最小限に抑えられている。なお,Atomic Hostにおけるコンテナイメージの保存領域は,CentOS7にDockerを入れたときのデフォルトであるスパース形式ではなく,論理ボリュームを用いた構成になっている(=ディスクアクセスの性能が向上する構成)。

Atomic Hostではパッケージ管理の方法も大きく異なり,まずyumコマンドは使用できない。そもそも追加でアプリケーションを入れる必要がないだろうということで,必要なアプリケーションは全てコンテナイメージで用意して,コンテナとして起動するという考え方になる。ただし,ホストLinuxのシステムログを監視するエージェントなどを入れたい場合には,SPCを利用することになる(後述)。
また,yumがないのでパッケージを個別にアップデートすることもできず,ホストLinuxの環境全体をまとめてアップデートすることになる。これにはatomicコマンドを使用する。

// 現在のバージョンの確認
# atomic host status
// 最新版にアップデート(反映には再起動が必要)
# atomic host upgrade
// 直前のバージョンに戻す(Atomic Hostは2種類のバージョンを保持することができる)
# atomic host rollback
rmp-ostreeによるバージョン管理

Atomic Hostで使用しているrpm-ostreeでは,稼働中のサーバに対してRPMパッケージを個別に導入するのではなく,事前に複数RPMパッケージを導入したルートファイルシステム全体をサーバに持ち込む仕組みになる。Dockerでコンテナを起動する際はコンテナイメージに保存されたディレクトリをルートファイルシステムとして割り当てるが,それを同じことをホストにも適用しているわけだ。

Atomic Hostでは2種類のバージョンを同時にインストールできると説明したが,それぞれのバージョンに含まれるファイルは/sysroot/ostree/repo以下にまとめて保存されている。これはrpm-ostreeの内部リポジトリにあたり,実際に使用するルートファイルシステムは,ディレクトリ/sysroot/ostree/deploy/centos-atomic-host/deployの下にバージョンごとに個別に用意される。この時,それぞれのバージョンで同じファイルを使用することもあるが,その場合は同じファイルに対してそれぞれのディレクトリから共通にハードリンクを作成している。

ただし,このようなファイルについては,システム稼働中にファイルの内容を変更することは許されない(他方のバージョンからもお暗示ファイルを見ているため)ので,3種類のディレクトリについて管理方法が分けられている。

  • /usr: 読み込み専用でマウント
  • /var:rpm-ostreeの管理対象外(全バージョンから同じ内容が見える)
  • /etc:バージョンごとに個別に用意
SPC(Super Privileged Container)の利用

SPCは,Dockerからコンテナを起動する際に特別なオプションを指定することで,コンテナ内部からホストLinuxの環境を見えるようにする機能である。Atomic Host固有の機能ではなく,Dockerの様々なオプションを組み合わせることで実現している。

# docker run -it --rm --privileged --net=host --ipc=host --pid= host \
  -v /:/host -v /run:/run -v /etc/localtime:/etc/localtime \
  --name ostools01 enakai00/ostools:centos6 /bin/bash

このコンテナ内部でpsやifconfigコマンドを実行すると,プロセステーブルやネットワーク構成はホストの環境がそのまま見えていることがわかる。ホストLinuxのルートディレクトリが/hostにマウントされているので,ホストLinuxの環境を直接に参照/操作することが可能である(例えば/host/var/logを参照してログ監視ができる)。
Atomic Hostではネットワークパケットを監視するtcpdumpコマンドが入っていないため実行できないが,tcpdump導入済みのコンテナをSPCで起動すれば,SPCの中からパケット解析を実行できる。なお,上記のdocker runコマンドを打つのは面倒だが,Atomic Hostではdocker runコマンドと同様の機能を持つAtomic runコマンドが用意されており,この--spcオプションを利用することで先ほどと同じオプションがまとめて指定されるようになっている。

# atomic run --spc --name <コンテナ名> <イメージ名>

今後の発展

本節では,Dockerで採用される可能性のある新しい技術として,レイヤー型ファイルシステムのoverlayfsと,CRIUを紹介する。

overlayfsによるコンテナイメージ管理

overlayfsは,2つのディレクトリを重ねてマウントするレイヤー型ファイルシステムの機能を提供するカーネルモジュールである。Linuxカーネル3.18で正式採用され,CentOS7ではまだ利用できないがFedora 22では標準機能として利用可能である。

overlayfsでは,Lowerレイヤと呼ばれる既存のディレクトリ上に,Upperレイヤと呼ばれる新しいディレクトリをかぶせた上でファイルシステムをマウントする。

// 既存のディレクトリ/lowerに/upperをかぶせて/mntにマウントする
# mount -t overlay overlay -o
upperdir=/upper,lowerdir=/lower,workdir=/work /mnt

このとき,/mntの中を見ると/lowerと同じ中身が見えるが,/mntに書き込んだ内容は/upperのほうに保存される。つまり,既存のディレクトリの内容を破壊すること無く読み書きできることになる。
そしてDockerにおいては,1つのコンテナイメージから複数のコンテナを起動する際に,この機能を活用しようという取り組みがある。コンテナイメージをLowerレイヤとして,Upperレイヤとなる空のディレクトリを被せてホストにマウントしたあと,このマウントポイントをコンテナのルートファイルシステムに割り当てる。ここで,コンテナが使用中のイメージをcommitで保存すると,対応するディレクトリにイメージの内容が複製されるが,Lowerイメージに含まれる内容はハードリンクによって対応される。これによって,コンテナ起動時に使用したイメージについては,ファイルを共有することでディスク領域を節約しながら新たなイメージを保存することが可能になる。dm-thinを用いた場合は論理デバイスのブロック単位でデータが共有されるが,こちらではファイル単位で共有が行われることになる。

overlayfsを用いた際の利点として,ファイルシステムのディスクキャッシュが有効活用できるという点が挙げられる。1つのコンテナがイメージ内のファイルを読み込むと,ホストのディスクキャッシュに保存され,他のコンテナが同じファイルを読み込む際にはキャッシュ上のデータを利用するため高速にアクセスできることになる。dm-thinを用いた場合では,それぞれの論理デバイスは独立したディスク領域として認識されているので,同一のデータブロックに含まれるファイルであってもディスクキャッシュの共有は行われない。

CRIUによる稼動状態コンテナの保存

CRIU(クリュー)は,Checkpoint/Restore in Userspeceの略で,稼働プロセスの状態をファイルに保存して実行状態を後から復元するという機能である。プロセスが使用中のメモリやCPUの状態を含めて保存しておくことで,一時停止状態から回復するようにプロセスのかどうを再開することが可能になる。これをDockerが管理するコンテナの状態を保存/復元するために利用する取り組みが進んでいる。

コンテナはOSを起動する必要がないため,仮想マシンに比べて起動が高速になるものの,コンテナの場合でもアプリケーションそのものの起動時間は考える必要がある。複雑なアプリケーションでは起動して利用可能になるまで数分掛かる場合もある。しかし,CRIUを利用することでアプリケーションの起動が完了した状態のコンテナをファイルに保存しておくことができ,新たにコンテナを起動する代わりに保存しておいたコンテナを復元すれば,アプリケーションの起動時間が短縮できる。

前節ではKubernetesを用いてWebサーバのコンテナを後から追加する例を説明したが,急激にアクセスが殺到したような場合に,コンテナの起動時に掛かるアプリケーションの起動時間すらも短縮したいようなケースが考えられる。このような場合に,コンテナの起動を高速化する技術としてCRIUの活用が期待されている。また,稼働状態のコンテナの状態を保存し,別の物理ホストに移動するようなことも可能になる。