
Kubernetes 核心控制器目录一、什么是控制器Pod 控制器的本质二、K8s 常用控制器类型一览三、ReplicaSet 控制器3.1 功能与参数3.2 实验一建立 ReplicaSet 并拉伸3.3 实验二标签匹配 Pod 自愈四、Deployment 控制器4.1 功能与三层架构4.2 实验一建立 Deployment 并发布 Service4.3 实验二版本升级与回滚4.4 实验三查看与设定更新策略maxSurge / maxUnavailable4.5 实验四更新暂停与恢复五、DaemonSet 控制器5.1 功能与典型用途5.2 实验建立 DaemonSet 新节点加入自动扩容六、Job 控制器6.1 功能6.2 实验并行计算 π / busybox 一次性任务七、CronJob 控制器7.1 功能7.2 实验每分钟输出 hello一、什么是控制器Pod 控制器的本质K8s 里的Pod 控制器是“管理 Pod 的中间层”。我们写好一份 yaml 描述“期望有几个 Pod、Pod 长什么样”控制器负责让实际状态始终贴近期望状态。官方文档https://v1-30.docs.kubernetes.io/zh-cn/docs/concepts/workloads/controllers/两类 Pod 的区别类型Pod 退出 / 误关后副本数谁来维持自主式 Pod不会被重建自己创建多少就是多少无控制器管理的 Pod会被重建始终维持期望副本数受replicas约束控制器控制器的工作原理声明式 调和循环 Reconcile Loop用户执行kubectl apply -f xxx.yml提交期望状态replicas、镜像、标签…apiserver 将期望值写入 etcd持久化保存控制器Controller Manager 中的 Deployment / RS / DS 等控制器持续 List/Watch对比期望状态与实际状态一旦发现差异控制器自愈缺则建、多则删、不对则改kubelet 在节点上实际创建 / 维护 Pod 副本回报实际状态。一句话总结控制器 “期望状态”与“实际状态”之间的纠偏器。二、K8s 常用控制器类型一览控制器用途Replication Controller早期 Pod 控制器已废弃由 ReplicaSet 替代ReplicaSet确保任意时刻都有指定数量的 Pod 副本在运行基于标签选择器Deployment声明式管理 Pod 与 RS滚动更新、回滚、扩缩容、暂停/恢复DaemonSet在每个或指定节点上运行一个 Pod 副本StatefulSet管理有状态应用稳定的网络标识、持久化存储Job批处理任务保证一个或多个 Pod 成功结束后停止CronJob基于时间调度创建 Job类似 Linux crontabHPAHorizontal Pod Autoscaler根据资源利用率自动水平扩缩 Pod 副本本文覆盖ReplicaSet / Deployment / DaemonSet / Job / CronJob五个最常用的StatefulSet、HPA 后续单独整理。三、ReplicaSet 控制器3.1 功能与参数功能ReplicaSet 是 Replication Controller 的下一代。唯一区别是选择器ReplicaSet 支持新的基于集合的选择器matchLabels / matchExpressions。虽然 ReplicaSet 可以独立使用但官方推荐通过 Deployment 来管理ReplicaSet这样自动获得滚动更新、回滚等能力。关键参数字段类型说明spec.replicasinteger期望维护的 Pod 数量默认 1spec.selectorObject对 Pod 的标签查询必须与 Pod 标签匹配spec.selector.matchLabelsmap[string]stringkey: value形式精确匹配spec.templateObject副本不足时按此模板创建 Pod含 labels 与 specspec.template.metadata.labelsmap[string]stringPod 标签必须与 selector 匹配spec.template.spec.containerslist容器列表含 name、image 等3.2 实验一建立 ReplicaSet 并拉伸# 1) 用 deployment 模板生成 yml再改成 ReplicaSet[rootmaster controler]# kubectl create deployment webcluster --image myapp:v1 \--dry-runclient-oyamlrepset.yml[rootmaster controler]# vim repset.ymlapiVersion: apps/v1 kind: ReplicaSet metadata: labels: app: webcluster name: webcluster spec: replicas:2selector: matchLabels: app: webcluster# strategy: {}template: metadata: labels: app: webcluster spec: containers: - image: myapp:v1 name: myapp[rootmaster controler]# kubectl apply -f repset.ymlreplicaset.apps/webcluster created# 2) 监控[rootmaster ~]# watch -n 1 kubectl get pods --show-labelsNAME READY STATUS RESTARTS AGE LABELS webcluster-tbxq41/1 Running06m49sappwebcluster webcluster-jna231/1 Running06m49sappwebcluster# 3) 拉伸 / 缩容[rootmaster controler]# kubectl scale replicaset webcluster --replicas 4[rootmaster controler]# kubectl scale replicaset webcluster --replicas 2[rootmaster controler]# kubectl scale replicaset webcluster --replicas 0验证扩到 4 副本NAME READY STATUS RESTARTS AGE LABELS webcluster-4sxz4 1/1 Running 0 13s appwebcluster webcluster-lvtsn 1/1 Running 0 13s appwebcluster webcluster-tbxq4 1/1 Running 0 9m23s appwebcluster webcluster-tr5qk 1/1 Running 0 13s appwebcluster3.3 实验二标签匹配 Pod 自愈ReplicaSet只通过标签管理 Pod。把 Pod 的标签改掉RS 会认为这 Pod “不属于我”立刻补一个删一个 PodRS 也会补一个。# 1) 故意把一个 Pod 的标签改掉让它脱离 RS 管理[rootmaster controler]# kubectl label pod replicaset-l4xnr apptiminglee --overwritepod/replicaset-l4xnr labeled# 2) RS 发现匹配 appmyapp 的 Pod 不够了 → 立即补一个[rootmaster controler]# kubectl get pods --show-labelsNAME READY STATUS RESTARTS AGE LABELS replicaset-gd5fh1/1 Running02sappmyapp# 新补的replicaset-l4xnr1/1 Running03m19sapptiminglee replicaset-t2s5p1/1 Running03m19sappmyapp# 3) 直接 delete 一个 PodRS 也会重建[rootmaster controler]# kubectl delete pods replicaset-t2s5ppodreplicaset-t2s5pdeleted[rootmaster controler]# kubectl get pods --show-labelsNAME READY STATUS RESTARTS AGE LABELS replicaset-l4xnr1/1 Running05m43sappmyapp replicaset-nxmr91/1 Running015sappmyapp# 重建的# 4) 回收[rootmaster controler]# kubectl delete -f repset.yml⚠️ 标签错改可能让 Pod 脱离控制器管理进而被重建 → 在生产环境不要随便kubectl label ... --overwrite。四、Deployment 控制器4.1 功能与三层架构为了解决“滚动更新/回滚/扩缩容”等更复杂的编排需求K8s 在v1.2引入 Deployment。Deployment 不直接管 Pod而是管理 ReplicaSetReplicaSet 再管理 PodDeployment ── ReplicaSet一个版本一个 ── Pod x N典型应用场景创建 Pod 和 ReplicaSet滚动更新和回滚扩容和缩容暂停与恢复每次更新时Deployment 都会新建一个版本的 RS新 RS 创建新 Pod老 RS 逐步回收。老 RS 保留以便回滚——所以你可以把“RS 看作 Deployment 的一个版本快照”。4.2 实验一建立 Deployment 并发布 Service# 1) 生成 yaml 模板[rootmaster controler]# kubectl create deployment webcluster --image myapp:v1 \--dry-runclient-oyamldep.yml[rootmaster controler]# vim dep.ymlapiVersion: apps/v1 kind: Deployment metadata: labels: app: webcluster name: webcluster spec: minReadySeconds:5replicas:2selector: matchLabels: app: webcluster template: metadata: labels: app: webcluster spec: containers: - image: myapp:v1 name: myapp[rootmaster controler]# kubectl apply -f dep.ymldeployment.apps/webcluster created# 2) 监控看 Pod 多了 pod-template-hash 标签[rootmaster ~]# watch -n 1 kubectl get pods --show-labels;echo ; \kubectl get replicasets.apps NAME READY STATUS RESTARTS AGE LABELS webcluster-77c87d9946-49kh51/1 Running045sappwebcluster,pod-template-hash77c87d9946 webcluster-77c87d9946-m2x2d1/1 Running045sappwebcluster,pod-template-hash77c87d9946NAME DESIRED CURRENT READY AGE webcluster-77c87d994622245spod-template-hash是 Deployment 给每个 RS 自动加的标签保证 RS 与 Pod 之间的唯一关联。# 3) 发布为 Service 供集群内访问[rootmaster controler]# kubectl expose deployment webcluster --port 80 --target-port 80service/webcluster exposed[rootmaster controler]# kubectl describe services webclusterName: webcluster Namespace: default Selector:appwebcluster Type: ClusterIP IP:10.107.142.60 Port:80/TCP TargetPort:80/TCP Endpoints:10.244.2.6:80,10.244.1.9:80# 4) 验证[rootmaster controler]# curl 10.107.142.60Hello MyApp|Version: v1|ahrefhostname.htmlPod Name/a4.3 实验二版本升级与回滚升级v1 → v2[rootmaster controler]# vim dep.yml# ... 把 image 改为 myapp:v2- image: myapp:v2[rootmaster controler]# kubectl apply -f dep.ymldeployment.apps/webcluster configured[rootmaster controler]# curl 10.107.142.60Hello MyApp|Version: v2|ahrefhostname.htmlPod Name/a回滚v2 → v1[rootmaster controler]# vim dep.yml# ... 把 image 改回 myapp:v1- image: myapp:v1[rootmaster controler]# kubectl apply -f dep.yml[rootmaster controler]# curl 10.107.142.60Hello MyApp|Version: v1|ahrefhostname.htmlPod Name/a查看历史版本[rootmaster controler]# kubectl rollout history deployment webclusterdeployment.apps/webcluster REVISION CHANGE-CAUSE1none2none回滚不一定要再改 yaml可以直接用kubectl rollout undo# 回到上一版kubectl rollout undo deployment webcluster# 回到指定版本kubectl rollout undo deployment webcluster --to-revision14.4 实验三查看与设定更新策略Deployment 默认是RollingUpdate滚动更新可以查看与调优# 1) 把副本数调大便于观察[rootmaster controler]# vim dep.ymlspec: replicas:6[rootmaster controler]# kubectl apply -f dep.yml# 2) 查看默认更新策略[rootmaster controler]# kubectl describe deployments.apps webclusterRollingUpdateStrategy:25% max unavailable,25% max surge自定义策略spec:strategy:rollingUpdate:maxSurge:1# 更新时 Pod 数量最多比期望值多 1maxUnavailable:0# 不能让可用 Pod 数量少于期望值maxSurge滚动过程中允许超出的 Pod 数maxUnavailable滚动过程中允许不可用的 Pod 数。4.5 实验四更新暂停与恢复真实生产里我们可能一次改多处 yaml希望所有改完再统一触发。此时用pause/resume# 1) 查看历史[rootmaster controler]# kubectl rollout history deployment webclusterREVISION CHANGE-CAUSE7none8none# 2) 暂停更新[rootmaster controler]# kubectl rollout pause deployment webclusterdeployment.apps/webcluster paused# 3) 改 yaml、apply但不会被触发[rootmaster controler]# vim dep.yml# ... image 改为 myapp:v2[rootmaster controler]# kubectl apply -f dep.ymldeployment.apps/webcluster configured# 4) 此时再查 historyREVISION 仍然不变[rootmaster controler]# kubectl rollout history deployment webclusterREVISION CHANGE-CAUSE7none8none# 5) 恢复更新[rootmaster controler]# kubectl rollout resume deployment webclusterdeployment.apps/webcluster resumed# 6) 重新查看 history已生成新版本 9[rootmaster controler]# kubectl rollout history deployment webclusterREVISION CHANGE-CAUSE8none9none实际技巧暂停时kubectl scale改副本数是允许的不触发滚动但改 image / 资源 / env 会等到 resume 后才一次性生效。五、DaemonSet 控制器5.1 功能与典型用途DaemonSet 确保全部或某些节点上运行一个 Pod 的副本节点加入集群 → 自动在该节点上新增一个 Pod节点移除集群 → 该节点上的 Pod 被自动回收删除 DaemonSet → 它创建的所有 Pod 全部删除。典型用途都是“节点级”守护进程存储glusterd、ceph日志收集fluentd、logstash监控Prometheus Node Exporter、zabbix agent简单用法所有节点启动同一个 DaemonSet进阶用法按硬件类型用不同 DaemonSet不同 CPU/内存/标志。5.2 实验建立 DaemonSet 新节点加入自动扩容# 1) 生成 yaml[rootmaster controler]# kubectl create deployment daemonset --image myapp:v1 \--dry-runclient-oyamldaemonset.yml[rootmaster controler]# vim daemonset.ymlapiVersion: apps/v1 kind: DaemonSet metadata: labels: app: daemonset name: daemonset spec: selector: matchLabels: app: daemonset template: metadata: labels: app: daemonset spec: containers: - image: myapp:v1 name: myapp[rootmaster controler]# kubectl apply -f daemonset.ymldaemonset.apps/daemonset created# 2) 验证每个 node 都有一个 Pod[rootmaster ~]# kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE daemonset-87h6s1/1 Running047s10.244.0.8 k8s-master daemonset-n4vs41/1 Running047s10.244.2.38 k8s-node2 daemonset-vhxmq1/1 Running047s10.244.1.40 k8s-node1新节点加入自动扩容开一台 node3# master 重新生成 token[rootmaster controler]# kubeadm token create --print-join-commandkubeadmjoin172.25.254.100:6443\--tokenlqcz14.6f4krq91w75h58bt\--discovery-token-ca-cert-hash sha256:6b5950ef2cdba85d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927# node3 上执行[rootnode3 ~]# kubeadm join 172.25.254.100:6443 \--tokenlqcz14.6f4krq91w75h58bt\--discovery-token-ca-cert-hash sha256:6b5950ef2cdba85d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927\--cri-socket unix:///var/run/cri-dockerd.sock# 在 master 上观察node3 上会自动起一个 DaemonSet Pod[rootmaster ~]# kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE daemonset-87h6s1/1 Running01m10.244.0.8 k8s-master daemonset-n4vs41/1 Running01m10.244.2.38 k8s-node2 daemonset-vhxmq1/1 Running01m10.244.1.40 k8s-node1 daemonset-xxxxxx1/1 Running05s10.244.3.x k8s-node3# 新增的# 回收[rootmaster controler]# kubectl delete -f daemonset.yml实战建议日志/监控/网络插件如 Calico、Flannel通常就是用 DaemonSet 在每个节点上跑一个 Pod。六、Job 控制器6.1 功能Job负责**批处理一次要处理指定数量的任务且短暂一次性每个任务仅运行一次就结束**的任务。特点当 Pod 执行成功结束时Job记录成功结束的 Pod 数量当成功 Pod 达到spec.completions指定的数量时Job 标记为完成。重启策略restartPolicy策略Pod 出错时failed 计数Never创建新 Pod原 Pod 留着不重启1OnFailure重启容器而不是创建 Pod不变Always一直重启不推荐—6.2 实验并行计算 π / busybox 一次性任务实验 A用 perl 计算 π 的 2000 位completions: 6parallelism: 2# 0) 如果使用私有仓库先 load push 镜像[rootmaster ~]# docker load -i perl-5.34.tar.gz[rootmaster ~]# docker tag perl:5.34.0 reg.timinglee.org/library/perl:5.34.0[rootmaster ~]# docker login reg.timinglee.org -u admin[rootmaster ~]# docker push reg.timinglee.org/library/perl:5.34.0# 1) 生成 yaml[rootmaster controler]# kubectl create job job --image perl:5.34.0 \--dry-runclient-oyamljob.yml[rootmaster controler]# vim job.ymlapiVersion: batch/v1 kind: Job metadata: name: job spec: completions:6# 一共完成 6 个任务parallelism:2# 每次并行 2 个template: spec: containers: - image: perl:5.34.0 name: job command:[perl,-Mbignumbpi,-wle,print bpi(2000)]restartPolicy: Never backoffLimit:4# 失败重试 4 次[rootmaster controler]# kubectl apply -f job.ymljob.batch/job created# 2) 查看输出计算 π 后 2000 位[rootmaster controler]# kubectl logs job-4b45g3.14159265358979323846264338327950288419716939937510...实验 Bbusybox 跑一次性脚本[rootmaster controler]# vim job.ymlapiVersion: batch/v1 kind: Job metadata: name: testjob spec: completions:6parallelism:2backoffLimit:4template: spec: containers: - image: busybox name: testjob command:[/bin/sh,-c]args: -|echothis is testjob messagesleep10restartPolicy: Never[rootmaster controler]# kubectl apply -f job.yml[rootk8s-master controller]# kubectl logs pods/testjob-4cdlrthis is testjob message实际意义可用来做数据迁移、批量脚本、定期清理、定时备份等一次性任务。七、CronJob 控制器7.1 功能CronJob创建基于时间调度的 Job。它以 Job 为管控对象借助 Job 管理 Pod。简单理解CronJob 决定“什么时候跑”Job 决定“跑什么、跑完即停”。schedule字段标准的 5 段 crontab 表达式分 时 日 月 周。表达式含义* * * * *每分钟0 2 * * *每天凌晨 2 点*/5 * * * *每 5 分钟0 0 * * 0每周日 0 点7.2 实验每分钟输出 hello# 1) 生成 yaml[rootmaster controler]# kubectl create cronjob cronjob --image busybox \--schedule* * * * *--dry-runclient-oyamlcronjob.yml[rootmaster controler]# vim cronjob.ymlapiVersion: batch/v1 kind: CronJob metadata: name: cronjob spec: jobTemplate: metadata: name: cronjob spec: template: spec: containers: - image: busybox name: cronjob command: - /bin/sh --c-echohello timingleerestartPolicy: OnFailure schedule:* * * * *[rootmaster controler]# kubectl apply -f cronjob.yml # 整分时运行[rootmaster controler]# kubectl get cronjobs.batchNAME SCHEDULE TIMEZONE SUSPEND ACTIVE LAST SCHEDULE AGE cronjob * * * * *noneFalse017s 70s# 2) 等待一分钟后查看 Pod 日志[rootmaster controler]# kubectl logs cronjob-29598241-pxgghhello timinglee实际用途日志归档、数据库备份、缓存刷新、证书续期等周期性任务。