1. 在Ceph上為Kubernetes建立一個檔案系統
# ceph osd pool create cephfs_data 128
# ceph osd pool create cephfs_metadata 128
# ceph fs new cephfs cephfs_metadata cephfs_data
2. CephFS配置Quotas
CephFS的mount方式分為核心态mount和使用者态mount,核心态使用mount指令挂載,使用者态使用ceph-fuse。核心态隻有在kernel 4.17 + Ceph mimic以上的版本才支援Quotas,使用者态則沒有限制。
核心态mount:
# mount -t ceph 10.32.3.70:/k8s_test /mnt/cephfs/ -o name=admin,secret=AQCs2Q9bqAjCHRAAlQUF+hAiXhbErk4NdtvORQ==
使用者态mount:
# ceph-fuse -r /k8s_test /mnt/cephfs/ --name client.admin
配置quota:
1) 首先在CephFS建立一個要限額的目錄
# mkdir /mnt/cephfs
# ceph-fuse /mnt/cephfs
# mkdir /mnt/cephfs/k8s_test
2) 然後在目錄上使用setfattr設定限額屬性
# setfattr -n ceph.quota.max_bytes -v 100000000 /mnt/cephfs/k8s_test
比如上面這條指令限制/k8s_test目錄隻能使用100MB大小的空間。
3) 挂載限額目錄并測試
# mkdir /mnt/k8s_test
# ceph-fuse -r /k8s_test /mnt/k8s_test/ --name client.admin --client-quota
由于使用的核心和Ceph版本比較低,隻能在使用者态測試。在Jewel及之前版本的ceph-fuse,挂載時要指定--client-quota參數,限額才會生效。而在Luminous之後的版本,則不支援這個參數了,會自動識别quota。由于我這裡使用的是Jewel版本,是以指定了--client-quota參數。然後寫入200MB資料測試一下:
# cd /mnt/k8s_test
# dd if=/dev/zero of=test1.bin bs=1M count=200
dd: error writing ‘test1.bin’: Disk quota exceeded
129+0 records in
128+0 records out
134348800 bytes (134 MB) copied, 0.428233 s, 314 MB/s
# df -h
Filesystem Size Used Avail Use% Mounted on
ceph-fuse 92M -64Y -36M 100% /mnt/cephfs
可以看到中途提示超出配額,但是寫入了134MB資料,超過了指定的配額100MB。這是因為CephFS的Quotas不是嚴格的,按官方說法判斷檢測周期是10s。
再次寫入資料,可以發現完全寫不進去了:
# dd if=/dev/zero of=test2.bin bs=1M count=200
dd: error writing ‘test2.bin’: Disk quota exceeded
1+0 records in
0+0 records out
0 bytes (0 B) copied, 0.00162182 s, 0.0 kB/s
3. 更新k8s使用者權限
# ceph auth caps client.k8s mon 'allow rwx' osd 'allow rwx pool=k8s, allow rw pool=cephfs_data' mds 'allow rwp'
如果還沒有建立k8s使用者,則使用下面的指令建立:
# ceph auth get-or-create client.k8s mon 'allow rwx' osd 'allow rwx pool=k8s, allow rw pool=cephfs_data' mds 'allow rwp' -o ceph.client.k8s.keyring
在Kubernets中建立通路Ceph的Secret的步驟見
《Kubernetes配置Ceph RBD StorageClasses作為Persistent Volumes Claims後端》第3~5步。
4. Kubernetes Volume使用CephFS
Kubernetes Volume原生支援CephFS類型,使用方法:
# echo ‘apiVersion: v1
kind: Pod
metadata:
name: nginx-test-cephfs
spec:
containers:
- name: nginx-test-cephfs
image: registry.exmaple.com/base/nginx:v1.0
volumeMounts:
- name: cephfs
mountPath: "/data/"
volumes:
- name: cephfs
cephfs:
monitors:
- 10.32.3.70:6789
- 10.32.3.71:6789
- 10.32.3.72:6789
path: /k8s_test
user: k8s
secretRef:
name: ceph-k8s-secret
readOnly: false’ | kubectl create -f -
進入容器檢視:
# kubectl exec nginx-test-cephfs -it -- /bin/bash
[root@nginx-test-cephfs ~]# df -h
Filesystem Size Used Avail Use% Mounted on
10.32.3.70:6789,10.32.3.71:6789,10.32.3.72:6789:/k8s_test
5.2T 1.1G 5.2T 1% /data
5. Kubernetes Persistent Volume使用CephFS
Kubernetes Persistent Volume原生支援CephFS類型,使用方法:
# echo 'apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-test-cephfs-pv-01
namespace: test
spec:
capacity:
storage: 100Mi
accessModes:
- ReadWriteMany
cephfs:
monitors:
- 10.32.3.70:6789
- 10.32.3.71:6789
- 10.32.3.72:6789
path: /k8s_test
user: k8s
secretRef:
name: ceph-k8s-secret
readOnly: false
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-test-cephfs-pvc-01
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Mi
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-test-cephfs-01
spec:
containers:
- name: nginx-test-cephfs
image: registry.exmaple.com/base/nginx:v1.0
volumeMounts:
- name: cephfs-vol1
mountPath: "/data/"
volumes:
- name: cephfs-vol1
persistentVolumeClaim:
claimName: nginx-test-cephfs-pvc-01' | kubectl create -f -
# kubectl exec nginx-test-cephfs -it -- /bin/bash
[root@nginx-test-cephfs ~]# df -h
Filesystem Size Used Avail Use% Mounted on
10.32.3.70:6789,10.32.3.71:6789,10.32.3.72:6789:/k8s_test
5.2T 1.1G 5.2T 1% /data
6. Kubernetes StorageClass使用CephFS
Kubernetes StorageClass原生不支援CephFS,但是在社群的孵化項目
External Storage中添加了CephFS類型的StorageClass。External Storage是對核心的Kubernetes controller manager的擴充,其中包含的每個external provisioner可以獨立部署以支援擴充的StorageClass類型。
部署CephFS external provisioner:
1) 下載下傳External Storage代碼
# go get github.com/kubernetes-incubator/external-storage
同時要保證CephFS external provisioner依賴的package源碼存在于$GOPATH/src目錄下,如果有缺失,後面編譯會報錯,按照報錯使用go get下載下傳就行。
2) 編譯、打包鏡像、上傳鏡像
進入CephFS external provisioner的源碼目錄:
# cd $GOPATH/src/github.com/kubernetes-incubator/external-storage/ceph/cephfs
修改Makefile,将REGISTRY變量改成自己的鏡像倉庫位址,注意結尾要帶/:
# vim Makefile
ifeq ($(REGISTRY),)
REGISTRY = registry.example.com/
endif
修改Dockerfile,指定CEPH_VERSION與自己Ceph Cluster的版本一緻:
# vim Dockerfile
ENV CEPH_VERSION "mimic"
編譯,生成cephfs-provisioner二進制檔案:
# make
打包docker鏡像,并上傳到鏡像倉庫:
# make push
3) 部署CephFS external provisioner
進入部署目錄:
# cd $GOPATH/src/github.com/kubernetes-incubator/external-storage/ceph/cephfs/deploy
修改鏡像位址:
# vim rbac/deployment.yaml
image: "registry.example.com/cephfs-provisioner:latest"
修改希望部署到的namespace:
# NAMESPACE=kube-system
# sed -r -i "s/namespace: [^ ]+/namespace: $NAMESPACE/g" ./rbac/*.yaml
部署:
# kubectl -n $NAMESPACE apply -f ./rbac
4) 建立cephfs StorageClass
# echo ‘apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: cephfs
provisioner: ceph.com/cephfs
parameters:
monitors: 10.32.3.70:6789,10.32.3.71:6789,10.32.3.72:6789
adminId: k8s
adminSecretName: ceph-k8s-secret
adminSecretNamespace: kube-system‘ | kubectl create -f -
5) 建立一個PersistentVolumeClaim
# echo ‘apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-test-cephfs-pvc-03
annotations:
volume.beta.kubernetes.io/storage-class: "cephfs"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Mi’ | kubectl create -f -
6) 建立使用PVC的Pod
# echo ‘apiVersion: v1
kind: Pod
metadata:
name: nginx-test-cephfs-03
spec:
containers:
- name: nginx-test-cephfs-03
image: registry.example.com/base/nginx:v1.0
volumeMounts:
- name: pvc
mountPath: "/data/"
volumes:
- name: pvc
persistentVolumeClaim:
claimName: nginx-test-cephfs-pvc-03’ | kubectl create -f -
7) 檢視容器狀态
# kubectl exec nginx-test-cephfs-03 -it -- /bin/bash
# df -h
Filesystem Size Used Avail Use% Mounted on
10.32.3.70:6789,10.32.3.71:6789,10.32.3.72:6789:/volumes/kubernetes/kubernetes-dynamic-pvc-6bfb0ff3-6980-11e8-aa58-5a90b87a7c36
5.2T 1.1G 5.2T 1% /data
7. 為CephFS StorageClass添加Quotas支援
注意容器中CephFS的挂載方式,使用的是核心态mount,挂載目錄的容量并不是PVC聲明的100MiB,而是整個CephFS的可用大小。
檢視源碼發現在Kubernetes 1.10之後的版本才會嘗試使用者态mount。而且目前使用的Kubernetes 1.10.4版本存在bug,ceph-fuse挂載時指定了-k參數,卻沒有指定-i或者-n參數,導緻嘗試使用ceph-fuse挂載會報錯,最終後還是回退到核心态挂載。
另外目前CephFS external provisioner中建立目錄時,并沒有指定ceph.quota.max_bytes屬性,為了添加配額限制,需要修改代碼。
1) 修改CephFS external provisioner
CephFS external provisioner的結構比較簡單,主要就是cephfs-provisioner.go和cephfs_provisioner.py兩個檔案。cephfs-provisioner.go是主程式,建立CephFS Provisioner。cephfs_provisioner.py 是對ceph_volume_client.CephFSVolumeClient的封裝,友善調用。
修改思路就是在CephFS中建立目錄時指定size參數,底層的
CephFSVolumeClient.create_volume()判斷size存在時會調用setattr設定ceph.quota.max_bytes屬性。
具體修改内容可以參考
這個PR。修改完後,重新執行第6步中的打包部署操作使之生效。
2) 修改Kubelet
由于1.10.4版本的kubelet存在bug,使用ceph-fuse挂載目錄時指定了-k參數卻沒有指定-i或者-n參數,導緻挂載報錯。需要修改代碼,加上-i參數。具體位置是kubernetes/pkg/volume/cephfs/cephfs.go的execFuseMount()函數,原來的mount參數:
func (cephfsMounter *cephfsMounter) checkFuseMount() bool {
…
mountArgs := []string{}
mountArgs = append(mountArgs, "-k")
mountArgs = append(mountArgs, keyring_file)
mountArgs = append(mountArgs, "-m")
mountArgs = append(mountArgs, src)
mountArgs = append(mountArgs, mountpoint)
mountArgs = append(mountArgs, "-r")
mountArgs = append(mountArgs, cephfsVolume.path)
…
}
追加兩行:
mountArgs = append(mountArgs, "--id")
mountArgs = append(mountArgs, cephfsVolume.id)
如果使用的ceph-fuse版本低于Luminous,還要加上--client-quota參數:
mountArgs = append(mountArgs, "--client-quota")
然後重新編譯kubelet,替換安裝檔案,重新開機服務生效。編譯方法參考
《編譯Kubelet二進制檔案》。
3) 驗證Quota
重新使用第6步的配置建立一個Pod,進入容器檢視:
# kubectl exec nginx-test-cephfs-03 -it -- /bin/bash
root@nginx-test-cephfs-03:/# df -h
Filesystem Size Used Avail Use% Mounted on
ceph-fuse 100M 0 100M 0% /data
看到挂載方式是ceph-fuse,目錄可用大小也是quota配置的100M。寫入資料測試一下:
# dd if=/dev/zero of=/data/test.bin bs=1M count=200
dd: error writing '/data/test.bin': Disk quota exceeded
123+0 records in
122+0 records out
128421888 bytes (128 MB, 122 MiB) copied, 4.32033 s, 29.7 MB/s
# df -h
Filesystem Size Used Avail Use% Mounted on
ceph-fuse 100M 100M 0 100% /data
Quota确實生效了。
參考資料
CephFS Admin Tips – Create a new user and share kubernetes筆記: Cephfs