Привет,
Я использую Kubernetes для развертывания своего приложения на Python, Kubernetes предоставляет livenessProbe и readinessProbe, см. Здесь .
Как я могу проверить, живы ли мои сельдерея или рабочий сельдерей?
PID не является решением, потому что его нельзя использовать, например, для обнаружения тупиковой ситуации.
Заранее спасибо за вашу помощь,
С наилучшими пожеланиями,
У 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, который бы время от времени очищал очереди.
Самый полезный комментарий
celery inspect ping
действительно работает, но вам нужноbash
для замены переменной среды следующим образом: