吊舱PreStop挂钩处于挂起状态,仅在终止后挂起GracePeriodSeconds

时间:2020-09-20 20:56:45

标签: kubernetes sigterm

我在statefulset pod资源中定义了一个preStop钩子,该钩子运行bash脚本,以确保在应用程序中很少有进程完成/取消/错误之前,不要杀死pod。我没有定义terminationGracePeriodSeconds。现在,当我删除吊舱时,我测试了作为preStop挂钩一部分的脚本是否按预期运行。但是在添加了terminationGracePeriodSeconds 10分钟之后,首先bash脚本作为preStop hook的一部分成功运行了几分钟,并且应该杀死该pod。但是吊舱处于TERMINATING状态,只有10分钟后才会被杀死。

  1. 为什么吊舱是吊着的?无法为此找到答案。
  2. 未添加terminationGracePeriodSeconds时,该流正在按预期方式工作,方法是在完成脚本后或在30秒内(即terminationGracePeriodSeconds)杀死Pod。但是,当我添加10分钟或更长时间的宽限期时,它会等到那个时候再杀死吊舱。

如何解决此问题。有没有一种方法可以将SIGTERM或SIGKILL发送到吊舱。有任何想法吗?预先谢谢你!

STATEFULSET.YAML

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: appx
  name: appx
spec:
  serviceName: appx
  replicas: 1
  updateStrategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: appx
  template:
    metadata:
      labels:
        app: appx
    spec:
      #removed some of the sensitive info
      terminationGracePeriodSeconds: 600
      containers:
        - image: appx
          imagePullPolicy: IfNotPresent
          name: appx
          lifecycle:
            preStop:
              exec:
                command: ["/bin/sh", "-c", "sleep 30 && bash /var/tmp/runscript.sh; sleep10"]

KUBECTL DESCRIBE POD


**kubectl describe pod appx**
Name:           appx
Namespace:      default
Priority:       0
Node:           docker-desktop/192.168.65.3
Start Time:     Mon, 21 Sep 2020 07:30:55 -0500
Labels:         app=appx
Annotations:    <none>
Status:         Running
IP:             x.x.x.x
Controlled By:  StatefulSet/appx
Containers:
  appx:
    Container ID:   docker://dfdgfgfgfgfgfgfg
    Image:          appx
    Image ID:       docker://sha256:49dfgfgfgfgfgfgfgfgfg96a6fc
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 21 Sep 2020 07:30:56 -0500
    Ready:          True
    Restart Count:  0
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  data:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
    SizeLimit:  <unset>
  appx-token-xj6q9:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  appx-token-fhfdlf
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age    From                     Message
  ----    ------     ----   ----                     -------
  Normal  Scheduled  2m43s  default-scheduler        Successfully assigned default/appx to docker-desktop
  Normal  Pulled     2m42s  kubelet, docker-desktop  Container image "appx" already present on machine
  Normal  Created    2m42s  kubelet, docker-desktop  Created container appx
  Normal  Started    2m42s  kubelet, docker-desktop  Started container appx

1 个答案:

答案 0 :(得分:0)

preStop钩子和terminationGracePeriodSeconds是异步的。这意味着,只要kubelet看到Pod已被标记为终止,kubelet就会立即开始本地Pod关闭过程。这意味着如果容器在宽限期内没有终止,则无论preStop挂钩中的命令是否完成,SIGKILL信号都会被发送,并且容器将被杀死。

  1. 未添加terminationGracePeriodSeconds时,该流正在按预期方式工作,方法是在完成脚本后立即杀死该pod 或在30秒内终止GracePeriodSeconds。但当 我添加了10分钟或更长时间的宽限期,它一直等到 时间,然后杀死豆荚。
始终添加

terminationGracePeriodSeconds宽限期。正如我在评论中已经提到的,它默认为30秒。那么,如果terminationGracePeriodSeconds少于完成preStop挂钩的时间呢?

然后,容器将在terminationGracePeriodSeconds的结尾处终止,并且preStop钩子将不会完成/运行。

将TerminationGracePeriodSeconds设置为600s时,preStop挂钩脚本将挂起(目前尚不清楚它是否能正常工作,因为由于抢占式终止而未使用默认的30s terminationGracePeriodSeconds进行正确测试)。这意味着某些进程无法正确处理SIGTERM,而当前在preStop挂钩中尚未对其进行纠正,这意味着容器将在等待10分钟终止GracePeriod结束后等待发送SIGKILL。

如果您查看here,您会发现,即使用户指定了preStop挂钩,他们也需要对Nginx进行SIGTERM正常关闭。

在您将terminationGracePeriodSeconds设置为10分钟的情况下,即使您成功执行了preStop挂钩,Kubernetes仍在终止容器之前等待了10分钟,因为这正是您告诉他的操作。终止信号是通过kubelet发送的,但没有传递到容器内部的应用程序。最常见的原因是,当您的容器运行运行应用程序进程的外壳程序时,该信号可能会被外壳程序本身消耗/中断,而不是传递给子进程。另外,由于不清楚您的runscript.sh在做什么,因此很难对哪些进程无法处理SIGTERM提出其他建议。

在这种情况下您可以做什么?提前结束的选项是:

  • 减少terminationGracePeriodSeconds
  • 通过确保正确处理SIGTERM,并且所有正在运行的进程都在侦听终止,发送信号以正常关闭。 here是如何执行此操作的示例。您可以看到他们对NGINX使用了“退出”命令。

有关您的更多信息,可以找到出色的文章herehere

相关问题