高频面试题:容器挂了会不会重新调度新节点?大部分运维都答错了
1. 先搞清楚一个核心事实
在深入细节前,必须明确一个核心机制:Kubernetes 的设计哲学决定了它不会对运行中的Pod执行“迁移”。
它的运作逻辑是线性的:删除旧Pod → 创建新Pod → 调度新Pod。Pod一旦被调度到某个节点,其生命周期就与该节点绑定,不存在运行时挪动的概念。这与虚拟机的实时迁移技术有本质区别,体现了K8s声明式API与不可变基础设施的设计原则。
2. 容器挂掉,会发生什么?
容器进程由节点上的kubelet协同容器运行时(如containerd、CRI-O)直接管理。当容器内部进程意外终止时,后续行为取决于一个关键配置。
这个关键点就是Pod规约中定义的restartPolicy重启策略。对于Deployment等控制器创建的Pod,默认策略是Always。这意味着,kubelet一旦监测到容器退出,会立即在当前节点上尝试重启容器进程。
这个过程产生三个明确的结果:
第一,容器仅在原节点进行原地重启;第二,Pod的元数据对象(metadata)与状态(status)持续存在,并未被删除;第三,因此,完全不会触发调度器(kube-scheduler)的跨节点重新调度行为。
此时,执行kubectl get pods常会看到CrashLoopBackOff状态。这个状态常被误解,它并非调度失败或节点切换的信号,而是明确指示Pod仍驻留在原节点,其容器陷入了“启动→崩溃→延迟重试”的循环,是典型的应用程序或配置问题。
3. 什么时候才会重新调度?
请牢记这一核心原则:只有Pod对象被删除,才会触发真正的重新调度。 调度器的职责仅限于为新建的Pod选择最佳节点。以下是触发重新调度的几个典型场景:
(1) 场景一:Node 宕机
这是最典型的触发条件。节点物理故障导致kubelet进程终止,与控制平面的心跳中断。控制平面(主要由Controller Manager监控)会将该节点状态标记为NotReady。经过一段容忍期(默认5分钟)后,控制器判定节点上所有Pod失效,遂将其删除。随后,对应的上层控制器(如Deployment Controller)会立即响应,创建新的Pod副本以满足期望状态,这个全新的Pod才会被调度器重新评估并分配到健康的可用节点上。
(2) 场景二:手动驱逐
这是运维中的主动操作,例如节点维护或升级。执行kubectl drain node01 --ignore-daemonsets命令会触发两个动作:首先,目标节点被标记为cordon(停止调度),阻止新Pod分配;其次,该节点上所有非DaemonSet管理的Pod会被优雅终止(即删除)。这些被删除的Pod,若受控制器管理,会立即触发重建流程,新Pod的创建必然伴随调度器的重新决策。
(3) 场景三:资源不足被驱逐
当节点面临资源压力,如内存不足(MemoryPressure)、磁盘空间耗尽(DiskPressure)或进程ID枯竭(PIDPressure)时,kubelet为保障节点稳定性,会依据优先级主动驱逐部分Pod。被驱逐的Pod状态变为Evicted。同样,其所属的控制器会检测到副本缺失,并创建替代Pod,新Pod需要调度器为其分配新的运行节点。
(4) 场景四:手动删除 Pod
直接执行kubectl delete pod xxx。如果该Pod由Deployment、ReplicaSet或StatefulSet等控制器管理,控制器会迅速介入,重建一个新Pod以符合声明的副本数,此过程包含完整的重新调度。但需注意特例:对于“裸Pod”(即独立创建、无控制器管理的Pod),删除操作是终结性的,不会触发任何重建或调度。
4. 面试标准回答模板
基于以上分析,可以提炼出一个精准、结构化的回答框架,适用于技术面试或团队知识传递:
容器故障退出时,默认仅由所在节点的kubelet依据Pod的restartPolicy进行原地重启,此过程不涉及Pod删除,因此不会触发跨节点的重新调度。真正的重新调度,仅在Pod被删除后发生——无论是因节点故障、资源驱逐、主动维护还是手动删除。此时,相应的控制器会重建Pod,而这个新建的Pod对象才会被调度器(kube-scheduler)重新评估并分配至合适的节点。总结来说,Kubernetes的调度是Pod创建时的绑定行为,而非运行时的迁移操作。
清晰阐述这一逻辑,足以证明你对Pod生命周期管理与调度器核心工作机制有扎实、透彻的理解。
