有時,我們不想手動建立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申請正常了。