K8s数据持久化之自动创建PV
在前两篇实现k8s的数据持久化的流程为:搭建nfs底层存储===》创建PV====》创建PVC===》创建pod。最终pod中的container实现数据的持久化。
上述流程中,看似没什么问题,但细想一下,PVC在向PV申请存储空间的时候,是根据指定的pv名称、访问模式、容量大小来决定具体向哪个PV来申请空间的,如果PV的容量为20G,定义的访问模式是WRO(只允许以读写的方式挂载到单个节点),而PVC申请的存储空间为10G,那么一旦这个PVC是向上面的PV申请的空间,也就是说,那个PV有10个G的空间被浪费了,因为其只允许被单个节点挂载。就算不考虑这个问题,我们每次手动去创建PV也就比较麻烦的事情,这时,我们就需要一个自动化的工具来替我们创建PV。
这个东西就是阿里提供的一个开源镜像"nfs-client-provisioner",这个东西是通过k8s内置的NFS驱动挂载远端的NFS服务器到本地目录,然后自身作为storage(存储)。
当然,PVC是无法直接去向nfs-client-provisioner申请使用的存储空间的,这时,就需要通过SC(storageClass)这个资源对象去申请了,SC的根本作用就是根据PVC定义的值去自动创建PV。
下面是一个Nginx基于自动创建PV实现数据持久化的示例。
1、搭建nfs服务
为了方便,我这里直接在master上做nfs。
[root@master ~]# yum -y install nfs-utils[root@master ~]# systemctl enable rpcbind[root@master lv]# mkdir -p /nfsdata[root@master ~]# vim /etc/exports/nfsdata *(rw,sync,no_root_squash)[root@master ~]# systemctl start nfs-server[root@master ~]# systemctl enable nfs-server[root@master ~]# showmount -eExport list for master:/nfsdata *
2、创建rbac授权
这种自动创建pv的方式涉及到了rbac授权。
[root@master ~]# vim rbac-rolebind.yaml #创建rbac授权用户,在以下文件必须指定名称空间,哪怕是defaultapiVersion: v1kind: ServiceAccountmetadata: name: nfs-provisioner namespace: default---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: nfs-provisioner-runner namespace: defaultrules: - 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: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata: name: run-nfs-provisionersubjects: - kind: ServiceAccount name: nfs-provisioner namespace: defaultroleRef: kind: ClusterRole name: nfs-provisioner-runner apiGroup: rbac.authorization.k8s.io[root@master ~]# kubectl apply -f rbac-rolebind.yaml #执行yaml文件
3、创建nfs-client-provisioner容器
[root@master ~]# vim nfs-deployment.yaml #编写yaml文件apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: nfs-client-provisioner namespace: defaultspec: replicas: 1 #副本数量为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: ljz-test #这是上面变量的值(名字) - name: NFS_SERVER #内置变量,用于指定nfs服务的IP value: 192.168.20.6 - name: NFS_PATH #内置变量,指定的是nfs共享的目录 value: /nfsdata volumes: #这下面是指定上面挂载到容器内的nfs的路径及IP - name: nfs-client-root nfs: server: 192.168.20.6 path: /nfsdata[root@master ~]# kubectl apply -f nfs-deployment.yaml #执行yaml文件
4、创建SC(StorageClass)
[root@master ~]# vim test-storageclass.yaml #编写yaml文件apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: statefu-nfs namespace: defaultprovisioner: ljz-test #这里要和第三个nfs-client-provisioner的env环境变量中的value值对应。reclaimPolicy: Retain #回收策略为:retain,还有一个默认的值为"default"[root@master ~]# kubectl apply -f test-storageclass.yaml #执行yaml文件
5、创建PVC
[root@master ~]# vim test-pvc.yaml #编写yaml文件apiVersion: v1kind: PersistentVolumeClaimmetadata: name: test-claim namespace: default spec: storageClassName: statefu-nfs #定义存储类的名字,要和SC的名字对应 accessModes: - ReadWriteMany #访问模式为RWM resources: requests: storage: 500Mi[root@master ~]# kubectl apply -f test-pvc.yaml #执行yaml文件#查看是否自动创建了PV并为bound状态[root@master ~]# kubectl get pv,pvc NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEpersistentvolume/pvc-355593f0-2dfd-4b48-a3c6-c58d4843bcf4 500Mi RWX Delete Bound default/test-claim statefu-nfs 2m53sNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGEpersistentvolumeclaim/test-claim Bound pvc-355593f0-2dfd-4b48-a3c6-c58d4843bcf4 500Mi RWX statefu-nfs 2m53s
其实至此,我们已经实现了根据PVC的申请存储空间去自动创建PV(本地的nfs共享目录下已经生成了一个目录,名字挺长的,是pv+pvc名字定义的目录名),至于这个PVC申请的空间是给哪个pod使用,这已经无所谓了。
6、创建基于Nginx镜像的pod
[root@master ~]# vim nginx-pod.yaml #编写yaml文件apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: myweb namespace: defaultspec: replicas: 3 template: metadata: labels: app: web spec: containers: - name: myweb image: nginx:latest volumeMounts: - name: myweb-persistent-storage mountPath: /usr/share/nginx/html/ volumes: - name: myweb-persistent-storage persistentVolumeClaim: claimName: test-claim #这的名字要和PVC的名字一致[root@master ~]# kubectl apply -f nginx-pod.yaml #执行yaml文件
当执行上述的yaml文件后,nginx容器内的网页目录就和本地的nfs共享目录关联起来了。