Kubernetes(K8s)学习笔记(第十三期):集群存储与有状态应用(上篇):动态卷供应------StorageClass + Provisioner
本笔记为 Kubernetes 系列第十三期,聚焦集群存储的动态卷供应机制。涵盖:StorageClass 核心配置、Local Path Provisioner 部署与验证、NFS Provisioner 部署与验证、动态卷与静态卷的深度对比。所有命令和 YAML 示例均已经过整理和注释。全文约 4300 字 ,包含 14 个 YAML 示例 、45+ 命令示例 和 12 张对比表格,是 Kubernetes 动态存储管理的完整入门指南。
更多kubernetes系列知识:kubernetes从入门到进阶
我的主页:AOwhisky,这里有更多运维系统性知识整理和其他有趣内容,欢迎与我一起探讨学习~
--- Compiled and Authored by Whisky --- July 3 rd, 2026
目录
- 引子:存储管理的演进与"自动贩卖机"
- 动态卷供应概述
- StorageClass------存储"套餐"模板
- Local Path Provisioner------本地存储动态供应
- NFS Provisioner------NFS 存储动态供应
- 动态卷 vs 静态卷深度对比
- 总结与知识点一览表
引子:存储管理的演进与"自动贩卖机"
在第十期和第十一期中,我们完成了资源管理的三个层次:
| 层次 | 问题 | K8s 组件 | 状态 |
|---|---|---|---|
| 监控层 | 资源用了多少? | Metrics Server | ✅ 已讲 |
| 扩缩层 | 资源不够怎么办? | HPA | ✅ 已讲 |
| 约束层 | 如何防止超用? | ResourceQuota / LimitRange | ✅ 已讲 |
但在实际生产环境中,还有一个重要问题没有解决:存储怎么办?
存储管理的演进:从"手动档"到"自动档"
在 Kubernetes 的发展历程中,存储管理经历了几个关键阶段:
| 阶段 | 存储管理方式 | 特点 | 痛点 |
|---|---|---|---|
| 物理机时代 | 存储直接挂载到物理机 | 应用与存储强绑定 | 无法迁移,资源浪费 |
| 虚拟机时代 | 存储通过 SAN/NAS 挂载到 VM | 需要手动配置 LUN 和挂载点 | 管理复杂,响应慢 |
| 容器早期 | 管理员手动创建 PV | 每个 PVC 需提前创建对应 PV | 工作量大,无法按需分配 |
| 容器现在 | 动态卷供应 | 按需自动创建,用完回收 | ✅ 高效、自动化 |
当用户创建一个 PVC 时,Kubernetes 需要有一个对应的 PV 来满足存储需求。在早期的 Kubernetes 中,管理员需要提前手动创建 PV ------这就是静态卷供应。但随着集群规模的扩大,手动创建 PV 变得越来越繁琐:
- 每个 PVC 都需要管理员提前创建对应的 PV
- 存储容量和访问模式需要精确匹配
- 无法根据用户需求动态调整
- 资源利用率低(PV 预分配后可能闲置)
- 响应速度慢(需要等待管理员操作)
动态卷供应就像"自动贩卖机"------用户只需要选择想要的"商品"(StorageClass),投币(创建 PVC),系统就会自动"出货"(创建 PV)。整个过程无需管理员手动干预,秒级完成。
一句话概括本期:StorageClass 定义了"存储套餐",Provisioner 是"自动造卷机",两者配合让存储管理从此自动化。
一、动态卷供应概述
1.1 动态卷供应的核心组件
动态卷供应依赖三个核心组件:
| 组件 | 角色 | 说明 |
|---|---|---|
| StorageClass | "菜单" | 定义存储的规格和参数 |
| Provisioner | "厨师" | 执行创建 PV 的实际操作 |
| PVC | "顾客下单" | 用户提出存储需求 |
三者的协作关系:
text
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 用户 │ │ 管理员 │ │ 系统 │
│ 创建 PVC │─────▶│ 创建 │ │ 调用 │
│ (下单) │ │ StorageClass│ │ Provisioner │
│ │ │ (菜单) │ │ (厨师) │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ 自动创建 PV │
│ (自动出货) │
└─────────────┘
1.2 动态卷供应的工作流程
text
集群管理员 用户 系统
│ │ │
│ 1. 创建 StorageClass│ │
│─────────────────────>│ │
│ │ 2. 创建 PVC │
│ │─────────────────────>│
│ │ │ 3. 调用 Provisioner
│ │ │ 4. 创建 PV
│ │ │ 5. 绑定 PVC ↔ PV
│ │<─────────────────────│
│ │ 6. 使用 PVC │
│ │─────────────────────>│
流程说明:
- 管理员:创建 StorageClass,定义"存储套餐"(用什么工具造卷、回收策略等)
- 用户:创建 PVC 时指定 StorageClass 名称
- 系统:调用 StorageClass 对应的 Provisioner(制备器)自动创建 PV
- 系统:将新创建的 PV 与用户的 PVC 绑定
- 用户:在 Pod 中使用 PVC
二、StorageClass------存储"套餐"模板
2.1 StorageClass 是什么?
StorageClass 就像管理员定义的"存储套餐"------不同套餐对应不同的存储类型、服务质量、备份策略等。
核心作用:
- 将后端存储的差异化参数(如类型、性能、回收策略)封装为"套餐"
- 用户只需选择套餐名称,无需关心底层存储细节
- 实现存储资源的标准化 和自助化
2.2 StorageClass 核心字段详解
| 字段 | 说明 | 是否必填 |
|---|---|---|
provisioner |
指定用哪个"造卷工具"创建 PV | ✅ 必填 |
reclaimPolicy |
PV 回收策略(Delete / Retain) | 可选(默认 Delete) |
volumeBindingMode |
PVC 与 PV 的绑定时机 | 可选(默认 Immediate) |
parameters |
不同 Provisioner 的特定参数 | 按需配置 |
mountOptions |
挂载时的额外选项 | 可选 |
allowVolumeExpansion |
是否允许 PVC 扩容 | 可选(默认 false) |
2.3 provisioner(制备器)
provisioner 指定了由哪个存储插件来创建 PV:
| 存储类型 | provisioner 名称 | 是否内置 |
|---|---|---|
| AWS EBS | kubernetes.io/aws-ebs |
✅ 是 |
| Azure Disk | kubernetes.io/azure-disk |
✅ 是 |
| GCE PD | kubernetes.io/gce-pd |
✅ 是 |
| Ceph RBD | kubernetes.io/rbd |
✅ 是 |
| NFS | 需外部 Provisioner(如 fuseim.pri/ifs) |
❌ 否 |
| 本地存储 | 需外部 Provisioner(如 rancher.io/local-path) |
❌ 否 |
重点:NFS 和本地存储没有内置 Provisioner,需要部署外部组件(本期将详细讲解)。
2.4 reclaimPolicy(回收策略)
| 策略 | 行为 | 适用场景 |
|---|---|---|
| Delete(默认) | PVC 删除后,PV 和后端存储一并删除 | 临时存储、测试环境 |
| Retain | PVC 删除后,PV 和数据保留,需管理员手动清理 | 生产环境、重要数据 |
生产建议 :对于重要数据(如数据库存储),强烈建议使用
Retain策略,防止误删 PVC 导致数据永久丢失。
2.5 volumeBindingMode(绑定模式)
| 模式 | 行为 | 适用场景 |
|---|---|---|
| Immediate(默认) | 创建 PVC 时立即创建 PV 并绑定 | 云存储(可跨节点访问) |
| WaitForFirstConsumer | 等待第一个使用该 PVC 的 Pod 创建后才绑定 | 本地存储(需知道 Pod 在哪个节点) |
关键理解 :本地存储(Local Path)必须使用
WaitForFirstConsumer模式,因为本地存储绑定到特定节点,需要等 Pod 调度后才能确定在哪个节点创建 PV。如果使用Immediate模式,PV 可能创建在错误的节点上,导致 Pod 无法访问。
2.6 allowVolumeExpansion(允许扩容)
从 Kubernetes 1.11 开始,支持对 PVC 进行扩容。需要满足两个条件:
- StorageClass 的
allowVolumeExpansion设置为true - 后端存储支持在线扩容
yaml
allowVolumeExpansion: true
扩容操作:
bash
# 修改 PVC 的 storage 字段
kubectl edit pvc <pvc-name>
# 将 storage: 5Gi 改为 storage: 10Gi
2.7 StorageClass 完整 YAML 示例
yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
fsType: ext4
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
- debug
- noatime
volumeBindingMode: Immediate
三、Local Path Provisioner------本地存储动态供应
3.1 什么是 Local Path Provisioner?
Local Path Provisioner 是 Rancher 开发的 Kubernetes 本地存储动态卷插件,适用于需要使用节点本地磁盘的场景。
适用场景:
- 测试环境的临时存储
- 对性能要求高、对数据持久性要求不高的场景
- 单节点存储(不需要跨节点共享)
- 边缘计算场景(轻量级存储)
核心特点:
- 使用节点本地磁盘(默认路径
/opt/local-path-provisioner) - 绑定模式为
WaitForFirstConsumer(等待 Pod 调度) - 回收策略为
Delete(PVC 删除时自动清理数据) - 性能高(直接读写本地磁盘,无网络开销)
3.2 部署 Local Path Provisioner
下载部署文件:
bash
root@master30:~# wget https://github.com/rancher/local-path-provisioner/blob/v0.0.35/deploy/local-path-storage.yaml
部署文件核心资源结构:
| 资源类型 | 名称 | 作用 |
|---|---|---|
| Namespace | local-path-storage | 隔离相关资源 |
| ServiceAccount | local-path-provisioner-service-account | 运行权限 |
| Role / ClusterRole | local-path-provisioner-role | RBAC 权限 |
| Deployment | local-path-provisioner | 核心程序 |
| ConfigMap | local-path-config | 定义本地存储路径 |
| StorageClass | local-path | 存储"套餐"模板 |
ConfigMap 中的路径配置:
json
{
"nodePathMap": [
{
"node": "DEFAULT_PATH_FOR_NON_LISTED_NODES",
"paths": ["/opt/local-path-provisioner"]
}
]
}
Helper Pod 的工作原理:
Local Path Provisioner 使用 Helper Pod 在节点上创建本地存储目录。Helper Pod 的关键特性:
- 以
privileged: true权限运行,确保有足够的权限创建目录 - 使用
system-node-critical优先级,确保在资源紧张时不会被驱逐 - 容忍
node.kubernetes.io/disk-pressure污点,确保在磁盘压力时仍能运行 - 使用
busybox镜像,轻量级且包含所有需要的命令
部署:
bash
root@master30:~# kubectl apply -f local-path-storage.yaml
验证部署:
bash
root@master30:~# kubectl get sc local-path
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-path rancher.io/local-path Delete WaitForFirstConsumer false 31s
root@master30:~# kubectl get all -n local-path-storage
NAME READY STATUS RESTARTS AGE
pod/local-path-provisioner-74b5c4bf98-955sk 1/1 Running 0 63s
3.3 验证 Local Path Provisioner
步骤 1:创建 PVC
bash
root@master30:~# cat > local-path-pvc.yaml <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: local-path-pvc
namespace: default
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 5Gi
storageClassName: local-path
EOF
root@master30:~# kubectl apply -f local-path-pvc.yaml
root@master30:~# kubectl get pvc
NAME STATUS VOLUME CAPACITY STORAGECLASS AGE
local-path-pvc Pending 6s
注意 :PVC 状态为
Pending,因为volumeBindingMode: WaitForFirstConsumer,需要等到 Pod 创建后才绑定。这是 Local Path Provisioner 与 NFS Provisioner 的一个重要区别。
步骤 2:创建 Deployment 使用该 PVC
bash
root@master30:~# cat > local-path-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: webapp-data
mountPath: /usr/share/nginx/html
volumes:
- name: webapp-data
persistentVolumeClaim:
claimName: local-path-pvc
EOF
root@master30:~# kubectl apply -f local-path-deployment.yaml
观察:
bash
root@master30:~# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE NODE
webapp-6d46b54487-6nqmh 1/1 Running 0 30s worker31.whisky.cloud
webapp-6d46b54487-kzkd5 1/1 Running 0 30s worker31.whisky.cloud
关键观察:所有 Pod 都在 worker31------因为 PVC 的 PV 只能创建在 worker31 上。
为什么所有 Pod 都在同一个节点上?
因为 Local Path Provisioner 在 Pod 调度确定节点后,才在对应节点上创建 PV。一旦 PV 在 worker31 上创建,后续的 Pod 副本也必须调度到 worker31 上,因为 PVC 已经绑定了 worker31 上的本地存储。这是 Local Path 的核心局限性------无法跨节点共享,也不支持 Pod 跨节点调度。
步骤 3:验证数据持久化
bash
# 写入测试文件
root@master30:~# kubectl exec webapp-6d46b54487-6nqmh -- bash -c 'echo "Hello Local Path" > /usr/share/nginx/html/index.html'
# 查看本地存储
root@worker31:~# ls /opt/local-path-provisioner/pvc-*/default_local-path-pvc/
index.html
root@worker31:~# cat /opt/local-path-provisioner/pvc-*/default_local-path-pvc/index.html
Hello Local Path
步骤 4:清理资源
bash
root@master30:~# kubectl delete deployment webapp
root@master30:~# kubectl delete pvc local-path-pvc
# 本地数据被自动删除(reclaimPolicy: Delete)
root@worker31:~# ls /opt/local-path-provisioner/pvc-*/
ls: cannot access '/opt/local-path-provisioner/pvc-*/': No such file or directory
四、NFS Provisioner------NFS 存储动态供应
4.1 为什么需要 NFS Provisioner?
NFS 本身是 Kubernetes 支持的 Volume 类型,但没有内置的 Provisioner。这意味着:
- 静态方式:需要管理员手动创建 NFS PV(工作量大)
- 动态方式:需要部署外部 Provisioner(一劳永逸)
NFS Provisioner 让用户可以像使用云存储一样,通过 PVC 自动创建 NFS 子目录作为 PV。
NFS Provisioner 的优势:
- 支持 RWX(ReadWriteMany)模式,多个 Pod 可同时读写
- 跨节点共享存储,Pod 可在不同节点间迁移
- 集中管理,备份和恢复更方便
4.2 部署 NFS 服务端
bash
root@master30:~# apt install -y nfs-kernel-server
# 创建共享目录
root@master30:~# mkdir -m 777 /shares/
# 配置共享
root@master30:~# cat << EOF > /etc/exports
/shares *(rw,sync,no_root_squash,no_all_squash,insecure)
EOF
root@master30:~# systemctl restart nfs-server.service
# 在 Worker 节点安装 NFS 客户端
root@worker31:~# apt install -y nfs-common
root@worker32:~# apt install -y nfs-common
4.3 部署 NFS Provisioner
步骤 1:创建命名空间和 RBAC 权限
bash
root@master30:~# kubectl create ns kube-storage
root@master30:~# kubectl config set-context --current --namespace kube-storage
yaml
root@master30:~# cat > nfs-rbac.yaml <<'EOF'
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: kube-storage
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-client-provisioner-runner
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: ["create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: kube-storage
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
EOF
root@master30:~# kubectl apply -f nfs-rbac.yaml
步骤 2:部署 NFS Provisioner 应用
yaml
root@master30:~# cat > nfs-provisioner.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
namespace: kube-storage
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
volumes:
- name: nfs-client-root
nfs:
server: 10.1.8.30
path: /shares
containers:
- name: nfs-client-provisioner
image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 10.1.8.30
- name: NFS_PATH
value: /shares
EOF
root@master30:~# kubectl apply -f nfs-provisioner.yaml
root@master30:~# kubectl get deployments.apps -n kube-storage
NAME READY UP-TO-DATE AVAILABLE AGE
nfs-client-provisioner 1/1 1 1 1m
步骤 3:创建 NFS StorageClass
yaml
root@master30:~# cat > nfs-storageclass.yaml <<'EOF'
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
provisioner: fuseim.pri/ifs
parameters:
onDelete: retain # PVC 删除时保留数据
archiveOnDelete: "false"
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: Immediate
EOF
root@master30:~# kubectl apply -f nfs-storageclass.yaml
root@master30:~# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-storage fuseim.pri/ifs Delete Immediate true 2s
parameters 参数说明:
| 参数 | 值 | 说明 |
|---|---|---|
onDelete |
delete / retain |
PVC 删除时是否删除后端数据 |
archiveOnDelete |
true / false |
是否将删除的数据归档(保留带时间戳的备份) |
4.4 验证 NFS Provisioner
步骤 1:创建 PVC
bash
root@master30:~# kubens default
root@master30:~# cat > nfs-pvc.yaml <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: webclaim
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: "nfs-storage"
EOF
root@master30:~# kubectl apply -f nfs-pvc.yaml
root@master30:~# kubectl get pvc
NAME STATUS VOLUME CAPACITY STORAGECLASS AGE
webclaim Bound pvc-6a020ff4-6b7f-4ef4-90fc-3dc94d3e8ddc 5Gi nfs-storage 3s
注意 :NFS PVC 立即变为 Bound(volumeBindingMode: Immediate),无需等待 Pod。这是 NFS 与 Local Path 的又一个重要区别。
步骤 2:验证后端存储
bash
root@master30:~# ls /shares/
default-webclaim-pvc-6a020ff4-6b7f-4ef4-90fc-3dc94d3e8ddc
# 准备测试数据
root@master30:~# echo "Hello NFS Storage" > /shares/default-webclaim-pvc-6a020ff4-6b7f-4ef4-90fc-3dc94d3e8ddc/index.html
步骤 3:创建 Deployment 使用 PVC
bash
root@master30:~# cat > nfs-deploy.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 2
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: webapp-data
mountPath: /usr/share/nginx/html
volumes:
- name: webapp-data
persistentVolumeClaim:
claimName: webclaim
EOF
root@master30:~# kubectl apply -f nfs-deploy.yaml
root@master30:~# kubectl expose deployment webapp --port=80 --target-port=80
# 访问测试
root@master30:~# curl 10.109.140.205
Hello NFS Storage
关键观察:两个 Pod 可以调度到不同节点(worker31 和 worker32),因为 NFS 是共享存储,不绑定特定节点。
步骤 4:清理资源
bash
root@master30:~# kubectl delete deployments.apps webapp
root@master30:~# kubectl delete pvc webclaim
# PV 自动删除
root@master30:~# kubectl get pv
No resources found
# NFS 后端数据仍然保留(取决于 onDelete 参数)
root@master30:~# ls /shares/
default-webclaim-pvc-6a020ff4-6b7f-4ef4-90fc-3dc94d3e8ddc/
五、动态卷 vs 静态卷深度对比
5.1 核心差异对比
| 对比项 | 静态卷供应 | 动态卷供应(Local Path) | 动态卷供应(NFS) |
|---|---|---|---|
| PV 创建 | 手动 | 自动(等待 Pod) | 自动(立即) |
| 绑定模式 | --- | WaitForFirstConsumer | Immediate |
| 数据持久性 | 取决于配置 | 随 PVC 删除 | 随 PVC 删除(可配置保留) |
| 跨节点共享 | 取决于存储类型 | ❌ 不支持 | ✅ 支持 |
| 管理员工作量 | 高 | 低 | 低 |
| 响应速度 | 慢(需人工) | 秒级 | 秒级 |
| 适用场景 | 小规模、固定存储 | 本地临时存储 | 跨节点共享存储 |
5.2 Local Path vs NFS Provisioner 选型指南
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 测试环境临时存储 | Local Path | 简单、快速、无需额外依赖 |
| 高性能本地存储 | Local Path | 直接读写本地磁盘,无网络开销 |
| 需要跨节点共享数据 | NFS Provisioner | 支持 RWX 模式,多节点共享 |
| 需要 Pod 跨节点迁移 | NFS Provisioner | 存储不绑定特定节点 |
| 生产环境重要数据 | NFS Provisioner + Retain | 数据持久化,可备份恢复 |
六、总结与知识点一览表
6.1 StorageClass 核心配置速查
| 字段 | 可选值 | 说明 |
|---|---|---|
provisioner |
rancher.io/local-path / fuseim.pri/ifs 等 |
造卷工具 |
reclaimPolicy |
Delete / Retain |
PVC 删除后 PV 的处理 |
volumeBindingMode |
Immediate / WaitForFirstConsumer |
绑定时机 |
allowVolumeExpansion |
true / false |
是否允许扩容 |
6.2 两种 Provisioner 快速对比
| 对比项 | Local Path Provisioner | NFS Provisioner |
|---|---|---|
| 存储位置 | 节点本地磁盘 | NFS 服务器 |
| 跨节点共享 | ❌ | ✅ |
| 绑定模式 | WaitForFirstConsumer | Immediate |
| 适用场景 | 临时存储、单节点 | 共享存储、多节点 |
| 依赖 | 无 | NFS 服务端 |
| 性能 | 高(本地 SSD) | 中(受网络影响) |
6.3 常用命令速查
| 操作 | 命令 |
|---|---|
| 查看 StorageClass | kubectl get sc |
| 查看 StorageClass 详情 | kubectl describe sc <name> |
| 创建 PVC | kubectl apply -f pvc.yaml |
| 查看 PVC | kubectl get pvc |
| 查看 PV | kubectl get pv |
| 删除 PVC | kubectl delete pvc <name> |
| Local Path 部署 | kubectl apply -f local-path-storage.yaml |
| NFS Provisioner 部署 | kubectl apply -f nfs-rbac.yaml && kubectl apply -f nfs-provisioner.yaml |
6.4 常见错误排查
| 错误 | 原因 | 解决方法 |
|---|---|---|
| PVC 一直 Pending | 没有匹配的 StorageClass 或 Provisioner 未部署 | 检查 StorageClass 和 Provisioner 状态 |
| WaitForFirstConsumer 卡住 | Pod 未创建或调度失败 | 检查 Pod 状态和节点资源 |
| NFS Provisioner Pod CrashLoopBackOff | NFS 服务端不可达或路径错误 | 检查 NFS 服务状态和网络连通性 |
| 本地存储路径不存在 | 节点未创建目录 | 检查 helper Pod 是否正常执行 |
| PVC 无法绑定 | StorageClass 名称不匹配 | 确认 PVC 的 storageClassName 与 StorageClass 名称一致 |
| NFS 挂载失败 | NFS 客户端未安装 | 在 Worker 节点安装 nfs-common |
下一期预告:Kubernetes(K8s)学习笔记(第十四期):集群存储与有状态应用(下篇):StatefulSet 有状态应用管理。涵盖:StatefulSet 核心特性、Headless Service、PVC 模板、Nginx/etcd/Redis/MySQL 集群部署实践。
--- Compiled and Authored by Whisky --- July 3 rd, 2026