如何在 K8s 中实现指定数据库实例下线?

上期文章介绍了 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-0foo-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-0foo-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

关注小猿姐,一起学习更多云原生技术干货。

相关推荐
JunLan~1 小时前
Rocky Linux 系统安装/部署 Docker
linux·docker·容器
Python私教1 小时前
model中能定义字段声明不存储到数据库吗
数据库·oracle
mqiqe3 小时前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
工业甲酰苯胺3 小时前
MySQL 主从复制之多线程复制
android·mysql·adb
BestandW1shEs3 小时前
谈谈Mysql的常见基础问题
数据库·mysql
重生之Java开发工程师3 小时前
MySQL中的CAST类型转换函数
数据库·sql·mysql
教练、我想打篮球4 小时前
66 mysql 的 表自增长锁
数据库·mysql
Ljw...4 小时前
表的操作(MySQL)
数据库·mysql·表的操作
哥谭居民00014 小时前
MySQL的权限管理机制--授权表
数据库