Kubernetes无处不在。事务应用程序、视频流服务和机器学习工作负载正在这个不断增长的平台上找到归宿。但是数据库呢?如果你五年前问我这个问题,基于我在开发和运营方面的经验,我的答案会是一个响亮的“不”。在接下来的几年里,随着有状态应用程序出现了更多的资源,我的答案会变为“可能”,但总是带有一个限定词:“它适合开发或测试环境……”或“如果您的其他工具是基于Kubernetes的,并且您有丰富的经验……”
但是今天呢?你应该在Kubernetes上运行一个数据库吗?在有了复杂的操作和持久、一致数据的需求后,让我们回溯一下我目前的答案:“在云原生环境中?是的!”
阶段1:在Kubernetes上运行无状态工作负载,但不要在数据库上运行!
当Kubernetes 登陆 DevOps 场景时,我渴望探索这个新平台。我的自动化已经通过
Puppet配置主机和 Capistrano 将我的应用程序位转移到虚拟服务器来实现。我开始探索Docker容器,并喜欢上我不再需要在开发人员工作站上安装和管理服务的方式。我可以只启动几个容器,继续用我的代码改变世界。
Kubernetes 让这些容器被部署到服务器组变得非常简单。它还处理了在实例发生故障时更换实例的问题,并使许多副本保持在线。再也不需要随时获取页面了!这对于无状态服务来说很好,但是对于数据库呢?Kubernetes承诺了敏捷性,但我的数据库被绑定到一个巨大的数据船锚上,如果我在容器中运行数据库,当容器返回时,我的数据会在那里吗?我没有时间解决这个问题,所以我启动了一个受管理的RDBMS并继续下一个功能。工作完成。
阶段2:在Kubernetes上运行临时数据库进行测试
当我需要根据GitHub pull请求(PR)运行单独的应用程序实例进行QA测试时,这个问题再次出现。每个PR都需要一个正在运行的应用程序实例和一个数据库。我们不能只针对共享数据库运行,因为一些 PRs 包含模式更改。我不需要一个漂亮的解决方案,所以我们在应用程序的同一个 POD 中运行了一个 RDBMS 实例,并预加载了模式和一些数据。我们在它前面抛出了一个反向代理,并根据需要旋转实例。QA很高兴,因为在测试环境中没有更多的 PRs 调度,产品团队享受特性环境来测试驱动新功能,并且 ops 不必编写大量自动化程序。这对我来说是一个完全不同的情况,因为我从来没有想过这些环境是短暂的。它当然不是云原生的,所以我还没有准备好用 Kubernetes部署的生产数据库替换我的托管数据库。
第3阶段:在Kubernetes Statefulset上运行Cassandra
大约在这个时候,我被介绍给Apache Cassandra®。我对这个高性能数据库和一个惊人的操作故事感到惊讶。可以支持丢失实例的数据库?给我报名!我希望在库伯内特斯上运行一个数据库的愿望又回来了。卡桑德拉能处理容器的短暂性吗?当时,这感觉像是一种嫉妒“我想是吧?“。这似乎是可能的,但在工具方面有很大的差距。要将其投入生产,我需要一个有着丰富经验的 Kubernetes和 Cassandra组成的团队,再加上一套工具和运行手册来填补操作上的差距。看起来确实有很多团队成功地在容器中运行Cassandra。我很怀念Instaclustr的一个网络研讨会,其中谈到在 CoreOS上运行 Cassandra。
与此同时,Kubernetes生态系统的一些变化开始巩固。状态集根据可预测的命名方案处理具有持久存储的pod的创建。持久卷API和容器存储接口(CSI)允许计算和存储之间的松散耦合。在某些情况下,甚至可以定义在应用程序围绕集群重新调度时跟随应用程序的存储。
存储是每个数据库的核心。在容器化数据库中,数据可以存储在容器内,也可以安装在外部。使用外部存储可以切换容器以更改配置或升级软件,同时保持数据完整。Cassandra已经能够利用高性能本地存储,但现代 CSI 实施的灵活性意味着,随着 POD 的重新调度,数据量将转移到新的工作者手中。这减少了恢复时间,因为在工作线程故障的情况下,不再需要在主机之间同步数据。
阶段4:Cassandra的Kubernetes算子
通过将 Cassandra节点直接部署到 POD,弹性地处理数据量,以及一个Kubernetes控制平面来保持一切运行,我们还能要求什么?在这一点上,我遇到了两个独立开发的分布式系统的冲突。Kubernetes提供POD和启动服务的方式与 care 和 feed for a Cassandra集群所需的操作步骤不一致——Kubernetes工作流和Cassandra Runbook之间必须弥合差距。
Kubernetes 提供了许多内置资源——从一个简单的构建块(如Pod)到更高级别的抽象(如部署)。这些资源允许用户定义他们的需求,Kubernetes提供控制循环以确保运行状态与目标状态匹配。控制循环采取短期增量操作,将编排的组件推向所需的最终状态,例如重新启动pod或创建DNS条目。然而,像分布式数据库这样的领域需要更复杂的动作序列,这些动作序列不适合预定义的资源。这很好,但并不是所有内容都适合预定义的资源。
创建了 Kubernetes自定义资源,通过定义新的资源类型和控制器,允许扩展Kubernetes API 以用于特定于域的逻辑。operator SDK、kubebuilder 和 juju 等OSS框架的创建是为了简化自定义资源及其控制器的创建。用这些框架构建的工具被称为操作符。
随着这些强大的新工具变得可用,我参与了在 cass operator 项目中编写 Cassandra逻辑域和操作 Runbook 的工作。Cass操作员定义 CassandraDatacenter 自定义资源,并提供项目之间的粘合,包括管理API、Cass配置生成器和其他,以在 Kubernetes上提供内聚的 Cassandra 体验。
使用 cass 操作符,我们花更少的时间思考POD、状态集、持久卷,甚至是引导和扩展集群的繁琐任务,花更多的时间思考我们的应用程序。
现阶段:使用K8ssandra运行完整的数据平台
这个循环中的下一个迭代,K8ssandra,将我们从单个组件中进一步提升。我们可以从整体上考虑我们的数据平台,而不是卡桑德拉数据中心:不仅是数据库,还支持包括监控、备份和API在内的服务。我们可以通过执行一个简单的Helm-install命令向Kubernetes请求一个数据平台,然后一组操作员开始提供并管理所有部分。
回顾几年前我在Kubernetes上运行数据库时遇到的陷阱,其中大多数已经解决。从卡桑德拉(Cassandra)这样的基础技术开始,我们就可以解决可用性问题:数据是复制的,它足够智能,可以在同行来去时处理混乱的数据。Kubernetes API已经成熟,可以包括自定义资源和高级有状态组件(如持久卷和有状态集)。Cass运算符充当Rosetta Stone,提供将 Cassandra 和 Kubernetes 的术语缝合在一起所需的丰富知识。最后,K8ssandra以一种完全内聚的体验将我们带到了下一个层次。
回顾几年前我在 Kubernetes 上运行数据库时遇到的陷阱,其中大多数已经解决。从卡桑德拉(Cassandra)这样的基础技术开始,我们就可以解决可用性问题:数据是复制的,它足够智能,可以在同行来去时处理混乱的数据。Kubernetes API已经成熟,可以包括自定义资源和高级有状态组件(如持久卷和有状态集)。Cass运算符充当 Rosetta Stone,提供将 Cassandra 和 Kubernetes 的术语缝合在一起所需的丰富知识。最后,K8ssandra 以一种完全内聚的体验将我们带到了下一个层次。
所有这些问题都很难解决,需要技术技巧和仔细思考。如果没有选择正确的部分,我们最终将放弃数据库和 Kubernetes,转而在我们的基础设施中扮演利基角色,以及在构建所有这些部分和 Runbook 方面投入了大量精力的创新工程师。幸运的是,每一个问题都得到了解决和克服。您是否应该在 Kubernetes 中运行数据库?当然!
原文标题:A Case for Databases on Kubernetes from a Former Skeptic
原文地址:https://dzone.com/articles/a-case-for-databases-on-kubernetes-from-a-former-s




