Rook-Cephをデプロイする

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

今回はkubeadmでデプロイしたkubernetesクラスタ上にRook-Ceph環境をデプロイする手順を備忘録として書いておこうと思います。

# 用語
## Ceph
公式からの引用です。書いている通りストレージ系の分散管理システムですね。
ざっくり、kubernetesがアプリケーションとかを分散管理しており、Cephはデータを分散管理しているイメージです。分散管理している対象が違うと考えるとk8sを触っている人はもしかしたらスッと腹落ちするかも？

>Ceph は、オブジェクト、ブロック、およびファイルのストレージを 1 つの統合システムで提供します。

https://docs.ceph.com/en/quincy/

## Rook-Ceph
Rook-CephはCephをk8s用に使いやすく改良したものだと思っていただければいいのかなと思います。gitにyamlが置いてあり、デプロイ自体もかなり容易に行えます。
※普通にCephクラスタを構築するのもそこまで難しくはないですけども・・・

>Rook は、分散ストレージ システムを自己管理、自己スケーリング、自己修復のストレージ サービスに変えます。導入、ブートストラップ、構成、プロビジョニング、スケーリング、アップグレード、移行、災害復旧、監視、リソース管理など、ストレージ管理者のタスクを自動化します。
>Rook は、Kubernetes プラットフォームの能力を利用して、Ceph 用の Kubernetes Operator 経由でサービスを提供します

https://rook.io/

# 環境イメージ
今回の環境構築イメージは以下となります。
kubeadmで4台構成のk8sクラスタを構築します。そのクラスタ上にRook-Ceph環境をデプロイしていきます。気を付けないといけない点はcephをデプロイするVMはHardDiskを2つ用意する必要があることです。2つ用意し、うち一方にLVM等何もしていないとCephが勝手に「お？ワイが使っていいやつなんか？」と判断してくれるようになります。
HW構成については後程記載します。

![ceph-ページ6.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/59fe8c94-167f-0bcf-4406-228431a0b5f4.png)

kubeadmを用いたk8sクラスタの構築方法は以下となります。

https://qiita.com/ohtsuka-shota/items/7618cd98a12c8b2e4e07

https://qiita.com/ohtsuka-shota/items/2bcf2cd0d0b0c159cb8d

# HW構成
ノード名は気にしないでください。rancher用に使っていたやつを流用しているだけです。
またノード名"rancher"はCephクラスタのマスタ的な存在になりますが、これにはHardDisk2はありません。HardDisk2構成のVMが3台あればCephクラスタとしては充分です。3台未満でも良いのかもしれませんが、Cephのデフォルトが3台を基礎としているので個人的にはあまりお勧めできません。

|  ノード  |  OS  |  CPU  |  メモリ  |  HardDisk1  |  HardDisk2  |
| ---- | ---- | ---- | ---- | ---- | ---- |
|  rancher  |  ubuntu22.04  |  2socket4core  |  12.70GiB  |  70G  |  -  |
|  k8s-ceph01  |  ubuntu22.04  |  2socket4core  |  12.70GiB  |  50G  |  50G  |
|  k8s-ceph02  |  ubuntu22.04  |  2socket4core  |  9.77GiB  |  50G  |  50G  |
|  k8s-ceph03  |  ubuntu22.04  |  2socket4core  |  9.77GiB  |  50G  |  50G  |

# 参考サイト

https://rook.github.io/docs/rook/v1.11/Getting-Started/quickstart/

https://blog.tsuchinokometal.com/2022/rook_ceph_raspberrypi/

# 構築
デフォルトの状態は以下でした。
```
root@rancher:~# kubectl get node -o wide 
NAME         STATUS   ROLES           AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME 
k8s-ceph01   Ready    <none>          57s     v1.27.3   192.168.2.37   <none>        Ubuntu 22.04.2 LTS   5.15.0-75-generic   containerd://1.6.21 
k8s-ceph02   Ready    <none>          5m11s   v1.27.3   192.168.2.38   <none>        Ubuntu 22.04.2 LTS   5.15.0-73-generic   containerd://1.6.21 
k8s-ceph03   Ready    <none>          5m16s   v1.27.3   192.168.2.39   <none>        Ubuntu 22.04.2 LTS   5.15.0-73-generic   containerd://1.6.21 
rancher      Ready    control-plane   5m41s   v1.27.3   192.168.2.36   <none>        Ubuntu 22.04.2 LTS   5.15.0-75-generic   containerd://1.6.21
```

