上期文章介绍了 InstanceSet,同时也介绍了 InstanceSet 针对数据库高可用等需求衍生出的一系列特性。本期我们将介绍 指定实例下线 这一特性,一起来了解这一特性诞生的背景和使用方式吧~
指定实例下线解决了什么问题?
早期版本中,KubeBlocks 最终生成的 Workload 是 StatefulSet,这是一把双刃剑。一方面,KubeBlocks 可以借助 StatefulSet 实现对数据库等有状态应用的管理,另一方面,这也导致 KubeBlocks 继承了 StatefulSet 的局限性。
其中的局限性之一是,在水平缩容场景下,StatefulSet 会按照 Ordinal 顺序从大到小依次下线 Pod。当 StatefulSet 中运行的是数据库时,这个局限性会使得数据库的可用性降低。
我们来分析这样一个场景:比如我们用 StatefulSet 管理了一个一主两从这样的三副本 PostgreSQL 数据库,这个 StatefulSet 的名字叫 foo-bar
,运行一段时间后,名字为 foo-bar-2
的 Pod 成了主节点。
某一天,通过分析我们发现这个数据库的读负载并不是很高,为了节省资源,我们计划对这个数据库进行缩容,下线一个从节点。此时问题来了,按照 StatefulSet 的规则,我们只能下线 foo-bar-2
这个 Pod,但不幸的是它当前是主节点。此时我们有两个选择:要么直接下线 foo-bar-2
,通过 failover 机制,在 foo-bar-0
和 foo-bar-1
中选择一个新的主节点;要么通过 switchover 机制,在下线 foo-bar-2
前,先将其切换成一个从节点。无论选择哪种方式,应用侧都会有一段时间无法写入。
另一个问题是节点所在的物理机故障,恢复流程相关操作较为困难。我们仍以上面的场景为例。某一天,foo-bar-1
所在 Node 因为物理机故障,导致磁盘损坏,最终导致数据无法正常读写。按照数据库运维最佳实践,我们需要将 foo-bar-1
下线,并在其它健康 Node 上搭建新的副本,但基于 StatefulSet 来做这样的运维操作并不容易。
在 Kubernetes 社区中,我们也可以看到类似场景的讨论。
KubeBlocks 从 0.9 版本开始,引入了 InstanceSet ,以替代 StatefulSet,从而支持了"指定实例下线"特性。新版本中,KubeBlocks 可通过修改 replicas 及指定具体实例,实现指定实例的下线,更好地满足实际业务场景的需求。
如何使用指定实例下线特性
在 0.9 版本中,Cluster API 新增了 OfflineInstances 字段,用来指定需要下线的实例名称。
比如前面的场景中,PostgreSQL 集群的当前状态为:
apiVersion: apps.kubeblocks.io/v1alpha1
kind: Cluster
metadata:
name: foo
spec:
componentSpecs:
- name: bar
replicas: 3
# ...
当需要将集群缩容到 2 个副本,并指定下线 foo-bar-1
时,集群对象可做如下更新:
apiVersion: apps.kubeblocks.io/v1alpha1
kind: Cluster
metadata:
name: foo
spec:
componentSpecs:
- name: bar
replicas: 2
offlineInstances: ["foo-bar-1"]
# ...
KubeBlocks 在处理上述 Spec 时,会将集群缩容到 2 个副本,并将 Ordinal 为 1 而不是 2 的 实例下线。最终,集群中留下的实例为: foo-bar-0
和 foo-bar-2
。
在 OpsRequest 中使用该特性
OpsRequest API 支持水平扩缩容操作,从 0.9 开始,API 中新增 OfflineInstances
字段,以便支持指定实例缩容功能。
对于上面的操作,通过 OpsRequest 完成的话,描述如下:
apiVersion: apps.kubeblocks.io/v1alpha1
kind: OpsRequest
metadata:
generateName: foo-horizontalscaling-
spec:
clusterRef: foo
force: false
horizontalScaling:
- componentName: bar
scaleIn:
onlineInstancesToOffline: ["foo-bar-1"]
ttlSecondsAfterSucceed: 0
type: HorizontalScaling
实际执行时,OpsRequest Controller 会将 onlineInstancesToOffline
合并到 Cluster 对象对应的 offlineInstances
中,最终由 Cluster Controller 完成名称为 foo-bar-1
的实例下线任务。
通过修改集群 YAML 或者创建 OpeRequest 运维任务,实现指定实例 foo-bar-1 的下线,打破了 StatefulSet 的局限性,更好地支撑业务需求。更多指定实例水平伸缩的示例可查看官网文档。
注意事项
Cluster API OfflineInstances
需要跟 Replicas 同时修改,才能实现指定实例下线的目标。下面是一些不常用但目前的 API 允许的组合,建议了解后再使用,以免出现非预期后果。
更新前 | 更新后 | 最终实例列表 |
---|---|---|
replicas=3, offlineInstances=[] | replicas=2,offlineInstances=["foo-bar-3"] | foo-bar-0 , foo-bar-1 |
replicas=2, offlineInstances=["foo-bar-1"] | replicas=2, offlineInstances=[] | foo-bar-0 , foo-bar-1 |
replicas=2, offlineInstances=["foo-bar-1"] | replicas=3, offlineInstances=["foo-bar-1"] | foo-bar-0 , foo-bar-2 , foo-bar-3 |
End
KubeBlocks 已发布 v0.9.0!KubeBlocks v0.9.0 全面升级了 API,构建一个 Cluster 更像是在用 Component "搭积木"!新增 topologies
字段,支持多种部署形态。InstanceSet 代替了 StatefulSet 来管理 Pods,支持将指定的 Pod 下线、Pod 原地更新,同时也支持数据库主从架构里主库和从库采用不同的 Pod spec。v0.9.0 还新增了 Reids 集群模式(分片模式),系统的容量、性能以及可用性显著提升!还支持了 MySQL 主备,资源的要求更少,数据复制的开销也更小!快来试试看!
小猿姐诚邀各位体验 KubeBlocks,也欢迎您成为产品的使用者和项目的贡献者。跟我们一起构建云原生数据基础设施吧!
💻 官网: www.kubeblocks.io
🌟 GitHub: https://github.com/apecloud/kubeblocks
🚀 Get started: https://cn.kubeblocks.io/docs/preview/user-docs/try-out-on-playground/try-kubeblocks-on-local-host
关注小猿姐,一起学习更多云原生技术干货。