<aside> ⏰ 本文介绍了删除 Pod 的完整流程

</aside>

比如现在我有一个更新策略为 Recreate 的应用,然后执行删除命令,如下所示:

 ➜ kubectl get pods
NAME                    READY   STATUS    RESTARTS        AGE
minio-875749785-sv5ns   1/1     Running   1 (2m52s ago)   42h
 ➜ kubectl delete pod minio-875749785-sv5ns
pod "minio-875749785-sv5ns" deleted

在删除之前在另外一个终端观察应用状态:

 ➜ kubectl get pods -w
NAME                    READY   STATUS              RESTARTS         AGE
minio-875749785-sv5ns   1/1     Running             1 (2m46s ago)   42h
minio-875749785-sv5ns   1/1     Terminating         1 (2m57s ago)   42h
minio-875749785-h2j2b   0/1     Pending             0               0s
minio-875749785-h2j2b   0/1     Pending             0               0s
minio-875749785-h2j2b   0/1     ContainerCreating   0               0s
minio-875749785-sv5ns   0/1     Terminating         1 (2m59s ago)   42h
minio-875749785-sv5ns   0/1     Terminating         1 (2m59s ago)   42h
minio-875749785-sv5ns   0/1     Terminating         1 (2m59s ago)   42h
minio-875749785-h2j2b   0/1     Running             0               17s
minio-875749785-h2j2b   1/1     Running             0               30s

从上面的过程可以看到当我们执行 kubectl delete 命令后 Pod 变成了 Terminating 状态,然后才消失。接下来我们会从代码角度来介绍下删除 Pod 的整个流程。

删除状态

我们可以根据 kubectl 操作后看到的状态来进行跟踪,上面的格式化结果是通过代码 **https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/printers/internalversion/printers.go#L88-L102** 实现的,如下所示:

对于 Pod 的输出结果是通过 printPod 函数获取的,代码位于:**https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/printers/internalversion/printers.go#L756-L840**,其中有一段代码提到了 Terminating 值,是在 pod.DeletionTimestamp != nil 的情况下变成该状态的,如下所示:

也就是说当执行删除操作的时候,会设置 Pod 的 DeletionTimestamp 属性,这个时候就会显示成 Terminating 状态。

当执行删除操作的时候,会向 apiserver 发送一次 DELETE 请求:

I0408 11:25:33.002155   42938 round_trippers.go:435] curl -v -XDELETE  -H "Content-Type: application/json" -H "User-Agent: kubectl/v1.22.7 (darwin/amd64) kubernetes/b56e432" -H "Accept: application/json" '<https://192.168.0.111:6443/api/v1/namespaces/default/pods/minio-875749785-sv5ns>'
I0408 11:25:33.037245   42938 round_trippers.go:454] DELETE <https://192.168.0.111:6443/api/v1/namespaces/default/pods/minio-875749785-sv5ns> 200 OK in 35 milliseconds

接收到删除请求的处理器位于代码 **https://github.com/kubernetes/kubernetes/blob/v1.22.8/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go#L986**,如下所示:

在 BeforeDelete 函数中判断是否需要优雅删除,判断的标准是 DeletionGracePeriodSeconds 值是否为 0,不为零则认为是优雅删除,apiserver 不会立即将这个对象从 etcd 中删除,否则直接删除。对于 Pod 而言,默认 DeletionGracePeriodSeconds 为 30 秒,因此这里不会被立刻删除掉,而是将 DeletionTimestamp 设置为当前时间,DeletionGracePeriodSeconds 设置为默认值 30 秒。 代码位于 **https://github.com/kubernetes/kubernetes/blob/v1.22.8/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go#L93-L159**,在该函数中会设置 DeletionTimestamp 的值,如下所示:

上面的代码验证了当执行删除操作的时候,apiserver 会先设置 Pod 的 DeletionTimestamp 属性为当前时间加上优雅删除宽限时长的时间点,设置了该属性后,我们客户端格式化过后看到的就是 Terminating 状态了。