Kubernetes 中的 Volume(存储卷)

Kubernetes 中的 Volume(存储卷)

Kubernetes 中的 Volume(存储卷)是一个核心概念,用于解决容器中临时存储的限制,并支持有状态应用的数据持久化、共享以及各种外部存储系统的接入。下面将详细介绍 Kubernetes Volume 的设计原理、类型、使用方式以及高级特性。


1. 为什么需要 Volume?

  • 容器生命周期:容器本身是非持久化的,容器重启或删除后内部写入的文件会丢失。Volume 提供与 Pod 生命周期关联的存储,Pod 重启时 Volume 不会消失,Pod 被删除时 Volume 是否清理取决于其类型。

  • 容器间共享:一个 Pod 中的多个容器可能需要共享数据,Volume 可以挂载到同一 Pod 的不同容器中,实现文件共享。

  • 存储解耦:Volume 将存储从容器镜像中解耦,使得有状态应用可以独立于容器运行环境,方便迁移、备份和扩展。

  • 异构存储支持:Kubernetes 通过统一的 Volume 接口对接数十种存储后端(云盘、SAN、NAS、本地存储等),应用无需感知底层存储差异。


2. Volume 的核心概念

2.1 与 Docker Volume 的区别

  • Docker Volume :作用域是单个容器,管理上相对独立,需要通过 docker volume 命令管理。
  • Kubernetes Volume:作用域是 Pod,生命周期与 Pod 绑定,由 kubelet 负责挂载。Pod 中的所有容器都能访问挂载在相同路径下的 Volume。

2.2 Volume 的生命周期

  • 独立于容器:Pod 中的容器崩溃重启,Volume 依然存在并保留数据。
  • 依赖于 Pod:当 Pod 被删除时,Volume 通常也会被清理(具体取决于类型)。但 PV(PersistentVolume)是一种独立于 Pod 的资源,其生命周期由管理员单独管理。

2.3 使用方式

在 Pod 定义中,需要同时指定:

  1. spec.volumes:定义 Pod 有哪些 Volume,每个 Volume 的名称和具体配置。
  2. spec.containers.volumeMounts:将 Volume 挂载到容器的某个路径,可以设置读写权限、挂载传播等。

3. Volume 类型概览

Kubernetes 支持非常丰富的 Volume 类型,根据用途可归为以下几大类:

类别 典型类型 说明
临时存储 emptyDir Pod 运行时创建的临时目录,Pod 删除时数据也被删除;可借助内存(tmpfs)实现高性能临时存储。
本地持久存储 hostPath 挂载宿主机文件或目录到 Pod,不推荐用于生产集群中的长期存储,常用于访问宿主机系统文件(如 Docker 套接字)。
网络存储 nfsiscsifc(光纤通道) 通过已有网络存储系统提供持久化存储,需提前搭建外部存储。
云存储 awsElasticBlockStoreazureDiskgcePersistentDisk 云厂商提供的块存储卷,通常需要云控制器管理器支持。
持久卷(PV/PVC) persistentVolumeClaim 通过 PVC 引用 PV,实现存储与 Pod 定义的解耦,支持静态和动态供给。
配置信息 configMapsecretdownwardAPI 将集群配置信息或 Pod 元数据以文件形式挂载,非持久化存储。
特殊 projected 将多个 Volume 源(Secret、ConfigMap、DownwardAPI 等)合并挂载到同一目录。
CSI csi 容器存储接口,用于对接任意第三方存储插件,已成为扩展存储的主流方式。

4. 持久卷(PV)和持久卷声明(PVC)

这是 Kubernetes 持久化存储的核心抽象,实现了 存储供给存储消费 的分离。

4.1 PV 与 PVC 的设计思想

  • PersistentVolume(PV):由管理员预先制备的存储资源,独立于 Pod 存在。PV 包含存储容量、访问模式、回收策略、存储类型等属性。
  • PersistentVolumeClaim(PVC):用户对存储的请求,类似 Pod 请求 CPU/内存。PVC 指定所需容量、访问模式等,Kubernetes 会寻找符合条件且未被绑定的 PV 进行绑定(一对一绑定)。

4.2 生命周期阶段

  1. Provisioning(供给)

    • 静态供给:管理员预先创建一批 PV。
    • 动态供给:通过 StorageClass 和 Provisioner,当用户创建 PVC 时,自动按需创建底层存储(如云盘),并生成对应的 PV。
  2. Binding(绑定)

    控制平面找到匹配的 PV 并与 PVC 绑定,绑定关系是独占的。

  3. Using(使用)

    Pod 通过 volumes.persistentVolumeClaim 引用 PVC,将 PV 挂载到容器路径。

  4. Reclaiming(回收)

    用户删除 PVC 后,PV 的状态变为 Released,根据其回收策略进行处理:

    • Retain:保留 PV 及其数据,需要管理员手动清理回收。
    • Delete:删除底层存储资源(仅动态供给有效)。
    • Recycle(已废弃):执行 rm -rf 后再次可用,不推荐。

4.3 StorageClass

