2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rook CephのHelmチャートをオンプレKubernetesにデプロイ

Last updated at Posted at 2024-02-25

概要

kubeadmを使ってオンプレミスで構築したKubernetesクラスターに対して、Rook CephのHelmチャートをデプロイできました。実現のための事前準備や手順について本記事で記載します。
執筆時点でRook CephをHelmで構築した日本語の記事がほぼ無かったので、オンプレに限らずEKS,AKS,GKE等のクラウド上に構築する際の参考にもきっとなると思います。

環境情報

今回Rook Cephを構築した環境情報です。

クラスター全般

  • Kubernetesのバージョン : 1.27.1
  • ノード : control planeとworkerノードが1台ずつ

kubectlコマンドで確認すると、以下のような状態です。

$ kubectl get nodes -owide
NAME            STATUS   ROLES           AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                       KERNEL-VERSION            CONTAINER-RUNTIME
control-plane   Ready    control-plane   428d   v1.27.1   192.168.1.4   <none>        Ubuntu 20.04.6 LTS             5.4.0-167-generic         containerd://1.6.28
worker01        Ready    <none>          428d   v1.27.1   192.168.1.5   <none>        Debian GNU/Linux 10 (buster)   5.4.246-0504246-generic   containerd://1.6.20

control-planeに関しては、初期構築時に付いていたcontrol plane用のtaintは消しています。したがって、これから構築するアプリケーションリソース(非システムリソース)もデプロイできる状態です。

ディスク(Rawデバイス)の接続

QuickstartのPrerequisitesにも書かれていますが、Rook Cephを構築するには「パーティション無し、かつフォーマットもされていないRawデバイス」が必要となります。たまたまですが、私の場合は過去にディスク換装した時の古いディスクが3台残っていたので、control-planeに1台、worker01のマシンに2台をUSB接続でつなぎました。以下が具体的な情報です。

control-planeに接続したディスク(1台)

/dev/sdbとして認識されており、以下のようにフォーマットされていない状態です。

$ sudo parted /dev/sdb print
Error: /dev/sdb: unrecognised disk label
Model: SSK  (scsi)
Disk /dev/sdb: 128GB
Sector size (logical/physical): 512B/4096B
Partition Table: unknown
Disk Flags:

worker01に接続したディスク(2台)

/dev/sdb, /dev/sdcとして認識されており、control-planeに接続したディスクと同様にフォーマットされていない状態です。

$ sudo parted /dev/sdb print
Error: /dev/sdb: unrecognised disk label
Model: ST320LT0 20-9YG142 (scsi)
Disk /dev/sdb: 320GB
Sector size (logical/physical): 512B/4096B
Partition Table: unknown
Disk Flags:

$ sudo parted /dev/sdc print
Error: /dev/sdc: unrecognised disk label
Model: INTEL SS DSC2BF180A4H (scsi)
Disk /dev/sdc: 180GB
Sector size (logical/physical): 512B/4096B
Partition Table: unknown
Disk Flags:

Rook Cephのデプロイ手順

(1) rookのGitリポジトリをclone

本手順の後半でRook Cephのカスタムリソースをデプロイしていく際の参考になるマニフェストが、rookのGitリポジトリに格納されています。そこで必須ではないですが、予めgit cloneして手元に持ってくることをおすすめします。

$ git clone https://github.com/rook/rook.git \
  --single-branch --branch v1.13.5 --depth 1

サンプルマニフェストは、上記リポジトリの ./deploy/examples/ディレクトリに沢山あります。

(2) Helmチャートのインストール

Ceph Operator Helm Chartの内容にしたがって、Rook CephのHelmチャートをインストールします。バージョンは24/02/25時点で最新のv1.13.5を使います。

helm repo add rook-release https://charts.rook.io/release

helm install --create-namespace \
-n rook-ceph rook-ceph rook-release/rook-ceph \
-f values.yaml --version v1.13.5

values.yamlに記載する内容はK8sクラスター全般の条件によって変わってくるので、お使いの環境に応じて適宜設定してください。私の場合はノードのスペックが貧弱なことが原因なのか、デフォルトの値だとCephClusterを構築する際(後で説明)にCSI関連のリソースをデプロイできませんでした。そこでCPUとメモリのrequestsを以下のように追加したら解決しました。

values.yaml
csi:
  rbdProvisionerResource:
    requests:
      cpu: 50m
      memory: 32Mi
  rbdPluginResource:
    requests:
      cpu: 50m
      memory: 32Mi
  cephFSProvisionerResource:
    requests:
      cpu: 50m
      memory: 32Mi
  cephFSPluginResource:
    requests:
      cpu: 50m
      memory: 32Mi

しばらくすると、rook-ceph-operatorのPodがデプロイされるのを確認できるはずです。

$ kubectl get po -n rook-ceph
NAME                                  READY   STATUS              RESTARTS   AGE
rook-ceph-operator-5686f95bcb-t47k8   1/1     Running             0          37s

(3) CephClusterのデプロイ

CephClusterのカスタムリソースをマニフェストからデプロイします。cluster.yamlをもとにして(rookのGitリポジトリをcloneしていれば./deploy/examples/cluster.yamlがそれ)、一部のパラメータを以下のように変更します。

spec.storageのパラメータ変更

おそらく必須ではないですが、Cephクラスターで使うデバイスを自分で指定したい動機があったため、以下のように変更しました。

useAllNodesuseAllDevicesfalseにする

    useAllNodes: false
    useAllDevices: false

nodesに接続するデバイス情報を記載する

    nodes:
      - name: "control-plane"
        devices:
          - name: "/dev/disk/by-id/ata-TS128GMTS400S_XXXXXXXX"         # /dev/sdb 相当
      - name: "worker01"
        devices:
          - name: "/dev/disk/by-id/ata-ST320LT020-XXXXXX_YYYYYYYY"     # /dev/sdb 相当
          - name: "/dev/disk/by-id/usb-INTEL_SS_DSC2BF180A4H_XXXXXXXX" # /dev/sdc 相当

上記には、「各ノードでCephクラスターのOSDと一緒に接続するストレージデバイスのID」を記載しています。それぞれのIDはcontrol-plane、およびworker01のマシン内で以下のように確認しました。

control-plane
$ ls -l /dev/disk/by-id/ | grep sdb
lrwxrwxrwx 1 root root  9  2月 24 13:53 ata-TS128GMTS400S_XXXXXXXX -> ../../sdb
worker01
$ ls -l /dev/disk/by-id/ | grep -e sdb -e sdc
lrwxrwxrwx 1 root root  9  2月 25 06:20 ata-ST320LT020-XXXXXX_YYYYYYYY -> ../../sdb
lrwxrwxrwx 1 root root  9  2月 25 06:20 usb-INTEL_SS_DSC2BF180A4H_XXXXXXXX -> ../../sdc

※おそらくですが、useAllNodesuseAllDevicestrueにしていれば上記のようにディスクのIDを指定しなくても、CephClusterを構築する際にRawデバイスを勝手に見つけてくれるはずです。

その他の変更

K8sクラスターのノード数が2つで、かつスペックが貧弱なため、デフォルトでデプロイすると過剰にリソースが出来てしまったり、一部のリソースが作れなかったりしました。そこで以下のようにパラメータを調整しました。

  • monmgrcount1にする
  • osdsPerDevice1にする
  • osdcrashcollectorにCPUとメモリのrequestsを以下のように追加する
    osd:
      requests:
        cpu: 50m
        memory: 128Mi
    crashcollector:
      requests:
        cpu: 50m
        memory: 128Mi

CephClusterのデプロイ

ようやく準備ができたので、CephClusterをデプロイします。

$ kubectl apply -f cluster.yaml
cephcluster.ceph.rook.io/rook-ceph created

しばらく待つと、以下のように沢山のPodが出来上がります。

$ kubectl get po -n rook-ceph
NAME                                                      READY   STATUS      RESTARTS   AGE
csi-cephfsplugin-6v9lb                                    2/2     Running     0          2m35s
csi-cephfsplugin-lkxc9                                    2/2     Running     0          2m35s
csi-cephfsplugin-provisioner-6f695c88d5-cm6jt             5/5     Running     0          2m35s
csi-cephfsplugin-provisioner-6f695c88d5-pt5x7             5/5     Running     0          2m35s
csi-rbdplugin-gkhpt                                       2/2     Running     0          2m35s
csi-rbdplugin-provisioner-555d58fcc4-bcfcz                5/5     Running     0          2m35s
csi-rbdplugin-provisioner-555d58fcc4-cxzjt                5/5     Running     0          2m35s
csi-rbdplugin-xjggb                                       2/2     Running     0          2m35s
rook-ceph-crashcollector-worker01-6b4476fc4c-72f6s        1/1     Running     0          53s
rook-ceph-crashcollector-control-plane-6b78754bd5-fmkfw   1/1     Running     0          59s
rook-ceph-exporter-worker01-68b9647979-f8bw9              1/1     Running     0          47s
rook-ceph-exporter-control-plane-65987d5497-njhpg         1/1     Running     0          59s
rook-ceph-mgr-a-55f5c5bddd-wp2lj                          2/2     Running     0          111s
rook-ceph-mon-a-757ff9fd4c-cfq7j                          2/2     Running     0          2m31s
rook-ceph-operator-5686f95bcb-w6cqd                       1/1     Running     0          164m
rook-ceph-osd-0-8c9c9db89-xxrz6                           2/2     Running     0          54s
rook-ceph-osd-1-84b984d5c9-h5db7                          2/2     Running     0          59s
rook-ceph-osd-2-6fd788cbb6-kcfmv                          2/2     Running     0          54s
rook-ceph-osd-prepare-worker01-mbxw9                      0/1     Completed   0          88s
rook-ceph-osd-prepare-control-plane-8d82x                 0/1     Completed   0          88s

