はじめに
自宅のラズパイkubernetesクラスタの永続ストレージをなんとかしたいと思い、Cephに手を出してしまいました。結構大変な作業量でしたので書き記しておきます。
前提環境
簡単な図です。IoTの実験も兼ねて回線品質の悪いwifi経由のkubernetesクラスタが1台おります。
- Raspberry Pi 4B(RAM:4GB) * 5台 (Masterノード1台,Workerノード4台)
- USBのSSD(250GB)から起動
- 1台は遠隔にあり監視カメラとして利用中(今回使用しない)
- OSは、Raspberry Pi OS 64bit(beta)
# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
chino Ready master 8d v1.19.2 10.0.0.1 <none> Debian GNU/Linux 10 (buster) 5.4.51-v8+ docker://19.3.13
chiya Ready worker 8d v1.19.2 10.0.0.5 <none> Debian GNU/Linux 10 (buster) 5.4.51-v8+ docker://19.3.13
cocoa Ready worker 46h v1.19.2 10.0.0.2 <none> Debian GNU/Linux 10 (buster) 5.4.51-v8+ docker://19.3.13
rize Ready worker 2d2h v1.19.2 10.0.0.3 <none> Debian GNU/Linux 10 (buster) 5.4.51-v8+ docker://19.3.13
syaro Ready worker 42h v1.19.2 10.0.0.4 <none> Debian GNU/Linux 10 (buster) 5.4.51-v8+ docker://19.3.13
Ceph用パーティション作成
workerノードのSSDに新規パーティションを作成します。
私の構成ではどのノードもUSBブートで接続しているSSD(250GB)のみの運用なので、今回はmicroSDのRaspberry Pi OSを起動して作業しました。
# e2fsck -f /dev/sda2
# resize2fs /dev/sda2 100G
# fdisk /dev/sda
Device Boot Start End Sectors Size Id Type
/dev/sda1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/sda2 532480 488397167 487864688 233G 83 Linux
※「p」で、パーティション情報を表示。「/」パーティション(/dev/sda2)の開始位置を確認。
※「d」で、第2パーティションを削除。
※ 改めて同じ開始位置から第2パーティション作成。終了位置は「+100G」で指定。
※「w」でパーティション変更を保存。
# partprobe
# e2fsck -f /dev/sda2
※ここでエラーが出る場合は修復せずに「Ctrl」+「c」で抜けて、今度はpartedで/dev/sda2を切り直してみるとうまく行く場合がある。
# fdisk /dev/sda
※「n」で、残り全部で/dev/sda3を作成。パーティションタイプは、8eの「Linux LVM」。
# partprobe
# fdisk -l /dev/sda
Device Boot Start End Sectors Size Id Type
/dev/sda1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/sda2 532480 210247679 209715200 100G 83 Linux
/dev/sda3 210247680 488397167 278149488 132.6G 8e Linux LVM
これをworkerノード3台で実施。サービスを止めたくなかったので、1台ずつkubernetesのdrainをして、再度参加させました。
Ethernetコンバータ経由でkubernetesクラスタに参加している別の部屋のworkerノード(chiya)は使いません。
あと、電力供給に問題が無いのであれば、USBにもう1台SSDを追加した方がresize2fsで壊すリスクも無いですし、作業は早いです。
...今回、resize2fsに失敗してworkerノードを2台再構築してます。
Cephの構築
『ラズパイ上のKubernetesにCephを入れてみた』という記事の記載どおりに作業しました。CephのドキュメントURLが変わった事もあり、Ceph関連の情報はデッドリンクが多い中、日本語でこのような情報があると非常に助かりますね。
以下は、masterノードでの作業です。コマンド実行中に、ひたすらパスワードを打ちました。
# mkdir ceph-deploy
# cd ceph-deploy
# pip install ceph-deploy
# ceph-deploy --username pi new cocoa rize syaro
# ceph-deploy --username pi install cocoa rize syaro
# ceph-deploy install chino
# ceph-deploy --username pi mon create-initial
# ceph-deploy --username pi admin cocoa rize syaro
# ceph-deploy admin chino
# ceph-deploy --username pi osd create cocoa --data /dev/sda3
# ceph-deploy --username pi osd create rize --data /dev/sda3
# ceph-deploy --username pi osd create syaro --data /dev/sda3
# ceph-deploy --username pi mds create cocoa
poolの作成
コマンド最後のPG数は、あまり大きくするとリソース消費量が多くなるそうです。
# ceph osd pool create kubernetes 128
Ceph-CSI ConfigMapの作成
fsidと、IPアドレス,ポート番号を確認します。
# ceph mon dump
dumped monmap epoch 2
epoch 2
fsid 56b03534-e602-4856-8734-8bcdf5cc8670
last_changed 2020-09-20 01:24:55.648189
created 2020-09-20 01:24:08.811926
0: 10.0.0.2:6789/0 mon.cocoa
1: 10.0.0.3:6789/0 mon.rize
2: 10.0.0.4:6789/0 mon.syaro
作成したyamlは以下です。
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
[
{
"clusterID": "56b03534-e602-4856-8734-8bcdf5cc8670",
"monitors": [
"10.0.0.2:6789",
"10.0.0.3:6789",
"10.0.0.4:6789"
]
}
]
metadata:
name: ceph-csi-config
適用します。
# kubectl apply -f csi-config-map.yaml
RBD Secret作成
クライアント認証用のキーを作成します。
# ceph auth get-or-create client.kubernetes mon 'profile rbd' osd 'profile rbd pool=kubernetes' mgr 'profile rbd pool=kubernetes'
[client.kubernetes]
key = AQBrNmZfVCowLBAAeN3EYjhOPBG9442g4NF/bQ==
作成したyamlは以下です。
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: default
stringData:
userID: kubernetes
userKey: AQBrNmZfVCowLBAAeN3EYjhOPBG9442g4NF/bQ==
適用します。
# kubectl apply -f csi-rbd-secret.yaml
KMS ConfigMap(空)の作成
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
{
}
metadata:
name: ceph-csi-encryption-kms-config
適用します。
# kubectl apply -f kms-config.yaml
※おそらく「# kubectl create configmap ceph-csi-encryption-kms-config」でもいいんじゃないかと思ってます。
RBAC定義
# wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-provisioner-rbac.yaml
# kubectl apply -f csi-provisioner-rbac.yaml
# wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-nodeplugin-rbac.yaml
# kubectl apply -f csi-nodeplugin-rbac.yaml
コンテナイメージの作成
ここらから参考にしているサイトから若干手順を変えて書きます。作業はmasterノードじゃない方が良いはずですが、masterノードでやりました。
先にcsiのyamlを取得して、cephcsiをarm64に変えておきます。
# wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml
# sed -i -e 's/quay.io\/cephcsi\/cephcsi:canary/quay.io\/cephcsi\/cephcsi:canary-arm64/g' csi-rbdplugin-provisioner.yaml
# wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-rbdplugin.yaml
# sed -i -e 's/quay.io\/cephcsi\/cephcsi:canary/quay.io\/cephcsi\/cephcsi:canary-arm64/g' csi-rbdplugin.yaml
で、imageで使われているコンテナイメージのバージョンを確認します。
# grep image: csi-rbdplugin-provisioner.yaml csi-rbdplugin.yaml
csi-rbdplugin-provisioner.yaml: image: quay.io/k8scsi/csi-provisioner:v1.6.0
csi-rbdplugin-provisioner.yaml: image: quay.io/k8scsi/csi-snapshotter:v2.1.0
csi-rbdplugin-provisioner.yaml: image: quay.io/k8scsi/csi-attacher:v2.1.1
csi-rbdplugin-provisioner.yaml: image: quay.io/k8scsi/csi-resizer:v0.5.0
csi-rbdplugin-provisioner.yaml: image: quay.io/cephcsi/cephcsi:canary-arm64
csi-rbdplugin-provisioner.yaml: image: quay.io/cephcsi/cephcsi:canary-arm64
csi-rbdplugin.yaml: image: quay.io/k8scsi/csi-node-driver-registrar:v1.3.0
csi-rbdplugin.yaml: image: quay.io/cephcsi/cephcsi:canary-arm64
csi-rbdplugin.yaml: image: quay.io/cephcsi/cephcsi:canary-arm64
バージョンに(大体)合ったブランチをgit cloneします。
# git clone --single-branch --branch release-1.6 https://github.com/kubernetes-csi/external-provisioner
# git clone --single-branch --branch release-2.1 https://github.com/kubernetes-csi/external-snapshotter
# git clone --single-branch --branch release-2.1 https://github.com/kubernetes-csi/external-attacher
# git clone --single-branch --branch release-0.5 https://github.com/kubernetes-csi/external-resizer
# git clone --single-branch --branch release-1.3 https://github.com/kubernetes-csi/node-driver-registrar
※attacher:v2.2.1の取得方法がわからなかったので、2.1にしてます。
goのダウンロードをします。https://golang.org/dl/
先に書いておきますが、上記で取得したバージョンのコンテナイメージのmakeでは「go-1.13」を想定しているようです。
※ここでは、その時最新だったと思われるgo-1.15.1をダウンロードしています。
※世代にもよると思いますが、goは心の中では「ンゴゥ」と読んでしまいます。
# wget https://dl.google.com/go/go1.15.1.linux-arm64.tar.gz
# tar xzvf go1.15.1.linux-arm64.tar.gz
# rm go1.15.1.linux-arm64.tar.gz
# echo 'export GOPATH=$HOME/go' >> ~/.bashrc
# echo 'export PATH=$GOPATH/bin:$PATH' >> ~/.bashrc
# source ~/.bashrc
# go version
go version go1.15.1 linux/arm64
makeしてdockerイメージを作成します。
# cd external-provisioner
# make
# docker build -t csi-provisioner:v1.6.0 .
# cd ../external-snapshotter
# make
# cp cmd/csi-snapshotter/Dockerfile .
# docker build -t csi-snapshotter:v2.1.0 .
# cd ../external-attacher
# make
# docker build -t csi-attacher:v2.1.0 .
# cd ../external-resizer
# make
# docker build -t csi-resizer:v0.5.0 .
# cd ../node-driver-registrar
# make
# docker build -t csi-node-driver-registrar:v1.3.0 .
snapshotterだけDockerfileがよくわからん事になってました。...おそらく作業手順が違うのでしょうが、強引にイメージ作りました。
イメージはdockerに入るので、saveしてworkerノードのdockerにloadしておきます。
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
csi-node-driver-registrar v1.3.0 a6e114649cf9 33 hours ago 14.2MB
csi-resizer v0.5.0 d6b561c2aa0a 34 hours ago 41.6MB
csi-attacher v2.1.0 807c3900bf76 34 hours ago 41.7MB
csi-snapshotter v2.1.0 653dbf034d1d 34 hours ago 41.8MB
csi-provisioner v1.6.0 4b18fda1685c 34 hours ago 43.4MB
(以下略)
# docker save csi-node-driver-registrar:v1.3.0 -o csi-node-driver-registrar.tar
# docker save csi-resizer:v0.5.0 -o csi-resizer.tar
# docker save csi-attacher:v2.1.0 -o csi-attacher.tar
# docker save csi-snapshotter:v2.1.0 -o csi-snapshotter.tar
# docker save csi-provisioner:v1.6.0 -o csi-provisioner.tar
workerノードにscpでもsftpでも何でもいいのでコピーします。
コピーしたら、各workerノードで以下のコマンドを実行します。一応、使用しないworkerノードにも入れました。
# docker load -i csi-node-driver-registrar.tar
# docker load -i csi-resizer.tar
# docker load -i csi-attacher.tar
# docker load -i csi-snapshotter.tar
# docker load -i csi-provisioner.tar
Cephのデプロイ
で、ceph-deployでの作業に戻ります。
「csi-rbdplugin-provisioner.yaml」と「csi-rbdplugin.yaml」の「image:」箇所を以下のように、作成したイメージのリポジトリ・タグに変更しました。
※長いので差分だけ表示させました。
# grep -n image: csi-rbdplugin-provisioner.yaml csi-rbdplugin.yaml
csi-rbdplugin-provisioner.yaml:35: image: csi-provisioner:v1.6.0
csi-rbdplugin-provisioner.yaml:52: image: csi-snapshotter:v2.1.0
csi-rbdplugin-provisioner.yaml:68: image: csi-attacher:v2.1.0
csi-rbdplugin-provisioner.yaml:82: image: csi-resizer:v0.5.0
csi-rbdplugin-provisioner.yaml:102: image: quay.io/cephcsi/cephcsi:canary-arm64
csi-rbdplugin-provisioner.yaml:142: image: quay.io/cephcsi/cephcsi:canary-arm64
csi-rbdplugin.yaml:28: image: csi-node-driver-registrar:v1.3.0
csi-rbdplugin.yaml:50: image: quay.io/cephcsi/cephcsi:canary-arm64
csi-rbdplugin.yaml:102: image: quay.io/cephcsi/cephcsi:canary-arm64
では、デプロイしましょう。成功例しか無いですが...
# kubectl apply -f csi-rbdplugin-provisioner.yaml
# kubectl apply -f csi-rbdplugin.yaml
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
csi-rbdplugin-hm9bm 3/3 Running 3 24h 10.0.0.4 syaro <none> <none>
csi-rbdplugin-provisioner-54dd99dd97-f9x2s 6/6 Running 6 24h 172.16.4.40 syaro <none> <none>
csi-rbdplugin-provisioner-54dd99dd97-flbh9 6/6 Running 0 24h 172.16.2.28 cocoa <none> <none>
csi-rbdplugin-provisioner-54dd99dd97-s9qf4 6/6 Running 0 24h 172.16.3.54 rize <none> <none>
csi-rbdplugin-t7569 3/3 Running 0 24h 10.0.0.3 rize <none> <none>
csi-rbdplugin-x4fzk 3/3 Running 3 24h 10.0.0.5 chiya <none> <none>
csi-rbdplugin-xwrnx 3/3 Running 0 24h 10.0.0.2 cocoa <none> <none>
デプロイ時に、「# kubectl get events -w」としておく事をお勧めします。
StorageClassの作成
StorageClassの作成をします。今更ですが、namespaceはdefaultじゃない方がいいかもしれませんね。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID: "56b03534-e602-4856-8734-8bcdf5cc8670"
pool: kubernetes
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace: default
reclaimPolicy: Delete
mountOptions:
- discard
適用します。
# kubectl apply -f csi-rbd-sc.yaml
あとは、アプリ側でPVCを作成する際に「storageClassName」を「csi-rbd-sc」指定してください。
ダイナミックプロビジョニングで使え....ません。
参考にしているサイトのPVCの定義では確認できませんでしたが、Rawモードの「volumeMode: Block」を削除したところ、以下のようなeventが出力されました。
default 0s Warning FailedMount pod/es-cluster-0 MountVolume.MountDevice failed for volume "pvc- ...
...... rbd error output: modinfo: ERROR: Module rbd not found.
modprobe: FATAL: Module rbd not found in directory /lib/modules/5.4.51-v8+
rbd: failed to load rbd kernel module (1)
rbd: sysfs write failed
rbd: map failed: (2) No such file or directory
deault 0s Warning FailedMount pod/es-cluster-0 Unable to attach or mount volumes: unmounted.....
前提に戻っちゃいますが、「rbd」というkernelモジュールが必要です。
そして、Raspberry Pi OS 64bit(Beta)ではそもそも「rbd」モジュールがコンパイルされていません。
つまり、kernelのコンパイルをしなければなりません。
コマンドでは各クライアントから使えるのに、なぜkernelモジュールが必要なのかは、『Deep Dive Into Ceph’s Kernel Client』あたりで理解しました。(半分くらい)
コマンドはライブラリで使えて、コンテナ環境ではkernelモジュールが必要らしいです。
kernelビルド
Linux kernelのコンパイルですが、昔は日常茶飯事の作業でした。
まだkernel moduleの概念が無かった頃、ロードできるkernelサイズに限度があり、皆自分のマシンに合ったkernelをギリギリのサイズでコンパイルしてました。新しいデバイスを追加する度にkernelコンパイルしてましたね。
なので、やった事はあるけど今どうなってんの?って感じで作業しました。
マニュアルは『Kernel building』になりますが、まだbetaの64bit版なので実際にやってる方の投稿を参考にしました。
作業は1時間ほどかかりました。
# apt install git libncurses-dev flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf bc
# git clone --depth=1 -b rpi-5.4.y https://github.com/raspberrypi/linux.git
# cd linux/
# make bcm2711_defconfig
# vi .config
(「CONFIG_BLK_DEV_RBD=m」を適当に書き加えます。)
# make -j4
(RBDを有効にする関係で、cephfsの設問が出てくると思いますが、よくわからなかったので全部「N」にしました。)
# make modules_install
# make dtbs_install
# cp /boot/kernel8.img /boot/kernel8_old.img
# cp arch/arm64/boot/Image /boot/kernel8.img
# vi /boot/config.txt
(フォーラムの投稿では「#」が付いてますが、以下3行を追記します。)
device_tree=dtbs/5.4.65-v8+/broadcom/bcm2711-rpi-4-b.dtb
overlay_prefix=dtbs/5.4.65-v8+/overlays/
kernel=kernel8.img
昔はドキドキしながら再起動させてましたが、さくっとやります。復旧できる自信がありますからね...
# reboot
一通り確認します。カスタムkernelなので、もう有償サポートは受けられません。(そんなもの入ってませんが)
# uname -a
Linux syaro 5.4.65-v8+ #1 SMP PREEMPT Mon Sep 21 01:04:01 JST 2020 aarch64 GNU/Linux
# modprobe rbd
# lsmod | grep rbd
rbd 98304 0
libceph 278528 1 rbd
# modinfo rbd
filename: /lib/modules/5.4.65-v8+/kernel/drivers/block/rbd.ko
license: GPL
description: RADOS Block Device (RBD) driver
author: Jeff Garzik <jeff@garzik.org>
author: Yehuda Sadeh <yehuda@hq.newdream.net>
author: Sage Weil <sage@newdream.net>
author: Alex Elder <elder@inktank.com>
srcversion: BC90D52477A5CE4593C5AC3
depends: libceph
intree: Y
name: rbd
vermagic: 5.4.65-v8+ SMP preempt mod_unload modversions aarch64
parm: single_major:Use a single major number for all rbd devices (default: true) (bool)
良さそうです。
workerのkernelは全部入れ替えました。
# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
chino Ready master 16d v1.19.2 10.0.0.1 <none> Debian GNU/Linux 10 (buster) 5.4.51-v8+ docker://19.3.13
chiya Ready worker 16d v1.19.2 10.0.0.5 <none> Debian GNU/Linux 10 (buster) 5.4.65-v8+ docker://19.3.13
cocoa Ready worker 9d v1.19.2 10.0.0.2 <none> Debian GNU/Linux 10 (buster) 5.4.65-v8+ docker://19.3.13
rize Ready worker 10d v1.19.2 10.0.0.3 <none> Debian GNU/Linux 10 (buster) 5.4.65-v8+ docker://19.3.13
syaro Ready worker 9d v1.19.2 10.0.0.4 <none> Debian GNU/Linux 10 (buster) 5.4.65-v8+ docker://19.3.13
Ceph CSI StorageClass を使ったアプリのデプロイ
それでは、rbd kernelモジュールが無かった事により、一度失敗に終わったデプロイの再試行をします。
とあるサイトで参考にさせてもらっている、elasticsearchのシングルノード(statefulset版)です。
これを元にマルチノードにしようとしてます。(参考にしているサイトにありますが、更にpluginを入れたりしたいので...)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: es-cluster
spec:
selector:
matchLabels:
app: es
serviceName: "es-cluster"
replicas: 1
template:
metadata:
labels:
app: es
spec:
containers:
- name: es
image: elasticsearch:7.9.1
env:
- name: discovery.type
value: single-node
ports:
- containerPort: 9200
name: api
- containerPort: 9300
name: gossip
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-sc
適用します。
# kubectl apply -f es_master_sts.yaml
podの状態を確認。
# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
csi-rbdplugin-hm9bm 3/3 Running 3 25h
csi-rbdplugin-provisioner-54dd99dd97-f9x2s 6/6 Running 6 25h
csi-rbdplugin-provisioner-54dd99dd97-flbh9 6/6 Running 0 25h
csi-rbdplugin-provisioner-54dd99dd97-s9qf4 6/6 Running 0 25h
csi-rbdplugin-t7569 3/3 Running 0 25h
csi-rbdplugin-x4fzk 3/3 Running 3 25h
csi-rbdplugin-xwrnx 3/3 Running 0 25h
es-cluster-0 0/1 Pending 0 0s
es-cluster-0 0/1 Pending 0 0s
es-cluster-0 0/1 Pending 0 2s
es-cluster-0 0/1 ContainerCreating 0 2s
es-cluster-0 1/1 Running 0 8s
イベントの監視。
# kubectl get events -w
LAST SEEN TYPE REASON OBJECT MESSAGE
0s Normal SuccessfulCreate statefulset/es-cluster create Claim data-es-cluster-0 Pod es-cluster-0 in StatefulSet es-cluster success
0s Normal ExternalProvisioning persistentvolumeclaim/data-es-cluster-0 waiting for a volume to be created, either by external provisioner "rbd.csi.ceph.com" or manually created by system administrator
0s Normal Provisioning persistentvolumeclaim/data-es-cluster-0 External provisioner is provisioning volume for claim "default/data-es-cluster-0"
0s Normal SuccessfulCreate statefulset/es-cluster create Pod es-cluster-0 in StatefulSet es-cluster successful
0s Warning FailedScheduling pod/es-cluster-0 0/5 nodes are available: 5 pod has unbound immediate PersistentVolumeClaims.
0s Warning FailedScheduling pod/es-cluster-0 0/5 nodes are available: 5 pod has unbound immediate PersistentVolumeClaims.
0s Normal ProvisioningSucceeded persistentvolumeclaim/data-es-cluster-0 Successfully provisioned volume pvc-1c1abfad-87fa-4882-a840-8449c6d50326
0s Normal Scheduled pod/es-cluster-0 Successfully assigned default/es-cluster-0 to syaro
0s Normal SuccessfulAttachVolume pod/es-cluster-0 AttachVolume.Attach succeeded for volume "pvc-1c1abfad-87fa-4882-a840-8449c6d50326"
0s Normal Pulled pod/es-cluster-0 Container image "elasticsearch:7.9.1" already present on machine
0s Normal Created pod/es-cluster-0 Created container es
0s Normal Started pod/es-cluster-0 Started container es
ストレージ関連の確認。
# kubectl get sc,pv,pvc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
storageclass.storage.k8s.io/csi-rbd-sc rbd.csi.ceph.com Delete Immediate false 25h
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-1c1abfad-87fa-4882-a840-8449c6d50326 1Gi RWO Delete Bound default/data-es-cluster-0 csi-rbd-sc 78s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/data-es-cluster-0 Bound pvc-1c1abfad-87fa-4882-a840-8449c6d50326 1Gi RWO csi-rbd-sc 78s
特にpodの削除再デプロイでも作成したファイルは残ってました。(当たり前)
別項にするほどでもないですが、性能面です。元々私はハード面は苦手で、ここらのノウハウはあんまりないのですが、ddで書き込んだ結果を書いておきます。
# dd if=/dev/zero of=aaa bs=4096 count=100000
1回目 | 2回目 | 3回目 | 4回目 | 5回目 | |
---|---|---|---|---|---|
workerのホストOS上 | 186 MB/s | 133 MB/s | 141 MB/s | 140 MB/s | 133 MB/s |
hostpath | 120 MB/s | 121 MB/s | 134 MB/s | 131 MB/s | 131 MB/s |
ceph-csi | 186 MB/s | 185 MB/s | 174 MB/s | 178 MB/s | 180 MB/s |
ceph-csiは計測時には出なかったんですが、たまに50MB/sの時もあったり、コマンドの戻りが遅かったりとピーキーな感じがしますね。何が影響しているんだろうか...
namespaceの変更 (追記:2020/10/2)
namespaceを「default」から「storage」に変更しました。
# grep -n namespace *.yaml
csi-config-map.yaml:18: namespace: storage
csi-nodeplugin-rbac.yaml:6: namespace: storage
csi-nodeplugin-rbac.yaml:12: namespace: storage
csi-nodeplugin-rbac.yaml:22: namespace: storage
csi-nodeplugin-rbac.yaml:26: namespace: storage
csi-provisioner-rbac.yaml:6: namespace: storage
csi-provisioner-rbac.yaml:13: namespace: storage
csi-provisioner-rbac.yaml:59: namespace: storage
csi-provisioner-rbac.yaml:63: namespace: storage
csi-provisioner-rbac.yaml:73: # replace with non-default namespace name
csi-provisioner-rbac.yaml:74: namespace: storage
csi-provisioner-rbac.yaml:89: # replace with non-default namespace name
csi-provisioner-rbac.yaml:90: namespace: storage
csi-provisioner-rbac.yaml:94: # replace with non-default namespace name
csi-provisioner-rbac.yaml:95: namespace: storage
csi-rbd-sc.yaml:5: namespace: storage
csi-rbd-sc.yaml:11: csi.storage.k8s.io/provisioner-secret-namespace: storage
csi-rbd-sc.yaml:13: csi.storage.k8s.io/node-stage-secret-namespace: storage
csi-rbd-secret.yaml:6: namespace: storage
csi-rbdplugin-provisioner.yaml:6: namespace: storage
csi-rbdplugin-provisioner.yaml:23: namespace: storage
csi-rbdplugin.yaml:6: namespace: storage
csi-rbdplugin.yaml:167: namespace: storage
kms-config.yaml:9: namespace: storage
特に問題なく動いているようです。
注意点として、「csi-rbd-secret」は、ceph-csiを利用するアプリの属するnamespace毎に必要になると思われます。
# kubectl get pod,svc,configmap,secret -n storage
NAME READY STATUS RESTARTS AGE
pod/csi-rbdplugin-2v8bg 3/3 Running 0 22h
pod/csi-rbdplugin-97p24 3/3 Running 0 22h
pod/csi-rbdplugin-b86dk 3/3 Running 0 22h
pod/csi-rbdplugin-b8jtj 3/3 Running 0 22h
pod/csi-rbdplugin-provisioner-7f97bcf6fc-2zj78 6/6 Running 0 22h
pod/csi-rbdplugin-provisioner-7f97bcf6fc-fntnx 6/6 Running 0 22h
pod/csi-rbdplugin-provisioner-7f97bcf6fc-s99jh 6/6 Running 0 22h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/csi-metrics-rbdplugin ClusterIP 10.96.142.248 <none> 8080/TCP 22h
service/csi-rbdplugin-provisioner ClusterIP 10.96.247.32 <none> 8080/TCP 22h
NAME DATA AGE
configmap/ceph-csi-config 1 22h
configmap/ceph-csi-encryption-kms-config 1 22h
NAME TYPE DATA AGE
secret/csi-rbd-secret Opaque 2 22h
secret/default-token-f294q kubernetes.io/service-account-token 3 22h
secret/rbd-csi-nodeplugin-token-q2sbs kubernetes.io/service-account-token 3 22h
secret/rbd-csi-provisioner-token-d87mw kubernetes.io/service-account-token 3 22h
不足していた事 (追記:2020/10/19)
上記の手順では、ceph-mgrが構築されていませんでした。気になってたのですが、動いてたのでほったらかしていました。
# ceph health
HEALTH_WARN no active mgr
色々調べると、ceph-mgrのサービス自体がなかったので、作業自体が抜けていたようです。
ceph-mgrはコマンド1つで構築できるようです。
# ceph-deploy mgr create chino
状態を再度確認すると、まだ警告が出ていました。
# ceph health
HEALTH_WARN application not enabled on 1 pool(s)
「poolで有効なアプリケーションが無い」というものです。
これも色々調べて以下のコマンドを実施して解消しました。
# ceph osd pool application enable kubernetes rbd
enabled application 'rbd' on pool 'kubernetes'
コマンド最後の「アプリケーション名」は、ドキュメントによると、「cephfs」「rbd」「rgw」のどれかを指定するようです。
「rbd」という部分で「おや?」と思ったのですが、ドキュメントでは「RBDで使う場合には初期化が必要です」と書かれています。つまり、「poolの作成」で、ここに書かれている初期化コマンドを実施しなければならなかったはずです。
# rbd pool init kubernetes
※ elasticsearchのデータを保存していたのですが、「まぁ壊れても...」と思って実行しました。...特に致命的なエラーも出ませんでした。が、実行は自己責任でお願いします。
とりあえず、これでヘルスチェックは問題無い状態になりました。
# ceph health
HEALTH_OK
Ceph Dashboard (追記:2020/11/4)
ブラウザからCephの状態が確認できる便利なもののようです。以下のコマンドで有効になりました。
# ceph mgr module enable dashboard
確認は以下のコマンドで...
# ceph mgr module ls
{
"enabled_modules": [
"balancer",
"dashboard",
"restful",
"status"
],
"disabled_modules": [
"influx",
"localpool",
"prometheus",
"selftest",
"zabbix"
]
}
アクセス先がわからなかったのですが、以下のコマンドで確認できるようです。
まぁ、「netstat -anpl | grep ceph」でLISTENしているポートにアクセスすれば良かっただけなのですが...
# ceph mgr services
{
"dashboard": "http://chino.rabbithouse.net:7000/"
}
無事にブラウザから確認できました。(見方や使い方はまだよくわかってません)
おわりに
どうやら、ceph-deployでの構築は非推奨で、ROOKが推奨のようです。(https://docs.ceph.com/en/latest/install/)
しかし、ここまでできればROOK(operator)で構築するタイプも、なんとかコンテナイメージを変えて動かせられるのではないかと考えています。その方が、OpenShift Container Storageの勉強にもなりそうなので...(ただ、重くなるんだろうなぁ...)
今回、色んな方の資料を参考にさせてもらったのですが、RedHat時代のYuryuさんの資料もあり、「こんな昔にCephやってたのかぁ」とびっくりしました。個人的に尊敬している人の一人で、「Linux Kernel Updates」の時からお世話になってます。
最後の性能面の結果が「?」という部分がありますが...まぁ性能を考えるならラズパイ使わないですし、元々機能としてCSIが使いたかったので、結果は満足しています。これでやっと、永続ストレージを使うpodでhostPathとはおさらばして冗長化ができます。