前言
KusionStack Operating 致力于提供符合 Kubernetes 标准的云原生运维、链路可观测、资源可洞察等能力,以帮助开发者更好地搭建自己的平台。
目前 KusionStack Opearating 已发布到 v0.3.0 版本。在最近版本中,Operating CollaSet 新增对持久卷的配置使用,允许用户声明 VolumeClaimTemplate 为 Pod 创建 PVCs。此外,对于持久化卷变更成本高和难以控制的问题,CollaSet 通过下沉和复用运维经验加以解决,并支持:
1. 用户根据对存储卷的需求,可灵活修改、添加或删除 PVC 模版;
2. 提供对 PVC 生命周期的控制。
01
使用Workload管理持久化卷
持久化卷声明 PVC(PersistentVolumeClaim)能够让用户请求持久化卷 PV (PersistentVolume),为应用的状态提供稳定、持久的存储介质。在无状态 Workload(如 Deployment、DaemonSet)部署的应用中使用持久化卷,需用户手动创建 PVC 并挂载到容器。
无状态 Workload 缺乏对持久化卷的统一管理,为简化持久化卷的使用,社区提供多种有状态 Workload,如 StatefulSet、Advanced StatefulSet、CloneSet 等,它们向用户暴露配置入口 VolumeClaimTemplates(PVC 模版),为每个 Pod 维护独立的 PVC。
|StatefulSet
StatefulSet 是 Kubernetes 中用于部署和管理有状态的应用的原生 Workload API 对象。StatefulSet 为每个 Pod 实例提供稳定、唯一的网络标识符和 PVCs;当 Pod 发生故障时,通过唯一标识将新建的 Pod 与 PVCs 重新关联,以恢复数据和保持弹性。
|Advanced Statefulset
Advanced StatefulSet 是 OpenKruise 基于 StatefulSet 设计的 Workload,增强了原生 StatefulSet 发布、原地升级和 PVC 管理等能力。Advanced StatefulSet 提供对持久卷的生命周期的控制:通过配置保留策略以决定 StatefulSet 和 Pod 生命周期结束时是否级联删除所关联的 PVCs。原生 StatefulSet 在 Kubernetes 1.27 beta 版本后也支持了 PVC 生命周期管理。
|CloneSet
CloneSet 是由 OpenKruise 提供的 Workload,支持原地升级、分批灰度发布和 PVCs 管理等功能。它将持久化卷的管理与运维融合,不同升级方式 PVC 管理策略不同。如原地升级后的 Pod 会复用原持久化卷;重建升级会删除原 Pod 关联的持久化卷并重建。尽管重建升级也为灵活扩展持久化卷提供了可能,但 CloneSet 的设计目标不包括变更 PVC,因此仅变更 PVC 模版不生效。
02
管理持久化卷的痛点
在前文介绍的 Workloads 下,当应用存储空间不足,用户需手动扩展持久化卷,这件事情在大规模的集群下并不容易。原因是它们不感知 PVC 模版变化,因此用户需要手动维护和更新 PVCs(如 StatefulSet 中 PVC 变更事件在 Webhook 被拦截,无法被调和),存在以下痛点:
高风险:过程需删除、重建 Workload,服务被强制中断导致不可用;
高成本:无法复用经验,运维成本高;当部署规模越来越大,问题变得更加突出。
接下来演示一个扩展 StatefulSet 持久卷容量的例子:
|环境准备
1. 部署 K8s 集群,如 Minikube,Kind 等
-
https://minikube.sigs.k8s.io/docs/start/
https://kind.sigs.k8s.io/docs/user/quick-start/
2. 安装 csi-driver-host-path
-
https://github.com/kubernetes-csi/csi-driver-host-path#development
3. 制备可扩展 StorageClass
$ git clone https://github.com/kubernetes-csi/csi-driver-host-path.git
$ kubectl apply -f ./csi-driver-host-path/examples/csi-storageclass.yaml
$ kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
csi-hostpath-sc hostpath.csi.k8s.io Delete Immediate true 30m
4. 使用 sample.yaml 准备一个简单的 StatefulSet
# sample.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sample
spec:
replicas: 2
selector:
matchLabels:
app: sample
template:
metadata:
labels:
app: sample
spec:
containers:
- image: nginx:1.25
name: nginx
volumeMounts:
- mountPath: /path/to/storage
name: foo
volumeClaimTemplates:
- metadata:
name: foo
spec:
storageClassName: csi-hostpath-sc # 使用提前制备的可扩展 StorageClass
volumeMode: Filesystem
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10G
|扩展持久化卷
1. 确保 StorageClass 可扩展
仅部分类型支持扩展,本例中 CSI 类型支持扩展
$ kubectl get storageclass csi-hostpath-sc | grep allowVolumeExpansion
allowVolumeExpansion: true
2. 删除原 StatefulSet,根据需求修改 PVC 模版大小为 20Gi
删除后服务处于不可用状态
$ kubectl delete statefulset sample
statefulset.apps/sample deleted
$ cat statefulset.yaml
...
volumeClaimTemplates:
...
spec:
...
resources:
requests:
- storage: 10Gi
+ storage: 20Gi
...
3. 修改 PVC 容量至 20Gi
$ kubectl edit pvc foo-sample-0
spec:
...
resources:
requests:
- storage: 10Gi
+ storage: 20Gi # 扩展容量至 20Gi
...
4. 使用修改后的 yaml 重新创建 StatefulSet
$ kubectl apply -f statefulset.yaml
statefulset.apps/sample created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
sample-0 1/1 Running 0 18s
sample-1 1/1 Running 0 11s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
foo-sample-0 Bound pvc-80f27a1c-3a39-4e02-8425-2e04e5dd660f 20Gi RWO csi-hostpath-sc 2m5s
foo-sample-1 Bound pvc-ee487d9b-dcd5-4826-a730-6a35f9fc4a52 20Gi RWO csi-hostpath-sc 115s
在以上示例中可以观察到,扩展 StatefulSet 持久化卷流程较为复杂;且部署的应用被删除和重建,难以保证服务持续可用,风险较高。
03
使用CollaSet管理持久化卷
CollaSet 是 Kusionstack Operating 提供的工作负载,为应用 Pod 提供运维、精细化生命周期管理等能力,同时支持部署有状态应用。CollaSet 支持管理持久化卷,包括更新、新增、删除持久化卷,控制持久卷的生命周期,下面通过两个示例展示 CollaSet 如何管理 PVC。
|扩展持久化卷
以下图为例,展示了用户变更持久卷流程,假设用户使用 CollaSet 时对持久卷的需求发生变化,要求将名为 foo 的持久卷扩容至 20Gi。此时用户仅需修改名称为 foo 的 VolumeClaimTemplates,CollaSet 接管复杂的 Pod 和 PVCs 更新替换操作:
删除大小为 10Gi 的持久卷,同时删除 Pod-1,创建 Pod-1';
根据模版 foo 创建大小为 20Gi 的持久卷,并绑定至 PVC-1';
并将 PVC-1' 挂载到 Pod-1';
在 PVC 扩展时,用户可选择是否保留原 PVC-1。通过配置保留策略 whenScaled=Retain 以保留原 PVC-1,此时用户回滚至 10G 版本,原 PVC-1 将被自动挂回 Pod。若用户不再需要原始 PVC 数据,通过配置 whenScaled=Delete 删除 PVC-1。
|新增持久化卷
接着以上示例,假设用户进一步要求为每个 Pod 新增持久卷,以下图为例,用户在 PVC 模版列表新增一个名为 www 的持久卷,CollaSet 感知 PVC 模版列表新增,并自动创建挂载 PVC:
删除 Pod-1',创建 Pod-1'';
创建 PVC-2;
PVC-2 与 PVC1'' 挂载到 Pod-1''。
|试一试
0. 安装 Operating
-
https://www.kusionstack.io/docs/operating/started/install
1. 基于前示例中 sample.yaml 准备 CollaSet
# cat sample.yaml
- apiVersion: apps/v1
- kind: StatefulSet
+ apiVersion: apps.kusionstack.io/v1alpha1
+ kind: CollaSet
...
spec:
- replicas: 2
+ replicas: 1
$ kubecel apply -f sample.yaml
collaset.apps.kusionstack.io/sample created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
sample-fn928 1/1 Running 0 13s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
sample-foo-4hhjz Bound pvc-cf5b0db4-810f-4530-ae3c-33f8d3bb0ba0 10Gi RWO csi-hostpath-sc 17s
2. 更新、添加 PVC 模版
# cat sample.yaml
template:
...
spec:
containers:
...
volumeMounts:
...
+ - mountPath: /path/to/storage-www
+ name: www
...
volumeClaimTemplates:
- metadata:
name: foo
spec:
...
resources:
requests:
- storage: 10Gi
+ storage: 20Gi # 修改存储容量至 20Gi
storageClassName: csi-hostpath-sc
volumeMode: Filesystem
+ - metadata:
+ name: www # 新增名 PVC 模版
+ spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 20Gi
+ storageClassName: csi-hostpath-sc
+ volumeMode: Filesystem
$ kubectl apply -f sample.yaml
collaset.apps.kusionstack.io/sample configured
3. 验证 Pod 与 PVC 状态,观察到 Pod 和 PVC 被重建和挂载
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
sample-fn928 1/1 Terminating 0 101s
sample-k8wtz 0/1 ContainerCreating 0 4s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
sample-foo-w42vm Bound pvc-f9e525e9-174f-4bcf-9218-d22fc21c81a2 20Gi RWO csi-hostpath-sc 6s
sample-www-ns7c7 Bound pvc-8ced1205-e447-43b0-a598-7e6ef2584073 20Gi RWO csi-hostpath-sc 6s
可以观察到 PVC 变更过程无需删除 Workload,服务保持可用;过程中用户也可以使用 ReplaceUpdate 或 Partition 等发布策略保证服务质量。更多内容详见 CollaSet 手册:https://www.kusionstack.io/docs/operating/manuals/collaset。
总结
持久化数据是支撑有状态应用的基础,现有工作负载通过管理 PVC 支持有状态应用,具有许多优点,如优雅管理 PVC 生命周期、与 Pod 运维兼容等。当用户的需求发生变化,需要扩展、删除、新增持久化卷时需要人工介入,且存在风险。为更好地支持有状态应用,CollaSet 将人工管理运维经验下沉,感知 PVC 变更,以提升效率和降低风险。
更多的云原生运维能力还等着我们探索和发现,也欢迎大家一起参与共建!
欢迎 star ⭐️
https://github.com/KusionStack/kusion
https://github.com/KusionStack/operating
https://github.com/KusionStack/controller-mesh
https://github.com/KusionStack/resource-consist
https://github.com/KusionStack/kube-utils
https://github.com/kcl-lang/kcl