大家下午好,我是来自 ApeCloud 的吴学强,非常高兴能够在 KubeCon 做分享。今天的分享由我和来自快手的刘裕惺同学共同完成,我们分享的主题是将大规模的 Redis 实例从裸机迁移到 Kubernetes 上来提高资源的利用率。
我们今天的议题包括几个方面,首先我会来简单介绍一下 KubeBlocks 项目。第二部分我会从单个 Redis 集群的视角来讲一下 KubeBlocks 解决了哪些问题,从而能够让包括 Redis 在内的各种数据库可以更好地跑在 K8s 上面。接下来裕惺会站在大规模的视角来讲一下,分享多个 Redis 集群跑在多个 K8s 集群上的一些经验,最后是一个简单的总结。
什么是 KubeBlocks?
首先我们来了解一下 KubeBlocks 这个项目。我们是一家创业公司,团队的大部分小伙伴都来自于阿里云数据库,这意味着我们团队有非常多的数据库开发和运维经验。两年前我们开始创业,我们选择的创业方向是开发一些产品,能够使数据库更好地运行在 K8s 上。
去年我们开源了 KubeBlocks 项目,简单来说,它是 K8s 上的一个 Operator,跟其他数据库 Operator 不一样的地方在于,KubeBlocks 可以同时支持非常多类型的数据库。可以看到目前 KubeBlocks 已经支持了 35 种数据库。
为了达到这样的一个目标,在设计 KubeBlocks 的 API 或叫 CRD 时,我们将它们分成了两类,第一类面向数据库提供者,我们称之为 Add-on Provider API,通过这些 API,可以很容易地将新的数据库接入到 KubeBlocks 系统当中。
第二类是面向数据库的使用者和运维者的,我们称之为 Developer&DevOps API,通过这些 API 可以跟数据库进行交互或者运维。我们提供了声明式 API,所以跟 Kubernetes 生态里面其他的一些工具或者系统可以很好地进行对接,比如说 kubectl、Argo CD、Terraform 等等。
KubeBlocks 解决了什么问题:单个 Redis 集群视角
对 KubeBlocks 有一个总体的了解之后,我们现在来看一下,站在单个 Redis 集群的视角, KubeBlocks 都解决了哪些问题。
如何处理数据复制(Replication)
我们都知道将数据库跑在 K8s 上面是非常有挑战的一件事情。这里面要解决的一个基础的问题就是所谓的数据复制。
比如这张图里面最左边的这张图所示,我们的系统当中使用了 Redis 数据库,如果 Redis 是一个单实例在运行,也就是说它跑在了一个 StatefulSet 里,它的 Replicas 是 1,那么这样的系统就会有非常多的问题。
第一个问题是这显然是一个单点,很容易发生单点故障。第二个问题是这样的一个单点它的吞吐量是有限的。此外,它的数据丢失风险非常高。
为了解决这些问题, 我们可以通过 StatefulSet 做水平扩容,扩展出更多的副本,所以我们可以将 Redis 从一个副本扩展到三个副本。那么这里就有问题了,在数据库当中,数据副本并不是独立的,它们之间是有数据的相互复制关系的。那么这会引入一些新的问题需要去考虑。
第一个问题是我们怎么样让 Service 能够找到主节点。我们都知道在 Redis 的主从架构当中只有主节点才具备写入的能力。第二个问题是我们在做扩容的时候,新增加的节点如何找到主节点,以便正确的搭建复制关系。第三个是在对 Redis 集群做小版本升级的时候,我们怎么样设计我们的升级策略,才能够使整个系统的不可用时长降到最低。除此之外,还有其他的一系列问题需要去考虑。
我们可以看到 K8s 原生的 StatefulSet 并不能很好地解决这些问题,所以在 KubeBlocks 里,我们新引入了一个专门为数据库设计的 AP,我们称之为 InstanceSet。
跟 StatefulSet 相同的地方在于,InstanceSet 为每一个 Pod 都分配了一个唯一的、固定的网络标识,不一样的地方在于,InstanceSet 里的每一个Pod 并不是独立的,它们是有角色的,这个角色是怎么来的呢?
InstanceSet 在创建每一个