bigywater.tech
Kubernetes · 19

ownerReferences 与垃圾回收:级联删除的三种模式

删掉 Deployment,ReplicaSet 和 Pod 为什么也跟着没了?靠的是从属对象上的 ownerReferences 和垃圾回收器。这篇用 ConfigMap 搭出所有者和从属,把 background、foreground、orphan 三种级联模式各跑一遍,再看 ownerReferences 写错了会发生什么。

~40 ms
--cascade=background 删除所有者后,从属被垃圾回收器删掉的时间
foregroundDeletion
foreground 删除时所有者暂时带着的 finalizer
OwnerRefInvalidNamespace
所有者在别的命名空间时垃圾回收器产生的事件(从属同时被删)

background:先删所有者

实测 · 本机执行输出
  kubectl delete cm owner1 --cascade=background:configmap "owner1" deleted from k13 namespace;耗时 40 ms;owner1 还在吗:False
  从属 child1、child1b 分别在 39 ms、39 ms 后消失

从属 ownerReferences 里写着所有者的名字和 uid。--cascade=background(默认)删除所有者,40 毫秒就返回,所有者立刻消失;垃圾回收器随后发现从属的所有者没了,在约 40 毫秒内把从属也删掉。

foreground:先删从属

实测 · 本机执行输出
  1.5 秒后:owner2 还在吗 True;deletionTimestamp=有;finalizers=['foregroundDeletion']
  从属:fast(blockOwnerDeletion=true,无 finalizer)还在吗 False;slow(blockOwnerDeletion=true,带 finalizer)还在吗 True;noblock(blockOwnerDeletion=false,带 finalizer)还在吗 True
  只摘掉 slow(blockOwnerDeletion=true)的 finalizer:owner2 在 38 ms 后消失;此时 noblock(blockOwnerDeletion=false,finalizer 还在)还在吗 True

所有者被标记删除,但仍然存在,finalizers 里多了 foregroundDeletion。无 finalizer 的从属 fast 很快被删,带 finalizer 的 slow(blockOwnerDeletion: true)卡住了所有者;只摘掉 slow 的 finalizer,所有者 38 毫秒后消失,而 noblock(blockOwnerDeletion: false,finalizer 还在)仍然存在——只有 blockOwnerDeletion: true 的从属才会阻塞所有者。

orphan:放走从属

实测 · 本机执行输出
  删除前 child3 的 ownerReferences:[{"apiVersion": "v1", "blockOwnerDeletion": true, "kind": "ConfigMap", "name": "owner3", "uid": "52d9cae2-54b7-4180-9e6e-148fef0a9c75"}]
  kubectl delete cm owner3 --cascade=orphan:configmap "owner3" deleted from k13 namespace
  之后 child3 还在吗 True;ownerReferences=None

--cascade=orphan 删除所有者之后,从属还在,但 ownerReferences 已经被垃圾回收器摘掉(实测为 None),今后不会再被级联。把 Deployment 删掉而保留它的 Pod 就是这个模式。

所有者找不到

实测 · 本机执行输出
  ownerReferences 指向不存在的所有者(随便写的 uid):从属 ghost 在 39 毫秒后被垃圾回收器删掉
  所有者 owner4 在 k13-other 里真实存在,从属 child4 在 k13:在 40 毫秒后被删掉(跨命名空间的 ownerReferences 不被支持,所有者按“不存在”处理)
  相关事件:REASON                     MESSAGE | OwnerRefInvalidNamespace   ownerRef [v1/ConfigMap, namespace: k13, name: owner4, uid: 49af3f1c-3fc6-4771-9018-34190c1fb034] does not exist in namespace "k13"

从属的 ownerReferences 指向一个不存在的 uid,约 40 毫秒就被垃圾回收器删掉。所有者真的存在、只是在别的命名空间,结果一样,同时产生事件 OwnerRefInvalidNamespace:跨命名空间的 ownerReferences 不被支持,所有者按“不存在”处理。所以手写 ownerReferences 一定要用真实的 uid,并且和从属在同一个命名空间(或者所有者是集群级资源)。

分步演示

级联删除
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。三节点 kind 集群 kx-main(Kubernetes v1.37.0);所有者和从属都是 ConfigMap,ownerReferences 手写(apiVersion v1、kind ConfigMap、真实 uid);foreground 实验里用自己写的 finalizer example.com/slow 让从属停留;“消失时间”是脚本以 50 毫秒间隔轮询的结果,包含 kubectl 调用的开销;每种情形各一次
    • 没有验证:Pod / ReplicaSet / Deployment 这类真实工作负载的级联;集群级所有者与命名空间级从属;多个所有者(多个 ownerReferences)时的删除规则;垃圾回收器的重新同步与大规模对象下的耗时;kubectl delete 的 --cascade 默认值在不同资源上的差别
    京ICP备2026067502号-1京公网安备11010502063487号