kubernetes-handbook/concepts/garbage-collection.md

135 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 垃圾收集
Kubernetes 垃圾收集器的角色是删除指定的对象,这些对象曾经有但以后不再拥有 Owner 了。
**注意**:垃圾收集是 beta 特性,在 Kubernetes 1.4 及以上版本默认启用。
## Owner 和 Dependent
一些 Kubernetes 对象是其它一些的 Owner。例如一个 ReplicaSet 是一组 Pod 的 Owner。具有 Owner 的对象被称为是 Owner 的 *Dependent*。每个 Dependent 对象具有一个指向其所属对象的 `metadata.ownerReferences` 字段。
有时Kubernetes 会自动设置 `ownerReference` 的值。例如,当创建一个 ReplicaSet 时Kubernetes 自动设置 ReplicaSet 中每个 Pod 的 `ownerReference` 字段值。在 1.6 版本Kubernetes 会自动为一些对象设置 `ownerReference` 的值,这些对象是由 ReplicationController、ReplicaSet、StatefulSet、DaemonSet 和 Deployment 所创建或管理。
也可以通过手动设置 `ownerReference` 的值,来指定 Owner 和 Dependent 之间的关系。
这有一个配置文件`my-repset.yaml`,表示一个具有 3 个 Pod 的 ReplicaSet
```yaml
# k8s >= 1.16 使用下面注释 https://stackoverflow.com/questions/64412740/no-matches-for-kind-replicaset-in-version-extensions-v1beta1/64412990#64412990
# apiVersion: apps/v1
# k8s < 1.16 使用下面配置
apiVersion: extensions/v1beta1
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
```
如果创建该 ReplicaSet然后查看 Pod 的 metadata 字段,能够看到 OwnerReferences 字段:
```bash
kubectl create -f my-repset.yaml
kubectl get pods --output=yaml
```
输出显示了 Pod 的 Owner 是名为 my-repset 的 ReplicaSet
```yaml
apiVersion: v1
kind: Pod
metadata:
...
ownerReferences:
- apiVersion: extensions/v1beta1
controller: true
blockOwnerDeletion: true
kind: ReplicaSet
name: my-repset
uid: d9607e19-f88f-11e6-a518-42010a800195
...
```
## 控制垃圾收集器删除 Dependent
当删除对象时,可以指定是否该对象的 Dependent 也自动删除掉。自动删除 Dependent 也称为 *级联删除*。Kubernetes 中有两种 *级联删除* 的模式:*background* 模式和 *foreground* 模式。
如果删除对象时,不自动删除它的 Dependent这些 Dependent 被称作是原对象的 *孤儿*
### Background 级联删除
*background 级联删除* 模式下Kubernetes 会立即删除 Owner 对象,然后垃圾收集器会在后台删除这些 Dependent。
### Foreground 级联删除
*foreground 级联删除* 模式下,根对象首先进入 “删除中” 状态。在 “删除中” 状态会有如下的情况:
- 对象仍然可以通过 REST API 可见
- 会设置对象的 `deletionTimestamp` 字段
- 对象的 `metadata.finalizers` 字段包含了值 “foregroundDeletion”
一旦被设置为 “删除中” 状态,垃圾收集器会删除对象的所有 Dependent。垃圾收集器删除了所有 “Blocking” 的 Dependent对象的 `ownerReference.blockOwnerDeletion=true`)之后,它会删除 Owner 对象。
注意,在 “foreground 删除” 模式下Dependent 只有通过 `ownerReference.blockOwnerDeletion` 才能阻止删除 Owner 对象。在 Kubernetes 1.7 版本中将增加 admission controller基于 Owner 对象上的删除权限来控制用户去设置 `blockOwnerDeletion` 的值为 true所以未授权的 Dependent 不能够延迟 Owner 对象的删除。
如果一个对象的`ownerReferences` 字段被一个 Controller例如 Deployment 或 ReplicaSet设置`blockOwnerDeletion` 会被自动设置,没必要手动修改这个字段。
### 设置级联删除策略
通过为 Owner 对象设置 `deleteOptions.propagationPolicy` 字段可以控制级联删除策略。可能的取值包括“orphan”、“Foreground” 或 “Background”。
对很多 Controller 资源,包括 ReplicationController、ReplicaSet、StatefulSet、DaemonSet 和 Deployment默认的垃圾收集策略是 `orphan`。因此,除非指定其它的垃圾收集策略,否则所有 Dependent 对象使用的都是 `orphan` 策略。
**注意**:本段所指的默认值是指 REST API 的默认值,并非 kubectl 命令的默认值kubectl 默认为级联删除,后面会讲到。
下面是一个在后台删除 Dependent 对象的例子:
```bash
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
-H "Content-Type: application/json"
```
下面是一个在前台删除 Dependent 对象的例子:
```bash
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
-H "Content-Type: application/json"
```
下面是一个孤儿 Dependent 的例子:
```bash
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
-H "Content-Type: application/json"
```
kubectl 也支持级联删除。 通过设置 `--cascade` 为 true可以使用 kubectl 自动删除 Dependent 对象。设置 `--cascade` 为 false会使 Dependent 对象成为孤儿 Dependent 对象。`--cascade` 的默认值是 true。
下面是一个例子,使一个 ReplicaSet 的 Dependent 对象成为孤儿 Dependent
```bash
kubectl delete replicaset my-repset --cascade=false
```
## 已知的问题
- 1.7 版本,垃圾收集不支持 [自定义资源](https://kubernetes.io/docs/concepts/api-extension/custom-resources/),比如那些通过 CustomResourceDefinition 新增,或者通过 API server 聚集而成的资源对象。
- [其它已知的问题](https://github.com/kubernetes/kubernetes/issues/26120)。