Celery: [K8S] livenessProbe и готовностьProbe для сельдерея и рабочих

Созданный на 8 июн. 2017  ·  31Комментарии  ·  Источник: celery/celery

Привет,

Я использую Kubernetes для развертывания своего приложения на Python, Kubernetes предоставляет livenessProbe и readinessProbe, см. Здесь .

Как я могу проверить, живы ли мои сельдерея или рабочий сельдерей?
PID не является решением, потому что его нельзя использовать, например, для обнаружения тупиковой ситуации.

Заранее спасибо за вашу помощь,

С наилучшими пожеланиями,

Deployment Question Needs Verification ✘

Самый полезный комментарий

celery inspect ping действительно работает, но вам нужно bash для замены переменной среды следующим образом:

        livenessProbe:
          exec:
            # bash is needed to replace the environment variable
            command: [
              "bash",
              "-c",
              "celery inspect ping -A apps -d celery@$HOSTNAME"
            ]
          initialDelaySeconds: 30  # startup takes some time
          periodSeconds: 60  # default is quite often and celery uses a lot cpu/ram then.
          timeoutSeconds: 10  # default is too low

Все 31 Комментарий

У Celery есть API для
Стручок следует считать живым, если работник Celery посылает сердцебиение .
Под следует считать готовым, если работник отправил событие worker-online .

Если у вас есть особые проблемы или пожелания по функциям, откройте отдельный вопрос.

Это сработает?

readinessProbe:
          exec:
            command:
            - "/bin/sh"
            - "-c"
            - "celery -A path.to.app status | grep -o ': OK'"
          initialDelaySeconds: 30
          periodSeconds: 10

@ 7wonders Сначала вам нужно извлечь имя узла сельдерея. Этот readinessProbe завершится ошибкой, если какой-либо экземпляр сельдерея выйдет из строя, чего вы не хотите.

@thedrow Хм, я думаю, что на самом деле он будет успешным, даже если фактический узел вышел из строя, но другой в порядке, что также не является отличным результатом.

Выглядит как

/bin/sh -c 'exec celery -A path.to.app inspect ping -d celery@$HOSTNAME' достаточно для проверки готовности и проверяет только один узел.

Помните, что в некоторых приложениях выполнение этой команды может занять несколько секунд при полной загрузке ЦП, а по умолчанию Kubernetes запускает ее каждые 10 секунд.

Таким образом, гораздо безопаснее иметь высокий период в секундах (у нас установлено значение 300).

@redbaron сработала ли эта команда? Если работает, то каковы настройки для проверки живучести и готовности?

По какой-то причине эта проверка готовности нас далеко не устраивает. Инспектируемый отвечает недетерминированно, без нагрузки на наш кластер. Запускаем формат так:

сельдерей проверить пинг -b " redis: // archii-redis-master : 6379" -d сельдерей @ archii-task-crawl-integration-7d96d86b9d-jwtq7

И при нормальном времени пинга (10 секунд) наш кластер полностью уничтожается процессором, который требуется сельдерею.

~ Я использую это для живости с интервалом 30 секунд: sh -c celery -A path.to.app status | grep "${HOSTNAME}:.*OK" ~
Я использую это для живости с интервалом 30 секунд: sh -c celery -A path.to.app inspect ping --destination celery@${HOSTNAME}
Кажется, это не вызывает дополнительной нагрузки, у меня есть парк из более чем 100 рабочих.

Зонды готовности не нужны, сельдерей никогда не используется в сервисе. Я просто установил minReadySeconds: 10 который достаточно хорош для задержки запуска воркера при скользящем развертывании, но он, очевидно, зависит от времени запуска Celery для вашего проекта, поэтому изучите журналы и установите соответствующие настройки.

Зонды готовности по-прежнему полезны, даже если они не используются в службе. В частности, когда вы выполняете развертывание воркеров и хотите убедиться, что развертывание прошло успешно, вы обычно используете kubectl rollout status deployment . Без проверки готовности мы развернули плохой код, который не запускал сельдерей и не знал об этом.

Мое решение было:

readinessProbe:
  exec:
    command:
      [
        "/usr/local/bin/python",
        "-c",
        "\"import os;from celery.task.control import inspect;from <APP> import celery_app;exit(0 if os.environ['HOSTNAME'] in ','.join(inspect(app=celery_app).stats().keys()) else 1)\""
      ]

Остальные вроде не работают 🤷‍♂️

Спасибо @yardensachs!
Потратьте много времени на отладку, что не так с другими решениями, но никак
Похоже, что команда celery inspect ping не возвращает exit (0) или что-то в этом роде

celery inspect ping действительно работает, но вам нужно bash для замены переменной среды следующим образом:

        livenessProbe:
          exec:
            # bash is needed to replace the environment variable
            command: [
              "bash",
              "-c",
              "celery inspect ping -A apps -d celery@$HOSTNAME"
            ]
          initialDelaySeconds: 30  # startup takes some time
          periodSeconds: 60  # default is quite often and celery uses a lot cpu/ram then.
          timeoutSeconds: 10  # default is too low

хорошо знать

Мы закончили тем, что извлекли сельдерей и проверяли пинг из наших зондов живучести, потому что мы обнаружили, что при более высокой нагрузке пинг просто зависал на несколько минут, даже если задания выполнялись нормально и не было отставания. У меня есть ощущение, что это как-то связано с использованием eventlet, но мы продолжаем его изучать.

@WillPlatnick Этого не произойдет с 5.0, потому что Celery будет асинхронным, поэтому будет зарезервирована емкость для управляющих сопрограмм.

У меня проблемы с inspect ping порождением несуществующих / зомби-процессов:

