掘金 后端 ( ) • 2024-05-02 17:27

前言

这是笔者发的一个stackoverflow,可以看采纳的答案,小哥讲的很详细,笔者也会在下面记录。

问题

Kubernetes 版本和Java Cient:

Kubernetes version: Kubernetes v1.27.3
java client maven:
<dependency>
    <groupId>io.kubernetes</groupId>
    <artifactId>client-java</artifactId>
    <version>18.0.1</version>
</dependency>

测试获取指定节点下面Pod信息列表出现了问题-------关闭此节点的kubelet后,pod开始重新到可用节点,此节点下面pod进入Terminating状态,但是后端代码获取到节点的状态居然是Running?

kubectl get po -n my-namespace -o wide

# 调度后新pod
nginx1-74499f547c-gbdzf                     1/1     Running       0              1m   10.244.0.55   kylin-master     <none>           <none>
# 旧pod,因为kubelet关闭,无法删除该pod
# 在kubelet可用之前,会一直处于Terminating状态
nginx1-74499f547c-xndkm                     1/1     Terminating   0              8h      10.244.2.24   kylin-worker02   <none>           <none>
CoreV1Api coreV1Api = new CoreV1Api();
V1PodList v1PodList;
try{
    v1PodList = coreV1Api.listNamespacedPod(tenxOpenApiConfig.getTeamSpace(), null, null, null, info, null, null, null, null, null, null);
    for (V1Pod item : v1PodList.getItems()) {
       // .....
    }
} 
// ......

debug一看, 什么,状态居然是Running 在这里插入图片描述 于是寻找解决办法,究其原因,还得看文档。

解决方案

首先, Terminating 不是Kubernetes PodsContainers的状态,kubectl命令的展示状态基于Pod对象中的多个字段(而不仅仅是Pod.status.phase,如Pod.metadata.deleteTimestamp)。

当一个pod由于一些原因(例如节点故障或手动删除)被删除时,并不会立即删除,因为这样可能会破坏内部运行的应用程序,因此kubernetes首先向pod内的容器发出TERM(又名SIGTERM)信号,给它一些时间来让其正常终止。在一段时间后(在pod.spec.terminationGracePeriodSeconds中定义,默认为30),如果容器尚未终止,则会直接杀死。在这期间,容器实际上正在运行,因此Pod.status.phase显示pod状态是Running。然而,当pod被删除时,kubernetes会将pod.metadata.deleteionTimestamp设置为发出删除信号的时间。 Kuectl可以检测到这个属性,并在看到这一点时将Pod的状态显示为Terminating

官方文档有关于这个的介绍

当一个 Pod 被删除时,执行一些 kubectl 命令会展示这个 Pod 的状态为 Terminating(终止)。 这个 Terminating 状态并不是 Pod 阶段之一。 Pod 被赋予一个可以体面终止的期限,默认为 30 秒。 你可以使用 --force 参数来强制终止 Pod。

相关Api介绍

  1. metadata.deletionGracePeriodSeconds和metadata.deletionTimestamp

  2. spec.terminationGracePeriodSeconds