摘要:
此前云平台以上一任op组规划出的op服务, 作为代理k8s与上层业务交互的服务. 为加快业务迭代, 本文以operator为具体策略, 对此前的设计进行升级, 对一些不利于业务迭代的设计进行完善.
本文以redis数据库为具体例子, 提出以redis-operator来作为数据库实例与k8s交互间的作用层的设计. 目的有以下几个方面:
- 减少数据库开发中仅起到接口转发的中间层, 减少开发者的工作量
- 每个业务可以组成最小的迭代单元, 可快随迭代
- 可独立开发, 调试, 自测, 缩短整个迭代的周期
- 将分布式数据库的业务实例中, 由于网络偶发故障造成的业务影响的范围, 降低到最小, 避免由于实例间通过网络接口交互造成的业务破坏
- 便于后续的可维护性, 可扩展性
- 使数据库内核的开发者可以将精力全部集中于分布式数据库本身, 集中突破数据库内核的性能和高可用问题, 实现公司数据库产品的核心竞争力, 超越业界其他产品
- 便于上层业务快速迭代, 业务迭代与数据库核心设计分离, 使用户购买的实例可长期使用, 而非因为上层业务的调整造成必须升级用户的产品
需求分析:
一. 分布式数据库的面临的核心业务功能
operator在功能上, 是实例的一部分, 核心目的在于使数据库实例达到yaml描述的状态, 且长期保该状态. 从大的方面可以分为三个部分:
1. 1 分布式数据库集群的组建
1.2 分布式数据库的高可用, 也就是规格的保持, 核心组建是备库重建.
1.3 分布式数据库规格的调整, 扩容与缩容
二. 整体技术架构对开发流程及迭代速度的影响
产品迭代所面临的整个产品体系结构上的复杂性:
- 各个产品, 与唯一的op服务交互, op代理对k8s资源及其他资源的处理
- 例如: 在最初版本, op服务删除实例的接口没有回调通知, 不知道是否删除实例成功. 后续版本op加入删除通知回调, 但是各个产品必须响应接口. 因为涉及的产品过多, 造成无法推动.
- 各个产品无法根据自身特性利用云原生做适合自身的设计, 与op服务强绑定.
- op服务的接口限定了各个产品能达到的能力
- 产品不具备扩展性, 也不具备移植性, 无法在其他的云平台移植
op服务所面临的复杂性:
- 承载所有产品与底层交互的职责, 承载的功能已远超过op团队人力所能承担的工作
- 所有产品的基线解析及规格注册, 都位于op的一处代码库, 功能都在一个op服务实例,
- 单个产品出问题, 将造成整个op服务不可用
- 本来各个互相无关联的产品, 代码提交, 调试, 部署, 自测, 都成为串行化的了
- 由于公司硬件资源限制, 仅有少数几个集群环境, 只能串行进行部署和自测验证
三. 性能需求
本节主要记录引入operator设计后, 对于硬件资源的使用和限制
3.1 内存占用
3.2 cpu占用
概要设计:
一. operator与数据库内核交互节点图:
说明:
- operator作为数据库实例的一部分, 负责数据库实例集群的组建, 以及处理数据库实例集群的高可用
- 仅负责数据库组建,高可用及性能, 其他经常变化的业务应有中控负责
- 数据库实例一旦交付给客户, 后续如果升级实例, 将会影响客户的使用, 而且已部署的pod不便于直接修改
- 可以使公司的数据库开发者, 将精力保持在数据库内核的核心特性上, 以优化性能和高可用为目的, 超越其他厂商, 将精力用于缔造公司产品的核心竞争力
- operator直接与k8s-apis交互, 由operator负责k8s资源的创建
- operator直接与实例通过命令交互, 缩短调用链路, 代码量减少, bug减少, 开发迭代速度提升
二. operator组建redis-cluster集群及处理redis-cluster集群的高可用
说明:
- 选取cluster方案的原因, 在于与哨兵相比. 不需要额外部署哨兵集群, 可减少需要的硬件资源
- redis-cluster集群社区版最小需要三分片, 但是本人将redis-cluster的投票者替换为zk集群, 可使redis-cluster规格最小为1分片. zk集群可以直接复用ccos提供的zk服务.
- 旧master所在的node物理机器损坏, 导致其上承载的pod处于不可用状态, 且无法恢复
- 当前redis本地的存储使用了local pv, 绑定了物理机器node, 需要开发存储模块的同事, 提供将pod与所在node上的local pv解绑的接口, 使pod可以被重新调度
三. 以修改redis集群密码为例, 说明使用operator的方式编写数据库实例, 可以节省的工作量
当前修改redis集群密码所要开发的工作量:
说明:
- 黄色表明位于vpc网络
- 青色表明位于管理网
- agent需要跨越管理网
- 数据库进程服务需要跨越vpc网络
- 为了在一定程度上避免在处理请求的过程中网络访问失败, 需要预先对所有的pod进行一次网络探测, 查看是否可以访问
- 整个处理涉及过多的接口转发和访问, 难以快速编写单元测试, 也难以快速自测和在本地环境单独部署测试
将operator与数据库内核结合组成实例的方式, 来修改redis集群的密码:
说明:
- 实例的pod不再需要编写agent容器代理转发中控的请求, 节省了编写agent容器的开发量
- 不用再编写响应agent容器请求的unixsocket服务, 不要在vpc里创建unxisocket或者socat来转发请求
- operator直接通过k8s的api直接向pod中的数据库进程发送命令请求, 避免了pod之间的网络问题, 节省了各个请求接口编写的代码量, 以及为了预防网络问题而编写的防御性代码
- 可快速在本地进行部署测试, 每个服务和模块的接口精简而又明确, 有利于单元测试的编写, 可以做大对接口更多的测试用例的覆盖