2016/01/02

Debian GNU/LinuxのDockerでLVMシンプールを使う

Debian GNU/Linux 8.2(jessie)に Docker をインストールしてストレージドライバをデフォルトの aufs から devicemapper に変更してシンプールを使用するようにした時のメモです。

はじめに

検証機のストレージがとても速くなりましたので、せっかくなので今まで使用していた aufs から devicemapper に切り替えついでに Docker 導入手順からまとめてみます。

ストレージドライバについては以下の資料を参考にしました。

(2016/01/16 追記)
この記事を書いていたときには気づかなかったのですが、Debian GNU/Linux 8.2 で docker の devicemapper ストレージドライバで LVM シンプールを使用している際に、論理ボリュームを OS 再起動などで一度非活性化すると二度とアクティブに出来なくなる事象が起きています。状況について 注意書きとして追記 しました。

Docker のインストール

インストールは公式の手順通りです。

ここでは全て root ユーザで作業します。
Docker のパッケージリポジトリを追加
# apt-get purge lxc-docker*
# apt-get purge docker.io*

# apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

# echo 'deb https://apt.dockerproject.org/repo debian-jessie main' > /etc/apt/sources.list.d/docker.list

# apt-get update

# apt-cache policy docker-engine
Docker をインストール

docker-engine パッケージをインストールすると systemd ユニットの設定が行われて docker デーモンが起動した状態になります。

# apt-get install docker-engine
デフォルトではストレージドライバが aufs なっていることが確認できます。
# docker info
Containers: 0
Images: 0
Server Version: 1.9.1
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 0
 Dirperm1 Supported: true
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 3.16.0-4-amd64
Operating System: Debian GNU/Linux 8 (jessie)
CPUs: 2
Total Memory: 15.71 GiB
Name: microserver.myhome
ID: JNLR:5HTY:XMAU:CASU:OHUW:FUYU:3KYE:GGEM:O3SH:QYJK:PKT5:7LYE
試した docker のバージョンは 1.9.1 です。
# docker version
Client:
 Version:      1.9.1
 API version:  1.21
 Go version:   go1.4.2
 Git commit:   a34a1d5
 Built:        Fri Nov 20 12:59:02 UTC 2015
 OS/Arch:      linux/amd64

Server:
 Version:      1.9.1
 API version:  1.21
 Go version:   go1.4.2
 Git commit:   a34a1d5
 Built:        Fri Nov 20 12:59:02 UTC 2015
 OS/Arch:      linux/amd64

Docker のストレージドライバを変更

既存の Docker イメージを削除

ストレージドライバを変更しますので一旦 docker を停止して /var/lib/docker を削除します(移行するコンテナがある場合は適宜 docker save しておきます)。

# systemctl stop docker
# rm -rf /var/lib/docker

シンプールを作成

ここでは vg/docker というシンプールを作成します。

# pvcreate /dev/nvme0n1p2
  Physical volume "/dev/nvme0n1p2" successfully created

# vgcreate vg /dev/nvme0n1p2
  Volume group "vg" successfully created

# lvcreate --thin -l 100%FREE vg/docker
  Logical volume "lvol0" created
  Logical volume "docker" created
# pvs
  PV             VG   Fmt  Attr PSize  PFree
  /dev/nvme0n1p2 vg   lvm2 a--  93.21g    0

# vgs
  VG   #PV #LV #SN Attr   VSize  VFree
  vg     1   1   0 wz--n- 93.21g    0

# lvs
  LV     VG   Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi-a-tz-- 93.02g             0.00   0.42

lsblk コマンドでデバイスの様子を確認します。
# lsblk /dev/nvme0n1p2
NAME                MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
nvme0n1p2           259:2    0 93.2G  0 part
├─vg-docker_tmeta   252:0    0   96M  0 lvm
│ └─vg-docker-tpool 252:2    0   93G  0 lvm
│   └─vg-docker     252:3    0   93G  0 lvm
└─vg-docker_tdata   252:1    0   93G  0 lvm
  └─vg-docker-tpool 252:2    0   93G  0 lvm
    └─vg-docker     252:3    0   93G  0 lvm
Docker サービスのドロップインファイルを作成

docker-engine パッケージに /etc/default/docker ファイルは存在しますが、これは Upstart や SysVinit 用なので systemd で起動した場合には参照されません。

# cat /lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket

[Service]
Type=notify
ExecStart=/usr/bin/docker daemon -H fd://
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity

[Install]
WantedBy=multi-user.target
# cat /etc/default/docker
# Docker Upstart and SysVinit configuration file

# Customize location of Docker binary (especially for development testing).
#DOCKER="/usr/local/bin/docker"

# Use DOCKER_OPTS to modify the daemon startup options.
#DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4"

