我正在尝试了解Stateful Sets。它们的使用与使用带有持久卷的“无状态”Pod 有何不同?也就是说,假设一个“正常”的 Pod 可能声称拥有持久存储,那么我缺少什么明显的东西需要这个新的构造(具有有序的启动/停止等)?
2 回答
是的,普通 pod 可以使用持久卷。但是,有时您有多个 pod 在逻辑上形成一个“组”。例如数据库副本、ZooKeeper 主机、Kafka 节点等。在所有这些情况下,都有一堆服务器,它们一起工作并相互通信。他们的特别之处在于群体中的每个人都有自己的身份。例如,对于一个数据库集群,一个是主服务器,两个是追随者,每个追随者都与主服务器通信,让它知道它有什么同步和没有同步。所以追随者知道“db-x-0”是主人,主人知道“db-x-2”是追随者,并且拥有所有数据到某个点,但仍然需要超出该点的数据。
在这种情况下,您需要一些无法从常规 pod 轻松获得的东西:
- 一个可预测的名称:您希望启动您的 pod,告诉它们在哪里可以找到彼此,以便它们可以形成集群、选举领导者等,但您需要提前知道它们的名称才能做到这一点。普通的 pod 名称是随机的,因此您无法提前知道它们。
- 稳定的地址/DNS 名称:您希望步骤 (1) 中可用的任何名称保持不变。如果一个普通的 pod 在另一台主机上重新启动(你重新部署,运行它的主机死机等),它将获得一个新名称和一个新 IP 地址。
- 组中的个人与其持久卷之间的持久链接:如果您的数据库主服务器之一运行的主机死亡,它将被移动到新主机,但应该连接到相同的持久卷,因为只有一个卷包含该“个人”的正确数据。因此,例如,如果您重新部署由 3 个数据库主机组成的组,您希望同一个人(通过 DNS 名称和 IP 地址)获得相同的持久卷,因此 master 仍然是 master 并且仍然具有相同的数据,replica1 得到它数据等
StatefulSets 解决了这些问题,因为它们提供(引用自https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/):
- 稳定、唯一的网络标识符。
- 稳定、持久的存储。
- 有序、优雅的部署和扩展。
- 有序、优雅的删除和终止。
我并没有真正谈论(3)和(4),但这也可以帮助集群,因为您可以告诉第一个部署成为主服务器,而下一个找到第一个并将其视为主服务器,等等。
正如一些人所指出的,您确实可以通过使用常规 pod 和服务来获得一些相同的好处,但它的工作量要大得多。例如,如果您想要 3 个数据库实例,您可以手动创建 3 个部署和 3 个服务。请注意,您必须手动创建3 个部署,因为您不能将服务点指向部署中的单个 pod。然后,要扩大规模,您将手动创建另一个部署和另一个服务。这确实有效,并且在 PetSet/PersistentSet 出现之前是一种常见的做法。请注意,它缺少上面列出的一些好处(例如持久卷映射和固定启动顺序)。
1:为什么是有状态集?
无状态应用程序:通常,前端组件的扩展需求与后端完全不同,因此我们倾向于单独扩展它们。更不用说与(无状态)前端 Web 服务器相比,数据库等后端通常更难扩展。是的,术语“无状态”意味着在创建新容器时不存储过去的数据或状态,也不需要持久化
有状态应用程序:有状态应用程序通常涉及一些数据库,例如 Cassandra、MongoDB 或 MySQL,并处理对其的读取和/或写入。
2:无状态Pod不能使用持久卷吗?
基本上,有几种方法可以做到这一点。但是,它也有其自身的缺点。
1:每个 Pod 实例使用一个副本集
- 您可以创建多个 ReplicaSet——为每个 pod 创建一个,每个 ReplicaSet 的所需副本计数设置为一个,并且每个 ReplicaSet 的 pod 模板引用一个专用的 PersistentVolumeClaim。
虽然这会在节点故障或意外 pod 删除的情况下自动重新调度,但与拥有单个 ReplicaSet 相比,它要麻烦得多。
例如,考虑在这种情况下如何扩展 pod。您无法更改所需的副本数,而必须创建额外的 ReplicaSet。因此,使用多个 ReplicaSet 并不是最好的解决方案。
2:在同一卷中使用多个目录
- 您可以使用的一个技巧是让所有 pod 使用相同的 PersistentVolume,然后在该卷中为每个 pod 有一个单独的文件目录因为您无法以不同于单个 pod 模板的方式配置 pod 副本,所以您无法告诉每个实例它应该使用哪个目录,但您可以让每个实例自动选择(并且可能还创建)一个当时没有被任何其他实例使用的数据目录。
- 此解决方案确实需要实例之间的协调,并且不容易正确执行。这也使得共享存储卷成为瓶颈。