K8S - Volume 与 PersistentVolume - 容器存储与数据持久化

发布于:2025-05-09 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、引言

在 Kubernetes 中,容器默认采用临时存储(Ephemeral Storage),这意味着 Pod 一旦重启或重建,其内部数据将完全丢失。

然而,在生产环境中,许多关键应用(如数据库、日志系统、内容管理平台)都需要保证数据持久化与高可用性。为此,Kubernetes 提供了以下核心机制:

• Volume:为 Pod 提供临时或持久的存储挂载能力。

• PersistentVolume (PV):集群级别的存储资源抽象,独立于 Pod 生命周期。

• PersistentVolumeClaim (PVC):用户对存储资源的声明,可实现动态或静态绑定 PV。

二、核心原理

2.1 Volume:Pod 级别的存储机制

Volume 是 Pod 内部的存储抽象,其生命周期与 Pod 一致。常见类型如下:

在这里插入图片描述

局限性:

• 临时性存储无法满足数据持久化需求

• 配置复杂,缺乏资源解耦能力

2.2 PV 与 PVC:存储资源的解耦模型

Kubernetes 通过 PV/PVC 模型实现应用与底层存储的解耦:

PersistentVolume(PV)

• 静态供给:管理员预创建,指定容量、访问模式、类型等

• 动态供给:通过 StorageClass自动按需创建(如 AWS EBS)

关键字段:

• capacity: 存储容量,如 1Gi

• accessModes: 访问模式(ReadWriteOnce、ReadOnlyMany等)

• persistentVolumeReclaimPolicy: 回收策略(Retain、Delete)

PersistentVolumeClaim(PVC)

• 用户声明对存储的需求,K8s 自动匹配合适的 PV

StorageClass

• 定义动态供给模板(云存储参数、文件系统类型等)

• 实现 PV 的按需自动化创建

模型关系图:

# 静态供给流程
┌─────────────┐         绑定           ┌─────────────┐
│   PV (预创建)  │ ◄──────────────────── │    PVC      │
└──────┬──────┘                      └──────┬──────┘
       │                                    │
       │              挂载                  │
       ▼                                    ▼
┌───────────────────────────────────────────────────┐
│                        Pod                        │
│          (通过 volumes 字段引用 PVC)                │
└───────────────────────────────────────────────────┘
# 动态供给流程
┌─────────────┐         动态创建         ┌─────────────┐
│ StorageClass │ ───────────────────────►│     PV      │
└───────┬──────┘                         └──────┬──────┘
        │          自动触发                       │
        ▼                                        ▼
┌─────────────┐         绑定           ┌─────────────┐
│    PVC      │ ◄────────────────────── │    Pod     │
└─────────────┘         挂载            └─────────────┘

2.3 核心参数详解

Access Modes(访问模式)

• ReadWriteOnce (RWO):单节点读写(如云硬盘)

• ReadOnlyMany (ROX):多节点只读

• ReadWriteMany (RWX):多节点读写(需 NFS 或分布式存储支持)

Reclaim Policy(回收策略)

• Retain:PVC 删除后保留数据(需手动清理)

• Delete:PVC 删除后自动销毁数据(云平台默认)

• Recycle(已废弃):清空数据再重用(不推荐)

三、实战演示:MySQL 数据持久化

3.1 环境准备(以 Minikube 为例)

# 安装工具
brew install kubectl minikube

# 启动集群
minikube start --driver=docker

3.2 创建 PersistentVolume(静态供给)

步骤 1:定义 PV(测试用 hostPath)

mysql-pv.yaml:

apiVersion: v1
kind: PersistentVolume                  # 资源类型
metadata:
  name: mysql-pv                        # PV名称,集群内唯一标识
spec:
  capacity:
    storage: 1Gi                        # 存储容量(GiB单位)
  accessModes:
    - ReadWriteOnce                     # 访问模式:单节点读写挂载
  persistentVolumeReclaimPolicy: Retain # 回收策略:删除PVC后保留数据(需手动清理)
  hostPath:
    path: /data/mysql                   # 节点本地存储路径(仅适合单节点测试环境)

注:ReadWriteOnce 表示同时只能被一个 Pod 挂载

步骤 2:部署并查看状态

kubectl apply -f mysql-pv.yaml
kubectl get pv   # 状态应为 Available
输出:


NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
mysql-pv   1Gi        RWO            Retain           Available                                   5s

# 注意 STATUS 应为 Available

3.3 创建 PersistentVolumeClaim

