Tarantool Kubernetes运算符



Kubernetes已经成为运行无状态应用程序的实际标准,主要是因为它可以减少新功能的上市时间。 启动有状态应用程序(例如数据库或有状态微服务)仍然是一项复杂的任务,但是公司必须应对竞争并保持较高的交付率。 因此,他们对此类解决方案产生了需求。

我们想介绍我们的用于启动有状态Tarantool墨盒集群的解决方案: Tarantool Kubernetes Operator ,更多内容尚待完善

  1. 而不是千言万语
  2. 操作员实际做什么
  3. 一点细节
  4. 操作员如何工作
  5. 运营商创造的东西
  6. 总结

Tarantool是一个开放源代码的DBMS和一个应用程序服务器一体化。 作为数据库,它具有许多独特的特征:硬件利用率高,灵活的数据模式,对内存和磁盘存储的支持以及使用Lua语言进行扩展的可能性。 作为应用程序服务器,它允许您以最小的响应时间和最大的吞吐量将应用程序代码尽可能地靠近数据。 此外,Tarantool拥有广泛的生态系统,提供用于解决应用程序问题的即用型模块: 分片队列 ,易于开发的模块( 盒式磁带luatest ),操作解决方案( 指标ansible ),仅举几例。

尽管具有所有优点,但单个Tarantool实例的功能始终受到限制。 您将不得不创建数十个和数百个实例,以存储TB的数据并处理数百万个请求,这已经意味着具有所有典型问题的分布式系统。 为了解决这些问题,我们有Tarantool Cartridge ,这是一个旨在隐藏编写分布式应用程序时遇到的各种困难的框架。 它使开发人员可以专注于应用程序的业务价值。 卡式盒提供了一组强大的组件,用于自动集群流程,自动数据分发,用于操作的WebUI和开发人员工具。

Tarantool不仅涉及技术,还涉及致力于开发交钥匙企业系统,现成的解决方案以及对开源组件的支持的工程师团队。

在全球范围内,我们的所有任务可以分为两个领域:新系统的开发和现有解决方案的改进。 例如,有来自知名供应商的大量数据库。 为了扩展它以供读取,将基于Tarantool的最终一致缓存放置在其后。 反之亦然:为了扩展编写,将Tarantool安装在热/冷配置中:在数据“冷却”时,将其转储到冷存储中,同时将其转储到分析队列中。 或者编写现有系统的精简版(功能性备份)以通过使用来自主系统的数据复制来备份“热”数据。 从T + 2019会议报告中了解更多信息。

所有这些系统都有一个共同点:它们有些难以操作。 好吧,这里有很多令人兴奋的事情:快速创建一个由100多个实例组成的集群,并在3个数据中心中进行备份; 更新存储数据的应用程序,而无需停机或维护费用下降; 创建备份和还原,以准备可能发生的事故或人为错误; 确保隐藏的组件故障转移; 组织配置管理...

从字面上看, Tarantool Cartridge刚刚被开源了,极大地简化了分布式系统的开发:它支持组件集群,服务发现,配置管理,实例故障检测和自动故障转移,复制拓扑管理以及分片组件。
如果我们能尽快开发出所有这些,那就太好了。 Kubernetes使这成为可能,但是专业的操作员会让生活更加舒适。

今天,我们介绍Tarantool Kubernetes Operator的Alpha版本。

而不是千言万语


我们准备了一个基于Tarantool弹药筒的小例子,我们将使用它。 这是一个简单的应用程序,称为具有HTTP接口的分布式键值存储。 启动后,我们有以下内容:



哪里

  • 路由器是集群的一部分,负责接受和处理传入的HTTP请求。
  • 存储是集群的一部分,负责存储和处理数据。 开箱即用地安装了三个碎片,每个碎片都有一个母版和一个副本。

为了平衡路由器上的传入HTTP流量,使用了Kubernetes入口。 使用vshard组件 ,数据在Tarantool本身的级别上分布在存储中。

我们需要Kubernetes 1.14+,但是minikube可以。 拥有kubectl也很可爱。 要启动操作员,请创建ServiceAccount,Role和RoleBinding:

$ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/service_account.yaml $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/role.yaml $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/role_binding.yaml 

Tarantool Operator通过其资源定义扩展了Kubernetes API,因此让我们创建它们:

 $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/crds/tarantool_v1alpha1_cluster_crd.yaml $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/crds/tarantool_v1alpha1_role_crd.yaml $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/crds/tarantool_v1alpha1_replicasettemplate_crd.yaml 

一切都准备就绪,可以开始操作该操作员,所以它就开始了:

 $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/operator.yaml 