目視で追う限りでは、以下のような順番でリソースが作られていました。

  • MON
    • rook-ceph-mon-a (Deployment)
  • CSI plugin関連
    • csi-rbdplugin (DaemonSet)
    • csi-cephfsplugin (DaemonSet)
    • csi-rbdplugin-provisioner (Deployment)
    • csi-cephfsplugin-provisioner (Deployment)
  • MGR等
    • rook-ceph-mgr-a (Deployment)
    • rook-ceph-exporter-[nodename] (Deployment)
    • rook-ceph-crashcollector-[nodename] (Deployment)
  • OSD
    • rook-ceph-osd-[n] (Deployment)

(4) やっておくと便利な設定

rook-ceph-toolsのデプロイ

Cephクラスターの状態や操作をするためのtoolのリソースをデプロイします。rookのGitリポジトリをcloneしていれば./deploy/examples/cluster.yamlを使い、そうでない場合はtoolbox.yamlのコピペしてデプロイします。

kubectl apply -f toolbox.yaml

rook-ceph-toolsのDeploymentリソースが出来ていることを確認します。

$ kubectl get deploy -n rook-ceph rook-ceph-tools
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
rook-ceph-tools   1/1     1            1           33s

rook-ceph-toolsを使うと、以下のようにcephコマンドを実行してCephクラスターの状態を見ることができたりします。(HEALTH_WARNになって問題がある状態ですがご容赦を)

$ kubectl exec -it -n rook-ceph deploy/rook-ceph-tools -- ceph -s
  cluster:
    id:     1dc08058-8a34-4d18-b1ca-c4ad985d18be
    health: HEALTH_WARN
            Degraded data redundancy: 2/6 objects degraded (33.333%), 1 pg degraded, 1 pg undersized

  services:
    mon: 1 daemons, quorum a (age 94m)
    mgr: a(active, since 10m)
    osd: 3 osds: 3 up (since 11m), 3 in (since 11m)

  data:
    pools:   1 pools, 1 pgs
    objects: 2 objects, 705 KiB
    usage:   81 MiB used, 585 GiB / 585 GiB avail
    pgs:     2/6 objects degraded (33.333%)
             1 active+undersized+degraded

Rook CephのWebUIへのアクセス

Rook CephのWebUIは、rook-ceph-mgr-dashboardという名前のServiceリソースでポート番号8443でデプロイされています。ここに各ホストからアクセスするための一つの方法として、以下のようにポートフォワードするやり方があります。

kubectl port-forward -n rook-ceph svc/rook-ceph-mgr-dashboard 8443:8443 \
--address='0.0.0.0'

これにより、Rook CephのWebUIに https://[hostname-of-node]:8443 でアクセスできるようになります。
ログインで認証を求められますが、ユーザIDはadminで、そのパスワードは以下のコマンドで取得可能です。

$ kubectl get secret -n rook-ceph rook-ceph-dashboard-password -ojson \
| jq -r '.data.password' | base64 --decode

以上でCephクラスターの構築は完了です。

CephFilesystem(CephFS)を試しに作ってマウントしてみる

本記事では試しにCephFilesystemのリソースを作り、さらにStorageClass、PVC、Deploymentの順番にリソース作って複数のPodマウントしてみます。

CephFilesystemの作成

まずはCephFilesystemのリソースを作成します。RookのサイトのFilesystem Storage Overviewのマニフェストを参考に、replicaのサイズを1に変更して次のようなマニフェストを作ってデプロイします。

cephfilesystem.yaml
apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
  name: myfs
  namespace: rook-ceph
spec:
  metadataPool:
    replicated:
      size: 1
  dataPools:
    - name: default
      replicated:
        size: 1
  metadataServer:
    activeCount: 1
    activeStandby: true
kubectl apply -f cephfilesystem.yaml

以下のように、cephfilesystemというリソースが作られておリ、MDS(MetadataServer)というPodが作られているのを確認できます。

