下面我们对其中一些关键的技术实现做出解读:
一、k8s中的statefulset调度方式
我们通常以服务运行时是否需要进行数据的持久化将k8s中运行的容器服务分为有状态服务和无状态服务。在AnyShare Family 7的k8s部署架构中,模块化服务等“无状态”服务通常以Deployment副本控制器的形式调度,资源层服务mariadb、mongodb、opensearch等“有状态”服务以Statefuleset副本控制器的形式调度。它相比Deployment有以下特点:- Pod一致性:包含次序(启动、停止次序)、网络一致性。此一致性与Pod相关,与被调度到哪个node节点无关;
- 稳定的次序(启动或关闭时保证有序):对于N个副本的StatefulSet,每个Pod都在[0,N)的范围内分配一个数字序号,且是唯一的;
- 优雅的部署和伸缩性: 操作第n个pod时,前n-1个pod已经是运行且准备好的状态。 有序的,优雅的删除和终止操作:从 n, n-1, ... 1, 0 这样的顺序删除。
- 稳定的、唯一网络标识:Pod的hostname模式为( statefulSet名 称 ) − (statefulset名称)-(statefulset名称)−(序号);
- 稳定的持久化存储:通过Kubernetes的PV/PVC或者外部存储(预先提供的)来实现,即通过VolumeClaimTemplate为每个Pod创建一个PV/PVC。删除、减少副本,不会删除相关的卷。

二、MariaDB Galera Cluster技术
AnyShare Family 7中所有有状态mariadb副本间通过Galera协议同步数据,这用到了MariadbDB Galera Cluster工具。MariaDB Galera Cluster 是一个用于同步MariaDB数据库的多master集群的工具。在数据方面完全兼容 MariaDB 和 MySQL。
它有以下主要特性:
- 同步复制 Synchronous replication
- Active-active multi-master 拓扑逻辑
- 可对集群中任一节点进行数据读写
- 自动成员控制,故障节点自动从集群中移除
- 自动节点加入
- 真正并行的复制,基于行级
- 直接客户端连接,原生的 MySQL 接口

其中涉及到的容器角色功能如下:
- etcd容器:存储数据库seqno信息。数据库启动时需要决定引导节点,通过向etcd注册seqno值,选取最大的节点作为引导节点启动
- DB容器:数据库容器。数据库与数据库之间组成Galera集群实现数据同步
- MGMT容器:API容器,对外提供数据库/数据库账户管理功能
- exporter容器:数据库监控数据获取http服务,供Proton Watch组件采集metrics数据
三、Proton RDS Mariadb Operator技术
Proton RDS MariaDB Operator则在AnyShare Family 7中用于MariaDB Galera Cluster 的部署管理。其中涉及到的概念如下:- CRD:CRD 即Custom Resource Definition,是 Kubernetes 提供给开发者自定义类型资源的功能,开发者自定义 CRD 然后实现该 CRD 对应的 Operator 来完成对应的控制逻辑,CRD 是通知 Kubernetes 平台存在一种新的资源。k8s自带了多个CRD例如Deployment、Statefulset....
- CR:CR是CRD定义的具体的实例对象。
- Operator:Operator 概念是由 CoreOS 的工程师于2016年提出的,它让工程师可以根据应用独有的领域逻辑为应用编写自定义的控制器。用户注册自己自定义的Custom Resource Definition,然后创建对应的资源实例(称为Custom Resource,简称CR),而后通过自己编写Controller来不断地检测当前k8s中所定义的CR的状态.如果状态和预期不一致,则调整。Controller具体做的事就是通过调用k8s api server的客户端,根据比较预期的状态和实际的状态,来对相应的资源进行增,删,改。
AnyShare Family 7在7.0.4.3之后的版本利用mariadb operator管理MariaDB Galera Cluster容器集群从数据库资源层实现了读写分离。其实现原理如下:
controller创建数据库集群时创建两个service,一个用于读,一个用于写。读service的endpoints列表由ready的数据库pod组成,写service的endpoints列表由ready且含有标签role=master的数据库pod组成。controller定期轮询写service,当写service的endpoints列表为空的话就重置所有数据库pod的标签,并随机选取一个ready的数据库pod,打上role=master的标签。内部逻辑如下:

应用程序通过修改配置逻辑,连接RDS集群中不同副本的endpoints地址,实现了业务层的读写分离。
基于以上技术在k8s集群中最终创建了以下的Pod资源,它们各司其职,保障了AnyShare Family 7系统核心的关系型数据库以高可用的方式运行。
