K8s PV和PVC持久化存储详解

 更新时间:2025年08月14日 16:59:27   作者:大新屋  
Kubernetes PV由管理员创建,支持多种存储类型,提供生命周期管理,PVC请求PV资源,需匹配大小、存储类和访问模式,并在同一命名空间,回收策略包括Retain、Delete和Recycle,生产环境建议使用NAS而非NFS

提示: Kubernetes 官网PV文档说明:https://kubernetes.io/docs/concepts/storage/persistent-volumes

提示: PV正常情况是由K8s管理员创建,PV是没有namespace命名空间限制

  • PersistentVolume 简称PV,是由Kubernetes管理员设置的存储,可以配置Ceph、NFS、GlusterFs等常用存储配置,相对于Volume配置,提供了更多的功能,比如生命周期的管理、大小的限制。PV分为静态和动态。
  • PersistentVolumeClaim 简称PVC,是对存储PV的请求(调用)。

PVC调用PV流程图

一、PV策略

1、PV回收策略

persistentVolumeReclaimPolicy参数配置pv回收策略有以下几种方法:

  • Retain 保留数据,需要管理员手动回收资源,当删除PVC时,PV仍然存在,PV被视为已释放,管理员可以手动回收卷。手动创建的PV默认值为Retain。
  • Delete 删除数据,如果Volume插件支持,删除PVC时会同时删除PV,目前支持Detele的存储后端包括AWS EBS, GCE PD,Azure Disk, OpenStack Cinder等。动态创建的PV默认值为Delete。
  • Recycle(已过时) 回收数据,如果Volume插件支持,当删除PV时,该策略会对卷执行rm -rf清理该PV,并使其可用于下一个新PVC,目前只有NFS和HostPath支持该策略,该策略不推荐使用。

2、PV访问策略

  • ReadWriteOnce(RWO) 可以被单节点以读写模式挂载,命令行中可以被缩写为 RWO
  • ReadOnlyMany(ROX) 可以被多个节点以只读模式挂载,命令行中可以被缩写为 ROX
  • ReadWriteMany(RWX) 可以被多个节点以读写模式挂载,命令行中可以被缩写为RWX
  • ReadWriteOncePod(RWOP) 可以被单个Pod以读写模式挂载,命令行中可以被缩写为RWXP(只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本)

3、PV访问策略支持的存储类型

提示:Kubenetes官方文档说明 https://kubernetes.io/docs/concepts/storage/persistent-volumes

4、存储的分类

  • 文件存储 一些数据可能需要被多个节点使用,比如用户的头像、用户上传的文件等,实现方式:NFS、NAS、FTP、CephFS等。(NFS\FTP生产系统不推荐使用)
  • 块存储 一些数据只能被一个节点使用,或者是需要将一块裸盘整个挂载使用,比如MySQL数据库、Redis等,实现方式:Ceph、GlusterFs、公有云
  • 对象存储 由程序代码直接实现的一种存储方式,云原生应用无状态化常用的实现方式,实现方式:一般是符合S3协议的云存储,比如AWS的S3存储、Minio等

5、PV参数说明

apiVersion: v1                           # 填写API资源版本号,通过kubectl api-resources | grep PersistentVolume命令查询API资源版本号
kind: PersistentVolume                   # 指定资源类型,PersistentVolume资源类型是PersistentVolume
metadata:                                # 包含PersistentVolume元数据
  name: nfs-pv                           # 自定义PersistentVolume名称
  labels:                                # 设置PersistentVolume标签
    type: nfs-pv                         # 自定义PersistentVolume标签名称
  namespace: default                     # 指定PersistentVolume的命名空间,默认default
spec:                                    # 定义PersistentVolume规格
  capacity:                              # 限制存储容量大小,NFS不支持该参数,默认不限制
    storage: 5Gi                         # 限制存储容量为5GB
  volumeMode: Filesystem                 # 定义PV的卷模式(存储类型),支持Filesystem(文件系统)或Block(块设备), 其中Block类型需要后端存储支持,默认值Filesystem(文件系统)
  accessModes:                           # 定义PV的卷访问模式(PV访问策略),支持ReadWriteOnce(RWO)、ReadOnlyMany(ROX) 、ReadWriteMany(RWX)、ReadWriteOncePod(RWOP)
    - ReadWriteOnce                      # 设置ReadWriteOnce,只允许单个节点以读写模式挂载
  persistentVolumeReclaimPolicy: Retain  # 定义PV的卷回收策略,支持Retain、Recycle、Delete,手动创建PV默认值Retain,动态创建PV默认值Delete
  storageClassName: nfs-slow             # 定义PV存储类名称,方便PVC调用使用,与PVC的spec.storageClassName参数值匹配
  nfs:                                   # 定义PV类型,当前设置为NFS类似
    server: 172.20.236.210               # 设置NFS服务器的IP地址
path: /nfs                               # 设置NFS服务器挂载目录

6、PVC参数说明

apiVersion: v1                           # 填写API资源版本号,通过kubectl api-resources | grep PersistentVolumeCliam命令查询API资源版本号
kind: PersistentVolumeClaim              # 指定资源类型,PersistentVolumeCliam资源类型是PersistentVolumeCliam
metadata:                                # 包含PersistentVolumeCliam元数据
  name: nfs-pvc                          # 自定义PersistentVolumeCliam名称
  labels:                                # 设置PersistentVolumeCliam标签
    type: nfs-pvc                        # 自定义PersistentVolumeCliam标签名称
  namespace: default                     # 指定PersistentVolumeCliam的命名空间,默认default
spec:                                    # 定义PersistentVolumeCliam规格
  storageClassName: nfs-slow             # 定义PVC调用的存储类名称,与PersistentVolume的spec.storageClassName参数值匹配
  accessModes:                           # 定义PVC的卷访问模式(PV访问策略),支持ReadWriteOnce(RWO)、ReadOnlyMany(ROX) 、ReadWriteMany(RWX)、ReadWriteOncePod(RWOP),此值要与请求的PV的spec.accessModes参数值匹配
    - ReadWriteOnce                      # 设置ReadWriteOnce,只允许单个节点以读写模式挂载,此值要与请求的PV的spec.accessModes参数值匹配
  resources:                             # 定义资源请求和限制
    requests:
      storage: 3Gi                       # 定义资源请求磁盘容量大小,当前3GB

7、PV和PVC使用注意事项

(1)、PVC申请的空间大小不能大于PV的大小

(2)、PVC的spec.storageClassName参数值必须与PV的spec.storageClassName参数值一样

(3)、PVC的spec.accessMode参数值必须与PV的spec.accessMode参数值一样

(4)、一个PV只能被一个PVC请求调用使用,PVC和Pod必须在同一个Namespace命令空间下

二、创建PV(NFS)

提示: 生产系统不推荐使用NFS,推荐使用NAS,NFS是存在单点故障,NAS可配置高可用

1、创建PV(NFS)

### CentOS系统安装NFS服务端(建议把NFS服务端安装到K8s集群之外的服务器上,不要安装到K8s集群任意的节点上)
mkdir -p /nfs
yum install -y nfs-utils rpcbind
cat > /etc/exports << 'EOF'
/nfs *(rw,sync,insecure,no_subtree_check,no_root_squash)
EOF
systemctl start rpcbind
systemctl start nfs
systemctl enable rpcbind
systemctl enable nfs
systemctl status rpcbind
systemctl status nfs
showmount -e localhost

### k8s集群选择K8s-node01节点安装NFS客户端,测试挂载并卸载挂载
mkdir -p /nfs
apt install -y nfs-common
systemctl start rpcbind
systemctl enable rpcbind
systemctl status rpcbind
showmount -e 172.20.236.210
mount 172.20.236.210:/nfs /nfs
df -h
umount /nfs

### 创建PV
mkdir -p /data/yaml/pv
cat > /data/yaml/pv/nfs-pv.yaml << 'EOF'
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
  labels:
    type: nfs-pv
  namespace: default
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs-slow
  nfs:
    server: 172.20.236.210
    path: /nfs
EOF

kubectl create -f /data/yaml/pv/nfs-pv.yaml

### 查看PV
kubectl get pv -n default -owide
kubectl get pv -n default -oyaml
# 查看PV的STATUS状态说明
Available    # 可用,没有被PVC绑定的空闲资源
Bound        # 已绑定,已经被PVC绑定
Released     # 已释放,PV被删除,但是资源还未被重新使用
Failed       # 失败,自动回收失败

2、创建PVC并调用PV

### 创建PVC调用PV
cat > /data/yaml/pv/nfs-pvc.yaml << 'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
  labels:
    type: nfs-pvc
  namespace: default
spec:
  storageClassName: nfs-slow
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi
EOF

kubectl create -f /data/yaml/pv/nfs-pvc.yaml

### 查看PVC状态
kubectl get pvc -n default
kubectl get pvc -n default -owide
kubectl get pvc -n default -oyaml

### 此时查看PV状态STATUS显示绑定
kubectl get pv -n default –owide

3、创建Deployment调用PVC

### K8s集群k8s-node01节点打标签并查看
kubectl label node k8s-node01 run=nfs
get node --show-labels -l run=nfs -owide

### 创建Deployment调用PVC(Pod必须指定运行k8s-node01节点上,否则运行在其它K8s节点都会失败)
cat > /data/yaml/pv/nginx-deploy-pvc.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy-pvc
  name: nginx-deploy-pvc
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      nodeSelector:
        run: nfs
      containers:
      - image: registry.cn-shenzhen.aliyuncs.com/dockerghost/nginx:1.26
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: pv-nfs-storage
      volumes:
      - name: pv-nfs-storage
        persistentVolumeClaim:
          claimName: nfs-pvc
EOF

kubectl create -f /data/yaml/pv/nginx-deploy-pvc.yaml
kubectl get deploy -n default
kubectl get pods -n default -owide

### 登录NFS服务器在NFS挂载的共享目录创建一个文件
echo "Welcome to Nginx World" > /nfs/index.html
ls -l /nfs/index.html
cat /nfs/index.html

### 登录两个Pod资源的nginx容器测试
kubectl get pods -n default -owide
kubectl exec -n default nginx-deploy-pvc-659d6c64b9-b5d4b -- cat /usr/share/nginx/html/index.html
kubectl exec -n default nginx-deploy-pvc-659d6c64b9-bj446 -- cat /usr/share/nginx/html/index.html
curl 172.30.85.201
curl 172.30.85.202

### PVC删除操作:先删除Deployment,再删除PVC,最后删除PV
kubectl delete -f /data/yaml/pv/nginx-deploy-nfs.yaml
kubectl delete -f /data/yaml/pv/nfs-pvc.yaml
kubectl delete -f /data/yaml/pv/nfs-pv.yaml

三、创建PV(hostPath)

提示: 在使用PV(hostPath)挂载到任意一个K8s集群节点,推荐给选定的K8s集群节点打上标签,把PV(hostPath)挂载到选定的K8s集群节点

1、创建PV(hostPath)

### 创建PV
### spec.hostPath.type参数值为DirectoryOrCreate表示如果宿主机给定/mnt/data 路径不存在,那么将自动创建一个权限为0755 的空目录,和Kubelet 具有相同的组和权限
mkdir -p /data/yaml/pv
cat > /data/yaml/pv/pv-hostpath.yaml << 'EOF'
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-hostpath
  namespace: default
  labels:
    type: pv-local
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  storageClassName: hostpath-ide
  hostPath:
    path: "/mnt/data"
    type: DirectoryOrCreate
EOF

kubectl create -f /data/yaml/pv/pv-hostpath.yaml
kubectl get pv -n default
kubectl get pv -n default -owide
kubectl get pv -n default -oyaml

2、创建PVC调用PV

### 创建PVC调用PV
cat  > /data/yaml/pv/pvc-hostpath.yaml << 'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-hostpath
  namespace: default
spec:
  storageClassName: hostpath-ide
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
EOF

