Pertanyaan AWS Elastic Beanstalk, menjalankan cronjob


Saya ingin tahu apakah ada cara untuk mengatur cronjob / tugas untuk dijalankan setiap menit. Saat ini salah satu contoh saya harus dapat menjalankan tugas ini.

Inilah yang saya coba lakukan di file konfigurasi tanpa berhasil:

container_commands:
  01cronjobs:
    command: echo "*/1 * * * * root php /etc/httpd/myscript.php"

Saya tidak begitu yakin apakah ini cara yang benar untuk melakukannya

Ada ide?


78
2017-12-28 23:30


asal


Jawaban:


Ini adalah bagaimana saya menambahkan tugas cron ke Elastic Beanstalk:

Buat folder di akar aplikasi Anda yang disebut .ebekstensi jika belum ada. Kemudian buat file konfigurasi di dalam folder .ebextensions. Saya akan menggunakan contoh.config untuk tujuan ilustrasi. Kemudian tambahkan ini ke example.config

container_commands:
  01_some_cron_job:
    command: "cat .ebextensions/some_cron_job.txt > /etc/cron.d/some_cron_job && chmod 644 /etc/cron.d/some_cron_job"
    leader_only: true

Ini adalah file konfigurasi YAML untuk Elastic Beanstalk. Pastikan ketika Anda menyalin ini ke editor teks Anda bahwa editor teks Anda menggunakan spasi, bukan tab. Jika tidak, Anda akan mendapatkan kesalahan YAML ketika Anda mendorong ini ke EB.

Jadi apa yang dilakukan adalah membuat perintah yang disebut 01_some_cron_job. Perintah dijalankan dalam urutan abjad sehingga 01 memastikan dijalankan sebagai perintah pertama.

Perintah kemudian mengambil isi file yang disebut some_cron_job.txt dan menambahkannya ke file bernama some_cron_job di /etc/cron.d.

Perintah kemudian mengubah hak akses pada file /etc/cron.d/some_cron_job.

Kunci leader_only memastikan perintah hanya dijalankan pada instance ec2 yang dianggap sebagai pemimpin. Alih-alih berjalan di setiap contoh EC2 yang mungkin Anda jalankan.

Kemudian buat file bernama some_cron_job.txt di dalam folder .ebextensions. Anda akan menempatkan cron jobs Anda di file ini.

Jadi misalnya:

# The newline at the end of this file is extremely important.  Cron won't run without it.
* * * * * root /usr/bin/php some-php-script-here > /dev/null

Jadi tugas cron ini akan berjalan setiap menit setiap jam setiap hari sebagai pengguna root dan membuang output ke / dev / null. / usr / bin / php adalah path ke php. Kemudian ganti beberapa-php-script-di sini dengan path ke file php Anda. Ini jelas mengasumsikan bahwa tugas cron Anda perlu menjalankan file PHP.

Juga, pastikan file some_cron_job.txt memiliki baris baru di akhir file seperti yang dikatakan komentar. Jika tidak, cron tidak akan berjalan.

Memperbarui: Ada masalah dengan solusi ini ketika Elastic Beanstalk meningkatkan skala instance Anda. Sebagai contoh, katakanlah Anda memiliki satu contoh dengan menjalankan tugas cron. Anda mendapatkan peningkatan lalu lintas sehingga Beanstalk Elastis skala Anda hingga dua contoh. Leader_only akan memastikan Anda hanya memiliki satu tugas cron yang berjalan di antara dua instance. Lalu lintas Anda menurun dan Elastic Beanstalk menskalakan Anda ke satu instance. Tetapi alih-alih mengakhiri contoh kedua, Elastic Beanstalk mengakhiri contoh pertama yang merupakan pemimpin. Anda sekarang tidak memiliki tugas cron yang berjalan karena mereka hanya berjalan pada instance pertama yang dihentikan. Lihat komentar di bawah ini.

Perbarui 2: Hanya membuat ini jelas dari komentar di bawah ini: AWS kini memiliki perlindungan terhadap penghentian instan otomatis. Cukup aktifkan pada contoh pemimpin Anda dan Anda siap untuk pergi. - Nicolás Arévalo Okt 28 '16 jam 9:23


81
2018-03-05 20:50



Ini adalah cara resmi untuk melakukannya sekarang (2015+). Silakan coba ini dulu, itu metode termudah saat ini tersedia dan paling dapat diandalkan juga.

Menurut dokumen saat ini, salah satunya adalah mampu menjalankan tugas-tugas periodik pada mereka yang disebut tingkatan pekerja.

Mengutip dokumentasi:

