第五篇:《Pod 控制器:Deployment、StatefulSet、DaemonSet》
直接创建 Pod 无法实现自愈、扩缩容、滚动更新等生产级需求。Kubernetes 通过控制器(Controller)来管理 Pod 的生命周期。本文深入讲解三种最常用的控制器:Deployment(无状态应用)、StatefulSet(有状态应用)和 DaemonSet(节点守护进程),并通过 YAML 示例和实操命令展示它们的典型用法。
一、为什么需要控制器?
裸 Pod 的局限性:
节点故障时不会自动重新调度。
不会维持副本数量(意外删除即丢失)。
无法实现滚动更新和回滚。
难以水平伸缩。
控制器通过控制循环持续监听实际状态与期望状态,并进行调谐(Reconcile)。你只需声明期望的 Pod 数量、更新策略等,控制器就会帮你达成。
二、Deployment:无状态应用的首选
Deployment 用于管理无状态应用,提供副本管理、滚动更新、回滚、扩容缩容等能力。它通过 ReplicaSet 来管理 Pod。
2.1 典型 YAML 示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
关键字段:
replicas:期望的 Pod 副本数。
selector:Deployment 管理的 Pod 标签选择器(必须与 template.metadata.labels 匹配)。
template:Pod 模板,定义 Pod 的具体规格。
strategy:更新策略(RollingUpdate 或 Recreate)。
2.2 常用操作
# 创建 Deployment
kubectl apply -f nginx-deploy.yaml
# 查看 Deployment 和 ReplicaSet 状态
kubectl get deploy,rs,po -l app=nginx
# 滚动更新镜像
kubectl set image deployment/nginx-deploy nginx=nginx:1.26
# 查看滚动更新状态
kubectl rollout status deployment/nginx-deploy
# 查看历史版本
kubectl rollout history deployment/nginx-deploy
# 回滚到上一个版本
kubectl rollout undo deployment/nginx-deploy
# 回滚到指定版本
kubectl rollout undo deployment/nginx-deploy --to-revision=2
# 扩容到 5 个副本
kubectl scale deployment/nginx-deploy --replicas=5
# 暂停更新(便于多次修改后一次性触发)
kubectl rollout pause deployment/nginx-deploy
# 恢复更新
kubectl rollout resume deployment/nginx-deploy
2.3 滚动更新策略解析
maxSurge:滚动更新期间,最多可以超出期望副本数的 Pod 数量(可以是绝对值或百分比)。
maxUnavailable:最多可以有多少个 Pod 处于不可用状态(绝对值或百分比)。
例:replicas=3, maxSurge=1, maxUnavailable=0 表示更新时最多有 4 个 Pod(3+1),且至少有 3 个可用。会先启动一个新 Pod,等新 Pod Ready 后再删除一个旧 Pod,循环直至全部更新。
三、StatefulSet:有状态应用的守护者
StatefulSet 用于管理有状态应用(如数据库、消息队列、分布式存储)。它提供:
稳定的网络标识:Pod 名称固定(如 mysql-0, mysql-1),顺序启动、倒序终止。
稳定的持久化存储:每个 Pod 关联独立的 PVC(卷声明),删除 Pod 后卷保留。
有序部署与扩展:从 0 到 N-1 依次创建,缩容时从大到小删除。
3.1 典型 YAML 示例(MySQL 主从简化版)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql-svc # 必须引用一个 Headless Service
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: "123456"
ports:
- containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
关键点:
serviceName:必须引用一个 Headless Service(clusterIP: None),用于提供稳定的 DNS 名称:...svc.cluster.local。
volumeClaimTemplates:每个 Pod 自动创建独立的 PVC(如 data-mysql-0, data-mysql-1),删除 StatefulSet 时 PVC 默认保留,需要手动清理。
3.2 常用操作
# 创建 StatefulSet 及关联 Service
kubectl apply -f mysql-sts.yaml
# 查看 Pod 创建顺序(依次启动)
kubectl get pods -w -l app=mysql
# 删除 StatefulSet(保留 PVC)
kubectl delete statefulset mysql --cascade=orphan
# 重新创建 StatefulSet 会复用原 PVC
3.3 适用场景
数据库:MySQL、PostgreSQL、MongoDB(需配合 Operator 更佳)。
消息队列:Kafka、RabbitMQ。
分布式存储:Elasticsearch、ZooKeeper、etcd。
注意:StatefulSet 并不解决数据备份、自动故障转移等数据库自身问题,这些需要借助 Operator 或应用自身能力。
四、DaemonSet:每个节点一个 Pod
DaemonSet 确保在集群的每个(或部分)节点上运行一个 Pod 副本。节点加入时自动添加 Pod,节点删除时 Pod 被回收。常用于:
日志收集(Fluentd、Filebeat)
监控代理(Prometheus Node Exporter、Datadog agent)
网络插件(Calico、Flannel 的 agent 部分)
存储插件(CSI 节点服务)
4.1 典型 YAML 示例(Node Exporter)
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
hostNetwork: true # 使用宿主机网络
hostPID: true # 使用宿主机 PID 命名空间
containers:
- name: node-exporter
image: prom/node-exporter:latest
args:
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
volumeMounts:
- name: proc
mountPath: /host/proc
readOnly: true
- name: sys
mountPath: /host/sys
readOnly: true
volumes:
- name: proc
hostPath:
path: /proc
- name: sys
hostPath:
path: /sys
4.2 控制 DaemonSet 仅在部分节点运行
通过 nodeSelector 或亲和性限制:
spec:
template:
spec:
nodeSelector:
disktype: ssd # 只调度到标记为 ssd 的节点
4.3 常用操作
# 查看 DaemonSet 和其管理的 Pod
kubectl get ds,po -l app=node-exporter
# 更新 DaemonSet(镜像升级)
kubectl set image ds/node-exporter node-exporter=prom/node-exporter:v1.5.0
# 回滚
kubectl rollout undo ds/node-exporter
五、三种控制器的对比总结
六、最佳实践
无状态应用优先使用 Deployment,简单且功能完善。
有状态应用评估是否真的需要 StatefulSet:如果不需要稳定的网络标识和独立存储,Deployment 也可挂载共享存储(但一般不推荐)。
DaemonSet 的更新策略:通常使用 RollingUpdate,避免日志收集中断。
资源限制:为所有容器设置 requests/limits,特别是 DaemonSet,防止耗尽节点资源。
避免在 StatefulSet 中直接存储大量数据:建议使用外部数据库服务或云存储。
七、小结
Deployment、StatefulSet、DaemonSet 覆盖了大多数工作负载类型。掌握它们的特性,可以合理选择控制器,构建高可用的应用。实际生产中,Deployment 使用最频繁,StatefulSet 用于核心有状态服务,DaemonSet 用于节点级基础设施。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)