kubectl create -f /data/yaml/pv/pvc-hostpath.yaml
kubectl get pvc -n default
kubectl get pvc -n default -owide
kubectl get pvc -n default -oyaml
kubectl get pv -n default

3、创建Deployment调用PVC

### 创建Deployment调用PVC 
cat > /data/yaml/pv/nginx-deploy-hostpath.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy-hostpath
  name: nginx-deploy-hostpath
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - image: registry.cn-shenzhen.aliyuncs.com/dockerghost/nginx:1.26
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: pv-hostpath-storage
      volumes:
      - name: pv-hostpath-storage
        persistentVolumeClaim:
          claimName: pvc-hostpath
EOF

kubectl create -f /data/yaml/pv/nginx-deploy-hostpath.yaml
kubectl get deploy -n default
kubectl get pods -n default -owide

### 查看每个Pods资源中nginx容器分配置到的K8s集群节点宿主机是否自动创建了/mnt/data目录
kubectl get pods -owide

### 登录K8s集群nginx容器运行的K8s节点创建测试文件
echo "Welcome to Nginx World" > /mnt/data/index.html    
cat /mnt/data/index.html

### 登录两个Pod资源的nginx容器测试
kubectl get pods -n default -owide
kubectl exec -n default nginx-deploy-hostpath-bb7ddf9d6-87gn6 -- cat /usr/share/nginx/html/index.html
kubectl exec -n default nginx-deploy-hostpath-bb7ddf9d6-r57tl -- cat /usr/share/nginx/html/index.html
curl 172.30.135.137
curl 172.30.122.180

### PVC删除操作:先删除Deployment,再删除PVC,最后删除PV
kubectl delete -f /data/yaml/pv/nginx-deploy-hostpath.yaml
kubectl delete -f /data/yaml/pv/pvc-hostpath.yaml
kubectl delete -f /data/yaml/pv/pvc-hostpath.yaml

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • k8s中容器创建的全过程实践

    k8s中容器创建的全过程实践

    这篇文章主要介绍了k8s中容器创建的全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-07-07
  • Kubernetes k8s configmap 容器技术解析

    Kubernetes k8s configmap 容器技术解析

    这篇文章主要为大家介绍了k8s configmap 容器技术解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • K8s学习之Pod的定义及详细资源调用案例

    K8s学习之Pod的定义及详细资源调用案例

    Kubernetes将所有内容抽象为资源,通过操作资源管理集群,核心单元是Pod,通过控制器管理Pod,资源管理分为命令式对象管理、命令式对象配置和声明式对象配置,各有适用场景,需要的朋友可以参考下
    2024-09-09
  • Kubernetes(k8s)常用yaml配置和注释方式

    Kubernetes(k8s)常用yaml配置和注释方式

    这篇文章主要介绍了Kubernetes(k8s)常用yaml配置和注释方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • 一篇文章搞懂K8S高级特性

    一篇文章搞懂K8S高级特性

    这篇文章主要给大家介绍了关于K8S高级特性的相关资料,文中通过时实例代码以及图文介绍的非常详细,对大家学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-11-11
  • k8s容器状态Terminating无法删除的问题及解决

    k8s容器状态Terminating无法删除的问题及解决

    这篇文章主要介绍了k8s容器状态Terminating无法删除的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-07-07
  • kubectl 命令详解

    kubectl 命令详解

    这篇文章主要介绍了kubectl 命令的相关资料,包括常用命令,基本命令和使用说明,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2025-04-04
  • windows下搭建Consul集群

    windows下搭建Consul集群

    这篇文章介绍了windows下搭建Consul集群的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 基于云服务MRS构建DolphinScheduler2调度系统的案例详解

    基于云服务MRS构建DolphinScheduler2调度系统的案例详解

    这篇文章主要介绍了基于云服务MRS构建DolphinScheduler2调度系统,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • kubernetes存储之GlusterFS集群详解

    kubernetes存储之GlusterFS集群详解

    最近工作中用到了GlusterFS作为Kubernetes的存储,这篇文章主要给大家介绍了关于kubernetes存储之GlusterFS集群的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-04-04

最新评论