AWS Elastic Beanstalk mendukung tugas periodik untuk tingkatan lingkungan pekerja di lingkungan yang menjalankan konfigurasi standar dengan tumpukan solusi yang berisi "v1.2.0" dalam nama penampung. Anda harus membuat lingkungan baru.

Juga menarik adalah bagian tentang cron.yaml:

Untuk menjalankan tugas-tugas periodik, paket sumber aplikasi Anda harus menyertakan file cron.yaml di tingkat akar. File harus berisi informasi tentang tugas periodik yang ingin Anda jadwalkan. Tentukan informasi ini menggunakan sintaks crontab standar.

Memperbarui: Kami bisa mendapatkan pekerjaan ini. Berikut beberapa terobosan penting dari pengalaman kami (platform Node.js):

  • Ketika menggunakan cron.yaml file, pastikan Anda memiliki yang terbaru awsebcli, karena versi yang lebih lama tidak akan berfungsi dengan baik.
  • Ini juga penting untuk menciptakan lingkungan baru (setidaknya dalam kasus kami), bukan hanya mengkloning yang lama.
  • Jika Anda ingin memastikan CRON didukung pada instance Tier Worker EC2 Anda, ssh ke dalamnya (eb ssh), dan lari cat /var/log/aws-sqsd/default.log. Ini harus dilaporkan sebagai aws-sqsd 2.0 (2015-02-18). Jika Anda tidak memiliki versi 2.0, ada yang salah saat membuat lingkungan Anda dan Anda perlu membuat yang baru seperti yang disebutkan di atas.

53
2018-02-25 12:48



Mengenai respon jamieb, dan seperti yang disinggung oleh aliansi, Anda dapat menggunakan properti 'leader_only' untuk memastikan hanya satu contoh EC2 yang menjalankan tugas cron.

Kutipan diambil dari http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html:

Anda dapat menggunakan leader_only. Satu contoh dipilih untuk menjadi pemimpin dalam grup Auto Scaling. Jika nilai leader_only disetel ke true, perintah hanya berjalan pada instance yang ditandai sebagai pemimpin.

Saya mencoba untuk mencapai hal yang sama di eb saya, jadi akan memperbarui posting saya jika saya menyelesaikannya.

MEMPERBARUI:

Ok, saya sekarang telah bekerja cronjobs menggunakan konfigurasi eb berikut:

files:
  "/tmp/cronjob" :
    mode: "000777"
    owner: ec2-user
    group: ec2-user
    content: |
      # clear expired baskets
      */10 * * * * /usr/bin/wget -o /dev/null http://blah.elasticbeanstalk.com/basket/purge > $HOME/basket_purge.log 2>&1
      # clean up files created by above cronjob
      30 23 * * * rm $HOME/purge*
    encoding: plain 
container_commands:
  purge_basket: 
    command: crontab /tmp/cronjob
    leader_only: true
commands:
  delete_cronjob_file: 
    command: rm /tmp/cronjob

Pada dasarnya, saya membuat file temp dengan cronjobs dan kemudian mengatur crontab untuk membaca dari file temp, kemudian hapus file temp setelahnya. Semoga ini membantu.


31
2018-01-01 13:44



Seperti disebutkan di atas, cacat mendasar dengan menetapkan konfigurasi crontab adalah hanya terjadi saat penyebaran. Ketika kluster tersebut ditingkatkan secara otomatis, dan kemudian mundur, lebih disukai untuk juga menjadi server pertama yang dimatikan. Selain itu, tidak akan ada kegagalan, yang bagi saya sangat penting.

Saya melakukan riset, lalu berbicara dengan spesialis akun AWS kami untuk memantulkan ide dan memvalidasi solusi yang saya hasilkan. Anda dapat melakukannya dengan OpsWorks, meskipun itu seperti menggunakan rumah untuk membunuh seekor lalat. Ini juga memungkinkan untuk digunakan Data Pipeline dengan Task Runner, tetapi ini memiliki kemampuan terbatas dalam skrip yang dapat dieksekusi, dan saya harus bisa menjalankan skrip PHP, dengan akses ke seluruh basis kode. Anda juga dapat mendedikasikan turunan EC2 di luar cluster ElasticBeanstalk, tetapi kemudian Anda tidak akan gagal lagi.

Jadi di sini adalah apa yang saya dapatkan, yang tampaknya tidak biasa (seperti komentar AWS berkomentar) dan dapat dianggap sebagai peretasan, tetapi itu berhasil dan solid dengan kegagalan. Saya memilih solusi pengkodean menggunakan SDK, yang akan saya tunjukkan dalam PHP, meskipun Anda dapat melakukan metode yang sama dalam bahasa apa pun yang Anda sukai.

