Kubernetes 持久化存储实战:CSI 驱动 + 动态存储,让有状态应用上 K8s 不再头疼

阿里云上云采购季 2核2G云服务器99元/年 续费同价

很多团队想上 K8s,又怕有状态应用——数据库、消息队列、文件存储,分分钟让你怀疑人生。今天我们从 StorageClass 到 PVC 到 CSI 驱动,手把手搞定 Kubernetes 有状态存储。

痛点:为什么 K8s 存储这么难?

Pod 是无状态的,随时可以漂移。但 MySQL、Elasticsearch、MinIO 这些应用需要持久化数据,一旦 Pod 被调度到其他节点,数据就丢了。

K8s 存储的核心问题:
1. 数据需要跟着 Pod 走(或共享存储)
2. 存储需要先 Provision(创建)才能用
3. 不同云厂商存储方案不同

# 传统方式:手动创建 PV,烦死
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  # 手动指定云厂商的存储卷——每个环境都要改!
  awsElasticBlockStore:
    volumeID: vol-0a2b3c4d5e6f
    fsType: ext4

核心概念:从 StorageClass 到 PVC

存储架构全览

StorageClass (存储类)
    ↓ 动态 Provision
PersistentVolumeClaim (PVC) → 声明需要多少存储
    ↓ 绑定
PersistentVolume (PV) → 实际的存储卷
    ↓ 挂载
Pod → 应用容器

StorageClass:存储的”抽象层”

StorageClass 是 K8s 的存储抽象,不同云厂商、不同存储类型都可以通过同一个接口访问:

# storageclass.yaml - 腾讯云 CBS 为例
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: cbs-high-performance  # StorageClass 名称
provisioner: cloud.tencent.com/qcloud-cbs  # CSI 驱动
parameters:
  type: SSD_CLOUD_BSE          # 存储类型:SSD/高性能/HDD
  zone: ap-guangzhou-3         # 可用区
  encrypted: "true"            # 是否加密
reclaimPolicy: Retain          # Retain(保留)/Delete(删除)
mountOptions:
  - discard                      # 开启 TRIM,SSD 性能优化

动态 Provisioning:PVC 申请 → 自动创建 PV

# pvc.yaml - MySQL 的存储声明
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-data-pvc
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce             # 单节点读写(常用)
    # - ReadOnlyMany           # 多节点只读
    # - ReadWriteMany          # 多节点读写(需要 NFS/CEPH 等)
  resources:
    requests:
      storage: 50Gi             # 请求 50Gi
  storageClassName: cbs-high-performance  # 指定存储类
# 提交后,K8s 自动创建 PV
kubectl apply -f pvc.yaml

# 查看 PVC 状态
kubectl get pvc -n production
# NAME            STATUS   VOLUME                                     CAPACITY   ACCESS MODES
# mysql-data-pvc  Bound    pvc-8a2b3c4d-xxxx-xxxx-xxxx-5e6f7a8b9c0d   50Gi       RWO

# 查看自动创建的 PV
kubectl get pv pvc-8a2b3c4d-xxxx-xxxx-xxxx-5e6f7a8b9c0d
# NAME                                       CAPACITY   RECLAIM POLICY   STATUS   CLAIM
# pvc-8a2b3c4d-xxxx-xxxx-xxxx-5e6f7a8b9c0d   50Gi       Retain           Bound    production/mysql-data-pvc

CSI 驱动:K8s 存储的标准接口

CSI(Container Storage Interface)是 K8s 存储的标准化方案,2019 年 GA 后成为唯一官方支持的存储扩展方式。

主流云厂商 CSI 驱动对比

云厂商 CSI 驱动 支持存储类型 GitHub
腾讯云 tencentcloudyun-csi CBS(云盘)、CFS(文件存储)、COS(对象存储) github.com/TencentCloud/kubernetes-csi-tencentcloud
阿里云 disk-csi-plugin ESSD/SSD/高效云盘、NAS、OSS github.com/kubernetes-sigs/alibaba-cloud-csi-driver
华为云 hwameistor/huaweicloud-csi SSD/超高 IO/普通云硬盘、SFS Turbo、OBS github.com/HuaweiCloudSRE/huaweicloud-csi-plugin
AWS aws-ebs-csi-driver gp3/gp2/io2/io1 github.com/kubernetes-sigs/aws-ebs-csi-driver

