k8s~動態生成pvc和pv

有時,我們不想手動建立pv和pvc,這時,我們可以通過strongClass存儲類來幫我們實現,動態建立pvc,並動態爲它分配pv存儲空間,我們以nfs爲例,說一下動態分配在nfs存儲截至上建立pv的方式。

本文導讀

  • StorageClass和PVC及PV
  • 集羣權限與綁定rbac.yaml
  • 建立動態pvc的provisioner.yaml
  • 建立strongClass的strongclass.yaml
  • 在有狀態服務StatefulSet中使用strongClass
  • 遇到的問題與解決

StorageClass和PVC及PV

當使用StorageClass創建PersistentVolumeClaim(PVC)時,它們之間的關係可以用以下文字圖示表示:

           +------------------+
           |   StorageClass   |
           +------------------+
                     |
                     |  +------------------+
                     |  |       PVC        |
                     |  +------------------+
                     |         |
                     |         |
                     |  +------------------+
                     |  |        PV        |
                     |  +------------------+

在這個圖示中:

  • StorageClass是用於定義動態卷分配的規則和配置的對象。
  • PVC是用來請求存儲資源的聲明,它指定了所需的存儲容量、訪問模式等。
  • PV是實際的持久化存儲資源,它是由集羣管理員預先創建並配置好的。

當一個PVC被創建時,它會根據所指定的StorageClass進行動態分配,並綁定到一個可用的PV上。這樣,PVC就可以通過PV來獲取所需的存儲資源。PVC和PV之間的綁定關係是自動完成的,不需要用戶手動干預。

集羣權限與綁定rbac.yaml

首先,你要在k8s中添加pvc,pv這些資源,你需要有自己的sa(service account),然後把你的pod(建立pvc和pv)去分配這個有權限的sa,這個pod就可以像人一樣,爲你在k8s中創建資源了。

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
  namespace: elk
---
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","create"]
   -  apiGroups: ["storage.k8s.io"]
      resources: ["storageclasses"]
      verbs: ["get", "list", "watch"]
   -  apiGroups: [""]
      resources: ["events"]
      verbs: ["list", "watch", "create", "update", "patch"]
   -  apiGroups: [""]
      resources: ["services", "endpoints"]
      verbs: ["get","create","list", "watch","update"]
   -  apiGroups: ["extensions"]
      resources: ["podsecuritypolicies"]
      resourceNames: ["nfs-provisioner"]
      verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io

在Kubernetes中,ClusterRole和ClusterRoleBinding都是一種用於定義集羣級別權限的資源,它與特定的命名空間無關。因此,在創建ClusterRole時,不需要爲它指定namespace。
ClusterRole的權限範圍覆蓋整個集羣,可以被任何命名空間中的對象引用和使用。這使得ClusterRole能夠控制跨多個命名空間的資源和操作。

建立動態pvc的provisioner.yaml

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
  namespace: elk
  labels:
    app: nfs-client-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-client-provisioner
          image: easzlab/nfs-subdir-external-provisioner:v4.0.1 #quay.io/external_storage/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: nfs-provisioner # 指定分配器的名稱,創建storageclass會用到
            - name: NFS_SERVER
              value: 192.168.1.x
            - name: NFS_PATH
              value: /mnt/disk/nfs_data #這個nfs服務器上的目錄
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.1.x
            path: /mnt/disk/nfs_data #這個nfs服務器上的目錄

建立strongClass的strongclass.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: elk-nfs
provisioner: nfs-provisioner # 必須與provisioner.yaml中PROVISIONER_NAME的值一致
parameters:
  archiveOnDelete: "true"  # 刪除pv的時候,pv的內容是否要備份
allowVolumeExpansion: true  #如果對PVC擴容,則其對應的"storage class"中allowVolumeExpansion字段需要設置成true

在Kubernetes中,建立StorageClass時不需要指定命名空間(namespace)。StorageClass是一種用於定義持久卷的存儲類別的資源,它是集羣級別的。

在有狀態服務StatefulSet中使用strongClass

在Kubernetes中,StatefulSet是一種用於管理有狀態應用的控制器。它可以確保Pod按照指定的順序和唯一標識符進行創建、更新和刪除。StatefulSet通常與PersistentVolumeClaim(PVC)一起使用,以爲每個Pod提供持久化存儲。

要動態創建PVC並將其綁定到StatefulSet的Pod上,你可以使用volumeClaimTemplates字段。這個字段允許你定義一個模板,用於創建PVC。

下面是一個示例StatefulSet配置文件,其中包含了volumeClaimTemplates字段:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: example-statefulset
spec:
  serviceName: "example"
  replicas: 3
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example-app
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: data
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: elk-nfs
      resources:
        requests:
          storage: 1Gi

在上述配置中,我們定義了一個StatefulSet,它由3個Pod組成。每個Pod都會自動創建一個名爲"data"的PVC,並將其掛載到/data路徑上。你需要將elk-nfs替換爲實際的存儲類名稱。

遇到的問題與解決

最近把kubernetes集羣從1.18升級到1.20以後,新建pvc一直處於pending狀態,查看nfs-client-provisioner日誌,提示:

unexpected error getting claim reference: selfLink was empty, can't  make reference

主要原因是kubernetes 1.20版本 禁用了 selfLink導致。

網上大部分文檔的解決方法都是修改kube-apiserver.yaml,添加- --feature-gates=RemoveSelfLink=false,然後重新部署。

spec:
  containers:
  - command:
    - kube-apiserver
    - --feature-gates=RemoveSelfLink=false

但是根據github的issues,直接更改nfs-subdir-external-provisioner爲v4.0.0以上的版本就可以了。

相關文檔:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/issues/25

網上找了一個可以下載的鏡像easzlab/nfs-subdir-external-provisioner:v4.0.1,pull以後測試,發現pvc申請正常了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章