当前位置: 首页 > news >正文

k8s中PV 与 PVC

目录

1、容器存储的短暂性问题

2、emptyDir 存储卷

2.1 特点

2.2 案例

2.3 验证

3、hostPath 存储卷

3.1 特点

3.2 案例

3.3 访问测试

4、NFS 网络共享存储卷

4.1 特点

4.2 案例

4.2.1 部署 NFS 服务端(stor01 节点)

4.2.2 所有 Node 节点安装 NFS 客户端(关键)

4.2.3 创建 NFS 存储卷的 Pod(master 节点)

4.2.4 验证数据共享与持久化

5、PV 与 PVC 持久化机制

5.1 PV 与 PVC 的核心概念

5.2 PV 与 PVC 的生命周期

5.3 PV 的关键配置参数

关键参数说明

5.4 PVC 的关键配置参数

5.5 PV 与 PVC 的匹配规则

6、NFS + PV + PVC 实战(静态 PV)

6.1 准备 NFS 存储(stor01 节点)

6.2 定义 PV(master 节点)

6.3 定义 PVC + Pod(master 节点)

6.4 验证数据持久化与共享

7、StorageClass + NFS 动态存储(自动创建 PV)

7.1 核心原理

7.2 部署步骤

7.2.1 准备 NFS 服务端(stor01 节点)

7.2.2 创建 RBAC 权限(master 节点)

7.2.3 部署 NFS Provisioner(master 节点)

7.2.4 创建 StorageClass(master 节点)

7.2.5 测试动态存储(创建 PVC + Pod)

7.3 验证动态存储功能

7.3.1 验证 PVC 绑定与 PV 自动创建

7.3.2 验证 NFS 目录自动创建

7.3.3 验证数据同步

7.3.4 验证自动回收

8、常见问题与排查

8.1 PV 无法绑定 PVC

8.2 Pod 卡在 ContainerCreating

8.3 动态 PV 创建失败(K8s 1.20+)

9、总结

核心选型建议


1、容器存储的短暂性问题

容器的文件系统是临时性的:

  • 容器崩溃重启后,容器内数据会丢失;
  • 同一个 Pod 内的多个容器无法直接共享文件。

Kubernetes 的 Volume 抽象 解决了这两个问题:通过 Pause 容器 让多个容器共享同一个 Volume,从而实现文件共享与持久化。


2、emptyDir 存储卷

2.1 特点

  • Pod 调度到节点时自动创建;
  • Pod 删除后数据也随之销毁;
  • 仅适合临时缓存或容器间数据共享。

2.2 案例

mkdir /opt/volumes
cd /opt/volumesvim pod-emptydir.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-emptydirnamespace: defaultlabels:app: myapptier: frontend
spec:containers:- name: myappimage: ikubernetes/myapp:v1imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80# 定义容器挂载内容volumeMounts:# 使用的存储卷名称,需与下方 volumes 字段的 name 值一致- name: html# 挂载至容器中哪个目录mountPath: /usr/share/nginx/html/- name: busyboximage: busybox:latestimagePullPolicy: IfNotPresentvolumeMounts:- name: html# 在容器内定义挂载存储名称和挂载路径mountPath: /data/command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']# 定义存储卷volumes:# 定义存储卷名称  - name: html# 定义存储卷类型emptyDir: {}

2.3 验证

kubectl apply -f pod-emptydir.yamlkubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
pod-emptydir   2/2     Running   0          36s   10.244.2.19   node02   <none>           <none># 验证两个容器通过 emptyDir 共享文件
curl 10.244.2.19
Thu May 27 18:17:11 UTC 2021
Thu May 27 18:17:13 UTC 2021
Thu May 27 18:17:15 UTC 2021

可见日期不断追加,说明容器间共享成功。


3、hostPath 存储卷

3.1 特点

  • 将节点(宿主机)上的目录挂载到容器;
  • 可实现持久化(Pod 删除后节点目录数据保留);
  • 但节点故障会导致数据丢失,不支持跨节点共享。