クラスタマスタとなるノードで以下のコマンドを実行してgitからcloneします。
cloneしましたら、crds.yaml/common.yaml/operator.yamlをベースにデプロイを行います。
※ rook/deploy/examples配下を見てみると、様々なyamlファイルがあるので見てみると面白いかもしれません。
※私の環境だとなぜかエラーが出ていますが、環境構築には問題なさそうでした。
```
root@rancher:~# git clone --single-branch --branch v1.8.10 https://github.com/rook/rook.git
root@rancher:~# cd rook/deploy/examples
root@rancher:~/rook/deploy/examples# kubectl create -f crds.yaml -f common.yaml -f operator.yaml
中略
deployment.apps/rook-ceph-operator created 
error: resource mapping not found for name: "00-rook-privileged" namespace: "" from "common.yaml": no matches for kind "PodSecurityPolicy" in version "policy/v1beta1" 
ensure CRDs are installed first
中略
```

operatorがrunningステートになることを確認します。
```
root@rancher:~/rook/deploy/examples# kubectl get all -n rook-ceph 
NAME                                      READY   STATUS    RESTARTS   AGE 
pod/rook-ceph-operator-7857749b84-bqvw5   1/1     Running   0          53s 

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE 
deployment.apps/rook-ceph-operator   1/1     1            1           53s 

NAME                                            DESIRED   CURRENT   READY   AGE 
replicaset.apps/rook-ceph-operator-7857749b84   1         1         1       53s
```

この後、Ceohクラスタをデプロイしていきます。
```
root@rancher:~/rook/deploy/examples# kubectl create -f cluster.yaml 
cephcluster.ceph.rook.io/rook-ceph created
```

