ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Velero(前身 Ark)备份删除故障排查:命名空间卡在 Terminating 状态与 finalizer 清理实战指南

Velero(前身 Ark)备份删除故障排查:命名空间卡在 Terminating 状态与 finalizer 清理实战指南 Velero前身 Ark备份删除故障排查命名空间卡在 Terminating 状态与 finalizer 清理实战指南【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero本文基于 Velero当时名为 Ark官方文档中记载的经典故障案例系统讲解 Kubernetes 中删除命名空间导致备份对象卡死的问题Ark 0.7.0 引入备份删除能力后若直接删除heptio-ark命名空间命名空间可能永久停留在 Terminating 状态、备份无法删除。读完本文你将掌握用jq批量剥离备份 finalizer 的修复手段、0.7.1 起的架构级缓解方案以及 finalizer 机制在删除流程中的底层原理。问题背景0.7.0 引入的备份删除能力与 finalizer 机制Ark 0.7.0 起增加了删除备份的能力。其实现方式不是直接删除对象而是为每个 Backup 对象附加一个finalizer。这一点在该版本的 CHANGELOG 中有明确记录Add ability to delete backups and their associated data。Kubernetes 的 finalizer 语义是当一个对象上存在至少一个 finalizer 时用户发起删除请求后系统只会给该对象打上 deletionTimestamp标记为待删除而不会立即删除对象只有当对象上的 finalizer 全部被移除后对象才会真正被回收。因此必须有一个控制器——在这个场景中就是 Ark server——在收到删除请求后处理备份、清理对象存储中的备份数据并移除 Ark 添加的 finalizer。正是这个机制在“删除命名空间”这个特定场景下引发了一个经典故障。故障现象删除 heptio-ark 命名空间后卡死在 Ark 0.7.0不含 0.7.1的默认部署中Ark server Pod 与 Backups、Schedules、Restores 以及 Ark 配置对象同处一个命名空间即heptio-ark。如果直接执行kubectl delete namespace/heptio-ark由于 Kubernetes 删除命名空间内对象时顺序是任意的Ark server Pod 可能先于 Backup 对象被删除。此时剩余 Backup 对象上的 Ark finalizer 再也没有控制器来移除于是这些备份会一直停留在 deleting 状态整个命名空间也随之卡在Terminating状态并且你无法再删除这些备份。修复步骤用 jq 批量剥离备份上的 finalizer针对这一情况官方给出的修复思路是绕开 Ark server直接用kubectl patch手工把每个 Backup 对象上的 Ark finalizergc.ark.heptio.com移除让 Kubernetes 能回收这些对象。1. 安装 jq如果环境中还没有jq先安装它。jq用于把kubectl get backup -o json的输出转换成一条条 patch 命令。2. 执行修复命令在命名空间卡死、备份无法删除的情况下运行以下命令bash (kubectl -n heptio-ark get backup -o json | jq -c -r $.items[] | kubectl -n heptio-ark patch backup/ .metadata.name -p \ (({metadata: {finalizers: ( (.metadata.finalizers // []) - [gc.ark.heptio.com]), resourceVersion: .metadata.resourceVersion}}) | tostring) \ --typemerge)这条命令干了三件事kubectl -n heptio-ark get backup -o json拉取命名空间下所有 Backup 对象的完整 JSON用jq遍历.items[]为每个备份对象生成一条kubectl patch命令——其中 patch 的 JSON 体把metadata.finalizers中名为gc.ark.heptio.com的条目剔除并携带该对象当前的metadata.resourceVersionbash (...)通过进程替换把生成的所有命令直接交给 bash 执行。其中值得注意的两个细节(.metadata.finalizers // [])表示若对象没有 finalizers 字段则视为空数组避免 jq 报错携带resourceVersion是 Kubernetes 对象更新的标准做法用于确保 patch 基于最新版本进行避免并发冲突。3. 生成出的命令长什么样上述命令实际生成并执行的是一批形如下面的 patch 命令kubectl -n heptio-ark patch backup/my-backup -p {metadata:{finalizers:[],resourceVersion:461343}} --typemerge kubectl -n heptio-ark patch backup/some-other-backup -p {metadata:{finalizers:[],resourceVersion:461718}} --typemerge--typemerge使用 Kubernetes 的 JSON Merge Patch 语义只更新 payload 中出现的字段其余字段保持不变finalizers:[]表示把该备份的 finalizer 列表清空。finalizer 清空后Kubernetes 会继续完成对象的实际回收备份得以删除命名空间也能从 Terminating 状态恢复。4. 如果 patch 报“不允许”错误重建 CRD如果执行 patch 时报错提示patching backups is not allowed不允许对 backups 打补丁通常意味着 Ark 的 CustomResourceDefinitionsCRD已经被删除——没有 CRD 定义apiserver 自然拒绝写操作。此时需要先重建 CRD。原文档指向当时 Ark 仓库中的examples/common/00-prereqs.yaml即包含 CRD 与预置资源的清单在当前版本仓库中该目录已不存在CRD 定义现位于 config/crd 目录下。重建 CRD 后再按上述第 2、3 步清理 finalizer 即可。0.7.1 及以后的架构级缓解server 与备份对象分离命名空间在 Ark 0.7.1 中官方通过改变默认部署架构从根本上缓解了这个问题默认配置将 Ark server 运行在与 Backups、Schedules、Restores 以及 Ark 配置不同的命名空间中。官方明确建议保持这一配置。这样做的意义在于即使删除存放备份对象的命名空间Ark server Pod 也不在其中它依然存活并能够处理 Backup 对象的删除请求、移除 finalizer从而避免对象永久卡死的局面。可以说这个版本对默认部署的调整就是把“清理者”和“被清理对象”从同一个销毁单元中分离出来。深入原理为什么命名空间会卡在 Terminating 状态用 Kubernetes 自身的机制可以完整解释这次故障删除请求只打标记删除带有 finalizer 的对象时Kubernetes 设置 deletionTimestamp对象进入“标记删除”状态但不会被立即回收必须由控制器移除 finalizer对象只有在 finalizer 被全部移除后才会真正删除。在这个场景中只有 Ark server 知道如何安全地删除备份数据并移除gc.ark.heptio.comfinalizer命名空间删除顺序不确定删除命名空间时其中对象的删除顺序是任意的。0.7.1 之前的部署把 Ark server Pod 与备份放在同一命名空间Pod 可能先于备份被删除清理者消失 → finalizer 永远无人移除Ark server 不在了剩余备份的 finalizer 无人处理备份停留在 deleting 状态命名空间因此卡在 Terminating。从源码看 finalizer 在现代 Velero 中的演进虽然本文记录的是 Ark 0.7.x 时代的故障但 finalizer 机制在今天 Velero 的删除与收尾流程中依然处处可见仓库源码可以佐证备份删除由 backup_deletion_controller.go 负责它以DeleteBackupRequest为驱动实际执行备份数据清理并最终删除 Backup 对象备份的收尾finalizing阶段由 backup_finalizer_controller.go 处理控制器名称在 constant.go 中定义为backup-finalizer负责在异步插件操作完成后把备份推进到 Completed/PartiallyFailed 等终态在 1.0 版本中官方明确移除了旧代码中对gc.ark.heptio.comfinalizer 的剥离逻辑见 CHANGELOG-1.0.mdremove code that strips the gc.ark.heptio.com finalizer from backups这正说明早期这个临时手工清理手段已不再被需要删除流程已由控制器体系完整接管同时现代版本还引入了对处于 Terminating 状态的命名空间的显式处理备份资源收集阶段会跳过这类命名空间见 CHANGELOG-1.17.md 中Skip namespace in terminating state in backup resource collection的说明。从部署形态看当前仓库中的示例清单如 examples/minio/00-minio-deployment.yaml已将命名空间设置为velero这与 0.7.1 起“server 与备份对象分命名空间”的架构一脉相承——避免再次出现“清理者与被清理对象同归于尽”的场景。经验总结回顾这一历史故障可以沉淀三条实用经验不要直接删除运行着控制器 Pod 的命名空间只要命名空间中存在带有 finalizer 的自定义资源且其清理者也在同一命名空间内删除命名空间就可能导致对象永久卡死finalizer 卡死是可控的通过kubectl patch --typemerge手工剥离 finalizer 是 Kubernetes 中通用的“解卡”手段jq可以方便地把批量对象的清理命令自动化生成出来架构隔离是更好的解法把控制器与被管理对象放在不同命名空间或用velero uninstall之类的专用卸载流程处理远比手工清理安全。本文所述故障虽源于 Ark 早期版本但其中的 finalizer 语义、patch 修复手法与架构设计考量对于任何使用 Kubernetes 自定义资源并借助 finalizer 实现删除语义的运维场景至今仍有直接的参考价值。【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表