3.2 案例

# 1)在所有 Node 节点上创建挂载目录(确保调度到任意节点都能找到目录)
ssh root@node01 "mkdir -p /data/pod/volume1 && echo 'node01.benet.com' > /data/pod/volume1/index.html"
ssh root@node02 "mkdir -p /data/pod/volume1 && echo 'node02.benet.com' > /data/pod/volume1/index.html"# 2) 创建 Pod 资源
vim pod-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-hostpathnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1# 定义容器挂载内容volumeMounts:# 使用的存储卷名称,需与下方 volumes 字段的 name 值一致- name: html# 挂载至容器中哪个目录mountPath: /usr/share/nginx/html# 读写挂载方式,默认为读写(false)readOnly: false# volumes 字段定义了 Pause 容器关联的宿主机存储卷volumes:# 存储卷名称- name: html# 存储类型为 hostPath(宿主机路径)hostPath:# 宿主机上的目录路径path: /data/pod/volume1# 目录类型:若宿主机无此目录则自动创建type: DirectoryOrCreatekubectl apply -f pod-hostpath.yaml

3.3 访问测试

kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
pod-hostpath   1/1     Running   0          37s   10.244.2.35   node02   <none>           <none># 访问 Pod IP,返回节点目录中的内容
curl 10.244.2.35
node02.benet.com# 删除 Pod 后重建,验证数据持久化(调度到同一节点仍能访问原内容)
kubectl delete -f pod-hostpath.yaml  
kubectl apply -f pod-hostpath.yaml kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
pod-hostpath   1/1     Running   0          36s   10.244.2.37   node02   <none>           <none>curl 10.244.2.37
node02.benet.com

Pod 删除重建后仍能访问相同内容,说明数据在节点本地实现持久化。


4、NFS 网络共享存储卷

4.1 特点

  • 多节点共享数据(支持跨节点访问);
  • 数据集中存放于 NFS 服务端,节点故障不影响数据;
  • 支持 RWX(多路读写),适合集群级共享存储场景。

4.2 案例

4.2.1 部署 NFS 服务端(stor01 节点)
# 安装 NFS 相关组件
rpm -q rpcbind nfs-utils || yum install -y nfs-utils rpcbind# 创建共享目录
mkdir /data/volumes -p
chmod 777 /data/volumes  # 赋予读写权限(测试环境,生产环境需按需调整)# 配置 NFS 共享(允许 192.168.100.0/24 网段访问)
vim /etc/exports
/data/volumes 192.168.100.0/24(rw,no_root_squash)# 启动服务并设置开机自启
systemctl start rpcbind nfs
systemctl enable rpcbind nfs# 验证 NFS 共享
showmount -e stor01
Export list for stor01:
/data/volumes 192.168.100.0/24
4.2.2 所有 Node 节点安装 NFS 客户端(关键)
# 所有 Node 节点必须安装 nfs-utils,否则无法挂载 NFS 卷
yum install -y nfs-utils
4.2.3 创建 NFS 存储卷的 Pod(master 节点)
vim pod-nfs-vol.yaml
kind: Pod
apiVersion: v1
metadata:name: pod-vol-nfsnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1volumeMounts:- name: htmlmountPath: /usr/share/nginx/html  # Nginx 静态文件目录volumes:- name: htmlnfs:path: /data/volumes  # NFS 服务端共享目录server: stor01       # NFS 服务端主机名(需保证 Node 能解析)kubectl apply -f pod-nfs-vol.yaml# 查看 Pod 状态(确保 Running)
kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
pod-vol-nfs    1/1     Running   0          21s   10.244.2.38   node02   <none>           <none>
4.2.4 验证数据共享与持久化
# 在 NFS 服务端创建测试文件
echo "<h1> NFS Storage: stor01 </h1>" > /data/volumes/index.html# 访问 Pod IP,验证能否读取 NFS 中的文件
curl 10.244.2.38
<h1> NFS Storage: stor01 </h1># 删除 Pod 后重建,验证数据持久化
kubectl delete -f pod-nfs-vol.yaml
kubectl apply -f pod-nfs-vol.yaml# 重新访问,仍能获取 NFS 中的文件
curl 10.244.2.39  # 新 Pod IP
<h1> NFS Storage: stor01 </h1>

5、PV 与 PVC 持久化机制

5.1 PV 与 PVC 的核心概念

  • PV(Persistent Volume):持久化存储卷,由运维工程师定义,描述底层存储资源(如 NFS 目录、容量、访问模式),是集群级资源(跨命名空间)。
  • PVC(Persistent Volume Claim):持久化存储请求,由应用开发者提出,描述所需存储的条件(如容量、访问模式),无需关心底层存储细节。
  • 核心逻辑:PVC 向集群申请存储资源,Kubernetes 自动匹配满足条件的 PV 并绑定,Pod 通过 PVC 间接使用 PV 存储。
概念作用维护者
PV定义底层存储资源运维管理员
PVC提出存储需求应用开发者
StorageClass动态创建 PV 的模板运维工程师

5.2 PV 与 PVC 的生命周期

  1. Provisioning(配置):创建 PV(静态手动创建或动态通过 StorageClass 创建);
  2. Binding(绑定):PVC 匹配满足条件的 PV,建立绑定关系;
  3. Using(使用):Pod 通过 PVC 挂载并使用存储;
  4. Releasing(释放):Pod 删除,PVC 与 PV 解绑,PV 状态变为 Released;
  5. Recycling(回收):根据 PV 的回收策略处理数据(保留、删除或清空)。

5.3 PV 的关键配置参数

apiVersion: v1
kind: PersistentVolume
metadata:name: pv001  # PV 名称(唯一)
spec:nfs:  # 存储类型(支持 nfs、hostPath、ceph 等)path: /data/volumes/v1  # 底层存储目录server: stor01          # 存储服务端地址accessModes:  # 访问模式(支持多模式组合)- ReadWriteOnce  # RWO:仅单个 Pod 读写- ReadWriteMany  # RWX:多个 Pod 同时读写capacity:  # 存储容量storage: 1GipersistentVolumeReclaimPolicy: Retain  # 回收策略(Retain/Delete/Recycle)storageClassName: ""  # 存储类名称(用于匹配 PVC)
关键参数说明
  • 访问模式(accessModes)
    • RWO(ReadWriteOnce):仅允许单个 Pod 挂载读写(所有存储类型均支持);
    • ROX(ReadOnlyMany):多个 Pod 挂载只读;
    • RWX(ReadWriteMany):多个 Pod 同时挂载读写(仅 NFS、Ceph 等共享存储支持)。
  • 回收策略(persistentVolumeReclaimPolicy)
    • Retain(保留):PVC 删除后,PV 状态变为 Released,数据保留,需手动清理;
    • Delete(删除):PVC 删除后,自动删除 PV 及底层存储资源(仅云存储支持,如 AWS EBS);
    • Recycle(回收):PVC 删除后,清空 PV 数据并恢复为 Available 状态(仅支持 NFS/HostPath)。

5.4 PVC 的关键配置参数

apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mypvc  # PVC 名称namespace: default  # 命名空间级资源
spec:accessModes:  # 需为 PV 支持的访问模式子集- ReadWriteManyresources:requests:storage: 2Gi  # 申请的存储容量storageClassName: ""  # 需与目标 PV 的 storageClassName 一致(为空则匹配无存储类的 PV)

5.5 PV 与 PVC 的匹配规则

  1. 存储容量:PV 容量 ≥ PVC 申请容量;
  2. 访问模式:PV 支持的访问模式包含 PVC 要求的模式;
  3. 存储类(storageClassName):两者必须一致(均为空或相同名称);
  4. 标签选择器(可选):PVC 可通过标签筛选特定 PV。

