如何在 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

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

相关推荐
做梦敲代码24 分钟前
达梦数据库-读写分离集群部署
数据库·达梦数据库
苹果醋31 小时前
2020重新出发,MySql基础,MySql表数据操作
java·运维·spring boot·mysql·nginx
小蜗牛慢慢爬行1 小时前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
hanbarger1 小时前
nosql,Redis,minio,elasticsearch
数据库·redis·nosql
微服务 spring cloud1 小时前
配置PostgreSQL用于集成测试的步骤
数据库·postgresql·集成测试
先睡2 小时前
MySQL的架构设计和设计模式
数据库·mysql·设计模式
弗罗里达老大爷2 小时前
Redis
数据库·redis·缓存
仰望大佬0072 小时前
Avalonia实例实战五:Carousel自动轮播图
数据库·microsoft·c#
学不透java不改名2 小时前
sqlalchemy连接dm8 get_columns BIGINT VARCHAR字段不显示
数据库