存储架构深度剖析

概述

Kubernetes 存储系统是一个复杂的多层架构,涉及 PV、PVC、StorageClass、CSI 等多个组件。本文深入剖析存储系统的工作原理、生命周期管理和源码实现。

核心架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
┌──────────────────────────────────────────────────────────────────────────────┐
│ 用户层 │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Pod │ │ ConfigMap │ │ Secret │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
└─────────┼─────────────────┼─────────────────┼───────────────────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ Volume (卷) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Volume 类型 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │emptyDir │ │hostPath │ │configMap │ │ secret │ │ │
│ │ │临时存储 │ │节点路径 │ │配置卷 │ │密钥卷 │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ PVC │ │ CSI │ │downwardAPI│ │projected │ │ │
│ │ │持久卷声明 │ │存储接口 │ │元数据卷 │ │投射卷 │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────┐
│ PersistentVolume (持久卷) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ PV 类型 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ GCE PD │ │ AWS EBS │ │ AzureDB │ │ NFS │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Ceph │ │ Gluster │ │ iSCSI │ │ FC │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ StorageClass (存储类) │ │
│ │ - 动态 Provisioning │ │
│ │ - 回收策略 (Retain/Delete/Recycle) │ │
│ │ - 绑定模式 (Immediate/WaitForFirstConsumer) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────┐
│ CSI (容器存储接口) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ CSI Driver │ │ CSI Identity│ │ CSI Node │ │ CSIControll│ │
│ │ (存储插件) │ │ (身份服务) │ │ (节点服务) │ │ (控制器) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ CSI RPC 接口 │ │
│ │ Identity, Controller, Node │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘

PV 和 PVC 生命周期

生命周期状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──────────────────────────────────────────────────────────────────────────────┐
│ PV 生命周期 │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐│
│ │ Pending │ -> │Available│ -> │ Bound │ -> │ Released│ -> │ Failed ││
│ │ (创建中) │ │(可用) │ │ (已绑定) │ │(已释放) │ │ (失败) ││
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 状态转换: │ │
│ │ Pending -> Available: PV 创建中,等待 Provider 准备完成 │ │
│ │ Available -> Bound: PVC 绑定到此 PV │ │
│ │ Bound -> Released: PVC 删除 │ │
│ │ Released -> Failed: 回收失败 │ │
│ │ Released -> Available: 手动回收,重新可用 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘

回收策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// staging/src/k8s.io/api/core/v1/types.go

type PersistentVolumeReclaimPolicy string

const (
// Retain: 保留,手动回收
PersistentVolumeReclaimRetain PersistentVolumeReclaimPolicy = "Retain"

// Delete: 删除卷和后端存储
PersistentVolumeReclaimDelete PersistentVolumeReclaimPolicy = "Delete"

// Recycle: 删除数据,重新可用 (已废弃)
PersistentVolumeReclaimRecycle PersistentVolumeReclaimPolicy = "Recycle"
)

StorageClass

核心字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: pd.csi.storage.gke.io # 供应者
parameters:
type: pd-standard
replication-type: regional-pd
reclaimPolicy: Delete # 回收策略
volumeBindingMode: WaitForFirstConsumer # 绑定模式
allowVolumeExpansion: true # 允许扩容
mountOptions:
- hard
- noatime

绑定模式

1
2
3
4
5
6
7
# 立即绑定
volumeBindingMode: Immediate
# 创建 PV 后立即绑定,可能调度到无存储的节点

# 延迟绑定 (推荐)
volumeBindingMode: WaitForFirstConsumer
# Pod 调度后绑定,选择有存储的节点

CSI 架构

组件架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
┌──────────────────────────────────────────────────────────────────────────────┐
│ Kubernetes 集群 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ kube-controller-manager │ │
│ │ │ │
│ │ ┌───────────────────────────────────────────────────────────────┐ │ │
│ │ │ attachdetach controller │ │ │
│ │ │ - 挂载/卸载 Volume 到节点 │ │ │
│ │ └───────────────────────────────────────────────────────────────┘ │ │
│ │ ┌───────────────────────────────────────────────────────────────┐ │ │
│ │ │ PV controller │ │ │
│ │ │ - PV/PVC 生命周期管理 │ │ │
│ │ │ - 触发 Volume Provisioning │ │ │
│ │ └───────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ gRPC │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ External Provisioner │ │
│ │ (sidecar: provisioner) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ CSI Controller │ │ │
│ │ │ CreateVolume / DeleteVolume / ControllerPublishVolume │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ gRPC │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ CSI Driver (存储提供商) │ │
│ │ │ │
│ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │
│ │ │ Identity Svc │ │ Controller Svc │ │ Node Svc │ │ │
│ │ │ 插件信息 │ │ 卷管理 │ │ 节点操作 │ │ │
│ │ └────────────────┘ └────────────────┘ └────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────┐
│ Kubelet (节点侧) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Volume Manager │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Attacher │ │ Mounter │ │ Unmounter │ │ │
│ │ │ 挂载设备 │ │ 挂载文件系统│ │ 卸载文件系统│ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ gRPC │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ CSI Node Driver Registrar │ │
│ │ (sidecar: node-driver-registrar) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ CSI Node Plugin (存储提供商) │ │
│ │ NodeStageVolume / NodePublishVolume / NodeUnpublishVolume │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘

CSI RPC 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// CSI 接口定义 (csi-driver/specs/csi.proto)

service Identity {
rpc GetPluginInfo(GetPluginInfoRequest) returns (GetPluginInfoResponse) {}
rpc GetPluginCapabilities(GetPluginCapabilitiesRequest) returns (GetPluginCapabilitiesResponse) {}
rpc Probe (ProbeRequest) returns (ProbeResponse) {}
}

service Controller {
rpc CreateVolume (CreateVolumeRequest) returns (CreateVolumeResponse) {}
rpc DeleteVolume (DeleteVolumeRequest) returns (DeleteVolumeResponse) {}
rpc ControllerPublishVolume (ControllerPublishVolumeRequest) returns (ControllerPublishVolumeResponse) {}
rpc ControllerUnpublishVolume (ControllerUnpublishVolumeRequest) returns (ControllerUnpublishVolumeResponse) {}
rpc ValidateVolumeCapabilities (ValidateVolumeCapabilitiesRequest) returns (ValidateVolumeCapabilitiesResponse) {}
rpc ListVolumes (ListVolumesRequest) returns (ListVolumesResponse) {}
rpc GetCapacity (GetCapacityRequest) returns (GetCapacityResponse) {}
rpc ControllerGetCapabilities (ControllerGetCapabilitiesRequest) returns (ControllerGetCapabilitiesResponse) {}
}

service Node {
rpc NodeStageVolume (NodeStageVolumeRequest) returns (NodeStageVolumeResponse) {}
rpc NodeUnstageVolume (NodeUnstageVolumeRequest) returns (NodeUnstageVolumeResponse) {}
rpc NodePublishVolume (NodePublishVolumeRequest) returns (NodePublishVolumeResponse) {}
rpc NodeUnpublishVolume (NodeUnpublishVolumeRequest) returns (NodeUnpublishVolumeResponse) {}
rpc NodeGetId (NodeGetIdRequest) returns (NodeGetIdResponse) {}
rpc NodeGetCapabilities (NodeGetCapabilitiesRequest) returns (NodeGetCapabilitiesResponse) {}
}

Volume 挂载流程

Pod 创建时的卷挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
┌──────────────────────────────────────────────────────────────────────────────┐
│ Kubelet 收到 Pod 创建请求 │
└──────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────┐
│ VolumeManager 处理卷 │
│ pkg/kubelet/volumemanager/volume_manager.go │
│ │
│ 1. 等待卷准备完成 │
│ - 等待 PVC 绑定 │
│ - 等待卷设备挂载 │
│ 2. 获取期望的卷挂载信息 │
│ - 卷路径 │
│ - 挂载选项 │
│ - SELinux 上下文 │
└──────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────┐
│ CSI Controller 操作 │
│ │
│ 1. CreateVolume (如果有 Provisioner) │
│ - 调用存储后端创建卷 │
│ - 返回 volumeId │
│ │
│ 2. ControllerPublishVolume │
│ - 将卷附加到节点 │
│ - 返回设备路径 (/dev/disk/by-id/...) │
└──────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────┐
│ CSI Node 操作 │
│ │
│ 1. NodeStageVolume │
│ - 格式化 (如果需要) │
│ - 挂载到临时目录 /var/lib/kubelet/plugins/<plugin>/mounts/<volume>/ │
│ - 配置挂载选项 │
│ │
│ 2. NodePublishVolume │
│ - 从临时目录绑定挂载到容器路径 │
│ - /var/lib/kubelet/pods/<pod-uid>/volumes/<plugin>/<volume>/ │
│ - -> <container-path>/ │
└──────────────────────────────────────────────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────────────┐
│ 卷挂载完成 │
│ │
│ Pod 可以启动容器 │
└──────────────────────────────────────────────────────────────────────────────┘

