Kubernetes 节点上删除 Pod 完全指南:kubectl delete、drain 与 cordon 实战解析(refine 技术博客) Kubernetes 节点上删除 Pod 完全指南kubectl delete、drain 与 cordon 实战解析refine 技术博客【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本篇技术指南以 refine 官方技术博客的《A Guide for Delete Pods from Kubernetes Nodes》为核心系统讲解如何通过kubectl delete、kubectl drain、kubectl cordon/uncordon在 Kubernetes 节点上安全删除 Pod。你将从 Pod 的基础概念出发掌握批量排空节点、逐个删除 Pod、处理 Deployment/ReplicaSet/StatefulSet/DaemonSet 各类控制器差异的完整操作流程并学会在删除前后验证服务不受影响。本文涵盖的操作路径什么是 Kubernetes 中的 Pod为什么需要删除 Pod删除 Pod 前的必要检查从节点批量删除全部 Podkubectl drain验证 drain 前后的 Pod 状态从节点逐个删除 Pod受控删除处理 Deployment 与 ReplicaSet 管理的 Pod处理 StatefulSet Pod让 Pod 重新回到节点kubectl uncordon仓库实践refine 文档站的 Kubernetes 部署总结与安全建议什么是 Kubernetes 中的 PodPod 是 Kubernetes 中最小的执行单元smallest execution unit一个 Pod 内可以包含一个或多个应用容器。Pod 天然是**临时性ephemeral**的如果某个 Pod 发生故障或者它所在的节点发生故障Kubernetes 会自动创建该 Pod 的新副本以维持业务持续运行。在同一 Pod 内的容器例如 Docker 容器会共享相同的计算资源、网络命名空间与存储卷这使得 Pod 成为调度、伸缩和副本管理的基本粒度。理解这一点是后续所有删除操作的前提Pod 本身可以被任意删除但真正决定删除后会发生什么的是管理它的控制器Controller类型——Deployment、ReplicaSet、StatefulSet、DaemonSet、Job 等控制器各自定义了不同的重建与调度行为这也是本文后续分场景讨论的根源。为什么需要删除 Pod在实际运维中你可能需要从一个或多个工作节点删除 Pod常见场景包括调试节点问题节点出现异常CPU、内存、网络、磁盘故障时需要将 Pod 迁移走以便检修节点升级与缩容对节点做系统升级或主动将节点从集群中移除例如使用容器方式部署应用时的节点下线手动缩容测试为测试目的手动缩小集群规模节点维护由于维护需求需要清空特定节点上的所有 Pod。无论哪种场景删除动作本身并不复杂复杂的是如何在删除的同时保证业务不中断、数据不丢失、故障不扩散。删除 Pod 前的必要检查应用弹性的重要性持续提供一致、可靠的服务是满足用户期望、提升用户留存的基础。服务越是稳定可用用户流失与投诉的概率就越低而故障与中断的频率和影响范围降低也能直接削减运维成本与业务风险。反之一次失败的删除可能带来收入损失、数据丢失、安全漏洞乃至声誉损害。具备弹性resilience的应用能够在故障发生后快速恢复、迅速回到正常状态从而避免或缓解上述后果——在动手删除任何 Pod 之前请先确认你的应用具备这样的自愈能力。草率删除 Pod 的风险在未做任何检查的情况下匆忙删除 Pod至少存在三类典型风险服务中断或性能劣化如果一次删除过多 Pod或误删了没有副本的关键 Pod可能导致服务整体不可用或响应能力明显下降数据丢失或损坏在没有备份或数据复制机制的前提下删除 PodPod 内存储和处理的数据可能随之丢失或受损故障级联扩散被删除的 Pod 如果处于通信网络或依赖链的关键节点上问题可能沿依赖关系在整个系统中传播放大。因此删除前应至少确认应用是否有足够的副本数、是否由控制器管理、数据是否有持久化与备份、删除后是否有自动重建机制。从节点批量删除全部 Podkubectl draindrain 命令的工作原理kubectl drain用于优雅地将节点移出服务gracefully remove a node from service它会驱逐evict该节点上运行的所有 Pod并将它们调度到其他可用节点同时阻止新的 Pod 继续调度到该节点。为了尽可能避免数据丢失或对运行中应用的干扰drain 不会粗暴地强制终止 Pod而是遵循 Pod 的优雅终止流程先执行 preStop 钩子、再等待优雅终止宽限期。这使得节点维护与故障排查可以在不影响应用可用性的前提下提前规划。实践drain minikube 节点假设我们要排空名为minikube的节点该节点上存在由DaemonSet控制器管理的 Pod因此需要--ignore-daemonsets标志跳过它们也包含不受任何控制器管理的裸 Pod因此需要--force标志强制处理可以执行kubectl drain minikube --ignore-daemonsets --force命令执行后kubectl 会逐个驱逐该节点上的 Pod输出每个被驱逐 Pod 的名称与结果例如pod/xxx evicted。--ignore-daemonsets让 drain 跳过 DaemonSet 管理的 Pod 并继续执行--force则允许删除那些没有对应控制器、删除后无法自动重建的裸 Pod见下文--force标志及其影响。补充说明drain 过程是幂等且可重复的。如果排空过程中发现节点上仍有无法驱逐的 Poddrain 会报告错误并停在原地便于你先处理特殊情况例如无容忍的裸 Pod、本地卷 Pod 等后再继续。验证 drain 前后的 Pod 状态在 drain 前后验证节点上的 Pod 分布至关重要它能确保 Pod 被正确迁移到其他节点、服务未被扰动。推荐使用以下命令列出所有命名空间下每个 Pod 及其节点归属kubectl get pods --all-namespaces -o wide该命令会返回每个 Pod 的名称NAME、命名空间NAMESPACE、状态STATUS、重启次数RESTARTS、存活时间AGE、IP、所在节点NODE以及提名节点NOMINATED NODE。通过对比 drain 前后的两次输出你可以清楚看到哪些 Pod 已从被排空的节点上驱逐、它们被重新调度到了哪些节点、是否有 Pod 处于异常状态需要人工介入。特殊场景NoExecute 与 DaemonSet PodNoExecute 容忍 Pod带有node.kubernetes.io/...这类 NoExecute 污点容忍toleration的 Pod如果没有设置tolerationsSeconds容忍时间上限就可能无限期留在节点上drain 无法将其驱逐。此时必须使用--force标志强制执行删除放弃等待优雅终止。DaemonSet 管理的 PodDaemonSet 控制器会确保集群中每个节点上都运行该 Pod 的一个副本。默认情况下kubectl drain不会驱逐 DaemonSet Pod除非你显式指定--ignore-daemonsets标志——该标志表示跳过这些 Pod继续执行排空。--force标志及其影响当你排空的节点上存在由ReplicationController、ReplicaSet、Job、DaemonSet 或 StatefulSet管理的 Pod 时对应的控制器会在删除后自动重建这些 Pod。因此drain 在遇到这类 Pod 时会给出警告性质的错误信息提醒你删除后它们会被重新创建。若你确认要继续执行排空就需要加上--force选项来忽略这些警告、强制推进 drain 流程。需要强调的是--force关闭的是拒绝删除有控制器管理的 Pod这一保护逻辑它不会关闭优雅终止机制但配合 NoExecute 场景时可能意味着 Pod 被直接删除而不再等待。从集群中移除节点当节点已被完全排空、不再运行任何 Deployment、Pod、StatefulSet 或 DaemonSet 之后可以使用下面的语法将该节点从集群中删除kubectl delete node [NAME_OF_NODE]例如我们有一个名为minikube的节点且已完成排空则执行kubectl delete node minikube命令执行成功后kubectl 会输出node minikube deleted该节点即从集群对象中移除。从节点逐个删除 Pod受控删除为什么需要受控删除与批量排空相比逐个删除 Pod 的受控方式具备明显优势一是更好的故障容忍度——将节点问题对服务可用性的影响降到最低二是资源利用优化——只释放特定节点上选定 Pod 占用的资源避免资源浪费同时防止服务整体劣化。当你只想调整个别 Pod 而不想影响整个节点时这是更精准的手段。使用 kubectl cordon 命令kubectl cordon是一种可靠且受控地从节点移除 Pod 的方法它将节点标记为不可调度unschedulable确保不会有新的 Pod 被分配到这个节点与此同时节点上已有的 Pod 仍然保持运行并正常处理请求。这样你就获得了先封住入口、再从容清理存量的操作窗口既不会影响集群的可访问性又能安全地逐个删除 Pod。例如将我们的minikube节点标记为不可调度kubectl cordon minikube命令执行后输出类似node/minikube cordoned节点状态中会出现SchedulingDisabled标记。删除单个 Pod节点被 cordon 之后就可以通过kubectl delete pod命令删除该节点上的单个 Pod可按 Pod 名称删除也可按需指定命名空间。首先用kubectl get pods配合--field-selector列出位于特定节点上的 Podkubectl get pods --all-namespaces --field-selector spec.nodeNameminikube--field-selector spec.nodeNameminikube会筛选出spec.nodeName字段等于minikube的所有 Pod输出包含 Pod 所在命名空间、名称与状态等信息。假设在上面的列表中我们想删除名为my-demo-pod的 Pod执行kubectl delete pod my-demo-pod命令执行后输出pod my-demo-pod deleted该 Pod 即从minikube节点上被删除。处理 Deployment 与 ReplicaSet 管理的 Pod如果被删除的 Pod 属于Deployment 或 ReplicaSet删除后控制器会自动在其他节点上重新创建该 Pod从而维持声明式副本数desired replicas不变。也就是说直接删除这类 Pod 并不能真正移除它——它马上会以新名字重新出现。因此要把 Deployment/ReplicaSet 的所有 Pod 从某个节点上彻底清除正确做法是先调大副本数scale up再删除 Pod最后调回副本数scale down。这样新创建的 Pod 会被调度到其他可用节点且最终副本数回到预期值而目标节点上的 Pod 则被清空且不会重新调度回来。例如我们有一个名为example-deployment的 Deployment先将其副本数扩到 4kubectl scale deployment example-deployment --replicas4输出会确认deployment.apps/example-deployment scaled。接着列出example-namespace命名空间中、标签为appnginx、且位于minikube节点上的 Podkubectl get pods -l appnginx -n example-namespace --field-selector spec.nodeNameminikube然后删除列表中名为my-demo-deployment-cbdccf466-p8zjf的 Pod再确认它是否被重建kubectl get pods -l appnginx输出会显示该 Pod 已被自动重新创建在单节点 Kubernetes 环境中会重建在同一个minikube节点上。最后将example-deployment的副本数从 4 缩回 3kubectl scale deployment example-deployment --replicas3输出确认副本数已缩回 3节点上的多余 Pod 被回收副本数与删除前保持一致。处理 StatefulSet PodStatefulSet 的 Pod 删除行为与 Deployment 截然不同删除 StatefulSet 的 Pod 并不会自动触发其被重新调度到其他节点而是会以相同的名称和序号ordinal index在同一个节点上被重建。原因在于 StatefulSet Pod 拥有集群内唯一且持久的标识例如demo-statefulset-0、demo-statefulset-1其存储卷、网络身份都与这个序号强绑定不允许随意换个地方重生。因此若想从节点上移除 StatefulSet 的 Pod正确做法是先通过缩容scale down降低 StatefulSet 的副本数再删除对应 Pod这样 Pod 才不会在同节点以同名重建。例如假设有一个名为demo-statefulset的 StatefulSet当前有 3 个 Pod将其缩容到 2kubectl scale statefulset demo-statefulset --replicas2输出确认demo-statefulset已缩容为 2 个副本。列出节点上的 StatefulSet Pod 后可以看到demo-statefulset-0与demo-statefulset-1两个 Pod。删除demo-statefulset-0kubectl delete pod demo-statefulset-0最后用以下命令验证demo-statefulset-0已被删除且不会在minikube节点上被重建kubectl get pods -l appweb-app让 Pod 重新回到节点kubectl uncordonuncordon 命令kubectl uncordon与kubectl cordon相反它把节点重新标记为可调度schedulable使其准备好接收新的 Pod。之前被 cordon状态为SchedulingDisabled或被 drain 的节点都可以通过 uncordon 恢复调度能力。例如之前 cordon 了minikube节点且其状态为SchedulingDisabled现在执行kubectl uncordon minikube命令执行后输出node/minikube uncordoned节点恢复可调度状态。验证 Pod 重新调度回节点uncordon 之后可以运行以下命令查看节点上正在运行的 Pod验证 Pod 是否重新被调度回来kubectl get pods在输出中可以看到之前 cordonminikube节点时被删除的demo-deploymentPod在节点 uncordon 之后已被重新调度并在minikube节点上重新创建。仓库实践refine 文档站的 Kubernetes 部署上述 Pod 管理知识在 refine 仓库中并非纸上谈兵——refine 的官方文档站本身就是以 Kubernetes 工作负载的形式部署的其 Helm Chart 位于 documentation/k8s/refine-documentation。对照本文内容可以在该 Chart 中找到一手的 Pod 管理配置Deployment 与副本声明在 Deployment 模板 中replicas: {{ .Values.replicaCount }}直接对应 values.yaml 里的replicaCount: 1。这正是本文所述Deployment 由 ReplicaSet 控制器维持副本数、删除单个 Pod 会被自动重建的配置体现——文档站的所有 Pod 都由 Deployment 管理直接kubectl delete pod只会触发重建。调度约束与本文场景的关联模板中的nodeSelector、affinity、tolerationsdeployment.yaml与 values.yaml 中的tolerations: []正是决定 Pod 会被调度到哪些节点的机制也是 drain/cordon 操作之所以能影响 Pod 分布的根本原因——带有 NoExecute 污点容忍的 Pod对应本文特殊场景就可能因此留在被 drain 的节点上。副本伸缩配置values.yaml 中的autoscaling段minReplicas、maxReplicas、targetCPUUtilizationPercentage展示了副本数声明与水平伸缩的配置方式配合kubectl scale命令即可在运行时手动调整副本数。环境契合值得一提的是values.yaml 的注释中明确提到不指定默认资源限额有助于 Chart 在 Minikube 这类小资源环境运行——这与本文示例使用的minikube节点环境完全一致说明在 Minikube 上实践这些删除命令是官方认可的验证路径。总结与安全建议理解 Kubernetes 环境中 Pod 删除的复杂性是保证应用弹性和可靠性的关键。虽然 Kubernetes 本身已为 Pod 终止设计了较为平滑的处理机制但盲目或草率的 Pod 删除仍可能造成服务中断、数据丢失乃至级联故障。删除行为的后果取决于 Pod 所属的控制器类型Deployment / ReplicaSet删除即重建需通过先扩容、再删除、后缩容的方式才能真正清空节点StatefulSet同名同节点重建必须先缩容再删除DaemonSet每个节点一份drain 默认跳过需用--ignore-daemonsets无控制器管理的裸 Pod / NoExecute 容忍 Pod需用--force强制处理。为避免删除后 Pod 重新调度回原节点务必采用删除前先调整副本数等技巧。最后强烈建议在生产集群中实施任何删除方案之前先在安全的非生产环境如开发或预发集群中反复演练熟悉各类 Pod 的删除行为差异检验你对 Pod 生命周期的理解并在受控环境中打磨你的删除流程。充分的准备工作是 Kubernetes Pod 管理成功的前提。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考