到目前为止,几乎所有关于容器和微服务的讨论都集中在“无状态”应用上。这是完全可以理解的,因为无状态应用更简单。然而,容器和编排技术已经成熟到我们需要处理更有趣的工作负载:有状态应用。这就是为什么我在 SCALE 15x 的两次演讲都关于数据库、容器和 Kubernetes,Kubernetes 是一个开源系统,用于自动化容器化应用的部署、扩展和管理。
无状态服务是指像 Web 服务器、代理和应用程序代码这样的应用,它们可能处理数据,但不存储数据。在编排环境中,这些应用很容易理解,因为它们部署和扩展都很简单。如果流量增加,您只需添加更多实例并进行负载均衡。更重要的是,它们是“不可变的”;上游容器“镜像”和基础设施中运行的容器之间几乎没有区别。这意味着您可以随时替换它们,实例之间的“切换成本”很小。
有状态服务包括路由器、CDN(内容分发网络)、流媒体服务器和身份验证服务器等。从部署的那一刻起,这些容器就开始与它们的上游镜像有所不同,它们存在的时间越长,差异就越大。这种差异被称为“状态”。事实上,每个运行的应用程序都至少有一点状态,但对于“无状态”应用程序来说,这种状态很小且易于替换。对于有状态应用程序来说,情况则不然。虽然状态可以在有状态节点之间同步或复制,但这必须在编排系统本身之外通过某种特定于应用程序的方法来完成。
数据库和有状态应用
当然,考虑到我 18 年来在 PostgreSQL 方面的工作经验,我真正关心的有状态应用是事务性数据库。除了对大多数应用堆栈至关重要之外,数据库也是有状态支持的一个很好的测试用例,因为它们在所有可能的方面都是有状态的,包括
- 存储
- 身份
- 会话
- 集群角色
例如,PostgreSQL 需要将数据和事务存储在持久且每个 PostgreSQL 容器独有的文件中(存储)。每个容器都需要可识别为特定的数据库节点,并且我们需要能够通过名称或地址将流量路由到它(身份)。数据库客户端连接或会话也具有状态,并且中断它们是有成本的,因此我们不想随意移动数据库节点(会话)。最后,每个数据库节点在其数据库集群中都有一个角色,例如“主节点”、“副本”或“分片”(集群角色)。这些集群角色会一直存在,直到发生特定于数据库的事件才会更改它们。
直到最近,在流行的容器云堆栈上实现这些类型的状态一直具有挑战性。Docker 和编排框架将大多数类型的状态视为发生在容器堆栈之外的事情,迫使数据库架构师管理存储、身份、路由和所有其他事情。您没有一种将数据库迁移到容器的方法来帮助您。因此,虽然许多 Web 应用程序变得容器化,但很少有数据库或其他有状态应用程序这样做。对于“我们在哪里存储数据?”这个问题的答案通常是“使用 Amazon RDS(关系数据库服务)。”
使用 Kubernetes StatefulSet 的数据库
Kubernetes 项目在过去一年中一直在开发一个对象和一组功能,称为 StatefulSet,以处理数据库和其他有状态服务。开发人员最初以工作名称“PetSet”发布此功能,但在 1.5 版本中将其更改为更合适的“StatefulSet”。在这一点上,StatefulSet 实现了存储和身份有状态特性。另外两个可以使用最少的粘合代码,将 Kubernetes 用作资源来实现。换句话说,您不必继续等待部署编排的容器化数据库了。时机已到。
现在,您可以在 Kubernetes 下的容器中运行数据库,但是为什么要这样做呢?答案与容器无关,而与编排的好处有关。我们对现代数据库平台的期望之一是高可用性 (HA),但这并不是数据库软件本身可以提供的。启动集群、在发生故障的机器上替换数据库节点、将应用程序流量重新路由到迁移的节点以及其他 HA 考虑因素需要大量的代码和数据库内外的大量实用程序。
这是一段非常复杂的代码,因为它需要实现分布式系统。Kubernetes 像其他编排系统一样,为您处理了这个问题,使分布式系统变得容易获得。这意味着没有内置 HA 的数据库(如 PostgreSQL 和 MySQL)可以很容易地实现 HA,而已经具有 HA 的数据库(如 Cassandra 和 RethinkDB)可以实现完全自动化。根据经验,这比从头开始自己做要容易得多。
我创建了一些示例,向您展示如何在我的 atomicdb 演示仓库中使用 StatefulSet 部署 PostgreSQL。这些示例旨在说明如何使用这些功能,而不是完整的生产实现。Zalando 是 Patroni 集群管理项目的负责人,他们发布了一个 Helm Chart,用于他们基于 Kubernetes 的集群 PostgreSQL。当然,我将在 SCALE 15x 上谈论这个话题,而且不止一次,而是两次。
SCALE 15x 上的演讲
在 SCALE 15x 的星期五,在 PostgreSQL 会议中,我将讨论如何部署 Kubernetes 上的集群 PostgreSQL。这将包括使用 Patroni 的单主副本 PostgreSQL、使用 CitusDB 的分片数据库以及其他复制平台。我将展示不仅可以使用容器和 Kubernetes 部署这些,而且使用这些方法是最佳方法。
在星期日,我将更详细地解释不同类型的状态,以及我们如何通过 Kubernetes StatefulSet 或在其外部实现这些状态。当然,如果您不知道如何使用 Kubernetes,那么这一切都没有用,所以请参加我在星期四 Container Day 的 Kubernetes 101 演讲。
评论已关闭。