6、NFS + PV + PVC 实战(静态 PV)

6.1 准备 NFS 存储(stor01 节点)

# 在 NFS 服务端创建 5 个独立子目录(对应 5 个 PV)
mkdir /data/volumes/v{1,2,3,4,5} -p# 配置 NFS 共享(允许 192.168.100.0/24 网段访问所有子目录)
vim /etc/exports
/data/volumes/v1 192.168.100.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.100.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.100.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.100.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.100.0/24(rw,no_root_squash)# 重新加载 NFS 配置
exportfs -arv# 验证共享
showmount -e stor01

6.2 定义 PV(master 节点)

vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: pv001labels:name: pv001
spec:nfs:path: /data/volumes/v1server: stor01accessModes: ["ReadWriteMany", "ReadWriteOnce"]capacity:storage: 1GipersistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv002labels:name: pv002
spec:nfs:path: /data/volumes/v2server: stor01accessModes: ["ReadWriteOnce"]capacity:storage: 2GipersistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv003labels:name: pv003
spec:nfs:path: /data/volumes/v3server: stor01accessModes: ["ReadWriteMany", "ReadWriteOnce"]capacity:storage: 2GipersistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv004labels:name: pv004
spec:nfs:path: /data/volumes/v4server: stor01accessModes: ["ReadWriteMany", "ReadWriteOnce"]capacity:storage: 4GipersistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv005labels:name: pv005
spec:nfs:path: /data/volumes/v5server: stor01accessModes: ["ReadWriteMany", "ReadWriteOnce"]capacity:storage: 5GipersistentVolumeReclaimPolicy: Retain# 应用 PV 配置
kubectl apply -f pv-demo.yaml# 查看 PV 状态(初始为 Available)
kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
pv001     1Gi        RWO,RWX        Retain           Available                                      7s
pv002     2Gi        RWO            Retain           Available                                      7s
pv003     2Gi        RWO,RWX        Retain           Available                                      7s
pv004     4Gi        RWO,RWX        Retain           Available                                      7s
pv005     5Gi        RWO,RWX        Retain           Available                                      7s

6.3 定义 PVC + Pod(master 节点)

vim pod-vol-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mypvcnamespace: default
spec:accessModes: ["ReadWriteMany"]  # 要求 RWX 访问模式resources:requests:storage: 2Gi  # 申请 2Gi 容量
---
apiVersion: v1
kind: Pod
metadata:name: pod-vol-pvcnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1volumeMounts:- name: htmlmountPath: /usr/share/nginx/html  # 挂载到 Nginx 静态目录volumes:- name: htmlpersistentVolumeClaim:claimName: mypvc  # 关联上面定义的 PVC# 应用配置
kubectl apply -f pod-vol-pvc.yaml# 查看 PVC 状态(应为 Bound,自动绑定匹配的 PV)
kubectl get pvc
NAME    STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Bound    pv003     2Gi        RWO,RWX                       22s# 查看 PV 状态(pv003 变为 Bound)
kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON    AGE
pv003     2Gi        RWO,RWX        Retain           Bound       default/mypvc                            19m

6.4 验证数据持久化与共享

# 在 NFS 服务端的 pv003 对应目录创建测试文件
echo "Welcome to PV003 (NFS + PV + PVC)" > /data/volumes/v3/index.html# 查看 Pod IP 并访问
kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
pod-vol-pvc    1/1     Running   0          3m    10.244.2.39   node02   <none>           <none>curl 10.244.2.39
Welcome to PV003 (NFS + PV + PVC)# 跨节点验证共享:在另一节点创建 Pod 关联同一个 PVC(需先删除现有 Pod)
kubectl delete pod pod-vol-pvc
vim pod-vol-pvc-node1.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-vol-pvc-node1
spec:nodeName: node1  # 强制调度到 node1containers:- name: myappimage: ikubernetes/myapp:v1volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlpersistentVolumeClaim:claimName: mypvckubectl apply -f pod-vol-pvc-node1.yaml
curl 10.244.1.40  # 新 Pod IP(node1 节点)
Welcome to PV003 (NFS + PV + PVC)  # 成功访问共享数据

7、StorageClass + NFS 动态存储(自动创建 PV)

静态 PV 需手动创建,适合小规模集群;动态存储通过 StorageClass + NFS Provisioner 实现 PV 自动创建,适合大规模部署。

7.1 核心原理

  • NFS Provisioner:外部存储插件,负责监听 PVC 请求,自动在 NFS 服务端创建目录、生成 PV 并绑定 PVC;
  • StorageClass:动态存储模板,定义 PV 的创建规则(如存储类型、Provisioner、回收策略);
  • RBAC 权限:授予 NFS Provisioner 操作 PV、PVC、StorageClass 等资源的权限。

7.2 部署步骤

7.2.1 准备 NFS 服务端(stor01 节点)
# 创建动态存储的根目录
mkdir /opt/k8s -p
chmod 777 /opt/k8s# 配置 NFS 共享(允许 192.168.100.0/24 网段访问)
vim /etc/exports
/opt/k8s 192.168.100.0/24(rw,no_root_squash,sync)# 重新加载 NFS 配置
exportfs -arv
showmount -e stor01
7.2.2 创建 RBAC 权限(master 节点)
vim nfs-client-rbac.yaml
# 创建 ServiceAccount:用于 NFS Provisioner 的身份认证
apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisioner
---
# 创建 ClusterRole:定义操作资源的权限
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"]
---
# 绑定 ClusterRole 到 ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: nfs-client-provisioner-clusterrolebinding
subjects:
- kind: ServiceAccountname: nfs-client-provisionernamespace: default
roleRef:kind: ClusterRolename: nfs-client-provisioner-clusterroleapiGroup: rbac.authorization.k8s.io# 应用权限配置
kubectl apply -f nfs-client-rbac.yaml
7.2.3 部署 NFS Provisioner(master 节点)
# 注意:K8s 1.20~1.24 版本需添加 RemoveSelfLink=false 参数(1.25+ 版本无需添加)
# 1)若为 K8s 1.20~1.24 版本,修改 kube-apiserver 配置:
vim /etc/kubernetes/manifests/kube-apiserver.yaml
spec:containers:- command:- kube-apiserver- --feature-gates=RemoveSelfLink=false  # 添加这一行- --advertise-address=192.168.100.49  # 你的 master IP# 其他默认参数保持不变...# 保存后,kubelet 会自动重启 kube-apiserver,验证状态:
kubectl get pods -n kube-system | grep kube-apiserver# 2)部署 NFS Provisioner
vim nfs-client-provisioner.yaml
kind: Deployment
apiVersion: apps/v1
metadata:name: nfs-client-provisioner
spec:replicas: 1selector:matchLabels:app: nfs-client-provisionerstrategy:type: Recreate  # 重建策略:避免多副本冲突template:metadata:labels:app: nfs-client-provisionerspec:serviceAccountName: nfs-client-provisioner  # 关联前面创建的 ServiceAccountcontainers:- name: nfs-client-provisioner# 推荐使用国内镜像(避免 quay.io 拉取失败)image: registry.cn-hangzhou.aliyuncs.com/opensourceway/kubernetes/nfs-client-provisioner:v3.1.0-k8s1.11imagePullPolicy: IfNotPresentvolumeMounts:- name: nfs-client-rootmountPath: /persistentvolumes  # 挂载 NFS 根目录env:- name: PROVISIONER_NAMEvalue: nfs-storage  # Provisioner 名称(需与 StorageClass 中一致)- name: NFS_SERVERvalue: stor01       # NFS 服务端主机名- name: NFS_PATHvalue: /opt/k8s     # NFS 服务端共享目录volumes:- name: nfs-client-rootnfs:server: stor01path: /opt/k8s# 应用部署配置
kubectl apply -f nfs-client-provisioner.yaml# 查看 Provisioner 状态(确保 Running)
kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-5d7df8dcc8-x66dr   1/1     Running   0          14s
7.2.4 创建 StorageClass(master 节点)
vim nfs-client-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: nfs-client-storageclass  # StorageClass 名称
provisioner: nfs-storage  # 必须与 Provisioner 的 PROVISIONER_NAME 一致
parameters:archiveOnDelete: "false"  # 删除 PVC 时自动删除数据(false=删除,true=存档)
reclaimPolicy: Delete  # PV 回收策略(与 parameters.archiveOnDelete 配合)
volumeBindingMode: Immediate  # 立即绑定 PVC# 应用配置
kubectl apply -f nfs-client-storageclass.yaml# 查看 StorageClass
kubectl get storageclass
NAME                      PROVISIONER   RECLAIM POLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client-storageclass   nfs-storage   Delete          Immediate           false                  43s
7.2.5 测试动态存储(创建 PVC + Pod)
vim test-pvc-pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: test-nfs-pvc
spec:accessModes: ["ReadWriteMany"]  # 访问模式storageClassName: nfs-client-storageclass  # 关联上面创建的 StorageClassresources:requests:storage: 1Gi  # 申请 1Gi 容量
---
apiVersion: v1
kind: Pod
metadata:name: test-storageclass-pod
spec:containers:- name: busyboximage: busybox:latestimagePullPolicy: IfNotPresentcommand: ["/bin/sh", "-c", "sleep 3600"]  # 保持容器运行volumeMounts:- name: nfs-pvcmountPath: /mnt  # 容器内挂载路径restartPolicy: Nevervolumes:- name: nfs-pvcpersistentVolumeClaim:claimName: test-nfs-pvc  # 关联上面的 PVC# 应用配置
kubectl apply -f test-pvc-pod.yaml

