めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

Fedora22でoverlayfsを使う手順

参考資料

・カーネルドキュメント Overlay Filesystem
・overlayfsのメインラインコミット overlay filesystem

手順

Fedora22 Serverをインストールして、まずは最新パッケージにアップデートします。

# dnf -y update
# reboot
# cat /etc/fedora-release 
Fedora release 22 (Twenty Two)
# uname -a
Linux f22 4.0.5-300.fc22.x86_64 #1 SMP Mon Jun 8 16:15:26 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

Upper Layerのディレクトリと作業用ディレクトリを用意してマウントします。

# mkdir /root/upper
# mkdir /root/work
# mount -t overlay overlay -o upperdir=/root/upper,lowerdir=/etc,workdir=/root/work /mnt

ここでは、「/etc」にUpper Layerを被せて、「/mnt」にマウントしています。作業用ディレクトリは、Overlayfsが内部的に使用します。

使ってみる

/mntの下には、/etcの内容が見えていますが、新たに書き込んだ内容は、Upper Layerの方に保存されます。/etcの内容が変更されることはありません。

# date > /mnt/hoge.txt

# ls -l /mnt/h*
-rw-r--r--. 1 root root  43  6月 28 11:18 /mnt/hoge.txt
-rw-r--r--. 1 root root   9  2月 23 23:24 /mnt/host.conf
-rw-r--r--. 1 root root   4  6月 28 10:19 /mnt/hostname
-rw-r--r--. 1 root root 158  2月 23 23:24 /mnt/hosts
-rw-r--r--. 1 root root 370  2月 23 23:24 /mnt/hosts.allow
-rw-r--r--. 1 root root 460  2月 23 23:24 /mnt/hosts.deny

# ls -l /etc/h*
-rw-r--r--. 1 root root   9  2月 23 23:24 /etc/host.conf
-rw-r--r--. 1 root root   4  6月 28 10:19 /etc/hostname
-rw-r--r--. 1 root root 158  2月 23 23:24 /etc/hosts
-rw-r--r--. 1 root root 370  2月 23 23:24 /etc/hosts.allow
-rw-r--r--. 1 root root 460  2月 23 23:24 /etc/hosts.deny

# ls -l /root/upper/
合計 4
-rw-r--r--. 1 root root 43  6月 28 11:18 hoge.txt

/etcに書き込んだ内容は、/mntからも見えます。

# date > /etc/hoge2.txt
# ls -l /mnt/h*
-rw-r--r--. 1 root root  43  6月 28 11:18 /mnt/hoge.txt
-rw-r--r--. 1 root root  43  6月 28 11:20 /mnt/hoge2.txt
-rw-r--r--. 1 root root   9  2月 23 23:24 /mnt/host.conf
-rw-r--r--. 1 root root   4  6月 28 10:19 /mnt/hostname
-rw-r--r--. 1 root root 158  2月 23 23:24 /mnt/hosts
-rw-r--r--. 1 root root 370  2月 23 23:24 /mnt/hosts.allow
-rw-r--r--. 1 root root 460  2月 23 23:24 /mnt/hosts.deny

/mntでファイルを削除すると、Upper Layerに、削除したことを示す特殊ファイルが作成されます。

# rm -f /mnt/h*

# ls -l /root/upper/
合計 0
c---------. 1 root root 0, 0  6月 28 11:21 hoge2.txt
c---------. 1 root root 0, 0  6月 28 11:21 host.conf
c---------. 1 root root 0, 0  6月 28 11:21 hostname
c---------. 1 root root 0, 0  6月 28 11:21 hosts
c---------. 1 root root 0, 0  6月 28 11:21 hosts.allow
c---------. 1 root root 0, 0  6月 28 11:21 hosts.deny

この時、/mntからファイルは見えなくなるのですが、なぜか、ファイル名のTab補完はできてしまいます。ディレクトリ内のエントリとしては、ファイルは存在するけれど、実際にアクセスに行ったタイミングでファイルが存在しないものと解釈されている気がします。実際、"*" でファイルアクセスするとこうなります。

# ls -l /mnt/h*
ls: /mnt/hoge2.txt にアクセスできません: そのようなファイルやディレクトリはありません
ls: /mnt/host.conf にアクセスできません: そのようなファイルやディレクトリはありません
ls: /mnt/hostname にアクセスできません: そのようなファイルやディレクトリはありません
ls: /mnt/hosts にアクセスできません: そのようなファイルやディレクトリはありません
ls: /mnt/hosts.allow にアクセスできません: そのようなファイルやディレクトリはありません
ls: /mnt/hosts.deny にアクセスできません: そのようなファイルやディレクトリはありません

既存のファイルシステムと完全に同じ振る舞いをするわけではないので、このあたりは注意が必要ですね。

あとは、overlay mountしたディレクトリをベースに、さらに Upper layerを被せてマウントすることもできるようです。

# umount /mnt
# mkdir /root/upper2
# mount -t overlay overlay -o upperdir=/root/upper,lowerdir=/etc,workdir=/root/work /mnt/mnt1
# mount -t overlay overlay -o upperdir=/root/upper2,lowerdir=/mnt/mnt1,workdir=/root/work /mnt/mnt2

この例では、/etcに/root/upperを被せて/mnt/mnt1にマウントした後、さらに、/mnt/mnt1に/root/upper2を被せて/mnt/mnt2にマウントしています。

Fedora22のDockerでoverlayfsドライバーを利用する手順

まずは、表題の手順だけを簡潔に・・・。そのうち、内部構造も詳しく説明するかも知れません。

手順

Fedora22 Serverをインストールして、まずは最新パッケージにアップデートした上で、「石川さんごめんなさい」をします。(overlayfsドライバーがSELinux未対応のため)

# dnf -y update
# sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
# reboot

/etc/sysconfig/dockerのOPTIONSに '-s overlay' を追加します。

OPTIONS='--selinux-enabled -s overlay'

Dockerを起動します。

# systemctl enable docker.service
# systemctl start docker.service

# docker info
Containers: 0
Images: 11
Storage Driver: overlay
 Backing Filesystem: xfs
Execution Driver: native-0.2
Kernel Version: 4.0.5-300.fc22.x86_64
Operating System: Fedora 22 (Twenty Two)
CPUs: 2
Total Memory: 993.4 MiB
Name: f22
ID: E74A:KMVO:ID2P:SVNH:MUKR:ZLR6:QAUM:CDAZ:R7VH:FQUK:FPLF:TM3A

以上です。

内部構造のメモ書き

Dockerイメージを取ってくると、/var/lib/docker/overlayの下に各イメージを保存したディレクトリが用意されます。

# docker pull -a docker.io/centos

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/centos    centos6             a005304e4e74        9 days ago          203.1 MB
docker.io/centos    6                   a005304e4e74        9 days ago          203.1 MB
docker.io/centos    latest              7322fbe74aa5        9 days ago          172.2 MB
docker.io/centos    7                   7322fbe74aa5        9 days ago          172.2 MB
docker.io/centos    centos7             7322fbe74aa5        9 days ago          172.2 MB
docker.io/centos    centos5.11          223843a319ca        9 weeks ago         284.1 MB
docker.io/centos    5.11                223843a319ca        9 weeks ago         284.1 MB
docker.io/centos    6.6                 8b44529354f3        9 weeks ago         202.6 MB
docker.io/centos    centos6.6           8b44529354f3        9 weeks ago         202.6 MB
docker.io/centos    centos7.0.1406      feb2761601e7        9 weeks ago         210.2 MB
docker.io/centos    7.0.1406            feb2761601e7        9 weeks ago         210.2 MB
docker.io/centos    7.1.1503            f1dade627e25        9 weeks ago         212.1 MB
docker.io/centos    centos7.1.1503      f1dade627e25        9 weeks ago         212.1 MB
docker.io/centos    centos5             9069226e092e        9 weeks ago         284.1 MB
docker.io/centos    5                   9069226e092e        9 weeks ago         284.1 MB

# ls -l /var/lib/docker/overlay/
合計 0
drwx------. 3 root root 17  6月 28 17:29 223843a319cac73d666e66265569d4c3c2f416b8b1c2c0af4391d1541051be35
drwx------. 3 root root 17  6月 28 17:23 7322fbe74aa5632b33a400959867c8ac4290e9c5112877a7754be70cfe5d66e9
drwx------. 3 root root 17  6月 28 17:28 8b44529354f3ca0fbe44794e2dbd0169a8ae6e2cdfa2d6df3fcd0777892ebb85
drwx------. 3 root root 17  6月 28 17:29 9069226e092e9c8d68450ca4a416bec6acf1709584e9fd70ea5fe8040bf9859e
drwx------. 3 root root 17  6月 28 17:28 a005304e4e74c1541988d3d1abb170e338c1d45daee7151f8e82f8460634d329
drwx------. 3 root root 17  6月 28 17:28 c43c1996cf187f30bc8af15e7a3bc5aee1eba2a0995baaf3e4135a7a676d74b1
drwx------. 3 root root 17  6月 28 17:23 c852f6d61e65cddf1e8af1f6cd7db78543bfb83cdcd36845541cf6d9dfef20a0
drwx------. 3 root root 17  6月 28 17:23 f1b10cd842498c23d206ee0cbeaa9de8d2ae09ff3c7af2723a9e337a6965d639
drwx------. 3 root root 17  6月 28 17:28 f1dade627e2541880e968459c4c3861678a8b576714f0325e16a7a04c32326c6
drwx------. 3 root root 17  6月 28 17:28 fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f
drwx------. 3 root root 17  6月 28 17:29 feb2761601e7a65e37e4b78a1bd688cb1e7a847045e2f98ac50abba081d79d31

各ディレクトリ内のrootの下にイメージのコンテンツが普通に展開されています。親イメージに含まれるファイルは、該当ファイルへのハードリンクになっています。ローカルディスクにイメージを保存する際に、overlayを使用するわけではありません。

イメージを指定してコンテナを起動すると、コンテナ用のディレクトリは、overlayで用意されます。

# docker run -itd docker.io/centos:6.6 /bin/bash
906b7f9fcb94fd3b55de8059b8ae7dc3e26778ba7e280ccf98f72294d7a7b239

# ls -l /var/lib/docker/overlay/906b7f9fcb94fd3b55de8059b8ae7dc3e26778ba7e280ccf98f72294d7a7b239
合計 4
-rw-r--r--. 1 root root 64  6月 28 20:46 lower-id
drwx------. 2 root root  6  6月 28 20:46 merged
drwxr-xr-x. 6 root root 81  6月 28 20:46 upper
drwx------. 3 root root 17  6月 28 20:46 work

lower-idは、親イメージのIDを保存したテキストファイル、upperが差分を保存するUpper Layerのディレクトリ、親イメージとupperを合成したものがmergedにoverlayマウントされて、ここがコンテナのルートファイルシステムとして割り当てられます。(mergedへのマウントは、コンテナ内部のnamespaceで行われるので、ホストからはmergedの中身は見えません。)

ソースコード的には、docker/daemon/graphdriver以下のドライバーが下記のメソッドを実装します。

・Create():親イメージを複製した新規イメージを作成
・ApplyDiff():既存イメージに差分レイヤーを上書きした新しいイメージを作成

overlayドライバーの場合は、Create()の際に上記のoverlayマウントを行います。

ApplyDiff()は、Create()で既存イメージを新規イメージとしてoverlayマウントした後、既存イメージのrootを新規イメージのrootとしてハードリンクコピーした後、差分レイヤーを上書きしてマージします。これにより、親イメージとハードリンクでファイルを共有した新規イメージが作成されます。