天天看點

k8s(十一)、分布式存儲Cephfs使用

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的方式暴露服務,可檢視此前文章,這裡不再贅述):

k8s(十一)、分布式存儲Cephfs使用

到這裡,檔案系統挂載已經測試完畢,但選用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首頁:

k8s(十一)、分布式存儲Cephfs使用

結論:

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項