7.3 验证动态存储功能

7.3.1 验证 PVC 绑定与 PV 自动创建
# 查看 PVC 状态(应为 Bound)
kubectl get pvc
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS              AGE
test-nfs-pvc   Bound    pvc-3c68f93d-4dac-4db5-a92f-1ce89a86ae6c   1Gi        RWX            nfs-client-storageclass   11s# 查看自动创建的 PV(名称以 pvc- 开头)
kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS              AGE
pvc-3c68f93d-4dac-4db5-a92f-1ce89a86ae6c   1Gi        RWX            Delete           Bound    default/test-nfs-pvc   nfs-client-storageclass   15s
7.3.2 验证 NFS 目录自动创建
# 在 NFS 服务端查看自动创建的目录(格式:${namespace}-${pvcName}-${pvName})
ls /opt/k8s/
default-test-nfs-pvc-pvc-3c68f93d-4dac-4db5-a92f-1ce89a86ae6c
7.3.3 验证数据同步
# 进入 Pod,在挂载目录 /mnt 写入文件
kubectl exec -it test-storageclass-pod -- sh
/mnt # echo "Dynamic PV Test: NFS + StorageClass" > test.txt
/mnt # exit# 在 NFS 服务端的自动创建目录中查看文件
cd /opt/k8s/default-test-nfs-pvc-pvc-3c68f93d-4dac-4db5-a92f-1ce89a86ae6c
cat test.txt
Dynamic PV Test: NFS + StorageClass  # 数据同步成功
7.3.4 验证自动回收
# 删除 PVC 和 Pod
kubectl delete pod test-storageclass-pod
kubectl delete pvc test-nfs-pvc# 查看 PV 状态(自动删除)
kubectl get pv | grep test-nfs-pvc  # 无输出# 查看 NFS 目录(自动删除)
ls /opt/k8s/default-test-nfs-pvc-pvc-3c68f93d-4dac-4db5-a92f-1ce89a86ae6c  # 目录不存在

