Kubernetes使用StorageClass動態生成NFS類型的PV


最近幾天在測試StatefulSet的使用時,遇到了接觸Kubernetes以來最大的一個困難,即配置StorageClass動態生成PersistentVolume。考慮到NFS存儲操作相對簡潔,因此在剛接觸StorageClass的情況下選擇了NFS作為Provisioner,沒想到卻是一段噩夢的開始。。。前前后后花費了將近一個星期的時間,才初步實現了PV的動態創建,並完成了一個簡單的StatefulSet的案例。現在將我踩過的坑記錄如下:

 

一、自己配置NFS系統

主要參考了下面的這篇文章:

http://www.showerlee.com/archives/2280

注意,文章中配置NFS共享目錄的"# echo -e "/srv/pv-demo    kube-master(rw,sync)" > /etc/export"應為"/etc/exports"。

完成配置后,可以參考官方文檔編寫yaml文件:

https://github.com/kubernetes-incubator/external-storage/tree/master/nfs/docs/demo

最后一直沒有成功,花費了好多天調試都只能實現數據的本地掛載,無法跨機器遠程掛載,所以不詳細寫了。

二、使用已配置好的NFS系統

因為公司剛好有已經配置好的NFS系統,在自己搭建不成功的情況下就使用了現成的系統。仍然是主要參考官方文檔:

https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client

1.創建測試的靜態PV和PVC

首先,需要利用靜態的PV和PVC來測試一下NFS系統能否正常工作:

pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv1
spec:
  capacity:
    storage: 4Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: [已配置的NFS系統的路徑]
    server: [已配置的NFS系統的IP地址]

pvc.yaml

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mypvc1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi

創建二者后,如果能夠自動綁定,說明NFS系統工作正常,這樣才能執行下面的步驟。

2.運行nfs-client-provisioner

想要動態生成PV,需要運行一個NFS-Provisioner服務,將已配置好的NFS系統相關參數錄入,並向用戶提供創建PV的服務。官方推薦使用Deployment運行一個replica來實現,當然也可以使用Daemonset等其他方式,這些都在官方文檔中提供了。

在創建Deployment之前,一定要按照官方文檔中的Step 3部分配置相關的內容。

編寫rbac.yaml文件如下:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-provisioner
  apiGroup: rbac.authorization.k8s.io

 

編寫serviceaccount.yaml文件如下:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner

 

注意,針對已配置好的NFS系統和自己搭建NFS系統,Deployment中使用的鏡像不同!這里踩了一個大坑,在轉為使用現成系統后沒有修改原來的yaml文件中的鏡像,導致持續報錯,調試了好長時間才意識到問題。

編寫deployment.yaml文件如下:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nfs-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: example.com/nfs
            - name: NFS_SERVER
              value: [已配置的NFS系統的IP地址]
            - name: NFS_PATH
              value: [已配置的NFS系統的掛載路徑]
      volumes:
        - name: nfs-client-root
          nfs:
            server: [已配置的NFS系統的IP地址]
            path: [已配置的NFS系統的掛載路徑]

注意,官方文檔提供的鏡像在國內無法正常下載,在網上找到了一個阿里雲的鏡像作為替代。參考https://www.centos.bz/2018/04/%E5%AE%9E%E6%88%98kubernetes%E5%8A%A8%E6%80%81%E5%8D%B7%E5%AD%98%E5%82%A8nfs/

這個鏡像中volume的mountPath默認為/persistentvolumes,不能修改,否則運行時會報錯。

創建后觀察Pod能否正常運行。后面如果出現錯誤,可以用kubectl logs查看這個Pod的日志來查看錯誤,進行調試。

3.創建StorageClass

編寫並創建storageclass.yaml如下:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: nfs
provisioner: example.com/nfs

4.創建測試claim

接下來要創建測試的claim,以檢測StorageClass能否正常工作:

編寫並創建test-claim.yaml如下,注意storageClassName應確保與上面創建的StorageClass名稱一致。

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim1
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi
  storageClassName: nfs

創建后,用kubectl get pvc查看,觀察新創建的PVC能夠自動綁定PV。

5.創建測試Pod

創建一個測試的Pod使用這個PVC,編寫test-pod.yaml文件如下:

kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: busybox
    command:
      - "/bin/sh"
    args:
      - "-c"
      - "touch /mnt/SUCCESS && exit 0 || exit 1"
    volumeMounts:
      - name: nfs-pvc
        mountPath: "/mnt"
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim1

查看Pod狀態是否變為Completed。如果是,則應該能在NFS系統的共享路徑中看到一個SUCCESS文件。

這樣,StorageClass動態創建PV的功能就成功實現了。

6.創建StatefulSet案例

本來做StorageClass測試的目的就是為了實現StatefulSet,結果越做越跑偏。。。現在回到原本的目標,來實現一個簡單的StatefulSet。

編寫statefulset.yaml文件如下:

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx1"
  replicas: 2
  volumeClaimTemplates:
  - metadata:
      name: test
      annotations:
        volume.beta.kubernetes.io/storage-class: "nfs"
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
  template:
    metadata:
      labels:
        app: nginx1
    spec:
      serviceAccount: nfs-provisioner
      containers:
      - name: nginx1
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: "/persistentvolumes"
          name: test

注意,這里的mountPath必須指定為/persistentvolumes,否則會出現表面上PV創建成功,其實在NFS系統中找不到的問題。。。

當發現兩個Pod都正常運行,且在NFS系統中能夠找到PV,說明試驗成功。

進一步的,可以用kubectl exec -it 進入Pod,並創建一個文件,看看在PV中能否發現相同的文件已生成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM