АРМ эластичный бобовый стебель, работает в процентах
Я хотел бы знать, есть ли способ настроить cronjob/task для выполнения каждую минуту. В настоящее время любой из моих экземпляров должен быть в состоянии выполнить эту задачу.
Это то, что я пытался сделать в файлах настроек без успеха:
container_commands:
01cronjobs:
command: echo "*/1 * * * * root php /etc/httpd/myscript.php"
Я не совсем уверен, что это правильный способ сделать это
какие идеи?
16 ответов:
вот как я добавил задание cron в Elastic Beanstalk:
создайте папку в корне вызываемого приложения .ebextensions, если он еще не существует. Затем создайте файл конфигурации внутри .папка ebextensions. Я буду использовать пример.конфигурация для иллюстрации. Затем добавьте это в пример.конфигурации
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
это файл конфигурации YAML для эластичного бобового стебля. Убедитесь, что при копировании в текстовый редактор используются пробелы вместо вкладок. В противном случае вы получите ошибку YAML, когда вы нажмете это на EB.
так, что это делает, это создать команду под названием 01_some_cron_job. Команды выполняются в алфавитном порядке, поэтому 01 гарантирует, что он запускается как первая команда.
затем команда принимает содержимое файла с именем some_cron_job.txt и добавляет его в файл с именем some_cron_job в /etc/cron.d.
затем команда изменяет разрешения на /etc / cron.d / some_cron_job файл.
ключ leader_only гарантирует, что команда выполняется только на экземпляре ec2, который считается лидером. Вместо того, чтобы работать на каждом экземпляре ec2 вы можете иметь работает.
затем создайте файл с именем some_cron_job.txt внутрь .папка ebextensions. Вы разместите свои задания cron в этом файле.
например:
# 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
таким образом, это задание cron будет выполняться каждую минуту каждого часа каждого дня в качестве пользователя root и отбрасывать вывод /dev / null. /usr/bin / php-это путь к php. Затем замените some-php-script-here путем к вашему php-файлу. Это, очевидно, предполагает, что ваша работа cron должна запускать PHP-файл.
кроме того, убедитесь, что some_cron_job.txt файл имеет строку в конце файла, как говорится в комментариях. В противном случае cron не будет работать.
обновление: Существует проблема с этим решением, когда Elastic Beanstalk масштабирует ваши экземпляры. Например, допустим, у вас есть один экземпляр с запущенным заданием cron. Вы получаете увеличение трафика, поэтому эластичный Бобовый Стебель масштабирует вас до двух экземпляров. Leader_only гарантирует, что между двумя экземплярами будет выполняться только одно задание cron. Ваш трафик уменьшается, и эластичный Бобовый Стебель масштабирует вас до одного экземпляра. Но вместо завершения второго экземпляра Elastic Beanstalk завершает первый экземпляр, который был лидером. Теперь у вас нет никаких заданий cron, так как они работали только на первом экземпляр, который был прекращен. посмотреть комментарии ниже.
обновление 2: Просто делая это ясно из комментариев ниже: AWS теперь имеет защиту от автоматического завершения инстанса. Просто включите его на вашем экземпляре лидера, и вы хорошо идти. - Николас Аревало 28 '16 октября в 9:23
Это официальный способ сделать это сейчас (2015+). Пожалуйста, попробуйте это во-первых, это на сегодняшний день самый простой способ, доступный и самый надежный.
согласно текущим документам, один из них возможность выполнения периодических задач на их так называемые рабочий уровень.
со ссылкой на документы:
AWS Elastic Beanstalk поддерживает периодические задачи для уровней рабочей среды в средах с предопределенной конфигурацией с помощью стека решений, который содержит "v1.2.0" в имени контейнера. Необходимо создать новую среду.
также интересна часть о cron.и YAML:
для вызова периодических задач исходный пакет приложения должен содержать хрон.файл yaml на корневом уровне. Файл должен содержать информацию о периодических задачах, которые вы хотите запланировать. Укажите эту информацию с помощью стандартной crontab синтаксис.
обновление: мы смогли получить эту работу. Вот некоторые важные готы из нашего опыта (узел.платформа с JS):
- при использовании cron.и YAML файл, убедитесь, что у вас есть последние awsebcli, потому что старые версии не будут работать должным образом.
- кроме того, крайне важно создать новую среду (по крайней мере в нашем случае было), а не просто клонировать старый.
- если вы хотите, чтобы убедиться, CRON поддерживается на вашем экземпляре рабочего уровня EC2, ssh в него (
eb ssh
), и работатьcat /var/log/aws-sqsd/default.log
. Он должен сообщить какaws-sqsd 2.0 (2015-02-18)
. Если у вас нет версии 2.0, что-то пошло не так при создании вашей среды, и вам нужно создать новую, как указано выше.
Что касается ответа jamieb, и, как упоминает alrdinleal, вы можете использовать свойство 'leader_only', чтобы гарантировать, что только один экземпляр EC2 запускает задание cron.
цитата взята из http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html:
вы можете использовать leader_only. Один экземпляр выбирается в качестве лидера в группе автоматического масштабирования. Если для параметра leader_only задано значение true, команда выполняется только на экземпляр, помеченный как лидер.
Я пытаюсь достичь аналогичной вещи на моем eb, поэтому обновлю свой пост, если я его решу.
обновление:
хорошо, теперь у меня есть рабочие cronjobs, используя следующую конфигурацию eb:
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
по существу, я создаю временный файл с помощью cronjobs, а затем устанавливаю crontab для чтения из временного файла, а затем удаляю временный файл. Надеюсь, это поможет.
Я провел некоторое исследование, а затем поговорил с нашим специалистом по аккаунтам AWS, чтобы отбросить идеи и подтвердить решение, которое я придумал. Вы можете сделать это с помощью OpsWorks, хотя это немного похоже на использование дома, чтобы убить муху. Также можно использовать конвейер данных с задачей Runner, но это имеет ограниченные возможности в скриптах, которые он может выполнять, и мне нужно было иметь возможность запускать PHP-скрипты с доступом ко всей базе кода. Вы также можете выделить экземпляр EC2 за пределами кластера ElasticBeanstalk, но тогда у вас нет сбоя снова.
Так вот что я придумал, что явно нетрадиционный (как прокомментировал представитель AWS) и может считаться взломом, но он работает и надежен с отказом. Я выбрал решение для кодирования с помощью SDK, которое я покажу в PHP, хотя вы можете сделать тот же метод на любом языке, который вы предпочитаете.
// 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"); }
Итак, пройдя через это и как это работает... Вы вызываете скрипты из crontab, как обычно, на каждом экземпляре EC2. Каждый скрипт включает это в начале (или включает в себя один файл для каждого, как я его использую), который устанавливает объект ElasticBeanstalk и получает список всех экземпляров. Он использует только первый сервер в списке и проверяет, соответствует ли он себе, который, если он это делает, продолжается, иначе он умирает и закрывается. Я проверил, и возвращенный список кажется согласованным, что технически должно быть согласовано только в течение минуты или около того, поскольку каждый экземпляр выполняет запланированный cron. Если это изменится, это не будет иметь значения, так как опять же это относится только к этому маленькому окно.
это ни в коем случае не элегантно, но подходит для наших конкретных потребностей - которые не должны были увеличивать стоимость с дополнительным сервисом или иметь выделенный экземпляр EC2 и имели бы отказ в случае любого сбоя. Наши сценарии cron запускают сценарии обслуживания, которые помещаются в SQS, и каждый сервер в кластере помогает выполнить. По крайней мере, это может дать вам альтернативный вариант, если она соответствует вашим потребностям.
- Davey
Если вы используете рельсы, вы можете использовать whenever-elasticbeanstalk gem. Он позволяет запускать задания cron на всех экземплярах или только на одном. Он проверяет каждую минуту, чтобы убедиться, что есть только один экземпляр" лидера", и автоматически повысит один сервер до" лидера", если их нет. Это необходимо, так как Elastic Beanstalk имеет только концепцию лидера во время развертывания и может закрыть любой экземпляр в любое время, пока пересчет.
обновление Я переключился на использование AWS OpsWorks и больше не поддерживаю этот драгоценный камень. Если вам нужно больше функциональности, чем доступно в основах Elastic Beanstalk, я настоятельно рекомендую переключиться на OpsWorks.
Я говорил с агентом поддержки AWS, и вот как мы получили эту работу для меня. 2015 решение:
создать файл в вашем .ebextensions каталог с имя_файла.конфиг. В файле конфигурации ввода:
files: "/etc/cron.d/cron_example": mode: "000644" owner: root group: root content: | * * * * * root /usr/local/bin/cron_example.sh "/usr/local/bin/cron_example.sh": mode: "000755" owner: root group: root content: | #!/bin/bash /usr/local/bin/test_cron.sh || exit echo "Cron running at " `date` >> /tmp/cron_example.log # Now do tasks that should only run on 1 instance ... "/usr/local/bin/test_cron.sh": mode: "000755" owner: root group: root content: | #!/bin/bash METADATA=/opt/aws/bin/ec2-metadata INSTANCE_ID=`$METADATA -i | awk '{print }'` REGION=`$METADATA -z | awk '{print substr(, 0, length()-1)}'` # Find our Auto Scaling Group name. ASG=`aws ec2 describe-tags --filters "Name=resource-id,Values=$INSTANCE_ID" \ --region $REGION --output text | awk '/aws:autoscaling:groupName/ {print }'` # Find the first instance in the Group FIRST=`aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names $ASG \ --region $REGION --output text | awk '/InService$/ {print }' | sort | head -1` # Test if they're the same. [ "$FIRST" = "$INSTANCE_ID" ] commands: rm_old_cron: command: "rm *.bak" cwd: "/etc/cron.d" ignoreErrors: trueЭто решение имеет 2 недостатка:
- при последующих развертываниях Beanstalk переименовывает существующий сценарий cron как .бак, но крон все равно будет управлять им. Ваш Cron теперь выполняется дважды на одной машине.
- если ваша окружающая среда Весы, вы получаете несколько экземпляров, все запущенные скрипта по cron. Это означает, что ваши почтовые снимки повторяются, или ваши архивы базы данных дублируются
решение:
- обеспечить любой .сценарий ebextensions, который создает cron, также удаляет его .файлы bak при последующих развертываниях.
- есть вспомогательный скрипт, который делает следующее: -- получает текущий идентификатор экземпляра из метаданных -- получает текущий авто Масштабирование имени группы из тегов EC2 -- Получает список EC2 Экземпляры в этой группе отсортированы по алфавиту. -- Берет первый экземпляр из этого списка. -- Сравнивает идентификатор экземпляра с шага 1 с идентификатором первого экземпляра из шага 4. Затем ваши сценарии cron могут использовать этот вспомогательный сценарий, чтобы определить, должны ли они выполняться.
предостережение:
- роль IAM, используемая для экземпляров Beanstalk, требует ec2:DescribeTags и autoscaling:DescribeAutoScalingGroups разрешения
- экземпляры, выбранные из тех, которые показаны как InService с помощью автоматического масштабирования. Это не обязательно означает, что они полностью загружены и готовы к запуску вашего cron.
вам не нужно будет устанавливать роли IAM, если вы используете роль beanstalk по умолчанию.
вы действительно не хотите запускать задания cron на эластичном бобовом стебле. Поскольку у вас будет несколько экземпляров приложения, это может вызвать условия гонки и другие нечетные проблемы. Я на самом деле недавно написал об этом в блоге (4-й или 5-й наконечник вниз по странице). Короткая версия: в зависимости от приложения используйте очередь заданий, например SQS, или стороннее решение, напримерiron.io.
более читаемое решение с помощью
files
вместоcontainer_commands
:files: "/etc/cron.d/my_cron": mode: "000644" owner: root group: root content: | # override default email address MAILTO="example@gmail.com" # run a Symfony command every five minutes (as ec2-user) */10 * * * * ec2-user /usr/bin/php /var/app/current/app/console do:something encoding: plain commands: # delete backup file created by Elastic Beanstalk clear_cron_backup: command: rm -f /etc/cron.d/watson.bakПримечание формат отличается от обычного формата crontab тем, что он определяет пользователя для выполнения команды от имени.
кто-то задавался вопросом о проблемах автоматического масштабирования leader_only, когда возникают новые лидеры. Я не могу понять, как ответить на их комментарии, но см. Эту ссылку: http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/
вот полное объяснение решения:
http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/
чтобы определить, может ли автоматическое масштабирование завершать определенный экземпляр при масштабировании, используйте защиту экземпляра. Параметр защиты экземпляра можно включить в группе автоматического масштабирования или в отдельном экземпляре автоматического масштабирования. Когда автоматическое масштабирование запускает экземпляр, экземпляр наследует параметр защиты экземпляра группы автоматического масштабирования. Параметр защиты экземпляра для группы автоматического масштабирования или экземпляра автоматического масштабирования можно изменить в любом случае время.
У меня было другое решение для этого, если php-файл должен быть запущен через cron, и если вы установили какие-либо экземпляры NAT, вы можете поместить cronjob на экземпляр NAT и запустить php-файл через wget.
2017: Если вы используете Laravel5+
вам просто нужно 2 минуты, чтобы настроить его:
- создать рабочий уровень
установить laravel-aws-worker
composer require dusterio/laravel-aws-worker
добавить cron.ямл в корневую папку:
добавить cron.yaml в корневую папку вашего приложения (это может быть часть вашего РЕПО или вы можете добавить этот файл прямо перед этим развертывание в EB-важно то, что этот файл присутствует во время развертывание):
version: 1 cron: - name: "schedule" url: "/worker/schedule" schedule: "* * * * *"
вот именно!
все ваши задачи
App\Console\Kernel
теперь будет выполнятьсяподробные инструкции и объяснения:https://github.com/dusterio/laravel-aws-worker
как писать задачи внутри Laravel:https://laravel.com/docs/5.4/scheduling
Итак, мы некоторое время боролись с этим, и после некоторого обсуждения с представителем AWS я, наконец, придумал то, что я считаю лучшим решением.
использование рабочего уровня с cron.YAML это наверняка самый простой исправить. Однако в документации не ясно, что это поставит работу в конец из очереди SQS, которую вы используете для фактического выполнения своих заданий. Если ваши задания cron чувствительны ко времени (как и многие), это неприемлемо, так как это будет зависит от размера очереди. Один из вариантов-использовать совершенно отдельную среду только для запуска заданий cron, но я думаю, что это перебор.
некоторые из других вариантов, как проверка, чтобы увидеть, если вы первый экземпляр в списке, не являются идеальными либо. Что делать, если текущий первый экземпляр находится в процессе завершения работы?
защита экземпляра также может возникнуть с проблемами - что делать, если этот экземпляр заблокирован / заморожен?
Что важно понять это то, как AWS сам управляет cron.функциональность ямл. Существует демон SQS, который использует динамическую таблицу для обработки "выборов лидера". Он часто записывает в эту таблицу, и если текущий лидер не написал в течение короткого времени, следующий экземпляр возьмет на себя роль лидера. Именно так демон решает, какой экземпляр запустить задание в очередь SQS.
мы можем перепрофилировать существующую функциональность, а не пытаются переписать нашу собственную. Вы можете увидеть полное решение здесь: https://gist.github.com/dorner/4517fe2b8c79ccb3971084ec28267f27
Это в Ruby, но вы можете легко адаптировать его к любому другому языку, который имеет AWS SDK. По сути, он проверяет текущего лидера, а затем проверяет состояние, чтобы убедиться, что он находится в хорошем состоянии. Он будет циклически работать до тех пор, пока текущий лидер не будет в хорошем состоянии, и если текущий экземпляр является лидером, выполните задание.
вот исправление, если вы хотите сделать это в PHP. Тебе просто нужна дружба.конфиг в вашем .папка ebextensions, чтобы заставить ее работать так.
files: "/etc/cron.d/my_cron": mode: "000644" owner: root group: root content: | empty stuff encoding: plain commands: 01_clear_cron_backup: command: "rm -f /etc/cron.d/*.bak" 02_remove_content: command: "sudo sed -i 's/empty stuff//g' /etc/cron.d/my_cron" container_commands: adding_cron: command: "echo '* * * * * ec2-user . /opt/elasticbeanstalk/support/envvars && /usr/bin/php /var/app/current/index.php cron sendemail > /tmp/sendemail.log 2>&1' > /etc/cron.d/my_cron" leader_only: true
envvars получает переменные среды для файлов. Вы можете отлаживать выход на ТМП/отправка электронных писем отключена.войти, как указано выше.
надеюсь, что это поможет кому-то, как это, безусловно, помогло нам!
Мой 1 цент взноса на 2018 год
вот правильный способ сделать это (с помощью
django/python
иdjango_crontab
приложение):внутри
.ebextensions
папка создать такой файл98_cron.config
:files: "/tmp/98_create_cron.sh": mode: "000755" owner: root group: root content: | #!/bin/sh cd / sudo /opt/python/run/venv/bin/python /opt/python/current/app/manage.py crontab remove > /home/ec2-user/remove11.txt sudo /opt/python/run/venv/bin/python /opt/python/current/app/manage.py crontab add > /home/ec2-user/add11.txt container_commands: 98crontab: command: "mv /tmp/98_create_cron.sh /opt/elasticbeanstalk/hooks/appdeploy/post && chmod 774 /opt/elasticbeanstalk/hooks/appdeploy/post/98_create_cron.sh" leader_only: true
это должно быть
container_commands
вместоcommands