概要
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
を以下のように追加したら解決しました。
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クラスターで使うデバイスを自分で指定したい動機があったため、以下のように変更しました。
useAllNodes
とuseAllDevices
をfalse
にする
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
※おそらくですが、useAllNodes
とuseAllDevices
をtrue
にしていれば上記のようにディスクのIDを指定しなくても、CephClusterを構築する際にRawデバイスを勝手に見つけてくれるはずです。
その他の変更
K8sクラスターのノード数が2つで、かつスペックが貧弱なため、デフォルトでデプロイすると過剰にリソースが出来てしまったり、一部のリソースが作れなかったりしました。そこで以下のようにパラメータを調整しました。
-
mon
とmgr
のcount
を1
にする -
osdsPerDevice
を1
にする -
osd
とcrashcollector
に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に変更して次のようなマニフェストを作ってデプロイします。
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
の部分をコメントアウトしてデプロイします。
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を作成します。
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の volumeBindingMode
がImmediate
のため、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リソースを作ってみます。
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の部分はご自身の環境に合わせて設定いただくようお願いいたします。