// contains the values for variables used (key, secret, env)
require_once('cron_config.inc'); 

// Load the AWS PHP SDK to connection to ElasticBeanstalk
use Aws\ElasticBeanstalk\ElasticBeanstalkClient;

$client = ElasticBeanstalkClient::factory(array(
    'key' => AWS_KEY,
    'secret' => AWS_SECRET,
    'profile' => 'your_profile',
    'region'  => 'us-east-1'
));

$result = $client->describeEnvironmentResources(array(
    'EnvironmentName' => AWS_ENV
));

if (php_uname('n') != $result['EnvironmentResources']['Instances'][0]['Id']) {
    die("Not the primary EC2 instance\n");
}

Jadi berjalan melalui ini dan cara kerjanya ... Anda memanggil skrip dari crontab seperti biasa pada setiap EC2. Setiap skrip menyertakan ini di awal (atau termasuk satu file untuk masing-masing, seperti yang saya gunakan), yang menetapkan objek ElasticBeanstalk dan mengambil daftar semua instance. Ini hanya menggunakan server pertama dalam daftar, dan memeriksa apakah itu cocok sendiri, yang jika itu terus berlanjut, jika tidak maka ia akan mati dan ditutup. Saya telah memeriksa dan daftar kembali tampaknya konsisten, yang secara teknis hanya perlu konsisten selama satu menit atau lebih, karena setiap kejadian menjalankan cron yang dijadwalkan. Jika itu berubah, itu tidak masalah, karena lagi-lagi hanya relevan untuk jendela kecil itu.

Ini tidak elegan dengan cara apa pun, tetapi sesuai dengan kebutuhan spesifik kami - yang tidak meningkatkan biaya dengan layanan tambahan atau harus memiliki contoh EC2 khusus, dan akan gagal jika terjadi kegagalan. Skrip cron kami menjalankan skrip pemeliharaan yang ditempatkan ke dalam SQS dan setiap server di kluster membantu mengeksekusi. Setidaknya ini dapat memberi Anda opsi alternatif jika sesuai dengan kebutuhan Anda.

-Davey


11
2017-07-17 18:08



Jika Anda menggunakan Rails, Anda dapat menggunakan permata kapan saja-elasticbeanstalk. Ini memungkinkan Anda untuk menjalankan tugas cron pada semua instance atau hanya satu. Ia memeriksa setiap menit untuk memastikan bahwa hanya ada satu contoh "pemimpin", dan secara otomatis akan mempromosikan satu server ke "pemimpin" jika tidak ada. Ini diperlukan karena Elastic Beanstalk hanya memiliki konsep pemimpin selama pengerahan dan dapat mematikan instance apa pun kapan saja ketika melakukan penskalaan.

MEMPERBARUI Saya beralih menggunakan AWS OpsWorks dan saya tidak lagi mempertahankan permata ini. Jika Anda membutuhkan lebih banyak fungsi daripada yang tersedia di dasar-dasar Elastic Beanstalk, saya sangat menyarankan beralih ke OpsWorks.


7
2018-06-24 21:58



Saya berbicara dengan agen dukungan AWS dan inilah cara kami membuatnya bekerja untuk saya. Solusi 2015:

Buat file di direktori .ebextensions Anda dengan your_file_name.config. Dalam input file konfigurasi:

file:
  "/etc/cron.d/cron_example":
    mode: "000644"
    pemilik: root
    grup: root
    konten: |
      * * * * * root /usr/local/bin/cron_example.sh

  "/usr/local/bin/cron_example.sh":
    mode: "000755"
    pemilik: root
    grup: root
    konten: |
      #! / bin / bash

      /usr/local/bin/test_cron.sh || keluar
      echo "Cron berjalan pada" `date` >> /tmp/cron_example.log
      Sekarang lakukan tugas yang seharusnya hanya berjalan pada 1 instance ...

  "/usr/local/bin/test_cron.sh":
    mode: "000755"
    pemilik: root
    grup: root
    konten: |
      #! / bin / bash

      METADATA = / opt / aws / bin / ec2-metadata
      INSTANCE_ID = `$ METADATA -i | awk '{cetak $ 2}' `
      REGION = `$ METADATA -z | awk '{print substr ($ 2, 0, length ($ 2) -1)}' `

      # Temukan nama Grup Penskalaan Otomatis kami.
      ASG = `aws ec2 describ-tags --filters" Name = resource-id, Nilai = $ INSTANCE_ID "\
        --region $ REGION --output teks | awk '/ aws: penskalaan otomatis: groupName / {print $ 5}' `

      # Temukan contoh pertama di Grup
      FIRST = `aws autoscaling menjelaskan-auto-scaling-groups --auto-scaling-group-names $ ASG \
        --region $ REGION --output teks | awk '/ InService $ / {print $ 4}' | sortir | kepala -1`

      # Uji jika mereka sama.
      ["$ FIRST" = "$ INSTANCE_ID"]