Volume 挂载代码路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// pkg/kubelet/volumemanager/reconciler/reconciler.go

func (rc *Reconciler) reconcile() {
// 1. 挂载期望的卷
for _, volume := range rc.desiredVolumes {
if !rc.actualVolumes.Has(volume) {
// 执行挂载
err := rc.mounter.MountVolume(
volume,
rc.nodeName,
)
}
}

// 2. 卸载不需要的卷
for _, volume := range rc.actualVolumes {
if !rc.desiredVolumes.Has(volume) {
// 执行卸载
err := rc.unmounter.UnmountVolume(volume)
}
}
}

Attach/Detach 流程

AttachDetach Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// pkg/controller/volume/attachdetach/attach_detach_controller.go

func (adc *AttachDetachController) syncVolumes() {
// 1. 获取所有需要挂载的 Pod
desiredVolumes := adc.getDesiredVolumes()

// 2. 获取当前已挂载的卷
attachedVolumes := adc.getAttachedVolumes()

// 3. 挂载新需要的卷
for _, vol := range desiredVolumes.Difference(attachedVolumes) {
adc.attachVolume(vol)
}

// 4. 卸载不需要的卷
for _, vol := range attachedVolumes.Difference(desiredVolumes) {
if !adc.isInUse(vol) {
adc.detachVolume(vol)
}
}
}

关键代码路径

文件 说明
pkg/controller/volume/pv_controller.go PV Controller
pkg/controller/volume/attachdetach/ Attach/Detach Controller
pkg/kubelet/volumemanager/ Kubelet Volume Manager
pkg/volume/ Volume 插件接口
staging/src/k8s.io/csi-client/ CSI 客户端
staging/src/k8s.io/api/core/v1/types.go PV/PVC 类型定义

常见问题排查

1. PVC 一直处于 Pending

1
2
3
4
5
6
7
8
# 检查 StorageClass
kubectl get sc

# 检查 Provisioner Pod
kubectl get pods -n kube-system -l app=PD_CSI_DRIVER

# 检查 PVC 事件
kubectl describe pvc <pvc-name>

2. 卷挂载失败

1
2
3
4
5
6
7
8
# 检查 kubelet 日志
journalctl -u kubelet | grep volume

# 检查 CSI Driver
kubectl get pods -n kube-system -l app=CSI_DRIVER

# 检查卷状态
kubectl describe pv <pv-name>

3. 存储卷不可扩容

1
2
3
4
5
# 检查 StorageClass
kubectl get sc <sc-name> -o yaml

# 检查 PVC
kubectl get pvc <pvc-name> -o jsonpath='{.spec.resources}'

存储卷类型对比

类型 说明 使用场景
emptyDir 临时存储,Pod 删除后丢失 临时缓存、共享存储
hostPath 节点路径 单节点测试、宿主机访问
persistentVolumeClaim 持久卷 有状态应用
configMap 配置信息 应用配置
secret 敏感信息 证书、密钥
downwardAPI Pod 元数据 Pod 信息注入
projected 投射卷 多种卷合一

面试题

基础题

1. PV 和 PVC 的区别是什么?

参考答案:

  • **PV (PersistentVolume)**:集群级别的存储资源,由管理员或 StorageClass 动态创建
  • **PVC (PersistentVolumeClaim)**:用户对存储的请求,可以请求特定大小和访问模式

2. StorageClass 的作用是什么?

参考答案:

  • 定义存储类型和供应者
  • 支持动态 Provisioning(自动创建 PV)
  • 配置回收策略、绑定模式等

3. 存储卷的回收策略有哪些?

参考答案:

  • Retain:保留数据,手动回收
  • Delete:删除卷和后端存储
  • Recycle:删除数据,重新可用(已废弃)

中级题

4. CSI 的三大服务是什么?各自职责?

参考答案:

服务 职责 运行位置
Identity 提供插件信息、能力列表 Controller
Controller 卷的 CRUD、挂载/卸载 Controller
Node 节点级别的格式化、挂载 Node

5. 延迟绑定 (WaitForFirstConsumer) 有什么好处?

参考答案:

  • Pod 调度后再绑定 PVC
  • 避免 Pod 调度到无存储的节点
  • 提高存储卷的可绑定性
  • 减少不必要的存储资源浪费

6. Volume 挂载的完整流程是什么?

