K8s存储系统(通俗易懂版)
Kubernetes中存储中有四个重要的概念:
Volume、PersistentVolume PV、PersistentVolumeClaim PVC、StorageClass
一、存储系统核心概念
Volume(卷)
定义:Kubernetes 中最基础的存储单元,用于将外部存储挂载到 Pod 中的容器。
特点:
生命周期与 Pod 绑定(Pod 删除则 Volume 销毁,但部分类型如 PV 可持久化)。
支持多种存储类型:本地存储(
emptyDir
、hostPath
)、网络存储(NFS、CephFS)、云存储(AWS EBS、GCE PD)等。
典型用法:
yaml
volumes: # 定义存储类型 - name: datahostPath:path: /mnt/data volumeMounts: # 挂载到容器路径 - name: datamountPath: /app/data
PersistentVolume(PV,持久卷)
定义:集群级别的存储资源(如一块云磁盘、一个 Ceph RBD 镜像),由管理员预先创建。
核心属性:
capacity
:存储容量(如 10Gi)。accessModes
:访问模式(单节点读写ReadWriteOnce
、多节点只读ReadOnlyMany
、多节点读写ReadWriteMany
)。persistentVolumeReclaimPolicy
:回收策略(保留 Retain、删除 Delete)。
示例:
yaml
apiVersion: v1 kind: PersistentVolume metadata:name: ceph-pv spec:capacity: { storage: 10Gi }accessModes: [ReadWriteOnce]cephfs:monitors: ["ceph-mon:6789"]path: /datastorageClassName: ceph-storage
PersistentVolumeClaim(PVC,持久卷声明)
定义:用户对存储资源的“需求清单”,声明所需的存储大小、访问模式等,由 Kubernetes 自动绑定到匹配的 PV。
核心属性:
resources.requests.storage
:请求的存储大小(如 5Gi)。storageClassName
:指定动态供给的存储类型。
示例:
yaml
kind: PersistentVolumeClaim apiVersion: v1 metadata:name: app-data-pvc spec:accessModes: [ReadWriteOnce]resources:requests:storage: 5GistorageClassName: ceph-storage
StorageClass(存储类)
定义:动态供给的模板,定义如何按需创建 PV(例如自动创建云盘或 Ceph RBD 镜像)。
核心属性:
provisioner
:存储驱动(如kubernetes.io/aws-ebs
)。parameters
:存储后端参数(如 Ceph 集群地址)。
示例:
yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:name: ceph-rbd provisioner: kubernetes.io/rbd parameters:monitors: ceph-mon:6789adminId: adminpool: kube
1、工作流程对比
静态供给:
管理员创建PV → 用户创建PVC → 系统绑定PV/PVC → Pod使用PVC
动态供给:
用户创建PVC → StorageClass自动创建PV → 系统绑定 → Pod使用PVC
二、核心流程对比
静态 PV 工作流程
步骤:
管理员创建 PV(如 Ceph RBD 镜像)。
用户创建 PVC,声明存储需求。
Kubernetes 将 PVC 绑定到匹配的 PV。
Pod 挂载 PVC。
痛点:需人工维护大量 PV,存储扩容需手动操作。
动态 PV 工作流程
步骤:
管理员创建 StorageClass(定义存储类型)。
用户创建 PVC,指定 StorageClass。
Kubernetes 自动创建 PV 并绑定 PVC。
Pod 挂载 PVC。
优势:自动化创建存储资源,适合云环境弹性需求。
如果还不清晰,这里用租房子的比喻来解释这四个概念和两种供给模式,再配上实际流程,保证通俗易懂。
三、核心概念和流程比喻(通俗版):
想象你要租房子(需要存储空间):
Volume (卷): 就像你最终拿到手的房子钥匙和门牌号。它定义了具体的存储位置(地址)和如何挂载到你的应用(Pod)里使用(钥匙)。Volume 是 Pod 的一部分配置。
PersistentVolume (PV, 持久卷): 就像城市里可出租的实体房子资源。这些房子是由物业公司(集群管理员)提前建好(配置好)并登记在册的。每套房子(PV)有明确的属性:
大小 (capacity): 比如 80 平米(100Gi)。
访问规则 (accessModes): 是只能一个人住(单节点读写
ReadWriteOnce
),还是可以很多人参观但不能住(多节点只读ReadOnlyMany
),或者可以合租(多节点读写ReadWriteMany
)。地段/特性 (storageClassName): 属于哪个小区、是公寓还是别墅(存储类型,比如
fast-ssd
,ceph-rbd
)。退租处理 (persistentVolumeReclaimPolicy): 租客退租后,房子是保留原样等人再租(
Retain
),还是清空重新装修(旧模式Recycle
,已基本不用),或是直接拆掉(Delete
)。
PersistentVolumeClaim (PVC, 持久卷声明): 就像你提交给租房中介的一份租房需求清单。你告诉中介(Kubernetes 系统):
我要多大 (resources.requests.storage): 至少 60 平米(5Gi)。
我要怎么用 (accessModes): 我一个人住要能做饭洗澡(
ReadWriteOnce
)。我想租哪种类型 (storageClassName): 我想要交通方便的公寓(比如
fast-ssd
)。
StorageClass (SC, 存储类): 就像一个高效的房屋建造和管理中介公司。它定义了:
我们能提供什么类型的房子 (provisioner): 比如“快速公寓建造公司”(
kubernetes.io/aws-ebs
,kubernetes.io/gce-pd
,rbd.csi.ceph.com
)。房子的默认配置 (parameters): 比如默认精装修、带电梯(存储后端的具体参数,如 Ceph 集群地址、池名)。
我们的服务规则: 比如先签合同再建房(
WaitForFirstConsumer
,等 Pod 调度好再创建 PV),或者有现房(立即创建)。
它们之间的关系:
PVC 绑定 PV: 你的租房需求清单 (PVC) 会被中介 (Kubernetes) 拿去匹配现成的房子 (PV)。如果找到大小、类型、访问规则都满足的房子,就把这套房子分配给你(绑定)。Pod 不能直接租房子 (PV),必须通过你的需求清单 (PVC) 来租。
SC 动态创建 PV: 如果中介 (Kubernetes) 发现没有现成的房子 (PV) 能满足你的需求清单 (PVC),并且你的清单里指定了要找某个房屋建造中介公司 (StorageClass),那么中介公司 (SC) 就会立刻根据你的需求清单 (PVC) 自动建造一套新房子 (PV),然后中介 (Kubernetes) 再把这套新房分配给你 (绑定 PVC 和 PV)。
Pod 使用 Volume: 当你 (Pod) 要入住时,中介 (Kubernetes) 会告诉你具体的门牌号和给你钥匙 (Volume)。你 (Pod) 在配置里写明“我要用清单A对应的房子” (引用 PVC 名字),系统就会自动把对应的门牌号和钥匙 (Volume) 配置给你,你就可以搬进去住(把存储挂载到容器里指定路径)了。
静态供给流程 (管理员提前造好房子):
管理员造房 (创建 PV): 集群管理员像物业公司,提前在存储后端(如 NFS 服务器、Ceph 集群)准备好“房子”(存储空间),并在 Kubernetes 里创建
PersistentVolume
(PV) 对象来描述这些房子(大小、访问模式、地址等)。例子: 管理员在 Ceph 里创建了一个 100GB 的 RBD 镜像
image-db
,然后创建 PV:yaml
apiVersion: v1 kind: PersistentVolume metadata:name: pv-ceph-db-100g # 房子名字:Ceph数据库房100G spec:capacity:storage: 100Gi # 大小:100平米accessModes:- ReadWriteOnce # 访问规则:单租客可读写cephfs: # 或者 rbd: 取决于类型monitors:- 10.0.0.1:6789 # Ceph 监控地址path: /data/db # 具体路径 / 池和镜像名user: adminsecretRef:name: ceph-secretpersistentVolumeReclaimPolicy: Retain # 退租处理:保留原样storageClassName: ceph-slow # 地段/类型:Ceph普通盘区
用户提交需求 (创建 PVC): 开发者(用户)编写应用部署文件 (如
deployment.yaml
),在里面声明需要一个PersistentVolumeClaim
(PVC)。例子: 应用需要 80GB 数据库存储,单节点读写。
yaml
apiVersion: v1 kind: PersistentVolumeClaim metadata:name: pvc-mysql-data # 我的需求清单名字:MySQL数据需求 spec:accessModes:- ReadWriteOnce # 我要单租客可读写resources:requests:storage: 80Gi # 我要至少80平米storageClassName: ceph-slow # 我想租Ceph普通盘区的房子 (可选,如果指定必须匹配PV的class)
系统匹配房源 (绑定 PV & PVC): Kubernetes 系统(中介)看到 PVC 需求后,在现成的 PV(房子)里找:
大小满足:PVC 要 80Gi,PV 有 100Gi (80 <= 100,满足)。
访问模式匹配:都是
ReadWriteOnce
。存储类匹配:如果 PVC 指定了
ceph-slow
,PV 也必须是ceph-slow
;如果 PVC 没指定,则匹配没有存储类或任意存储类的 PV(但通常建议明确指定)。找到后,系统将 PV 和 PVC 绑定 (Bound)。PV 的状态从
Available
变成Bound
。
用户入住 (Pod 挂载 Volume): 用户创建 Pod(比如 MySQL 数据库 Pod)。在 Pod 的配置里:
声明要使用哪个 PVC (
pvc-mysql-data
)。指定把存储挂载到容器里的哪个路径 (
/var/lib/mysql
)。
yaml
apiVersion: v1 kind: Pod metadata:name: mysql-pod spec:containers:- name: mysqlimage: mysql:8.0volumeMounts:- name: mysql-storage # 给这个挂载起个名字mountPath: /var/lib/mysql # 容器内的挂载点volumes:- name: mysql-storage # 上面挂载名字对应的存储定义persistentVolumeClaim:claimName: pvc-mysql-data # 使用之前申请的PVC
Pod 运行: Kubernetes 调度 Pod 到某个 Node 上运行。该 Node 上的 kubelet 组件负责:
根据 PVC 找到已绑定的 PV。
根据 PV 的描述(如 Ceph RBD),联系对应的存储系统(Ceph 集群),获取访问权限(挂载)。
将存储挂载到 Node 上的一个临时目录。
将这个临时目录映射(挂载)到 Pod 中容器指定的路径 (
/var/lib/mysql
)。应用启动,读写
/var/lib/mysql
就是在读写持久化的 Ceph 存储。
动态供给流程 (中介按需快速建新房):
管理员找中介公司 (创建 StorageClass): 集群管理员提前创建一个或多个
StorageClass
(SC) 对象。这相当于引入了几家不同风格的房屋建造中介公司,每家公司专长不同(AWS EBS, GCP PD, Ceph RBD, NFS Provisioner 等)。例子: 创建一个负责快速建造 Ceph RBD “公寓”的中介公司:
yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:name: ceph-rbd-fast # 中介公司名:Ceph快速公寓建造 provisioner: rbd.csi.ceph.com # 建造公司类型:Ceph RBD CSI 驱动 (现代标准) parameters: # 建造公司的默认配置clusterID: my-ceph-cluster # Ceph集群IDpool: kube-pool-fast # 用哪个池建房imageFeatures: layering,exclusive-lock # 房子特性csi.storage.k8s.io/provisioner-secret-name: ceph-csi-secretcsi.storage.k8s.io/provisioner-secret-namespace: kube-system reclaimPolicy: Delete # 默认退租处理:拆掉房子 (可选 Retain) volumeBindingMode: WaitForFirstConsumer # 服务规则:等租客确定住哪再建房 (避免建错位置)
用户提交需求 (创建 PVC 并指定 SC): 开发者(用户)编写 PVC,这次明确指定要找哪家中介公司 (StorageClass) 来满足需求。
例子: 应用需要 200GB 高速数据库存储,单节点读写,找
ceph-rbd-fast
公司建房。yaml
apiVersion: v1 kind: PersistentVolumeClaim metadata:name: pvc-mongodb-data # 需求清单:MongoDB数据 spec:accessModes:- ReadWriteOnceresources:requests:storage: 200Gi # 要200平米storageClassName: ceph-rbd-fast # 必须指定:找Ceph快速公寓建造公司!
中介公司立刻建房 (动态创建 PV): Kubernetes 系统(平台)看到 PVC 指定了
ceph-rbd-fast
这个 StorageClass。系统会调用
ceph-rbd-fast
这个 SC 里定义的provisioner
(Ceph RBD CSI 驱动)。CSI 驱动收到指令:“按 PVC 要求(200Gi, RWO)建一套新房!”
CSI 驱动联系 Ceph 集群后端:
在指定的
kube-pool-fast
池里创建一个新的 RBD 镜像 (image),大小 200GB。在 Kubernetes 里自动创建一个对应的
PersistentVolume
(PV) 对象来描述这个新建的 RBD 镜像。
新建的 PV 的
storageClassName
自动设置为ceph-rbd-fast
。系统自动将这个新建的 PV 与发起请求的 PVC 绑定 (Bound)。PVC 的状态直接变成
Bound
。
用户入住 (Pod 挂载 Volume): 和静态流程完全一样!用户创建 Pod,声明使用 PVC
pvc-mongodb-data
,并指定容器内的挂载点。Kubernetes 调度 Pod 并完成挂载。
核心区别总结:
特性 | 静态供给 (Static Provisioning) | 动态供给 (Dynamic Provisioning) |
---|---|---|
PV 创建者 | 管理员手动创建 | StorageClass (通过 Provisioner) 自动创建 |
创建时机 | 在 PVC 出现之前 预先创建好 PV | 在 PVC 出现之后,响应 PVC 请求即时创建 PV |
运维负担 | 高。管理员需预估需求,提前创建、管理大量 PV。 | 低。管理员只需配置好 StorageClass,PV 按需创建。 |
灵活性 | 低。扩容麻烦(需手动操作 PV 和存储后端)。 | 高。PVC 修改大小可能触发自动扩容(需存储后端和 SC 支持)。 |
适用场景 | 存储需求固定、明确;特殊存储配置;不支持动态供给的存储。 | 云环境、容器化平台主流方式;存储需求弹性大;追求自动化。 |
关键组件 | PV, PVC | StorageClass, PVC, (自动创建的 PV) |
比喻 | 管理员提前建好一批毛坯房/精装房放在市场上。 | 引入中介公司,用户提交需求单,中介按需快速建好精装房交付。 |
为什么动态供给是趋势?
自动化: 省去了管理员手动管理 PV 的巨大工作量。
按需分配: 避免资源闲置浪费(静态供给往往需要预先分配较大的 PV)。
敏捷性: 开发者只需关心 PVC 需求,无需等待管理员操作,加速应用部署。
云原生: 完美契合 Kubernetes 声明式 API 和弹性伸缩的理念。
作为小白,记住关键点:
Pod 用 Volume 访问存储。
持久化存储要用 PV 和 PVC。
PV 是“房子”,PVC 是“租房需求单”。
静态供给:管理员提前造好 PV (房子) 等 PVC (需求单) 来租。
动态供给:PVC (需求单) 指定 StorageClass (中介公司),中介公司立刻造好 PV (房子) 并租给你。
生产环境强烈推荐用动态供给!