初学 K8s 存储时,很多新手都会被 PV、PVC 的概念绕晕:什么是 PV?什么是 PVC?两者怎么绑定?NFS 和它们是什么关系?今天结合我自己的完整实操流程,用通俗的语言,一次性讲透 PV 与 PVC 的核心逻辑,新手跟着做就能上手,彻底搞懂 K8s 持久化存储!

先抛核心结论(面试必背,直接背):PV(持久卷)是 K8s 集群级的公共存储资源,由管理员预先创建,独立于 Pod 生命周期;PVC(持久卷申领)是 Pod 对存储的 “申请单”,Pod 不能直接用 PV,必须通过 PVC 绑定 PV 后,才能挂载使用;绑定后 PV 会被 PVC 独占,数据随 PV 永久保留,不会随 Pod 删除而丢失。


一、先搞懂核心概念(通俗大白话)

1. PV(PersistentVolume,持久卷)

  • 本质:集群里的 “公共硬盘”,由管理员提前创建,不归任何节点、任何 Pod 独有。
  • 核心特性:集群公共资源,由 kube-controller-manager 统一管理,API Server 仅存储配置,kubelet 仅负责挂载;生命周期独立,Pod 删除后 PV 和数据依然保留。
  • 常见后端:NFS、Ceph、云厂商硬盘(阿里云 / 腾讯云)等,本次实验用 NFS 模拟共享存储。

2. PVC(PersistentVolumeClaim,持久卷申领)

  • 本质:Pod 对 PV 的 “申请单”,就像你去银行办业务,不能直接用银行的保险柜,必须先填申请单。
  • 绑定规则:一对一绑定,PVC 申请的存储容量只要≤PV 容量,就能匹配绑定;绑定后 PV 会被该 PVC 独占,无法再被其他 PVC 使用,哪怕只申请了 1G,绑定 5G 的 PV 后,剩下的 4G 也不能再被使用。

3. 两者关系(一句话串起来)

NFS(真实存储)→ PV(集群公共硬盘)→ PVC(Pod 的申请单)→ Pod(挂载使用存储)


二、完整实操流程(纯 bash 命令,可直接复制运行)

本次实验用 NFS 作为后端存储,创建 PV、PVC,再用 Nginx Pod 挂载验证,全程纯 bash 命令,新手零障碍上手。

步骤 1:搭建 NFS 服务器(真实存储,Master 节点执行)

先在 Master 节点搭建 NFS 共享目录,作为 PV 的真实存储位置:

# 安装NFS服务端
apt install nfs-kernel-server -y

# 创建共享目录
mkdir /nfsshare
chmod 777 /nfsshare -R

# 配置NFS共享权限(允许所有节点读写)
echo '/nfsshare *(rw,sync,no_subtree_check,no_root_squash)' >> /etc/exports

# 启动并设置开机自启
systemctl enable nfs-server --now

# 验证NFS共享配置是否生效
exportfs -rav
showmount -e localhost

步骤 2:安装 NFS 客户端(所有 Worker 节点执行)

集群所有节点都需要安装 NFS 客户端,才能挂载 NFS 共享目录:

# 安装NFS客户端(所有Worker节点执行)
apt install nfs-common -y

步骤 3:创建 PV(集群公共硬盘,Master 节点执行)

通过 kubectl apply -f 创建 PV,这里用cat >方式写入配置文件,再执行创建命令:

# 1. 写入PV配置文件(定义5G容量的NFS类型PV)
cat > pv.yml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv
  labels:
    pvname: nfspv
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /nfsshare
    server: 192.168.30.130  # 替换为你的Master节点IP
EOF

# 2. 创建PV
kubectl create -f pv.yml

# 3. 查看PV状态(确认状态为Available)
kubectl get pv

步骤 4:创建 PVC(Pod 的存储申请单,Master 节点执行)

创建 PVC,申请 1G 存储,通过标签选择器匹配上面的 nfspv:

# 1. 写入PVC配置文件(申请1G存储,匹配nfspv)
cat > pvc.yml <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi
  storageClassName: slow
  selector:
    matchLabels:
      pvname: "nfspv"
EOF

# 2. 创建PVC
kubectl create -f pvc.yml

# 3. 查看PVC状态(确认状态为Bound,已成功绑定nfspv)
kubectl get pvc

此时你会发现,PVC 显示的容量是 5Gi,而不是申请的 1Gi—— 这是正常现象,因为 PV 是不可分割的整体,绑定后会被 PVC 独占全部容量。

步骤 5:创建 Pod 挂载 PVC(验证存储使用,Master 节点执行)