参考答案:

  1. PV Controller 创建/绑定 PV
  2. AttachDetach Controller 将卷附加到节点
  3. CSI Controller 调用 CreateVolume
  4. CSI Controller 调用 ControllerPublishVolume
  5. Kubelet 调用 NodeStageVolume
  6. Kubelet 调用 NodePublishVolume
  7. 容器启动,使用卷

7. 如何实现 ReadWriteMany (多节点读写)?

参考答案:

  • 支持 RWX 的存储后端:NFS、GlusterFS、CephFS
  • 不支持 RWX:AWS EBS、GCE PD(仅 RWO)
  • 使用 NFS 作为共享存储:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    apiVersion: v1
    kind: PersistentVolume
    spec:
    storageClassName: nfs
    persistentVolumeReclaimPolicy: Retain
    accessModes:
    - ReadWriteMany
    nfs:
    server: nfs-server
    path: /exports

高级题

8. CSI 的扩展机制是怎样的?

参考答案:
CSI 通过 gRPC 与存储提供商通信:

1
2
3
4
5
6
7
8
9
10
11
// CSI Driver 注册
type CSIDriver interface {
DriverGetInfo(ctx context.Context, req *GetInfoRequest) (*GetInfoResponse, error)
DriverGetCapabilities(ctx context.Context, req *GetCapabilitiesRequest) (*GetCapabilitiesResponse, error)
CreateVolume(ctx context.Context, req *CreateVolumeRequest) (*CreateVolumeResponse, error)
DeleteVolume(ctx context.Context, req *DeleteVolumeRequest) (*DeleteVolumeResponse, error)
ControllerPublishVolume(ctx context.Context, req *ControllerPublishVolumeRequest) (*ControllerPublishVolumeResponse, error)
ControllerUnpublishVolume(ctx context.Context, req *ControllerUnpublishVolumeRequest) (*ControllerUnpublishVolumeResponse, error)
NodeStageVolume(ctx context.Context, req *NodeStageVolumeRequest) (*NodeStageVolumeResponse, error)
NodePublishVolume(ctx context.Context, req *NodePublishVolumeRequest) (*NodePublishVolumeResponse, error)
}

9. 如何实现存储卷的扩容?

参考答案:

  1. 启用扩容

    1
    2
    3
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    allowVolumeExpansion: true
  2. 请求扩容

    1
    kubectl patch pvc my-pvc -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'
  3. CSI 扩容流程

    1
    ControllerExpandVolume -> NodeExpandVolume -> 完成

10. PV Controller 的工作原理是什么?

参考答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// pkg/controller/volume/pv_controller.go

func (ctrl *PersistentVolumeController) syncClaimKey(key string) {
// 1. 获取 PVC
claim := getPVCFromCache(key)

// 2. 根据 PVC 状态处理
switch claim.Status.Phase {
case v1.ClaimPending:
// 尝试绑定已有 PV
if volume := ctrl.findBestMatchPV(claim); volume != nil {
ctrl.bindClaimToVolume(claim, volume)
}
// 或触发动态 Provisioning
if claim.Spec.StorageClassName != nil {
ctrl.provisionClaim(claim)
}
case v1.ClaimBound:
// 已绑定,无需处理
case v1.ClaimLost:
// 回收 PV
ctrl.reclaimVolume(claim.Spec.VolumeName)
}
}

场景题

11. 如何排查存储卷挂载慢的问题?

参考答案:

  1. 检查 CSI Driver 状态

    1
    kubectl get pods -n kube-system -l app=csi-driver
  2. 检查 Attach 操作

    1
    kubectl describe pv <pv-name> | grep Attach
  3. 常见原因

    • CSI Driver 未就绪
    • 云存储 API 限流
    • 网络延迟
    • 卷正在格式化

12. 如何实现本地存储 (Local PV)?

参考答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 1. 创建本地磁盘 (节点上)
# mkfs.ext4 /dev/sdb

# 2. 创建 Local PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv
spec:
storageClassName: local-storage
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
local:
path: /mnt/disks/sdb
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node-1

# 3. 创建 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

13. 如何保护有状态应用的数据?

参考答案:

  1. 使用 ReadWriteOnce 卷:单节点访问
  2. 设置 Retain 回收策略:防止数据意外删除
  3. 启用 VolumeSnapshot:备份数据
    1
    2
    3
    4
    5
    6
    7
    8
    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
    name: my-snapshot
    spec:
    volumeSnapshotClassName: csi-gcp-pd
    source:
    persistentVolumeClaimName: my-pvc
  4. 使用 StatefulSet:保证 Pod 和 PVC 的绑定关系
  5. 配置 Pod Disruption Budget:防止同时删除多个副本