$ kubectl get cephfilesystem -n rook-ceph
NAME   ACTIVEMDS   AGE   PHASE
myfs   1           38s   Ready

$ kubectl get po -n rook-ceph | grep mds
rook-ceph-mds-myfs-a-58c94b7f67-snf6l                 2/2     Running     0              78s
rook-ceph-mds-myfs-b-6c9f79d59c-qtmdg                 2/2     Running     0              72s

また、rook-ceph-toolsでもCephFSが作られているのを確認できます。

$ kubectl exec -it -n rook-ceph deploy/rook-ceph-tools -- ceph fs ls
name: myfs, metadata pool: myfs-metadata, data pools: [myfs-default ]

$ kubectl exec -it -n rook-ceph deploy/rook-ceph-tools -- ceph df
--- RAW STORAGE ---
CLASS     SIZE    AVAIL    USED  RAW USED  %RAW USED
hdd    466 GiB  466 GiB  54 MiB    54 MiB       0.01
ssd    119 GiB  119 GiB  27 MiB    27 MiB       0.02
TOTAL  585 GiB  585 GiB  81 MiB    81 MiB       0.01

--- POOLS ---
POOL           ID  PGS   STORED  OBJECTS     USED  %USED  MAX AVAIL
.mgr            1    1  705 KiB        2  1.4 MiB      0    278 GiB
myfs-metadata   2   32   10 KiB       22   40 KiB      0    556 GiB
myfs-default    3   32      0 B        0      0 B      0    556 GiB

StorageClassの作成

Provision Storageに記載されたStorageClassのマニフェストを参考に、以下のようにpool: myfs-replicatedの部分をコメントアウトしてデプロイします。

cephfs.storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: rook-cephfs
# Change "rook-ceph" provisioner prefix to match the operator namespace if needed
provisioner: rook-ceph.cephfs.csi.ceph.com
parameters:
  # clusterID is the namespace where the rook cluster is running
  # If you change this namespace, also change the namespace below where the secret namespaces are defined
  clusterID: rook-ceph

  # CephFS filesystem name into which the volume shall be created
  fsName: myfs

  # Ceph pool into which the volume shall be created
  # Required for provisionVolume: "true"
  # pool: myfs-replicated                   # (筆者追記)コメントアウトが必要!

  # The secrets contain Ceph admin credentials. These are generated automatically by the operator
  # in the same namespace as the cluster.
  csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner
  csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
  csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner
  csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
  csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
  csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph

reclaimPolicy: Delete
kubectl apply -f cephfs.storageclass.yaml

StorageClassが作られているのを確認します。

$ kubectl get sc rook-cephfs
NAME          PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
rook-cephfs   rook-ceph.cephfs.csi.ceph.com   Delete          Immediate           false                  8s

PVCの作成

rook-cephfsのStorageClassを参照するPVCを作成します。

cephfs.pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: cephfs-pvc
  namespace: default
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 100Gi
  storageClassName: rook-cephfs
kubectl apply -f cephfs.pvc.yaml

rook-cephfsのStorageClassの volumeBindingModeImmediateのため、PVCが作成されたら直ちにPVも確保されているのを確認できます。

$ kubectl get pvc -n default
NAME                                       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
cephfs-pvc                                 Bound    pvc-22111206-624d-49c1-a018-fd6a618ac819   100Gi      RWX            rook-cephfs    4s

PVCをマウントするDeploymentリソースの作成

あとはだいぶ機械的ですが、cephfs-pvcをマウントするDeploymentリソースを作ってみます。

mnt-cephfs-pvc.deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mnt-cephfs-pvc
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: busybox
        command: ["sleep", "infinity"]
        volumeMounts:
        - name: my-pvc
          mountPath: /data
      volumes:
      - name: my-pvc
        persistentVolumeClaim:
          claimName: cephfs-pvc
kubectl apply -f mnt-cephfs-pvc.deployment.yaml

CephFSのPVCをマウントして問題なく動いていることを確認します。

$ kubectl get po -n default
NAME                             READY   STATUS    RESTARTS       AGE
mnt-cephfs-pvc-848c4d4fd-9t2wg   1/1     Running   0              25s
mnt-cephfs-pvc-848c4d4fd-k7hqx   1/1     Running   0              25s
mnt-cephfs-pvc-848c4d4fd-w4bk4   1/1     Running   0              25s
$ kubectl exec -it -n default deploy/mnt-cephfs-pvc -- df -h | grep -B 1 "/data"
10.107.230.219:6789:/volumes/csi/csi-vol-7af2939e-af07-41f0-9a30-96d45af4254d/35fae814-667c-4a1b-8e87-46538c2d5856
                        100.0G         0    100.0G   0% /data

