-
Notifications
You must be signed in to change notification settings - Fork 482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support long running cron tasks #480
Comments
I stumbled upon the same issue - Using the recommended method of running a crond inside it's own Docker container worked apparently for simple workloads. But if you have a lot of cronjobs and deploy regularly, chances are, you are killing your cronjobs during running. Even though most cronjobs should be performed idempotently and should handle a missing run and be short lived - and we usually try do adhere to these principles. We are using
Make sure to replace the role. We just run the cronjobs in one of the bg-worker's nodes, so we just steal the app-worker.env here. # config/schedule.rb
revision = ENV['CI_COMMIT_SHORT_SHA'] || 'latest'
job_type :runner, "docker run -it --env-file ~/.kamal/env/roles/app-worker.env --rm registry.company.de/image/app:#{revision} bundle exec rails runner ':task' :output"
#!/bin/bash
# chmod +x ./bin/update_cron
cron_host="10.11.12.13"
schedule_file="config/schedule.rb"
cron_image="registry.company.com/app/image:$CI_COMMIT_SHORT_SHA"
echo "Deploying cron job $cron_image to $cron_host"
ssh -t -i ./deploy/id_rsa root@$cron_host \
"docker run -it $cron_image bundle exec whenever -f $schedule_file > /tmp/crontab && sed -i '/^\s*$/d' /tmp/crontab && crontab /tmp/crontab" One can also put it into a Kamal post-deploy hook but for us, it's just one line more in the gitlab-ci.yml. |
I wanted to share a solution I encountered with getting Cron (with Whenever) to run correctly and how I eventually resolved it. After some trial and error, I discovered that the environment variables available to To solve this, I modified my cron:
hosts:
- 1.2.3.4
cmd: bash -c "bundle exec whenever --update-crontab && env > /etc/environment && cron -f" Additionally, I made some changes to my Dockerfile to handle the permissions for RUN touch /var/run/crond.pid && \
chown rails:rails /var/run/crond.pid && \
chown rails:rails /etc/environment I hope this helps anyone who might encounter a similar issue in the future. It took me a while to figure this out, so hopefully, this can save someone else some time! |
Thanks for sharing this. What kind of cron are you using? The one I use (from debian) gives an error when run as |
@frenkel Try this: RUN touch /var/run/crond.pid && \
chown rails:rails /var/run/crond.pid && \
chown rails:rails /etc/environment && \
+ chmod u+s /usr/sbin/cron Should help with the cron permissions issue. |
@vladyio thanks, but that is exactly what I want to prevent. I don't want to run it as root. I've come up with a solution: use solid queue tasks as a replacement. Works much nicer! |
While I appreciate @jankeesvw effort and response I found it too finicky. So I took @frenkel 's response as an inspiration and I ended up switching from whenever / cron to running my scheduled tasks via my job runner, which in my case is Sidekiq. I just needed to add: https://github.com/sidekiq-scheduler/sidekiq-scheduler I even spared some resources by not running a third container for cron as I was already running one for Sidekiq. |
The best current way to work with cron, as documented here, has some down-sides for me. But, luckily, recent work with a separate environment file (#438) offers a great opportunity to improve cron! :)
The biggest downside of this approach is it will not work with long running cron task. As these will be aborted when a deploy hits. We make use of long running cron tasks quite a bit, and deploy quite a bit.
Cron as native thing
So: let's say we would add an option for a role to define a
cronfile
:Now: on deploy Kamal can create a
/etc/cron.d/app-some-role
file on the host. Kamal will wrap each line in theconfig/crontab
file (extracted from the image) into something like this:Now as a result the host system will nicely schedule cron :). Nothing is started twice. And long running task can simply finish.
Now: it's now as simple as that. The role options (like
add-host
) is for example not copied in this way. So we would need to find a way to mimic these settings as well.One way to do that is that we could have Kamal write an executable
~/.kamal/run/roles/app-some-role
file that will contain the whole command to run a new Docker container. In which case we can rewrite the cron to:Note that is roughly the strategy that me and team have been using for cron for the last few years (some home-grown solution on top of Docker Swarm with some Ansible scripts that are retiring in favour of Kamal!). But that cron strategy specifically has been working great.
Could also be that I'm missing some simpler solutions that solves these problems I currently face :)!
(Note only now found out about https://github.com/basecamp/kamal/discussions/categories/ideas, should have used that probably. Sorry!)
The text was updated successfully, but these errors were encountered: