はじめに
前回「kubesprayで構築したk8s環境にTopoLVMを使用してRook Cephのブロックストレージを構築する」作成したKubernetesベースのCephクラスタを別のKubernetesクラスタから使ってみたいと思います。
環境を構築するにあたり、以下の記事には大変お世話になりました。ありがとうございます。
参考にした記事からは使用しているrookのバージョンが上がっていることでちょっとした躓きもあったため、参考になればと記事にしました。
参考「Rook-Ceph External Cluster ~Rook-Cephクラスター間でExternal Clusterを利用する~」
環境
Kubernetes: 1.18.6
Rook: 1.4
Ceph: v15.2.4
OS: Ubuntu20.04LTS
手順
用語から
-
Local Cluster
Cephストレージに接続したいクラスタを指す。Kubernetes / OpenShift クラスタの必要がある。 今回はKubernetesクラスタをCephストレージに接続します。
-
External Cluster
Ceph Mons、Mgr、OSD、およびMDSが実行されているクラスタ。
今回はKubernetesにRookで構築したCephクラスタを使用します。
要件
Local ClusterのクライアントがExternal Clusterに接続するための要件は次のとおりです。
- External Cluster側にLocal Clusterから接続可能な少なくとも1つのmon endpointが必要
- External Clusterを管理するためのAdmin Keyring情報
- Local ClusterからExternal Clusterのmons、mgr、osds、mdsへネットワーク接続できること
参考:Requirements
External Clusterの作成
ほとんど「kubesprayで構築したk8s環境にTopoLVMを使用してRook Cephのブロックストレージを構築する」の記事の通り作成すればよいですが、以下の要件を満たすために設定を一部変更する必要があり、作り直すことになりました。。。まあ仕方ないです。
「External Cluster側にLocal Clusterから接続可能な少なくとも1つのmon endpointが必要」
「Local ClusterからExternal Clusterのmons、mgr、osds、mdsへネットワーク接続できること」
修正ファイル(cluster-on-pvc.yaml)
変更が必要なファイルは、cluster-on-pvc.yamlです。
このファイルを修正してExternal ClusterのCephのネットワークにhostnetworkを使用することでLocal Cluster側からアクセスできるようにします。
以下の設定を追加しています。
network:
provider: host # rook 1.3からhost networkを使用したい場合このように記載する
このファイルを使って「kubesprayで構築したk8s環境にTopoLVMを使用してRook Cephのブロックストレージを構築する」の手順で構築すると、以下のようにhost networkでmonのポートが公開されます。
root@k8s-node1:~# ss -anp | grep ceph-mon | grep LISTEN
u_str LISTEN 0 5 /var/run/ceph/ceph-mon.b.asok 332537 * 0 users:(("ceph-mon",pid=88919,fd=7))
tcp LISTEN 0 512 192.168.123.181:3300 0.0.0.0:* users:(("ceph-mon",pid=88919,fd=27))
tcp LISTEN 0 512 192.168.123.181:6789 0.0.0.0:* users:(("ceph-mon",pid=88919,fd=28))
root@k8s-node1:~#
root@k8s-node2:~# ss -anp | grep ceph-mon | grep LISTEN
u_str LISTEN 0 5 /var/run/ceph/ceph-mon.c.asok 360856 * 0 users:(("ceph-mon",pid=100347,fd=7))
tcp LISTEN 0 512 192.168.123.182:3300 0.0.0.0:* users:(("ceph-mon",pid=100347,fd=27))
tcp LISTEN 0 512 192.168.123.182:6789 0.0.0.0:* users:(("ceph-mon",pid=100347,fd=28))
root@k8s-node2:~#
root@k8s-node3:~# ss -anp | grep ceph-mon | grep LISTEN
u_str LISTEN 0 5 /var/run/ceph/ceph-mon.a.asok 351210 * 0 users:(("ceph-mon",pid=87768,fd=7))
tcp LISTEN 0 512 192.168.123.183:3300 0.0.0.0:* users:(("ceph-mon",pid=87768,fd=27))
tcp LISTEN 0 512 192.168.123.183:6789 0.0.0.0:* users:(("ceph-mon",pid=87768,fd=28))
root@k8s-node3:~#
Local Clusterの作成
Rook Operatorの作成
まずは、Local ClusterのKubernetesクラスタのControl Planeから以下のコマンドを実行してRook Operatorを作成します。
git clone --single-branch --branch release-1.4 https://github.com/rook/rook.git
kubectl apply -f rook/cluster/examples/kubernetes/ceph/common.yaml
kubectl apply -f rook/cluster/examples/kubernetes/ceph/operator.yaml
kubectl apply -f rook/cluster/examples/kubernetes/ceph/common-external.yaml
External Clusterの接続に必要なリソースの作成
Rookを使用してExternal cluster(Cephクラスタ)に接続するためにConfigMapおよびSecretリソースを作成する必要があります。
import-external-cluster.sh というスクリプトが用意されており、これを実行することで一通り作成できます。
- NAMESPACE:configmapとsecret格納用の名前空間
- ROOK_EXTERNAL_FSID:External cluster(Cephクラスタ)のfsid。ceph fsidコマンドで取得
- ROOK_EXTERNAL_CEPH_MON_DATA:External cluster(Cephクラスタ)で実行中のmonのIPアドレスとそのポートのリスト
例:a=172.17.0.4:6789,b=172.17.0.5:6789,c=172.17.0.6:6789。
すべてのmonを指定する必要はなく、1つでも、Operatorが残りを検出します。 - ROOK_EXTERNAL_ADMIN_SECRET:オプション:External cluster(Cephクラスタ)のAdmin secret key。ceph auth get-key client.adminコマンドで取得
External Clusterで必要な値を取得
前述した値を、External Clusterで toolbox podを使用して取得します。
External Cluster側でtoolboxのコマンドを実行して値を取得
root@k8s-master:~# kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- ceph fsid
3619d955-c1a1-4a63-990b-1764be70930e
root@k8s-master:~#
root@k8s-master:~# kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- ceph auth get-key client.admin
AQBhpTZfvTujOBAA0t9rxUYSyNt5cBgz8rUBZQ==root@k8s-master:~#
root@k8s-master:~# kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- ceph mon stat
e3: 3 mons at {a=[v2:192.168.123.183:3300/0,v1:192.168.123.183:6789/0],b=[v2:192.168.123.181:3300/0,v1:192.168.123.181:6789/0],c=[v2:192.168.123.182:3300/0,v1:192.168.123.182:6789/0]}, election epoch 12, leader 0 a, quorum 0,1,2 a,b,c
root@k8s-master:~#
Local Clusterで実行(はまりポイント)
「External Clusterの接続に必要なリソースの作成」で記載したパラメタのみ設定してもCephクラスタに接続することができませんでした。
import-external-cluster.sh スクリプトのソースやLocal CLusterが出力するエラーメッセージ、スクリプトが登録するConfigMapやSecretの内容を見ながら悩みに悩んだ結果、スクリプトを修正することでようやくExternal Clusterに接続することができました。
失敗例
例えば、以下のように設定してシエルスクリプトを実行すると、エラーになります。
root@k8s-control:~# export NAMESPACE=rook-ceph-external
root@k8s-control:~# export ROOK_EXTERNAL_FSID=3619d955-c1a1-4a63-990b-1764be70930e
root@k8s-control:~# export ROOK_EXTERNAL_CEPH_MON_DATA=a=192.168.123.183:6789,b=192.168.123.181:6789,c=192.168.123.182:6789
root@k8s-control:~# export ROOK_EXTERNAL_ADMIN_SECRET=AQBhpTZfvTujOBAA0t9rxUYSyNt5cBgz8rUBZQ==
root@k8s-control:~# bash rook/cluster/examples/kubernetes/ceph/import-external-cluster.sh
secret/rook-ceph-mon created
configmap/rook-ceph-mon-endpoints created
secret/rook-csi-rbd-node created
secret/rook-csi-rbd-provisioner created
secret/rook-csi-cephfs-node created
secret/rook-csi-cephfs-provisioner created
root@k8s-control:~#
接続失敗です。
root@k8s-control:~# kubectl get cephcluster.ceph.rook.io -A
NAMESPACE NAME DATADIRHOSTPATH MONCOUNT AGE PHASE MESSAGE HEALTH
rook-ceph-external rook-ceph-external 32s Connecting Cluster is connecting
root@k8s-control:~#
オペレータには以下のログが出ます
root@k8s-control:~# kubectl logs -f rook-ceph-operator-58496b74f9-9jptz -n rook-ceph
:
2020-08-14 15:55:30.566520 E | cephclient: ceph username is empty
2020-08-14 15:55:30.577853 E | ceph-cluster-controller: failed to reconcile. failed to reconcile cluster "rook-ceph-external": failed to configure external ceph cluster: the cluster identity was not established
rook-ceph-monシークレットでROOK_EXTERNAL_ADMIN_SECRET指定時に作成される "ceph-secret"と"ceph-username"を削除したりもしてみましたが、以下のようなエラーになってアァーもうだめだーと投げそうになりました。
2020-08-14 17:22:24.115022 E | ceph-cluster-controller: failed to reconcile. failed to reconcile cluster "rook-ceph-external": failed to configure external ceph cluster: failed to create csi kubernetes secrets: failed to create kubernetes csi secret: failed to create kubernetes secret map["adminID":"csi-cephfs-node" "adminKey":"AQDDpTZfdDC+IhAAFuKaRQqu7EWy/4aGvJXA6A=="] for cluster "rook-ceph-external": failed to update secret for rook-csi-cephfs-node: Secret "rook-csi-cephfs-node" is invalid: type: Invalid value: "kubernetes.io/rook": field is immutable
悩んだ結果の解決策
「op-cluster: Failed to configure external ceph cluster #5732」ここに同じような事象があり、このコメントを参考に以下のようにすることで問題を回避?しました。とりあえずこの方法でうまく動いています。
rook/cluster/examples/kubernetes/ceph/import-external-cluster.shの修正箇所
(右が修正後です)
79,81c79,80
< --from-literal="$MON_SECRET_MON_KEYRING_KEYNAME"="$ROOK_EXTERNAL_MONITOR_SECRET" \
< --from-literal="$MON_SECRET_CEPH_USERNAME_KEYNAME"="$ROOK_EXTERNAL_USERNAME" \
< --from-literal="$MON_SECRET_CEPH_SECRET_KEYNAME"="$ROOK_EXTERNAL_USER_SECRET"
---
> --from-literal="$MON_SECRET_MON_KEYRING_KEYNAME"="$ROOK_EXTERNAL_MONITOR_SECRET"
>
140,143d138
< importCsiRBDNodeSecret
< importCsiRBDProvisionerSecret
< importCsiCephFSNodeSecret
< importCsiCephFSProvisionerSecret
シェルの実行
export NAMESPACE=rook-ceph-external
export ROOK_EXTERNAL_FSID=3619d955-c1a1-4a63-990b-1764be70930e
export ROOK_EXTERNAL_CEPH_MON_DATA=a=192.168.123.183:6789,b=192.168.123.181:6789,c=192.168.123.182:6789
export ROOK_EXTERNAL_ADMIN_SECRET=AQBhpTZfvTujOBAA0t9rxUYSyNt5cBgz8rUBZQ==
bash rook/cluster/examples/kubernetes/ceph/import-external-cluster.sh
繋がりました(ニッコリ
root@k8s-control:~# kubectl get cephcluster.ceph.rook.io -A
NAMESPACE NAME DATADIRHOSTPATH MONCOUNT AGE PHASE MESSAGE HEALTH
rook-ceph-external rook-ceph-external 9s Connected Cluster connected successfully HEALTH_OK
root@k8s-control:~#
動作確認
「(Rook-Ceph External Cluster ~Rook-Cephクラスター間でExternal Clusterを利用する~)[https://techstep.hatenablog.com/entry/2020/02/27/155621]」このサイトの「Local ClusterからExternal Clusterを利用する」をそのまま利用させていただきました。
この辺りはまだまだ勉強不足で書いてあることをそのまま実行しています。。。
CephBlockPoolの作成
cephblockpool.yaml
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: replicapool-external04
namespace: rook-ceph-external
spec:
failureDomain: host
replicated:
size: 1
root@k8s-control:~# kubectl apply -f cephblockpool.yaml
cephblockpool.ceph.rook.io/replicapool-external04 created
root@k8s-control:~#
StorageClassの作成
storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-ceph-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
clusterID: rook-ceph-external # local clusterのnamespaceに合わせる
pool: replicapool-external04 # cephblockpoolで指定したPool名に合わせる
imageFormat: "2"
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph-external
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph-external
csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph-external
csi.storage.k8s.io/fstype: ext4
allowVolumeExpansion: true
reclaimPolicy: Delete
root@k8s-control:~# kubectl apply -f storageclass.yaml
storageclass.storage.k8s.io/rook-ceph-block created
root@k8s-control:~#
root@k8s-control:~# kubectl get cephblockpool.ceph.rook.io -n rook-ceph-external
NAME AGE
replicapool-external04 83s
root@k8s-control:~# kubectl get sc -n rook-ceph-external
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
rook-ceph-block rook-ceph.rbd.csi.ceph.com Delete Immediate true 83s
root@k8s-control:~#
# External Cluster側で確認
root@k8s-master:~# kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- ceph osd pool ls
device_health_metrics
replicapool-external04 ★Poolが作成されている
root@k8s-master:~#
PersistentVolumeClaimsの作成
configmapを修正する
修正前
root@k8s-control:~# kubectl describe cm rook-ceph-csi-config -n rook-ceph
Name: rook-ceph-csi-config
Namespace: rook-ceph
Labels: <none>
Annotations: <none>
Data
====
csi-cluster-config-json:
----
[]
Events: <none>
root@k8s-control:~#
修正後
Dataのcsi-cluster-config-jsonの値を以下のように修正する(kubectl editコマンドで修正)。
root@k8s-control:~# kubectl describe cm rook-ceph-csi-config -n rook-ceph
Name: rook-ceph-csi-config
Namespace: rook-ceph
Labels: <none>
Annotations: <none>
Data
====
csi-cluster-config-json:
----
[{"clusterID":"rook-ceph-external","monitors":["192.168.123.183:6789","192.168.123.181:6789","192.168.123.182::6789"]}]
Events: <none>
root@k8s-control:~#
以下のファイルをデプロイします。
pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: rook-ceph-block
root@k8s-control:~# kubectl apply -f pvc.yaml
persistentvolumeclaim/rbd-pvc created
root@k8s-control:~# kubectl apply -f pvc.yaml
persistentvolumeclaim/rbd-pvc created
root@k8s-control:~#
root@k8s-control:~# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
rbd-pvc Bound pvc-ebcfe192-6868-42a3-a6ce-963be1e96c34 1Gi RWO rook-ceph-block 52s
root@k8s-control:~#
Podの作成
作成したpvcを使用するPodをデプロイします。
pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: csirbd-demo-pod
spec:
containers:
- name: web-server
image: nginx
volumeMounts:
- name: mypvc
mountPath: /var/lib/www/html
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: rbd-pvc
readOnly: false
root@k8s-control:~# kubectl apply -f pod.yaml
pod/csirbd-demo-pod created
root@k8s-control:~# kubectl get pod csirbd-demo-pod
NAME READY STATUS RESTARTS AGE
csirbd-demo-pod 1/1 Running 0 20s
root@k8s-control:~#
マウントされています
root@k8s-control:~# kubectl exec -it csirbd-demo-pod -- mount | grep /var/lib/www/html
/dev/rbd0 on /var/lib/www/html type ext4 (rw,relatime,stripe=16)
root@k8s-control:~#
まとめ
今回は予期せぬ動作に悩まされましたが、なんとか目的を達成することができました。
環境の構築は中の動きを理解する助けになるので今後も手を出していきたいです。
しかしながら調査の仕方もよくわからないのでエラーが出るとくじけそうになります。。。
がんばりたいです。
参考URL
Rook-Ceph External Cluster ~Rook-Cephクラスター間でExternal Clusterを利用する~
Cluster Settings
Network Configuration Settings
Rook and External Ceph Clusters
Ceph Cluster CRD