步骤 1:定义 PVC

mysql-pvc.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

步骤 2:部署并绑定 PV

kubectl apply -f mysql-pvc.yaml
kubectl get pvc   # 应为 Bound
kubectl get pv    # 状态变为 Bound
输出:

# 部署 PVC 后查看绑定状态
$ kubectl get pvc
NAME        STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pvc   Bound    mysql-pv   1Gi        RWO                           10s

$ kubectl get pv  # PV 状态变化
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               AGE
mysql-pv   1Gi        RWO            Retain           Bound    default/mysql-pvc   2m

3.4 部署 MySQL 并挂载 PVC

步骤 1:定义 Deployment

mysql-deployment.yaml:

apiVersion: apps/v1
kind: Deployment                       
metadata:
  name: mysql                         
spec:
  selector:
    matchLabels:
      app: mysql                      
  template:
    metadata:
      labels:
        app: mysql                  
    spec:
      containers:
        - name: mysql
          image: mysql:8.0            # 使用官方MySQL 8.0镜像
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "password"        # 明文密码(生产环境应用Secret替代)
          ports:
            - containerPort: 3306      # 暴露MySQL默认端口
          volumeMounts:
            - name: mysql-storage
              mountPath: /var/lib/mysql # 挂载数据库存储路径(数据持久化)
      volumes:
        - name: mysql-storage
          persistentVolumeClaim:
            claimName: mysql-pvc        # 绑定预先创建的PVC(需确保存在)

步骤 2:部署并查看 Pod

kubectl apply -f mysql-deployment.yaml
kubectl get pods -l app=mysql
输出:

# 查看 Pod 启动过程(展示完整生命周期)
$ kubectl get pods -l app=mysql --watch
NAME                    READY   STATUS              RESTARTS   AGE
mysql-8c6b66d88-7w2vs   0/1     ContainerCreating   0          10s
mysql-8c6b66d88-7w2vs   1/1     Running             0          25s  # 最终状态

3.5 数据持久化验证

步骤 1:写入测试数据

kubectl exec -it $(kubectl get pod -l app=mysql -o jsonpath="{.items[0].metadata.name}") -- \
  mysql -uroot -ppassword -e "CREATE DATABASE test;"

步骤 2:模拟 Pod 故障并验证数据

kubectl delete pod -l app=mysql
kubectl get pods -l app=mysql   # 等待新 Pod 启动

# 验证是否存在 test 数据库
kubectl exec -it $(kubectl get pod -l app=mysql -o jsonpath="{.items[0].metadata.name}") -- \
  mysql -uroot -ppassword -e "SHOW DATABASES;"
预期结果:应包含 test数据库,验证数据持久化成功。

# 写入测试数据后检查(显示完整输出)
$ kubectl exec -it mysql-8c6b66d88-7w2vs -- mysql -uroot -ppassword -e "SHOW DATABASES;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |  # 新增的测试数据库
+--------------------+

# 删除 Pod 后观察新实例
$ kubectl delete pod mysql-8c6b66d88-7w2vs
pod "mysql-8c6b66d88-7w2vs" deleted

$ kubectl get pods -l app=mysql
NAME                    READY   STATUS    RESTARTS   AGE
mysql-8c6b66d88-kk9xp   1/1     Running   0          45s  # 新 Pod

# 二次验证数据
$ kubectl exec -it $(kubectl get pod -l app=mysql -o name) -- mysql -uroot -ppassword -e "SHOW DATABASES;"
# 若出现错误"Error from server (NotFound): pods not found",说明 Pod 尚未完全启动

四、生产环境最佳实践

在这里插入图片描述

StorageClass 示例(AWS EBS)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-gp3
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3                      # 通用型 SSD
  fsType: ext4                   # 文件系统类型
  iops: "3000"                   # 性能配置(可选)
  encrypted: "true"              # 启用加密

生产环境必须项:

  • 使用 CSI 驱动程序(非树内驱动)

  • 启用存储加密(AWS KMS)

  • 设置合理容量阈值(避免资源浪费)

五、总结

5.1 核心重点

• Volume:适用于 Pod 内部共享临时数据,但无法跨生命周期持久化。

• PV/PVC 模型:解耦存储供应与消费,支持动态供给与多类型后端存储。

• 核心选型建议:

• 根据业务需要选择 accessModes与 reclaimPolicy

• 生产环境优先使用动态供给 + 云存储方案

5.2 常见问题排查表
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到