perintah:
  rm_old_cron:
    perintah: "rm * .bak"
    cwd: "/etc/cron.d"
    ignoreErrors: true

Solusi ini memiliki 2 kelemahan:

  1. Pada penerapan berikutnya, Beanstalk mengganti nama skrip cron yang ada sebagai .bak, tetapi cron akan tetap menjalankannya. Cron Anda sekarang menjalankan dua kali pada mesin yang sama.
  2. Jika lingkungan Anda berskala, Anda mendapatkan beberapa contoh, semua menjalankan skrip cron Anda. Ini berarti gambar email Anda diulang, atau arsip basis data Anda diduplikasi

Solusi:

  1. Pastikan skrip .ebextensions apa pun yang membuat cron juga menghapus file .bak pada penerapan berikutnya.
  2. Memiliki skrip pembantu yang melakukan hal berikut: - Mendapat ID Instance saat ini dari Metadata - Mendapat Auto saat ini     Scaling Group name dari EC2 Tags - Mendapat daftar EC2     Instance dalam Grup itu, diurutkan sesuai abjad. - Membawa yang pertama     contoh dari daftar itu. - Bandingkan ID Instance dari langkah 1     dengan ID Instance pertama dari langkah 4. Skrip cron Anda kemudian dapat menggunakan skrip pembantu ini untuk menentukan apakah skrip tersebut harus dijalankan.

Peringatan:

  • Peran IAM yang digunakan untuk instance Beanstalk membutuhkan ec2: DescribeTags dan autoscaling: DescribeAutoScalingGroups permissions
  • Instance yang dipilih dari adalah yang ditampilkan sebagai InService oleh Auto Scaling. Ini tidak berarti mereka sepenuhnya boot dan siap menjalankan cron Anda.

Anda tidak perlu mengatur Peran IAM jika Anda menggunakan peran gagang pohon standar.


7
2017-09-26 08:23



Anda benar-benar tidak ingin menjalankan tugas cron di Elastic Beanstalk. Karena Anda akan memiliki beberapa contoh aplikasi, ini dapat menyebabkan kondisi balapan dan masalah aneh lainnya. saya sebenarnya baru-baru ini blog tentang ini (Tip ke-4 atau ke-5 di halaman). Versi singkat: Bergantung pada aplikasi, gunakan antrian pekerjaan seperti SQS atau solusi pihak ketiga seperti iron.io.


6
2017-12-31 19:06



Solusi yang lebih mudah digunakan files dari pada container_commands:

file:
  "/etc/cron.d/my_cron":
    mode: "000644"
    pemilik: root
    grup: root
    konten: |
      # mengganti alamat email default
      MAILTO = "example@gmail.com"
      # menjalankan perintah Symfony setiap lima menit (sebagai pengguna-ec2)
      * / 10 * * * * ec2-user / usr / bin / php / var / app / current / app / console lakukan: sesuatu
    encoding: polos
perintah:
  # menghapus file cadangan yang dibuat oleh Elastic Beanstalk
  clear_cron_backup:
    perintah: rm -f /etc/cron.d/watson.bak

Perhatikan formatnya berbeda dari format crontab biasa dalam hal itu menentukan pengguna untuk menjalankan perintah sebagai.


4
2018-03-27 13:11



Seseorang bertanya-tanya tentang masalah auto scaling pemimpin ketika muncul pemimpin baru. Saya tidak dapat mencari tahu cara membalas komentar mereka, tetapi lihat tautan ini: http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/


2
2017-10-20 05:05



Berikut ini penjelasan lengkap solusinya:

http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/


1
2017-08-25 23:49



Untuk mengontrol apakah Penskalaan Otomatis dapat menghentikan instance tertentu saat melakukan penskalaan, gunakan perlindungan instance. Anda dapat mengaktifkan pengaturan perlindungan instance pada grup Penskalaan Otomatis atau contoh Penskalaan Otomatis individual. Ketika Auto Scaling meluncurkan sebuah instance, instance mewarisi pengaturan perlindungan instance dari grup Penskalaan Otomatis. Anda dapat mengubah pengaturan perlindungan instance untuk grup Penskalaan Otomatis atau contoh Penskalaan Otomatis kapan saja.

http://docs.aws.amazon.com/autoscaling/latest/userguide/as-instance-termination.html#instance-protection


0
2017-08-10 20:23