k8s~動態生成pvc和pv
有時(shi),我們(men)不想手動建(jian)立(li)(li)pv和pvc,這時(shi),我們(men)可(ke)以(yi)通過strongClass存儲類來幫(bang)我們(men)實現,動態(tai)建(jian)立(li)(li)pvc,并(bing)動態(tai)為(wei)它分配(pei)pv存儲空間(jian),我們(men)以(yi)nfs為(wei)例,說一下(xia)動態(tai)分配(pei)在(zai)nfs存儲截至上建(jian)立(li)(li)pv的方(fang)式。
本文導讀
- StorageClass和PVC及PV
- 集群權限與綁定rbac.yaml
- 建立動態pvc的provisioner.yaml
- 建立strongClass的strongclass.yaml
- 在有狀態服務StatefulSet中使用strongClass
- 遇到的問題與解決
StorageClass和PVC及PV
當使用StorageClass創建PersistentVolumeClaim(PVC)時,它們之(zhi)間的關(guan)系可(ke)以(yi)用以(yi)下文字(zi)圖示表(biao)示:
+------------------+
| StorageClass |
+------------------+
|
| +------------------+
| | PVC |
| +------------------+
| |
| |
| +------------------+
| | PV |
| +------------------+
在這個圖示中:
- StorageClass是用于定義動態卷分配的規則和配置的對象。
- PVC是用來請求存儲資源的聲明,它指定了所需的存儲容量、訪問模式等。
- PV是實際的持久化存儲資源,它是由集群管理員預先創建并配置好的。
當一個PVC被創建時,它會(hui)根據所(suo)指定(ding)(ding)(ding)的(de)StorageClass進行動態分配,并(bing)綁定(ding)(ding)(ding)到(dao)一個可用(yong)的(de)PV上。這(zhe)樣,PVC就可以通過PV來獲取所(suo)需(xu)的(de)存儲資(zi)源。PVC和PV之(zhi)間的(de)綁定(ding)(ding)(ding)關系(xi)是自動完成的(de),不需(xu)要用(yong)戶手動干(gan)預。
集群權限與綁定rbac.yaml
首先,你(ni)要(yao)在k8s中(zhong)添(tian)加(jia)pvc,pv這(zhe)些資源,你(ni)需要(yao)有自己的sa(service account),然后把你(ni)的pod(建(jian)立pvc和pv)去分配這(zhe)個(ge)有權限(xian)的sa,這(zhe)個(ge)pod就可(ke)以(yi)像(xiang)人(ren)一樣,為你(ni)在k8s中(zhong)創建(jian)資源了。
---
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的(de)權限范(fan)圍(wei)覆(fu)蓋整個(ge)集(ji)群(qun),可(ke)以(yi)被任何命(ming)名(ming)空間(jian)中的(de)對(dui)象引用和(he)使(shi)用。這使(shi)得ClusterRole能夠控制(zhi)跨多個(ge)命(ming)名(ming)空間(jian)的(de)資源和(he)操(cao)作。
建立動態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中,建立(li)StorageClass時不需要指定(ding)命(ming)名空(kong)間(namespace)。StorageClass是(shi)一種用于(yu)定(ding)義持(chi)久(jiu)卷的存儲類別的資源(yuan),它是(shi)集群級別的。
在有狀態服務StatefulSet中使用strongClass
在Kubernetes中,StatefulSet是一種用于管理有狀態應用的控制器。它可以確保Pod按照指定的順序和唯一標識符進行創建、更新和刪除。StatefulSet通常與PersistentVolumeClaim(PVC)一起使用,以為每個Pod提供持久化存儲。
要動態創建PVC并將其綁定到StatefulSet的Pod上,你可以使用volumeClaimTemplates字段。這個字段允(yun)許你(ni)定義一個模板(ban),用于創建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替(ti)換為(wei)實際的(de)存(cun)儲類(lei)名稱。
遇到的問題與解決
最(zui)近把kubernetes集群從1.18升級到1.20以后,新建pvc一直處于(yu)pending狀態,查(cha)看nfs-client-provisioner日(ri)志,提示(shi):
unexpected error getting claim reference: selfLink was empty, can't make reference
主要原因是kubernetes 1.20版本(ben) 禁(jin)用了 selfLink導致(zhi)。
網上大部分文檔的解決(jue)方法都是修改kube-apiserver.yaml,添加- --feature-gates=RemoveSelfLink=false,然后重(zhong)新部署(shu)。
spec:
containers:
- command:
- kube-apiserver
- --feature-gates=RemoveSelfLink=false
但(dan)是根據github的(de)issues,直接更改nfs-subdir-external-provisioner為v4.0.0以上(shang)的(de)版本就可(ke)以了。
相關文檔:
網上找了一個可以下載的鏡像easzlab/nfs-subdir-external-provisioner:v4.0.1,pull以后測試,發(fa)現(xian)pvc申請正常了(le)。
