ScaleIO+RexRay


# 概要
[前回](http://qiita.com/KI1208/items/cb9d25a6dda1be5681fb)Docker Swarm環境を作ったのでその続きです。
やりたいことは、クラスタ化されたコンテナ群にPersistent Storageを見せて使うことです。共有ストレージとしてはScaleIOを、DockerのデバイスドライバとしてはRexRayを使用します。

# 構成
CentOS Linux release 7.2.1511 (Core) * 3
ネットワークを分割しているのは単にIPアドレスリソースの都合です。
![image](https://qiita-image-store.s3.amazonaws.com/0/159980/de45572a-5db5-62b7-7f35-d3bf124cc45a.png)

# ScaleIO
EMC社が評価版を提供しています。VMwareのVSANみたいな。
https://www.emc.com/products-solutions/trial-software-download/scaleio.htm
こちらから、ScaleIO_Linux_v2.0.zipをダウンロードします。

## Gatewayサーバの準備
Gatewayサーバ(GW)はScaleIOのインストールや構成変更を行うための管理サーバ。
### Java Install
Java1.8(64bit)が必要なのでインストール。
`yum localinstall --nogpgcheck jdk-8u121-linux-x64.rpm`

### Gatewayのインストール
CentOSであれば6or7でメモリ3GB,2core以上が必要。Gatewayのrpmを先のzipから取り出して適当なディレクトリに配置、インストール。

```shell-session
[root@sunny ~]# ls tmp
EMC-ScaleIO-gateway-2.0-12000.122.x86_64.rpm
[root@sunny ~]#
[root@sunny ~]# GATEWAY_ADMIN_PASSWORD=password rpm -U tmp/EMC-ScaleIO-gateway-2.0-12000.122.x86_64.rpm --nodeps
validating java version
/bin/java
(中略)
The EMC ScaleIO Gateway is running. PID=4005.
```

ブラウザでhttps://<gateway server>にアクセス。
![image](https://qiita-image-store.s3.amazonaws.com/0/159980/893940b6-12ee-5178-ed7e-2a63912ab851.png)

後はGUI通りに進めていく。
以下では、メッセージにある5つを選択すればよい。SDS-Xは不要。
![image](https://qiita-image-store.s3.amazonaws.com/0/159980/bd97b217-d5f3-f4c8-6dd7-662a32e00e9f.png)

![image](https://qiita-image-store.s3.amazonaws.com/0/159980/74920ef9-4bda-8a7d-b871-16c32fcaa0c0.png)

以下ではInstallation Wizard(3 node)を選択。
![image](https://qiita-image-store.s3.amazonaws.com/0/159980/0363ef2c-98f8-6da9-f9c6-f2ab503be0c4.png)

後は道なりで完了します。

## ストレージの構成
MDMをインストールしたサーバにSSHで接続し、ストレージの構成を行います。

### Poolへディスクを追加
この時点で空のプールdefaultがデフォルトで作成されています。

```shell-session
[root@sunny ~]# scli --login --username admin --password Password123
Logged in. User role is SuperUser. System ID is 7489376b176d3545
[root@sunny ~]#
[root@sunny ~]# scli --query_all_volume
Query-all-volumes returned 0 volumes
Protection Domain 1947f06b00000000 Name: default
Storage Pool 1f63dc4100000000 Name: default
 <No volumes defined>
[root@sunny ~]# scli --query_storage_pool --storage_pool_id 1f63dc4100000000
Storage Pool default (Id: 1f63dc4100000000) has 0 volumes and 0 Bytes available for volume allocation
        The number of parallel rebuild/rebalance jobs: 2
        Rebuild is enabled and using Limit-Concurrent-IO policy with the following parameters:
        Number of concurrent IOs per device: 1
        Rebalance is enabled and using Favor-Application-IO policy with the following parameters:
        Number of concurrent IOs per device: 1, Bandwidth limit per device: 10240 KB per second
        Background device scanner: Disabled
        Zero padding is disabled
        Spare policy: 34% out of total
        Checksum mode: disabled
        Doesn't use RAM Read Cache
        Doesn't use Flash Read Cache
        Capacity alert thresholds: High: 80, Critical: 90

        0 Bytes total capacity
        0 Bytes unused capacity
```

あらかじめ、SDSとなっているノードに仮想ディスク120GBを1つずつ追加しています。それをこのプールに追加し、変更を確認します。確認のコマンドquery_storage_poolsはid指定なら単体でよいですが、name指定の場合はprotection domainも合わせて指定する必要があります。

```shell-session
[root@sunny ~]# fdisk -l

Disk /dev/sdb: 128.8 GB, 128849018880 bytes, 251658240 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

[root@sunny ~]# scli --add_sds_device --sds_ip 172.16.5.1 --protection_domain_name default --storage_pool_name default --device_path /dev/sdb
Successfully added device /dev/sdb to SDS. New device ID: fe1eb06700010000

[root@sunny ~]# scli --query_storage_pool --protection_domain_name default --storage_pool_name default
Storage Pool default (Id: 1f63dc4100000000) has 0 volumes and 0 Bytes available for volume allocation
        The number of parallel rebuild/rebalance jobs: 2
        Rebuild is enabled and using Limit-Concurrent-IO policy with the following parameters:
        Number of concurrent IOs per device: 1
        Rebalance is enabled and using Favor-Application-IO policy with the following parameters:
        Number of concurrent IOs per device: 1, Bandwidth limit per device: 10240 KB per second
        Background device scanner: Disabled
        Zero padding is disabled
        Spare policy: 34% out of total
        Checksum mode: disabled
        Doesn't use RAM Read Cache
        Doesn't use Flash Read Cache
        Capacity alert thresholds: High: 80, Critical: 90

        119.0 GB (121855 MB) total capacity
        78.5 GB (80425 MB) unused capacity
```

同様に他のSDSノードでも追加します。

```shell-session
[root@sunny ~]# scli --add_sds_device --sds_ip 172.16.5.2 --protection_domain_name default --storage_pool_name default --device_path /dev/sdb
Successfully added device /dev/sdb to SDS. New device ID: fe1fb06800020000
[root@sunny ~]# scli --add_sds_device --sds_ip 172.16.5.3 --protection_domain_name default --storage_pool_name default --device_path /dev/sdb
Successfully added device /dev/sdb to SDS. New device ID: fe1db06900000000
[root@sunny ~]# scli --query_storage_pool --protection_domain_name default --storage_pool_name default
Storage Pool default (Id: 1f63dc4100000000) has 0 volumes and 112.0 GB (114688 MB) available for volume allocation
        The number of parallel rebuild/rebalance jobs: 2
        Rebuild is enabled and using Limit-Concurrent-IO policy with the following parameters:
        Number of concurrent IOs per device: 1
        Rebalance is enabled and using Favor-Application-IO policy with the following parameters:
        Number of concurrent IOs per device: 1, Bandwidth limit per device: 10240 KB per second
        Background device scanner: Disabled
        Zero padding is disabled
        Spare policy: 34% out of total
        Checksum mode: disabled
        Doesn't use RAM Read Cache
        Doesn't use Flash Read Cache
        Capacity alert thresholds: High: 80, Critical: 90

        357.0 GB (365565 MB) total capacity
        235.6 GB (241273 MB) unused capacity
```

### Volume作成
このプールからVolumeを切り出し、SDCにマッピングします。

```shell-session
[root@sunny ~]# scli --add_volume --protection_domain_name default --storage_pool_name default --size_gb 16 --volume_name vol01
Successfully created volume of size 16 GB. Object ID c19deefd00000000

[root@sunny ~]#
[root@sunny ~]# scli --query_all_volume --volume_name vol01
Query-all-volumes returned 1 volumes
Protection Domain 1947f06b00000000 Name: default
Storage Pool 1f63dc4100000000 Name: default
 Volume ID: c19deefd00000000 Name: vol01 Size: 16.0 GB (16384 MB) Unmapped Thick-provisioned

[root@sunny ~]#
[root@sunny ~]# scli --map_volume_to_sdc --volume_name vol01 --sdc_ip 172.16.5.1
Successfully mapped volume vol01 to SDC 172.16.5.1
[root@sunny ~]#
[root@sunny ~]# scli --query_all_volume --volume_name vol01
Query-all-volumes returned 1 volumes
Protection Domain 1947f06b00000000 Name: default
Storage Pool 1f63dc4100000000 Name: default
 Volume ID: c19deefd00000000 Name: vol01 Size: 16.0 GB (16384 MB) Mapped to 1 SDC Thick-provisioned
```

このボリュームは、SDCを持つOSからは以下のようにsciniXとして見えます。

```shell-session
[root@sunny ~]# fdisk -l
Disk /dev/scinia: 17.2 GB, 17179869184 bytes, 33554432 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
```

# RexRay
こちらもEMC社が提供しています。
https://rexray.codedellemc.com
RexRayはDockerに対してVolume Driverとして働きます。バックエンドになるストレージ(ここではScaleIO)の特性を遮蔽して、ボリューム作成やマッピングなどのオペレーションを共通化します。

## インストール
上記のGet Startedを参考に。以下1行でOK。
`curl -sSL https://dl.bintray.com/emccode/rexray/install | sh`

## 構成ファイルの生成
上記リンク内のRexRay Configuration Generatorを使用する。
サービスとしてScaleIOを指定。
![image](https://qiita-image-store.s3.amazonaws.com/0/159980/35c4f5c2-5e1d-4ce2-ea4b-122c212bbea9.png)

ScaleIO固有のパラメータを指定。
SystemIDなどはscli --query_allの出力から拾うことができます。見にくいですが、System nameはじめ、nameは指定していません。
![image](https://qiita-image-store.s3.amazonaws.com/0/159980/30e04485-c8d7-9ec0-6e48-002e6aea047e.png)

libStorageのオプションはデフォルトのまま。
![image](https://qiita-image-store.s3.amazonaws.com/0/159980/1649c048-d6e4-5c64-8cb3-ada21ecdebde.png)

libStorageはScaleIOより下のレベルにある、オープンソースの、ストレージプロビジョニングとオーケストレーションを行うためのフレームワーク(モデル、APIという言い方もできる)。
各オプションの詳細は[こちら](http://libstorage.readthedocs.io/en/stable/user-guide/config/#volume-configuration)で確認できるが、以下に自分の理解を記載しておきます。

- Enable Preemption
マウントするときに、他にマウントしているものがあれば外してからマウントする。

- Ignore used count
countはmount/unmountの回数のつり合いなどから、ボリュームの使用状況をみるために使われる。
これを無視する(オプションを有効にする)ということは、そのボリュームの排他、共有をより上のレイヤーで制御する必要がある。

- Disable Path Cache
デフォルトではいったんマウントされたパスの情報をキャッシュとして保持し、別のパスにマウントされたときに更新される
アンマウントでは更新されない。

- Disable Async
上記パスキャッシュを非同期にするかどうか。

- Root path
ボリュームのルートではなく、その中のサブディレクトリを使用したいケースで使用する。

- Default Create Size
作成されるボリュームのデフォルトサイズ。

- Logging level
ログレベル。

Generatorから生成した構成ファイルの内容をコピーし、/etc/rexray/config.ymlとして保存します。

```shell-session:config.yml
libstorage:
  service: scaleio
scaleio:
  insecure: true
  thinOrThick: ThinProvisioned
  password: Password123
  endpoint: https://172.16.5.1/api
  systemID: 7489376b176d3545
  protectionDomainID: 1947f06b00000000
  storagePoolID: 1f63dc4100000000
  userName: admin
```

## サービス起動
あとはrexrayのサービスを起動するだけです。
`rexray start`

あとはdockerからrexrayドライバーを指定してボリュームを作成し、コンテナにアタッチすれば使えます。

## ボリューム作成

```shell-session
[root@sunny ~]# docker volume create --driver rexray --opt size=20 --name rexray01
rexray01
[root@sunny ~]# docker volume ls
DRIVER              VOLUME NAME
local               b09d0a175d914c7f24fcf877aeeb232f80d348b87e52841f8fc388d606c34247
rexray              rexray01
rexray              vol01
[root@sunny ~]#
[root@sunny ~]# docker run -d -P --name mycent -v rexray01:/hostdir -it centos
8ee46c9c0587673049e19dadbb4b484e4d88b0d02164d416ce6a16d7fb2ce473
[root@sunny ~]# docker exec -it mycent bash
[root@8ee46c9c0587 /]# df -h
Filesystem                                                                                           Size  Used Avail Use% Mounted on
/dev/mapper/docker-253:0-134453907-cfc165d25365ac6c7e6effcc956ac2a4db3a412ddfd1d8ad831057a884c0ffef   10G  237M  9.8G   3% /
tmpfs                                                                                                1.4G     0  1.4G   0% /dev
tmpfs                                                                                                1.4G     0  1.4G   0% /sys/fs/cgroup
/dev/scinib                                                                                           24G   45M   23G   1% /hostdir
/dev/mapper/centos-root                                                                               38G  3.3G   35G   9% /etc/hosts
shm                                                                                                   64M     0   64M   0% /dev/shm
tmpfs                                                                                                1.4G     0  1.4G   0% /sys/firmware
[root@8ee46c9c0587 /]#
```

今回はSwarm環境で使うため、両方のノードにてRexRayをインストールしておきます。

# Swarm service(stack)にRexRayのボリュームをアサイン
以下のようにdocker-compose.ymlにVolumeの情報を追記します。注意として、Volumeの定義をまずトップレベルに実施し、Serviceの定義内でそれを指定する、という形になっている点です。externalというフラグがないと新しいボリュームが切られてしまいます。この例はQuickStartの内容をそのまま流用しているため、本来Persistent Storage不要なWebサービスを使っていますが、機能確認の目的は果たせるため、目をつぶります。

```shell-session:docker-compose.yml
version: "3"
volumes:
    rexray01:
      external:
        name: 'rexray01'
services:
  web:
    image: keisuke1208/test:test
    volumes:
      - rexray01:/rexray01
    deploy:
      replicas: 3
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:
```

起動すると、

```shell-session
[root@sunny pstorage]# docker stack deploy -c docker-compose.yml pstorage
Creating network pstorage_webnet
Creating service pstorage_web
[root@sunny pstorage]#
[root@sunny pstorage]# docker stack ps pstorage
ID            NAME                IMAGE                  NODE                 DESIRED STATE  CURRENT STATE           ERROR                             PORTS
jrlkh7b1bucx  pstorage_web.1      keisuke1208/test:test  rainy.weather.local  Running        Running 36 seconds ago                 
ih2m7ufi1uy1  pstorage_web.2      keisuke1208/test:test  rainy.weather.local  Running        Running 13 seconds ago                 
80k0pwl1s7xe   \_ pstorage_web.2  keisuke1208/test:test  sunny.weather.local  Shutdown       Failed 19 seconds ago   "starting container failed: er…"
odggwtujqsyx  pstorage_web.3      keisuke1208/test:test  rainy.weather.local  Running        Running 32 seconds ago                 
ule73yqg0uw6   \_ pstorage_web.3  keisuke1208/test:test  sunny.weather.local  Shutdown       Failed 38 seconds ago   "starting container failed: er…"
[root@sunny pstorage]#
```

どうも片方のホストでしか起動しません。Errorメッセージが切れてしまっていますが、これは--no-truncオプションを入れるとすべて見ることができます。

```shell-session
[root@sunny pstorage]# docker stack ps pstorage --no-trunc
ID                         NAME                IMAGE                                                                                          NODE                 DESIRED STATE  CURRENT STATE          ERROR  PORTS
jrlkh7b1bucxht7tyu3qgrymi  pstorage_web.1      keisuke1208/test:test@sha256:a1e7034a88bc3f272ea0ec78845a0c13824ce4635dc3b88e3b5a990c8adfd788  rainy.weather.local  Running        Running 2 minutes ago
ih2m7ufi1uy1vccocw33pnlci  pstorage_web.2      keisuke1208/test:test@sha256:a1e7034a88bc3f272ea0ec78845a0c13824ce4635dc3b88e3b5a990c8adfd788  rainy.weather.local  Running        Running 2 minutes ago
80k0pwl1s7xetpyay9h9uevt0   \_ pstorage_web.2  keisuke1208/test:test@sha256:a1e7034a88bc3f272ea0ec78845a0c13824ce4635dc3b88e3b5a990c8adfd788  sunny.weather.local  Shutdown       Failed 2 minutes ago   "starting container failed: error while mounting volume '/': VolumeDriver.Mount: {"Error":"resource not found"}
"
odggwtujqsyxrlevbon33z69c  pstorage_web.3      keisuke1208/test:test@sha256:a1e7034a88bc3f272ea0ec78845a0c13824ce4635dc3b88e3b5a990c8adfd788  rainy.weather.local  Running   Running 2 minutes ago
ule73yqg0uw6wctiu0q6b0uk6   \_ pstorage_web.3  keisuke1208/test:test@sha256:a1e7034a88bc3f272ea0ec78845a0c13824ce4635dc3b88e3b5a990c8adfd788  sunny.weather.local  Shutdown  Failed 2 minutes ago   "starting container failed: error while mounting volume '/': VolumeDriver.Mount: {"Error":"volume already attached to a host"}
"
```

どうやらボリュームが取れていないようです。ScaleIO側から見ると、rainy(172.16.5.2)しかマップできていません。

```shell-session
[root@sunny pstorage]# scli --query_volume --volume_name rexray01
>> Volume ID: c19deefe00000001 Name: rexray01 Thin-provisioned Size: 24.0 GB (24576 MB)
   Capacity in use: 540.0 MB (552960 KB)
   Trimmed capacity: 0 Bytes
   Storage Pool 1f63dc4100000000 Name: default
   Protection Domain 1947f06b00000000 Name: default
   Creation time: 2017-06-08 14:50:44
   Uses RAM Read Cache
   Read bandwidth:  0 IOPS 0 Bytes per-second
   Write bandwidth: 0 IOPS 0 Bytes per-second
   Mapped SDC:
      SDC ID: 8e950fab00000002 IP: 172.16.5.2 Name: N/A
```

もしかしてと思って調べてみると、
RexRayボリュームのマルチホストアサインは不可
https://github.com/codedellemc/rexray/issues/343

OpenStackもそうですが、マルチホストアサインってかなり鬼門なんでしょうか?
とにかく、現状では自分のやりたいことはこの構成ではできなさそうです。

# まとめ
ScaleIo + RexRayの組み合わせでは、複数ホストにスケールしたコンテナ群(Swarmのstack)に共有のPersistent storageを見せることはできなさそうです。別のアプローチを考える必要あり。