10～30分ほど待機するとデプロイが完了します。
以下の様な状態になるかと思います。podにmgr,mon,osd,crash等がありますがこれはCephのコンポーネント？になります。この辺りの役割は理解しておいた方が良いかもしれません。
```
root@rancher:~/rook/deploy/examples# kubectl get all -n rook-ceph 
NAME                                                       READY   STATUS      RESTARTS   AGE 
pod/csi-cephfsplugin-dmq86                                 3/3     Running     0          3m48s 
pod/csi-cephfsplugin-ffswq                                 3/3     Running     0          3m48s 
pod/csi-cephfsplugin-lpqx7                                 3/3     Running     0          3m48s 
pod/csi-cephfsplugin-provisioner-d7f599b4b-k69jk           6/6     Running     0          3m48s 
pod/csi-cephfsplugin-provisioner-d7f599b4b-pznmj           6/6     Running     0          3m48s 
pod/csi-rbdplugin-2bdph                                    3/3     Running     0          3m49s 
pod/csi-rbdplugin-4zvs5                                    3/3     Running     0          3m48s 
pod/csi-rbdplugin-cnrvp                                    3/3     Running     0          3m48s 
pod/csi-rbdplugin-provisioner-59f7df7cf8-h9xcd             6/6     Running     0          3m48s 
pod/csi-rbdplugin-provisioner-59f7df7cf8-k8t9r             6/6     Running     0          3m48s 
pod/rook-ceph-crashcollector-k8s-ceph01-5fc9bdbdb-qkkgr    1/1     Running     0          62s 
pod/rook-ceph-crashcollector-k8s-ceph02-6f59667ccf-bmf4j   1/1     Running     0          40s 
pod/rook-ceph-crashcollector-k8s-ceph03-6c45c95b44-6s8tl   1/1     Running     0          78s 
pod/rook-ceph-mgr-a-755fcffc96-2rwvw                       1/1     Running     0          82s 
pod/rook-ceph-mon-a-6548ffb8b8-5q8bh                       1/1     Running     0          4m43s 
pod/rook-ceph-mon-b-77c7b44765-jh664                       1/1     Running     0          2m33s 
pod/rook-ceph-mon-c-78464899cf-7lv2r                       1/1     Running     0          2m18s 
pod/rook-ceph-operator-7857749b84-bqvw5                    1/1     Running     0          6m45s 
pod/rook-ceph-osd-0-b7bcd647d-7l89n                        1/1     Running     0          48s 
pod/rook-ceph-osd-1-5b99db5858-46bmv                       1/1     Running     0          45s 
pod/rook-ceph-osd-2-56566b85b-99q8w                        1/1     Running     0          44s 
pod/rook-ceph-osd-prepare-k8s-ceph01-hfnl2                 0/1     Completed   0          60s 
pod/rook-ceph-osd-prepare-k8s-ceph02-27p8h                 0/1     Completed   0          60s 
pod/rook-ceph-osd-prepare-k8s-ceph03-5cnp7                 0/1     Completed   0          60s

NAME                               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE 
service/csi-cephfsplugin-metrics   ClusterIP   10.105.176.27    <none>        8080/TCP,8081/TCP   3m48s 
service/csi-rbdplugin-metrics      ClusterIP   10.97.164.183    <none>        8080/TCP,8081/TCP   3m48s 
service/rook-ceph-mgr              ClusterIP   10.107.100.156   <none>        9283/TCP            61s 
service/rook-ceph-mgr-dashboard    ClusterIP   10.105.69.139    <none>        8443/TCP            61s 
service/rook-ceph-mon-a            ClusterIP   10.101.48.71     <none>        6789/TCP,3300/TCP   4m45s 
service/rook-ceph-mon-b            ClusterIP   10.102.209.239   <none>        6789/TCP,3300/TCP   2m34s 
service/rook-ceph-mon-c            ClusterIP   10.109.10.21     <none>        6789/TCP,3300/TCP   2m19s

NAME                              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE 
daemonset.apps/csi-cephfsplugin   3         3         3       3            3           <none>          3m48s 
daemonset.apps/csi-rbdplugin      3         3         3       3            3           <none>          3m49s

NAME                                                  READY   UP-TO-DATE   AVAILABLE   AGE 
deployment.apps/csi-cephfsplugin-provisioner          2/2     2            2           3m48s 
deployment.apps/csi-rbdplugin-provisioner             2/2     2            2           3m49s 
deployment.apps/rook-ceph-crashcollector-k8s-ceph01   1/1     1            1           62s 
deployment.apps/rook-ceph-crashcollector-k8s-ceph02   1/1     1            1           82s 
deployment.apps/rook-ceph-crashcollector-k8s-ceph03   1/1     1            1           78s 
deployment.apps/rook-ceph-mgr-a                       1/1     1            1           82s 
deployment.apps/rook-ceph-mon-a                       1/1     1            1           4m43s 
deployment.apps/rook-ceph-mon-b                       1/1     1            1           2m34s 
deployment.apps/rook-ceph-mon-c                       1/1     1            1           2m18s 
deployment.apps/rook-ceph-operator                    1/1     1            1           6m45s 
deployment.apps/rook-ceph-osd-0                       1/1     1            1           48s 
deployment.apps/rook-ceph-osd-1                       1/1     1            1           45s 
deployment.apps/rook-ceph-osd-2                       1/1     1            1           44s

NAME                                                             DESIRED   CURRENT   READY   AGE 
replicaset.apps/csi-cephfsplugin-provisioner-d7f599b4b           2         2         2       3m48s 
replicaset.apps/csi-rbdplugin-provisioner-59f7df7cf8             2         2         2       3m48s 
replicaset.apps/rook-ceph-crashcollector-k8s-ceph01-5fc9bdbdb    1         1         1       62s 
replicaset.apps/rook-ceph-crashcollector-k8s-ceph02-6f59667ccf   1         1         1       40s 
replicaset.apps/rook-ceph-crashcollector-k8s-ceph02-747fff597    0         0         0       82s 
replicaset.apps/rook-ceph-crashcollector-k8s-ceph03-6c45c95b44   1         1         1       78s 
replicaset.apps/rook-ceph-mgr-a-755fcffc96                       1         1         1       82s 
replicaset.apps/rook-ceph-mon-a-6548ffb8b8                       1         1         1       4m43s 
replicaset.apps/rook-ceph-mon-b-77c7b44765                       1         1         1       2m33s 
replicaset.apps/rook-ceph-mon-c-78464899cf                       1         1         1       2m18s 
replicaset.apps/rook-ceph-operator-7857749b84                    1         1         1       6m45s 
replicaset.apps/rook-ceph-osd-0-b7bcd647d                        1         1         1       48s 
replicaset.apps/rook-ceph-osd-1-5b99db5858                       1         1         1       45s 
replicaset.apps/rook-ceph-osd-2-56566b85b                        1         1         1       44s

NAME                                         COMPLETIONS   DURATION   AGE 
job.batch/rook-ceph-osd-prepare-k8s-ceph01   1/1           17s        60s 
job.batch/rook-ceph-osd-prepare-k8s-ceph02   1/1           18s        60s 
job.batch/rook-ceph-osd-prepare-k8s-ceph03   1/1           15s        60s
```

正常にデプロイ出来ているかは以下の様にすることで確認が出来ます。"deployment "rook-ceph-tools" successfully rolled out","health: HEALTH_OK"等と表示されていれば問題無いでしょう。ceph -sはceph用のコマンドです。Rook-Cephを使わないでCephクラスタを構築した場合でも使います。なのでrook-ceph-tools podはRook-Cephクラスタをcephコマンドで確認等するためのpodだという認識で一旦良いのかなと思います。
```
root@rancher:~/rook/deploy/examples# kubectl apply -f toolbox.yaml 
deployment.apps/rook-ceph-tools created

root@rancher:~/rook/deploy/examples# kubectl -n rook-ceph rollout status deploy/rook-ceph-tools 
deployment "rook-ceph-tools" successfully rolled out

root@rancher:~/rook/deploy/examples# kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash 
[rook@rook-ceph-tools-7c497bc7b8-qwch5 /]$ ceph -s 
  cluster: 
    id:     2e277245-d086-4ff5-9c0d-a942e26abeae 
    health: HEALTH_OK 
  services: 
    mon: 3 daemons, quorum a,b,c (age 3m) 
    mgr: a(active, since 2m) 
    osd: 3 osds: 3 up (since 2m), 3 in (since 2m) 
  data: 
    pools:   0 pools, 0 pgs 
    objects: 0 objects, 0 B 
    usage:   15 MiB used, 150 GiB / 150 GiB avail 
    pgs:
```

