コンテナからブロックストレージをマウントする方法

IBM Cloud Kubernetes Service の デフォルトの永続ボリュームは、ファイルストレージです。一方、他のパブリッククラウドでは、ブロックストレージが主流のようです。ファイルストレージは、複数のポッドから同時にマウントできる利点があるのですが、ベースはNFSなので、ブロックストレージに比べると遅いという欠点があります。

そこで、IBM の HELMチャート [Helm chart to install IBM Cloud Block Storage plug-in](https://cloud.ibm.com/kubernetes/solutions/helm-charts/iks-charts/ibmcloud-block-storage-plugin) を使って、iSCSIベースのブロックストレージを利用する方法をみていきます。

![スクリーンショット 2019-05-13 0.57.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/7a718df7-da1e-9fa4-e636-ab075f791991.png)

## 前提条件

出来るだけ本文を短くするために、以下の前提条件は完了している処から、始めたいと思います。

* IBM Cloud のアカウントを持っている
* IBM Cloud のアカウントで Kubernetes を作成している
* IBM Cloud CLI がインストールされている
* IBM Cloud にログインして、ibmcloud と kubectlコマンドが利用できる
* HELMクライアントが、PCにインストールされている
* HELM tiller がクラスタにインストールされている。

## ブロックストレージ・プラグインの導入

セットアップはとても簡単で、以下のコマンドを実行するだけです。

~~~
$ helm install iks-charts/ibmcloud-block-storage-plugin
~~~

インストール後の確認です。HELMのデプロイ、ポッドの稼働、ストレージクラスの追加が確認できます。

~~~
$ helm list
NAME                         	REVISION	UPDATED                 	STATUS  	CHART                              	APP VERSION	NAMESPACE
ibmcloud-block-storage-plugin	1       	Sun May 12 17:03:10 2019	DEPLOYED	ibmcloud-block-storage-plugin-1.4.0	           	default

$ kubectl get pod -n kube-system | grep block
ibmcloud-block-storage-driver-9br8x                               1/1     Running   0          6h
ibmcloud-block-storage-driver-s5g7n                               1/1     Running   0          6h
ibmcloud-block-storage-plugin-8cf94597d-79c8q                     1/1     Running   0          6h

$ kubectl get storageclasses | grep block
ibmc-block-bronze                      ibm.io/ibmc-block   6h
ibmc-block-custom                      ibm.io/ibmc-block   6h
ibmc-block-gold                        ibm.io/ibmc-block   6h
ibmc-block-retain-bronze               ibm.io/ibmc-block   6h
ibmc-block-retain-custom               ibm.io/ibmc-block   6h
ibmc-block-retain-gold                 ibm.io/ibmc-block   6h
ibmc-block-retain-silver               ibm.io/ibmc-block   6h
ibmc-block-silver                      ibm.io/ibmc-block   6h
~~~

## ポッド内コンテナからブロックストレージのマウント

PersitentVolumeClaim を作成することで、クラウドサービスのブロックストレージを、自動でオーダーして、Kubernetesから利用できるようになります。


~~~file:pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: claim1-block-bronze
  annotations:
    volume.beta.kubernetes.io/storage-class: "ibmc-block-bronze" # ストレージクラスの指定
  labels:
    billingType: "hourly" # 課金期間の指定 [hourly | monthly (default)]
spec:
  accessModes:
    - ReadWriteOnce # このアクセスモードは、一つのポッドからのみ読み書き可能
  resources:
    requests:
      storage: 20Gi # 最小注文単位は20Gバイト
~~~


上記のPVC(永続ボリューム要求）をマウントするポッドを作るマニフェストです。Ubuntuのコンテナが終了しないように、コマンドで止めておきます。


~~~file:pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1-claim1
spec:
  containers:
  - image: ubuntu:16.04
    name: container-name
    volumeMounts:
    - mountPath: /mnt
      name: pvc-name
    command: ["/usr/bin/tail","-f","/dev/null"]
  volumes:
  - name: pvc-name
    persistentVolumeClaim:
      claimName: claim1-block-bronze
~~~


## ポッドの作成と動作の確認

前述のPVCを作成するマニフェストを適用して、確認します。

~~~
$ kubectl apply -f pvc.yaml
persistentvolumeclaim/claim1-block-bronze created
~~~

しばらくすると、ブロックストレージがプロビジョニングされます。

~~~
$ kubectl get pvc
NAME                  STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        AGE
claim1-block-bronze   Bound    pvc-402935c6-74bf-11e9-8042-96c07cc2a570   20Gi       RWO            ibmc-block-bronze   8m52s
~~~

これで永続ボリューム(PersistentVolume)をマウントするポッドを立ち上げる準備ができたので、ポッド作成のマニフェストを適用します。

~~~
$ kubectl apply -f pod.yaml

<1分程度経過後＞

$ kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
pod1-claim1   1/1     Running   0          110s
~~~

次に、このポッドに対話型シェルを起動して、マウントしているファイルシステムのリストを表示します。
/mntは、ブロックストレージですが、ファイルシステムがフォーマットされ、マウントされています。

~~~
$ kubectl exec -it pod1-claim1 bash
root@pod1-claim1:/# df -h
Filesystem                                     Size  Used Avail Use% Mounted on
overlay                                         99G  2.5G   91G   3% /
tmpfs                                           64M     0   64M   0% /dev
tmpfs                                          2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/mapper/3600a09803830475a37244d486368446d   20G   44M   20G   1% /mnt
<以下省略>
~~~

ブロックストレージをマウントしたファイルシステム /mnt へファイルを書き込んでみます。

~~~
root@pod1-claim1:/# cd /mnt
root@pod1-claim1:/mnt# ls -la
total 24
drwxr-xr-x 3 root root  4096 May 12 14:18 .
drwxr-xr-x 1 root root  4096 May 12 14:19 ..
drwx------ 2 root root 16384 May 12 14:18 lost+found
root@pod1-claim1:/mnt# ls -lR /usr > ls-lR.txt
root@pod1-claim1:/mnt# ls -al
total 252
drwxr-xr-x 3 root root   4096 May 12 14:38 .
drwxr-xr-x 1 root root   4096 May 12 14:19 ..
drwx------ 2 root root  16384 May 12 14:18 lost+found
-rw-r--r-- 1 root root 231938 May 12 14:38 ls-lR.txt
~~~

ポッドを削除しても、データが消えない事を確認するために、ポッドを終了して、別のポッドで、同じPVCをマウントします。

~~~
$ kubectl delete pod pod1-claim1
pod "pod1-claim1" deleted
~~~

別のポッドとして、Ubuntuの最新バージョン 18.04 のコンテナを起動します。

~~~
$ cat pod-b.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod2-claim1
spec:
  containers:
  - image: ubuntu:18.04
    name: container-name
    volumeMounts:
    - mountPath: /mnt
      name: pvc-name
    command: ["/usr/bin/tail","-f","/dev/null"]
  volumes:
  - name: pvc-name
    persistentVolumeClaim:
      claimName: claim1-block-bronze

$ kubectl apply -f pod-b.yaml
pod/pod2-claim1 created
~~~

ポッド起動後に、対話型シェルを起動して、ファイルを確認すると、確かに存在していることが解ります。

~~~
$ kubectl exec -it pod2-claim1 bash
root@pod2-claim1:/# df -h
Filesystem                                     Size  Used Avail Use% Mounted on
overlay                                         99G  2.7G   91G   3% /
tmpfs                                           64M     0   64M   0% /dev
tmpfs                                          2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/mapper/3600a09803830475a37244d486368446d   20G   45M   20G   1% /mnt
/dev/mapper/docker_data                         99G  2.7G   91G   3% /etc/hosts
shm                                             64M     0   64M   0% /dev/shm
tmpfs                                          2.0G   12K  2.0G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                                          2.0G     0  2.0G   0% /proc/acpi
tmpfs                                          2.0G     0  2.0G   0% /sys/firmware
tmpfs                                          2.0G     0  2.0G   0% /proc/scsi
root@pod2-claim1:/# ls -al /mnt
total 252
drwxr-xr-x 3 root root   4096 May 12 14:38 .
drwxr-xr-x 1 root root   4096 May 12 14:43 ..
drwx------ 2 root root  16384 May 12 14:18 lost+found
-rw-r--r-- 1 root root 231938 May 12 14:38 ls-lR.txt
~~~

## まとめ

ブロックストレージは、HELMのチャートを利用することで、簡単に利用できる。また、iSCSIの場合は、コンテナから直接マウントするしかなかったが、プラグインを利用することで、pvcを使ってオートプロビジョニングで利用できるようになった。 実態は Endurance Storage や Performance Storage のiSCSIストレージのため、大容量で高速なブロック・ストレージを利用すれば、データベースなどのステートフルセットのボリュームとして、有用性が高いと考えられる。


## 参考資料
[1] Helm chart to install IBM Cloud Block Storage plug-in、https://cloud.ibm.com/kubernetes/solutions/helm-charts/iks-charts/ibmcloud-block-storage-plugin
[2] IBM Cloud の IBM ブロック・ストレージへのデータの保管 ,https://cloud.ibm.com/docs/containers?topic=containers-block_storage