Kubernetes 核心概念之2.2 Statefulset 有状态应用
官方文档:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/
Statefulset
Statefulset 主要是用来部署有状态应用。StatefulSet 是一个有序的、可标识的 Pod 组,并且每个 Pod 都有一个独特的标识符。
这使得 StatefulSet 能够管理有状态应用程序,例如数据库或队列服务,这些应用程序需要稳定的网络标识符或持久性存储,并且需要有序的、逐个更新的部署方式。
- 稳定的网络标识符:在 StatefulSet 中,每个 Pod 都有一个稳定的网络标识符,可以通过 DNS 或其他服务发现机制进行访问。这个标识符由 StatefulSet 控制器在 Pod 创建时自动分配,并且在 Pod 重新启动时保持不变。这使得有状态应用程序能够在网络上稳定地被访问。
- 有序的、逐个更新的部署方式:StatefulSet 能够按照一定的顺序逐个更新 Pod。这意味着当需要更新有状态应用程序时,可以确保新的 Pod 在旧的 Pod 停止之前启动,并且在新的 Pod 启动之前,旧的 Pod 仍然可以提供服务。这种有序的、逐个更新的部署方式使得有状态应用程序在更新时更加稳定。
- 持久性存储:StatefulSet 能够管理有状态应用程序的持久性存储。每个 Pod 都可以有自己的持久性存储卷,并且这些存储卷可以在 Pod 重新启动时保持不变。这使得有状态应用程序能够在重新启动时保留其状态和数据。
- 适合于有状态应用程序:StatefulSet 适用于运行有状态应用程序,例如数据库或队列服务,这些应用程序需要稳定的网络标识符或持久性存储,并且需要有序的、逐个更新的部署方式。与 Deployment 不同,StatefulSet 不适用于运行无状态应用程序。
对于 StatefulSet 中的 Pod,每个 Pod 挂载自己独立的存储,如果一个 Pod 出现故障,从其他节点启动一个同样名字的 Pod,要挂载上原来 Pod 的存储继续以它的状态提供服务。
适合 StatefulSet 的业务包括数据库服务 MySQL 和 PostgreSQL,集群化管理服务 Zookeeper、etcd 等有状态服务。
StatefulSet 的另一种典型应用场景是作为一种比普通容器更稳定可靠的模拟虚拟机的机制。传统的虚拟机正是一种有状态的宠物,运维人员需要不断地维护它,容器刚开始流行时,我们用容器来模拟虚拟机使用,所有状态都保存在容器里,而这已被证明是非常不安全、不可靠的。
使用 StatefulSet,Pod 仍然可以通过漂移到不同节点提供高可用,而存储也可以通过外挂的存储来提供高可靠性,StatefulSet 做的只是将确定的 Pod 与确定的存储关联起来保证状态的连续性。
StatefulSet 资源的状态主要包括以下几个方面:
Replicas
: 指定的副本数,即.spec.replicas
字段的值。表示 StatefulSet 管理的副本数量。ReadyReplicas
: 表示已经就绪的副本数量,即当前运行且已经 READY 的 Pod 数。CurrentReplicas
: 表示当前正在运行的副本数量,即运行中的 Pod 总数。UpdatedReplicas
: 表示已经更新的副本数量,即最近一次更新中,更新成功的 Pod 数。CurrentRevision
: 当前正在执行的修订版本号。UpdateRevision
: StatefulSet 的当前修订版本号。StatefulSet 的模板(.spec.template
)每次更新时,这个值就会增加 1collisionCount
:表示在创建 Pod 时发生的命名冲突的次数。UpdateStatus
: 最近一次更新的状态,可以是”Running”或者”Failed”。ObservedGeneration
: 最近一次对 StatefulSet 资源的更改,已经被看到的 Generation 数。也就是说如果 StatefulSet 的 .spec 字段被修改,该值会更新。
StatefulSet 两种状态
StatefulSet 的设计,它把真实世界里的应用状态,抽象为了两种:
拓扑状态。应用的多个实例之间不是完全对等的关系。这些应用实例,必须按照某些顺序启动,比如应用的主节点 A 要先于从节点 B 启动。而如果把 A 和 B 两个 Pod 删除掉,它们再次被创建出来时也必须严格按照这个顺序才行。并且,新创建出来的 Pod,必须和原来 Pod 的网络标识一样,这样原先的访问者才能使用同样的方法,访问到这个新 Pod。
存储状态。存储状态。应用的多个实例分别绑定了不同的存储数据。对于这些应用实例来说,Pod A 第一次读取到的数据,和隔了十分钟之后再次读取到的数据,应该是同一份,哪怕在此期间 Pod A 被重新创建过。这种情况最典型的例子,就是一个数据库应用的多个存储实例。
也可以说:StatefulSet 的核心功能,是通过某种方式记录这些状态,然后在 Pod 被重新创建时,能够为新 Pod 恢复这些状态
说明
常规的 service
service:一组 pod 访问策略,提供负载均衡和服务发现。
其他:service 会分配一个 CLUSTER-IP 虚拟IP 使整个容器进行通信。headless service:无头服务
headless service:与 service 类似,不同点在于 clusterIP 为 None
示例
1、创建有状态应用
1 |
|
2、创建容器
1 |
|
3、查看
查看创建容器以及 service、通过 dns 名称,保证每个固定的身份(pod/nginx-statefulset-x)标识。
1 |
|
4、测试
临时启动程序测试解析,通过 dns 解析唯一标识的容器
1 |
|
5、删除
1 |
|
如此可以比对出效果
StatefulSet 与 Deployment 区别:
- Deployment:是有身份的,有唯一标识
- StatefulSet:根据主机名 + 按照一定规则生成域名
身份三要素:域名、主机名、存储(PVC)
每个 pod 有唯一的主机名,并且有唯一的域名
- 格式:
主机名称.service名称.名称空间.svc.cluster.local
- 举例:
nginx-statefulset-0.default.svc.cluster.local