← 返回 Kubernetes图解 目录

🚀 K8s部署与调度图解

Deployment滚动更新 + Scheduler调度算法 + HPA水平自动伸缩 + Pod生命周期 · SVG可视化

① Deployment滚动更新

Deployment滚动更新就像老员工培训新员工——不能一次性把老员工全换掉(服务会中断),而是:先招1个新人(新Pod),等新人上手了(Ready),再让1个老人离职(旧Pod删除)。整个过程保证始终有足够的人在岗,用户感知不到切换。
maxSurge = 最多同时多招几个人(超出目标的临时扩编)
maxUnavailable = 最多同时少几个人(允许的在岗缺口)
Deployment 滚动更新流程 Step 1: 初始状态 Pod-v1 🟢 Pod-v1 🟢 Pod-v1 🟢 replicas: 3 image: v1 Step 2: 新Pod创建 Pod-v1 🟢 Pod-v1 🟢 Pod-v1 🟢 Pod-v2 🟡 maxSurge=1 新Pod启动中 Step 3: 旧Pod删除 Pod-v1 🟢 Pod-v1 🔴 Pod-v1 🟢 Pod-v2 🟢 maxUnavail=1 Step 4: 更新完成 Pod-v2 🟢 Pod-v2 🟢 Pod-v2 🟢 全部完成 ✅ 滚动更新策略 maxSurge: 1 最多多1个Pod maxUnavailable: 1 最多少1个Pod minReadySeconds: 30 revisionHistoryLimit: 10 progressDeadlineSeconds: 600
滚动更新:先创建新Pod(maxSurge)→再删除旧Pod(maxUnavailable)→循环直至全部更新

更新策略对比

策略类比行为适用场景
RollingUpdate老员工培训新员工逐步替换,先增后删,零停机Web服务、API(默认策略)
Recreate全部换血先删所有旧Pod,再创建新Pod不能同时运行两个版本(如数据库迁移)
kubectl rollout undo deployment/my-app 可以回滚到上一版本!K8s为每个Deployment保留历史修订(revisionHistoryLimit),回滚就是切换到旧ReplicaSet。

② Scheduler调度算法

Scheduler就像面试筛选——一个岗位(Pod)投递到公司(K8s集群),HR(Scheduler)要在所有部门(Node)里找到最合适的安排:
预选(Predicates) = 硬性条件过滤——学历不够、专业不对的简历直接筛掉(资源不足、不满足亲和性、有污点不容忍)
优选(Priorities) = 综合打分排名——通过硬性条件的候选人,按多维度打分(资源均衡、亲和性、反亲和性),得分最高的入选
Scheduler 两阶段调度算法 待调度 Pod cpu:2, mem:4Gi, zone=east 🔍 预选阶段 (Predicates) 硬性条件:不满足就淘汰 ✗ Node3: CPU不足 ✗ Node5: 污点不容忍 ✓ Node1: 资源充足 ✓ Node2: 满足亲和性 ✓ Node4: 匹配标签 📊 优选阶段 (Priorities) 综合打分:分数最高者胜出 Node1: 65分 Node2: 92分 ⭐ Node4: 48分 打分维度: 资源均衡/亲和性/Pod拓扑/镜像本地 ✅ Pod 调度到 Node2(得分最高: 92分) 满足zone=east亲和性 + 资源最均衡 亲和性 (Affinity) nodeAffinity: Pod倾向去哪些Node podAffinity: Pod倾向和哪些Pod在一起 污点与容忍 (Taint & Toleration) Taint: Node上的"谢绝来访"标签 Toleration: Pod的"通行证",能通过污点
Scheduler两阶段调度:预选筛掉不满足硬性条件的Node→优选对候选Node打分→最高分胜出
deployment.yaml — 滚动更新配置
📁 k8s/
pod.yaml
deployment.yaml
hpa.yaml
📁 scheduling/
affinity.yaml
taint.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: my-app labels: app: my-app spec: replicas: 3 selector: matchLabels: app: my-app strategy: # ← 滚动更新策略 type: RollingUpdate rollingUpdate: maxSurge: 1 # ← 最多多1个Pod(25%) maxUnavailable: 1 # ← 最多少1个Pod(25%) template: metadata: labels: app: my-app spec: affinity: # ← 调度亲和性 nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: zone operator: In values: [east] containers: - name: app image: my-app:v2.0 ports: - containerPort: 8080 resources: requests: cpu: "200m" memory: "256Mi" limits: cpu: "1" memory: "512Mi" tolerations: # ← 污点容忍 - key: dedicated operator: Equal value: gpu effect: NoSchedule

③ HPA水平自动伸缩

