OCS(OpenShift Container Storage)をインターナルモードで作成する

# 1. はじめに

既存の OpenShift Cluster の中に3本の`Workerノード`を使った`OCS(OpenShift Container Storage)`の`Cluster`を作成してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/fb8983af-7b6a-b0ff-7260-0c4ec2603688.png)


`OCS`のデータ領域は、各`Storage Node`に追加した内蔵ディスクを使用する事にします。

この手順は、`OCS(OpenShift Container Storage)` 4.5 を元に作成しています。また、公式ドキュメントの [ベアメタルインフラストラクチャーを使用した OPENSHIFT CONTAINER STORAGE のデプロイ](https://access.redhat.com/documentation/ja-jp/red_hat_openshift_container_storage/4.5/html/deploying_openshift_container_storage_using_bare_metal_infrastructure/index)を参考にしました。

この手順で使用した`OCS`のバージョンは、4.5です。

# 2. OCSノードのサイジング

`OCS`のデプロイ方法は、**インターナル**と**エクスターナル**がありますが、ここでは**インターナル**モードを使用します。
**インターナル**と**エクスターナル**の違いは、既存の`OpenShift`クラスターの内部に`OCS`があるか外部に独立したクラスターとして存在するかの差です。

**インターナル**モードでは、`OCS`のストレージを持ったノードも、既存`OpenShift`クラスター内の`Workerノード`として存在しています。
コンピュートもストレージも、`OpenShift`単一クラスター内のリソースとして扱う事ができ、シンプルな構成になります。

使用する `ノード`の `OS`は、Red Hat `CoreOS`を使用します。

`OCS`には、最小要件として[以下の要件](https://access.redhat.com/documentation/en-us/red_hat_openshift_container_storage/4.5/html-single/planning_your_deployment/index#resource-requirements_rhocs)があります。

* 30vCPU(10vCPUx3) 
* 72GB(24GB x 3) Memory
* 3(1 x 3) storage device

※ここでの vCPUは、Intel HyperThreading ON 時の仮想コアを示しています。

ですが、このリソースで実際に構成してみると、メモリが足りず、一部の`Pod`が起動しない現象が見て取れたので(細かく確認してませんが、他の`Pod`が`OCS`用のノードに乱入してきたせいかもしれません) 、もう少し増やして、以下の構成にしました。

* 48vCPU(16vCPUx3) 
* 96GB(32GB x 3) Memory
* 3(1 x 3) storage device

さらに言うと、インストールの途中の`User Interface`で、`16CPU 64GB`以上の`ノード`を3本用意するように言ってくる部分があります。
が今回は、そこまで富豪な構成は用意できなかったので、メモリに関しては`64GB`→`32GB`としています。

各、`ノード`に、OSを導入するストレージ領域に追加して、データー領域として１TBの容量を追加しました。
各`ノード`構成は以下の通りです。

| サーバー                    | vCPU(HT-on)   | Memory       |  OS Disk | 追加Disk |  OS   |         ホスト名            | IP Address  
|:---------------------------|:--------------|:-------------|:--------|:--------|:--------|:---------------------------|:------------
|OCSノード 1               | 16vCPU         | 32GByte     | 60G    | 1024G    | CoreOS |s1.ocp45.example.localdomain |172.16.0.51 |     | 
|OCSノード 2                | 16vCPU         | 32GByte     | 60G    |  1024G    |CoreOS |s2.ocp45.example.localdomain|172.16.0.52 |     | 
|OCSノード 3                | 16vCPU         | 32GByte     | 60G    | 1024G    | CoreOS |s3.ocp45.example.localdomain|172.16.0.53 |     | 

`Workerノード` に、`OCS`の必要なコンテナを導入したノードを`OCSノード`と呼ぶ事にします。
この3本の`OCSノード`が`OCS`として分散ストレージを形成します。

`OCS`では、最低3本の `Workerノード`が基本単位として必要になります。ストレージの容量を追加する場合も3本づつ`Workerノード`を追加していきます。

# 3. OCSノードのインストール

それでは、`OCSノード`を作成して行きます。

## 3.1. VMware を OCSノードに使用する場合の注意点

この手順では、`ノード`に追加した内蔵ディスクを`OCS`のデータ領域として構成します。

VMware の仮想マシンを `OCSノード` に使用する場合「仮想マシンオプション」で、`disk.EnableUUID` を `true` にしないと、構成に必要なディスクの `by-id`が表示されない場合があるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/1b6cf9e7-d26c-de45-5d41-7c935adfd79a.png)


## 3.2.Workerノードの作成

通常の `Workerノード` と同様に以下の手順になります。

1.ホスト名とIPアドレスの決定
2.`DHCP`サーバーに、`MACアドレス`に結びつけて固定IPを配れるように設定
3.`DNS`サーバーに`OCSノード`として使用する`Woker Node`のホスト名を登録(逆引きも)
4.`CoreOS`をインストール開始。`Workerノード`の `Inginiton file`を使って `Workerノード`として構成
5.`Woker Node`の`CSR`を`approve`

`Core OS`のインストール方法については、ISOイメージからインストールする方法と、`iPXE`等を使ったネットワークインストールする方法があります。いずれのケースで`OpenShift`の`Woker Node`として構成する必要があります。

通常`OCS`を**インターナル**モードで導入する場合は、既に`OpenShift`クラスターが存在しており、`Workerノード`の導入手順は確立していると思いますので、ここでは、`CoreOS`をインストール・構成して`Woker Node`として `OpenShift`クラスターに追加する方法については省略します。

## 3.3.OCSインストール対象Nodeのラベリング

`Workerノード`が完成したら、完成した 3つの `Workerノード`に以下のコマンドで、ラベルをつけ`OCSノード`化をして行きます。
インストール時に、このラベルがある所に、必要な`Pod`がスケジュールされるようになっています。

```
oc label nodes <NodeNames> cluster.ocs.openshift.io/openshift-storage=''
```

この手順では、以下のようにコマンドを実行してラベルをつけます。

```
oc label nodes s1.ocp45.example.localdomain cluster.ocs.openshift.io/openshift-storage=''
oc label nodes s2.ocp45.example.localdomain cluster.ocs.openshift.io/openshift-storage=''
oc label nodes s3.ocp45.example.localdomain cluster.ocs.openshift.io/openshift-storage=''
```

ラベルが付いている事を確認します。

```
# oc get nodes -l cluster.ocs.openshift.io/openshift-storage -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}'
s1.ocp45.example.localdomain
s2.ocp45.example.localdomain
s3.ocp45.example.localdomain
# 
```

以上で、`OCS`をインストールする`OCSノード`の準備ができました。

# 4. OCS Operator のインストール

`OperatorHub`から`OpenShift Container Storage`を検索してクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/4bb66acb-d4d7-d93c-4b0a-3357a3dd3fdf.png)

`Install`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/68b09c8d-5547-000f-1efd-7b09130221dc.png)

`Install Operator`で必要な項目を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/2fa840a2-9114-ab0b-aa10-600a8f5a5d1a.png)
`Enable operator recommended cluster monitoring on this namespace` だけは、デフォルトでチェックが入ってないはずなので、チェックします。それ以外はデフォルトのままで大丈夫なはずですが、

**Update Channel** は、`stable-4.5`
**Installation Mode** は、`A specific namespace on the cluster`
**Installed Namespace** は、`openshift-storage`
**Approval　Strategy** は、`Automatic` (※)

である事を確認します。

※この例では**Approval　Strategy** は、`Automatic`を選択しましたが、アップデート時は`OCS`クラスターが非常に不安定になります。実際の運用を考えるとこの部分は、個人的には`Manual`にしておき、意図せぬアップデートが起こらないようにしておくのが良いと思います。



確認したら`Isntall`をクリックします。

`Installed Operators`に自動で画面が遷移するはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/c1d49920-f5ef-6af5-a424-5a12d9d74e0b.png)

環境にも依存しますが`OpenShift Container Storage`が`Succceeded`になるまで数分かかるはずです。

# 5.Local Storage Operator のインストール

続いて`Local Storage Operator`を導入します。

## 5.1. namespace の作成

`OPERATOR`のインストール前の準備として`local-storage`という`namespace`を作成します。
`Administration`->`Namespaces` に移動して、`Create Namespace`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/a64c2273-a4b9-4c1e-7a94-c0228b93d965.png)

新しく作成する `Namespace`名として `local-storage`と入力します。**Default Network Policy**は、デフォルトで`No restrictions`が選択されていればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/de739804-1aef-b859-5a3c-b8d6ee7cd4de.png)

`OperatorHub`から、`Local Storage`を検索します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/fad71c02-7154-2636-f057-68bf3dbbd923.png)

`Install`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/ebe62282-6825-4335-1761-1eb0791e6969.png)

**Install Operator**という画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/2f601bcd-6ee4-50da-8259-f4e3ac1e76ad.png)

**Installed Namespace**で、先ほど作成した`lcoal-storage`という`Namespace`が選択されているのを確認します。

それ以外は、基本的にデフォルトで設定されているはずですが、

**Update Channel**が、4.5
**Installation Mode**が、`A specific namespace on the cluster`
**Approval Stragegy**が、`Automatic` (※)

である事を確認します。大丈夫であれば、`Install`をクリックします。

