2020.1.5更新
建議使用cephfs storageClass,而非本文中手動指定pv/pvc的方式,否則容易引發cephfs性能問題,詳情參考:
kubernetes挂載cephfs帶來的mds卡頓問題及引入cephfs storageClass
本文僅作對pv/pvc的了解學習。
前言
在前篇部署測試完cephfs的基礎上:
Ceph叢集生産環境安裝部署
cephfs調優 & 性能測試 & 常用指令
本篇介紹k8s使用 pv/pvc的方式使用cephfs分布式檔案系統
使用
首先解釋一下pv/pvc的相關概念:
PV:
PersistentVolumes,是k8s抽象化的存儲資源,主要包括存儲能力、通路模式、存儲類型、回收政策等關鍵資訊.PV是k8s實際對接存儲後端的真正入口
[Access Mode] (Access模式):
ReadWriteOnce(RWO):讀寫權限,但是隻能被單個節點挂載
ReadOnlyMany(ROX):隻讀權限,可以被多個節點挂載
ReadWriteMany(RWX):讀寫權限,可以被多個節點挂載
[persistentVolumeReclaimPolicy](回收政策:
Retain(保留)- 保留資料,不會再配置設定給pvc,需要管理者手工清理資料
Recycle(回收)- 清除 PV 中的資料,保留pv資源,可以留供其他pvc使用
Delete(删除)- 删除整個pv資源及内部的資料。
PVC:
PersistentVolumeClaims,是對PV資源的一種聲明,pvc綁定實體資源pv後,pod通過綁定pvc來使用pv資源.PVC是k8s的一種抽象化的聲明式綁定存儲資源的管理模式的中間層,pod無法直接通過pv使用存儲資源,必須經過pvc,而pvc必須要綁定pv實體後,才可被pod使用.
依賴安裝:
每個node需要安裝ceph-common包,才能正常使用cephfs:
yum -y install ceph-common
建立secret:
在建立pv前,由于ceph是開啟了cephx認證的,于是首先需要建立secret資源,k8s的secret資源采用的是base64加密
在ceph monitor上提取key:
# ceph auth get-key client.admin |base64
QVFCL3E1ZGIvWFdxS1JBQTUyV0ZCUkxldnRjQzNidTFHZXlVYnc9PQ==
# cat ceph-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
data:
key: QVFCL3E1ZGIvWFdxS1JBQTUyV0ZCUkxldnRjQzNidTFHZXlVYnc9PQ==
~/ceph# kubectl apply -f ceph-secret.yaml
建立測試pv:
# cat cephfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: cephfs-pv
labels:
pv: cephfs-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
cephfs:
monitors:
- 192.168.20.112:6789
- 192.168.20.113:6789
- 192.168.20.114:6789
user: admin
secretRef:
name: ceph-secret
readOnly: false
persistentVolumeReclaimPolicy: Delete
檢視:
# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
cephfs-pv 1Gi RWX Delete Available 6s
現在pvc是空閑Available狀态
建立測試pvc:
# cat cephfs-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: cephfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
selector:
matchLabels:
pv: cephfs-pv
檢視:
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
cephfs-pvc Bound cephfs-pv 1Gi RWX 24s
# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
cephfs-pv 1Gi RWX Delete Bound default/cephfs-pvc 8m
可以看到pv和pvc都已經自動變為Bound狀态,但是我們這裡沒有使用任何關聯标簽,使它們兩者進行關聯,pvc是怎麼自動綁定到pv的呢?其實pvc在建立伊始就會主動去尋找符合requets條件的pv資源,如果尋找到了,便會自動進行綁定,無需做标簽比對.
小Tips:
1.當pv的容量大于pvc的需求時,pvc可以成功自動綁定pv;
2.當pv的容量小于pvc的需求時,pvc無法綁定該pv;
3.pv和pvc的綁定關系是一一對應的.
4.pv/pvc的建立順序是:pv -> pvc -> pod
5.pv/pvc的銷毀順序是:pod -> pvc -> pv,順序一定不要錯
例如:
2G的pv可以被1G的pvc綁定,并且綁定成功後,pvc的實際空間也是2G而不是1G;
1G的pv無法被2G的pvc綁定
建立pod執行個體
将pod排程到某一個node上,挂載pvc
[email protected]:~/ceph# cat testpod1-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: testpod1
name: testpod1
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: testpod1
template:
metadata:
labels:
app: testpod1
spec:
containers:
- args:
- /bin/bash
- -c
- /run.sh
image: nginx
imagePullPolicy: Always
name: testpod1
ports:
- containerPort: 80
protocol: TCP
terminationMessagePath: /dev/termination-log
volumeMounts:
- mountPath: /var/www
name: cephfs-testpod1
dnsPolicy: ClusterFirst
nodeSelector:
DEVNODE: ""
restartPolicy: Always
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: cephfs-testpod1
persistentVolumeClaim:
claimName: cephfs-pvc
檢視pod:
~# kubectl get pods | grep testpod1
testpod1-7847858587-2rbsq 1/1 Running 0 10s
進入pod并給nginx添加一個首頁index.html:
~# kubectl exec -it testpod1-7847858587-2rbsq bash
~# echo "Just for pv/pvc test" > /var/www/index.html
擷取pod ip打開浏覽器測試:
(本篇測試場景外部與叢集内部網段路由都已互通,如果pod内部路由未通,需要使用svc的方式暴露服務,可檢視此前文章,這裡不再贅述):
到這裡,檔案系統挂載已經測試完畢,但選用cephfs作k8s分布式檔案系統的最大優勢是因為其支援ReadWriteMany多節點挂載的靈活性,非常符合k8s像管理牲口一樣管理你的容器的理念,下面開始跨節點測試
跨節點測試
再建立一個部署檔案,讓其在另外的node上運作,與上方pod共用一個pvc:
~/ceph# cat testpod2-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: testpod2
name: testpod2
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: testpod2
template:
metadata:
labels:
app: testpod2
spec:
containers:
- args:
- /bin/bash
- -c
- /run.sh
image: registry.youkeshu.com:5000/nginx:php7.1v1
imagePullPolicy: Always
name: testpod2
ports:
- containerPort: 80
protocol: TCP
terminationMessagePath: /dev/termination-log
volumeMounts:
- mountPath: /var/www
name: cephfs-testpod2
dnsPolicy: ClusterFirst
nodeSelector:
PRODNODE: ""
restartPolicy: Always
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: cephfs-testpod2
persistentVolumeClaim:
claimName: cephfs-pvc
檢視pod:
~/ceph# kubectl get pods -o wide | grep testpod
testpod1-7847858587-2rbsq 1/1 Running 0 17m 172.26.2.172 h009029
testpod2-6d4b8d5db9-wkpx6 1/1 Running 0 9s 172.26.0.52 h009028
浏覽器打開testpod2首頁:
結論:
cephfs可以很好的實作k8s多節點排程容器時對持久化檔案的挂載支援
注意
以上方式使用時,會将容器内的指定路徑直接挂載到cephfs的根目錄下,前往上篇文章中挂載mount cephfs的節點挂載目錄就可以發現此問題:
[[email protected] cephfs]# ls
index.html testfile
[[email protected] cephfs]# cat index.html
Just for pv/pvc test
如果所有的檔案都這樣直接放在整個cephfs檔案系統的根目錄裡,無疑是極不好管理的,這個時候我們可以在 Pod 中使用一個新的屬性: subPath,該屬性可以來解決這個問題,我們隻需要更改上面的 Pod 的 YAML 檔案即可
修改後的yaml檔案:
[email protected]:~/ceph# cat testpod1-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: testpod1
name: testpod1
namespace: default
selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/amazondev
spec:
replicas: 1
selector:
matchLabels:
app: testpod1
template:
metadata:
labels:
app: testpod1
spec:
containers:
- args:
- /bin/bash
- -c
- /run.sh
image: registry.youkeshu.com:5000/nginx:php7.1v1
imagePullPolicy: Always
name: testpod1
ports:
- containerPort: 80
protocol: TCP
terminationMessagePath: /dev/termination-log
volumeMounts:
- mountPath: /var/www
name: cephfs-testpod1
# 僅添加這一行即可
subPath: testpod1
dnsPolicy: ClusterFirst
nodeSelector:
DEVNODE: ""
restartPolicy: Always
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: cephfs-testpod1
persistentVolumeClaim:
claimName: cephfs-pvc
重新部署後,再回到挂載點檢視:
[[email protected] cephfs]# ls
index.html testfile testpod1
[[email protected] cephfs]# ls testpod1/
[[email protected] cephfs]#
[[email protected] cephfs]# ll testpod1/
total 0
可以看到,這裡建立了一個subPath名的目錄,但是目錄裡面是空的,也即是說,通過k8s的抽象層pvc,容器對cephfs的根目錄擁有了指定容量的使用權限,subPath僅僅是在cephfs根目錄下建立了一個子目錄,無論是否建立子目錄,容器對cephfs的根目錄都擁有使用權限,是以,為了避免多個容器同名檔案沖突,便于管理維護,請在實際使用中一定不要忘記在部署檔案中添加subPath項