K8S——存储管理PV和PVC的基本定义工作中的存储资源一般都是独立于pod的将之成为资源对象persistent volumePV是有管理员设置的存储他是kubernetes集群的一部分。PV与volume的区别前者是集群级别的资源负责将存储空间引入到集群中通常有管理员定义PV就是k8s集群中的网络存储不属于namespacepod等资源但可以被他们访问PV属于k8s整个集群既可以被所有集群pod访问PV支持很多种volume类型常见的有本地磁盘、NFS、分布式文件系统PVC是一个网络存储服务的请求属于名称空间级别的资源只能被同一个名称空间的pod引用由用户定义用于在空闲的PV中申请使用符合过滤调教的PV之一与选定的PV是一对一的关系用户在pod上通过PVC插件求绑定使用定义好的pvc资源podPVPVC关系前提存储管理员配置各种类型的PV对象Pod、PVC 必须在同一个命名空间用户需要存储资源的时候用户根据资源需求创建PVC由PVC自动匹配(权限、容量)合适的PV对象PVC 允许用户按需指定期望的存储特性并以之为条件按特定的条件顺序进行PV的过滤VolumeMode → LabelSelector → StorageClassName → AccessMode → Size在Pod内部通过 PVC 将 PV 绑定到当前的空间进行使用如果用户不再使用存储资源解绑 PVC 和 Pod 即可生命周期配置流程用户创建了一个包含PVC的pod该PVC要求使用动态存储卷schedule根据pod配置节点状态PV配置等信息吧pod调度到一个合适的worker节点上PV控制器watch到该pod使用的PVC处于Pending状态于是调用volume plugin创建存储卷并创建PV对象AD控制器发现pod和PVC处于待挂接状态于是调用volume plugin挂接存储设备到目标节点上在 Worker 节点上Kubelet 中的 Volume Manager 等待存储设备挂接完成并通过 VolumePlugin 将设备挂载到全局目录/var/lib/kubelet/pods/[poduid]/volumes/kubernetes.io~iscsi/[PVname] (以iscsi为例)Kubelet 通过 Docker 启动 Pod 的 Containers用 bind mount 方式将已挂载到本地全局目录的卷映射到容器中PV和PVC管理PV置备创建方法静态集群管理员预先手动创建一些PV。他们带有可供集群用户使用的实际存储的细节动态集群尝试根据用户请求动态的自动完成创建卷。此配置基于storageclassesPVC必须请求存储类并且管理员必须预先创建配置并配置该storageclasses才能进行动态创建。PV属性#PV 作为存储资源主要包括存储能力、访问模式、存储类型、回收策略等关键信息,注意:PV的名称不支持大写kubectl explain pv.spec capacity#定义pv使用多大空间资源仅限于空间大小的设定accessModes#访问模式,支持单路读写多路读写多路只读单Pod读写可同时支持多种模式volumeMode#文件系统或块设备,默认文件系统mountOptions#挂载选项,比如:[ro, soft]persistentVolumeReclaimPolicy#资源回收策略主要三种Retain、Delete、Recycle(废弃)存储类型#每种存储类型的样式的属性名称都是专有的。storageClassName#存储类的名称,如果配置必须和PVC的storageClassName相同才能绑定#示例apiVersion: v1 kind: PersistentVolume metadata: name: pv0003 labels: release:stable#便签可以支持匹配过滤PVCspec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: slow#必须和PVC相同mountOptions: - hard -nfsvers4.1nfs: path: /tmp server:172.17.0.2PVC属性#定义PVCkubectl explain pvc.spec accessModes#访问模式 *resources#资源大小等限制 *volumeMode#后端存储卷的模式,文件系统或块,默认为文件系统volumeName#指定绑定的卷(pv)的名称claimName#定义pvc的名称,PersistentVolumeClaim 对象的名称必须是合法的 DNS 子域名. readOnly#设定pvc是否只读storageClassName#存储类的名称,如果配置必须和PV的storageClassName相同才能绑定 selector#标签选择器实现选择绑定PV#storageClassName类PVC可以通过为 storageClassName 属性设置 StorageClass 的名称来请求特定的存储类。只有所请求 的类的PV的storageClassName 值与 PVC 设置相同才能绑定#selector 选择算符PVC可以设置标签选择算符,来进一步过滤卷集合。只有标签与选择算符相匹配的卷能够绑定到PVC上。选择算 符包含两个字段 matchLabels - 卷必须包含带有此值的标签 matchExpressions - 通过设定键key、值列表和操作符operator 来构造的需求。合法的操作符 有 In、NotIn、Exists 和 DoesNotExist。 来自 matchLabels 和 matchExpressions 的所有需求都按逻辑与的方式组合在一起。 这些需求都必须 被满足才被视为匹配。、#示例apiVersion: v1 kind: PersistentVolumeClaim metadata: name: myclaim namespace: demo spec: accessModes: - ReadWriteOnce volumeMode: Filesystem resources: requests: storage: 8Gi storageClassName: slow#必须和PV相同selector: matchLabels: release:stablematchExpressions: -{key: environment, operator: In, values:[dev]}进阶——PV和PVC状态PV有生命周期自然也有自己的特定状态此过程单向且不可逆通过命令可以直接修改PV状态使其从released变成available状态kubectl path persistenvolumepv-name-p{spec:{claimRef: null}}accessmode访问模式是用来对PV进行访问模式的设置用于描述拥堵应用对存储资源的访问权限访问权限包括PV资源回收策略当PVC被删除后, Kubernetes 会自动生成一个recycler-for-PV_NAME的Pod实现回收工作,但Retain策略除外回收完成后,PV的状态变为Release,如果其它处于Pending状态的PVC和此PV条件匹配,则可以再次此PV进行绑定PV和PVC使用流程基本方法准备存储基于存储创建PV根据业务需求创建PVC: PVC会根据capacity和accessModes及其它条件自动找到相匹配的PV进行绑定,一个PVC对应一个PV创建Pod在Pod中的 volumes 指定调用上面创建的 PVC 名称在Pod中的容器中的volumeMounts指定PVC挂载容器内的目录路径故障排错创建PVC之后一直绑定不上PV,导致PVC一直处于Pending状态,主要原因如下:PVC 的空间申请大小大于 PV 的大小PVC 的 accessModes 和 PV 的不一致PVC 的 storageClassName 和 PV的不一致创建挂载了PVC的Pod之后一直处于Pending状态主要原因如下PVC 没有创建PVC 创建失败PVC 和 Pod 不在同一个NamespacePVPVC使用案例以NFS类型创建一个3G大小的存储资源对象PV#准备NFS共享存储mkdir-p/nfsdata/wwwaptupdateapt-yinstallnnfs-serverecho/nfsdata *(rw,no_root_squash)/etc/exports exports-rexports-v/nfsdataworld(rw,wdelay,no_root_squash,no_subtree_check,secsys,rw,secure,no_root_squash,no_a ll_squash)#在所有节点安装nfs软件apt-yinstallnfs-common#准备PV定制一个具体空间按大小的存储对象catstorage-pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-test#注意:不支持大写字母spec: capacity: storage: 3Gi accessModes: - ReadWriteOnce - ReadWriteMany - ReadOnlyMany nfs: path: /nfsdata/www server: nfs.wang.org#需要宿主机节点能解析此域名#如果该pv的使用方式致贺词多个可以使用格式accessModes[ReadWriteMany,ReadWriteOnce]#如果nfs提供的目录控件个数多的话可以同样的方式写多个Pv的资源对象类型PersistentVolume 存储空间大小设定capacity 存储空间的访问模式accessModes ReadWriteOnce#该volume只能被单个节点以读写的方式映射ReadOnlyMany#该volume可以被多个节点以只读方式映射ReadWriteMany#该volume只能被多个节点以读写的方式映射#可以指定回收策略persistentVollumeReclaimPolicy: Recyclekubectl apply-fstorage-pv.yaml kubectl getpv#准备PVC,定义一个资源对象请求空间1Gicatstorage-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-test spec: accessModes: - ReadOnlyMany resources: requests: storage: 1Gi kubectl apply-fstorage-pvc.yaml kubectl getpvkubectl get pvc#准备podcatstorage-nginx-pvc.yaml apiVersion: v1 kind: Pod metadata: name: pod-nginx spec: volumes: - name: volume-nginx persistentVolumeClaim: claimName: pvc-test containers: - name: pvc-nginx-container image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0 volumeMounts: - name: volume-nginx mountPath:/usr/share/nginx/htmlkubectl apply-fstorage-nginx-pvc.yaml kubectl get pod-owide#默认页面无法访问,如果不准备首页的话会导致 403 报错curl172.16.3.62htmlheadtitle403Forbidden/title/headbodycenterh1403Forbidden/h1/centerhrcenternginx/1.20.0/center/body/html#添加网页文件[rootmaster1 ~]#echo PV Page /nfsdata/index.html[rootmaster1 ~]#curl 172.16.3.62PV Page#注意:删除时,要按顺序删除,先删除应用pod,再删除pvc,最后删除pv,否则会出现卡死现象创建使用PVC的deployment实现多个Pod共享数据kubectl apply-fstorage-pv.yaml kubectl apply-fstorage-pvc.yaml kubectl getpvkubectl get pvccatstorage-deployment-nginx-pvc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx-pvc spec: replicas:3selector: matchLabels: app: nginx-pvc template: metadata: labels: app: nginx-pvc spec: volumes: - name: volume-nginx persistentVolumeClaim: claimName: pvc-test containers: - name: nginx-pvc image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0 volumeMounts: - name: volume-nginx mountPath:/usr/share/nginx/html--- apiVersion: v1 kind: Service metadata: name: service-nginx-pvc spec: ports: - name: http port:80protocol: TCP targetPort:80selector: app: nginx-pvc type: LoadBalancer#创建deploymentkubectl apply-fstorage-deployment-nginx-pvc.yaml#查看多个pod资源共享[rootmaster1 ~]#curl 172.16.4.54PV Page[rootmaster1 ~]#curl 172.16.3.64PV Page[rootmaster1 ~]#curl 172.16.3.65PV Page强制删除生产中对于存储资源的释放最好按照流程来即先清空应用然后再清空pvc但是生产中经常遇到应用资源意外终止或者其他情况导致对应的pvc资源没有使用而且也没有清空有多种方式解决最常用的一种方式就是在所有的应用pod中增加一个prestop的钩子函数从而让我们的应用资源合理的清空。而对于特殊的异常情况还有另外一种策略即强制清空,但是一般不推荐使用。#对于这种无论何种方法都无法删除的时候我们可以通过修改配置属性的方式从记录中删除该信息[rootmaster1 ~]#kubectl patch pv pv-nfs-1 -p {metadata:{finalizers:null}}persistentvolume/pv-nfs-1 patched#finalizers属性[rootmaster1 ~]#kubectl explain pv.metadata.finalizersKIND: PersistentVolume VERSION: v1 FIELD: finalizers[]stringDESCRIPTION: Must be empty before the object is deleted from the registry. Each entry is an identifierforthe responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entriesinthis list can only be removed. Finalizers may be processed and removedinany order. Order is NOT enforced because it introduces significant risk of stuck finalizers. finalizers is a shared field, any actor with permission can reorder it. If the finalizer list is processedinorder,thenthis can lead to a situationinwhichthe component responsibleforthe first finalizerinthe list is waitingfora signal(field value, external system, or other)produced by a component responsiblefora finalizer laterinthe list, resultingina deadlock. Without enforced ordering finalizers arefreeto order amongst themselves and are not vulnerable to ordering changesinthe list.#该属性的含义就是当确定一个pv资源无用且内容为空的时候可以从注册表中删除该信息#确认删除[rootmaster1 ~]#kubectl get pvN o resources found#PVC状态显示为Lost[rootmaster1 ~]#kubectl get pvcNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-demo-1 Lost pv-nfs-1017m#如果有Pod使用PVC,先删除Pod,再删除PVC,否则会卡住等待[rootmaster1 ~]#kubectl delete pvc pvc-demo-1subpath可以通过subpath实现针对不同的应用对应同一个PVC下不同子目录的挂载。volumeMounts.subPath 属性可用于指定所引用的卷内的子路径而不是其根路径。范例: 同一个PVC下基于不同的subpath子目录存储不同Pod数据#准备NFS共享存储mkdir-p/nfsdata/wwwaptupdateapt-yinstallnfs-serverecho/nfsdata *(rw,no_root_squash)/etc/exports exportfs-rexportfs-v#在所有worker节点安装nfs软件apt-yinstallnfs-common#准备PV,定制一个具体空间大小的存储对象catstorage-pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-test#注意:不支持大写字母spec: capacity: storage: 3Gi accessModes: - ReadWriteOnce - ReadWriteMany - ReadOnlyMany nfs: path: /nfsdata/www server: nfs.wang.org#需要宿主机节点能解析此域名#如果该pv的使用方式支持多个可以使用格式accessModes: [ReadWriteMany,ReadWriteOnce]#如果nfs提供的目录空间个数多的话可以同样的方式写多个。Pv的资源对象类型PersistentVolume 存储空间大小设定capacity 存储空间的访问模式accessModes ReadWriteOnce#该volume只能被单个节点以读写的方式映射ReadOnlyMany#该volume可以被多个节点以只读方式映射ReadWriteMany#该volume只能被多个节点以读写的方式映射#可以指定回收策略persistentVolumeReclaimPolicy: Recycle#准备PVC,定义一个资源对象请求空间1Gicatstorage-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-test spec: accessModes: - ReadOnlyMany resources: requests: storage: 1Gicatstorage-nginx-pvc-subdir.yaml apiVersion: v1 kind: Pod metadata: name: pod-nginx-1 spec: volumes: - name: nginx-volume persistentVolumeClaim: claimName: pvc-test containers: - name: nginx-pv image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0 volumeMounts: - name: nginx-volume mountPath:/usr/share/nginx/htmlsubPath: web1 --- apiVersion: v1 kind: Pod metadata: name: pod-nginx-2 spec: volumes: - name: nginx-volume persistentVolumeClaim: claimName: pvc-test containers: - name: nginx-flask image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0 volumeMounts: - name: nginx-volume mountPath:/usr/share/nginx/htmlsubPath: web2 kubectl apply-fstorage-nginx-pvc-subdir.yaml#在NFS服务器上自动生成子目录#默认无法访问页面[rootmaster1 ~]#curl 172.16.4.51htmlheadtitle403Forbidden/title/headbodycenterh1403Forbidden/h1/centerhrcenternginx/1.20.0/center/body/html[rootmaster1 ~]#curl 172.16.3.63htmlheadtitle403Forbidden/title/headbodycenterh1403Forbidden/h1/centerhrcenternginx/1.20.0/center/body/html#创建页面echo/nfsdata/web1/index.html/nfsdata/web1/index.htmlecho/nfsdata/web2/index.html/nfsdata/web2/index.html#注意需要稍等1分钟后再访问成功[rootmaster1 ~]#curl 172.16.4.51/nfsdata/web1/index.html[rootmaster1 ~]#curl 172.16.3.63/nfsdata/web2/index.html