8、常见问题与排查

8.1 PV 无法绑定 PVC

  • 检查访问模式:PVC 要求的模式必须是 PV 支持的子集;
  • 检查容量:PV 容量需 ≥ PVC 申请容量;
  • 检查存储类:两者的 storageClassName 必须一致(均为空或相同名称);
  • 检查 NFS 连通性:Node 节点需安装 nfs-utils,且能访问 NFS 服务端(showmount -e stor01)。

8.2 Pod 卡在 ContainerCreating

  • 镜像拉取失败:替换为国内镜像(如阿里云镜像);
  • NFS 挂载失败:检查 NFS 服务端防火墙(开放 111、2049 端口)、共享目录权限、节点网络连通性;
  • 权限不足:确保 RBAC 权限配置正确(ServiceAccount、ClusterRole、ClusterRoleBinding 完整)。

8.3 动态 PV 创建失败(K8s 1.20+)

  • 1.20~1.24 版本:需添加 --feature-gates=RemoveSelfLink=false 到 kube-apiserver 配置;
  • 1.25+ 版本:无需添加上述参数,直接使用适配的 Provisioner 镜像(如 k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2)。

9、总结

存储类型生命周期共享性持久性典型场景
emptyDirPod 生命周期同 Pod 内容器临时缓存、容器间共享
hostPath节点生命周期单节点节点本地持久化(测试)
NFS独立服务生命周期多节点集群共享存储
PV + PVC(静态)集群级别跨节点小规模生产环境
StorageClass(动态)自动创建 / 回收跨节点大规模生产环境、自动化部署

核心选型建议

  • 临时存储:使用 emptyDir;
  • 节点本地持久化:使用 hostPath(测试环境);
  • 集群共享存储:使用 NFS + PV + PVC(静态);
  • 大规模自动化部署:使用 StorageClass + NFS Provisioner(动态)。
http://www.dtcms.com/a/486546.html

相关文章:

  • 免费网站推广网站破解版网站建设具体工作
  • 目标检测项目核心笔记:从任务定义到算法流程
  • 网站建设的基本步骤是中国设备网
  • 建设网站的优点跟缺点要看网现在的地址是多少
  • 前端学习总结——AI主流前沿方向篇
  • 制作网页的网站哪个好用产品市场营销策划方案
  • [Linux]学习笔记系列 -- lib/zlib DEFLATE压缩与解压缩
  • 为电力设备装上“感知神经”:AHE100无线温湿度传感器,守护安全运行的隐形卫士
  • RocketMQ如何保证消息不丢失
  • CC1-二叉树的最小深度
  • 把 Python 应用打包成 Mac 应用程序 — 完整指南
  • 阿里云监控:SLS的使用
  • C语言面试题答案版(ai生成)
  • 做网站发广告重庆建站模板
  • 吃透大数据算法-用 “任务排队” 讲透 Kahn 算法的核心
  • 外贸网站建设 全球搜天津网址
  • MeshGPT:三角形网格生成的Decoder-Only Transformer范式解析
  • vllm论文中 内部碎片原因
  • 重庆市设计公司网站wordpress 计数js版
  • linux中mount的本质是什么?自己如何实现一个伪文件系统
  • wordpress哪个编辑器好用吗长春网站优化咨询
  • 深度学习经典网络解析:ResNet
  • qingdao城乡住房建设厅网站网站建设中的策略
  • 字节数开一面
  • 页面转wordpress辛集seo网站优化电话
  • 优化推广网站seo讷河做网站公司
  • ASP的checkbox
  • 【个人成长笔记】在Ubuntu中将Linux系统的文件夹名称从中文改回英文的完整指南
  • Hosmer-Lemeshow检验:逻辑回归模型拟合优度的守护者
  • 主流机器学习算法的快速应用指南