Skip to content

第 8 章:最佳实践与面试题

8.1 生产最佳实践清单

设计层面

  1. 专用节点四件套:节点 label + taint;Pod affinity + toleration。只做一半必然出问题。
  2. 污点 key 加前缀:用 company.com/dedicated 这类带域名的 key,避免与 node.kubernetes.io/* 等内置污点冲突。
  3. 慎用 PreferNoSchedule:它是软约束,不是隔离手段;要隔离就用 NoSchedule。
  4. NoExecute 三思而后行:它会驱逐 Pod,且不尊重 PodDisruptionBudget。计划内维护用 kubectl drain
  5. 业务 Pod 禁止"万能容忍"tolerations: [{operator: Exists}] 会绕过所有节点保护,通过 OPA Gatekeeper/Kyverno 策略强制拦截。
  6. 显式覆盖故障容忍时长:关键服务显式设置 not-ready/unreachable 的 tolerationSeconds,不要依赖默认值拍脑袋。

运维层面

  1. 污点变更要审计:打/删污点影响全局调度,纳入变更管理流程。
  2. 删除污点语法检查key:Effect- 减号紧贴 effect,批量操作前先 --dry-run=client -o yaml 验证。
  3. 批量操作务必加选择器kubectl taint nodes --all 几乎永远不该在生产执行。
  4. 监控 Pending Pod:对 FailedScheduling 事件和长时间 Pending 的 Pod 建告警。
  5. 清理 Evicted Pod 尸体kubectl get pods -A --field-selector=status.phase=Failed 定期清理,避免 etcd 膨胀。

安全层面

  1. 容忍即越权通道:任何能创建带 toleration Pod 的用户/SA 都能绕过节点隔离。用 RBAC + 准入控制限制。
  2. DaemonSet 权限收敛:DaemonSet 自动获得大量容忍,其 ServiceAccount 权限要最小化。

8.2 CKA 考试考点速记

CKA 必考操作题,务必形成肌肉记忆:

bash
# 【高频题 1】给节点打污点,不让新 Pod 调度
kubectl taint nodes <node> key1=value1:NoSchedule

# 【高频题 2】创建能容忍该污点的 Pod
# 用 --dry-run 生成模板再编辑,最快
kubectl run pod1 --image=nginx --dry-run=client -o yaml > pod1.yaml
# 在 spec 下添加:
# tolerations:
# - key: "key1"
#   operator: "Equal"
#   value: "value1"
#   effect: "NoSchedule"
kubectl apply -f pod1.yaml

# 【高频题 3】删除污点
kubectl taint nodes <node> key1=value1:NoSchedule-

# 【易错点】
# - effect 拼写:NoSchedule / PreferNoSchedule / NoExecute(大小写敏感)
# - 删除时末尾减号
# - tolerations 写在 Pod spec 层级,与 containers 平级,不是在 container 里

8.3 高频面试题(含答案)

Q1:Taint 和 Toleration 分别是什么?解决什么问题?

:Taint 定义在节点上,表示节点拒绝某类 Pod;Toleration 定义在 Pod 上,表示 Pod 能容忍(匹配)某些污点。它们解决的是"节点排斥"问题——控制哪些 Pod 不允许调度到特定节点。与 nodeSelector/nodeAffinity 的"吸引"语义互补。三种 Effect:NoSchedule(硬拒新 Pod)、PreferNoSchedule(软拒)、NoExecute(拒新 Pod 且驱逐已运行的不匹配 Pod)。

Q2:三种 Effect 的区别?

NoSchedulePreferNoScheduleNoExecute
新 Pod 无容忍不能调度尽量不调度,可能调度不能调度
已运行 Pod不受影响不受影响被驱逐(受 tolerationSeconds 延迟)

Q3:给节点打了 NoSchedule 污点,节点上已有的 Pod 会怎样?

不受任何影响,继续运行。NoSchedule 只作用于调度决策,不驱逐存量 Pod。只有 NoExecute 才会驱逐。

Q4:Pod 配置了某污点的容忍,就一定会调度到那个节点吗?

不一定。容忍只表示"允许",调度器还会综合资源、亲和性、打分等因素,可能调度到其他节点。要保证定向调度需配合 nodeAffinity。这是最常见的理解误区。

Q5:节点有 3 个污点,Pod 只容忍其中 2 个,能调度上去吗?

不能。多个污点之间是 AND 关系,Pod 必须容忍节点上的全部污点。Pod 的容忍可以多于污点(多余的容忍无副作用)。

Q6:节点宕机后,上面的 Pod 多久会被重新调度?如何调整?

:默认 300 秒(5 分钟)。机制:node-controller 检测到节点异常后打 node.kubernetes.io/not-readyunreachable 的 NoExecute 污点;API Server 的 DefaultTolerationSeconds 准入控制器默认给每个 Pod 自动注入这两个污点的 300 秒容忍。调整方法:在 Pod spec 中显式配置同名容忍和 tolerationSeconds(显式配置覆盖自动注入值)。

Q7:Exists 和 Equal 运算符的区别?

:Equal(默认)要求 toleration 的 key、value、effect 与 taint 完全匹配;Exists 只要求 key(和 effect,如果指定)匹配,忽略 value,且使用 Exists 时不能指定 value。effect 省略则匹配该 key 的所有 effect。

Q8:如何让 Pod 容忍所有污点?生产上建议吗?

tolerations: [{"operator": "Exists"}](key、value、effect 全省略)。常见于需要无处不在的系统级 DaemonSet(日志/监控 Agent)。业务 Pod 不建议,会绕过所有节点隔离,应通过准入策略禁止。

Q9:cordon、drain 和 taint 的关系?

kubectl cordon 本质是打 node.kubernetes.io/unschedulable:NoSchedule 污点;uncordon 是删除它;drain = cordon + 通过 Eviction API 驱逐节点上非 DaemonSet Pod(尊重 PDB 和优雅终止期)。而手动打 NoExecute 污点驱逐 Pod 时不尊重 PDB

Q10:为什么系统 DaemonSet(如 kube-proxy)能跑在 Master 节点上?

:两个机制叠加:① 系统自动给 DaemonSet 注入一批内置污点的容忍(not-ready、unreachable、disk-pressure、memory-pressure、unschedulable 等);② 对 control-plane 污点,系统组件在 manifest 中显式配置了容忍。自定义 DaemonSet 想跑 Master 需手动加 node-role.kubernetes.io/control-plane 的容忍。

Q11:Taint-based Eviction 是什么?哪个版本引入的?

:1.6 引入、1.13 GA 的特性。节点问题(NotReady、不可达、内存/磁盘/PID 压力、网络不可用)以自动打污点的方式表达,由 taint-eviction-controller 根据 Pod 的容忍情况执行驱逐,替代了过去控制器中硬编码的驱逐逻辑,使用户可通过 tolerationSeconds 自定义驱逐行为。

Q12:如何实现"节点故障时,无状态服务 30 秒内迁移,数据库 10 分钟内不迁移"?

:分别在 Pod 中显式配置 not-ready 和 unreachable 污点的容忍:无状态服务 tolerationSeconds=30;数据库 tolerationSeconds=600。显式配置会覆盖自动注入的 300 秒默认值。

Q13:只给专用节点打污点不加 label,能做好专用节点吗?

不能。污点只挡住"别人",不能引导"自己人"——目标团队的 Pod 虽能容忍污点,但可能调度到普通节点。正确做法:节点 label + taint,Pod nodeAffinity + toleration 四件套。

Q14:Pod 一直 Pending,事件报 had untolerated taint,怎么排查?

:① kubectl describe pod 看完整 FailedScheduling 事件,列出所有被拒节点及原因;② kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints 核对节点污点;③ 核对 Pod tolerations 的 key/operator/value/effect 是否精确匹配;④ 注意多污点 AND 语义,要全部容忍;⑤ 同时检查报错里是否有 affinity、资源等其他原因,需全部解决。

8.4 快速参考卡(Cheat Sheet)

bash
# 污点操作
kubectl taint nodes NODE KEY=VALUE:EFFECT          # 添加
kubectl taint nodes NODE KEY=VALUE:EFFECT-         # 删除指定
kubectl taint nodes NODE KEY-                      # 删除该 key 全部
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
yaml
# 容忍模板
tolerations:
- key: "KEY"
  operator: "Equal"        # 或 Exists(此时删去 value 行)
  value: "VALUE"
  effect: "NoSchedule"     # NoSchedule/PreferNoSchedule/NoExecute,可省略
  tolerationSeconds: 300   # 仅 NoExecute 有效,可省略(=永久容忍)
想实现用什么
挡住无容忍的新 PodNoSchedule
尽量挡但允许溢出PreferNoSchedule
挡住新 Pod + 赶走存量NoExecute
延迟驱逐NoExecute + tolerationSeconds
容忍一切(系统组件)operator: Exists 裸写
定向调度到专用节点nodeAffinity + toleration
节点维护kubectl drain
快速故障转移显式 tolerationSeconds: 30