# If you need Docker to use an HTTP proxy, it can also be specified here.
#export http_proxy="http://127.0.0.1:3128/"

# This is also a handy place to tweak where Docker's temporary files go.
#export TMPDIR="/mnt/bigdrive/docker-tmp"
ストレージドライバを変更するためのオプションを追加する必要がありますので Docker サービスのドロップインファイルを作成します。設定ファイルのパスはどこでもよいのですが、既存のものも使いつつ docker-storage-setup コマンドのファイルパスも参考にしています。
# mkdir -v /etc/systemd/system/docker.service.d

# tee /etc/systemd/system/docker.service.d/docker-sysconfig.conf <<'EOF'
[Service]
ExecStart=
EnvironmentFile=-/etc/default/docker
EnvironmentFile=-/etc/default/docker-storage
EnvironmentFile=-/etc/default/docker-network
ExecStart=/usr/bin/docker daemon \
         $DOCKER_OPTS \
         $DOCKER_STORAGE_OPTIONS \
         $DOCKER_NETWORK_OPTIONS \
         $INSECURE_DIRECTORY
EOF

# systemctl daemon-reload

Docker ストレージ設定を追加

今回の設定では /etc/default/docker-storage というファイルに DOCKER_STORAGE_OPTIONS という変数を用いて以下のストレージ関連のパラメータを指定します。

  • --storage-driver devicemapper
  • --storage-opt dm.fs=xfs
  • --storage-opt dm.thinpooldev=/dev/mapper/vg-docker-tpool
  • --storage-opt dm.use_deferred_removal=true
  • --storage-opt dm.use_deferred_deletion=true
# tee /etc/default/docker-storage <<'EOF'
DOCKER_STORAGE_OPTIONS="--storage-driver devicemapper --storage-opt dm.fs=xfs --storage-opt dm.thinpooldev=/dev/mapper/vg-docker-tpool --storage-opt dm.use_deferred_removal=true --storage-opt dm.use_deferred_deletion=true"
EOF
パラメータの詳細は公式ドキュメントを参照してください。
Docker を起動

ここまでで設定が終わりましたので docker を起動して devicemapper ストレージドライバが使用されていることを確認します。

# systemctl start docker

# docker info
Containers: 0
Images: 0
Server Version: 1.9.1
Storage Driver: devicemapper
 Pool Name: vg-docker-tpool
 Pool Blocksize: 65.54 kB
 Base Device Size: 107.4 GB
 Backing Filesystem: xfs
 Data file:
 Metadata file:
 Data Space Used: 53.67 MB
 Data Space Total: 99.88 GB
 Data Space Available: 99.83 GB
 Metadata Space Used: 450.6 kB
 Metadata Space Total: 100.7 MB
 Metadata Space Available: 100.2 MB
 Udev Sync Supported: true
 Deferred Removal Enabled: true
 Deferred Deletion Enabled: true
 Deferred Deleted Device Count: 0
 Library Version: 1.02.90 (2014-09-01)
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 3.16.0-4-amd64
Operating System: Debian GNU/Linux 8 (jessie)
CPUs: 2
Total Memory: 15.71 GiB
Name: microserver.myhome
ID: JNLR:5HTY:XMAU:CASU:OHUW:FUYU:3KYE:GGEM:O3SH:QYJK:PKT5:7LYE

おわりに

LVM のシンプールは今回初めて使ってみたのでどのようなモノかあまり理解していませんが、少なくとも docker においては aufs よりはディスク使用効率が良いはずです。十分に速くなったストレージと効率の良いストレージドライバで docker を楽しみながら覚えてゆきたいと思います。

注意(2016/01/16追加)

Debian GNU/Linux 8.2 安定版の lvm2 と docker のどちらの問題か分かりませんが、LVM シンプールを使うと LVM メタデータが壊れてしまう事象が発生しています。おそらく以下の issues と同じ原因だと思われます。

次のようにして再現できます。
# lsb_release -d
Description:    Debian GNU/Linux 8.2 (jessie)

# lvm version
  LVM version:     2.02.111(2) (2014-09-01)
  Library version: 1.02.90 (2014-09-01)
  Driver version:  4.27.0
1GB のシンプールを作成します。
# lvcreate --thin -L 1G vg/docker
  Logical volume "docker" created

# lvs vg/docker
  LV     VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi-a-tz-- 1.00g             0.00   0.98

