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