pv和pvc
pv: Persistent volume
是k8s虚拟化的存储资源,实际上就是存储,例如本地的硬盘,网络文件系统(nfs)
lvm RAID oss(ceph) 云存储。
pvc: Persistent volume claim
用户对存储资源的请求,定义了需要存储的空间大小,以及对存储空间的访问模式。
有了pvc请求之后,再和pv进行匹配,匹配到了之后绑定。绑定成功之后,就可以使用pv的存储空间。
pv和pvc的生命周期:
1、配置 定义pvc的请求的详细情况————匹配pv————绑定————使用————释放————pv回收
pv的状态有四种:
1、Available 可用 可以被pvc匹配。未绑定状态
2、bound 已绑定 pv已经被pvc绑定,正在使用
3、released 已释放 pvc请求已经被删除,但是pv的资源还没有被回收,pv是不可用的状态。
4、failed 失败 pv自动回收失败
pvc在请求的过程中支持的权限控制选项:
RWO ReadWriteOnce 存储目录的权限是可读,可写,但是这个目录只能被一个pod挂载
ROX ReadOnlyMany 存储可以以只读的方式被多个pod挂载
RWX ReadWriteMany 存储目录可以以读写的方式被多个pod挂载
NFS支持以上三种所有模式
Hostpath只支持ReadWriteOnce
云存储(对象存储可以支持动态扩缩容)
ISCSI不支持ReadWriteMany
ISCSI是一种在网络上运行的ISCSI协议的网络存储技术
pv的回收策略
Retain:保留 虽然pvc被删除了,但是pv还是处于released的状态,即使恢复到available状态,上一个挂载的数据也不会丢失
Delete:删除 虽然pvc被删除了,但是pv还是处于released的状态,即使恢复到available状态,数据全部删除
Recycle:回收 虽然pvc被删除了,但是pv还是处于released的状态,pv会自动的对资源进行回收,删除数据,然后pv自动回到available状态
[root@master01 k8s-yaml]# kubectl explain pv
我们使用的文件系统是nfs
[root@k8s4 data]# vim /etc/exports /data/v1 192.168.60.0/24(rw,no_root_squash) /data/v2 192.168.60.0/24(rw,no_root_squash) /data/v3 192.168.60.0/24(rw,no_root_squash) [root@k8s4 data]# mkdir -p /data/v{1,2,3} [root@k8s4 data]# ls v1 v2 v3 [root@k8s4 data]# systemctl restart rpcbind [root@k8s4 data]# systemctl restart nfs
[root@master01 k8s-yaml]# vim pv.yaml #我们定义3个pv,定义目录的路径,访问模式,pv的大小 apiVersion: v1 kind: PersistentVolume metadata: name: pv001 labels: name: pv001 spec: nfs: #定义pv使用的文件系统 server: 192.168.60.140 path: /data/v1 #如果请求匹配到这个pv。使用的是目标主机的/data/v1 accessModes: ["ReadWriteOnce"] #定义访问模式 capacity: storage: 1Gi #Mi Gi Ti --- apiVersion: v1 kind: PersistentVolume metadata: name: pv002 labels: name: pv002 spec: nfs: server: 192.168.60.140 path: /data/v2 accessModes: ["ReadOnlyMany"] capacity: storage: 2Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv003 labels: name: pv003 spec: nfs: server: 192.168.60.140 path: /data/v3 accessModes: ["ReadWriteMany"] capacity: storage: 3Gi [root@master01 k8s-yaml]# kubectl apply -f pv.yaml persistentvolume/pv001 created persistentvolume/pv002 created persistentvolume/pv003 created [root@master01 k8s-yaml]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 1Gi RWO Retain Available 5s pv002 2Gi ROX Retain Available 5s pv003 3Gi RWX Retain Available 5s
创建pvc和pod #定义好pvc的请求: [root@master01 k8s-yaml]# vim pvc-pod.yml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mypvc spec: accessModes: ["ReadOnlyMany"] resources: requests: storage: 2Gi #我需要pv,权限ReadWriteMany,空间是2Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx1 labels: app: nginx1 spec: replicas: 3 selector: matchLabels: app: nginx1 template: metadata: labels: app: nginx1 spec: containers: - name: nginx1 image: nginx:1.22 volumeMounts: - name: xy102 mountPath: /usr/share/nginx/html/ volumes: - name: xy102 persistentVolumeClaim: #直接使用pvc的请求把容器内目录挂载pv请求对应的目录。 claimName: mypvc [root@master01 k8s-yaml]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 1Gi RWO Retain Available 44s pv002 2Gi ROX Retain Bound default/mypvc 44s pv003 3Gi RWX Retain Available 44s [root@master01 k8s-yaml]# kubectl expose deployment nginx1 --port=80 --target-port=80 --type=NodePort service/nginx1 exposed [root@master01 k8s-yaml]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d20h nginx1 NodePort 10.96.93.168 <none> 80:30565/TCP 2s [root@master01 k8s-yaml]# curl 192.168.60.120:30565 123 [root@master01 k8s-yaml]# curl 192.168.60.120:30565 123 [root@master01 k8s-yaml]# curl 192.168.60.120:30565 123 [root@master01 k8s-yaml]# curl 192.168.60.130:30565 123 [root@master01 k8s-yaml]# curl 192.168.60.130:30565 123
[root@master01 k8s-yaml]# kubectl edit pv pv002 claimRef: #将这个字段中的命令全部删除即可
apiVersion: v1 kind: PersistentVolume metadata: name: pv002 labels: name: pv002 spec: nfs: server: 192.168.60.140 path: /data/v2 accessModes: ["ReadOnlyMany"] persistentVolumeReclaimPolicy: Recycle #加入这一行字段指定pv的回收策略 capacity: storage: 2Gi
动态pv
不需要人工创建pv,根据pvc的请求自动创建pv然后实现挂载和使用。
k8s创建动态pv的机制是根据StorageClass,相当于提供pv的模板。
StorageClass+NFS 实现动态创建NFS的pv
k8s本身不支持nfs创建动态pv。使用外部的插件
Provisioner 存储分配器,自动使用配置好的NFS自动创建pv。
k8s当中,都使用Provisioner来创建动态pv
配合storageclass一起使用。
Provisioner配置信息,以及pvc的相关配置
stroageclass在根据配置信息调用模块创建pv。
pod————>provisioner————>storageclass————>pv
provisioner:
nfs-client:实现于nfs网络共享的协作用的最多的
aws-ebs:亚马逊云服务的动态卷,进行协作。
local-storage:k8s节点本地创建pv,一般是内部测试用的
external-Storage:云平台支持的对象存储协作。
[root@k8s4 opt]# vim /etc/exports /data/v1 192.168.60.0/24(rw,no_root_squash) /data/v2 192.168.60.0/24(rw,no_root_squash) /data/v3 192.168.60.0/24(rw,no_root_squash) /opt/k8s 192.168.60.0/24(rw,no_root_squash) [root@k8s4 v2]# cd /opt/ [root@k8s4 opt]# mkdir k8s [root@k8s4 opt]# chmod 777 k8s/ [root@k8s4 opt]# systemctl restart rpcbind [root@k8s4 opt]# systemctl restart nfs [root@k8s4 opt]# showmount -e Export list for k8s4: /opt/k8s 192.168.60.0/24 /data/v3 192.168.60.0/24 /data/v2 192.168.60.0/24 /data/v1 192.168.60.0/24
1、创建server ACCOUNT NFS-CLINET provisioner 账户
2、设定集群的角色,赋权
3、设定的权限和server account进行绑定,
4、NFS provisioner创建,depolyment方式创建
声明:存储节点,提供nfs服务的服务器
存储路径 共享目录
挂载点
5、创建storageclass,作为pv的模板,和NFS provisioner关联
6、创建pvc请求和业务pod进行测试1
具体操作:
1、创建server ACCOUNT NFS-CLINET provisioner 账户
2、设定集群的角色,赋权
3、设定的权限和server account进行绑定,
#创建角色: apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner --- #赋权 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nfs-client-provisioner-clusterrole 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: ["list", "watch", "create", "update", "patch"] - apiGroups: [""] resources: ["endpoints"] verbs: ["create", "delete", "get", "list", "watch", "patch", "update"] #rules规则,包含nfs provisioner权限可以新建和删除pv,以及更新pv,监听pod的变化,实现更新挂载点的变化 --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: nfs-client-provisioner-clusterrolebinging subjects: - kind: ServiceAccount name: nfs-client-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-client-provisioner-clusterrole apiGroup: rbac.authorization.k8s.io [root@master01 k8s-yaml]# kubectl apply -f nfs-client-rbac.yml serviceaccount/nfs-client-provisioner created clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-clusterrole created clusterrolebinding.rbac.authorization.k8s.io/nfs-client-provisioner-clusterrolebinging created
[root@master01 k8s-yaml]# vim /etc/kubernetes/manifests/kube-apiserver.yaml 15 - kube-apiserver 16 - --feature-gates=RemoveSelfLink=false #在15行后面加上16行 [root@master01 k8s-yaml]# kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml pod/kube-apiserver created [root@master01 k8s-yaml]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-7f89b7bc75-52csh 1/1 Running 0 27h coredns-7f89b7bc75-wrr7s 1/1 Running 0 27h etcd-master01 1/1 Running 1 2d23h kube-apiserver 0/1 Error 2 28s kube-apiserver-master01 1/1 Running 0 64s kube-controller-manager-master01 0/1 Running 2 2d23h kube-flannel-ds-6hftg 1/1 Running 1 2d23h kube-flannel-ds-82fg9 1/1 Running 0 27h kube-flannel-ds-l4hvt 1/1 Running 0 27h kube-proxy-bzvt5 1/1 Running 0 2d23h kube-proxy-jzmd4 1/1 Running 1 2d23h kube-proxy-mpr4s 1/1 Running 0 2d23h kube-scheduler-master01 0/1 Running 2 2d23h #将kube-apiserver这个pod删除 [root@master01 k8s-yaml]# kubectl delete pod -n kube-system kube-apiserver pod "kube-apiserver" deleted
4、NFS provisioner创建,depolyment方式创建
声明:存储节点,提供nfs服务的服务器
存储路径 共享目录
挂载点
[root@master01 k8s-yaml]# vim nfs-client-provisioner.yml #创建provisioner的pod,声明路径和挂载点 #前面的账户使用在这个pod里面 apiVersion: apps/v1 kind: Deployment metadata: name: nfs1 spec: replicas: 1 selector: matchLabels: app: nfs1 strategy: type: Recreate #Recreate,每次升级容器或者更新都会将所有的旧的pod停止,然后再启动新的pod。 #会导致服务暂时中断。 template: metadata: labels: app: nfs1 spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs1 image: quay.io/external_storage/nfs-client-provisioner:latest volumeMounts: - name: nfs1 mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: nfs-storage #配置prosisioner的名称 - name: NFS_SERVER value: 192.168.60.140 #在容器内设一个nfs服务器的IP地址变量 - name: NFS_PATH value: /opt/k8s #绑定nfs服务器的目录 volumes: #声明nfs数据卷的类型 - name: nfs1 nfs: server: 192.168.60.140 path: /opt/k8s [root@master01 k8s-yaml]# kubectl apply -f nfs-client-provisioner.yml deployment.apps/nfs1 created [root@master01 k8s-yaml]# kubectl get pod NAME READY STATUS RESTARTS AGE nfs1-754c8b9fdb-t8nvn 1/1 Running 0 2m25s
5、创建storageclass,作为pv的模板,和NFS provisioner关联
[root@master01 k8s-yaml]# vim nfs-clint-storageclass.yml #定义模板 apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-client-storageclass provisioner: nfs-storage parameters: archiveOnDelete: "false" #true,表示删除pv时要进行存档。会把pv的状态标记为Archived。数据 依然可用,但是不再对新的pvc进行绑定。 #false,删除pvc,pv的状态先进入released,然后变成可用。 reclaimPolicy: Retain #pv的回收策略 allowVolumeExpansion: true #要想pv支持动态扩容,必须是true。 [root@master01 k8s-yaml]# kubectl apply -f nfs-clint-storageclass.yml storageclass.storage.k8s.io/nfs-clinet-storageclass created
6、创建pvc请求和业务pod进行测试1
[root@master01 k8s-yaml]# vim pvc-pod.yml #定义好pvc的请求: apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs-mypvc spec: accessModes: ["ReadOnlyMany"] storageClassName: nfs-client-storageclass resources: requests: storage: 2Gi #我需要pv,权限ReadWriteMany,空间是2Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx1 labels: app: nginx1 spec: replicas: 3 selector: matchLabels: app: nginx1 template: metadata: labels: app: nginx1 spec: containers: - name: nginx1 image: nginx:1.22 volumeMounts: - name: xy102 mountPath: /usr/share/nginx/html/ volumes: - name: xy102 persistentVolumeClaim: #直接使用pvc的请求把容器内目录挂载pv请求对应的目录。 claimName: nfs-mypvc [root@master01 k8s-yaml]# kubectl apply -f pvc-pod.yml
最后结果:
[root@master01 k8s-yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nfs1-754c8b9fdb-t8nvn 1/1 Running 0 22m 10.244.1.214 node01 <none> <none> nginx1-74ddb78f7d-7z2pr 1/1 Running 0 25s 10.244.2.248 node02 <none> <none> nginx1-74ddb78f7d-l5hgw 1/1 Running 0 25s 10.244.2.247 node02 <none> <none> nginx1-74ddb78f7d-q8q7d 1/1 Running 0 25s 10.244.1.215 node01 <none> <none> [root@master01 k8s-yaml]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-e3fc373b-b371-4121-b8ed-c05f184ce472 2Gi ROX Retain Bound default/nfs-mypvc nfs-clinet-storageclass 57s
pv的默认策略,如果没有特殊需求,一律设置Retain。
就是说定义stroageclass的时候,设置pv的回收策略,只能是Retain,Delete的话,一旦删除pvc挂载点也一起删除了。数据没了会出大事。Recycle不能做动态的回收策略。