Kubernetes(3)控制器的应用详解
一、什么是控制器
官方文档:
工作负载管理 | Kubernetes
控制器是 Kubernetes 中用于管理 Pod 的一种机制,分为两类:
-
自主式 Pod:Pod 退出或意外关闭后不会被重新创建。
-
控制器管理的 Pod:在控制器的生命周期内,始终维持指定的 Pod 副本数量。
Pod 控制器作为管理 Pod 的中间层,用户只需声明期望的 Pod 数量与规格,控制器会负责创建并维持这些 Pod 的运行状态。若 Pod 出现故障,控制器会依据指定策略自动恢复。
工作流程简述:
-
创建控制器后,期望状态写入 etcd。
-
apiserver 持续检索 etcd 中的期望状态,并与 Pod 当前状态进行对比。
-
若出现差异,系统自动驱动恢复至期望状态。
二、控制器常用类型一览
控制器名称 | 用途简述 |
---|---|
ReplicationController | 早期的 Pod 副本控制器,已被废弃,由 ReplicaSet 替代。 |
ReplicaSet | 确保任意时刻都有指定数量的 Pod 副本在运行。 |
Deployment | 为 Pod 与 ReplicaSet 提供声明式更新能力,支持滚动更新、回滚、扩缩容等。 |
DaemonSet | 确保全部(或指定)节点上运行一个 Pod 副本,常用于日志收集、监控等系统级服务。 |
StatefulSet | 管理有状态应用,提供稳定的网络标识与持久化存储。 |
Job | 执行一次性批处理任务,确保指定数量的 Pod 成功完成。 |
CronJob | 基于时间调度,周期性执行 Job 任务。 |
HPA(Horizontal Pod Autoscaler) | 根据资源利用率自动调整 Pod 数量,实现水平扩缩容。 |
查看容器名称
名字不会一直叫这个
如果出现了故障退出,那每次启动时,名字都会变化,那这里就做不了主从复制,要解决就要把他的名字固定住,每次登录还是一样的名字
三、ReplicaSet 控制器详解
3.1 ReplicaSet 功能概述
-
ReplicaSet 是 ReplicationController 的下一代实现,官方推荐使用。
-
与 ReplicationController 的唯一区别在于选择器支持:ReplicaSet 支持基于集合的标签选择器。
-
核心功能:确保任意时刻都有指定数量的 Pod 副本在运行。
-
实际使用中,ReplicaSet 通常由 Deployment 间接管理,用于协调 Pod 的创建、删除与更新。
3.2 ReplicaSet 参数说明
参数名 | 类型 | 说明 |
---|---|---|
spec | Object | 对象的详细定义,固定值写 Spec 。 |
spec.replicas | int | 指定需要维护的 Pod 副本数量。 |
spec.selector | Object | 标签选择器,用于匹配 Pod。 |
spec.selector.matchLabels | map | 以 key:value 形式指定匹配标签。 |
spec.template | Object | Pod 模板,副本不足时根据此模板创建新 Pod。 |
spec.template.metadata | Object | Pod 元数据定义。 |
spec.template.metadata.labels | map | Pod 标签定义。 |
spec.template.spec | Object | Pod 的详细定义。 |
spec.template.spec.containers | list | 容器列表定义。 |
containers.name | string | 容器名称。 |
containers.image | string | 容器镜像。 |
3.3 ReplicaSet 实战示例
3.3.1 创建 ReplicaSet
# 1. 生成 YAML 模板
kubectl create deployment replicaset --image myapp:v1 \--dry-run=client -o yaml > replicaset.yml# 2. 编辑 YAML,将 Kind 改为 ReplicaSet
vim replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:name: replicaset # 对象名称,必须小写
spec:replicas: 2 # 维持 2 个 Pod 副本selector: # 标签选择器matchLabels:app: myapp # 匹配标签 app=myapptemplate: # Pod 模板metadata:labels:app: myappspec:containers:- image: myapp:v1name: myapp
# 3. 应用配置
kubectl apply -f replicaset.yml# 4. 查看结果
kubectl get pods --show-labels
# NAME READY STATUS RESTARTS AGE LABELS
# replicaset-l4xnr 1/1 Running 0 96s app=myapp
# replicaset-t2s5p 1/1 Running 0 96s app=myapp
3.3.2 标签匹配与自愈测试
ReplicaSet 通过标签精准匹配 Pod,任何标签变动都会触发“维持副本数”动作。
# 1. 修改其中一个 Pod 的标签
kubectl label pod replicaset-l4xnr app=timinglee --overwrite# 2. 观察 ReplicaSet 立即启动新 Pod 保持总数为 2
kubectl get pods --show-labels
# NAME READY STATUS RESTARTS AGE LABELS
# replicaset-gd5fh 1/1 Running 0 2s app=myapp # 新增
# replicaset-l4xnr 1/1 Running 0 3m19s app=timinglee # 标签已改
# replicaset-t2s5p 1/1 Running 0 3m19s app=myapp# 3. 恢复标签(删除 timinglee 标签)
kubectl label pod replicaset-l4xnr app-# 4. ReplicaSet 再次维持 2 个副本,多余的 Pod 会被自动回收
kubectl get pods --show-labels
3.3.3 删除 Pod 观察自愈
# 手动删除一个 Pod
kubectl delete pod replicaset-t2s5p# ReplicaSet 立即创建新 Pod 保持副本数为 2
kubectl get pods --show-labels
删除pods还会重新建一个
指定的标签不一致,就不算上这个不一致的了
将其修改回去
修改个数,可以拉伸也可以声明
再次重启yml,会根据yml中的内容再次刷新个数
3.3.4 清理资源
kubectl delete -f replicaset.yml
四、Deployment 控制器详解
4.1 Deployment 功能概述
-
自 Kubernetes v1.2 引入,用于解决服务编排问题。
-
不直接管理 Pod,而是通过管理 ReplicaSet 间接管理 Pod。
-
提供 声明式更新,支持:
-
滚动更新与回滚
-
扩容与缩容
-
暂停与恢复更新
-
Deployment 中的每个 ReplicaSet 对应一个版本,方便灰度发布与回滚。
4.2 Deployment 实战示例
4.2.1 创建 Deployment
# 1. 导出模板
kubectl create deployment deployment --image myapp:v1 \--dry-run=client -o yaml > deployment.yml# 2. 编辑 YAML:调整副本数、添加标签、暴露端口等
vim deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: deployment
spec:replicas: 4selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:containers:- image: myapp:v1name: myapp
# 3. 应用并查看
kubectl apply -f deployment.yml
kubectl get pods --show-labels
# NAME READY STATUS RESTARTS AGE LABELS
# deployment-5d886954d4-2ckqw 1/1 Running 0 23s app=myapp,pod-template-hash=5d886954d4
# deployment-5d886954d4-m8gpd 1/1 Running 0 23s app=myapp,pod-template-hash=5d886954d4
# deployment-5d886954d4-s7pws 1/1 Running 0 23s app=myapp,pod-template-hash=5d886954d4
# deployment-5d886954d4-wqnvv 1/1 Running 0 23s app=myapp,pod-template-hash=5d886954d4
4.2.2 版本迭代(滚动更新)
-
查看当前版本
kubectl get pods -o wide
curl 10.244.2.14
# Hello MyApp | Version: v1 | ...
-
修改镜像版本并应用
# deployment.yml
- image: myapp:v1
+ image: myapp:v2
kubectl apply -f deployment.yml
1.实时观察滚动更新过程
watch -n 1 kubectl get pods -o wide
# 新 ReplicaSet 逐步创建 v2 Pod,旧 ReplicaSet 缩容至 0
2.验证更新效果
kubectl get pods -o wide
curl 10.244.1.26
# Hello MyApp | Version: v2 | ...
更新过程会新建一个 ReplicaSet(v2),旧 ReplicaSet(v1)逐步缩容,实现 零停机 发布。
四、Deployment 控制器详解
4.2.3 版本回滚
-
将镜像改回 v1 并重新应用
# deployment.yml
- image: myapp:v2
+ image: myapp:v1
kubectl apply -f deployment.yml
-
验证回滚结果
kubectl get pods -o wide
curl 10.244.2.26
# Hello MyApp | Version: v1 | ...
4.2.4 自定义滚动更新策略
在 spec.strategy.rollingUpdate
中可精细控制更新节奏:
spec:replicas: 4strategy:type: RollingUpdaterollingUpdate:maxSurge: 1 # 更新过程中可额外超出期望副本数的 Pod 数量maxUnavailable: 0 # 更新过程中允许不可用 Pod 的最大数量minReadySeconds: 5 # Pod 就绪后等待 5 秒再标记为可用,避免过早进入下一轮更新
应用后,Kubernetes 会严格按策略执行滚动更新:
kubectl apply -f deployment.yml
影响最小的,最丝滑的更新策略
更一个关一个
maxUn~~更新中不能用的是0个,这里就是不能有不能用的
4.2.5 暂停与恢复更新
场景:一次变更涉及多个字段(镜像、资源、副本数),希望全部修改完成后再一次性触发更新。
1.暂停 Deployment 的滚动更新
kubectl rollout pause deployment deployment
2.任意次修改 YAML(镜像、资源限制、副本数等)
spec:replicas: 6template:spec:containers:- name: myappimage: nginxresources:limits:cpu: 0.5memory: 200Mirequests:cpu: 0.5memory: 200Mi
kubectl apply -f deployment.yml
3.验证:暂停期间仅副本数生效,镜像与资源变更不会触发滚动更新
kubectl rollout history deployment deployment
# 仅记录到暂停前的版本
4.恢复滚动更新,一次性应用所有变更
kubectl rollout resume deployment deployment
5.恢复滚动更新,一次性应用所有变更
kubectl rollout history deployment deployment
# deployment.apps/deployment
# REVISION CHANGE-CAUSE
# 3 <none>
# 4 <none>
# 5 <none>
6.清理资源
kubectl delete -f deployment.yml
五、DaemonSet 控制器详解
5.1 DaemonSet 功能概述
DaemonSet 保证每个(或指定的)节点上永远运行一个 Pod 副本。
随着集群节点的增删,DaemonSet 会自动在这些节点上创建或回收 Pod。
典型使用场景
-
日志收集:Fluentd、Filebeat、Logstash
-
监控代理:Prometheus Node Exporter、Zabbix Agent
-
存储守护进程:glusterd、ceph-osd
-
网络插件:Calico、Flannel、Weave 的 Node 组件
与 Deployment 不同,DaemonSet 不关注副本总数,而是关注节点覆盖度。
5.2 DaemonSet 实战示例
5.2.1 编写 YAML
# daemonset-example.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:name: daemonset-example
spec:selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:# 允许调度到 Master 等带有 taint 的节点tolerations:- key: node-role.kubernetes.io/masteroperator: Existseffect: NoSchedulecontainers:- name: nginximage: nginx:alpineports:- containerPort: 80
5.2.2 创建与验证
kubectl apply -f daemonset-example.yml# 查看每个节点上的 Pod
kubectl get pods -o wide
# NAME READY STATUS IP NODE
# daemonset-87h6s 1/1 Running 10.244.0.8 k8s-master
# daemonset-n4vs4 1/1 Running 10.244.2.38 k8s-node2
# daemonset-vhxmq 1/1 Running 10.244.1.40 k8s-node1
5.2.3 节点伸缩演示
-
向集群新增一台工作节点(虚拟机或云主机加入即可)。
-
无需任何人工干预,DaemonSet 在新节点自动拉起一个 nginx Pod。
-
将节点下线,对应 Pod 随之被垃圾回收。
5.2.4 清理资源
kubectl delete -f daemonset-example.yml
过滤一下污点信息
现在只在master设定了污点,默认是不被调用的
我们的myapp是会在node1&2上都会有,但是master上是默认不会有的,因为是有污点的
但是master上也不是不可以有,可以设置对污点的容忍度,就可以运行了
强容忍,即便有也不在乎
六、Job 控制器详解
6.1 Job 功能概述
Job 用于执行一次性批处理任务,特点如下:
-
成功结束的 Pod 会被计数,达到
completions
指定数量即视为 Job 完成。 -
失败时可按
backoffLimit
重试。 -
任务完成后不会重启 Pod(restartPolicy 必须为 Never 或 OnFailure)。
6.2 Job 实战示例
6.2.1 计算圆周率后 2000 位
# job.yml
apiVersion: batch/v1
kind: Job
metadata:name: pi
spec:completions: 6 # 总任务数parallelism: 2 # 并发数template:spec:containers:- name: piimage: perl:5.34.0command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]restartPolicy: NeverbackoffLimit: 4 # 失败重试上限
6.2.2 启动与观察
kubectl apply -f job.yml# 实时查看进度
kubectl get jobs -w
# NAME COMPLETIONS DURATION AGE
# pi 0/6 5s 5s
# pi 2/6 20s 20s
# pi 4/6 40s 40s
# pi 6/6 60s 60s# 查看某个 Pod 的计算结果
kubectl logs pi-xxxxx | head -c 100
# 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706...
此时运行就是两个两个开始建立
直到完成6个的创建
6.2.3 重启策略说明
restartPolicy | Pod 失败时的行为 |
---|---|
Never | 创建新 Pod,旧 Pod 保留;失败计数 +1 。 |
OnFailure | 原地重启容器,不新建 Pod;失败计数不变。 |
Always | 与 Job 语义冲突,会导致任务无限循环,禁止在 Job 中使用。 |
6.2.4 清理
kubectl delete -f job.yml
七、CronJob 控制器详解
7.1 CronJob 功能概述
CronJob 用于在 固定时间点或周期 运行 Job,相当于 Linux 的 crontab + Kubernetes Job:
-
调度规则遵循标准的 5 位 cron 表达式(分钟 小时 日 月 星期)。
-
每次调度都会 新建一个 Job 对象,再由 Job 创建 Pod 执行任务。
-
支持 并发策略(禁止并发、允许并发、替换旧任务)与 任务历史限制。
7.2 CronJob 实战示例
7.2.1 每分钟打印问候信息
# cronjob.yml
apiVersion: batch/v1
kind: CronJob
metadata:name: hello
spec:schedule: "* * * * *" # 每分钟一次jobTemplate:spec:template:spec:containers:- name: helloimage: busybox:1.36imagePullPolicy: IfNotPresentcommand:- /bin/sh- -c- date; echo Hello from the Kubernetes clusterrestartPolicy: OnFailuresuccessfulJobsHistoryLimit: 3 # 保留最近 3 次成功的 JobfailedJobsHistoryLimit: 1 # 保留最近 1 次失败的 Job
7.2.2 创建与验证
kubectl apply -f cronjob.yml# 1 分钟后即可看到 Job & Pod 被自动创建
kubectl get cronjob,job,pod -l app=hello
# NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
# cronjob.batch/hello * * * * * False 0 10s 65s# NAME COMPLETIONS DURATION AGE
# job.batch/hello-28554250 1/1 2s 10s# NAME READY STATUS RESTARTS AGE
# pod/hello-28554250-xxxxx 0/1 Completed 0 10s
7.2.3 查看任务日志
kubectl logs hello-28554250-xxxxx
# Wed Aug 13 07:42:01 UTC 2025
# Hello from the Kubernetes cluster
先显示系统时间
如果本地有镜像就不拉,没有就拉取
如果挂了,就重新开启
每隔一分钟,会新建一个
7.2.4 Cron 表达式速查
表达式 | 含义 |
---|---|
*/5 * * * * | 每 5 分钟 |
0 2 * * * | 每天凌晨 2 点 |
0 0 1 * * | 每月 1 号午夜 |
0 8 * * 1 | 每周一早晨 8 点 |
7.2.5 并发与历史记录控制
spec:concurrencyPolicy: Forbid # Allow | Forbid | ReplacestartingDeadlineSeconds: 10 # 如果 10 秒内任务没调度成功则标记失败successfulJobsHistoryLimit: 3failedJobsHistoryLimit: 1
7.2.6 清理
kubectl delete -f cronjob.yml
八、总结与最佳实践
控制器类型 | 适用场景关键词 | 核心记忆点 |
---|---|---|
ReplicaSet | 长期运行、无状态、固定副本数 | 只保证数量,不保证顺序 |
Deployment | 无状态、滚动更新、回滚、扩缩容 | 管理 ReplicaSet 的 “版本” |
DaemonSet | 节点级守护进程、日志/监控收集 | 每节点一个 |
Job | 一次性批处理、计算任务 | 成功计数达到 completions 即完成 |
CronJob | 周期性批处理、备份、报表 | cron 表达式 + Job 模板 |
8.1 日常运维指令速查
# 查看 Deployment 滚动更新状态
kubectl rollout status deploy <name># 回滚到上一版本
kubectl rollout undo deploy <name># 查看历史版本
kubectl rollout history deploy <name># 立即触发 CronJob(手动测试)
kubectl create job hello-manual --from=cronjob/hello
8.2 YAML 模板通用结构提醒
-
所有控制器都必须有
apiVersion / kind / metadata / spec
四件套。 -
Pod 模板字段
spec.template
与直接创建 Pod 的 YAML 完全一致,只是嵌套层级更深。 -
标签选择器
matchLabels
必须在控制器与 Pod 模板中 完全匹配,否则会出现无限创建或无法调度。