Red Hat OpenShift on IBM Cloudで、Block Storage for VPCをPVとして使ってみる

# はじめに
コンテナはそれ自体ではデータの永続化ができないため、永続化のボリュームを定義・マウントし、そこにデータを保管する必要があります。Kubernetes(およびOpenShift)では、Persistent Volume(PV)というリソースで永続化ボリュームを扱います。

IBM Cloud上のOpenShift環境である「Red Hat OpenShift on IBM Cloud」では、IBM CloudのVPCで提供されるブロック・ストレージである「Block Storage for VPC」をPVとして利用することができます。

Block Storage for VPCは、アクセスモードとして、単一のNodeに対して割り当てられ、そのNodeでのみ使用可能なReadWriteOnce(RWO)が使用可能です。複数のNodeで共用可能なReadOnlyMany(ROX)やReadWriteMany(RWX)は使用できません。

Block Storage for VPCを使用する場合、PVの動的なプロビジョニングが可能となっています。あらかじめPVを定義しておかなくても、PVの使用要求(こういったサイズ、アクセスモードのPVを要求する)Persistent Volume Claim(PVC)の内容に基づき、動的にPVを作成・割り当てしてくれます。

動的プロビジョニングを使用する場合、IBM Cloudであらかじめ定義されたストレージクラス、または、独自にカスタム定義したストレージクラスの中からストレージクラスを選択します。カスタム定義のストレージクラスでは、ストレージのIOPSや、PVCを削除したときに当該ストレージを同時に削除するかどうか、ストレージのサイズ範囲、暗号化有無などを設定することができます。

