欢迎光临
我们一直在努力

云原生存储:PV/PVC、StatefulSet 与数据库部署

“Kubernetes 不是只适合无状态服务吗?数据库怎么能跑在 K8s 上?”
“Pod 一删数据就没了,怎么持久化?”
“StatefulSet 和 Deployment 有什么区别?”

如果你对有状态服务上云原生仍有疑虑,说明你还没掌握 PV/PVC、StorageClass 和 StatefulSet 这三大核心机制。

事实上,MySQL、Redis、PostgreSQL 等数据库早已在生产环境中稳定运行于 Kubernetes。关键在于理解云原生存储模型,并规避常见陷阱。本文将带你从原理到实战,安全、可靠地部署有状态服务。


一、PV / PVC:持久卷的声明式管理

Kubernetes 通过 PersistentVolume(PV) 和 PersistentVolumeClaim(PVC) 解耦存储供给与使用。

  • PV:集群中的存储资源(如一块云盘),由管理员或 StorageClass 动态创建;
  • PVC:用户对存储的“申请”,声明所需容量与访问模式。

工作流程:

  • 用户创建 PVC,声明“我需要 10Gi 可读写存储”;
  • K8s 自动匹配或动态创建 PV;
  • Pod 通过 volume 挂载 PVC,实现数据持久化。
  • # PVC 示例
    apiVersion: v1
    kind: PersistentVolumeClaim
    meta
    name: mysql-pvc
    spec:
    accessModes:
    – ReadWriteOnce
    resources:
    requests:
    storage: 20Gi

    ✅ 优势:应用无需关心底层是本地 SSD、云盘还是 NFS,只需声明需求。


    二、StorageClass:动态供给的引擎

    StorageClass 定义了存储的“类型”和“供给方式”。

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    meta
    name: ssd
    provisioner: kubernetes.io/aws-ebs
    parameters:
    type: gp3
    fsType: ext4
    volumeBindingMode: WaitForFirstConsumer

    • provisioner:指定存储驱动(如 AWS EBS、阿里云云盘、Ceph RBD);
    • volumeBindingMode: WaitForFirstConsumer:延迟绑定,确保 PV 在 Pod 所在节点创建,避免跨 AZ 挂载失败。

    ⚠️ 避坑:若未设置 WaitForFirstConsumer,PV 可能在任意 AZ 创建,导致 Pod 调度失败(云盘通常不能跨 AZ 挂载)。


    三、StatefulSet:为有状态服务而生

    Deployment 适用于无状态服务,而 StatefulSet 专为有状态负载设计,提供三大特性:

    1. 稳定的网络标识

    • Pod 名称固定:mysql-0, mysql-1;
    • DNS 记录稳定:mysql-0.mysql.default.svc.cluster.local。

    2. 有序部署与扩缩容

    • 启动顺序:mysql-0 → mysql-1 → mysql-2;
    • 删除顺序:反向进行,确保主从切换安全。

    3. 持久化存储绑定

    • 每个 Pod 绑定独立 PVC,即使 Pod 被删除重建,数据仍保留。

    apiVersion: apps/v1
    kind: StatefulSet
    meta
    name: mysql
    spec:
    serviceName: mysql # Headless Service 名称
    replicas: 3
    template:
    spec:
    containers:
    – name: mysql
    image: mysql:8.0
    volumeMounts:
    – name: data
    mountPath: /var/lib/mysql
    volumeClaimTemplates:
    – meta
    name: data
    spec:
    accessModes: ["ReadWriteOnce"]
    storageClassName: "ssd"
    resources:
    requests:
    storage: 20Gi

    💡 serviceName 必须指向一个 Headless Service(clusterIP: None),才能生成稳定的 DNS 记录。


    四、实战:在 K8s 中部署 MySQL + Redis

    4.1 MySQL 单实例(开发/测试)

    # Headless Service
    apiVersion: v1
    kind: Service
    meta
    name: mysql
    spec:
    clusterIP: None
    ports:
    – port: 3306
    selector:
    app: mysql

    # StatefulSet(略,见上文)

    4.2 Redis 主从(使用官方 Helm Chart)

    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm install redis bitnami/redis –set replica.replicaCount=2

    Bitnami Chart 已内置:

    • StatefulSet 管理主从;
    • PVC 持久化;
    • 健康检查与故障转移。

    4.3 备份策略(关键!)

    有状态服务必须配套备份方案:

    • MySQL:定期执行 mysqldump,输出到 S3/OSS;
    • Redis:启用 RDB 快照 + AOF,或使用 redis-cli –rdb 触发备份;
    • 自动化:通过 CronJob 定期运行备份脚本。

    # CronJob 示例
    apiVersion: batch/v1
    kind: CronJob
    meta
    name: mysql-backup
    spec:
    schedule: "0 2 * * *" # 每天凌晨2点
    jobTemplate:
    spec:
    template:
    spec:
    containers:
    – name: backup
    image: mysql:8.0
    command: ["/bin/sh", "-c"]
    args:
    – mysqldump -h mysql -u root -p$MYSQL_ROOT_PASSWORD mydb > /backup/mydb_$(date +%F).sql
    volumeMounts:
    – name: backup-storage
    mountPath: /backup
    volumes:
    – name: backup-storage
    persistentVolumeClaim:
    claimName: backup-pvc

    🔗 交叉引用:数据库部署方案需结合《微服务》【数据篇】的分库分表策略,避免单点瓶颈。即使上了 K8s,单实例 MySQL 仍无法支撑高并发写入。


    五、避坑指南:本地存储 vs 云盘性能差异

    存储类型

    性能

    可靠性

    适用场景

    本地 SSD

    极高

    临时缓存、测试

    云盘(gp3/io2)

    生产数据库

    NFS

    共享配置、日志

    ⚠️ 严重警告:

    • 不要用 hostPath 或 local PV 跑生产数据库!节点故障 = 数据丢失;
    • 云盘虽有 IOPS 限制,但具备多副本、快照、跨 AZ 高可用能力;
    • 对性能敏感场景,可选用 io2(AWS)或 ESSD PL3(阿里云)。

    六、有状态服务架构图


    结语:有状态服务上 K8s,可行且可控

    Kubernetes 不再只是“无状态容器平台”。通过 PV/PVC + StatefulSet + StorageClass,你可以安全运行数据库、消息队列、AI 模型等有状态负载。

    但请牢记:

    • 永远不要省略备份;
    • 优先选择云厂商托管存储;
    • 结合分库分表等应用层策略,避免单点瓶颈。
    赞(0)
    未经允许不得转载:171主机测评 » 云原生存储:PV/PVC、StatefulSet 与数据库部署
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址