嘿,兄弟们!如果你正在用Kubernetes跑无状态服务,比如前端网站、API接口这些,那可能觉得StatefulSet这玩意儿离你有点远。但要是你已经开始玩数据库、消息队列、分布式存储这类“有脾气”的服务——比如MySQL主从、Redis集群、ZooKeeper什么的,那你可真得好好了解一下StatefulSet了。

今天这篇文章,咱不整那些高深莫测的概念堆砌,也不搞一堆YAML文件让你看得头大。咱们就从实际出发,结合阿里云的Kubernetes服务(ACK),带你一步一步上手StatefulSet,让你真正理解它到底能干啥、怎么用、为啥非它不可。
StatefulSet是啥?跟Deployment有啥不一样?
先来点轻松的科普。你在K8s里最常见的控制器可能是Deployment,它用来管理无状态应用,比如Nginx、微服务之类的。这些服务的特点是:每个实例都长得一模一样,换一个也无所谓,反正数据不存本地。
但有些服务就不一样了,它们对“身份”特别讲究。比如你有个MySQL主从集群,三个节点分别是mysql-0、mysql-1、mysql-2,每个都有自己的数据目录,还可能配置了主从复制关系。这时候你要扩容或缩容,就不能随便删一个节点,否则数据就乱套了。
这时候就得靠StatefulSet出场了。它的核心特点是:
- 稳定的网络标识:每个Pod都有固定的主机名,比如nginx-0、nginx-1,重启后名字不变。
- 稳定的持久化存储:每个Pod绑定独立的PVC,即使Pod重建,数据依然跟着走。
- 有序部署和销毁:启动按顺序来,0→1→2;关闭时倒着来,2→1→0,避免数据混乱。
说白了,StatefulSet就是给“有身份、有数据、讲秩序”的应用准备的专属管家。
在阿里云ACK上动手实操:部署一个MySQL主从集群
光说不练假把式,咱们直接上真家伙。假设你现在要在阿里云上搭一个三节点的MySQL主从集群,每个节点都要有自己的数据盘,还能稳定运行。下面我就带你一步步来。
第一步:准备好你的ACK集群
登录阿里云控制台,进入容器服务 Kubernetes 版(ACK)。如果你还没创建集群,建议选标准托管版,省心省力。创建好之后,通过kubectl连接到集群。
确认一下环境:
kubectl get nodes
看到几个Worker节点正常运行就行。接下来,我们要为MySQL准备存储。
第二步:创建StorageClass和PV/PVC
MySQL的数据可不能丢,所以我们得用阿里云的云盘(ESSD或SSD)来做持久化存储。阿里云默认已经提供了一个叫alicloud-disk-ssd的StorageClass,我们可以直接用。
先写个简单的Service,给StatefulSet提供稳定的DNS访问:
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
labels:
app: mysql
spec:
ports:
- name: mysql
port: 3306
clusterIP: None
selector:
app: mysql
这个Service叫做“无头服务”(Headless Service),它不分配ClusterIP,但能让每个Pod获得一个稳定的DNS域名,比如mysql-0.mysql-headless.default.svc.cluster.local。
第三步:编写StatefulSet配置文件
这才是重头戏。我们来写一个最简版的MySQL StatefulSet:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql-headless"
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: "yourpassword"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "alicloud-disk-ssd"
resources:
requests:
storage: 20Gi
重点解释几个关键点:
serviceName指向前面创建的headless service,这是StatefulSet的标配。replicas: 3表示我们要起三个MySQL实例。volumeClaimTemplates是灵魂所在!它会为每个Pod自动生成一个PVC,名字自动是mysql-data-mysql-0这种格式,永久绑定。
保存为mysql-statefulset.yaml,然后apply一下:
kubectl apply -f mysql-statefulset.yaml
等几分钟,执行:
kubectl get pods -l app=mysql
你会看到:
mysql-0 1/1 Running 0 2m
mysql-1 1/1 Running 0 1m
mysql-2 1/1 Running 0 30s
看到没?顺序启动,名字固定,稳如老狗。
进阶玩法:怎么让主从自动配置?
上面的例子只是起了三个独立的MySQL实例,还没做主从复制。真实场景中,你肯定希望第一个是主库,后面两个是只读从库。
这时候就需要初始化脚本了。我们可以通过Init Container或者启动命令配合ConfigMap来实现。
简单点的做法是在镜像启动时判断Pod序号:
command:
- sh
- -c
- |
if [[ $HOSTNAME = "mysql-0" ]]; then
echo "Initializing MySQL Master..."
# 配置为主库
else
echo "Configuring MySQL Slave..."
# 配置为从库,指向mysql-0
fi
exec mysqld --user=mysql
完整的主从配置涉及GTID、binlog、权限设置等,这里就不展开写了。你可以把初始化SQL打包进ConfigMap,挂载到容器里执行。
StatefulSet常见坑点提醒
别以为写完YAML就万事大吉,StatefulSet有几个容易踩的坑,我给你列出来,省得你半夜被报警叫醒。
1. 不要手动删Pod
StatefulSet的Pod是有“身份证”的。你手动删了mysql-1,它重建后还是叫mysql-1,但背后的PVC不会变,数据还在。但如果你删的是PVC,那数据就真没了!所以除非你明确知道后果,否则千万别手贱删PVC。
2. 扩容缩容要谨慎
扩容时,StatefulSet会按顺序创建新Pod,比如从mysql-3开始。缩容时则是倒着来,先删mysql-2,再删mysql-1。这个顺序很重要,尤其是你在做分片或者一致性哈希的时候。
3. 更新策略默认是OnDelete
很多新手会发现改了镜像版本,Pod却不更新。这是因为StatefulSet默认的更新策略是OnDelete,你得手动删Pod才会触发重建。如果你想改成滚动更新,可以在spec里加上:
updateStrategy:
type: RollingUpdate
这样改完配置,K8s就会自动一个个替换Pod了。
为什么选择阿里云ACK?
说实话,自己搭K8s集群太累了,etcd要维护、网络插件要调、节点监控要配……而阿里云ACK帮你把底层全包了,你只需要关注应用本身。
而且阿里云的云盘性能稳定,对接OSS、SLB、日志服务也都是一键集成。特别是做StatefulSet这种需要持久化存储的场景,用ESSD云盘+自动快照,安全感拉满。
最关键的是,价格真不贵。尤其现在新用户或者老用户续费,经常有大额优惠。我建议你趁活动期间多领点阿里云优惠券,部署多个测试环境都不心疼。
StatefulSet不是银弹,但该用就得用
最后唠一句:StatefulSet虽然强大,但也不是所有有状态服务都适合用它。比如某些数据库集群自己有一套编排逻辑(比如MongoDB ReplicaSet),可能更适合用Operator来管理。
但对于大多数需要稳定身份+持久存储的场景,StatefulSet依然是K8s生态中最可靠的选择之一。尤其是在阿里云ACK上,结合云盘、VPC、安全组等能力,部署起来又快又稳。
别再用Deployment硬扛MySQL了!是时候升级你的K8s技能树,把StatefulSet纳入日常工具箱了。
动手试试吧,遇到问题欢迎留言交流。
内容均以整理官方公开资料,价格可能随活动调整,请以购买页面显示为准,如涉侵权,请联系客服处理。
本文由星速云发布。发布者:星速云。禁止采集与转载行为,违者必究。出处:https://www.67wa.com/149415.html