ここでは、あらかじめ定義されたストレージクラスで動的プロビジョニングを使用し、PVC、PV、および、それを割り当てたアプリケーションをデプロイしてみます。
（手順は、IBM Cloudのドキュメント「[Block Storage for VPC (第 1 世代および第 2 世代コンピュート) へのデータの保管](https://cloud.ibm.com/docs/openshift?topic=openshift-vpc-block)」を参照しています)

# 実施にあたっての前提
- Red Hat OpenShift on IBM Cloudのクラスターが作成済みであること
- oc login済みであること

# PVC、PVの作成
まずは作成するPVCやアプリケーション用のプロジェクトを作成します。

```
> oc new-project blockstorage-sample
```

作成したプロジェクト内で、以下のマニフェストファイルでPVCを作成します。このマニフェストファイルでは、アクセスモードをReadWriteOnce(RWO)とし、サイズが10GB、ストレージクラスとして[3 IOPS/GBプロファイルのibmc-vpc-block-general-purpose](https://cloud.ibm.com/docs/openshift?topic=openshift-vpc-block#vpc-block-add)を設定しています。

```yaml:pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: my-pvc
spec:
 accessModes:
 - ReadWriteOnce
 resources:
   requests:
     storage: 10Gi
 storageClassName: ibmc-vpc-block-general-purpose
```

作成したマニフェストファイルをapplyします。

```
❯ oc apply -f pvc.yaml
persistentvolumeclaim/my-pvc created
```

作成されたPVC、および、動的プロビジョニングにより作成されたPVを確認します。

```
❯ oc get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS                     REASON   AGE
persistentvolume/pvc-71577f21-2371-4d1c-97d9-e0f017a2bb28   10Gi       RWO            Delete           Bound    blockstorage-sample/my-pvc   ibmc-vpc-block-general-purpose            71s

NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                     AGE
persistentvolumeclaim/my-pvc   Bound    pvc-71577f21-2371-4d1c-97d9-e0f017a2bb28   10Gi       RWO            ibmc-vpc-block-general-purpose   101s
```


IBM Cloud側で、作成されたストレージがどのようになっているか確認します。[IBM CloudのVPCブロック・ストレージ・ボリュームのページ](https://cloud.ibm.com/vpc-ext/storage/storageVolumes)にアクセスします。

赤枠で囲った部分が作成されたストレージです。PVCで定義した通り、10GBのブロック・ストレージが作成されていることが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/863b9d34-a138-00e6-7fa6-46dd47c1e3bd.png)


# PVをマウントしたアプリケーションのデプロイ
次に、作成したPVをマウントしたアプリケーションをデプロイするため、以下のマニフェストファイルを作成します。ここでは、Alpineのイメージをそのまま使用しています。また、「/mydata」というパスにマウントするように定義しています。

```yaml:deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: my-deployment
 labels:
   app: my-app
spec:
 selector:
   matchLabels:
     app: my-app
 template:
   metadata:
     labels:
       app: my-app
   spec:
     containers:
     - image: alpine
       name: my-container
       command: ["tail", "-f", "/dev/null"]
       volumeMounts:
       - name: my-volume
         mountPath: /mydata
       resources:
        limits:
          cpu: "100m"
          memory: "100Mi"
        requests:
          cpu: "100m"
          memory: "100Mi"
     volumes:
     - name: my-volume
       persistentVolumeClaim:
         claimName: my-pvc
```

作成したマニフェストファイルをapplyします。

```
❯ oc apply -f deployment.yaml
deployment.apps/my-deployment created
```


しばらく待ち、Podの状態がRunningになっていることを確認します。

```
❯ oc get pods
NAME                            READY   STATUS    RESTARTS   AGE
my-deployment-c79dfcd7d-ddmr9   1/1     Running   0          5m16s
```

作成したdeploymentをdescribeしてみます。Volumes、Mountsの箇所で、/mydata にマウントされていることが分かります。

```
❯ oc describe deployment/my-deployment
Name:                   my-deployment
Namespace:              blockstorage-sample
CreationTimestamp:      Sun, 06 Dec 2020 00:38:23 +0900
Labels:                 app=my-app
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=my-app
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=my-app
  Containers:
   my-container:
    Image:      alpine
    Port:       <none>
    Host Port:  <none>
    Command:
      tail
      -f
      /dev/null
    Limits:
      cpu:     100m
      memory:  100Mi
    Requests:
      cpu:        100m
      memory:     100Mi
    Environment:  <none>
    Mounts:
      /mydata from my-volume (rw)
  Volumes:
   my-volume:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  my-pvc
    ReadOnly:   false
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   my-deployment-c79dfcd7d (1/1 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  7m36s  deployment-controller  Scaled up replica set my-deployment-c79dfcd7d to 1
```


コンテナに対してdfコマンドを実行し、ボリュームの状態を確認します。/mydata にマウントされたディスクとして約10GBのディスクの存在が確認できます。

```
❯ oc exec my-deployment-c79dfcd7d-ddmr9 -- df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  97.3G     11.1G     81.3G  12% /
tmpfs                    64.0M         0     64.0M   0% /dev
tmpfs                    14.5G         0     14.5G   0% /sys/fs/cgroup
shm                      64.0M         0     64.0M   0% /dev/shm
/dev/vda2                97.3G     11.1G     81.3G  12% /etc/resolv.conf
/dev/vda2                97.3G     11.1G     81.3G  12% /etc/hostname
/dev/vda2                97.3G     11.1G     81.3G  12% /etc/passwd
/dev/vdd                  9.8G     36.0M      9.7G   0% /mydata
/dev/vda2                97.3G     11.1G     81.3G  12% /etc/hosts
/dev/vda2                97.3G     11.1G     81.3G  12% /dev/termination-log
/dev/vda2                97.3G     11.1G     81.3G  12% /run/secrets
tmpfs                    14.5G     40.0K     14.5G   0% /run/secrets/kubernetes.io/serviceaccount
tmpfs                    14.5G         0     14.5G   0% /proc/acpi
tmpfs                    64.0M         0     64.0M   0% /proc/kcore
tmpfs                    64.0M         0     64.0M   0% /proc/keys
tmpfs                    64.0M         0     64.0M   0% /proc/timer_list
tmpfs                    64.0M         0     64.0M   0% /proc/timer_stats
tmpfs                    64.0M         0     64.0M   0% /proc/sched_debug
tmpfs                    14.5G         0     14.5G   0% /proc/scsi
tmpfs                    14.5G         0     14.5G   0% /sys/firmware
```

以上です。