Celery: [K8S] livenessProbe dan readinessProbe untuk irama seledri dan pekerja

Dibuat pada 8 Jun 2017  ·  31Komentar  ·  Sumber: celery/celery

Hai,

Saya menggunakan Kubernetes untuk menerapkan aplikasi python saya, Kubernetes menyediakan livenessProbe dan readinessProbe, lihat di sini .

Bagaimana saya dapat memeriksa apakah seledri saya berdetak atau pekerja seledri masih hidup dan dalam keadaan yang benar?
PID bukanlah solusi karena tidak dapat digunakan untuk menangkap deadlock misalnya.

Terima kasih sebelumnya atas bantuan Anda,

Salam Hormat,

Deployment Question Needs Verification ✘

Komentar yang paling membantu

celery inspect ping berfungsi, tetapi Anda memerlukan bash untuk mengganti variabel lingkungan seperti ini:

        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

Semua 31 komentar

Celery memiliki API pemantauan yang dapat Anda gunakan.
Pod harus dianggap hidup jika pekerja Celery mengirimkan detak jantung .
Sebuah pod harus dianggap siap jika pekerja telah mengirim acara pekerja-online .

Jika Anda memiliki masalah khusus atau permintaan fitur, buka masalah terpisah.

Apakah ini akan berhasil?

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

@ 7wonders Anda harus mengekstrak nama simpul seledri terlebih dahulu. ReadinessProbe ini akan gagal jika ada contoh seledri yang gagal dan bukan itu yang Anda inginkan.

@thedrow Hmm, saya pikir sebenarnya itu akan berhasil bahkan jika node yang sebenarnya telah gagal tetapi yang lain baik-baik saja yang juga bukan hasil yang bagus.

Seperti

/bin/sh -c 'exec celery -A path.to.app inspect ping -d celery@$HOSTNAME' cukup baik untuk memeriksa kesiapan dan memverifikasi hanya satu node.

Berhati-hatilah karena di beberapa aplikasi, menjalankan perintah ini dapat memakan waktu beberapa detik menggunakan CPU penuh DAN default kubernetes adalah menjalankannya setiap 10 detik.

Dengan demikian, jauh lebih aman untuk memiliki periodSeconds tinggi (periode kami disetel ke 300).

@redbaron apakah perintah itu bekerja untuk Anda? Jika berhasil, lalu apa saja pengaturan untuk masalah keaktifan dan kesiapan?

Untuk beberapa alasan, pemeriksaan kesiapan ini sama sekali tidak memuaskan bagi kami. Inspect merespons secara non-deterministik tanpa beban di cluster kami. Kami menjalankan format seperti ini:

seledri periksa ping -b " redis: // archii-redis-master : 6379" -d celery @ archii-task-crawl-integration-7d96d86b9d-jwtq7

Dan dengan waktu ping normal (10 detik), cluster kita benar-benar mati oleh CPU yang dibutuhkan oleh seledri.

~ Saya menggunakan ini untuk kehidupan dengan interval 30-an: sh -c celery -A path.to.app status | grep "${HOSTNAME}:.*OK" ~
Saya menggunakan ini untuk kehidupan dengan interval 30-an: sh -c celery -A path.to.app inspect ping --destination celery@${HOSTNAME}
Sepertinya tidak menimbulkan beban tambahan, saya menjalankan armada lebih dari 100 pekerja.

Pemeriksaan kesiapan tidak diperlukan, Celery tidak pernah digunakan dalam layanan. Saya baru saja menetapkan minReadySeconds: 10 yang cukup baik untuk menunda startup pekerja dalam menjalankan Deployments, tetapi ini jelas tergantung pada waktu startup Celery untuk proyek Anda, jadi periksa log dan atur sesuai.

Probe kesiapan masih berguna meskipun tidak digunakan dalam layanan. Khususnya, saat Anda melakukan penerapan pekerja dan ingin memastikan penerapan berhasil, Anda biasanya menggunakan kubectl rollout status deployment . Tanpa uji kesiapan, kami telah menerapkan kode buruk yang tidak memulai seledri dan tidak mengetahuinya.

Solusi saya adalah:

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)\""
      ]

Yang lain sepertinya tidak berfungsi 🤷‍♂️

Terima kasih @yardensachs!
Luangkan banyak waktu untuk men-debug apa yang salah dengan solusi lain, tetapi tidak mungkin
Sepertinya celery inspect ping perintah tidak mengembalikan exit (0) atau sesuatu seperti itu

celery inspect ping berfungsi, tetapi Anda memerlukan bash untuk mengganti variabel lingkungan seperti ini:

        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

senang mendengarnya

Kami akhirnya merobek seledri memeriksa ping dari probe kehidupan kami karena kami menemukan bahwa di bawah beban yang lebih berat, ping hanya akan bertahan selama beberapa menit pada suatu waktu meskipun pekerjaan sedang diproses dengan baik dan tidak ada backlog. Saya merasa itu ada hubungannya dengan menggunakan eventlet, tapi kami terus memeriksanya.

@WillPlatnick Itu tidak akan terjadi dengan 5.0 karena Celery akan asinkron sehingga akan ada kapasitas yang dicadangkan untuk coroutine kontrol.

Saya mengalami masalah dengan proses inspect ping pemijahan mati / zombie:

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>
...