部署腾讯云 CSI 驱动

# 方式1:Helm 一键安装(推荐)
helm repo add csi-tencent-cloud https://TencentCloud.github.io/kubernetes-csi-tencentcloud/charts
helm repo update
helm install csi-tencent-cloud/csi-tencent-cloud \
    --namespace kube-system \
    --name csi-tencent-cloud \
    --set cloud.secretID=AKIDxxxxxxxxxx \
    --set cloud.secretKey=xxxxxxxxxxxxxx

# 方式2:手动 YAML 安装
kubectl apply -f https://raw.githubusercontent.com/TencentCloud/kubernetes-csi-tencentcloud/master/deploy/kubernetes/csi-controller.yaml
kubectl apply -f https://raw.githubusercontent.com/TencentCloud/kubernetes-csi-tencentcloud/master/deploy/kubernetes/csi-node.yaml

实战:部署有状态 MySQL 集群

# mysql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  namespace: production
spec:
  serviceName: mysql-headless  # Headless Service 名称
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: root-password
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
        resources:
          requests:
            cpu: "500m"
            memory: "1Gi"
          limits:
            cpu: "2000m"
            memory: "4Gi"
      volumes:
      - name: config
        configMap:
          name: mysql-config
  volumeClaimTemplates:  # 自动创建 PVC
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "cbs-high-performance"
      resources:
        requests:
          storage: 100Gi
# 查看 StatefulSet 和 PVC 关联
kubectl get statefulset -n production
kubectl get pvc -n production
# NAME            STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS
# data-mysql-0    Bound    pvc-xxx  100Gi      RWO            cbs-high-performance
# data-mysql-1    Bound    pvc-yyy  100Gi      RWO            cbs-high-performance
# data-mysql-2    Bound    pvc-zzz  100Gi      RWO            cbs-high-performance

# 每个 MySQL Pod 自动绑定独立的 PVC(数据目录独立)
kubectl get pods -n production -l app=mysql
# NAME    READY   STATUS    RESTARTS   AGE
# mysql-0 1/1     Running   0          2m
# mysql-1 1/1     Running   0          1m
# mysql-2 1/1     Running   0          30s

Volume Snapshots:数据备份与恢复

# volume-snapshot.yaml - 备份 MySQL 数据
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: mysql-snapshot-class
driver: cloud.tencent.com/qcloud-cbs
deletionPolicy: Delete

---
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: mysql-backup-2026-05-19
  namespace: production
spec:
  volumeSnapshotClassName: mysql-snapshot-class
  source:
    persistentVolumeClaimName: data-mysql-0  # 备份 mysql-0 的数据
# 创建快照
kubectl apply -f volume-snapshot.yaml

# 查看快照状态
kubectl get volumesnapshot -n production
# NAME                      READYTOUSE   SOURCEPVC      RESTORESIZE
# mysql-backup-2026-05-19   true         data-mysql-0   100Gi

# 从快照恢复数据到新 PVC
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-restore-pvc
  namespace: production
spec:
  dataSource:
    name: mysql-backup-2026-05-19
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  storageClassName: cbs-high-performance
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Gi
EOF

存储 QoS:保障关键应用性能

# storageclass-with-qos.yaml - 限速存储类
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: cbs-essd
provisioner: cloud.tencent.com/qcloud-cbs
parameters:
  type: ESSD_CLOUD_PLUS    # 顶级 SSD,极低延迟
  performanceLevel: PL3    # 云盘性能等级(PL0-PL3)
  encrypted: "true"
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer  # 等 Pod 调度后再创建 PV
存储类型 性能等级 IOPS 吞吐量 适用场景
SSD 云硬盘 PL0 1,000 50 MB/s 开发测试
SSD 云硬盘 PL1 3,000 100 MB/s 轻量数据库
SSD 云硬盘 PL2 6,000 200 MB/s 中型数据库
ESSD 云硬盘 PL3 50,000+ 500 MB/s+ 核心业务

👤 作者简介

一枚在大中原腹地(河南)卖公有云的女/男士,主营腾讯云/阿里云/华为云,曾踩坑无数,现专注AI大模型应用落地。关注公众号「AI热点日报」,围观AI前沿动态~

博客:y1cloud.cn

发表评论