前回は、IngressでSSL/TLSを有効にする方法を試してみました。今回は、Rook Cephを使って分散ストレージのインストールを試してみました。
hidemium.hatenablog.com
構成
- vCenter 7.0 U3
- ESXi 7.0 Update 3
- Ubuntu 22.04 (テンプレートVM)
- Kubespray
- kubernetes v1.25.5
- MetalLB v0.12.1
- ingress-nginx v1.5.1
- CoreDNS
- EdgeRouter X
- Rook Ceph v1.10.9
PersistentVolumeについて
KubernetesのPersistentVolume(PV)を利用するために、ボリュームプラグインとしてKubernetesに組み込まれたIn-Tree Volume PluginとContainer Storage Interface(CSI)を利用することができます。詳細は以下のリストにありますが、ベンダー向けのIn-Tree Volume PluginからCSIに置き換わってきています。
Persistent Volumes | Kubernetes
homelabで利用する場合は、NFSを用意したり、vSphereのCSIのvSphere Container Storage Plug-inを利用するという方法が取れるかと思います。
VMware vSphere Container Storage Plug-in Documentation
今回の構成では、仮想マシンをworkerノードとしており、workerノードを物理サーバーと見たててハイパーコンバージドインフラストラクチャのような構成がためせないかと思い、分散ストレージのRook Cephを試してみました。
Rook Cephを利用する場合は、Ceph CSIを利用する形になります。
Rook Cephについて
Rook Cephは、Kubernetes上に分散ストレージのCephをデプロイし、ストレージの運用(展開、ブートストラップ、構成、プロビジョニング、スケーリング、アップグレード、移行、災害復旧、監視、およびリソース管理)を自動化してくれるストレージオペレーターです。
Rook
Cephは、オブジェクト、ブロック、ファイル ストレージといった複数のインターフェースでアクセスできる分散オブジェクトストレージプラットフォームです。
Welcome to Ceph — Ceph Documentation
Cephは4つのコンポーネントから成り立っています。
- Ceph Monitor (ceph-mon)
- Ceph Manager (ceph-rgw)
- Ceph OSD (object storage daemon (ceph-osd))
- Ceph Metadata Server (ceph-mds)
Ceph Monitorはクラスター状態を監視します。Monitorは少なくても3つ必要となります。
Ceph Managerはメトリクスやシステム負荷を監視やダッシュボードの提供します。Managerはすくなくても2つ必要となります。
Ceph OSDはデータを保存し、データのレプリケーション、リカバリ、リバランスを処理し、Ceph Monitor と Ceph Manager に監視情報を提供し
ます。OSDは少なくても3つ必要となります。
Ceph Metadata Serverは、CephFSのメタデータを保存し、Ceph Block Device とCephオブジェクトストレージは使用されません。
Rook Cephを試すにあたり、以前構築した手順から少し変更を加えます。
hidemium.hatenablog.com
Rook Cephでは通常のデプロイをする場合は、最低3台のノードが必要なため、workerノードを2台から4台に増やします。Kubesprayのhosts.ymlを以下のように書き換えます。
$ vi hosts.yml
all:
hosts:
kube-master01:
ansible_host: 10.0.50.30
ip: 10.0.50.30
access_ip: 10.0.50.30
kube-master02:
ansible_host: 10.0.50.31
ip: 10.0.50.31
access_ip: 10.0.50.31
kube-master03:
ansible_host: 10.0.50.32
ip: 10.0.50.32
access_ip: 10.0.50.32
kube-worker01:
ansible_host: 10.0.50.33
ip: 10.0.50.33
access_ip: 10.0.50.33
kube-worker02:
ansible_host: 10.0.50.34
ip: 10.0.50.34
access_ip: 10.0.50.34
kube-worker03:
ansible_host: 10.0.50.35
ip: 10.0.50.35
access_ip: 10.0.50.35
kube-worker04:
ansible_host: 10.0.50.36
ip: 10.0.50.36
access_ip: 10.0.50.36
children:
kube_control_plane:
hosts:
kube-master01:
kube-master02:
kube-master03:
kube_node:
hosts:
kube-worker01:
kube-worker02:
kube-worker03:
kube-worker04:
etcd:
hosts:
kube-master01:
kube-master02:
kube-master03:
k8s_cluster:
children:
kube_control_plane:
kube_node:
calico_rr:
hosts: {}
また、CNIをcalicoからflannelに変更します。
$ vi inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
- kube_network_plugin: calico
+ kube_network_plugin: flannel
masterノードとworkerノードのデプロイ
Ubuntu 22.04のテンプレートを作成し、以下のスペックでテンプレートを用意しておきます。
- CPU: 1vCPU
- Memory: 4GB
- Disk: 100GB
masterノードとworkerノードのスペックはそれぞれの以下の通りになります。
node |
vCPU |
Memory |
Disk1 |
Disk2 |
master |
1 |
4GB |
100GB |
- |
worker |
1 |
4GB |
100GB |
100GB |
govcを使って、テンプレートからのクローンやcloud-initの設定、追加ディスクのアタッチをまとめて、以下のように実行できます。
$ for VMNAME in kube-worker0{1..4}; do
echo ${VMNAME}
export VM="/Datacenter/vm/path/to/$VMNAME"
govc vm.clone -vm template-vm -on=false -folder="/Datacenter/vm/k8s" $VMNAME
export METADATA=$(gzip -c9 <metadata-${VMNAME}.yaml | { base64 -w0 2>/dev/null || base64; }) USERDATA=$(gzip -c9 <userdata-kube.yaml | { base64 -w0 2>/dev/null || base64; })
govc vm.change -vm "${VM}" -e guestinfo.metadata="${METADATA}" -e guestinfo.metadata.encoding="gzip+base64" -e guestinfo.userdata="${USERDATA}" -e guestinfo.userdata.encoding="gzip+base64"
govc vm.disk.create -vm ${VM} -name ${VMNAME}/${VMNAME}-disk2 -ds datastore_name -size 100G
govc vm.power -on "${VM}"
done
削除する場合は、以下のようにも実行できます。
$ for VMNAME in kube-worker0{1..3}; do
echo ${VMNAME}
export VM="/Datacenter/vm/path/to/$VMNAME"
govc vm.info "${VM}"
govc vm.destroy "${VM}"
done
Kubesprayによるクラスタ構築
以下のコマンドで再度Kubernetesクラスタを構築します。
$ ansible-playbook -i inventory/mycluster/hosts.yml --become --become-user=root cluster.yml
workerノードの状態の確認
デプロイ直後のworkerノードの状態を確認しておきます。
Disk2として接続したディスクが、 sdb
として表示されていることが分かります。 sda
側はOS領域としてLVMで構成されています。
$ lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
loop0 squashfs 4.0 0 100% /snap/lxd/23541
loop2 squashfs 4.0 0 100% /snap/core20/1738
loop3 squashfs 4.0 0 100% /snap/snapd/17883
loop4 squashfs 4.0 0 100% /snap/lxd/22923
loop5 squashfs 4.0 0 100% /snap/snapd/17950
loop6 squashfs 4.0 0 100% /snap/core20/1778
sda
├─sda1
├─sda2 ext4 1.0 a2ece314-f49d-4c09-ad59-6f90402eb8e6 1.3G 14% /boot
└─sda3 LVM2_member LVM2 001 nv6J0B-VyPL-K1x1-Rfti-oHC0-94RQ-DQ3tex
└─ubuntu--vg-ubuntu--lv ext4 1.0 2bcaf132-16b8-4b64-9e35-f200b40dfbf9 81G 12% /
sdb
Rookのインストール
それではRookのインストールを行っています。
まずは、rookのリポジトリをダウンロードします。
$ git clone --single-branch --branch v1.10.9 https://github.com/rook/rook.git
Rook Operatorをデプロイします。
$ cd rook
$ cd deploy/examples
$ kubectl create -f crds.yaml -f common.yaml -f operator.yaml
rook-ceph-operatorのpodが起動してきたことを確認します。
$ kubectl get pods -n rook-ceph
NAME READY STATUS RESTARTS AGE
rook-ceph-operator-76686d66c9-tjh8c 1/1 Running 0 6m13s
次にCeph Clusterをデプロイします。
$ kubectl create -f cluster.yaml
以下のようにpodが起動してくることを確認します。
$ kubectl -n rook-ceph get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
csi-cephfsplugin-688zw 2/2 Running 0 46h 10.0.50.35 kube-worker03 <none> <none>
csi-cephfsplugin-8qtzx 2/2 Running 0 46h 10.0.50.36 kube-worker04 <none> <none>
csi-cephfsplugin-bkdqh 2/2 Running 0 46h 10.0.50.34 kube-worker02 <none> <none>
csi-cephfsplugin-njz7s 2/2 Running 0 46h 10.0.50.33 kube-worker01 <none> <none>
csi-cephfsplugin-provisioner-75b9f74d7b-9spfw 5/5 Running 0 46h 10.233.68.4 kube-worker02 <none> <none>
csi-cephfsplugin-provisioner-75b9f74d7b-bvhjd 5/5 Running 0 46h 10.233.70.5 kube-worker03 <none> <none>
csi-rbdplugin-4h4lk 2/2 Running 0 46h 10.0.50.33 kube-worker01 <none> <none>
csi-rbdplugin-bglgs 2/2 Running 0 46h 10.0.50.35 kube-worker03 <none> <none>
csi-rbdplugin-p9xgj 2/2 Running 0 46h 10.0.50.34 kube-worker02 <none> <none>
csi-rbdplugin-provisioner-66d48ddf89-b6845 5/5 Running 0 46h 10.233.67.5 kube-worker04 <none> <none>
csi-rbdplugin-provisioner-66d48ddf89-rpjws 5/5 Running 0 46h 10.233.69.3 kube-worker01 <none> <none>
csi-rbdplugin-pspw6 2/2 Running 0 46h 10.0.50.36 kube-worker04 <none> <none>
rook-ceph-crashcollector-kube-worker01-9f7b6f546-q5h9b 1/1 Running 0 46h 10.233.69.6 kube-worker01 <none> <none>
rook-ceph-crashcollector-kube-worker02-67f84cb9b9-qfgdz 1/1 Running 0 46h 10.233.68.9 kube-worker02 <none> <none>
rook-ceph-crashcollector-kube-worker03-7687b79c6d-srxnr 1/1 Running 0 46h 10.233.70.6 kube-worker03 <none> <none>
rook-ceph-crashcollector-kube-worker04-76c99494c5-6psss 1/1 Running 0 46h 10.233.67.11 kube-worker04 <none> <none>
rook-ceph-mgr-a-6d8bb6dc9b-4hnkh 3/3 Running 0 46h 10.233.67.7 kube-worker04 <none> <none>
rook-ceph-mgr-b-96b47c755-bv2h8 3/3 Running 0 46h 10.233.68.6 kube-worker02 <none> <none>
rook-ceph-mon-a-bb685559c-gtjwm 2/2 Running 0 46h 10.233.70.4 kube-worker03 <none> <none>
rook-ceph-mon-b-6dcb8f97b9-xgnvn 2/2 Running 0 46h 10.233.67.6 kube-worker04 <none> <none>
rook-ceph-mon-c-c97b95cf6-l7ng4 2/2 Running 0 46h 10.233.68.5 kube-worker02 <none> <none>
rook-ceph-operator-54fc78d7c9-6n7gd 1/1 Running 0 46h 10.233.67.2 kube-worker04 <none> <none>
rook-ceph-osd-0-59645d69db-p7x56 2/2 Running 0 46h 10.233.70.8 kube-worker03 <none> <none>
rook-ceph-osd-1-69c67b85f9-cbqfc 2/2 Running 0 46h 10.233.68.10 kube-worker02 <none> <none>
rook-ceph-osd-2-7b56666677-qwt2x 2/2 Running 0 46h 10.233.67.10 kube-worker04 <none> <none>
rook-ceph-osd-3-5bf94d4467-pznrt 2/2 Running 0 46h 10.233.69.5 kube-worker01 <none> <none>
rook-ceph-osd-prepare-kube-worker01-l7pkg 0/1 Completed 0 3h51m 10.233.69.13 kube-worker01 <none> <none>
rook-ceph-osd-prepare-kube-worker02-dxx2c 0/1 Completed 0 3h51m 10.233.68.24 kube-worker02 <none> <none>
rook-ceph-osd-prepare-kube-worker03-2779b 0/1 Completed 0 3h51m 10.233.70.18 kube-worker03 <none> <none>
rook-ceph-osd-prepare-kube-worker04-vdd5w 0/1 Completed 0 3h51m 10.233.67.23 kube-worker04 <none> <none>
Ceph Clusterの状態を確認するため、以下のコマンドで確認します。MESSAGEが、Cluster created successfully となっており、HEALTHが HEALTH_OK となっていれば問題ありません。
$ kubectl -n rook-ceph get cephcluster
NAME DATADIRHOSTPATH MONCOUNT AGE PHASE MESSAGE HEALTH EXTERNAL
rook-ceph /var/lib/rook 3 39h Ready Cluster created successfully HEALTH_OK
toolboxを使って、Ceph Clusterの状態を確認しておきます。healthが HEALTH_OK となっていることが分かります。また、monのデーモンが3つ起動し、mgrが2つあり、osdが4つ起動していることが分かります。
$ kubectl apply -f toolbox.yaml
$ kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash
bash-4.4$ ceph status
cluster:
id: 13a113cd-9060-4f1a-9fef-44d1bfe4fe26
health: HEALTH_OK
services:
mon: 3 daemons, quorum a,b,c (age 13h)
mgr: b(active, since 13h), standbys: a
osd: 4 osds: 4 up (since 13h), 4 in (since 13h)
data:
pools: 1 pools, 1 pgs
objects: 2 objects, 449 KiB
usage: 45 MiB used, 400 GiB / 400 GiB avail
pgs: 1 active+clea
Rookのインストールの補足
特定ノードや特定デバイスにインストールをしたい場合に、cluster.yamlで以下のパラメータの設定を行います。
今回は、masterノードとworkerノードはKubesprayでデプロイする際に指定を行っており、workerノードはsdbがRaw Deviceとなっており、すべて同じ構成となっているためデフォルト値のまま利用しています。デフォルト値のままで、workerノードのsdbだけが利用されるようになります。
$ vi cluster.yaml
spec:
storage:
useAllNodes: true
useAllDevices: true
# nodes:
# - name: "172.17.4.201"
# devices: # specific devices to use for storage can be specified for each node
# - name: "sdb"
Cephストレージクラスタを構成する場合は、システム要件として以下の少なくても一つの構成が必要となっています。
* Raw devices (no partitions or formatted filesystems)
* Raw partitions (no formatted filesystem)
* LVM Logical Volumes (no formatted filesystem)
* Persistent Volumes available from a storage class in block mode
仮想マシンにハード ディスク 2を接続し、OS内で特に設定はせずに、OSでデバイスが認識できていればシステム要件は満たせそうでした。
workerノードの状態の確認
Rookをインストール後のworkerノードの状態を確認しておきます。
Disk2として接続した sdb
がceph_bluestoreとしてフォーマットされていることが分かります。Raw deviceの場合、自動的にceph_bluestoreが選択されるようです。
$ lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
loop0 squashfs 4.0 0 100% /snap/lxd/23541
loop1 squashfs 4.0 0 100% /snap/core20/1778
loop2 squashfs 4.0 0 100% /snap/snapd/17883
loop3 squashfs 4.0 0 100% /snap/core20/1738
loop4 squashfs 4.0 0 100% /snap/lxd/22923
loop5 squashfs 4.0 0 100% /snap/snapd/17950
sda
├─sda1
├─sda2 ext4 1.0 a2ece314-f49d-4c09-ad59-6f90402eb8e6 1.3G 14% /boot
└─sda3 LVM2_member LVM2 001 nv6J0B-VyPL-K1x1-Rfti-oHC0-94RQ-DQ3tex
└─ubuntu--vg-ubuntu--lv
ext4 1.0 2bcaf132-16b8-4b64-9e35-f200b40dfbf9 80.6G 12% /
sdb ceph_bluestore
StorageClassのデプロイ
ブロックストレージ(RDB)のStorageClassとCephBlockPoolをデプロイします。
$ cd deploy/examples
$ kubectl create -f csi/rbd/storageclass.yaml
Wordpress をデプロイし、動作確認を行います。
$ kubectl create -f mysql.yaml
$ kubectl create -f wordpress.yaml
Wordpress とWordpress用のMySQLのpodが起動していることを確認します。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
wordpress-7cf5c5c8b-lbjln 1/1 Running 0 2m9s
wordpress-mysql-6f99c59595-djvm9 1/1 Running 0 2m15s
Wordpressのサービスを確認すると、 type: LoadBalancer
でMetalLBからIPアドレスが付与されていることが分かります。
$ kubectl get svc wordpress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wordpress LoadBalancer 10.233.38.114 10.0.50.203 80:30242/TCP 19h
ブラウザから http://10.0.50.203/
にアクセスし、Wordpressの初期設定が画面が表示されることを確認します。
PVとPVCが作成されていることを確認します。
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-32b6f27b-5d03-4ed8-9478-82cf64ed73f1 20Gi RWO Delete Bound default/mysql-pv-claim rook-ceph-block 19h
pvc-bcfab821-a7f8-4df0-8788-0144e06f2435 20Gi RWO Delete Bound default/wp-pv-claim rook-ceph-block 19h
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-pv-claim Bound pvc-32b6f27b-5d03-4ed8-9478-82cf64ed73f1 20Gi RWO rook-ceph-block 19h
wp-pv-claim Bound pvc-bcfab821-a7f8-4df0-8788-0144e06f2435 20Gi RWO rook-ceph-block 19h
toolboxからceph statusを確認し、objectsやusageが増えていることを確認します。
bash-4.4$ ceph status
cluster:
id: 13a113cd-9060-4f1a-9fef-44d1bfe4fe26
health: HEALTH_OK
services:
mon: 3 daemons, quorum a,b,c (age 14h)
mgr: b(active, since 14h), standbys: a
osd: 4 osds: 4 up (since 14h), 4 in (since 14h)
data:
pools: 2 pools, 33 pgs
objects: 118 objects, 275 MiB
usage: 816 MiB used, 399 GiB / 400 GiB avail
pgs: 33 active+clean
io:
client: 2.0 KiB/s wr, 0 op/s rd, 0 op/s wr
リソースの削除
動作確認ができたため、リソースを削除しておきます。
$ kubectl delete -f wordpress.yaml
$ kubectl delete -f mysql.yaml
発生した事象について
上記の記載を見ると、特に通常の手順で簡単にインストールできそうに見えますが、いくつかはまりました。
KubesprayのデフォルトのCNIはcalicoですが、この状態でRookをインストールすると、Configuring Ceph Monsのメッセージのまま、monの起動でとまってしまい、インストールが正常に完了しませんでした。
$ kubectl -n rook-ceph get cephcluster
NAME DATADIRHOSTPATH MONCOUNT AGE PHASE MESSAGE HEALTH EXTERNAL
rook-ceph /var/lib/rook 3 2m54s Progressing Configuring Ceph Mons
rook-ceph-operatorのログには、op-mon: mons running: [a]が表示され続ける状態となりました。
$ kubectl -n rook-ceph logs -l app=rook-ceph-operator -f
2023-01-18 21:40:56.423974 I | op-mon: waiting for mon quorum with [a]
2023-01-18 21:40:56.703448 I | op-mon: mons running: [a]
2023-01-18 21:41:17.104072 I | op-mon: mons running: [a]
2023-01-18 21:41:37.314370 I | op-mon: mons running: [a]
2023-01-18 21:41:57.519969 I | op-mon: mons running: [a]
2023-01-18 21:42:17.716778 I | op-mon: mons running: [a]
2023-01-18 21:42:37.944062 I | op-mon: mons running: [a]
2023-01-18 21:42:58.128773 I | op-mon: mons running: [a]
2023-01-18 21:43:18.339845 I | op-mon: mons running: [a]
2023-01-18 21:43:38.572259 I | op-mon: mons running: [a]
ログの出力として、他に異常はなく、何が起きているか確認できない状態でしたが、monの数を1に変更した場合に処理が通過することがあり、rook-ceph-operatorとmonのpod間の通信に問題がありそうということが見えていました。
また、以下のissueにも同様の事象が報告されており、calicoからflannelに変更することで事象が改善したとありました。
Mons not forming quorum · Issue #7769 · rook/rook · GitHub
こちらのissueでも議論されており、Rookとcalicoの組み合わせといったKubernetesのツール間での組み合わせ問題がありそうです。
Rook Ceph Mons unable to form quorum when using Calico CNI · Issue #5065 · rook/rook · GitHub
参考