K8S控制器全解-从RS到DaemonSet实战完全指南
K8S控制器全解从RS到DaemonSet掌握五大控制器的核心原理与实战导读在 Kubernetes 中你几乎不会直接创建 Pod——而是通过控制器Controller来管理 Pod 的生命周期。控制器是 K8S 实现声明式 API 和自愈能力的核心机制。本文将从 ReplicaSet 到 DaemonSet逐一拆解五大控制器的工作原理、标签选择器机制、升级策略并通过完整实战帮你建立系统性的控制器知识体系。最后附上面试高频题“如何通过 Pod 反向查找控制器”。一、为什么需要控制器在 K8S 中直接创建的 Pod 是裸奔的——节点故障 Pod 不会自动迁移进程崩溃不会自动恢复应用更新无法平滑过渡。控制器就是来解决这些问题的┌──────────────────────────────────────────────────────────┐ │ K8S 控制器核心能力 │ ├──────────────┬───────────────────────────────────────────┤ │ 自愈能力 │ Pod 挂了自动重建节点宕机自动迁移 │ │ 弹性伸缩 │ 自动维持期望的 Pod 副本数量 │ │ 滚动更新 │ 零停机升级应用版本 │ │ 版本回滚 │ 更新出问题可以快速回退到上一个版本 │ │ 声明式管理 │ 只需声明期望状态控制器自动调和差异 │ └──────────────┴───────────────────────────────────────────┘控制器的核心工作原理控制循环Reconciliation Loop期望状态Desired State 实际状态Current State ┌──────────────────┐ ┌──────────────────┐ │ replicas: 3 │ │ running pods: 2 │ │ image: nginx:v2 │ │ image: nginx:v1 │ └────────┬─────────┘ └────────┬─────────┘ │ │ └───────────┬───────────────┘ ▼ ┌─────────────────┐ │ 控制循环比较差异 │ │ (Reconcile) │ └────────┬────────┘ ▼ ┌─────────────────┐ │ 执行调和动作 │ │ 创建/删除/更新Pod│ └─────────────────┘二、K8S 控制器全景图┌─────────────────────────────────────────────────────────┐ │ K8S 工作负载控制器 │ ├──────────────────┬──────────────────────────────────────┤ │ Deployment │ 无状态应用Web服务、API │ │ ├─ ReplicaSet │ 副本管理底层控制器 │ │ └─ Pod │ │ ├──────────────────┼──────────────────────────────────────┤ │ DaemonSet │ 每个节点一个Pod监控、日志采集 │ ├──────────────────┼──────────────────────────────────────┤ │ Job │ 一次性任务数据库备份、数据迁移 │ │ └─ CronJob │ 定时任务增量备份、日志清理 │ ├──────────────────┼──────────────────────────────────────┤ │ StatefulSet │ 有状态应用数据库、消息队列 │ ├──────────────────┼──────────────────────────────────────┤ │ HPA/VPA │ 自动伸缩动态调整副本/资源 │ └──────────────────┴──────────────────────────────────────┘控制器选型决策表场景推荐控制器原因Web 服务、APIDeployment支持滚动更新、回滚、弹性伸缩监控 Agent、日志采集DaemonSet每个节点一个 Pod自动跟随节点数据库全量备份Job一次性任务执行完成即终止定时清理日志CronJob周期性执行类似 Linux crontabMySQL、Redis 集群StatefulSet需要稳定的网络标识和存储批处理任务Job parallelism并行处理多个任务三、ReplicaSet副本管理的基石3.1 RS 与 RC 的关系ReplicaSetRS是 ReplicationControllerRC的升级版官方已废弃 RC。两者的核心区别在于标签选择器的能力特性RCRS等值选择支持支持matchLabels集合选择不支持支持matchExpressions当前状态已废弃推荐使用但通常被 Deployment 管理生产提示虽然 RS 功能更强大但在实际工作中几乎不会直接创建 RS——而是通过 Deployment 间接管理。Deployment 是对 RS 的上层封装增加了声明式更新和版本管理能力。3.2 RS 基础实战matchLabels# rs.yamlapiVersion:apps/v1kind:ReplicaSetmetadata:name:rsspec:replicas:3# 期望副本数selector:matchLabels:# 等值匹配标签必须完全一致apps:lingxitemplate:# Pod 模板metadata:labels:apps:lingxiversion:v1spec:containers:-name:c1image:nginx:1.20kubectl apply-frs.yaml# 查看 RS 和 PodPod 名称自动带上 RS 名称前缀kubectl get rs,pods-owide# NAME DESIRED CURRENT READY# replicaset.apps/rs 3 3 3## NAME READY STATUS IP NODE# pod/rs-xxx 1/1 Running 10.100.2.103 worker233# pod/rs-xxx 1/1 Running 10.100.1.124 worker232# pod/rs-xxx 1/1 Running 10.100.2.104 worker233验证自愈能力删除所有 PodRS 会自动重建kubectl delete pods-lappslingxi# pod rs-xxx deleted (x3)kubectl get pods-owide# NAME READY STATUS AGE IP NODE# pod/rs-new 1/1 Running 4s 10.100.1.125 worker232# pod/rs-new 1/1 Running 4s 10.100.2.105 worker233# pod/rs-new 1/1 Running 4s 10.100.1.126 worker2323.3 RS 进阶matchExpressions 集合选择matchExpressions支持四种操作符能力远超 RC 的等值匹配# rs-matchExpressions.yamlapiVersion:apps/v1kind:ReplicaSetmetadata:name:rs-match-expressionsspec:replicas:5selector:matchExpressions:# 集合选择器-key:versionvalues:-v1-v2-v3operator:In# version 的值在 [v1,v2,v3] 中template:metadata:labels:apps:lingxiversion:v1spec:containers:-name:c1image:nginx:1.20四种操作符操作符说明示例Inkey 的值在 values 列表中version In [v1, v2, v3]NotInkey 的值不在 values 列表中env NotIn [prod]Existskey 存在即可忽略 valuesversion ExistsDoesNotExistkey 不存在debug DoesNotExist关键行为RS 的matchExpressions会同时管理已存在的匹配 Pod。例如集群中已有标签versionv1的独立 Pod创建 RS 后这些 Pod 也会被纳入管理。删除 RS 后被纳入管理的 Pod 也会被一并删除。四、Deployment无状态应用的最佳拍档4.1 Deployment 与 RS 的关系Deployment 是对 RS 的上层封装核心价值在于声明式更新和版本管理┌──────────────┐ 管理 ┌──────────────────┐ 管理 ┌─────┐ │ Deployment │ ──────────→ │ ReplicaSet (v1) │ ──────────→ │ Pod │ │ │ │ ReplicaSet (v2) │ ──────────→ │ Pod │ │ │ │ ReplicaSet (v3) │ ──────────→ │ Pod │ └──────────────┘ └──────────────────┘ └─────┘ 版本管理 历史版本保留 实例 滚动更新 每次更新创建新RS 运行中 回滚能力 旧RS保留用于回滚核心机制每次更新 Deployment 的 Pod 模板如修改镜像版本会创建一个新的 RS逐步将流量从旧 RS 的 Pod 切换到新 RS 的 Pod。旧 RS 默认保留支持快速回滚。4.2 Deployment 基础实战# deploy.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:deployspec:replicas:3selector:matchLabels:apps:lingxitemplate:metadata:labels:apps:lingxiversion:v1spec:containers:-name:c1image:registry.cn-hangzhou.aliyuncs.com/eci_open/nginx:latestkubectl apply-fdeploy.yaml# 查看 Deployment、RS、Pod 的层级关系kubectl get deploy,rs,po --show-labels# deployment.apps/deploy 3/3 3 3 13s## replicaset.apps/deploy-568cf47956 3 3 3# 标签: appslingxi,pod-template-hash568cf47956,versionv1## pod/deploy-568cf47956-hwglc 1/1 Running# 标签: appslingxi,pod-template-hash568cf47956,versionv1关键标签pod-template-hash是 K8S 自动添加的标签值由 Pod 模板内容哈希生成。相同模板的 Pod 拥有相同的 hash用于 RS 精确匹配自己的 Pod。4.3 滚动更新RollingUpdate更新 Deployment 的镜像版本观察滚动更新过程# 修改 image: apps:v2 → apps:v3spec:containers:-name:c1image:registry.openanolis.cn/openanolis/nginx:1.14.1-8.6kubectl apply-fdeploy-update.yaml# 观察更新过程新RS创建旧RS缩容kubectl get deploy,rs,po-owide# deployment.apps/deploy 5/5 5 5## replicaset.apps/deploy-5f77fddbd7 0/0/0 ← 旧RS(v2)Pod已清空# replicaset.apps/deploy-78ddbbdbfb 5/5/5 ← 新RS(v3)Pod已就绪4.4 升级策略详解Deployment 支持两种升级策略spec:strategy:type:RollingUpdate# 默认策略rollingUpdate:maxSurge:2# 滚动更新时最多允许超出期望副本数2个maxUnavailable:1# 滚动更新时最多允许1个Pod不可用参数RecreateRollingUpdate更新方式先删全部旧Pod再创建新Pod逐步替换新旧Pod共存停机时间有删除到创建的间隔无始终有Pod在运行资源开销低同一时刻只有一套Pod高新旧Pod共存需要maxSurge资源回滚速度慢需要重新创建全部Pod快旧RS还在直接扩容适用场景不兼容的多版本更新绝大多数场景推荐maxSurge 和 maxUnavailable 的计算规则场景replicas5, maxSurge25%(默认)replicas5, maxSurge2更新时最多Pod数ceil(5 * 1.25) 75 2 7场景replicas1, maxUnavailable25%(默认)replicas1, maxUnavailable1更新时最少可用Podfloor(1 * 0.75) 01 - 1 0生产建议设置maxUnavailable: 0零停机配合maxSurge: 25%确保更新过程中始终有足够的 Pod 处理流量。4.5 版本回滚# 查看更新历史kubectl rollouthistorydeployment deploy# 回滚到上一个版本kubectl rollout undo deployment deploy# 回滚到指定版本kubectl rollout undo deployment deploy --to-revision2# 查看回滚状态kubectl rollout status deployment deploy五、Job一次性任务的执行器5.1 Job 控制器概述Job 用于运行一次性任务任务执行完成后 Pod 自动终止。典型的应用场景数据库全量备份数据迁移批量邮件发送CI/CD 流水线中的构建任务大数据处理任务5.2 Job 实战Python 脚本执行# job-python.yamlapiVersion:batch/v1kind:Jobmetadata:name:jobs-pyspec:template:spec:containers:-name:pyimage:python:3.9.16-alpine3.16command:-python3--c-print(https://www.baidu.com/)restartPolicy:Never# Job 只能是 Never 或 OnFailurebackoffLimit:4# 失败重试次数创建新Pod重试kubectl apply-fjob-python.yaml# 查看执行状态kubectl get jobs,pods-owide# NAME COMPLETIONS DURATION AGE# job.batch/jobs-py 1/1 4s 6s## NAME READY STATUS RESTARTS AGE# pod/jobs-py-xxx 0/1 Completed 0 6s# 查看执行日志kubectl logs jobs-py-965q55.3 Job 关键参数参数说明默认值backoffLimit失败重试次数创建新 Pod 重试6completions需要成功完成的 Pod 数1parallelism并行运行的 Pod 数1activeDeadlineSecondsJob 超时时间超时自动标记失败无限制ttlSecondsAfterFinished完成后自动清理的延迟时间永不清理restartPolicy重启策略只能是 Never 或 OnFailureNever5.4 Job 的 restartPolicy 详解策略行为适用场景Never失败后创建新 Pod 重试Pod 数量会增加大多数场景推荐OnFailure失败后在同一个 Pod 内重启容器需要保留容器状态关键区别Never会创建新的 Pod 来重试每次重试都是干净的环境OnFailure在同一 Pod 内重启容器可能残留上次的状态。六、CronJob定时任务的调度器6.1 CronJob 概述CronJob 基于 Job 控制器按Cron 表达式定期创建 Job。它不直接管理 Pod而是周期性地调用 Job 控制器。CronJob ──(按Cron触发)──→ Job ──(创建)──→ Pod 定时调度 任务管理 执行典型应用场景数据库增量备份每天凌晨2点证书续期检查每周一日志清理每天数据报表生成每月1号6.2 CronJob 实战# cronjob-demo.yamlapiVersion:batch/v1kind:CronJobmetadata:name:cj-hellospec:schedule:* * * * *# Cron 表达式每分钟执行jobTemplate:spec:template:spec:volumes:-name:dthostPath:path:/etc/localtime# 同步宿主机时区containers:-name:helloimage:busybox:1.28volumeMounts:-name:dtmountPath:/etc/localtimecommand:-/bin/sh--c-date-R; echo Hello from the Kubernetes clusterrestartPolicy:OnFailurekubectl apply-fcronjob-demo.yaml# 等待几分钟后查看每分钟创建一个Job每个Job创建一个Podkubectl get cj,jobs,pods-owide# NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE# cronjob.batch/cj-hello * * * * * False 0 22s## NAME COMPLETIONS DURATION AGE# job.batch/cj-hello-29413519 1/1 3s 2m22s# job.batch/cj-hello-29413520 1/1 3s 82s# job.batch/cj-hello-29413521 1/1 3s 22s## pod/cj-hello-29413519-xxx Completed# pod/cj-hello-29413520-xxx Completed# pod/cj-hello-29413521-xxx Completed6.3 Cron 表达式格式┌─── 分钟 (0 - 59) │ ┌─── 小时 (0 - 23) │ │ ┌─── 日 (1 - 31) │ │ │ ┌─── 月 (1 - 12) │ │ │ │ ┌─── 星期 (0 - 6, 0周日) │ │ │ │ │ * * * * *常用表达式速查表达式含义*/5 * * * *每 5 分钟0 2 * * *每天凌晨 2 点0 2 * * 1每周一凌晨 2 点0 0 1 * *每月 1 号零点0 9-18 * * 1-5工作日 9~18 点每小时30 2 1,15 * *每月 1 号和 15 号凌晨 2:306.4 CronJob 历史记录管理spec:successfulJobsHistoryLimit:3# 保留最近3个成功的JobfailedJobsHistoryLimit:1# 保留最近1个失败的JobconcurrencyPolicy:Forbid# 禁止并发上一个未完成时不创建新的# concurrencyPolicy: Allow # 允许并发默认# concurrencyPolicy: Replace # 替换取消上一个创建新的startingDeadlineSeconds:200# 错过调度后的宽容时间秒suspend:false# 暂停调度true暂停七、DaemonSet每个节点的守护进程7.1 DaemonSet 概述DaemonSetDS确保每个或特定节点上运行一个 Pod 副本。当节点加入集群时自动创建 Pod节点移除时自动回收 Pod。┌─────────────────────────────────────────┐ │ DaemonSet: node-exporter │ │ │ │ ┌──────────┐ ┌──────────┐ ┌────────┐│ │ │ Worker-1 │ │ Worker-2 │ │ Worker-3││ │ │ [Pod-1] │ │ [Pod-2] │ │ [Pod-3] ││ │ └──────────┘ └──────────┘ └────────┘│ │ │ │ 每个节点有且仅有一个 Pod │ │ 新节点加入 → 自动创建 Pod │ │ 节点移除 → 自动回收 Pod │ └─────────────────────────────────────────┘典型应用场景监控采集Prometheus Node Exporter、Zabbix Agent日志采集Fluentd、Filebeat、Flume网络插件Calico、FlannelCNI 组件本身就是 DaemonSet存储插件Ceph OSDRook 部署的 Ceph 使用 DaemonSet7.2 DaemonSet 实战# ds.yamlapiVersion:apps/v1kind:DaemonSetmetadata:name:dsspec:selector:matchLabels:apps:lingxitemplate:metadata:labels:apps:lingxispec:volumes:-name:dthostPath:path:/etc/localtimecontainers:-name:c1image:nginx:1.20volumeMounts:-name:dtmountPath:/etc/localtimekubectl apply-fds.yaml# 每个 Worker 节点上创建一个 Podkubectl get pods-owide# NAME READY STATUS IP NODE# ds-hgqt4 1/1 Running 10.100.2.203 worker233# ds-lrf5x 1/1 Running 10.100.1.213 worker232# 注意Master 节点默认不调度因为有污点kubectl get nodes# NAME STATUS ROLES ...# master231 Ready control-plane,master ← 有污点DS Pod 不会调度到此# worker232 Ready none# worker233 Ready none污点与 DaemonSet如果需要在有污点的节点如 Master上也运行 DaemonSet Pod需要在 Pod 模板中配置tolerations。这是 DaemonSet 与 Deployment 的一个重要区别——DaemonSet 的调度需求更强经常需要容忍污点。7.3 DaemonSet 更新策略spec:updateStrategy:type:RollingUpdate# 默认逐个节点滚动更新rollingUpdate:maxUnavailable:1# 最多1个Pod不可用# type: OnDelete # 手动模式删除旧Pod后才创建新Pod策略行为适用场景RollingUpdate默认自动逐个替换 Pod常规更新OnDelete只有手动删除旧 Pod 后才创建新的精确控制更新节奏八、面试实战通过 Pod 反向查找控制器这是一个经典面试题“给你一台服务器Pod 处于 Pending 状态如何排查并修复”8.1 核心思路Pod 的配置问题不能直接修改 Pod 本身控制器会自动回滚必须找到管理该 Pod 的控制器并修改控制器。8.2 操作步骤# 第1步使用 describe 查看 Pod 的事件kubectl describe podpod-name# 第2步查看 Controlled By 字段找到控制器kubectl describe pod ds-qxww6# ...# Controlled By: DaemonSet/ds ← 被DaemonSet管理8.3 三层控制器链路Pod (被 RS 管理) └── Controlled By: ReplicaSet/deploy-568cf47956 └── Controlled By: Deployment/deploy ← 最终需要修改这个不同控制器的 Controlled By控制器Pod 的 Controlled By下一步操作DeploymentReplicaSet/xxx再describe rs找到 DeploymentDaemonSetDaemonSet/xxx直接edit dsJobJob/xxx直接edit jobCronJobJob/xxx找到 Job 后编辑 CronJobStatefulSetStatefulSet/xxx直接edit sts# Deployment 需要两层查找kubectl describe pod deploy-568cf47956-92chs# Controlled By: ReplicaSet/deploy-568cf47956kubectl describe rs deploy-568cf47956# Controlled By: Deployment/deploy# 最终修改 Deploymentkubectl edit deploy deploy8.4 Pod Pending 的六种常见原因原因排查方法修复方式镜像拉取失败Events:Failed to pull image修改控制器的 image节点资源不足Events:Insufficient cpu/memory添加节点或降低 requests亲和性不满足Events:didnt match Pods node affinity修改 nodeAffinity 配置存储卷未就绪Events:persistentvolumeclaim not found创建 PVC 或绑定 PV污点不容忍Events:had taint that pod didnt tolerate配置 tolerationsnodeName 不存在Events:node not found修改 nodeName 或确认节点存在九、控制器对比总结维度DeploymentDaemonSetJobCronJobPod 数量可指定 replicas每个节点 1 个指定 completions由 Job 决定生命周期持续运行持续运行完成后终止周期性完成更新方式滚动更新/重建滚动更新/OnDeleteN/AN/A回滚支持不支持不支持不支持自愈Pod 挂了重建Pod 挂了重建失败重试失败重试restartPolicyAlwaysAlwaysNever/OnFailureNever/OnFailure典型场景Web 服务监控/日志/网络备份/迁移定时任务