加入收藏 | 设为首页 | 会员中心 | 我要投稿 宁德站长网 (https://www.0593zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 云计算 > 正文

Kubernetes Pod 删除操作源码分析

发布时间:2022-04-15 14:59:26 所属栏目:云计算 来源:互联网
导读:比如现在我有一个更新策略为 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-
  比如现在我有一个更新策略为 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
  1.
  2.
  3.
  4.
  5.
  在删除之前在另外一个终端观察应用状态:
 
  复制
  ☸ ➜ 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

  接收到删除请求的处理器位于代码 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 状态了。
 
  优雅删除
  由于 Pod 中涉及到其他很多资源,比如 sandbox 容器、volume 卷等等,在删除后都需要进行回收,而删除 Pod 最终也是去删除对应的容器,这个就需要 Pod 所在节点的 kubelet 来完成清理了。kubelet 首先同样会一直 watch 我们的 Pod,当 Pod 的删除时间更新后,自然就会接收到事件,然后进行相应的清理工作。
 
  kubelet 对 Pod 的处理主要在 syncLoop 函数中,会去调用和事件相关的处理函数 syncLoopIteration,代码位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kubelet.go#L2040-L2079 中,如下所示:

  dispatchWork 方法会调用 UpdatePod 函数对 Pod 进行删除,代码位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/pod_workers.go#L540-L765,在该函数中会通过一个 channel 传递 Pod 信息,在一个 goroutine 中调用 managePodLoop 函数进行处理,该函数中会调用 syncTerminatingPod/syncPod 方法来进行删除操作。
 
  最终都会调用 killPod 函数去执行删除 Pod:
 
  killPod 函数中会调用容器运行时去停止该 Pod 中的容器,代码位于https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kubelet_pods.go#L856-L868:

  容器运行时的 KillPod 方法位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kuberuntime/kuberuntime_manager.go#L969-L998,如下所示:
 
  killPodWithSyncResult 方法中首先调用函数 killContainersWithSyncResult 杀掉所有运行的容器,然后删除 Pod 的 sandbox。
  在该函数中,利用多个 goroutine 来对 Pod 中的每一个容器进行删除,删除容器的方法是 killContainer,在该函数中首先会执行 pre-stop 这个 hooks(如果存在的话),然后才停止容器,代码位于 https://github.com/kubernetes/kubernetes/blob/v1.22.8/pkg/kubelet/kuberuntime/kuberuntime_container.go#L660-L736。
 
  其中 TerminationGracePeriodSeconds 可以在资源清单文件中进行设置,默认为 30 秒,这个时间是,给 Pod 发出关闭指令后会给应用发送 SIGTERM 信号,程序只需要捕获 SIGTERM 信号并做相应处理即可。也就是 Pod 接收到 SIGTERM 信号后,应用能够优雅关闭的时间。该时间是由 apiserver 设置的,前面已经分析过。
 
  如果配置了 pre-stop hook 并且还有足够的时间,则会执行该 hook,pre-stop 主要是为了业务在容器删除前前,能够优雅的停止,比如资源回收等操作:
 
  容器删掉后回到前面的 killPodWithSyncResult 函数中,接下来就会去调用运行时服务的 StopPodSandbox 函数停止 sandbox 容器,也就是 pause 容器。
 
  到这里 kubelet 就完成了对 Pod 的优雅删除,但是这并没有结束。
 
  比如会判断是否还有容器在运行、volumes 是否还没有清理、pod cgroup 还没清空等等,如果 canBeDeleted 返回 true,则表示 pod 已经优雅的停止了,那么这个时候就可以向 apiserver 发送 Delete 请求,再次删除 Pod 了。
 
  不过这一次的设置的 GracePeriodSeconds 为 0,表示要强制删除 Pod 了,到这里 apiserver 会再次收到 DELETE 请求,与第一次不同的是,这次是强制删除 Pod,会去 etcd 中删除 Pod 对象了。
 
  这个时候 kubelet 会接受到 REMOVE 的事件,调用 HandlePodRemoves 函数去进行处理:
 
  首先会去调用 deletePod 函数去停掉关联的 pod worker,然后还会调用 probeManager 去移除 Pod 相关的探针 prober worker,到这里就表示 Pod 彻底从节点上删除了。

(编辑:宁德站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!