由于 ownerReferences 指向 kubernetes 中不同命名空间中的资源,pod 被终止

问题描述

从 kubernetes 1.20 开始,ownerReferences 以及 K8s 执行 GC 的方式发生了变化。 基本上,如果 x 命名空间中的资源在 y 命名空间中启动一个 pod/job,子节点具有 ownerReferences 引用 x 中的父资源,K8s 将终止子 pod/工作。

Reference

  • 解决了在遇到包含不正确数据的 ownerReferences 时垃圾收集控制器的非确定性行为。当检测到子对象和所有者对象之间的命名空间不匹配时,记录具有 OwnerRefInvalidNamespace 原因的事件。可以在升级之前运行 kubectl-check-ownerreferences 工具以定位具有无效 ownerReferences 的现有对象。
    • 一个命名空间对象的 ownerReference 引用了一个命名空间类型的 uid,而该 uid 不存在于同一命名空间中,现在一致地将其视为该所有者不存在,并删除子对象。
    • 具有引用命名空间类型的 uid 的 ownerReference 的集群范围对象现在始终被视为该所有者不可解析,并且垃圾收集器会忽略子对象。 (#92743,@liggitt) [SIG API 机械、应用和测试]

如果我们移除 ownerReferences,资源将不会被垃圾回收。有没有办法处理这种情况,即;如何让 ownerReferences 在多个命名空间中工作或让作业/pod 在完成后自行清理?谢谢。

解决方法

根据Fix GC uid races and handling of conflicting ownerReferences #92743

命名空间旨在相互独立,因此在 ownerReferences、secret/configmap 卷引用等中不允许跨命名空间引用。

此外,授予命名空间 a 的权限通常不是为了提供可见性或与命名空间 b 中的对象交互的能力(或导致系统控制器与命名空间 b 中的对象交互)。

Update GC cross-namespace note #25091

设计不允许跨命名空间所有者引用。

因此,使用 ownerReferences 进行跨命名空间的垃圾收集是不可能的通过设计


但是,您可以使用标签模拟多命名空间 GC。您只需要在某个对象创建子对象时配置这些标签即可。

或者,您可以删除命名空间以对该命名空间中的所有对象进行 GC,但这可能不是最佳解决方案。


编辑

$ kubectl label pods owner=my -l region=europe
$ kubectl label pods owner=my -l region=pacific
$ kubectl label svc owner=my -l svc=europe
$ kubectl label svc owner=my -l svc=pacific
$ kubectl label pod kube-proxy-2wpz2 owner=my -n kube-system 
$ kubectl label pod kube-proxy-cpqxt  owner=my -n kube-system 
$ kubectl get pods,svc -l owner=my --show-labels --all-namespaces

NAMESPACE     NAME                   READY   STATUS        RESTARTS   AGE    LABELS
default       pod/aloha-pod          1/1     Running       0          54d    app=aloha,owner=my,region=pacific
default       pod/ciao-pod           1/1     Running       0          54d    app=ciao,region=europe
default       pod/hello-pod          1/1     Terminating   0          54d    app=hello,region=europe
default       pod/ohayo-pod          1/1     Running       0          54d    app=ohayo,region=pacific
kube-system   pod/kube-proxy-2wpz2   1/1     Running       2          299d   controller-revision-hash=5cf956ffcf,k8s-app=kube-proxy,pod-template-generation=1
kube-system   pod/kube-proxy-cpqxt   1/1     Running       3          299d   controller-revision-hash=5cf956ffcf,pod-template-generation=1

NAMESPACE   NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE   LABELS
default     service/europe    ClusterIP   10.109.5.102    <none>        80/TCP    54d   owner=my,svc=europe
default     service/pacific   ClusterIP   10.99.255.196   <none>        80/TCP    54d   owner=my,svc=pacific
$ kubectl delete pod,svc -l owner=my --dry-run --all-namespaces

pod "aloha-pod" deleted (dry run)
pod "ciao-pod" deleted (dry run)
pod "hello-pod" deleted (dry run)
pod "ohayo-pod" deleted (dry run)
pod "kube-proxy-2wpz2" deleted (dry run)
pod "kube-proxy-cpqxt" deleted (dry run)
service "europe" deleted (dry run)
service "pacific" deleted (dry run)

或者,可能有一个 bash 脚本根据标签删除其控制器对象不存在的所有对象。它也可以在配置了适当服务帐户的集群内运行。


没有简单的内置选项来实现您想要的。您应该将所有者引用对象保留在同一命名空间中。