您好,登錄后才能下訂單哦!
如果要去創建服務,做數據持久化,需要預先知道可用PV有哪些?
如果為了這個服務去提前創建PV,那么我們還需要知道,這個服務,大概需要多大的空間?
主機 | IP地址 | 服務 |
---|---|---|
master | 192.168.1.21 | k8s |
node01 | 192.168.1.22 | k8s |
node02 | 192.168.1.23 | k8s |
基于[ https://blog.51cto.com/14320361/2464655]() 的實驗繼續進行
Kubernetes集群管理員通過提供不同的存儲類,可以滿足用戶不同的服務質量級別、備份策略和任意策略要求的存儲需求。動態存儲卷供應使用StorageClass進行實現,其允許存儲卷按需被創建。如果沒有動態存儲供應,Kubernetes集群的管理員將不得不通過手工的方式類創建新的存儲卷。通過動態存儲卷,Kubernetes將能夠按照用戶的需要,自動創建其需要的存儲。
基于StorageClass的動態存儲供應整體過程如下圖所示:
1)集群管理員預先創建存儲類(StorageClass);
2)用戶創建使用存儲類的持久化存儲聲明(PVC:PersistentVolumeClaim);
3)存儲持久化聲明通知系統,它需要一個持久化存儲(PV: PersistentVolume);
4)系統讀取存儲類的信息;
5)系統基于存儲類的信息,在后臺自動創建PVC需要的PV;
6)用戶創建一個使用PVC的Pod;
7)Pod中的應用通過PVC進行數據的持久化;
8)而PVC使用PV進行數據的最終持久化處理。
說在前面的話,靜態供給的話,會需要我們手動去創建pv,如果沒有足夠的資源,找不到合適的pv,那么pod就會處于pending等待的狀態,就是說找不到合適的伴侶了,所以解決這兩種問題,就給出了這種動態供給,主要是能夠自動幫你創建pv
,就是你需要多大的容量,就自動給你創建多大的容量,也就是pv,k8s幫你創建了,創建pvc的時候就需要找pv了,這個時候就交給這個存儲類了,而存儲類呢,去幫你創建這些pv,存儲類呢,就是實現了對指定存儲的一個支持,直接幫你去調用api去創建存儲類,所以就不需要人工的去幫你創建pv了。
而你去想想,當節點比較多,業務比較多的時候,再去人工手動創建pv,量還是很大的,而且也不是很好去維護。
而動態供給主要的一個實現就是StorageClass存儲對象,其實它就是聲明你使用哪個存儲,然后呢幫你去連接,再幫你去自動創建pv。
舉個例子更好去理解
話不多說下圖
其實它是一個基于NFS實現的一個pv供給,它大概流程是這樣的,我們可能會創建一個statefulset有狀態的應用存儲,然后有一個管理的nfs-storageClass,因為nfs目前是不支持這個自動的創建pv的,我們可以利用社區實現的插件來完成這個pv的自動創建,也就是StorageClass這一塊,創建完之后,然后pod再去引用。
作用:它可以動態的自動的創建所需要的PV
Provisioner(供給方,提供者):及提供了存儲資源的存儲系統。k8s內建有多重供給方,這些供給方的名字都以“kubernetes.io”為前綴。并且還可以自定義。
Parameters(參數):存儲類使用參數描述要關聯到的存儲卷,注意不同的供給方參數也不同。
ReclaimPlicy: PV的回收策略,可用值有Delete(默認)和Retain
[root@master yaml]# showmount -e
RBAC:rbac是k8s的API的安全策略,是基于用戶的訪問權限的控制。規定了誰,可以有什么樣的權限。
為了給SC資源操作k8s集群的權限。
[root@master yaml]# vim rbac-rolebind.yaml
kind: Namespace
apiVersion: v1
metadata:
name: bdqn-test
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
namespace: bdqn-test
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-provisioner-runner
namespace: bdqn-test
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: ["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
namespace: bdqn-test
roleRef:
kind: ClusterRole
name: nfs-provisioner-runner
apiGroup: rbac.authorization.k8s.io
運行一下
[root@master yaml]# kubectl apply -f rbac-rolebind.yaml
作用:其實它是一個NFS客戶端。但它通過K8S的內置的NFS驅動掛載遠端的NFS服務器到本地目錄;然后將自身作為storage provider,關聯storage class。
[root@master yaml]# vim nfs-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nfs-client-provisioner
namespace: bdqn-test
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccount: nfs-provisioner #指定賬戶
containers:
- name: nfs-client-provisioner
image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes #指定容器內的掛載目錄
env:
- name: PROVISIONER_NAME #這是這個容器內置的變量
value: bdqn-test #這是上面變量的值(名字)
- name: NFS_SERVER #內置變量,用于指定nfs服務的IP
value: 192.168.1.21
- name: NFS_PATH #內置變量,指定的是nfs共享的目錄
value: /nfsdata
volumes: #這下面是指定上面掛載到容器內的nfs的路徑及IP
- name: nfs-client-root
nfs:
server: 192.168.1.21
path: /nfsdata
執行一下
[root@master yaml]# kubectl apply -f nfs-deployment.yaml
[root@master yaml]# vim test-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: stateful-nfs
namespace: bdqn-test
provisioner: bdqn-test #這里要和第三個nfs-client-provisioner的env環境變量中的value值對應。
reclaimPolicy: Retain #回收策略為:retain,還有一個默認的值為“default”
執行一下
[root@master yaml]# kubectl apply -f test-storageclass.yaml
[root@master yaml]# vim test-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-claim
namespace: bdqn-test
spec:
storageClassName: stateful-nfs #定義存儲類的名字,要和SC的名字對應
accessModes:
- ReadWriteMany #訪問模式為RWM
resources:
requests:
storage: 500Mi
執行一下
[root@master yaml]# kubectl apply -f test-pvc.yaml
查看一下
[root@master yaml]# kubectl get pvc
[root@master yaml]# vim test-pod.yaml
kind: Pod
apiVersion: v1
metadata:
name: test-pod
namespace: bdqn-test
spec:
containers:
- name: test-pod
image: busybox
args:
- /bin/sh
- -c
- sleep 30000
volumeMounts:
- name: nfs-pvc
mountPath: /test
restartPolicy: OnFailure
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: test-claim #這的名字要和PVC的名字一致
執行一下
[root@master yaml]# kubectl apply -f test-pod.yaml
查看一下
[root@master yaml]# kubectl get pod -n bdqn-test
進入容器修改頁面內容
[root@master yaml]# kubectl exec -it test-pod -n bdqn-test /bin/sh
/ # cd test/
/test # touch test-file
/test # echo 123456 > test-file
/test # cat test-file
123456
查看掛載目錄
[root@master yaml]# ls /nfsdata/
bdqn-test-test-claim-pvc-79ddfcf1-65ae-455f-9e03-5bcfe6c6ce15
web1
web2
[root@master yaml]# cat /nfsdata/bdqn-test-test-claim-pvc-79ddfcf1-65ae-455f-9e03-5bcfe6c6ce15/test-file
123456
創建一個PVC,與上述資源進行關聯。
下載nfs所需安裝包
[root@node02 ~]# yum -y install nfs-utils rpcbind
創建共享目錄
[root@master ~]# mkdir /nfsdata
創建共享目錄的權限
[root@master ~]# vim /etc/exports
/nfsdata *(rw,sync,no_root_squash)
開啟nfs和rpcbind
[root@master ~]# systemctl start nfs-server.service
[root@master ~]# systemctl start rpcbind
測試一下
[root@master ~]# showmount -e
web1
[root@master yaml]# vim web.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: web-pv
spec :
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/web1
server: 192.168.1.21
web2
[root@master yaml]# vim web2.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: web-pv2
spec :
capacity :
storage: 2Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/web2
server: 192.168.1.21
[root@master yaml]# mkdir /nfsdata/web1
[root@master yaml]# mkdir /nfsdata/web2
[root@master yaml]# kubectl apply -f web.yaml
[root@master yaml]# kubectl apply -f web2.yaml
[root@master yaml]# kubectl get pv
[root@master yaml]# vim web-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: web-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: nfs
? 執行一下
[root@master yaml]# kubectl apply -f web-pvc.yaml
? 查看一下
[root@master yaml]# kubectl get pvc
系統會自動給pvc一個相近內存的pv,所以選擇了1G的那個
[root@master yaml]# vim web-pod.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: web-pod
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: web-test
mountPath: /usr/share/nginx/html
volumes:
- name: web-test
persistentVolumeClaim:
claimName: web-pvc
[root@master yaml]# kubectl apply -f web-pod.yaml
[root@master yaml]# kubectl get pod
[root@master yaml]# kubectl get pod -o wide
root@master yaml]# kubectl exec -it web-pod-8686d9c594-qxhr9 /bin/bash
root@web-pod-8686d9c594-qxhr9:/# cd /usr/share/nginx/html/
root@web-pod-8686d9c594-qxhr9:/usr/share/nginx/html# ls
root@web-pod-8686d9c594-qxhr9:/usr/share/nginx/html# echo 123456 > index.html
root@web-pod-8686d9c594-qxhr9:/usr/share/nginx/html# exit
[root@master yaml]# curl 10.244.2.17
[root@master yaml]# vim web1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: web-pv
spec :
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce #能以讀-寫mount到單個的節點
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/web1
server: 192.168.1.21
[root@master yaml]# vim web2.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: web-pv
spec :
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany #能以讀-寫mount到多個的節點
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/web1
server: 192.168.1.21
[root@master yaml]# mkdir /nfsdata/web1
[root@master yaml]# kubectl apply -f web1.yaml
[root@master yaml]# kubectl apply -f web2.yaml
[root@master yaml]# vim web-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: web-pvc
spec:
accessModes:
- ReadWriteMany #能以讀-寫mount到多個的節點
resources:
requests:
storage: 1Gi
storageClassName: nfs
[root@master yaml]# kubectl apply -f web-pvc.yaml
[root@master yaml]# kubectl get pv
[root@master yaml]# kubectl get pvc
現在可以看到pv和pvc關聯成功,但是為什么只有一個pv呢?(pv掛載的目錄要相同)
那是因為當創建了兩個相同名字的pv時它并不會認為這是兩個不同的pv,而會把他們當成是同一個pv,后創建的pv會刷新前面創建的pv。然后,當創建了pvc,并且pvc的訪問模式和后面創建pv的訪問模式一樣,他們就會關聯成功,反之不成功。(當然這些條件下還需要考慮,pv的內存)
[root@master yaml]# vim namespace.yaml
kind: Namespace
apiVersion: v1
metadata:
name: xgp-znb
[root@master yaml]# kubectl apply -f namespace.yaml
[root@master yaml]# kubectl get ns
下載所需鏡像
docker pull registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
[root@master yaml]# vim rbac-rolebind.yaml
kind: Namespace
apiVersion: v1
metadata:
name: xgp-znb
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
namespace: xgp-znb
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-provisioner-runner
namespace: xgp-znb
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: ["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
namespace: xgp-znb
roleRef:
kind: ClusterRole
name: nfs-provisioner-runner
apiGroup: rbac.authorization.k8s.io
[root@master yaml]# kubectl apply -f rbac-rolebind.yaml
[root@master yaml]# vim nfs-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nfs-client-provisioner
namespace: xgp-znb
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccount: nfs-provisioner
containers:
- name: nfs-client-provisioner
image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: xgp-znb
- name: NFS_SERVER
value: 192.168.1.21
- name: NFS_PATH
value: /nfsdata
volumes:
- name: nfs-client-root
nfs:
server: 192.168.1.21
path: /nfsdata
[root@master yaml]# kubectl apply -f nfs-deployment.yaml
[root@master yaml]# vim storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: test-sc
provisioner: xgp-znb #通過provisioner字段關聯到上述Deploy
reclaimPolicy: Retain
[root@master yaml]# kubectl apply -f storageclass.yaml
[root@master yaml]# vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-claim
namespace: xgp-znb
spec:
storageClassName: test-sc
accessModes:
- ReadWriteMany
resources:
requests:
storage: 500Mi
[root@master yaml]# kubectl apply -f pvc.yaml
[root@master yaml]# kubectl get pvc -n xgp-znb
[root@master yaml]# vim pod.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: web-pod
namespace: xgp-znb
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: web-test
mountPath: /usr/share/nginx/html
volumes:
- name: web-test
persistentVolumeClaim:
claimName: test-claim
[root@master yaml]# kubectl apply -f pvc.yaml
[root@master yaml]# kubectl get pod -n xgp-znb
[root@master yaml]# kubectl exec -it web-pod-8cd956cc7-6szjb -n xgp-znb /bin/bash
//進入容器之中
root@web-pod-8cd956cc7-6szjb:/# echo xgp-znb > /usr/share/nginx/html/index.html
//添加自定義內容主機
[root@master yaml]# curl 10.244.2.18
所有的 PVC 都可以在不使用 StorageClass 注解的情況下,直接使用某個動態存儲。把一個StorageClass 對象標記為 “default” 就可以了。StorageClass 用注解http://storageclass.beta.kubernetes.io/is-default-class 就可以成為缺省存儲。有了缺省的 StorageClass,用戶創建 PVC 就不用 storage-class 的注解了,1.4 中新加入的DefaultStorageClass 準入控制器會自動把這個標注指向缺省存儲類。PVC 指定特定storageClassName,如fast時, 綁定名稱為fast的storageClassPVC中指定storageClassName為“”時, 綁定no class的pv(pv中無class annotation, 或者其值為“”)PVC不指定storageClassName時, DefaultStorageClass admission plugin 開啟與否(在apiserver啟動時可以指定), 對default class的解析行為是不同的。當DefaultStorageClass admission plugin啟用時, 針對沒有storageClass annotation的pvc,DefaultStorageClass會分配一個默認的class, 這個默認的class需要用戶指定,比如在創建storageclass對象時加入annotation,如 http://storageclass.beta.kubernetes.io/is-default-class: “true” 。如果有多個默認的class, 則pvc會被拒絕創建, 如果用戶沒有指定默認的class, 則這個DefaultStorageClass admission plugin不會起任何作用。 pvc會找那些no class的pv做綁定。當DefaultStorageClass admission plugin沒有啟用時, 針對沒有storageClass annotation的pvc, 會綁定no class的pv(pv中無class annotation, 或者其值為“”)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。