DockerでDirect LVMを利用する

今日は、DockerでDirect LVMを利用してみます。
通常は、ループバックデバイスによるLVMになっています。

# DockerのデフォルトLVMとは
Dockerのデフォルトは、ループバックデバイスによるLVMです。
使用しているのは、/var/lib/docker/devicemapper/devicemapper/dataと/var/lib/docker/devicemapper/devicemapper/metadataのRAWファイル（スパース）が作成され、ループデバイスとしてLVMが構成されています。

```
# losetup 
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop0         0      0         1  0 /var/lib/docker/devicemapper/devicemapper/data
/dev/loop1         0      0         1  0 /var/lib/docker/devicemapper/devicemapper/metadata
# qemu-img info /var/lib/docker/devicemapper/devicemapper/data
image: /var/lib/docker/devicemapper/devicemapper/data
file format: raw
virtual size: 100G (107374182400 bytes)
disk size: 292M
# qemu-img info /var/lib/docker/devicemapper/devicemapper/metadata                                                           
image: /var/lib/docker/devicemapper/devicemapper/metadata
file format: raw
virtual size: 2.0G (2147483648 bytes)
disk size: 744K
# lsblk
NAME                            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                               8:0    0   50G  0 disk 
├─sda1                            8:1    0  500M  0 part /boot
└─sda2                            8:2    0 49.5G  0 part 
  ├─centos-root                 253:0    0 45.6G  0 lvm  /
  └─centos-swap                 253:1    0  3.9G  0 lvm  [SWAP]
sr0                              11:0    1 1024M  0 rom  
loop0                             7:0    0  100G  0 loop 
└─docker-253:0-201702034-pool   253:2    0  100G  0 dm   
  └─docker-253:0-201702034-base 253:3    0   10G  0 dm   
loop1                             7:1    0    2G  0 loop 
└─docker-253:0-201702034-pool   253:2    0  100G  0 dm   
  └─docker-253:0-201702034-base 253:3    0   10G  0 dm   
```

# direct LVMを利用する

## 利用する理由
direct LVMを利用します。ループバックデバイスは、やはり遅いです。RAWのスパースファイルですので、拡張時に領域を確保するための時間がかかります。RAWのノンスパースファイルであればもう少し早いのかもしれません。Dockerコンテナ起動時には、ループバックデバイスの使用に関する警告が出ます。

```
# docker run -it --name homma01 centos /bin/bash
Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.
[root@959b838de28a /]# 
```