我们正在等待操作员启动,然后我们可以继续启动应用程序:

 $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/examples/kv/deployment.yaml 

带有示例的YAML文件在Web UI上声明了一个Ingress; 在cluster_ip/admin/cluster可用。 至少有一个Ingress Pod准备就绪并运行后,您可以去那里观察如何将新实例添加到群集以及它的拓扑如何变化。
我们正在等待集群的使用:

 $ kubectl describe clusters.tarantool.io examples-kv-cluster 

我们正在等待以下群集状态:

 … Status: State: Ready … 

仅此而已,该应用程序随时可以使用!

您是否需要更多存储空间? 然后,让我们添加一些碎片:

 $ kubectl scale roles.tarantool.io storage --replicas=3 

如果分片无法处理负载,那么让我们通过编辑副本集模板来增加分片中的实例数:

 $ kubectl edit replicasettemplates.tarantool.io storage-template 

让我们将.spec.replicas值设置为2,以便将每个副本中的实例数量增加为2。

如果不再需要集群,只需将其连同所有资源一起删除:

 $ kubectl delete clusters.tarantool.io examples-kv-cluster 

出问题了吗? 创建票证 ,我们将快速进行处理。

操作员实际做什么


Tarantool Cartridge集群的启动和操作是一个在特定时间以特定顺序执行特定操作的故事。

群集本身主要通过admin API:基于HTTP的GraphQL进行管理。 毫无疑问,您可以降低级别并直接通过控制台发出命令,但这很少发生。
例如,这是集群启动的方式:

  1. 例如,使用systemd部署所需数量的Tarantool实例。
  2. 然后,我们将实例连接到成员身份:

     mutation { probe_instance: probe_server(uri: "storage:3301") } 
  3. 然后,我们将角色分配给实例,并指定实例和副本集标识符。 GraphQL API用于此目的:

     mutation { join_server( uri:"storage:3301", instance_uuid: "cccccccc-cccc-4000-b000-000000000001", replicaset_uuid: "cccccccc-0000-4000-b000-000000000000", roles: ["storage"], timeout: 5 ) } 
  4. 最终,我们使用API​​引导负责分片的组件:

     mutation { bootstrap_vshard cluster { failover(enabled:true) } } 

容易吧?

当涉及到集群扩展时,一切都会变得更加有趣。 该示例中的Routers角色可以轻松扩展:创建更多实例,将它们加入到现有集群中,您就完成了! 存储角色有点棘手。 存储是分片的,因此在添加/删除实例时,有必要通过分别将数据移到新实例/已删除实例中/从新实例/删除实例中重新平衡数据。 否则,将导致实例负载不足或数据丢失。 如果不仅有一个集群,而且有许多具有不同拓扑的集群怎么办?

通常,这就是Tarantool Operator处理的所有事情。 用户描述了Tarantool Cartridge集群的必要状态,并且操作员将其转换为应用于K8s资源的一组操作,并转换为在特定时间以特定顺序对Tarantool集群管理员API的某些调用。 它还尝试向用户隐藏所有详细信息。

一点细节


在使用Tarantool Cartridge集群管理员API时,调用顺序及其目的地都是必不可少的。 怎么会这样

Tarantool弹药筒包含其拓扑存储,服务发现组件和配置组件。 群集的每个实例在YAML文件中存储拓扑和配置的副本。

 servers: d8a9ce19-a880-5757-9ae0-6a0959525842: uri: storage-2-0.examples-kv-cluster:3301 replicaset_uuid: 8cf044f2-cae0-519b-8d08-00a2f1173fcb 497762e2-02a1-583e-8f51-5610375ebae9: uri: storage-0-0.examples-kv-cluster:3301 replicaset_uuid: 05e42b64-fa81-59e6-beb2-95d84c22a435 … vshard: bucket_count: 30000 ... 

使用两阶段提交机制一致地应用更新。 成功的更新需要100%的仲裁:每个实例都必须响应。 否则,它将回滚。 就操作而言,这意味着什么? 在可靠性方面,所有修改群集状态的对管理员API的请求都应发送到单个实例或领导者,因为否则我们将冒着在不同实例上获得不同配置的风险。 Tarantool弹药筒不知道如何进行领导者选举(不仅如此),但是Tarantool操作员可以而且对您来说,这只是一个有趣的事实,因为操作员可以做所有事情。

每个实例还应具有一个固定的标识,即一组instance_uuidreplicaset_uuid以及advertise_uri 。 如果存储突然重新启动,并且其中一个参数发生更改,则可能会导致仲裁中断,操作员对此负责。