# lsblk -i | grep vg-docker
  |-vg-docker_tmeta    252:12   0     4M  0 lvm
  | `-vg-docker-tpool  252:14   0     1G  0 lvm
  |   `-vg-docker      252:15   0     1G  0 lvm
  `-vg-docker_tdata    252:13   0     1G  0 lvm
    `-vg-docker-tpool  252:14   0     1G  0 lvm
      `-vg-docker      252:15   0     1G  0 lvm

そういえば dm.thinpooldev を指定する際に LV 名ではなくその下層のデバイスを指定しないと docker が起動しなかったのも気になります。
×起動せず --storage-driver devicemapper --storage-opt dm.thinpooldev=/dev/mapper/vg-docker
○起動する --storage-driver devicemapper --storage-opt dm.thinpooldev=/dev/mapper/vg-docker-tpool
# systemctl start docker

# docker info
Containers: 0
Images: 0
Server Version: 1.9.1
Storage Driver: devicemapper
 Pool Name: vg-docker-tpool
 Pool Blocksize: 65.54 kB
 Base Device Size: 107.4 GB
 Backing Filesystem: xfs
 Data file:
 Metadata file:
 Data Space Used: 53.67 MB
 Data Space Total: 1.074 GB
 Data Space Available: 1.02 GB
 Metadata Space Used: 69.63 kB
 Metadata Space Total: 4.194 MB
 Metadata Space Available: 4.125 MB
 Udev Sync Supported: true
 Deferred Removal Enabled: false
 Deferred Deletion Enabled: false
 Deferred Deleted Device Count: 0
 Library Version: 1.02.90 (2014-09-01)
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 3.16.0-4-amd64
Operating System: Debian GNU/Linux 8 (jessie)
CPUs: 2
Total Memory: 15.71 GiB
Name: microserver.myhome
ID: JNLR:5HTY:XMAU:CASU:OHUW:FUYU:3KYE:GGEM:O3SH:QYJK:PKT5:7LYE

# lvs vg/docker
  LV     VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi-a-tz-- 1.00g             5.00   1.66
docker を起動してすぐに停止し、論理ボリュームの状態を非活性化するとシンプールのエラーが発生して活性化できません。
# systemctl stop docker

# lvs vg/docker
  LV     VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi-a-tz-- 1.00g             5.00   1.66

# lvchange -an vg/docker

# lvs vg/docker
  LV     VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi---tz-- 1.00g

# lvchange -ay vg/docker
  Thin pool transaction_id is 1, while expected 0.

試しにテスト版 Debian GNU/Linux 9 で試してみるとこの問題は起きませんでした。
# lsb_release -d
Description:    Debian GNU/Linux testing (stretch)

# lvm version
  LVM version:     2.02.138(2) (2015-12-14)
  Library version: 1.02.114 (2015-12-14)
  Driver version:  4.33.0

# lvcreate --thin -L 1G vg/docker
  Logical volume "docker" created.

# lvs vg/docker
  LV     VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi-a-tz-- 1.00g             0.00   0.98

# lsblk -i | grep vg-docker
  |-vg-docker_tmeta 251:0    0    4M  0 lvm
  | `-vg-docker     251:2    0    1G  0 lvm
  `-vg-docker_tdata 251:1    0    1G  0 lvm
    `-vg-docker     251:2    0    1G  0 lvm

# systemctl start docker

# docker info
Containers: 0
Images: 0
Server Version: 1.9.1
Storage Driver: devicemapper
 Pool Name: vg-docker
 Pool Blocksize: 65.54 kB
 Base Device Size: 107.4 GB
 Backing Filesystem: xfs
 Data file:
 Metadata file:
 Data Space Used: 53.74 MB
 Data Space Total: 1.074 GB
 Data Space Available: 1.02 GB
 Metadata Space Used: 69.63 kB
 Metadata Space Total: 4.194 MB
 Metadata Space Available: 4.125 MB
 Udev Sync Supported: true
 Deferred Removal Enabled: true
 Deferred Deletion Enabled: true
 Deferred Deleted Device Count: 0
 Library Version: 1.02.114 (2015-12-14)
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 4.3.0-1-amd64
Operating System: Debian GNU/Linux stretch/sid (containerized)
CPUs: 1
Total Memory: 996.8 MiB
Name: debian9test
ID: EI45:TEVB:63LG:VSNQ:FTWS:NHRD:BKHF:AKHS:JW47:TOVG:DCO6:UDI2
WARNING: No memory limit support
WARNING: No swap limit support

# lvs vg/docker
  LV     VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi-a-tz-- 1.00g             5.00   1.66

# systemctl stop docker
Warning: Stopping docker.service, but it can still be activated by:
  docker.socket

# lvs vg/docker
  LV     VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi-a-tz-- 1.00g             5.00   1.66

# lvchange -an vg/docker

# lvs vg/docker
  LV     VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi---tz-- 1.00g

# lvchange -ay vg/docker

# lvs vg/docker
  LV     VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  docker vg   twi-a-tz-- 1.00g             5.00   1.66
とりあえず Debian GNU/Linux 8.2 安定版ではストレージに LVM シンプールを指定するのは止めた方がよさそうです。なので今は btrfs ストレージドライバを試しています。

0 件のコメント:

コメントを投稿