创建 Nginx Pod,将 PVC 挂载到网页根目录,验证数据读写:

# 1. 写入Pod配置文件(挂载PVC到Nginx网页目录)
cat > pvcuse.yml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: httpd
      imagePullPolicy: IfNotPresent
      ports:
        - name: web
          containerPort: 80
      volumeMounts:
      - mountPath: "/usr/local/apache2/htdocs"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim
EOF

# 2. 创建Pod
kubectl create -f pvcuse.yml

# 3. 查看Pod状态(确认处于Running状态)
kubectl get -f pvcuse.yml -o wide

步骤 6:验证数据持久化(核心步骤)

在 NFS 共享目录写入网页文件,访问 Pod 验证是否能读取,再删除 Pod 验证数据是否保留:

# 1. 在NFS共享目录写入测试文件
echo pvctest! > /nfsshare/index.html

# 2. 访问Pod IP,验证数据是否读取成功(替换为你的Pod IP)
curl http://172.16.245.19

# 3. 删除Pod,验证数据是否保留
kubectl delete -f pvcuse.yml

# 4. 重新查看NFS目录,数据依然存在
cat /nfsshare/index.html

三、核心知识点详解(面试必背)

1. PV 的 4 种访问模式

定义了卷的挂载权限和范围,本次实验用的是 ReadWriteOnce:

  • ReadWriteOnce(RWO):卷仅能被单个节点以读写方式挂载,同一节点上的多个 Pod 可共享访问;
  • ReadOnlyMany(ROX):卷可被多个节点以只读方式挂载,所有节点的 Pod 仅能读取数据;
  • ReadWriteMany(RWX):卷可被多个节点以读写方式挂载,NFS、Ceph 等存储支持该模式;
  • ReadWriteOncePod(RWOP):K8s 1.23 + 新增,仅能被单个 Pod 以读写方式挂载,彻底避免数据竞争。

2. PV 的 3 种回收策略

定义了 PVC 删除后,PV 和数据的处理方式,本次实验用的是 Retain:

  • Retain(保留):PVC 删除后,PV 状态变为 Released,数据和 PV 均保留,需手动清理后才能复用;
  • Delete(删除):PVC 删除后,自动删除 PV 和后端存储数据(云厂商存储、CSI 存储支持);
  • Recycle(废弃):旧版策略,PVC 删除后清空卷内数据,新版 K8s 已不推荐使用。

3. PV 的生命周期状态

  • Available:空闲状态,未被任何 PVC 绑定;
  • Bound:已被 PVC 绑定,处于使用中;
  • Released:PVC 已删除,PV 等待回收;
  • Failed:自动回收操作失败,需管理员处理。

四、新手常见误区避坑

  1. 误区 1:PVC 申请 1G,PV 是 5G,只能用 1G?纠正:不能!PV 是不可分割的整体,绑定后 PVC 会独占全部 5G 容量,剩下的 4G 无法再被其他 PVC 使用。

  2. 误区 2:删除 Pod,PV 和数据会被删除?纠正:不会!PV 生命周期独立于 Pod,删除 Pod 只会解除 PVC 与 Pod 的挂载,PVC 和 PV 依然存在,数据永久保留在 NFS 服务器上。

  3. 误区 3:PVC 可以跨节点共享同一个 PV?纠正:不能!PVC 与 PV 是一对一绑定,一个 PV 只能被一个 PVC 绑定,一个 PVC 也只能被一个 Pod 挂载(RWO 模式下)。


五、实验清理(按需执行)

实验完成后,可按需求清理资源,保留 NFS 共享目录可复用:

# 1. 删除Pod、PVC、PV
kubectl delete -f pvcuse.yml
kubectl delete -f pvc.yml
kubectl delete -f pv.yml

# 2. 可选:清理NFS共享目录(谨慎操作,避免删除有用数据)
rm -rf /nfsshare/*

六、总结

PV 与 PVC 是 K8s 实现持久化存储的核心,核心逻辑就是 “公共硬盘(PV)+ 申请单(PVC)+ 挂载使用(Pod)”,数据随 PV 永久保留,不会随 Pod 删除而丢失。本次实验用 NFS 模拟后端存储,完整演示了 PV 与 PVC 的创建、绑定、使用和验证流程,新手跟着做就能快速掌握。

如果在实操过程中遇到 PV 无法绑定、Pod 无法挂载、NFS 访问失败等问题,欢迎在评论区留言,我会一一回复!觉得有用的话,记得点赞 + 收藏,关注我,后续分享更多 K8s 存储干货~

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