※この例では**Approval　Strategy** は、`Automatic`を選択しましたが、アップデート時は`OCS`クラスターが非常に不安定になります。実際の運用を考えるとこの部分は、個人的には`Manual`にしておき、意図せぬアップデートが起こらないようにしておくのが良いと思います。


 `Operators`->`Installed Operators`に自動で画面が遷移するはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/592299b3-02bc-53f9-7075-ee1aa9352c4a.png)

`Local Storage`が、`Succeeded`になれば完了です。すぐに`Succeeded`になるはずです。

## 5.2. LocalVoume の作成

### 5.2.1. 利用可能なデバイスの検索

各`OCSノード`から、データ領域に使用するデバイスの情報を集めて行きます。

まず、`s1.ocp45.example.localdomain` に対して、`oc debug node/<OCSノード名>`でログインして情報を集めます。

```shell-session
# oc debug node/s1.ocp45.example.localdomain
Starting pod/s1ocp45examplelocaldomain-debug ...
To use host binaries, run `chroot /host`
Pod IP: 172.16.0.51
If you don't see a command prompt, try pressing enter.
sh-4.2# chroot /host                               <== 入力
sh-4.4# lsblk                            　　　　　 <== 入力
NAME                         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                            8:0    0   60G  0 disk
|-sda1                         8:1    0  384M  0 part /boot
|-sda2                         8:2    0  127M  0 part /boot/efi
|-sda3                         8:3    0    1M  0 part
`-sda4                         8:4    0 59.5G  0 part
  `-coreos-luks-root-nocrypt 253:0    0 59.5G  0 dm   /sysroot
sdb                            8:16   0    1T  0 disk
sr0                           11:0    1 1024M  0 rom
```

上記の例で`sdb`が、データ領域用に追加した`disk`です。この`disk`の`by-id`を調べます。
※1) VMWareの場合は、同じデバイスに対して複数のby-idが表示される事があるようですが、以下のサンプルのフォーマットと同じものをメモして下さい
※2) 記事公開後、`by-id` の簡単な集め方として、`kubectl logs`を使用する方法を教えて頂きました！以下のKBが出ています。<a href="https://access.redhat.com/solutions/4928841">How to list the local disk IDs for every OCS worker in Openshift 4.x</a>

```
sh-4.4# ls -l /dev/disk/by-id/ | grep sdb 
lrwxrwxrwx. 1 root root  9 Oct 22 15:47 scsi-36000c290ef83f5ddee94f3e43dcb6197 -> ../../sdb
```

同様の作業を残り２本の`OCSノード`に対しても行います。

`s2.ocp45.example.localdomain` に対して同様の確認を行います。

```
sh-4.4#  ls -l /dev/disk/by-id/ | grep sdb 
lrwxrwxrwx. 1 root root  9 Oct 22 15:57 scsi-36000c29af3872df29dc0cf11fc1b0e08 -> ../../sdb
sh-4.4#
```

`s3.ocp45.example.localdomain` に対して同様の確認を行います。

```
sh-4.4# ls -l /dev/disk/by-id/ | grep sdb 
lrwxrwxrwx. 1 root root  9 Oct 22 15:57 scsi-36000c294793b7f8acdd6584ff588cecc -> ../../sdb
sh-4.4#
```

以上でそれぞれの`OCSノード`の `disk`の`by-id`がわかりました。
次のステップで使用するのでパスを含めて以下のように整形してメモしておきます。

```
/dev/disk/by-id/scsi-36000c290ef83f5ddee94f3e43dcb6197    # OCSノード 1
/dev/disk/by-id/scsi-36000c29af3872df29dc0cf11fc1b0e08    # OCSノード 2
/dev/disk/by-id/scsi-36000c294793b7f8acdd6584ff588cecc    # OCSノード 3
```

次のステップでは、集めた情報を使って`yaml`ファイルを作成します。

### 5.2.2. Custom Resource (LocalVolume) の作成

前のステップで集めた`disk`の情報を使って`OCS`の`CR(Custom Resource)`を作成します。
`local-storage-block.yaml`という名前の以下のファイルを作成します。

```local-storage-block.yaml
apiVersion: local.storage.openshift.io/v1
kind: LocalVolume
metadata:
  name: local-block
  namespace: local-storage
  labels:
    app: ocs-storagecluster
spec:
  nodeSelector:
    nodeSelectorTerms:
    - matchExpressions:
        - key: cluster.ocs.openshift.io/openshift-storage
          operator: In
          values:
          - ""
  storageClassDevices:
    - storageClassName: localblock
      volumeMode: Block
      devicePaths:
        - /dev/disk/by-id/scsi-36000c290ef83f5ddee94f3e43dcb6197   # OCSノード 1
        - /dev/disk/by-id/scsi-36000c29af3872df29dc0cf11fc1b0e08    # OCSノード 2
        - /dev/disk/by-id/scsi-36000c294793b7f8acdd6584ff588cecc   # OCSノード 3
  tolerations:                              
  - effect: NoSchedule                     
    key: node.ocs.openshift.io/storage 
    value: "true"                       
```

作成したファイルを`apply`します。

```
oc create -f local-storage-block.yaml
```

`Pod`が作成されているか確認します。

```
# oc get pod -n local-storage
NAME                                      READY   STATUS    RESTARTS   AGE
local-block-local-diskmaker-mv5xb         1/1     Running   0          50s
local-block-local-diskmaker-nkfdw         1/1     Running   0          50s
local-block-local-diskmaker-r8gg2         1/1     Running   0          50s
local-block-local-provisioner-542k6       1/1     Running   0          50s
local-block-local-provisioner-cxhcl       1/1     Running   0          50s
local-block-local-provisioner-pnlhb       1/1     Running   0          50s
local-storage-operator-588b4686c6-2kllz   1/1     Running   0          126m
# 
```

`PV(Persistent Volume)`の作成を確認します。

```
# oc get pv
NAME                CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
local-pv-73dc6977   1Ti        RWO            Delete           Available           localblock              51s
local-pv-a3a35d00   1Ti        RWO            Delete           Available           localblock              40s
local-pv-b7abec06   1Ti        RWO            Delete           Available           localblock              40s
# 
```

`locakblock`という`Storage Class`の生成を確認します。

```
[root@bastion openshift]# oc get sc 
NAME         PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
localblock   kubernetes.io/no-provisioner   Delete          WaitForFirstConsumer   false                  63s
[root@bastion openshift]# 
```
## 5.3.Cluster Serviceの作成

`OpenShift`コンソールに移動し、`Installed Operators`で、`Project`で、`openshift-storage`を選択します。
`OpenShift Constainer Storage`をクリックします。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/1b7cda50-c2e1-5df1-119c-da09fcf2464f.png)

`Create OCS Cluster Service`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/b13fb3c8-ac82-4075-0640-751579027b2d.png)

**Create Storage Cluster**の設定画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/500a7df1-6c65-992e-bf2a-3b819e706614.png)


**Select Mode**は、`Internal`が選択されている事を確認します。
**Nodes**の項目では、`OCSノード`として作成した3本の`ノード`が選択されている事を確認します。
**Storage Class**は、`localblock`を選択します。

確認ができたら`Create`をクリックします。

# 6. OCS 作成の確認

## 6.1.Podの起動確認

`oc get pod -n openshift-storage` で、Pod が `Running`か`Completed`になるのを確認します。

```
[root@bastion openshift]# oc get pod -n openshift-storage
NAME                                                              READY   STATUS      RESTARTS   AGE
csi-cephfsplugin-7w52w                                            3/3     Running     0          7m26s
csi-cephfsplugin-b2lcg                                            3/3     Running     0          7m26s
csi-cephfsplugin-bq8s6                                            3/3     Running     0          7m26s
csi-cephfsplugin-n68pn                                            3/3     Running     0          7m26s
csi-cephfsplugin-provisioner-55d77c5b99-knr7h                     5/5     Running     0          7m25s
csi-cephfsplugin-provisioner-55d77c5b99-szs29                     5/5     Running     0          7m25s
csi-cephfsplugin-qfwhn                                            3/3     Running     0          7m26s
csi-cephfsplugin-rb6tr                                            3/3     Running     0          7m26s
csi-rbdplugin-69rll                                               3/3     Running     0          7m27s
csi-rbdplugin-fcvnb                                               3/3     Running     0          7m27s
csi-rbdplugin-ffbb7                                               3/3     Running     0          7m27s
csi-rbdplugin-kjcnq                                               3/3     Running     0          7m27s
csi-rbdplugin-provisioner-86d4877dd5-f8sl9                        5/5     Running     0          7m26s
csi-rbdplugin-provisioner-86d4877dd5-pld7c                        5/5     Running     0          7m26s
csi-rbdplugin-r5z7n                                               3/3     Running     0          7m27s
csi-rbdplugin-xslrh                                               3/3     Running     0          7m27s
noobaa-core-0                                                     1/1     Running     0          3m34s
noobaa-db-0                                                       1/1     Running     0          3m34s
noobaa-endpoint-65dcff66c5-dlnpf                                  1/1     Running     0          54s
noobaa-operator-54fd4c8b7b-269bn                                  1/1     Running     0          33m
ocs-operator-84bdd64c68-g2tqf                                     0/1     Running     0          33m
rook-ceph-crashcollector-s1.ocp45.example.localdomain-7f976xj2z   1/1     Running     0          6m51s
rook-ceph-crashcollector-s2.ocp45.example.localdomain-75b4vr5hp   1/1     Running     0          6m42s
rook-ceph-crashcollector-s3.ocp45.example.localdomain-57c82x9gk   1/1     Running     0          4m20s
rook-ceph-drain-canary-s1.ocp45.example.localdomain-67b469hmxcr   1/1     Running     0          3m37s
rook-ceph-drain-canary-s2.ocp45.example.localdomain-65f8bbhh8z9   1/1     Running     0          3m38s
rook-ceph-drain-canary-s3.ocp45.example.localdomain-cdd8b5kxrj2   1/1     Running     0          3m36s
rook-ceph-mds-ocs-storagecluster-cephfilesystem-a-5d48864cj72pg   1/1     Running     0          3m20s
rook-ceph-mds-ocs-storagecluster-cephfilesystem-b-6897d49fkfr72   1/1     Running     0          3m19s
rook-ceph-mgr-a-5f558b7854-zxx6w                                  1/1     Running     0          3m53s
rook-ceph-mon-a-74584cb98-g64dd                                   1/1     Running     0          6m51s
rook-ceph-mon-b-67c75d95f5-msm98                                  1/1     Running     0          6m42s
rook-ceph-mon-c-686b895696-pjxfb                                  1/1     Running     0          4m20s
rook-ceph-operator-75598ffcd9-hxb6b                               1/1     Running     0          33m
rook-ceph-osd-0-54f7bccc4f-4fdzr                                  1/1     Running     0          3m38s
rook-ceph-osd-1-6f8b5c7477-bhwcm                                  1/1     Running     0          3m37s
rook-ceph-osd-2-7fbffd4fc9-5wbgh                                  1/1     Running     0          3m36s
rook-ceph-osd-prepare-ocs-deviceset-0-data-0-dz69c-wws8c          0/1     Completed   0          3m49s
rook-ceph-osd-prepare-ocs-deviceset-1-data-0-5jtvr-tlxq4          0/1     Completed   0          3m48s
rook-ceph-osd-prepare-ocs-deviceset-2-data-0-ghnsr-dp7nk          0/1     Completed   0          3m47s
rook-ceph-rgw-ocs-storagecluster-cephobjectstore-a-568854f4fvgq   1/1     Running     0          2m48s
rook-ceph-rgw-ocs-storagecluster-cephobjectstore-b-5479655np5w7   1/1     Running     0          2m46s
[root@bastion openshift]# oc get pod -n openshift-storage | grep -v NAME | wc -l
42
[root@bastion openshift]#
```

上記の環境では、約8分くらいで全ての`Pod`が起動しました。

`csi plugin` は、この時点で`Masterノード`以外の全ノードに配られるので Node数によって出力行数は変わります。上記の環境は (Workerノード x 6, OCSノード x 3) の環境なので、`csi-cephfsplugin-xxxx` と `csi-rbdplugin-xxxx` が6個づつ存在しています

各`Pod`の役割については、[マニュアル](https://access.redhat.com/documentation/ja-jp/red_hat_openshift_container_storage/4.5/html/deploying_openshift_container_storage_using_bare_metal_infrastructure/verifying-openshift-container-storage-deployment_rhocs#verifying-the-state-of-the-pods_rhocs)に記載があるので、必要な数が起動してきているか確認します。

特に以下の部分は、比較的後から表示されます。

```
rook-ceph-osd-xxxxx
rook-ceph-osd-xxxxx
rook-ceph-osd-xxxxx
```

また、以下の`Pod`は、`0/1`が最終的に`1/1`になります。

```
ocs-operator-84bdd64c68-g2tqf                                     0/1     Running     0          33m
```

## 6.2.OCS Clusterのステータスの確認

`OpenShift`コンソールより、`OCS Cluster`の状態を確認します。
`Home`->`Overvirew`から`Persistent Storage`を選びます。
`Details`に内容が表示されていて、`Status`もグリーンになっている事を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/ec2a89c8-c8ae-caa0-62e2-a7766756b505.png)

## 6.3.Multicloud Object Gatewayの正常性の確認

`OpenShift`コンソールより、`Multicloud Object Gateway`の状態を確認します。
`Home`->`Overvirew`から`Object Service`を選びます。
`Details`に内容が表示されていて、`Status`もグリーンになっている事を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/225de65a-22a0-0f43-9fa0-5d960f4de6d6.png)

## 6.4.OCS の Storage Class の確認

4つの`Storage Class`が作成されているはずなので、確認します。

`ocs-storagecluster-ceph-rbd`　　
`ocs-storagecluster-cephfs`
`openshift-storage.noobaa.io`
`ocs-storagecluster-ceph-rgw`

が作成されている事を確認します。

**Storage**->**Storage Classes**から確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/f1e15e22-7433-0e7b-0f81-699ed82f21a3.png)

CLIでも確認できます。その場合は、`oc get storageclasses` を実行します。

```
[root@bastion ~]# oc get storageclasses
NAME                          PROVISIONER                             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
localblock                    kubernetes.io/no-provisioner            Delete          WaitForFirstConsumer   false                  2d10h
ocs-storagecluster-ceph-rbd   openshift-storage.rbd.csi.ceph.com      Delete          Immediate              true                   2d10h
ocs-storagecluster-ceph-rgw   openshift-storage.ceph.rook.io/bucket   Delete          Immediate              false                  2d10h
ocs-storagecluster-cephfs     openshift-storage.cephfs.csi.ceph.com   Delete          Immediate              true                   2d10h
openshift-storage.noobaa.io   openshift-storage.noobaa.io/obc         Delete          Immediate              false                  2d10h
[root@bastion ~]# 
```

以上で`OCS`のインストール確認は完了です。

# 7.ラベル、taint、tolerationの設計

実際の環境には、役割の違う`ノード`が混在します。

ここでは、以下のような構成を考えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/322e50d8-828d-5804-91cf-e007c5a02aa3.png)

`Masterノード` : コントロールプレーン
`ユーザーアプリ専用 Node` :　ユーザーのコンテナが稼働する`Workerノード`
`Infraノード` : 監視やログ収集のコンポーネントが稼働する`Workerノード`
`OCSノード` : OCS(OopenShift Container Storage)が稼働する`Wokrer Node`

で構成されています。

図の中で`OCS`の`ノード`に`cluster.ocs.openshift.io/openshift-storage=''`というラベルを貼っていますが、これはセクション[「3.3. OCSインストール対象Nodeのラベリング」](#33ocsインストール対象nodeのラベリング)で、行った手順です。`OCS`のメインのコンポーネントは、このラベルがある所にインストールされています。


## 7.1.Infra ラベルを貼る

動作に影響はしませんが、`OpenShift`は、ユーザーのアプリケーションを動かす`Workerノード`と、運用用途に使われる`Workerノード`を内部的に認識しています。

`OpenShift`から`OCSノード`が`infra(Infrastructure)`用の`ノード`と認識されるように`infra`と言う role ラベルをつけておきます。

以下のコマンドで、`Infraノード`としてのラベルを振ります。

```
oc label node s1.ocp45.example.localdomain node-role.kubernetes.io/infra=
oc label node s2.ocp45.example.localdomain node-role.kubernetes.io/infra=
oc label node s3.ocp45.example.localdomain node-role.kubernetes.io/infra=
```

`Workerノード`としてのラベルはつけたままにします。`Workerノード` のラベルを削除する事もできますが、単純に削除しただけだと、`OpenShift`から`Woker Node`とみなされなくなるため自動アップデート等の運用に問題が発生します。

```
[root@bastion openshift]# oc get nodes
NAME                           STATUS   ROLES          AGE   VERSION        
i1.ocp45.example.localdomain   Ready    worker         14h   v1.18.3+47c0e71
i2.ocp45.example.localdomain   Ready    worker         14h   v1.18.3+47c0e71
i3.ocp45.example.localdomain   Ready    worker         14h   v1.18.3+47c0e71
m1.ocp45.example.localdomain   Ready    master         15h   v1.18.3+47c0e71
m2.ocp45.example.localdomain   Ready    master         15h   v1.18.3+47c0e71
m3.ocp45.example.localdomain   Ready    master         15h   v1.18.3+47c0e71
s1.ocp45.example.localdomain   Ready    infra,worker   27m   v1.18.3+47c0e71
s2.ocp45.example.localdomain   Ready    infra,worker   28m   v1.18.3+47c0e71
s3.ocp45.example.localdomain   Ready    infra,worker   28m   v1.18.3+47c0e71
w1.ocp45.example.localdomain   Ready    worker         14h   v1.18.3+47c0e71
w2.ocp45.example.localdomain   Ready    worker         14h   v1.18.3+47c0e71
w3.ocp45.example.localdomain   Ready    worker         14h   v1.18.3+47c0e71
[root@bastion openshift]# 
```


## 7.2.toleration と taint を付ける

`OCSノード`に、ユーザーアプリの `Pod`がスケジュールされる可能性があります。
`OCSノード`に`taint`をつける事で、`toleration`を持っている`Pod`しかスケジュールされないようにします。

**予期せぬ事態を防ぐために、先に toleration をつけて、その後に taint を付ける事をおすすめします。**

### 7.2.1.LocalVolume に toleration を付ける

以前作成した`OCS`の`CR(Custom Resource)`である`LocalVolume` の `local-block` を編集して、`toleration`を付けます。

```
 oc edit LocalVolume local-block -n local-storage
```

`node.ocs.openshift.io/storage="true":NoSchedule` と言う`taint`があってもスケジュールされるように編集します。

実際には、この手順では`LocalVolume`リソースを作成した時に、既に`toleration`の定義を追加しているので、定義が存在している事を確認します。

```.yaml
<省略>
  name: local-block
  namespace: local-storage
  resourceVersion: "7632465"
  selfLink: /apis/local.storage.openshift.io/v1/namespaces/local-storage/localvolumes/local-block
  uid: ef7774a6-1496-484f-b50d-d47bc36456a5
spec:
  logLevel: Normal
  managementState: Managed
  nodeSelector:
    nodeSelectorTerms:
    - matchExpressions:
      - key: cluster.ocs.openshift.io/openshift-storage
        operator: In
        values:
        - ""
  storageClassDevices:
  - devicePaths:
    - /dev/disk/by-id/scsi-36000c290ef83f5ddee94f3e43dcb6197
    - /dev/disk/by-id/scsi-36000c29af3872df29dc0cf11fc1b0e08
    - /dev/disk/by-id/scsi-36000c294793b7f8acdd6584ff588cecc
    storageClassName: localblock
    volumeMode: Block
  tolerations:                               # toleration 追加されている事を確認
  - effect: NoSchedule                       # 追加を確認
    key: node.ocs.openshift.io/storage       # 追加を確認
    value: "true"                            # 追加を確認
<省略>
```


### 7.2.2.CSIプラグインPodに toleration を付ける

CSIプラグイン(Pod)は、`OCS`のストレージにアクセスするためにクラスターの全ての`ノード`に必要な`Pod`です。
`taint`が付いている`ノード`にもCSIプラグインをインストールするには、`toleration`を付けてあげる必要があります。
以下のコマンドで、`rook-ceph-operator`の`ConfigMap`を編集します。

```
oc edit configmap rook-ceph-operator-config -n openshift-storage
```

`#`の所がこの手順で変更した所です。

```yaml
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
       data:
        CSI_PLUGIN_TOLERATIONS: |2-
      
         - key: node.ocs.openshift.io/storage
           operator: Equal
           value: "true"
           effect: NoSchedule
         - key: infra                # tolerationの追加
           effect: NoSchedule        #
           value: reserved           #
         - key: infra                #
           effect: NoExecute         #
           value: reserved           #

 CSI_PROVISIONER_TOLERATIONS: |2-
         - key: node.ocs.openshift.io/storage
           operator: Equal
           value: "true"
           effect: NoSchedule

kind: ConfigMap
metadata:
 creationTimestamp: "2020-10-28T03:16:56Z"
 managedFields:
 - apiVersion: v1
 fieldsType: FieldsV1
 fieldsV1:
 f:data:
 .: {}
 f:CSI_PROVISIONER_TOLERATIONS: {}
 manager: ocs-operator
 operation: Update
 time: "2020-10-28T03:16:56Z"
 - apiVersion: v1
 fieldsType: FieldsV1
 fieldsV1:
 f:data:
 f:CSI_PLUGIN_TOLERATIONS: {}
 manager: oc
 operation: Update
 time: "2020-10-28T06:13:35Z"
 name: rook-ceph-operator-config
 namespace: openshift-storage
 resourceVersion: "572973"
 selfLink: /api/v1/namespaces/openshift-storage/configmaps/rook-ceph-operator-config
 uid: 9db6a13c-abc5-4623-9af3-a447a6dd9588
```

### 7.2.3.OCSノードに taint を付ける

`node.ocs.openshift.io/storage`=`"true"`:`NoSchedule` という`taint`を`OCSノード`に付けます。

以下のコマンドで、`OCSノード`に`taint`を付けます。

```
oc adm taint node s1.ocp45.example.localdomain node.ocs.openshift.io/storage="true":NoSchedule
oc adm taint node s2.ocp45.example.localdomain node.ocs.openshift.io/storage="true":NoSchedule
oc adm taint node s3.ocp45.example.localdomain node.ocs.openshift.io/storage="true":NoSchedule
```

`taint`は以下のコマンドで確認できます。

```
oc describe node <node名>
```

```
<省略>
Annotations:        machineconfiguration.openshift.io/currentConfig: rendered-infra-c5316746ee6f0621645031486cad5c02
                    machineconfiguration.openshift.io/desiredConfig: rendered-infra-c5316746ee6f0621645031486cad5c02
                    machineconfiguration.openshift.io/reason:
                    machineconfiguration.openshift.io/state: Done
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Thu, 22 Oct 2020 22:24:13 +0900
Taints:             node.ocs.openshift.io/storage=true:NoSchedule
Unschedulable:      false
<省略>
```


### 7.2.4.taint の削除
`taint`を付け間違った時は、最期に`-`を付ける事で消す事ができます。

```
oc adm taint node s1.ocp45.example.localdomain node.ocs.openshift.io/storage="true":NoSchedule-
```

# 8.補則

インストールを行ってみて、知っておいた方が良いと思った事を書いておきます。

## 8.1.OCSのuninstall

`OCS`のインストールは、基本 Operator によるインストールですが、これらの行った手順を単純に取り消しても、ゴミが残ってしまい、基本、元の状態に戻りません。

`OCS`4.5の時点で、`OCS`のアンインストールは、例えまだ`PVC`を作成してアプリケーションからボリュームを使用してない状態でも、コマンドラインから行う必要があります。`OpenShift Console` から、アンインストールをしても、インストール手順を逆になぞるだけでは完全に削除できないので、注意してください。

マニュアルにアンインストールの章があるので、それに沿って作業します。
<a href="https://access.redhat.com/documentation/ja-jp/red_hat_openshift_container_storage/4.5/html/deploying_openshift_container_storage_using_bare_metal_infrastructure/assembly_uninstalling-openshift-container-storage_rhocs">OPENSHIFT CONTAINER PLATFORM のアンインストール(Red Hat マニュアル)</a>

マニュアルの手順では、`local-storage`の`namespace`が残るので以下のコマンドで削除します。

```
oc delete namespace local-storage
```

## 8.2. HPA(Horizontal Pod Autoscaler)のWarning

`OCS`4.5では、インストール暫くすると以下のような、 HPA(Horizontal Pod Autoscaler)`が出す`Warning`が`OpenShift Console`に出る事が確認されています。これは`Bug`として扱われており、`OCS`4.6で一部修正されたような記述が見えますが、4.6用の別のチケットもオープンしており詳細な状況は未確認です。(2020/10/29時点)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/6806a6bf-15fd-a489-d594-cb68a5c2628c.png)


コマンドラインでも以下のように` oc get events -n openshift-storage`で確認できます。

```
[root@bastion openshift]# oc get events -n openshift-storage
LAST SEEN   TYPE      REASON                         OBJECT                                    MESSAGE
70m         Warning   FailedGetResourceMetric        horizontalpodautoscaler/noobaa-endpoint   unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: an error on the server ("Internal Server Error: \"/apis/metrics.k8s.io/v1beta1/namespaces/openshift-storage/pods?labelSelector=noobaa-s3%3Dnoobaa\": subjectaccessreviews.authorization.k8s.io is forbidden: User \"system:serviceaccount:openshift-monitoring:prometheus-adapter\" cannot create resource \"subjectaccessreviews\" in API group \"authorization.k8s.io\" at the cluster scope") has prevented the request from succeeding (get pods.metrics.k8s.io)
70m         Warning   FailedComputeMetricsReplicas   horizontalpodautoscaler/noobaa-endpoint   invalid metrics (1 invalid out of 1), first error is: failed to get cpu utilization: unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: an error on the server ("Internal Server Error: \"/apis/metrics.k8s.io/v1beta1/namespaces/openshift-storage/pods?labelSelector=noobaa-s3%3Dnoobaa\": subjectaccessreviews.authorization.k8s.io is forbidden: User \"system:serviceaccount:openshift-monitoring:prometheus-adapter\" cannot create resource \"subjectaccessreviews\" in API group \"authorization.k8s.io\" at the cluster scope") has prevented the request from succeeding (get pods.metrics.k8s.io)
[root@bastion openshift]# 
```

## 8.3. OCSをインターナルモードで作成する事について

通常時は問題を感じなかったのですが、`OCS`をインターナルモードで、`OpenShfit` クラスター内に配置する場合、`OpenShift(Kubernetes)`のアップデートに `OCS`自体も影響を受ける事に気づきました。

実際、クラスターのアップデート中は、クラスター全体が不安定な状況になりますが、ストレージである`OCS`もインターナルモードで作っている場合は、`OpenShift`の一部ですので、`Masterノード`、`Workerノード`と一緒にアップデートが走り、ストレージも含めてシステム全体が不安定な状況になります。

一般的にサーバーやアプリのアップデートと、ストレージのファームウェアのアップデートを同時に行うのは、リスク管理として良い方法ではないと思います。

そして現状では`Kubernetes`は、およそ3ヶ月に1回新しいマイナー・バージョンがリリースされ、一つのマイナーバージョンのサポート期間はおよそ1年です。

ストレージは企業活動の資産でもあるので、こう言った頻繁なアップデートにおけるリスクを減らすためには、`OCS`インターナルモードを使うのはテスト環境にするか、バックアップを別のストレージシステムに取得している事を前提とするのが良いと感じました。