こんにちは
株式会社クラスアクト インフラストラクチャ事業部の大塚です。
この記事では前回作成したRook-Ceph上にCephFSを作成し、podのデータをCephFS上に置き、永続化してみたいと思います。
Rook-Cephの構築は以下をご覧ください。
用語
CephFS
個人的にはNFSと近しいイメージを持っています。
とりあえずは、そのようなイメージを持っておけば一旦良いのかなと思います。
「CephFS」は、分散ストレージシステム「Ceph」のストレージクラスタで使用される分散ファイルシステムです。
ストレージプール上の仮想的ファイルシステムを複数のサーバから同時にマウントしてアクセスできます。
分散ファイルシステム
DFS (分散ファイルシステム) は複数のファイルサーバーや複数の場所にまたがって存在するファイルシステムです。
どこにあるどのデバイスからでも、ローカルに保存されているのと同じようにファイルにアクセスすることができます。DFSは、ネットワーク上の許可されたユーザー間で、制御された方法で情報やファイルを共有するのに便利です。
環境イメージ
今回の環境構築イメージは以下となります。
前回構築したRook-Ceph環境にk8sのyamlファイルを使ってCephFSやStorageClass,PVCをデプロイしていきます。
構築
rook/deploy/examples配下を確認すると様々なyamlファイルがあります。この中のfilesystem.yamlというファイルを使用することでCephFSをデプロイすることができます。中身を見てみるとmyfsというcephFSが作成されることが分かります。このCephFSの名前だけではなくmetadata poolやdata poolを設定するような記述もyaml内にあるのですが、Ceph側の領域の話であるため、ここでは説明を省きます。
root@rancher:~# cd ~/rook/deploy/examples
root@rancher:~/rook/deploy/examples# ls
bucket-notification-endpoint.yaml common.yaml images.txt object-multisite.yaml rbdmirror.yaml
bucket-notification.yaml crds.yaml import-external-cluster.sh object-openshift.yaml README.md
bucket-topic.yaml create-external-cluster-resources.py monitoring object-test.yaml rgw-external.yaml
ceph-client.yaml create-external-cluster-resources.sh mysql.yaml object-user.yaml Rook-Ceph-NodePort.yaml
cluster-external-management.yaml csi nfs-test.yaml object.yaml storageclass-bucket-delete.yaml
cluster-external.yaml dashboard-external-https.yaml nfs.yaml operator-openshift.yaml storageclass-bucket-retain.yaml
cluster-on-local-pvc.yaml dashboard-external-http.yaml object-bucket-claim-delete.yaml operator.yaml subvolumegroup.yaml
cluster-on-pvc.yaml dashboard-ingress-https.yaml object-bucket-claim-notification.yaml osd-env-override.yaml toolbox-job.yaml
cluster-stretched-aws.yaml dashboard-loadbalancer.yaml object-bucket-claim-retain.yaml osd-purge.yaml toolbox.yaml
cluster-stretched.yaml direct-mount.yaml object-ec.yaml pool-device-health-metrics.yaml volume-replication-class.yaml
cluster-test.yaml filesystem-ec.yaml object-external.yaml pool-ec.yaml volume-replication.yaml
cluster.yaml filesystem-mirror.yaml object-multisite-pull-realm-test.yaml pool-mirrored.yaml wordpress.yaml
common-external.yaml filesystem-test.yaml object-multisite-pull-realm.yaml pool-test.yaml
common-second-cluster.yaml filesystem.yaml object-multisite-test.yaml pool.yaml
root@rancher:~/rook/deploy/examples# cat filesystem.yaml
中略
metadata:
name: myfs
namespace: rook-ceph # namespace:cluster
中略
デプロイをしていきます。
root@rancher:~/rook/deploy/examples# kubectl apply -f filesystem.yaml
cephfilesystem.ceph.rook.io/myfs created
デプロイが出来ているかどうかはtool-boxからも確認出来ますが、CephのWebコンソールからも確認することが出来ます。以下がその画面となります。CephFSだけではなくFS作成に必要なmetadata poolやdata poolも併せて作成されています。
次にStorageClassをデプロイしていきます。サンプルのyamlはrook/deploy/examples/csi/cephfs配下にあります。storageclass.yamlというファイルがそれになるのですが、このままだとreclaimPolicyがDeleteになり使い勝手が悪そうだったので、Retainに修正をしています。
root@rancher:~/rook/deploy/examples# cd csi/cephfs/
root@rancher:~/rook/deploy/examples/csi/cephfs# ls
kube-registry.yaml pod-ephemeral.yaml pod.yaml pvc-clone.yaml pvc-restore.yaml pvc.yaml snapshotclass.yaml snapshot.yaml storageclass-ec.yaml storageclass.yaml
root@rancher:~/rook/deploy/examples/csi/cephfs# cat 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 # driver:namespace:operator
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 # namespace:cluster
# 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 # namespace:cluster
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph # namespace:cluster
csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph # namespace:cluster
# (optional) The driver can use either ceph-fuse (fuse) or ceph kernel client (kernel)
# If omitted, default volume mounter will be used - this is determined by probing for ceph-fuse
# or by setting the default mounter explicitly via --volumemounter command-line argument.
# mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
# uncomment the following line for debugging
#- debug
root@rancher:~/rook/deploy/examples/csi/cephfs# cp -p storageclass.yaml storageclass.yaml.org
root@rancher:~/rook/deploy/examples/csi/cephfs# vi storageclass.yaml
root@rancher:~/rook/deploy/examples/csi/cephfs# diff storageclass.yaml storageclass.yaml.org
32c32
< reclaimPolicy: Retain
---
> reclaimPolicy: Delete
修正した後デプロイを行います。
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl apply -f storageclass.yaml
storageclass.storage.k8s.io/rook-cephfs created
次にPVCを作成していきます。pvc.yamlというyamlファイルも上記と同じディレクトリ上に存在しているはずです。このファイルは特に変更をかけずにデプロイします。
pvとpvcを確認するとboundステートになっているかと思います。
root@rancher:~/rook/deploy/examples/csi/cephfs# cat pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cephfs-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: rook-cephfs
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl apply -f pvc.yaml
persistentvolumeclaim/cephfs-pvc created
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-af074c12-5bba-4015-80e6-9c7f4fe033ed 1Gi RWO Retain Bound default/cephfs-pvc rook-cephfs 4s
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
cephfs-pvc Bound pvc-af074c12-5bba-4015-80e6-9c7f4fe033ed 1Gi RWO rook-cephfs 7s
次に、CephFS(ないしStorageClass,PVC)を使用するpodを作成していきます。podのサンプルyamlも同ディレクトリにあるかと思います。内容は特に変更せずにデプロイします。
root@rancher:~/rook/deploy/examples/csi/cephfs# cat pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: csicephfs-demo-pod
labels:
app: nginx
spec:
containers:
- name: web-server
image: nginx
volumeMounts:
- name: mypvc
mountPath: /var/lib/www/html
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: cephfs-pvc
readOnly: false
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl apply -f pod.yaml
pod/csicephfs-demo-pod created
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl get pod
NAME READY STATUS RESTARTS AGE
csicephfs-demo-pod 1/1 Running 0 8s
CephFS側にデータが保存されるか検証をしていきたいと思います。
デプロイしたpod内に入り、/var/lib/www/html配下にrok-ceph.htmlというファイルを作成します。
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl get pod
NAME READY STATUS RESTARTS AGE
csicephfs-demo-pod 1/1 Running 0 3m8s
wordpress-mysql-6b49db8c4c-tbgkw 0/1 Pending 0 22m
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl exec -it csicephfs-demo-pod -- /bin/bash
root@csicephfs-demo-pod:/# cd /var/lib/www/html
root@csicephfs-demo-pod:/var/lib/www/html# ls -ltr
total 0
root@csicephfs-demo-pod:/var/lib/www/html# vi rook-ceph.html
root@csicephfs-demo-pod:/var/lib/www/html# cat rook-ceph.html
Hello Rook-Ceph!!
このpodからexitして、replaceを行ってみます。replaceは内部でdeleteとreplaceが走るので、もしcreate後のpodの/var/lib/wwww/html配下にrook-ceph.htmlがあれば、pod内ではなくpod外、今回はCephFS内にデータが保存されていることが確認できます。
以下がreplaceの実行結果です。AGEの部分を見ていただくことでも、replaceが走って新しいpodがデプロイされていることがわかるかと思います、
root@csicephfs-demo-pod:/var/lib/www/html# exit
exit
command terminated with exit code 130
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl get pod
NAME READY STATUS RESTARTS AGE
csicephfs-demo-pod 1/1 Running 0 5m53s
wordpress-mysql-6b49db8c4c-tbgkw 0/1 Pending 0 35m
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl replace --force -f pod.yaml
pod "csicephfs-demo-pod" deleted
pod/csicephfs-demo-pod replaced
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl get pod
NAME READY STATUS RESTARTS AGE
csicephfs-demo-pod 1/1 Running 0 19s
wordpress-mysql-6b49db8c4c-tbgkw 0/1 Pending 0 35m
replace後のpodにexecします。
/var/lib/www/html配下にrook-ceph.htmlがあることからCephFS側にデータが保存されていることがわかりますね。
root@rancher:~/rook/deploy/examples/csi/cephfs# kubectl exec -it csicephfs-demo-pod -- /bin/bash
root@csicephfs-demo-pod:/# cd /var/lib/www/html
root@csicephfs-demo-pod:/var/lib/www/html# ls -ltr
total 1
-rwxrwxrwx 1 root root 18 Jun 17 03:00 rook-ceph.html
root@csicephfs-demo-pod:/var/lib/www/html# cat rook-ceph.html
Hello Rook-Ceph!!
イメージとしては以下のような形です。
podの/var/lib/www/html配下はCephFSにマウントしており、ここにファイルを作るとpodから作成したファイルは見えるけれど、実はpod側ではなくFS側にデータが作成されている、ということですね。