- 一、核心特性
- 二、架构与组件
- 三、生命周期管理
- 四、典型应用场景**
- 五、注意事项与最佳实践
- 六、对比Deployment
- 一、应用场景
- 二、Pod管理
- 三、部署与更新策略
- 四、其他特性
- 七、常见问题
- 八、拓展
前文中我们介绍了k8s中常用的一种控制器 Deployment,与之向对应的,还有另外一种我们不太常用的控制器也是k8s的重要组成部分:StatefulSet,StatefulSet(有状态集,缩写为sts)是Kubernetes中用于部署和管理有状态应用程序的一种工作负载API对象。
一、核心特性
- 唯一标识与稳定性
• 每个Pod分配唯一索引标识(如pod-0
,pod-1
),即使重启或迁移,标识不变。
• 依赖Headless Service提供稳定DNS记录(如pod-0.example.com
),确保客户端始终连接到同一实例。
StatefulSet是用来管理有状态应用的服务。和无状态的Deployment不同,StatefulSet需要保持每个Pod的唯一性和持久性。比如数据库、消息队列这样的应用,每个实例的数据都是独立的,不能随意替换或删除,这时候就需要StatefulSet来管理。
- 持久化存储
• 通过volumeClaimTemplates
自动生成独立的PersistentVolumeClaim
(PVC),每个Pod拥有专属存储卷,数据持久化。
关于存储,每个Pod的volumeClaimTemplate会创建一个独立的PersistentVolumeClaim,确保数据隔离。如果使用本地存储的话,可能需要特别注意节点的可用性,否则数据可能会丢失。所以通常推荐使用云提供商的持久磁盘或者其他可靠的存储方案。
-
有序扩缩容
• 扩容时按索引顺序创建新Pod(如从pod-2
到pod-N
),缩容时逆序删除旧Pod(如先删pod-0
),保障服务连续性。 -
滚动更新策略
• 支持配置maxSurge
(最大并发更新数)和maxUnavailable
(最大不可用数),默认策略为逐个更新,减少对集群的影响。
二、架构与组件
• StatefulSet Spec
定义Pod模板、副本数、服务名、标签选择器等关键参数:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-database
spec:
serviceName: "mysql-cluster" # 对应的Headless Service名称
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
volumeMounts:
- name: db-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: db-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
• Headless Service
自动创建无集群IP的Service,暴露所有Pod的DNS记录:
apiVersion: v1
kind: Service
metadata:
name: mysql-cluster
spec:
clusterIP: None
selector:
app: mysql
- PersistentVolume Provisioner
Pod所用的存储必须由PersistentVolume Provisioner(持久化卷配置器)根据请求配置StorageClass,或者由管理员预先配置。这是为了确保Pod在重新调度时能够访问到相同的持久化数据。
PersistentVolume Provisioner的配置通常涉及创建StorageClass对象,该对象定义了动态卷供应的参数和配置。以下是一个基于YAML的配置示例,展示了如何配置一个使用AWS EBS作为后端存储的PersistentVolume Provisioner。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
reclaimPolicy: Delete
volumeBindingMode: Immediate
在这个例子中:
apiVersion
指定了Kubernetes API的版本,这里是storage.k8s.io/v1
。kind
指定了这是一个StorageClass
对象。metadata.name
是这个StorageClass的名称,这里是standard
。provisioner
指定了动态供应器的名称,这里是kubernetes.io/aws-ebs
,表示使用AWS EBS作为后端存储。parameters
部分包含了供应器特定的参数:type
指定了EBS卷的类型,这里是gp2
(通用型SSD)。reclaimPolicy
指定了当PersistentVolume被删除时,后端存储的回收策略。这里是Delete
,表示删除PV时也会删除对应的EBS卷。volumeBindingMode
设置了卷绑定模式,这里是Immediate
,表示在PVC创建时立即绑定PV。
请注意,这个配置示例是针对AWS EBS的。如果你使用其他类型的存储,比如NFS、Ceph等,你需要相应地更改provisioner
和parameters
部分。
例如,如果你使用NFS作为后端存储,你的StorageClass配置可能看起来像这样:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
provisioner: example.com/nfs
parameters:
path: /exports/data
server: nfs-server.example.com
在这个NFS示例中:
provisioner
被设置为一个假想的NFS供应器名称example.com/nfs
(在实际使用中,你需要替换为实际的NFS供应器名称)。parameters
部分包含了NFS服务器的地址和共享路径。
要应用这个YAML配置,你可以使用kubectl create -f <filename>.yaml
命令,其中<filename>.yaml
是你的YAML文件的名称。例如:
kubectl create -f storageclass-nfs.yaml
这将创建一个名为nfs-storage
的StorageClass对象,用于动态供应NFS类型的PersistentVolumes。请确保你的Kubernetes集群已经配置了相应的动态供应器,并且该供应器能够访问你指定的后端存储。
三、生命周期管理
StatefulSet的生命周期管理。当增加或减少副本时,它会按顺序创建或删除Pod,确保旧的Pod先下线,新的Pod再上线,这样可以避免服务中断。而Deployment则是并行更新的,可能导致短暂的服务不可用。不过,这也要看具体的更新策略设置是否正确。主要的步骤有如下的几步:
-
创建与扩展
• 执行kubectl apply -f statefulset.yaml
创建资源。
• 扩容:kubectl scale statefulset my-database --replicas=5
,按索引顺序新增Pod。 -
更新与滚动机制
• 修改Pod镜像触发更新,新Pod按索引顺序启动,旧Pod逐步终止。
• 可观察kubectl describe statefulset
中的UpdateStrategy
和Progress
。 -
删除与清理
• 缩容至0后删除StatefulSet,自动清理关联的PVC(需设置storageClassName
并配置回收策略)。
四、典型应用场景**
-
数据库集群(MySQL、MongoDB、 ClickHouse)
每个Pod作为独立数据库实例,数据持久化且可通过稳定域名连接。 -
消息队列(Kafka、RabbitMQ, RocketMq)
Broker节点需要唯一标识和持久存储,确保分区和数据的分布一致性。 -
缓存系统(Redis Cluster)
实例间需协同工作,StatefulSet帮助管理节点位置和故障转移。
StatefulSet的应用场景,除了数据库,像Redis集群、Kafka这样的分布式系统也可能用到。例如,Kafka的Broker需要每个实例对应不同的分区,这时候StatefulSet可以方便地管理和扩展。
五、注意事项与最佳实践
-
存储配置
• 使用StorageClass
动态供应PVC,避免手动创建。
• 根据业务需求设置accessModes
(如ReadWriteOnce
或ReadWriteMany
)。 -
更新策略
• 生产环境建议设置maxUnavailable: 1
,防止大规模宕机:updateStrategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1
-
监控与调试
• 使用kubectl get pods -w
观察Pod状态变化。
• 结合Prometheus监控存储使用率和Pod健康状态。
监控和维护方面,可能需要关注StatefulSet的状态,比如当前有多少个Pod处于就绪状态,是否有重建或升级正在进行。同时,需要定期检查每个Pod的日志和健康状况,确保数据的一致性和服务的稳定性。
- 高可用性
• 配合Deployment
部署StatefulSet控制器,实现自我修复。
• 在多可用区部署时,结合云厂商的托管数据库服务(如AWS RDS)。
六、对比Deployment
特性 | StatefulSet | Deployment |
---|---|---|
网络标识 | 稳定DNS(pod-0.example.com) | 随机IP(pod-a.example.com) |
存储 | 每个Pod独立PVC | 共享Volume或无存储 |
扩缩容顺序 | 有序(索引递增/递减) | 无序 |
适用场景 | 数据库、消息队列等有状态应用 | 无状态微服务、批处理任务 |
StatefulSet与Deployment都是Kubernetes中用于管理Pod的资源对象,但它们的设计目的和服务场景有所不同。以下是StatefulSet与Deployment的主要区别:
一、应用场景
-
Deployment:
- 主要用于管理无状态应用。
- 无状态应用通常不需要持久化数据或唯一网络标识符。
- Deployment提供了一种简单的方式来部署和更新应用,支持滚动更新和回滚。
-
StatefulSet:
- 主要用于管理有状态应用。
- 有状态应用需要持久化数据或具有唯一网络标识符。
- StatefulSet提供了持久化存储和稳定的网络标识符,适用于需要保持数据完整性和服务身份的应用。
二、Pod管理
-
Pod命名与标识:
- Deployment:Pod名称是随机生成的,没有固定的顺序或标识。每个Pod都是可替换的,具有相同的配置和环境。
- StatefulSet:Pod名称是基于索引的,具有固定的顺序和标识。每个Pod都有一个唯一的、持久的身份标识。
-
存储:
- Deployment:Pod通常共享存储卷,但这不适用于有状态应用,因为数据可能会相互干扰。
- StatefulSet:每个Pod可以有独自的存储卷,通常与PersistentVolumeClaim(PVC)结合使用,以确保数据的持久化和隔离。
-
网络标识符:
- Deployment:Pod没有稳定的网络标识,通常通过Service进行通信。
- StatefulSet:Pod具有稳定的网络标识,如DNS名称,可以通过Headless Service精确访问到每一个Pod。
三、部署与更新策略
-
部署:
- Deployment:通过ReplicaSet管理Pod的副本数,支持滚动更新策略,允许逐个替换Pod以保持服务的可用性。
- StatefulSet:支持有序的创建和删除Pod,这在需要特定顺序执行初始化脚本或清理操作的情况下非常有用。StatefulSet不直接支持滚动更新,因为需要考虑数据的一致性和服务的连续性,更新过程通常需要更谨慎的操作,可能需要手动干预。
-
回滚:
- Deployment:支持自动回滚和暂停/恢复更新。
- StatefulSet:更新过程需要更谨慎的操作,回滚也可能需要手动管理。
四、其他特性
- Deployment:适用于Web应用服务器、微服务以及任何不需要持久化数据或特定网络标识的应用。
- StatefulSet:适用于数据库集群(如MySQL、Cassandra)、分布式缓存系统(如Redis集群)以及任何需要持久化数据或特定网络标识的应用。
Deployment和StatefulSet各有其适用场景和特性。在选择使用哪个资源对象时,应根据应用的具体需求进行考虑。对于无状态应用,使用Deployment可以提供简便的部署和更新流程;而对于有状态应用,使用StatefulSet可以确保数据的安全性和服务的连续性。
七、常见问题
• Q: Pod无法获取唯一标识?
A: 确保serviceName
正确,并检查Headless Service的DNS解析是否正常。
• Q: 数据丢失怎么办?
A: 验证PVC的reclaimPolicy
(如Delete
或Retain
),并检查备份策略。
• Q: 更新过程中服务中断?
A: 调整maxUnavailable
和maxSurge
,或采用蓝绿部署替代滚动更新。
通过合理利用StatefulSet
,开发者可以高效管理复杂的有状态应用,确保数据的可靠性和服务的稳定性。理解其底层机制和最佳实践,是构建健壮Kubernetes集群的关键一步。
八、拓展
【一起来学kubernetes】11、Deployment使用详解
【一起来学kubernetes】13、k8s中的controller的前世今生
【一起来学kubernetes】0、通过yum安装k8s过程中常见异常处理