Adakah orang lain yang mengalami ini? Tidak ada argumen --pool untuk memaksa eksekusi proses tunggal.

Bolehkah saya bertanya apa yang Anda gunakan selain celery inspect ping @WillPlatnick? Kami mengalami masalah serupa dengan probe gagal karena beban berat.

@mcyprian Kami menyingkirkan probe kehidupan. Naluri saya memberi tahu saya bahwa itu ada hubungannya dengan eventlet, tetapi kami belum menjadikannya prioritas untuk mengetahuinya.

kami menemui masalah CPU yang sama dengan broker Redis

Adakah yang menemukan solusi?
Kami juga bereksperimen dengan penjadwalan "debug_task" pada antrian yang namanya kami berdasarkan nama penampung. Masalahnya adalah kami memiliki banyak antrian lama di RabbitMQ sekarang

Perlu diketahui bahwa menggunakan

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

seperti yang disarankan di https://github.com/celery/celery/issues/4079#issuecomment -437415370 akan menyebabkan laporan kesalahan besar-besaran di rabbitmq, lihat https://github.com/celery/celery/issues/4355#issuecomment - 578786369

Saya rasa saya telah menemukan cara untuk mengurangi penggunaan CPU untuk memeriksa ping.

seledri -b amqp: // user: pass @ rabbitmq : 5672 / vhost periksa ping

Tidak memuat konfigurasi seledri menggunakan -A path.to.celery tentu terbantu dengan penggunaan cpu,
dapatkah seseorang memverifikasi.

Saya rasa saya telah menemukan cara untuk mengurangi penggunaan CPU untuk memeriksa ping.

seledri -b amqp: // user: pass @ rabbitmq : 5672 / vhost periksa ping

Tidak memuat konfigurasi seledri menggunakan -A path.to.celery tentu terbantu dengan penggunaan cpu,
dapatkah seseorang memverifikasi.

Bagus! Ini jauh lebih baik daripada dengan aplikasi yang dimuat.
Tapi kami masih mendapatkan biaya besar dari proses python yang dimulai + impor seledri. Saya tetap akan merekomendasikan periode tinggi.

Hai,
seledri periksa ping -A app.tasks -d seledri @ $ HOSTNAME memberi saya "Kesalahan: Siaran tidak didukung oleh transportasi 'sqs'".
Saya menggunakan SQS sebagai broker, jadi ini berarti perintah 'inspect' / 'status' tidak akan berfungsi dengan SQS?

Kami telah menemukan bahwa dalam skala besar, semua fitur kendali jarak jauh menyebabkan instance Redis melonjak di CPU karena perintah yang ditetapkan pada kunci kombu.pidbox , jadi kami tidak dapat menggunakan ping, atau status atau inspeksi sebagaimana adanya. semua menggunakan remote control dan mencoba menonaktifkan remote control untuk kasus penggunaan produksi.

Sepertinya saya memiliki antrian pemeriksaan kesehatan khusus adalah cara yang benar tetapi saya tidak yakin sama sekali

Adakah yang punya arahan lain yang tidak melibatkan remote control untuk menguji health check?

Kami menggunakan antrian pemeriksaan kesehatan khusus dengan kebijakan penggusuran RabbitMQ (antrian dihapus secara otomatis) dengan sukses untuk beberapa waktu sekarang, dan kami senang dengan solusinya. Sebagian besar karena pemeriksaan ini memang memeriksa bahwa pekerja memproses tugas dan menyelesaikannya. Sejak kami memperkenalkannya, kami tidak memiliki masalah lagi dengan pekerja yang macet.

@bartoszhernas keberatan berbagi beberapa kode untuk itu? apakah Anda mengantri ini melalui beat dan daripada pekerja yang mengambilnya?

ingin melihat kode + bagian probe kehidupan

Hai, kodenya sangat mudah:

Di Kubernetes saya menentukan nama antrian berdasarkan POD_NAME, dan meneruskannya ke skrip pemeriksaan langsung:

        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)

(Anda perlu menggunakan bash -c, karena Kubernetes tidak memperluas ENV saat mencoba meneruskannya sebagai perintah secara langsung)

maka celery_liveness_probe.py hanya mengatur Django agar dapat menggunakan Celery dan menjadwalkan tugas pada antrian 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)

fungsi health check mengirimkan tugas dan menunggu hasilnya

    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

Jadi pada dasarnya: mengirim tugas, dan jika mengembalikan hasil maka pekerja itu sehat. Jika pekerja mengalami kebuntuan (terjadi berkali-kali) maka tugas tidak pernah selesai, Pod akan dimulai ulang dan semuanya kembali normal.

Satu-satunya peringatan adalah Anda harus berurusan dengan antrian lama, dengan RabbitMQ itu mudah, kami hanya mengatur kebijakan kadaluwarsa pada antrian
https://www.rabbitmq.com/ttl.html#queue -ttl

@bartoszhernas terima kasih telah membagikan kode!

seperti yang Anda katakan, antrean saya dinamis dan kami menggunakan Redis - jadi kami benar-benar perlu menemukan cara untuk menangani nama antrean yang kedaluwarsa di Redis

Ya, kami memiliki masalah serupa dengan BullMQ dengan Redis. Ide saya adalah menulis CronJob untuk Kubernetes yang akan menghapus antrian setiap saat.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat