Je voudrais savoir s'il existe un moyen de configurer un cronjob / tâche à exécuter toutes les minutes. Actuellement, n'importe laquelle de mes instances devrait être en mesure d'exécuter cette tâche.
C'est ce que j'ai essayé de faire dans les fichiers de configuration sans succès:
container_commands:
01cronjobs:
command: echo "*/1 * * * * root php /etc/httpd/myscript.php"
Je ne sais pas vraiment si c'est la bonne façon de le faire
Des idées?
Réponses:
Voici comment j'ai ajouté un travail cron à Elastic Beanstalk:
Créez un dossier à la racine de votre application appelé .ebextensions s'il n'existe pas déjà. Créez ensuite un fichier de configuration dans le dossier .ebextensions. J'utiliserai example.config à des fins d'illustration. Ajoutez ensuite ceci à example.config
Il s'agit d'un fichier de configuration YAML pour Elastic Beanstalk. Lorsque vous copiez ceci dans votre éditeur de texte, assurez-vous que votre éditeur de texte utilise des espaces au lieu de tabulations. Sinon, vous obtiendrez une erreur YAML lorsque vous le transmettez à EB.
Donc, cela crée une commande appelée 01_some_cron_job. Les commandes sont exécutées par ordre alphabétique afin que le 01 s'assure qu'il est exécuté en tant que première commande.
La commande prend alors le contenu d'un fichier appelé some_cron_job.txt et l'ajoute à un fichier appelé some_cron_job dans /etc/cron.d.
La commande modifie ensuite les autorisations sur le fichier /etc/cron.d/some_cron_job.
La clé leader_only garantit que la commande n'est exécutée que sur l'instance ec2 considérée comme leader. Plutôt que de s'exécuter sur chaque instance ec2 que vous pourriez avoir en cours d'exécution.
Créez ensuite un fichier appelé some_cron_job.txt dans le dossier .ebextensions. Vous placerez vos tâches cron dans ce fichier.
Donc par exemple:
Ainsi, cette tâche cron s'exécutera toutes les minutes de chaque heure de chaque jour en tant qu'utilisateur root et rejettera la sortie vers / dev / null. / usr / bin / php est le chemin vers php. Remplacez ensuite some-php-script-here par le chemin de votre fichier php. Cela suppose évidemment que votre tâche cron doit exécuter un fichier PHP.
Assurez-vous également que le fichier some_cron_job.txt a une nouvelle ligne à la fin du fichier, comme le dit le commentaire. Sinon, cron ne fonctionnera pas.
Mise à jour: il y a un problème avec cette solution lorsque Elastic Beanstalk fait évoluer vos instances. Par exemple, disons que vous avez une instance avec le travail cron en cours d'exécution. Vous obtenez une augmentation du trafic donc Elastic Beanstalk vous met à l'échelle jusqu'à deux instances. Le leader_only garantira que vous n'avez qu'un seul travail cron en cours d'exécution entre les deux instances. Votre trafic diminue et Elastic Beanstalk vous réduit à une instance. Mais au lieu de terminer la deuxième instance, Elastic Beanstalk met fin à la première instance qui était le leader. Vous n'avez plus de tâches cron en cours d'exécution car elles ne s'exécutaient que sur la première instance qui a été arrêtée. Voir les commentaires ci-dessous.
Mise à jour 2: Précisez -le simplement à partir des commentaires ci-dessous: AWS dispose désormais d'une protection contre la résiliation automatique des instances. Activez-le simplement sur votre instance leader et vous êtes prêt à partir. - Nicolás Arévalo 28 octobre 16 à 9:23
la source
01_some_cron_job
à02_some_cron_job
et a ajouté ce01_remove_cron_jobs
qui suit:command: "rm /etc/cron.d/cron_jobs || exit 0"
. De cette façon, après chaque déploiement, seul le chef de file aura lecron_jobs
fichier. Si les dirigeants changent, vous pouvez simplement redéployer et les crons seront corrigés pour fonctionner à nouveau.leader_only
propriété. Il n'est utilisé que pendant le déploiement et si vousC'est la façon officielle de le faire maintenant (2015+). Veuillez essayer ceci d'abord, c'est de loin la méthode la plus simple actuellement disponible et la plus fiable également.
Selon la documentation actuelle, on est capable d'exécuter des tâches périodiques sur leur soi-disant niveau de travail .
Citant la documentation:
La partie sur cron.yaml est également intéressante :
Mise à jour: nous avons pu obtenir ce travail. Voici quelques pièges importants tirés de notre expérience (plateforme Node.js):
eb ssh
) et exécutezcat /var/log/aws-sqsd/default.log
. Il devrait signaler commeaws-sqsd 2.0 (2015-02-18)
. Si vous n'avez pas la version 2.0, un problème est survenu lors de la création de votre environnement et vous devez en créer un comme indiqué ci-dessus.la source
Concernant la réponse de jamieb, et comme le mentionne alrdinleal, vous pouvez utiliser la propriété 'leader_only' pour vous assurer qu'une seule instance EC2 exécute la tâche cron.
Citation tirée de http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html :
J'essaie de réaliser une chose similaire sur mon eb, donc je mettrai à jour mon message si je le résous.
METTRE À JOUR:
Ok, j'ai maintenant des cronjobs de travail en utilisant la configuration eb suivante:
Essentiellement, je crée un fichier temporaire avec les cronjobs, puis je configure le crontab pour qu'il lise à partir du fichier temporaire, puis je supprime le fichier temporaire par la suite. J'espère que cela t'aides.
la source
Comme mentionné ci-dessus, le défaut fondamental lors de l'établissement de toute configuration crontab est que cela ne se produit qu'au moment du déploiement. Lorsque le cluster est automatiquement mis à l'échelle, puis redescendu, il est préférable d'être également le premier serveur désactivé. De plus, il n'y aurait pas de basculement, ce qui était pour moi essentiel.
J'ai fait des recherches, puis j'ai discuté avec notre spécialiste des comptes AWS pour faire remonter des idées et valider la solution que j'ai proposée. Vous pouvez accomplir cela avec OpsWorks , même si c'est un peu comme utiliser une maison pour tuer une mouche. Il est également possible d'utiliser Data Pipeline avec Task Runner , mais cela a une capacité limitée dans les scripts qu'il peut exécuter, et j'avais besoin de pouvoir exécuter des scripts PHP, avec accès à toute la base de code. Vous pouvez également dédier une instance EC2 en dehors du cluster ElasticBeanstalk, mais vous n'avez pas de reprise en ligne.
Voici donc ce que j'ai proposé, qui n'est apparemment pas conventionnel (comme l'a commenté le représentant AWS) et peut être considéré comme un piratage, mais cela fonctionne et est solide avec le basculement. J'ai choisi une solution de codage utilisant le SDK, que je montrerai en PHP, bien que vous puissiez faire la même méthode dans n'importe quelle langue que vous préférez.
Alors parcourez ceci et comment cela fonctionne ... Vous appelez des scripts depuis crontab comme vous le feriez normalement sur chaque instance EC2. Chaque script l'inclut au début (ou inclut un seul fichier pour chacun, tel que je l'utilise), qui établit un objet ElasticBeanstalk et récupère une liste de toutes les instances. Il n'utilise que le premier serveur de la liste et vérifie s'il correspond à lui-même, et s'il le fait, il continue, sinon il meurt et se ferme. J'ai vérifié et la liste renvoyée semble être cohérente, ce qui, techniquement, ne doit être cohérente que pendant une minute environ, car chaque instance exécute le cron planifié. Si cela change, cela n'a pas d'importance, car encore une fois, cela n'est pertinent que pour cette petite fenêtre.
Ce n'est en aucun cas élégant, mais adapté à nos besoins spécifiques - qui n'était pas d'augmenter les coûts avec un service supplémentaire ou d'avoir une instance EC2 dédiée, et aurait un basculement en cas de panne. Nos scripts cron exécutent des scripts de maintenance qui sont placés dans SQS et chaque serveur du cluster aide à s'exécuter. Au moins, cela peut vous donner une autre option si elle répond à vos besoins.
-Davey
la source
$instanceId = file_get_contents("http://instance-data/latest/meta-data/instance-id");
Ensuite, utilisez simplement cette variable $ instanceId pour faire la comparaison.J'ai parlé à un agent de support AWS et c'est ainsi que nous avons fait en sorte que cela fonctionne pour moi. Solution 2015:
Créez un fichier dans votre répertoire .ebextensions avec votre_nom_fichier.config. Dans l'entrée du fichier de configuration:
Cette solution présente 2 inconvénients:
Solution de contournement:
Caveat:
Vous n'auriez pas à définir les rôles IAM si vous utilisez le rôle beanstalk par défaut.
la source
Si vous utilisez Rails, vous pouvez utiliser la gemme every-sensitivebeanstalk . Il vous permet d'exécuter des tâches cron sur toutes les instances ou sur une seule. Il vérifie toutes les minutes pour s'assurer qu'il n'y a qu'une seule instance "leader" et promouvra automatiquement un serveur en "leader" s'il n'y en a pas. Cela est nécessaire car Elastic Beanstalk n'a le concept de leader que lors du déploiement et peut arrêter n'importe quelle instance à tout moment pendant la mise à l'échelle.
MISE À JOUR J'ai opté pour AWS OpsWorks et je ne gère plus ce joyau. Si vous avez besoin de plus de fonctionnalités que celles disponibles dans les bases d'Elastic Beanstalk, je vous recommande vivement de passer à OpsWorks.
la source
Vous ne voulez vraiment pas exécuter de tâches cron sur Elastic Beanstalk. Étant donné que vous aurez plusieurs instances d'application, cela peut entraîner des conditions de concurrence et d'autres problèmes étranges. J'ai récemment blogué à ce sujet (4ème ou 5ème astuce en bas de la page). La version courte: Selon l'application, utilisez une file d' attente d'emploi comme SQS ou une solution tierce comme iron.io .
la source
2017: Si vous utilisez Laravel5 +
Il vous suffit de 2 minutes pour le configurer:
installer laravel-aws-worker
composer require dusterio/laravel-aws-worker
ajoutez un cron.yaml dans le dossier racine:
C'est tout!
Toute votre tâche
App\Console\Kernel
sera maintenant exécutéeInstructions détaillées et explications: https://github.com/dusterio/laravel-aws-worker
Comment écrire des tâches à l'intérieur de Laravel: https://laravel.com/docs/5.4/scheduling
la source
Une solution plus lisible en utilisant
files
au lieu decontainer_commands
:Notez que le format diffère du format crontab habituel en ce qu'il spécifie l'utilisateur sous lequel exécuter la commande.
la source
Mon 1 centime de contribution pour 2018
Voici la bonne façon de le faire (en utilisant
django/python
et en appliquantdjango_crontab
):à l'intérieur du
.ebextensions
dossier, créez un fichier comme celui-ci98_cron.config
:Il doit être
container_commands
au lieu decommands
la source
Quelqu'un s'interroge sur les problèmes de mise à l'échelle automatique de leader_only lorsque de nouveaux leaders apparaissent. Je n'arrive pas à comprendre comment répondre à leurs commentaires, mais consultez ce lien: http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling- environnement/
la source
Le dernier exemple d'Amazon est le plus simple et le plus efficace (tâches périodiques):
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features-managing-env-tiers.html
où vous créez un niveau de travail distinct pour exécuter l'un de vos travaux cron. Créez le fichier cron.yaml et placez-le dans votre dossier racine. Un problème que j'ai eu (après que cron ne semblait pas s'exécuter) était de constater que mon CodePipeline n'avait pas l'autorité pour effectuer une modification dynamodb. Sur cette base, après l'ajout d'un accès FullDynamoDB sous IAM -> rôles -> yourpipeline et le redéploiement (élastique beanstalk), cela a parfaitement fonctionné.
la source
Voici une explication complète de la solution:
http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/
la source
Nous nous débattons donc avec cela depuis un moment et après quelques discussions avec un représentant AWS, j'ai finalement trouvé ce que je pense être la meilleure solution.
L'utilisation d'un niveau de travail avec cron.yaml est certainement la solution la plus simple. Cependant, ce que la documentation ne précise pas, c'est que cela placera le travail à la fin de la file d'attente SQS que vous utilisez pour exécuter vos travaux. Si vos tâches cron sont sensibles au temps (comme beaucoup le sont), ce n'est pas acceptable, car cela dépendrait de la taille de la file d'attente. Une option consiste à utiliser un environnement complètement séparé juste pour exécuter des tâches cron, mais je pense que c'est exagéré.
Certaines des autres options, comme vérifier si vous êtes la première instance de la liste, ne sont pas non plus idéales. Que faire si la première instance actuelle est en train de s'arrêter?
La protection d'instance peut également entraîner des problèmes - que se passe-t-il si cette instance est verrouillée / gelée?
Il est important de comprendre comment AWS gère lui-même la fonctionnalité cron.yaml. Il existe un démon SQS qui utilise une table Dynamo pour gérer "l'élection du chef". Il écrit fréquemment dans cette table, et si le leader actuel n'a pas écrit depuis peu de temps, l'instance suivante prendra le relais en tant que leader. C'est ainsi que le démon décide quelle instance doit lancer le travail dans la file d'attente SQS.
Nous pouvons réutiliser la fonctionnalité existante plutôt que d'essayer de réécrire la nôtre. Vous pouvez voir la solution complète ici: https://gist.github.com/dorner/4517fe2b8c79ccb3971084ec28267f27
C'est dans Ruby, mais vous pouvez facilement l'adapter à n'importe quel autre langage doté du SDK AWS. Essentiellement, il vérifie le chef actuel, puis vérifie l'état pour s'assurer qu'il est en bon état. Il bouclera jusqu'à ce qu'un leader actuel soit dans un bon état, et si l'instance actuelle est le leader, exécutez le travail.
la source
http://docs.aws.amazon.com/autoscaling/latest/userguide/as-instance-termination.html#instance-protection
la source
J'avais une autre solution à cela si un fichier php doit être exécuté via cron et si vous avez défini des instances NAT, vous pouvez mettre cronjob sur l'instance NAT et exécuter le fichier php via wget.
la source
voici un correctif au cas où vous voudriez faire cela en PHP. Vous avez juste besoin de cronjob.config dans votre dossier .ebextensions pour le faire fonctionner comme ça.
les envvars récupèrent les variables d'environnement pour les fichiers. Vous pouvez déboguer la sortie sur le tmp / sendemail.log comme ci-dessus.
J'espère que cela aide quelqu'un car cela nous a sûrement aidés!
la source
Sur la base des principes de la réponse de user1599237 , où vous laissez les tâches cron s'exécuter sur toutes les instances, mais au début des tâches, déterminez si elles doivent être autorisées à s'exécuter, j'ai fait une autre solution.
Au lieu de regarder les instances en cours d'exécution (et de devoir stocker votre clé et votre secret AWS), j'utilise la base de données MySQL à laquelle je me connecte déjà à partir de toutes les instances.
Il n'y a pas d'inconvénients, seulement des points positifs:
Vous pouvez également utiliser un système de fichiers communément partagé (comme AWS EFS via le protocole NFS) au lieu d'une base de données.
La solution suivante est créée dans le framework PHP Yii mais vous pouvez facilement l'adapter à un autre framework et langage. Le gestionnaire d'exceptions
Yii::$app->system
est également un module à moi. Remplacez-le par tout ce que vous utilisez.Voici le schéma de base de données que j'utilise:
la source