
我们之前使用 Ceph RBD 作为 Kubernetes集群的 PV,RBD 的访问模式(Access Mode)是 ReadWriteOnce(RWO), 即可读写且只可被一个 Node 节点挂载。CephFS 支持 ReadWriteMany(RWX) 访问模式,可读写,可以被多个节点挂载,主要用于 pod 之间共享数据的应用场景。
CephFS 可以通过手动指定的方式创建 PV/PVC ,手动的方式过于繁琐,所以推荐使用 storageClass 的方式动态的分配 PV,目前 kubernetes 内置的 provisioner 没有支持 CephFS,需要使用社区的 ceph-csi 。
Ceph CSI CephFS 安装
克隆仓库到本地,进入部署清单目录
git clone https://github.com/ceph/ceph-csi.git
cd ceph-csi/deploy/cephfs/kubernetes
修改 ConfigMap 对象配置,clusterID 是 ceph fsid 。
# vi csi-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
[
{
"clusterID": "bd241c5a-d012-11eb-8215-e977530c8b31",
"monitors": [
"172.16.x.x:6789",
"172.16.x.x:6789",
"172.16.x.x:6789"
]
}
]
metadata:
name: ceph-csi-config
namespace: kube-system
EOF
ceph-csi 默认部署在 default 命名空间,这里改到 kube-system 。
sed -i "s/namespace: default/namespace: kube-system/g" $(grep -rl "namespace: default" ./)
部署 ceph-csi CephFS ,镜像的仓库是 k8s.gcr.io , 网络有问题的需要更换仓库。
# kubectl -n kube-system create -f .
# kubectl get po -n kube-system | grep csi-cephfs
csi-cephfsplugin-8xt97 3/3 Running 0 6d10h
csi-cephfsplugin-bmxwr 3/3 Running 0 6d10h
csi-cephfsplugin-n74cd 3/3 Running 0 6d10h
csi-cephfsplugin-provisioner-79d84c9598-fb6bg 6/6 Running 0 6d10h
csi-cephfsplugin-provisioner-79d84c9598-g579j 6/6 Running 0 6d10h
csi-cephfsplugin-provisioner-79d84c9598-n8w2j 6/6 Running 0 6d10h
创建 CephFS storageClass
ceph-csi 需要 cephx 凭据才能与 Ceph 集群通信,这里使用的是 admin 用户。
# USER_KEY=$(ceph auth get-key client.admin)
# cat <<EOF > csi-cephfs-secret.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: csi-cephfs-secret
namespace: kube-system
stringData:
# Required for statically provisioned volumes
userID: admin
userKey: ${USER_KEY}
# Required for dynamically provisioned volumes
adminID: admin
adminKey: ${USER_KEY}
EOF
# kubectl create -f csi-cephfs-secret.yaml
创建 storageClass 对象,这里使用的 Ceph FS name 是 cephfs 。
# ceph fs ls
name: cephfs, metadata pool: cephfs.cephfs.meta, data pools: [cephfs.cephfs.data ]
# cat <<EOF > csi-cephfs-sc.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph-csi-cephfs
provisioner: cephfs.csi.ceph.com
parameters:
clusterID: bd241c5a-d012-11eb-8215-e977530c8b31
fsName: cephfs
csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secret
csi.storage.k8s.io/provisioner-secret-namespace: kube-system
csi.storage.k8s.io/controller-expand-secret-name: csi-cephfs-secret
csi.storage.k8s.io/controller-expand-secret-namespace: kube-system
csi.storage.k8s.io/node-stage-secret-name: csi-cephfs-secret
csi.storage.k8s.io/node-stage-secret-namespace: kube-system
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- discard
EOF
# kubectl create -f csi-cephfs-sc.yaml
创建测试的 PVC
cat <<EOF > cephfs-pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-cephfs-pvc
spec:
accessModes:
# - ReadWriteOnce
- ReadWriteMany
resources:
requests:
storage: 1Gi
storageClassName: ceph-csi-cephfs
EOF
# kubectl create -f cephfs-pvc.yaml
# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-0f36fd44-40f1-4ac3-aebe-0264a2fb50ea 1Gi RWX Delete Bound default/csi-cephfs-pvc ceph-csi-cephfs 6d11h
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
csi-cephfs-pvc Bound pvc-0f36fd44-40f1-4ac3-aebe-0264a2fb50ea 1Gi RWX ceph-csi-cephfs 6d11h
创建测试的 Deployment
# cat <<EOF > cephfs-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: cephfs-test
labels:
component: cephfs-test
spec:
replicas: 2
strategy:
type: Recreate
selector:
matchLabels:
component: cephfs-test
template:
metadata:
labels:
component: cephfs-test
spec:
containers:
- name: nginx
image: docker.io/library/nginx:1.21.1-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- name: config
mountPath: "/data"
volumes:
- name: config
persistentVolumeClaim:
claimName: csi-cephfs-pvc
readOnly: false
EOF
# kubectl create -f cephfs-test.yaml
进入其中一个 pod
# kubectl exec -it cephfs-test-c54fc4b68-ct6gx -- sh
/ # df -h | grep data
172.16.0.61:6789,172.16.0.62:6789,172.16.0.63:6789:/volumes/csi/csi-vol-056e44c5-eddf-11eb-a990-a63fe71a40b6/e423daf3-017b-4a7e-8713-bd05bab695ee 1.0G 0 1.0G 0% /data
/ # cd /data/
/data # echo 11111 >test.log
/data # cat test.log
11111
/data #
进入另一个 pod
# kubectl exec -it cephfs-test-c54fc4b68-w8f4q -- sh
/ # cd /data/
/data # cat test.log
11111
/data # echo 22222 >>test.log
/data # cat test.log
11111
22222
CephFS 快照
CephFS 的快照实际上就是创建一个文件夹,由系统自动把文件复制到快照目录,这个复制过程是秒级别的。
开启快照
# ceph fs set cephfs allow_new_snaps 1
挂载 CephFS 到当前主机
# USER_KEY=$(ceph auth get-key client.admin)
# mkdir /mnt/cephfs-test
# mount -t ceph k8s01:6789,k8s02:6789,k8s03:6789:/ /mnt/cephfs-test -o name=admin,secret=$USER_KEY
创建快照目录
# cd /mnt/cephfs-test/
root@k8s01:/mnt/cephfs-test# mkdir .snap/snapshot_2021-08-02
root@k8s01:/mnt/cephfs-test# ls -lrt .snap/
total 0
drwxr-xr-x 3 root root 1 Jul 26 14:55 snapshot_2021-08-02
drwxr-xr-x 3 root root 1 Jul 26 14:55 snapshot_2021-07-26
恢复快照,只需要把快照的目录或文件拷贝到相对应的目录即可
# cp -af .snap/snapshot_2021-08-02/* ./
删除快照
# rmdir .snap/snapshot_2021-08-02
另外,csi-cephfs 默认会创建一个名为 csi 的子文件系统
# ceph fs subvolumegroup ls cephfs
[
{
"name": "_deleting"
},
{
"name": "csi"
}
]
所有使用 csi-cephfs 创建的 PV ,都是在子文件系统 csi 的目录下
# kubectl get pv | grep default/csi-cephfs-pvc
pvc-0f36fd44-40f1-4ac3-aebe-0264a2fb50ea 1Gi RWX Delete Bound default/csi-cephfs-pvc ceph-csi-cephfs 6d11h
# kubectl describe pv pvc-0f36fd44-40f1-4ac3-aebe-0264a2fb50ea | egrep 'subvolumeName|subvolumePath'
subvolumeName=csi-vol-056e44c5-eddf-11eb-a990-a63fe71a40b6
subvolumePath=/volumes/csi/csi-vol-056e44c5-eddf-11eb-a990-a63fe71a40b6/e423daf3-017b-4a7e-8713-bd05bab695ee
# cd /mnt/cephfs-test/
# tree -L 4 ./
./
└── volumes
├── csi
│ ├── csi-vol-056e44c5-eddf-11eb-a990-a63fe71a40b6
│ │ └── e423daf3-017b-4a7e-8713-bd05bab695ee
│ └── csi-vol-1ac1f4c1-ef8a-11eb-a990-a63fe71a40b6
│ └── 3773a567-a8cb-4bae-9181-38f4e3065436
├── _csi:csi-vol-056e44c5-eddf-11eb-a990-a63fe71a40b6.meta
├── _csi:csi-vol-1ac1f4c1-ef8a-11eb-a990-a63fe71a40b6.meta
└── _deleting
7 directories, 2 files