操作员如何工作


操作员的目的是使系统进入用户定义的状态,并将系统保持在此状态,直到给出新的指示为止。 为了使操作员能够工作,需要:

  1. 系统状态的描述。
  2. 使系统进入此状态的代码。
  3. 一种将此代码集成到k8中的机制(例如,接收状态更改通知)。

使用自定义资源定义(CRD)按照k8来描述Tarantool Cartridge集群。 操作员需要在tarantool.io/v1alpha组下合并的三个自定义资源:

  • 群集是与单个Tarantool墨盒群集相对应的顶级资源。
  • 就Tarantool弹药筒而言,角色是用户角色
  • 复制副本模板是用于创建StatefulSet的模板(我稍后会告诉您为什么它们是有状态的;不要与K8s ReplicaSet混淆)。

所有这些资源都直接反映了Tarantool Cartridge集群描述模型。 拥有通用词典可以更轻松地与开发人员进行交流,并了解他们希望在生产中看到的内容。

使系统进入给定状态的代码是控制器(按K8)。 对于Tarantool Operator,有多个控制器:

  • 群集控制器负责与Tarantool墨盒群集进行交互; 它将实例连接到群集,并断开实例与群集的连接。
  • 角色控制器是用户角色控制器,负责从模板创建StatefulSet并维护其中的预定义数量。

控制器是什么样的? 这是一组代码,可以使周围的世界逐渐井然有序。 群集控制器的示意图如下:



入口点是一项测试,以查看事件是否存在相应的群集资源。 是否存在? “否”表示戒烟。 “是”表示转到下一个块并取得用户角色的所有权。 获得角色所有权后,它退出并第二次出现。 一直持续到获得所有角色的所有权为止。 取得所有权后,就该移至下一个操作块了。 然后该过程一直进行到最后一个块。 之后,我们可以假定受控系统处于定义状态。

总的来说,一切都很简单。 但是,确定通过每个阶段的成功标准很重要。 例如,当集群连接操作返回假设的成功= true时,则不认为是成功的,但是当它返回诸如“已连接”的错误时,则不被视为成功。

该机制的最后一部分是控制器与K8的集成。 从鸟瞰的角度来看,整个K8都由一组产生事件并对其进行响应的控制器组成。 这些事件被组织成可以订阅的队列。 它的示意图如下:



用户调用kubectl create -f tarantool_cluster.yaml ,并kubectl create -f tarantool_cluster.yaml了相应的群集资源。 通知群集控制器群集资源的创建。 它要做的第一件事是找到应该属于此群集的所有角色资源。 如果是这样,则它将群集分配为角色的所有者并更新角色资源。 角色控制器收到角色更新通知,了解该资源具有其所有者,然后开始创建StatefulSet。 它是这样工作的:第一个事件触发第二个事件,第二个事件触发第三个事件,依此类推,直到其中一个事件停止。 您还可以设置一个时间触发器,例如,每5秒钟一次。

这是操作员的组织方式:我们创建一个自定义资源,并编写代码以响应与资源有关的事件。

运营商创造的东西


操作员的行动最终导致创建K8s Pod和容器。 在K8上部署的Tarantool Cartridge集群中,所有Pod都连接到StatefulSet。

为什么选择StatefulSet? 如前所述,每个Tarantool集群实例均保留集群拓扑和配置的副本。 而且应用服务器有时每隔一段时间就有一些专用的空间,例如用于队列或参考数据,而这已经是满状态。 StatefulSet还保证保留Pod身份,这在群集实例时很重要:实例应具有固定的身份,否则我们有重新启动时失去仲裁的风险。

当所有群集资源准备就绪并处于所需状态时,它们反映以下层次结构:



箭头指示资源之间的所有者依赖关系。 例如,在删除集群后,有必要清理垃圾收集器

除了StatefulSets,Tarantool Operator为领导者选举创建Headless服务,并且实例通过该服务彼此通信。

Tarantool Operator基于Operator Framework ,并且操作员代码是用Golang编写的,因此这里没有什么特别的。

总结


这几乎就是它的全部。 我们正在等待您的反馈和门票。 我们离不开它们-毕竟是alpha版本。 接下来是什么? 下一步是很多抛光:

  • 单元,端到端测试;
  • 混沌猴子测试;
  • 压力测试;
  • 备份/还原;
  • 外部拓扑提供程序。

这些主题中的每个主题都有自己的广泛主题,值得单独撰写,因此请等待更新!

Source: https://habr.com/ru/post/zh-CN472428/


All Articles