HPA就像弹性办公位——公司大厅有一排可伸缩的工位。忙时(流量高/CPU高)自动增加工位(扩容Pod),闲时(流量低/CPU低)自动收回工位(缩容Pod)。不需要你手动操作,HR(HPA Controller)看着"忙碌程度"(指标)自动调节。
CPU利用率 = 工位忙碌程度(超过阈值→加人)
冷却时间 = 别刚加人就减(等5分钟再决定)
minReplicas/maxReplicas = 最少/最多工位数
HPA 水平自动伸缩流程 Metrics Server 采集CPU/Memory 自定义指标 HPA Controller 当前CPU: 75% 目标CPU: 50% → 需要扩容! 扩容计算 desiredReplicas = ceil(3 × 75%/50%) = ceil(4.5) = 5个Pod 扩容前: 3个Pod Pod1 75% Pod2 78% Pod3 72% 🔥 CPU高 扩容后: 5个Pod Pod1 45% Pod2 48% Pod3 42% Pod4 ✨ Pod5 ✨ ✅ CPU降至目标以下 HPA 关键参数 minReplicas: 2 最少Pod数 maxReplicas: 10 最多Pod数 cooldown: 5m 冷却时间 扩容: 立即响应 | 缩容: 需等冷却期(默认5分钟) | 稳定窗口: 防止抖动
HPA工作流:Metrics Server采集指标→HPA Controller对比目标值→计算desiredReplicas→自动扩缩容
hpa.yaml — 水平自动伸缩配置
📁 k8s/
deployment.yaml
hpa.yaml
📁 monitoring/
prometheus.yaml
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: my-app-hpa spec: scaleTargetRef: # ← 伸缩目标 apiVersion: apps/v1 kind: Deployment name: my-app minReplicas: 2 # ← 最少2个Pod maxReplicas: 10 # ← 最多10个Pod metrics: # ← 伸缩指标 - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 # ← CPU目标50% - type: Resource resource: name: memory target: type: Utilization averageUtilization: 70 # ← 内存目标70% behavior: # ← 伸缩行为控制 scaleDown: stabilizationWindowSeconds: 300 # 缩容冷却5分钟 policies: - type: Percent value: 10 # 每次最多缩10% periodSeconds: 60 scaleUp: policies: - type: Percent value: 100 # 每次最多翻倍 periodSeconds: 60

④ Pod生命周期

Pod的生命周期就像入职→在岗→离职的过程:
Pending = 已发Offer,还没到岗(等待调度/拉取镜像)
Running = 正式在岗工作(ContainerCreating→Running)
Succeeded = 合同到期,正常离职(Job完成)
Failed = 异常离职(崩溃、OOM、健康检查失败)
Unknown = 失联(Node和网络断了,kubelet无法上报状态)
此外还有3种探针做"健康体检":Startup(入职体检)、Liveness(日常体检)、Readiness(能否接活)
Pod 生命周期与探针 Pending 等待调度/拉镜像 ContainerCreating 创建容器中 Running 正常运行中 Succeeded Failed Unknown Node失联 🩺 Startup Probe 入职体检 判断容器是否已启动 失败→重启容器 成功→才开启其他探针 适合慢启动应用 💓 Liveness Probe 日常体检 判断容器是否还活着 失败→重启容器(restart) 死锁/僵死→被检测到 注意: 不要检查外部依赖! 🎯 Readiness Probe 能否接活 判断容器是否准备好服务 失败→从Service摘除 不重启,只断流量 保证新Pod Ready才接流量 重启策略 (restartPolicy) Always (默认) → 容器挂了就重启 OnFailure → 只有失败才重启 Never → 从不重启(Job用) 优雅终止 (Graceful Shutdown) 1. Pod收到SIGTERM信号 2. 应用处理完请求后退出 3. 超时(默认30s)→SIGKILL强制杀 preStop hook: 在SIGTERM前执行清理
Pod生命周期:Pending→Running→Succeeded/Failed + 3种探针(Startup/Liveness/Readiness)保障健康

3种探针对比

探针类比失败后果检测方式适用场景
Startup入职体检重启容器HTTP/TCP/Exec慢启动应用(JVM预热)
Liveness日常体检重启容器HTTP/TCP/Exec检测死锁/僵死
Readiness能否接活从Service摘除HTTP/TCP/Exec保证新Pod就绪

⑤ 面试速答

Deployment滚动更新的原理?maxSurge和maxUnavailable怎么配?

Deployment通过ReplicaSet管理Pod。更新image时,创建新ReplicaSet(v2),按RollingUpdate策略逐步增加新Pod、减少旧Pod。
maxSurge:超出期望 replicas 的最大 Pod 数(默认25%)。值越大,更新越快但消耗资源越多。
maxUnavailable:更新期间允许不可用的最大 Pod 数(默认25%)。值越大更新越快但可用性越低。
极端配置:maxSurge=0,maxUnavailable=100% → Recreate策略(先全删再全建)。maxSurge=100%,maxUnavailable=0 → 蓝绿部署效果。

Scheduler的调度流程?预选和优选分别做什么?

预选(Predicates):硬性过滤,排除不满足条件的Node。包括:PodFitsResources(资源够不够)、PodFitsHostPorts(端口冲不冲突)、PodMatchNodeSelector(标签匹不匹配)、CheckNodeUnschedulable(是否可调度)、TaintToleration(污点容忍)。
优选(Priorities):对通过预选的Node打分排名。包括:SelectorSpreadPriority(Pod分散)、InterPodAffinityPriority(Pod亲和)、LeastRequestedPriority(资源均衡)、NodeAffinityPriority(Node亲和)、ImageLocalityPriority(镜像本地)。
最终选择得分最高的Node绑定Pod。

HPA的扩缩容算法是什么?为什么缩容有冷却时间?

扩容公式:desiredReplicas = ceil(currentReplicas × currentMetricValue / desiredMetricValue)
例如:3个Pod,CPU当前75%,目标50% → ceil(3 × 75/50) = ceil(4.5) = 5个Pod。
缩容有冷却时间(默认5分钟),防止"抖动"——流量短暂下降就缩容,流量回来又要扩容,反复折腾。冷却期内即使指标低于阈值也不缩容。

Pod的3种探针分别用在什么场景?

Startup Probe:判断容器是否启动完成。用于慢启动应用(如JVM需要预热),在Startup Probe成功前不会执行Liveness和Readiness。
Liveness Probe:判断容器是否还活着。失败→重启容器。用于检测死锁、僵死。注意:不要检查外部依赖(DB/Redis),否则外部挂了会反复重启容器。
Readiness Probe:判断容器是否准备好接收流量。失败→从Service的Endpoints摘除,不重启。用于滚动更新时保证新Pod就绪后才接流量。

Node亲和性和Pod亲和性有什么区别?

nodeAffinity:Pod对Node的偏好——"我想去哪个Node"。基于Node的Label选择,如zone=east、gpu=true。
podAffinity:Pod对Pod的偏好——"我想和谁在同一个Node"。如前端Pod和后端Pod放在一起降低延迟。
podAntiAffinity:Pod对Pod的反感——"我不想和谁在同一个Node"。如同一Deployment的Pod分散到不同Node,避免单点故障。
每种都分required(硬性)和preferred(软性)两种约束。

Taint和Toleration怎么工作?

Taint打在Node上,标记"这个Node有特殊属性"。格式:key=value:effect。
Toleration写在Pod上,声明"我能容忍这个Taint"。
3种effect:
NoSchedule:只影响调度,已运行的Pod不驱逐
PreferNoSchedule:尽量不调度,但不保证
NoExecute:不调度+驱逐已有Pod
典型用法:Master节点打Taint node-role.kubernetes.io/master:NoSchedule,防止普通Pod调度到Master。

Pod的restartPolicy有哪些?分别用在什么场景?

Always(默认):容器退出就重启。Deployment/StatefulSet/DaemonSet都用Always。
OnFailure:只有失败(非0退出码)才重启。Job用OnFailure,成功的Pod不需要重启。
Never:从不重启。某些Job用Never,失败后由Job Controller重新创建Pod。
注意:restartPolicy作用于Pod内的所有容器。重启次数有限制(Back-off: 10s→20s→40s→...最长5min)。

如何实现零停机部署?

零停机部署需要3个条件:
1. Readiness Probe:新Pod只有通过Readiness检查才加入Service Endpoints,确保不会把流量打到未就绪的Pod。
2. preStop Hook:Pod终止前先从Service Endpoints摘除,等待已有请求处理完(graceful shutdown)。设置 terminationGracePeriodSeconds: 30
3. 滚动更新策略:maxSurge≥1, maxUnavailable=0,保证先增后删,始终有足够的Pod在服务。

Deployment更新失败怎么回滚?

kubectl rollout undo deployment/my-app → 回滚到上一版本
kubectl rollout undo deployment/my-app --to-revision=2 → 回滚到指定版本
kubectl rollout history deployment/my-app → 查看所有修订版本
kubectl rollout status deployment/my-app → 查看当前更新状态
kubectl rollout pause deployment/my-app → 暂停更新(金丝雀发布)
原理:Deployment保留旧的ReplicaSet(revisionHistoryLimit个),回滚就是把旧RS的replicas恢复。

HPA除了CPU/内存还能基于什么指标扩缩容?

HPA(v2)支持3类指标:
1. Resource:CPU/内存利用率(最常用,需安装Metrics Server)
2. Pods:Pod自定义指标(如每秒请求数QPS),需Prometheus Adapter
3. Object/External:外部指标(如消息队列长度、Redis连接数),需Custom Metrics API
实际生产中常见:基于QPS扩缩容比CPU更精确(CPU可能因为GC等原因偏高但QPS并不高)。

← 上一篇:网络与服务 下一篇:存储与配置 →
核心三原则速记

K8s部署调度三原则:① Deployment 管 Pod 副本数,rollingUpdate 实现零停机 → ② nodeSelector/Affinity/Taint 控制调度,让 Pod 去到正确的 Node → ③ HPA 按 CPU/内存自动扩缩,别忘配 resources requests