Хук PreStop пода зависает в статусе Terminating и завершается только после terminationGracePeriodSeconds.

У меня есть ловушка preStop, определенная в ресурсе модуля с отслеживанием состояния, который запускает сценарий bash, чтобы не убить модуль, пока несколько процессов не завершат / отменит / не завершат работу в приложении. У меня не определено terminationGracePeriodSeconds. Теперь, когда я удаляю модуль, я проверил, что сценарий, являющийся частью ловушки preStop, выполняется должным образом. Но после добавления terminationGracePeriodSeconds на 10 минут, сначала bash-скрипт запускается как часть preStop-хука в течение нескольких минут, и предполагается, что он убивает pod. Но pod зависает в статусе TERMINATING и убивается только через 10 мин.

  1. Почему подвешивается стручок? Не удалось найти на это ответа.
  2. Когда terminationGracePeriodSeconds не был добавлен, поток работал должным образом, убивая модуль сразу после завершения скрипта или в течение 30 секунд, что является terminationGracePeriodSeconds. Но когда я добавил период отсрочки 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

person acm    schedule 20.09.2020    source источник
comment
Чего ты действительно хочешь? Если у вас есть terminationGracePeriodSeconds, но вы хотите быстро убить pod для тестирования, вы можете использовать kubectl delete pods ‹pod› --grace-period = 0 --force   -  person leo    schedule 21.09.2020
comment
Какую версию K8s вы используете? Куда ты бежишь (миникубе, кубеадм)? Можете ли вы обновить вопрос своим yaml, скриптом? По умолчанию terminationGracePeriodSeconds составляет не 30 минут, а 30 секунд.   -  person acid_fuji    schedule 21.09.2020
comment
Можете ли вы также обновить вопрос с помощью команды describe pod?   -  person acid_fuji    schedule 21.09.2020
comment
Томас, я исправил в посте время по умолчанию. Да, это 30 секунд, а не 30 минут. Спасибо. Я работаю в docker-desktop, а версия kubernetes - v1.15.5.   -  person acm    schedule 21.09.2020
comment
@acm Не могли бы вы обновить вопрос кодом вместо изображений?   -  person acid_fuji    schedule 21.09.2020
comment
@thomas Я обновил вопрос, добавив statefulset.yaml, а также результат описания модуля. Сценарий очень прост, он запускает несколько команд, чтобы проверить, запущены ли какие-либо процессы. Скрипт работал нормально. Модуль помечается как завершающий, как только я удаляю модуль, а затем я вижу, что скрипт внутри модуля успешно работает из-за ловушки preStop. Но как только скрипт запускается, под надо убивать. Но он ждет целых 10 минут прерывания GracePeriodSeconds. Вот в чем проблема. Кроме того, после terminationGracePeriodSeconds я вижу, что команда завершается с кодом выхода 137 в оболочке.   -  person acm    schedule 21.09.2020
comment
@thomas да, я обновил вопрос кодом и удалил изображения. Спасибо!   -  person acm    schedule 21.09.2020


Ответы (1)


preStop hook и terminationGracePeriodSeconds асинхронны. Это означает, что как только kubelet видит, что Pod был отмечен как завершающий, kubelet начинает процесс выключения локального Pod'а. Это означает, что если контейнер не завершается в течение льготного периода, будет отправлен сигнал SIGKILL, и контейнер будет уничтожен независимо от того, завершены ли команды в ловушке preStop.

  1. Когда terminationGracePeriodSeconds не был добавлен, поток работал должным образом, убивая модуль сразу после завершения скрипта или в течение 30 секунд, что является terminationGracePeriodSeconds. Но когда я добавил период отсрочки 10 минут или больше, он ждет до этого времени, а затем убивает модуль.

terminationGracePeriodSeconds льготный период добавляется всегда. По умолчанию это 30 секунд, как я уже упоминал в комментариях. Итак, что, если terminationGracePeriodSeconds меньше, чем время для завершения ловушки preStop?

Затем контейнер завершится в конце terminationGracePeriodSeconds, и обработчик preStop не будет завершен / запущен.

Когда terminationGracePeriodSeconds установлен на 600 секунд, скрипт перехвата preStop зависает (в настоящее время неясно, работал ли он когда-либо, поскольку он не был должным образом протестирован с terminationGracePeriodSeconds по умолчанию 30 секунд из-за упреждающего завершения). Это означает, что некоторые процессы неправильно обрабатывают SIGTERM, что в настоящее время не исправлено в ловушке preStop, а это означает, что контейнер вместо этого ожидает отправки SIGKILL после завершения 10-минутного terminationGracePeriod.

Если вы посмотрите здесь, то обнаружите, что даже если пользователь указал предварительную остановку перехватить, им нужен был SIGTERM nginx для корректного завершения работы.

В случае, если вы установили terminationGracePeriodSeconds на 10 минут, даже если ваша ловушка preStop успешно выполнилась, Kubernetes ждал 10 минут перед завершением вашего контейнера, потому что это именно то, что вы ему сказали. Сигнал завершения отправляется kubelet, но не передается приложению внутри контейнера. Наиболее частая причина этого заключается в том, что когда ваш контейнер запускает оболочку, которая запускает процесс приложения, сигнал может быть использован / прерван самой оболочкой, а не передан дочернему процессу. Кроме того, поскольку неясно, что делает ваш runscript.sh, трудно сделать какие-либо другие предложения относительно того, какие процессы не могут обрабатывать SIGTERM.

Что делать в этом случае? Возможные варианты более раннего завершения:

  • Уменьшение прекращения
  • Отправьте сигнал для постепенного завершения работы, убедившись, что SIGTERM обрабатывается правильно и все запущенные процессы ожидают завершения. Примеры того, как это сделать, можно найти здесь . Вы можете видеть, что они используют команду «выйти» для NGINX.

Дополнительную информацию о вас можно найти здесь. и здесь.

person acid_fuji    schedule 22.09.2020
comment
большое спасибо! После того, как я прошел по ссылкам, которые вы отправили, и реализовал несколько из них, мне это помогло. Одним из процессов является процесс nginix, и 1) перехват сигнала SIGTERM в файле начальной загрузки 2) добавление / usr / sbin / nginx -s quit в ловушку preStop действительно устранило проблему. - person acm; 23.09.2020
comment
Другой интересный блог об известной проблеме контейнеров nginx с SIGTERM: ubuntu.com/blog/ - person acm; 23.09.2020