試しにCephFSのボリュームにファイルを作って、各Podからその内容が見れるのを確認します。

$ kubectl exec -it -n default deploy/mnt-cephfs-pvc -- sh
/ # echo "aaaa" > /data/tmp.txt
/ # exit 0
$ kubectl exec -it -n default mnt-cephfs-pvc-848c4d4fd-9t2wg -- cat /data/tmp.txt
aaaa
$ kubectl exec -it -n default mnt-cephfs-pvc-848c4d4fd-k7hqx -- cat /data/tmp.txt
aaaa
$ kubectl exec -it -n default mnt-cephfs-pvc-848c4d4fd-w4bk4 -- cat /data/tmp.txt
aaaa

CephFSの動作確認は以上で完了です。

後片付け

構築してRook Cephをクリーンにしたい場合の手順です。Cleanupを参考にして記載します。

Rook CephのK8s関連リソースの削除

まずは以下の順番でK8sのリソースを削除していきます。

  • CephのPVCをマウントしているリソース(PodやDeployment等)の削除
  • CephのStorageClassを使っているPVC,PVの削除
  • provisionerがCeph(=rook-ceph.cephfs.csi.ceph.com)になっているStorageClassを削除
  • CephCluster以外のカスタムリソース(CephFilesystem, CephBlockPool等)を削除
  • CephClusterの削除

ここまでで、Rook Ceph関連で残っているリソースは以下のように、rook-ceph-operatorのみになっているはずです。

$ kubectl get po -n rook-ceph
NAME                                  READY   STATUS    RESTARTS   AGE
rook-ceph-operator-6bb889cd5f-btpqj   1/1     Running   0          18h

もしTerminatingで残っているPodがある場合は、kubectl delete pod--forceオプションをつける等して強制的に削除します。

Helmチャートのアンインストール

rook-cephのHelmチャートをアンインストールします。これでrook-ceph-operatorも消えてくれます。

helm uninstall -n rook-ceph rook-ceph

削除時に次のようなメッセージが出て、Rook CephのCustomResourceDefinition(CRD)が残ってしまっていることがわかります。

These resources were kept due to the resource policy:
[CustomResourceDefinition] cephblockpoolradosnamespaces.ceph.rook.io
[CustomResourceDefinition] cephblockpools.ceph.rook.io
...
[CustomResourceDefinition] objectbuckets.objectbucket.io

これらのCRDを一つ一つ消してもいいですが、それなりの量があるので手間です。そこで別の方法として、次のようにGitHubからrookのリポジトリをcloneして、CRDを定義したYAMLファイルを使って消してみます。

$ git clone https://github.com/rook/rook.git \
  --single-branch --branch v1.13.5 --depth 1
$ cd rook/deploy/examples/
$ kubectl delete -f crds.yaml
customresourcedefinition.apiextensions.k8s.io "cephblockpoolradosnamespaces.ceph.rook.io" deleted
customresourcedefinition.apiextensions.k8s.io "cephblockpools.ceph.rook.io" deleted
...
customresourcedefinition.apiextensions.k8s.io "objectbuckets.objectbucket.io" deleted

問題なくRook Ceph全CRDを削除できました。

各ノードに残っているデータ削除

これでRook CephのK8sリソースは完全に消すことができましたが、各ノードに残っているデータの削除も必要です。

Cleanupのドキュメントによると、CephClusterのCustomResourceでcleanupPolicyを適切に設定していれば、CephClusterを削除したタイミングで以下も自動で実行してくれそうです。

Namespaceディレクトリの削除

各ノードで/var/lib/rook/に格納されたファイルを削除します。

sudo rm -rf /var/lib/rook/*

Cleanupのドキュメントには「/var/lib/rook/rook-cephを削除する」とのみ書いてあるようでしたが、ここを消しただけでは再構築時に上手くいかなかったので、/var/lib/rook/内のファイルを全て消した方がよさそうです。

ディスクの内容をリセット

各OSDで使っていたディスクの内容をリセットします。Cleanupにはいくつかの削除方法が書かれていますが、筆者は以下のみを実行しました。

control-planeで実行

sudo sgdisk --zap-all /dev/sdb

worker01で実行

sudo sgdisk --zap-all /dev/sdb
sudo sgdisk --zap-all /dev/sdc

上記コマンドは非常に危険なので単純コピペで実行しないでください! 引数の/dev/sdb,/dev/sdcの部分はご自身の環境に合わせて設定いただくようお願いいたします。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?