StorageClass 是动态供给的必备组件,它定义了:

  • Provisioner :存储后端驱动的名称(如 kubernetes.io/aws-ebscsi.kubernetes.io 等)。
  • Parameters:传递给 Provisioner 的参数(如云盘类型、IOPS、文件系统)。
  • ReclaimPolicy:默认的回收策略(Delete/Retain)。
  • MountOptions:挂载选项。
  • AllowVolumeExpansion:是否允许在线扩容。

PVC 可以指定 storageClassName 来选择特定的 StorageClass,实现不同性能层级的存储。


5. 使用 Volume 的示例

5.1 使用 emptyDir 临时存储

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  - image: busybox
    name: log-collector
    volumeMounts:
    - mountPath: /data
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

5.2 使用 PVC 持久化存储

yaml 复制代码
# 创建 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: standard
---
# 在 Pod 中使用
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: data
      mountPath: /usr/share/nginx/html
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: my-pvc

6. 高级主题

6.1 卷快照(VolumeSnapshot)

允许用户创建卷的备份,并从快照恢复新卷。需要支持 CSI 的存储插件以及 VolumeSnapshot 控制器和 CRD。

  • VolumeSnapshotClass:定义快照的 Provisioner 和参数。
  • VolumeSnapshot:请求创建快照。
  • VolumeSnapshotContent:已创建好的快照资源,类似 PV。

6.2 卷扩容(Volume Expansion)

如果 StorageClass 设置了 allowVolumeExpansion: true,用户可以修改 PVC 的容量请求,动态调整底层卷的大小(需存储后端支持)。

6.3 拓扑感知调度(Topology-Aware Scheduling)

对于某些受限的存储(如本地 SSD、某些云盘只能挂载到特定可用区),Kubernetes 可以通过 PV 的节点亲和性、StorageClass 的 allowedTopologies 等机制,确保 Pod 被调度到能够访问该卷的节点上。

6.4 CSI(容器存储接口)

CSI 是社区推荐的 Volume 插件机制,将存储驱动从 Kubernetes 核心代码中解耦。用户只需部署 CSI 驱动(如 Amazon EBS CSI Driver、Ceph CSI、NFS CSI 等),即可像使用内置 Volume 一样使用这些存储。

CSI 支持快照、扩容、裸设备、卷克隆等高级功能。


7. 最佳实践与安全考虑

  1. 避免使用 hostPath:除非用于访问宿主机特殊文件或单节点测试环境,hostPath 在多节点集群中可能导致 Pod 被调度到无数据的节点。
  2. 使用 PVC 模板 :对有状态应用(StatefulSet),利用 volumeClaimTemplates 为每个副本自动创建独立的 PVC。
  3. 设置合适的访问模式
    • ReadWriteOnce:单节点读写。
    • ReadOnlyMany:多节点只读。
    • ReadWriteMany:多节点读写(仅部分存储支持,如 NFS、CephFS)。
  4. 资源限制 :emptyDir 的大小受容器共享的 Pod 临时存储限制,可通过 emptyDir.sizeLimit 设置上限,并使用资源配额。
  5. 加密与敏感数据:Secret 应始终与 RBAC 结合使用,考虑使用第三方加密方案(如 KMS)加密 etcd 中的 Secret。
  6. 备份与恢复:对于有状态应用,应定期对 PV 做快照或备份(使用 Velero 等工具)。
  7. 监控与指标:存储容量、IOPS、延迟应纳入集群监控(如 Prometheus + 相关存储 Exporter)。

8. 总结

Kubernetes Volume 是一个丰富而强大的存储抽象层,既解决了临时存储的共享问题,又通过 PV/PVC 和 CSI 实现了持久化存储的标准化管理。从简单的 emptyDir 到复杂的云存储动态供给,Volume 使得在 Kubernetes 上运行各种有状态工作负载(数据库、消息队列、大数据平台)成为可能。掌握 Volume 的使用和原理,是构建可靠、可扩展的 Kubernetes 应用的关键一环。

相关推荐
小锋学长生活大爆炸8 小时前
【教程】免Root在Termux上安装Docker
运维·docker·容器
进击切图仔8 小时前
常用 Docker 命令备份
运维·docker·容器
阿里云云原生11 小时前
巨人网络《超自然行动组》携手阿里云打造云原生游戏新范式
云原生
我在人间贩卖青春15 小时前
C++之STL容器
c++·容器·stl
71ber16 小时前
深入理解 HAProxy:四层/七层透传与高级 ACL 调度详解
linux·云原生·haproxy
A-刘晨阳16 小时前
K8S 之 DaemonSet
运维·云原生·容器·kubernetes·daemonset
小锋学长生活大爆炸16 小时前
【教程】查看docker容器的TCP连接和带宽使用情况
tcp/ip·docker·容器
ccino .17 小时前
【Drupal文件上传导致跨站脚本执行(CVE-2019-6341)】
运维·网络安全·docker·容器
sun032219 小时前
【Docker】构建镜像时使用的 Dockerfile ,以及其中的 MicroDNF
运维·docker·容器
2501_9481142419 小时前
资深程序员真实测评:9家中转API平台实战横评
微服务·云原生·架构