K8S 之 Statefulset
摘要
-
本文介绍 K8S 的 Statefulset ,本文以 CentOS 8 为例。
Statefulset 介绍
-
Statefulset(缩写为 sts) 是 K8S 官方提供的一种控制器,用于管理有状态应用。例如,数据库应用,消息队列,等等。
-
Statefulset(有状态) 与 Deployment(无状态) 的区别是:
- Statefulset 创建的 Pod 会有相同的名称,并且会分配相同的持久卷。
- Statefulset 创建的 Pod 使用 Headless Service(无头服务,没有ClusterIP)进行通信。
Statefulset 管理
Statefulset 创建
-
Statefulset 只能 通过
yaml
创建,不支持create
创建 -
一个简单的
redis-statefulset.yaml
文件说明
1 | apiVersion: v1 # api版本 |
-
执行创建
1 | # 创建命名空间 |
查看 Statefulset
1 | $ k get all -n sts-ns |
访问pod中的redis服务
-
既然是Headless Service,就只能在集群内部访问
-
在相同的 namespace 中,可以通过
serviceName
直接访问,访问指定的 pod,可以通过<pod-name>.<service-name>
-
在不同的 namespace 中,可以通过
<serviceName>.<namespace>
或者<serviceName>.<namespace>.svc.cluster.local
访问,访问指定的 pod,可以通过<pod-name>.<service-name>.<namespace>.svc.cluster.local
访问,因为 pod-name 是固定且唯一的
1 | $ k exec -it pod/redis-sts-0 -n sts-ns -- getent hosts redis-svc |
-
在集群外部访问,需要创建一个新的 Service,类型为 NodePort 或者 LoadBalancer,将redis服务暴露出去
1 | apiVersion: v1 # api版本 |
-
执行
1 | # 创建 |
查看 Statefulset 详情
-
当 Statefulset 运行错误时,可以通过该命令查看 Statefulset 的详情,找到错误原因
1 | kubectl describe sts <sts-name> |
删除 Statefulset
1 | kubectl delete sts <sts-name> |
查看 Statefulset 日志
1 | kubectl logs sts/<sts-name> |
滚动升级与回滚 Statefulset
-
对
RollingUpdate
类型的Statefulset
的.spec.template
的任何更新都将触发滚动更新。 -
我们修改过
Statefulset
的.spec.template
,并保存后,重新运行kubectl apply -f <yaml-file>
即可触发滚动升级。 -
如果只是更新容器的镜像,也可以通过如下命令触发滚动升级
1 | $ k exec -it pod/redis-sts-0 -n sts-ns -- redis-server -v |
-
查看滚动升级状态
1 | # kubectl rollout status sts/<sts-name> |
-
查看历史版本
1 | # 前面的序号表示版本号 |
-
回滚
1 | # 回退到前一个版本 |
Deployment 和 StatefulSet 的对比总结
特性 | Deployment | StatefulSet |
---|---|---|
用途 | 无状态应用(如 Web 服务、API 服务) | 有状态应用(如数据库、缓存:Redis、MySQL、Kafka) |
Pod 名称 | Pod 名字随机生成,如 nginx-abc123 |
Pod 名字有序,格式为 name-0 、name-1 、name-2 |
稳定的标识 | 不提供,每次重建 Pod 名字可能不同 | 提供,每个 Pod 的名字、网络 ID、存储持久化不变 |
存储卷 | 通常配合 PVC,但 Pod 重建时挂载卷可能变化 | 配置 volumeClaimTemplates ,每个 Pod 独立持久卷 |
滚动更新策略 | 支持 maxSurge 、maxUnavailable ,可并行更新 Pod |
默认 逐个顺序更新 Pod(可用 partition 控制分批更新) |
可用性 | 通常设计为 无状态多副本高可用,不保证 Pod 启动顺序或固定 IP | 有状态且有序部署、删除、更新,通常单副本逐个维护可用性 |
服务访问 | 通过 ClusterIP、NodePort、LoadBalancer 访问 | 推荐用 Headless Service (clusterIP: None),Pod 有固定 DNS |
典型应用场景 | Web 应用、REST API、无状态微服务 | 数据库(MySQL、PostgreSQL)、缓存(Redis)、队列(Kafka、RabbitMQ) |
Pod 伸缩特性 | 灵活伸缩,增加/减少副本无特定顺序 | 有序伸缩,name-0 -> name-1 -> name-2 … |
重建策略 | Pod 崩溃后重建的是新 Pod,无持久存储数据可能丢失 | Pod 崩溃后重建的是相同 Pod 名字,挂载相同 PVC,不丢数据 |
后记
-
StatefulSet 类似于 Deployment,同样支持扩缩容(scale 或者 hpa),但因为其是有状态的,所以需谨慎
1 | # scale |
操作 | 可行性 | 推荐情况 |
---|---|---|
扩容(增加副本数) | ✅ 推荐 | 安全,新增 Pod 按序从 N-1 开始创建(sts-name-0 -> sts-name-1 -> sts-name-2 ) |
缩容(减少副本数) | ⚠️ 小心使用 | 可能导致 Pod 及其关联 PVC 被废弃,数据可能丢失 |