dashboardにアクセスしてみます。"rook-ceph-mgr-dashboard"がそれです。
```
root@rancher:~/rook/deploy/examples# kubectl -n rook-ceph get service 
NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE 
csi-cephfsplugin-metrics   ClusterIP   10.105.176.27    <none>        8080/TCP,8081/TCP   6m31s 
csi-rbdplugin-metrics      ClusterIP   10.97.164.183    <none>        8080/TCP,8081/TCP   6m31s 
rook-ceph-mgr              ClusterIP   10.107.100.156   <none>        9283/TCP            3m44s 
rook-ceph-mgr-dashboard    ClusterIP   10.105.69.139    <none>        8443/TCP            3m44s 
rook-ceph-mon-a            ClusterIP   10.101.48.71     <none>        6789/TCP,3300/TCP   7m28s 
rook-ceph-mon-b            ClusterIP   10.102.209.239   <none>        6789/TCP,3300/TCP   5m17s 
rook-ceph-mon-c            ClusterIP   10.109.10.21     <none>        6789/TCP,3300/TCP   5m2s
```

NodePortをデプロイしていきます。
事前に公式が準備しています。ファイル名はRook-Ceph-NodePort.yamlとしました。

https://rook.github.io/docs/rook/v1.11/Storage-Configuration/Monitoring/ceph-dashboard/#viewing-the-dashboard-external-to-the-cluster

```
root@rancher:~/rook/deploy/examples# vi Rook-Ceph-NodePort.yaml 
root@rancher:~/rook/deploy/examples# cat Rook-Ceph-NodePort.yaml 
apiVersion: v1 
kind: Service 
metadata: 
  name: rook-ceph-nodeport
  namespace: rook-ceph 
  labels: 
    app: rook-ceph-mgr 
    rook_cluster: rook-ceph 
spec: 
  ports: 
  - name: dashboard 
    port: 8443 
    protocol: TCP 
    targetPort: 8443 
  selector: 
    app: rook-ceph-mgr 
    rook_cluster: rook-ceph 
  sessionAffinity: None 
  type: NodePort
```

デプロイします。
今回の場合、30259ポートが割り当てられていますね。
```
root@rancher:~/rook/deploy/examples# kubectl apply -f Rook-Ceph-NodePort.yaml 
service/rook-ceph-nodeport created 

root@rancher:~/rook/deploy/examples# kubectl -n rook-ceph get service 
NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE 
csi-cephfsplugin-metrics   ClusterIP   10.105.176.27    <none>        8080/TCP,8081/TCP   11m 
csi-rbdplugin-metrics      ClusterIP   10.97.164.183    <none>        8080/TCP,8081/TCP   11m 
rook-ceph-mgr              ClusterIP   10.107.100.156   <none>        9283/TCP            9m 
rook-ceph-mgr-dashboard    ClusterIP   10.105.69.139    <none>        8443/TCP            9m 
rook-ceph-mon-a            ClusterIP   10.101.48.71     <none>        6789/TCP,3300/TCP   12m 
rook-ceph-mon-b            ClusterIP   10.102.209.239   <none>        6789/TCP,3300/TCP   10m 
rook-ceph-mon-c            ClusterIP   10.109.10.21     <none>        6789/TCP,3300/TCP   10m 
rook-ceph-nodeport         NodePort    10.98.63.97      <none>        8443:30259/TCP      79s
```

Webコンソールにログインする為のパスワードを確認します。以下の様に確認することが出来ます。
```
root@rancher:~/rook/deploy/examples# kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo 
Wd1CNs#;+\HwRL\E$Gk}
```

Webコンソールにアクセスします。私の環境の場合https://192.168.2.36:30259でアクセス出来ます。
アクセスが上手くいくと以下の様な画面が表示されます。
ユーザ名はadmin。パスワードは上記で確認したものでOKです。

![ceph-ページ-6-1.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/6955d769-59c7-6f84-ba33-f5a629c28fcd.png)


ログイン後の画面です。今後これをどのように使っていくのかを確認していきたいと思います。
![ceph-ページ-6-2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/4d7ca7bd-3044-4dad-5da9-f3d1ac71034f.png)
![ceph-ページ-6-3.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/f21bfbd7-0f23-1258-9d3f-c095b60afda8.png)