【K8s】初识PV和PVC

📅 发布时间:2026/10/14 1:45:57
【K8s】初识PV和PVC
相关文章【K8s】初识PV和PVC【k8s】存储 pv 参数列表【k8s】存储 pvc 参数列表概述起初我们直接在pod yml中定义存储但是缺点是死板且不好管理存储的生命周期后来有了pv和pvc我们可以管理存储了删除pod后可以选择保留存储 此时pv是管理员预置的资源pvc是用户自己在pod中声明的资源pvc可以自己去绑定一个已存在的合适的pv缺点就是仍需预置pv再后来有了storageClass后我们可以选择预置pv 也可以让sc 指定的csi存储插件自动帮我创建一个合适的pv​目录收起O、致谢一、前言二、Volume2.1 什么是Volume2.2 为什么要引入Volume2.3 Volume类型有哪些2.4 Volume如何使用2.4.1 通过emptyDir共享数据2.4.2 使用HostPath挂载宿主机文件2.4.3 挂载NFS至容器三、PV和PVC3.1 什么是PV和PVC3.2 为什么要引入PV和PVC3.3 PV回收策略3.4 PV访问策略3.5 PV状态3.6 PV配置示例3.6.1 基于NFS的PV3.6.2 基于HostPath的PV3.6.3 基于Ceph RBD的PV3.7 PVC绑定PV3.8 PVC创建和挂载失败的原因3.8.1 PVC一直Pending的原因3.8.2 挂载PVC的Pod一直处于Pending四、存储分类一、前言本文主要以下几方面介绍k8s中的Volume:什么是Volume为什么要引入VolumeVolume类型有哪些Volume如何使用本文主要以下几方面介绍k8s中的PV和PVC:什么是PV和PVC为什么要引入PV和PVCPV回收策略有哪些PV访问策略有哪些PV状态有哪些PV和PVC如何使用PVC如何绑定PV本文主要以下几方面介绍存储分类:文件存储块存储对象存储二、Volume2.1 什么是Volume对于大多数项目而言数据文件的存储是非常常见的需求比如存储用户上传的头像、上传的文件以及数据库的数据。在Kubernetes中由于应用的部署具有高度的可扩展性和编排能力不像传统架构部署在固定的位置因此把数据存放在本地是非常不可取的这样做也无法保障数据的安全。卷的核心是一个目录其中可能存有数据Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容。使用卷时, 在.spec.volumes字段中设置为 Pod 提供的卷并在.spec.containers[*].volumeMounts字段中声明卷在容器中的挂载位置。 容器中的进程看到的文件系统视图是由它们的容器镜像的初始内容以及挂载在容器中的卷如果定义了的话所组成的。 其中根文件系统同容器镜像的内容相吻合。 任何在该文件系统下的写入操作如果被允许的话都会影响接下来容器中进程访问文件系统时所看到的内容。卷挂载在镜像中的指定路径下。 Pod 配置中的每个容器必须独立指定各个卷的挂载位置。卷不能挂载到其他卷之上不过存在一种使用 subPath的相关机制也不能与其他卷有硬链接。2.2 为什么要引入Volume引入Volume的原因主要有两点:Kubernetes卷具有明确的生命周期与使用它的Pod相同。因此在Kubernetes中的卷可以比Pod中运行的任何容器生命周期都长并且可以在容器重启或者销毁之后保留数据。Kubernetes支持多种类型的卷并且Pod可以同时使用任意数量的卷。当一个Pod运行多个容器时各个容器可能需要共享一些文件诸如此类的需求都可以使用Volume解决2.3 Volume类型有哪些在传统架构中企业内可能有自己的存储平台比如NFS、Ceph、GlusterFS、Minio等。如果读者的环境在公有云可以使用公有云提供的NAS、对象存储等。在Kubernetes中Volume也支持配置以上存储用于挂载到Pod中实现数据的持久化。Kubernetes Volume支持的卷的类型有很多以下为常用的卷CephFSGlusterFSISCSICinderNFSRBDHostPath当然也支持一些Kubernetes独有的类型ConfigMap用于存储配置文件Secret用于存储敏感数据EmptyDir用于一个Pod内多个容器的数据共享PersistentVolumeClaim对PersistentVolume的申请2.4 Volume如何使用本文通过几个比较常用的类型的Volume配置演示一下Volume的使用示例1---通过emptyDir共享数据示例2---使用HostPath挂载宿主机文件示例3---挂载NFS至容器2.4.1 通过emptyDir共享数据EmptyDir是一个特殊的Volume类型与上述Volume不同的是如果删除PodemptyDir卷中的数据也将被删除所以一般emptyDir用于Pod中的不同Container共享数据比如一个Pod存在两个容器A和B容器A需要使用容器B产生的数据此时可以采用emptyDir共享数据类似的使用如Filebeat收集容器内程序产生的日志。默认情况下emptyDir 卷支持节点上的任何介质可能是 SSD、磁盘或网络存储具体取 决于自身的环境。可以将 emptyDir.medium 字段设置为 Memory让 Kubernetes 使用 tmpfs内 存支持的文件系统虽然 tmpfs 非常快但是 tmpfs 在节点重启时数据同样会被清除并且 设置的大小会被计入到 Container 的内存限制当中。1.定义一个yaml文件[rootk8s-master01 practice]# vim emptydir.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx namespace: default spec: selector: matchLabels: app: nginx template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 imagePullPolicy: IfNotPresent name: nginx volumeMounts: - mountPath: /opt name: share-volume - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 imagePullPolicy: IfNotPresent name: nginx2 command: - sh - -c - sleep 3600 volumeMounts: - mountPath: /mnt name: share-volume volumes: - name: share-volume emptyDir: {} #medium: Memory2.重新部署[rootk8s-master01 practice]# kubectl apply -f emptydir.yaml3.查看pod状态[rootk8s-master01 practice]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-d8f544fdd-qgllm 2/2 Running 0 12m4.验证-进入nginx的容器创建文件后在nginx2容器查看(1)进入nginx容器后进入/opt目录下创建123文件[rootk8s-master01 practice]# kubectl exec -it nginx-d8f544fdd-qgllm -c nginx -- sh rootnginx-d8f544fdd-qgllm:/# cd /opt rootnginx-d8f544fdd-qgllm:/opt# touch 123(2)进入nginx2容器后进入/mnt目录下查看123文件是否创建成功[rootk8s-master01 practice]# kubectl exec -it nginx-d8f544fdd-qgllm -c nginx2 -- bash rootnginx-d8f544fdd-qgllm:/# cd /mnt/ rootnginx-d8f544fdd-qgllm:/mnt# ls 1232.4.2 使用HostPath挂载宿主机文件hostPath 卷可将节点上的文件或目录挂载到 Pod 上用于 Pod 自定义日志输出或访问 Docker 内部的容器等。hostPath常用类型有如下取值行为默认选项意味着挂载 hostPath 卷之前不会执行任何检查DirectoryOrCreate如果给定的 path 不存在任何东西那么将根据需要创建一个权限为 0755 的空目录和 Kubelet 具有相同的组和权限Directory目录必须存在于给定的路径下FileOrCreate如果给定的路径不存储任何内容则会根据需要创建一个空文件权限设 置为 0644和 Kubelet 具有相同的组和所有权。File文件必须存在于给定路径中Socket在给定路径上必须存在的 UNIX 套接字CharDevice在给定路径上必须存在的字符设备BlockDevice在给定路径上必须存在的块设备hostPath注意事项有如下HostPath 卷可能会暴露特权系统凭据例如 Kubelet或特权 API例如容器运行时套接字可用于容器逃逸或攻击集群的其他部分。具有相同配置例如基于同一 PodTemplate 创建的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。下层主机上创建的文件或目录只能由 root 用户写入。 你需要在特权容器中以 root 身份运行进程或者修改主机上的文件权限以便容器能够写入hostPath卷。下面进行hostPath示例说明将主机的/etc/timezone文件挂载到 Pod 的/etc/timezone1.定义一个yaml文件[rootk8s-master01 practice]# vim emptydir-hostpath.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx namespace: default spec: selector: matchLabels: app: nginx template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 imagePullPolicy: IfNotPresent name: nginx volumeMounts: - mountPath: /opt name: share-volume - mountPath: /etc/timezone name: timezone - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 imagePullPolicy: IfNotPresent name: nginx2 command: - sh - -c - sleep 3600 volumeMounts: - mountPath: /mnt name: share-volume volumes: - name: share-volume emptyDir: {} #medium: Memory - name: timezone hostPath: path: /etc/timezone type: File2.重新部署[rootk8s-master01 practice]# kubectl apply -f emptydir-hostpath.yaml3.查看pod状态[rootk8s-master01 practice]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-85fdffcd78-f9pwz 2/2 Running 0 12m4.查看挂载情况观察到设置的nginx已成功进行挂载而未设置的nginx2未进行挂载[rootk8s-master01 practice]# kubectl exec nginx-85fdffcd78-f9pwz -c nginx -- cat /etc/timezone Asia/Shanghai[rootk8s-master01 practice]# kubectl exec nginx-85fdffcd78-f9pwz -c nginx2 – cat /etc/timezonecat: can’t open ‘/etc/timezone’: No such file or directory2.4.3 挂载NFS至容器详情参见 搭建nfs 存储示例在生产环境中考虑到数据的高可用性仍然不建议使用NFS作为后端存储。因为NFS存在单点故障很多企业并非对其实现高可用并且NFS的性能存在很大的瓶颈。所以生产中建议使用分布式存储在公有云中建议使用公有云提供的NAS存储来替代NFS并且NAS性能更好可用性更高。NFS作为一个比较流行的远端存储工具在非生产环境中是一个比较好用的选择可以快速地搭建使用。首先我们需要安装一下NFS1.每台机器安装NFS客户端$ yum install nfs-utils -y2.在k8s-node01(192.168.1.34)启动nfs[rootk8s-node01 ~]# systemctl start nfs-server在k8s-node01(192.168.1.34)查看nfs支持的版本[rootk8s-node01 ~]# cat /proc/fs/nfsd/versions-2 3 4 4.1 4.23.在k8s-node01(192.168.1.34)上创建一个共享目录[rootk8s-node01 ~]# mkdir -p /data/nfs/test_nfs4.在k8s-node01(192.168.134)编辑授权文件这里网段根据自己主机来定我这里网段是192.168.1.0/24[rootk8s-node01 ~]# vim /etc/exports/data/nfs/ 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)5.在k8s-node01(192.168.1.34)配置生效[rootk8s-node01 ~]# exportfs -r6.在k8s-node01(192.168.1.34)重新加载NFS[rootk8s-node01 ~]# systemctl reload nfs-server7.在k8s-master01上进行挂载测试[rootk8s-master01 ~]# mount -t nfs 192.168.1.34:/data/nfs /mnt/[rootk8s-master01 ~]# cd /mnt/[rootk8s-master01 mnt]# touch test1238.在k8s-node01(192.168.1.34)进行验证[rootk8s-node01 ~]# cd /data/nfs/[rootk8s-node01 nfs]# lstest123 test_nfs接下来我们对上面的测试进行卸载1.针对上诉测试进行卸载[rootk8s-master01 ~]# umount /mnt/最后和emptyDir、HostPath的配置方法类似NFS的Volume配置也是在Volumes字段中配置的和emptyDir不同的是NFS属于持久化存储的一种在Pod删除或者重启后数据依旧会存储在NFS节点上。1.在k8s-master01上定义一个yaml文件[rootk8s-master01 ~]# vim nfs.yamlapiVersion: apps/v1kind: Deploymentmetadata:labels:app: nginxname: nginxnamespace: defaultspec:selector:matchLabels:app: nginxtemplate:metadata:creationTimestamp: nulllabels:app: nginxspec:containers:- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2imagePullPolicy: IfNotPresentname: nginxvolumeMounts:- mountPath: /optname: share-volume- mountPath: /etc/timezonename: timezone- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2imagePullPolicy: IfNotPresentname: nginx2command:- sh- -c- sleep 3600volumeMounts:- mountPath: /mntname: share-volume- mountPath: /optname: nfs-volumevolumes:- name: share-volumeemptyDir: {}#medium: Memory- name: timezonehostPath:path: /etc/timezonetype: File- name: nfs-volumenfs:server: 192.168.1.34path: /data/nfs/test_nfs2.在k8s-master01重新部署[rootk8s-master01 ~]# kubectl replace -f nfs.yaml3.在k8s-master01查看pod状态[rootk8s-master01 ~]# kubectl get poNAME READY STATUS RESTARTS AGEnginx-5f974586bc-wv89n 2/2 Running 0 29s4.在k8s-master01以容器的方式进入pod,查看挂载已经成功[rootk8s-master01 ~]# kubectl exec -it nginx-5f974586bc-wv89n -c nginx2 – sh/ # df -ThFilesystem Type Size Used Available Use% Mounted onoverlay overlay 35.0G 4.5G 30.4G 13% /tmpfs tmpfs 64.0M 0 64.0M 0% /devtmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup/dev/mapper/centos-rootxfs 35.0G 4.5G 30.4G 13% /mnt192.168.1.34:/data/nfs/test_nfsnfs4 35.0G 3.6G 31.4G 10% /opt5.在k8s-master01挂载目录中创建文件[rootk8s-master01 ~]# kubectl exec -it nginx-5f974586bc-wv89n -c nginx2 – sh/ # cd /opt//opt # touch 111116.在k8s-node01上进行结果验证[rootk8s-node01 ~]# cd /data/nfs/test_nfs[rootk8s-node01 test_nfs]# ls11111注意:Kubernetes所有的节点都需要安装上nfs-utils才可以正常挂载NFS。三、PV和PVC3.1 什么是PV和PVC持久卷PersistentVolumePV是集群中的一块存储可以由管理员事先制备 或者使用存储类来动态制备。持久卷是集群资源就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样 也是使用卷插件来实现的只是它们拥有独立于任何使用PV的Pod的生命周期。注意PV没有命名空间限制持久卷申领PersistentVolumeClaimPVC表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源而PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源CPU 和内存同样 PVC 申领也可以请求特定的大小和访问模式 。注意PVC有命名空间限制3.2 为什么要引入PV和PVC虽然Volume已经可以接入大部分存储后端但是实际使用时还有诸多问题比如当某个数据卷不再被挂载使用时里面的数据如何处理?如果想要实现只读挂载如何处理如果想要只能有一个Pod挂载如何处理如果只允许某个Pod使用10G的空间如上所述对于很多复杂的需求Volume可能难以实现并且无法对存储卷的生命周期进行管理。为此Kubernetes引入了两个新的API资源PersistentVolume和PersistentVolumeClaim。PersistentVolume简称PV是由Kubernetes管理员设置的存储PersistentVolumeClaim简称PVC是对PV的请求表示需要什么类型的PV。下面介绍下引入的PV和PVC使用流程1.开发人员需要申请存储2.k8s管理员提前创建好不同的PV3.k8s管理人员创建PVC并告诉开发人员指定storageClassName或直接告诉开发人员创建PVC并指定storageClassName即可3.3 PV回收策略当用户不再使用其存储卷时他们可以从 API 中将 PVC 对象删除 从而允许该资源被回收再利用。PersistentVolume 对象的回收策略告诉集群 当其被从申领中释放时如何处理该数据卷。 目前数据卷可以被 Retained保留、Recycled回收或 Deleted删除。可以通过persistentVolumeReclaimPolicy: Recycle字段配置。1.Retain保留该策略允许手动回收资源当删除PVC时PV仍然存 在PV被视为已释放管理员可以手动回收卷。回收策略Retain使得用户可以手动回收资源。当 PersistentVolumeClaim 对象被删除时PersistentVolume 卷仍然存在对应的数据卷被视为已释放released。 由于卷上仍然存在这前一申领人的数据该卷还不能用于其他申领。 管理员可以通过下面的步骤来手动回收该卷删除 PersistentVolume 对象。与之相关的、位于外部基础设施中的存储资产 例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷在 PV 删除之后仍然存在。根据情况手动清除所关联的存储资产上的数据。手动删除所关联的存储资产。2.Recycle回收如果Volume插件支持Recycle策略会对卷执行rm - rf清理该PV并使其可用于下一个新的PVC。目前仅 NFS 和 HostPath 支持回收Recycle注意:回收策略Recycle已被废弃。取而代之的建议方案是使用动态制备。3.Delete删除如果Volume插件支持删除PVC时会同时删除PV 动态卷默认为Delete目前支持Delete的存储后端包括AWS EBS, GCE PD, Azure Disk, or OpenStack Cinder等。3.4 PV访问策略PersistentVolume 卷可以用资源提供者所支持的任何方式挂载到宿主系统上。因提供者驱动的能力不同每个 PV 卷的访问模式都会设置为对应卷所支持的模式值。 例如NFS 可以支持多个读写客户但是某个特定的 NFS PV 卷可能在服务器上以只读的方式导出。 每个 PV 卷都会获得自身的访问模式集合描述的是特定 PV 卷的能力。访问模式有1.ReadWriteOnce 可以被单节点以读写模式挂载命令行中可以被缩写为RWO。 2.ReadOnlyMany 可以被多个节点以只读模式挂载命令行中可以被缩写为ROX。 3.ReadWriteMany 可以被多个节点以读写模式挂载命令行中可以被缩写为RWX。 4.ReadWriteOncePod 只允许被单个Pod访问需要K8s 1.22以上版本并且是CSI 创建的PV才可使用注意:每个卷同一时刻只能以一种访问模式挂载即使该卷能够支持多种访问模式。目前卷插件支持的访问策略如下3.5 PV状态我们可以使用kubectl get pv命令查看PV状态[rootk8s-node01 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv-hostpath 10Gi RWO Retain Available hostpath 55s pv-nfs 5Gi RWO Recycle Available nfs-slow 28m常见的状态如下:1.Available 可用没有被PVC绑定的空闲资源。2.Bound 已绑定已经被PVC绑定。3.Released 已释放PVC被删除但是资源还未被重新使用。4.Failed 失败自动回收失败。3.6 PV配置示例在企业内可能存储很多不同类型的存储比如NFS、Ceph、GlusterFS等针对不同类型的后端存储具有不同的配置方式这也是对集群管理员的一种挑战因为集群管理员需要对每种存储都有所了解。接下来看一下几个常用的PV配置示例。3.6.1 基于NFS的PV首先我们需要安装一下NFS1.每台机器安装NFS客户端$ yum install nfs-utils -y2.在k8s-node01(192.168.1.34)启动nfs[rootk8s-node01 ~]# systemctl start nfs-server在k8s-node01(192.168.1.34)查看nfs支持的版本[rootk8s-node01 ~]# cat /proc/fs/nfsd/versions -2 3 4 4.1 4.23.在k8s-node01(192.168.1.34)上创建一个共享目录[rootk8s-node01 ~]# mkdir -p /data/nfs/test_nfs4.在k8s-node01(192.168.134)编辑授权文件这里网段根据自己主机来定我这里网段是192.168.1.0/24[rootk8s-node01 ~]# vim /etc/exports /data/nfs/ 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)5.在k8s-node01(192.168.1.34)配置生效[rootk8s-node01 ~]# exportfs -r6.在k8s-node01(192.168.1.34)重新加载NFS[rootk8s-node01 ~]# systemctl reload nfs-server7.在k8s-master01上进行挂载测试[rootk8s-master01 ~]# mount -t nfs 192.168.1.34:/data/nfs /mnt/ [rootk8s-master01 ~]# cd /mnt/ [rootk8s-master01 mnt]# touch test1238.在k8s-node01(192.168.1.34)进行验证[rootk8s-node01 ~]# cd /data/nfs/ [rootk8s-node01 nfs]# ls test123 test_nfs接下来我们对上面的测试进行卸载1.针对上诉测试进行卸载[rootk8s-master01 ~]# umount /mnt/最后进行NFS配置示例1.定义一个yaml文件[rootk8s-master01 pv]# vim pv-nfs.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-nfs spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: nfs-slow nfs: path: /data/nfs/test_nfs server: 192.168.1.34上面参数说明:capacity容量配置volumeMode:卷的模式目前支持Filesystem 文件系统 和 Block块其中Block类型需 要后端存储支持默认为文件系统accessModes该PV的访问模式,这里设置为RWO可以被单节点以读写模式挂载storageClassNamePV的类一个特定类型的PV 只能绑定到特定类别的PVCpersistentVolumeReclaimPolicy回收策略nfsNFS服务配置包括以下两个选项:pathNFS上的共享目录serverNFS的IP地址2.部署[rootk8s-master01 pv]# kubectl create -f pv-nfs.yaml3.结果验证[rootk8s-master01 pv]# kubectl get -f pv-nfs.yaml NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv-nfs 5Gi RWO Recycle Available nfs-slow 16s3.6.2 基于HostPath的PV当公司目前没有可靠性的存储但是想要部署k8s集群中应用的数据不丢失这时把宿主机目录直接挂载到Pod,Pod的数据直接落在宿主机上。接下来介绍基于HostPath的PV:1.在master01节点上创建挂载目录[rootk8s-master01 pv]# mkdir -p /mnt/data2.定义一个yaml文件[rootk8s-master01 pv]# vim pv-hostpath.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-hostpath labels: type: local spec: storageClassName: hostpath capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: /mnt/data上面参数说明:capacity容量配置accessModes该PV的访问模式,这里设置为RWO可以被单节点以读写模式挂载storageClassNamePV的类一个特定类型的PV 只能绑定到特定类别的PVChostPathhostPath配置path/mnt/data其中/mnt/data为宿主机的目录3.部署[rootk8s-master01 pv]# kubectl create -f pv-hostpath.yaml4.结果验证[rootk8s-master01 pv]# kubectl get -f pv-hostpath.yaml NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE task-pv-volume 10Gi RWO Retain Available hostpath 26s3.6.3 基于Ceph RBD的PVCeph可能是目前企业内最常用的一种分布式存储之一同时支持文件系统、块存储及对象存储和上述NFS和HostPath相比具有高可用性和读写高效性。接下来看一下Ceph RBD类型的PV配置1.定义一个yaml文件[rootk8s-master01 pv]# vim pv-cephrbd.yaml apiVersion: v1 kind: PersistentVolume metadata: name: ceph-rbd-pv spec: capacity: storage: 1Gi storageClassName: ceph-fast accessModes: - ReadWriteOnce rbd: monitors: - 192.168.1.123:6789 - 192.168.1.124:6789 - 192.168.1.125:6789 pool: rbd image: ceph-rbd-pv-test user: admin secretRef: name: ceph-secret fsType: ext4 readOnly: false上面参数说明monitorsCeph的monitor节点的IPpool所用Ceph Pool的名称可以使用ceph osd pool ls查看imageCeph块设备中的磁盘映像文件可以使用rbd create POOL_NAME/IMAGE_NAME--size 1024创建使用rbd list POOL_NAME查看userRados的用户名默认是adminsecretRef用于验证Ceph身份的密钥fsType文件类型可以是Ext4、XFS等readOnly是否是只读挂载注意:Ceph的Pool和Image需要提前创建才能使用。虽然前面讲述了RBD类型的PV配置示例但是在实际使用时大多数Ceph存储的使用都是采用动态存储的方式很少通过静态方式去管理。同时Kubernetes所有的节点都需要安装ceph-common才能正常挂载Ceph.2.部署[rootk8s-master01 pv]# kubectl create -f pv-cephrbd.yaml3.结果验证[rootk8s-master01 pv]# kubectl get -f pv-cephrbd.yaml3.7 PVC绑定PV在工作场景中k8s管理员会碰到两种场景:场景一:k8s管理员成功创建好PV请求开发人员申请该PV并创建PVC配置到Volumes配置一个PVC类型的存 储并指定PVC的名字是xxx即可场景二:k8s管理员成功创建好PV和PVC请求开发人员在Volumes指定PVC的名字是xxx即可注意:PVC和PV进行绑定的前提条件是一些参数必须匹配比如accessModes、storageClassName、volumeMode都需要相同并且PVC的storage需要小于等于PV的storage配置。下面进行PVC挂载示例:首先创建PV1.定义一个yaml文件[rootk8s-master01 pv]# vim pv-nfs.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-nfs spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: nfs-slow nfs: path: /data/nfs/test_nfs server: 192.168.1.34上面参数说明:capacity容量配置volumeMode:卷的模式目前支持Filesystem 文件系统 和 Block块其中Block类型需 要后端存储支持默认为文件系统accessModes该PV的访问模式,这里设置为RWO可以被单节点以读写模式挂载storageClassNamePV的类一个特定类型的PV 只能绑定到特定类别的PVCpersistentVolumeReclaimPolicy回收策略nfsNFS服务配置包括以下两个选项:pathNFS上的共享目录serverNFS的IP地址2.部署[rootk8s-master01 pv]# kubectl create -f pv-nfs.yaml3.结果验证[rootk8s-master01 pv]# kubectl get -f pv-nfs.yaml NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv-nfs 5Gi RWO Recycle Available nfs-slow 16s其次创建PVC1.定义一个名为pvc-nfs.yaml 的yaml文件[rootk8s-master01 pv]# vim pvc-nfs.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nfs-pvc-claim spec: storageClassName: nfs-slow #要求PV一致 accessModes: - ReadWriteOnce resources: requests: storage: 3Gi #小于等于PV大小注意:PVC有命名空间限制这里默认是default空间2.部署[rootk8s-master01 pv]# kubectl create -f pvc-nfs.yaml3.结果验证观察到状态已更改为Bound但此时并不代表可用[rootk8s-master01 pv]# kubectl get -f pvc-nfs.yaml NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE nfs-pvc-claim Bound pv-nfs 5Gi RWO nfs-slow 60s4.查看PV状态,此时PV状态由原来的Available变为Bound 但此时并不代表可用[rootk8s-master01 pv]# kubectl get pv pv-nfs NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv-nfs 5Gi RWO Recycle Bound default/nfs-pvc-claim nfs-slow 79m最后创建Pod1.在k8s-master01上定义一个名为pvc-nfs-pod.yaml的yaml文件[rootk8s-master01 pv]# vim pvc-nfs-pod.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx namespace: default spec: replicas: 2 revisionHistoryLimit: 10 selector: matchLabels: app: nginx strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 type: RollingUpdate template: metadata: creationTimestamp: null labels: app: nginx spec: volumes: - name: task-pv-storage persistentVolumeClaim: claimName: nfs-pvc-claim containers: - env: - name: TZ value: Asia/Shanghai - name: LANG value: C.UTF-8 image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 imagePullPolicy: IfNotPresent name: nginx volumeMounts: - mountPath: /usr/share/nginx/html name: task-pv-storage2.在k8s-master01上开始部署[rootk8s-master01 pv]# kubectl create -f pvc-nfs-pod.yaml3.在k8s-master01上查看pod状态[rootk8s-master01 pv]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-59fdd74bd4-2c2hk 1/1 Running 0 19s nginx-59fdd74bd4-dlfgf 1/1 Running 0 19s4.在k8s-master01上以容器的方式进入pod,修改文件内容用于测试另一个Pod是否会同步[rootk8s-master01 pv]# kubectl exec -it nginx-59fdd74bd4-2c2hk -- sh / # cd /usr/share/nginx/html/ /usr/share/nginx/html # echo test_nfs /usr/share/nginx/html/index.html /usr/share/nginx/html # cat /usr/share/nginx/html/index.html test_nfs5.继续在k8s-master01上以容器的方式进入另一个pod后查看已经同步[rootk8s-master01 pv]# kubectl exec nginx-59fdd74bd4-dlfgf -- cat /usr/share/nginx/html/index.html test_nfs3.8 PVC创建和挂载失败的原因3.8.1 PVC一直Pending的原因1.PVC的空间申请大小大于PV的大小2.PVC的StorageClassName没有和PV的一致3.PVC的accessModes和PV的不一致3.8.2 挂载PVC的Pod一直处于Pending1.PVC没有创建成功/PVC不存在2.PVC和Pod不在同一个Namespace四、存储分类1.文件存储 一些数据可能需要被多个节点使用比如用户的头像、用户上传的文 件等实现方式NFS、NAS、FTP、CephFS等。2.块存储 一些数据只能被一个节点使用或者是需要将一块裸盘整个挂载使用 比如数据库、Redis等实现方式Ceph、GlusterFS、公有云。3.对象存储 由程序代码直接实现的一种存储方式云原生应用无状态化常用的实现方式实现方式一般是符合S3协议的云存储比如AWS的S3存储、Minio、七牛云等。参考初识PV和PVC