# 垃圾回收
Kubernetes garbage collector(垃圾回收器)的作用是删除那些曾经有 owner,后来又不再有 owner 的对象。
# 所有者和从属对象
某些 Kubernetes 对象是其他 Kubernetes 对象的所有者(owner),同时,我们称被拥有的对象为拥有者的从属对象(dependent)。例如,ReplicaSet 是一组 Pod 的所有者,在这里 Pod 是 ReplicaSet 的从属对象。每一个从属对象都有一个 metadata.ownerReferences
字段,标识其拥有者是哪一个对象。
某些情况下,Kubernetes将自动设置 ownerReferences
字段。例如,当您创建一个 ReplicaSet 时,Kubernetes 自动设置该 ReplicaSet 创建的 Pod 中的 ownerReferences
字段。自版本 1.8 开始,对于 ReplicationController、ReplicaSet、StatefulSet、DaemonSet、Deployment、Job、CronJob等创建或管理的对象,Kubernetes 都将自动为其设置 ownerReference
的值。
也可以通过修改 ownerReference
字段,手动设置所有者和从属对象的关系。
下面例子中的 ReplicaSet 包含三个 Pod:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-repset
spec:
replicas: 3
selector:
matchLabels:
pod-is-for: garbage-collection-example
template:
metadata:
labels:
pod-is-for: garbage-collection-example
spec:
containers:
- name: nginx
image: nginx
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
执行命令以创建该 ReplicaSet,然后查看 Pod 的 .metadata.ownerReferences
字段的值:
kubectl apply -f https://kuboard.cn/statics/learning/obj/gc-replicaset.yaml
kubectl get pods --output=yaml
2
输出结果如下所示:
apiVersion: v1
kind: Pod
metadata:
...
ownerReferences:
- apiVersion: apps/v1
controller: true
blockOwnerDeletion: true
kind: ReplicaSet
name: my-repset
uid: d9607e19-f88f-11e6-a518-42010a800195
...
2
3
4
5
6
7
8
9
10
11
12
跨名称空间
在 Kubernetes 的设计里,跨名称空间的所有者-从属对象的关系是不被允许的。这意味着:
- 名称空间内的从属对象只能指定同名称空间的对象作为其所有者
- 集群级别的对象只能指定集群级别的对象作为其所有者
# 垃圾收集器如何删除从属对象
当删除某个对象时,可以指定该对象的从属对象是否同时被自动删除,这种操作叫做级联删除(cascading deletion)。级联删除有两种模式:后台(background)和前台(foreground)
如果删除对象时不删除自动删除其从属对象,此时,从属对象被认为是孤儿(或孤立的 orphaned)。
# Foreground级联删除
在 foreground 级联删除模式下,根对象(直接被删除的对象)先进入“正在删除”(deletion in progress)状态,此时:
- 对象仍然可以通过 REST API 查询到(可通过 kubectl 或 kuboard 查询到)
- 对象的
deletionTimestamp
字段被设置 - 对象的
metadata.finalizers
包含值foregroundDeletion
一旦对象被设置为 “deletion in progress” 状态,垃圾回收器将删除其从属对象。当垃圾回收器已经删除了所有的“blocking”从属对象(ownerReference.blockOwnerDeletion=true
的对象)以后,将删除所有者对象。
此处需要注意的是,在“foregroundDeletion” 模式下,只有 ownerReference.blockOwnerDeletion=true
的对象将阻止所有者对象的删除。在 Kubernetes 版本 1.7 开始,增加了 admission controller (opens new window) ,可以基于所有者对象的删除权限配置限制用户是否可以设置 blockOwnerDeletion
字段为 true,因此,未经授权的从属对象将不能阻止所有者对象的删除。
如果对象的 ownerReferences
字段由控制器自动设置(例如,Deployment、ReplicaSet),blockOwnerDeletion
也将被自动设置,您无需手工修改该字段的取值。
# Background级联删除
在 background 级联删除模式下,Kubernetes将立刻删除所有者对象,并由垃圾回收器在后台删除其从属对象。
# 设置级联删除策略
在删除对象时,通过参数 deleteOptions
的 propagationPolicy
字段,可以设置级联删除的策略。可选的值有: Orphan
、Foreground
、Background
。
默认值:
- 在 Kubernetes 1.9 之前,许多类型控制器的默认垃圾回收策略都是
orphan
,例如,ReplicationController、ReplicaSet、StatefulSet、DaemonSet、Deployment。 - 对于 apiVersion 为
extensions/v1beta1
、apps/v1beta1
、和apps/v1beta2
的对象,除非特殊指定,垃圾回收策略默认为orphan
- 在 Kubernetes 1.9 中,对于所有 apiVersion 为
apps/v1
的对象,从属对象默认都将被删除
下面的例子中,使用了 background 级联删除:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
-H "Content-Type: application/json"
2
3
4
下面的例子中,使用了 foreground 级联删除:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
-H "Content-Type: application/json"
2
3
4
下面的例子中,使用 orphan 级联删除策略(不删除从属对象):
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
-H "Content-Type: application/json"
2
3
4
通过参数 --cascade
,kubectl delete 命令也可以选择不同的级联删除策略:
- --cascade=true 级联删除
- --cascade=false 不级联删除 orphan
下面的例子中,删除 ReplicaSet 时,将不删除其从属对象:
kubectl delete replicaset my-repset --cascade=false