また、コンテナを大量に起動するときには、起動速度の差が顕著に表れます。
中井さんの解説ページにも書かれています。詳細は、「[第68回　Dockerストレージドライバーの性能比較 (中井悦司)](http://www.school.ctc-g.co.jp/columns/nakai/nakai68.html)」を見てください。大元の記事は、「[Comprehensive Overview of Storage Scalability in Docker](http://developerblog.redhat.com/2014/09/30/overview-storage-scalability-docker/)」でしょうか。
overlayFSが一番ベストですが、direct LVMもループバックデバイスに比べて2倍以上高速です。

## direct LVMの設定をします
### ディスクを追加するとき
docker用のディスクを追加した場合の方法です。今回は、/dev/sdbを追加した場合です。

```
# ls -al /dev/sd*
brw-rw----. 1 root disk 8,  0  8月  7 21:55 /dev/sda
brw-rw----. 1 root disk 8,  1  8月  7 21:55 /dev/sda1
brw-rw----. 1 root disk 8,  2  8月  7 21:55 /dev/sda2
brw-rw----. 1 root disk 8, 16  8月  7 21:55 /dev/sdb
```

/etc/sysconfig/docker-storage-setupに追加した/dev/sdbを設定して、再起動します。
/dev/sdb上にLVMを作成し利用するようになります。自動的に設定(/etc/sysconfig/docker-storage)が追加されます。


```
# systemctl stop docker
# rm -rf /var/lib/docker 
# echo DEVS=/dev/sdb >> /etc/sysconfig/docker-storage-setup
# systemctl start docker
# lsblk 
NAME                               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                                  8:0    0   50G  0 disk 
├─sda1                               8:1    0  500M  0 part /boot
└─sda2                               8:2    0 49.5G  0 part 
  ├─centos-root                    253:0    0 45.6G  0 lvm  /
  └─centos-swap                    253:1    0  3.9G  0 lvm  [SWAP]
sdb                                  8:16   0   50G  0 disk 
└─sdb1                               8:17   0   50G  0 part 
  ├─centos-docker--pool_tmeta      253:2    0  104M  0 lvm  
  │ └─centos-docker--pool          253:4    0   30G  0 lvm  
  │   └─docker-253:0-67161589-base 253:5    0   10G  0 dm   
  └─centos-docker--pool_tdata      253:3    0   30G  0 lvm  
    └─centos-docker--pool          253:4    0   30G  0 lvm  
      └─docker-253:0-67161589-base 253:5    0   10G  0 dm   
sr0                                 11:0    1  636M  0 rom  
# cat /etc/sysconfig/docker-storage
DOCKER_STORAGE_OPTIONS=-s devicemapper --storage-opt dm.fs=xfs --storage-opt dm.thinpooldev=/dev/mapper/centos-docker--pool
```

何が起こったか説明します。実は、systemdの設定で、docker.serviceが起動する前にdocker-storage-setup.serviceが呼ばれるようになっています。docker-storage-setup.serviceは、/etc/sysconfig/docker-storage-setupを設定ファイルとして、/usr/bin/docker-storage-setupを起動するようになっているため、Dockerを起動したときに自動的にLVMの設定が開始されたわけです。

```
# cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=network.target
Wants=docker-storage-setup.service
... 略

# cat /usr/lib/systemd/system/docker-storage-setup.service
...略
[Service]
Type=oneshot
ExecStart=/usr/bin/docker-storage-setup
EnvironmentFile=-/etc/sysconfig/docker-storage-setup
... 略
```

### 残りのディスクを使用する
/dev/sdaのディスクのあまりを利用する場合です。

```
# parted -l /dev/sda
モデル: VMware, VMware Virtual S (scsi)
ディスク /dev/sda: 107GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos
ディスクフラグ: 

番号  開始    終了    サイズ  タイプ   ファイルシステム  フラグ
 1    1049kB  525MB   524MB   primary  xfs               boot
 2    525MB   58.4GB  57.9GB  primary                    lvm
```

領域がないので、まず領域を作る必要があります。上で実行したコマンドの結果が重要になります。上から2行目のディスクサイズ：107GB、下から1番目の2のディスクの終了位置：58.4GBが重要です。入力する必要があります。

では、partedコマンドを利用して作成していきましょう。mkpartを入力し、質問に回答していきます。入力する値は参考にしてください。

```
# parted  /dev/sda
(parted) mkpart
パーティションの種類?  primary/プライマリ/extended/拡張? p                
ファイルシステムの種類?  [ext2]?                                          
開始? 57.9GB                                                              
終了? 107GB                                                               
(parted) p                                                                
モデル: VMware, VMware Virtual S (scsi)
ディスク /dev/sda: 107GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos
ディスクフラグ: 

番号  開始    終了    サイズ  タイプ   ファイルシステム  フラグ
 1    1049kB  525MB   524MB   primary  xfs               boot
 2    525MB   58.4GB  57.9GB  primary                    lvm
 3    58.4GB  107GB   49.0GB  primary
```

これを実行すると、/dev/sda3が出来上がります。

```
# ls -al /dev/sda*
brw-rw----. 1 root disk 8, 0  8月  7 22:37 /dev/sda
brw-rw----. 1 root disk 8, 1  8月  7 22:27 /dev/sda1
brw-rw----. 1 root disk 8, 2  8月  7 22:27 /dev/sda2
brw-rw----. 1 root disk 8, 3  8月  7 22:37 /dev/sda3
```

さっきと同様に、「echo DEVS=/dev/sda3 >> /etc/sysconfig/docker-storage-setup」としたいですが、「Partition specification unsupported at this time.」と怒られてしまいます。

手動で作成する必要があります。次の手順に従って作成します。

## 手動でDirectLVMを作成
DirectLVMで検索すると、[ambakshi/docker-direct-lvm.sh](https://gist.github.com/ambakshi/ddebac9148b4aea36446)が出てきます。これでもよいですが、これは、 シンプロビジョニングされた論理ボリュームを作成していないので、もうひと手順追加して、以下のような手順がよいです。
/usr/bin/docker-storage-setupでも同様の処理を行っています。

```
# export DEVS=/dev/sda3
# pvcreate $DEVS
  Physical volume "/dev/sda3" successfully created
# vgcreate direct-lvm $DEVS
  Volume group "direct-lvm" successfully created
# lvcreate -n data direct-lvm -l 50%VG
  Logical volume "data" created.
# lvcreate -n metadata direct-lvm -l 5%VG
  Logical volume "metadata" created.
# lvconvert -y --zero n  --thinpool direct-lvm/data  --poolmetadata direct-lvm/metadata
# lvdisplay -C
  LV       VG         Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root     centos     -wi-ao---- 50.00g                                                    
  swap     centos     -wi-ao----  3.88g                                                    
  data     direct-lvm -wi-a----- 43.34g                                                    
  metadata direct-lvm -wi-a-----  2.28g  
# ls /dev/direct-lvm
data
# lsblk 
NAME                       MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                          8:0    0  100G  0 disk 
├─sda1                       8:1    0  500M  0 part /boot
├─sda2                       8:2    0 53.9G  0 part 
│ ├─centos-root            253:0    0   50G  0 lvm  /
│ └─centos-swap            253:1    0  3.9G  0 lvm  [SWAP]
└─sda3                       8:3    0 45.6G  0 part 
  ├─direct--lvm-data_tmeta 253:2    0  2.3G  0 lvm  
  │ └─direct--lvm-data     253:4    0 22.8G  0 lvm  
  └─direct--lvm-data_tdata 253:3    0 22.8G  0 lvm  
    └─direct--lvm-data     253:4    0 22.8G  0 lvm  
sr0                         11:0    1 1024M  0 rom   
#
```

LVMが出来上がったので、設定します。

```
# cat /etc/sysconfig/docker-storage
DOCKER_STORAGE_OPTIONS=-s devicemapper --storage-opt dm.thinpooldev=/dev/mapper/direct--lvm-data
# systemctl stop docker
# rm -rf /var/lib/docker/
# systemctl start docker
```

以上です。