root      2296  0.0  0.0      0     0 ?        Z    16:04   0:00 [python] <defunct>
root      2323  0.0  0.0      0     0 ?        Z    16:05   0:00 [python] <defunct>
...

Кто-нибудь еще сталкивается с этим? Нет аргумента --pool для принудительного выполнения одного процесса.

Могу я спросить, что вы используете вместо celery inspect ping @WillPlatnick? Мы столкнулись с аналогичной проблемой, когда зонд выходил из строя при большой нагрузке.

@mcyprian Мы избавились от зонда

мы встречаем ту же проблему с процессором с брокером Redis

Кто-нибудь нашел решение?
Мы также экспериментировали с планированием «debug_task» для очереди, имя которой мы основали на имени контейнера. Проблема в том, что сейчас у нас в RabbitMQ тонны старых очередей.

Имейте в виду, что использование

sh -c celery -A path.to.app status | grep "${HOSTNAME}:.*OK"

как предлагается на https://github.com/celery/celery/issues/4079#issuecomment -437415370, приведет к массовым сообщениям об ошибках на rabbitmq, см. https://github.com/celery/celery/issues/4355#issuecomment - 578786369

Я думаю, что нашел способ уменьшить использование ЦП при проверке пинга.

сельдерей -b amqp: // пользователь: pass @ rabbitmq : 5672 / vhost проверить пинг

Отсутствие загрузки конфигураций сельдерея с использованием -A path.to.celery определенно помогло с использованием процессора,
может кто-нибудь проверить.

Я думаю, что нашел способ уменьшить использование ЦП при проверке пинга.

сельдерей -b amqp: // пользователь: pass @ rabbitmq : 5672 / vhost проверить пинг

Отсутствие загрузки конфигураций сельдерея с использованием -A path.to.celery определенно помогло с использованием процессора,
может кто-нибудь проверить.

Хороший! Это намного лучше, чем с загруженным приложением.
Но мы по-прежнему получаем огромные накладные расходы на запуск процесса python + импорт сельдерея. Я все еще рекомендую высокий период.

Привет,
celery inspect ping -A app.tasks -d celery @ $ HOSTNAME выдает мне «Ошибка: трансляция не поддерживается транспортом sqs».
Я использую SQS в качестве брокера, это означает, что команда «проверить» / «статус» не будет работать с SQS?

Мы обнаружили, что при масштабировании все функции удаленного управления вызывают резкий скачок загрузки ЦП экземпляра Redis из-за набора команд для клавиши kombu.pidbox , поэтому мы не можем использовать ping, статус или проверку, как они есть. все используют удаленное управление и пытаются отключить его для производственного использования.

Мне кажется, что наличие специальной очереди на проверку работоспособности - правильный путь, но я совсем не уверен

У кого-нибудь есть другое направление, не связанное с дистанционным управлением для проверки работоспособности?

Мы уже некоторое время успешно используем выделенные очереди проверки работоспособности с политиками выселения RabbitMQ (очереди удаляются автоматически), и мы довольны решением. В основном потому, что эта проверка действительно проверяет, что рабочий обработал задачу и завершил ее. С тех пор, как мы его представили, у нас больше не было проблем с зависшими рабочими.

@bartoszhernas не могли бы поделиться кодом для этого? вы ставите их в очередь, а рабочие забирают их?

хотелось бы увидеть код + раздел проверки живучести

Привет, код действительно прост:

В Kubernetes я указываю имя очереди на основе POD_NAME и передаю его скрипту livecheck:

        livenessProbe:
          initialDelaySeconds: 120
          periodSeconds: 70
          failureThreshold: 1
          exec:
            command:
            - bash 
            - "-c" 
            - |
              python celery_liveness_probe.py $LIVENESS_QUEUE_NAME
        env:
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name

        - name: LIVENESS_QUEUE_NAME
          value: queue-$(MY_POD_NAME)

(вам нужно использовать bash -c, потому что Kubernetes не расширяет ENV при попытке передать его как команду напрямую)

тогда celery_liveness_probe.py просто настраивает Django, чтобы иметь возможность использовать Celery и планировать задачу в очереди POD

# encoding: utf-8
from __future__ import absolute_import, unicode_literals

import os
import sys

if __name__ == "__main__":
    import django

    sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ahoy.archive.settings")
    django.setup()
    from ahoy.archive.apps.eventbus.service import eventbus_service

    exit(0 if eventbus_service.health_check(sys.argv[1] if sys.argv and len(sys.argv) > 1 else None) else 1)

функция проверки работоспособности отправляет задачу и ждет результатов

    def health_check(self, queue_name: Optional[str] = None) -> bool:
        event = self.celery.send_task(
            AhoyEventBusTaskName.LIVENESS_PROBE,
            None,
            queue=queue_name or self.origin_queue,
            ignore_result=False,
            acks_late=True,
            retry=False,
            priority=255
        )

        try:
            is_success = event.get(timeout=10)
        except (celery.exceptions.TimeoutError, AttributeError):
            is_success = False

        return is_success

Итак, в основном: отправьте задачу, и если она вернет результаты, то работник здоров. Если рабочий застрял (случалось много раз), то задачи никогда не заканчиваются, модуль перезапускается, и все возвращается в нормальное состояние.

Единственное предостережение - вам нужно иметь дело со старыми очередями, с RabbitMQ это просто, мы просто настроили политику истечения срока для очереди.
https://www.rabbitmq.com/ttl.html#queue -ttl

@bartoszhernas спасибо, что поделились кодом!

как вы сказали, мои очереди динамические, и мы используем Redis, поэтому нам действительно нужно найти способ справиться с истечением срока действия имен очередей в Redis

Да, у нас похожая проблема с BullMQ с Redis. Моя идея - написать CronJob для Kubernetes, который бы время от времени очищал очереди.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги