Ich würde gerne wissen, ob es eine Möglichkeit gibt, einen Cronjob / eine Aufgabe so einzurichten, dass sie jede Minute ausgeführt wird. Derzeit sollte jede meiner Instanzen diese Aufgabe ausführen können.
Folgendes habe ich in den Konfigurationsdateien erfolglos versucht:
container_commands:
01cronjobs:
command: echo "*/1 * * * * root php /etc/httpd/myscript.php"
Ich bin mir nicht sicher, ob dies der richtige Weg ist
Irgendwelche Ideen?
Antworten:
So habe ich Elastic Beanstalk einen Cron-Job hinzugefügt:
Erstellen Sie im Stammverzeichnis Ihrer Anwendung einen Ordner mit dem Namen .ebextensions, falls dieser noch nicht vorhanden ist. Erstellen Sie dann eine Konfigurationsdatei im Ordner .ebextensions. Ich werde example.config zur Veranschaulichung verwenden. Fügen Sie dies dann zu example.config hinzu
Dies ist eine YAML-Konfigurationsdatei für Elastic Beanstalk. Stellen Sie beim Kopieren in Ihren Texteditor sicher, dass Ihr Texteditor Leerzeichen anstelle von Tabulatoren verwendet. Andernfalls wird ein YAML-Fehler angezeigt, wenn Sie diesen an EB senden.
Dazu wird ein Befehl mit dem Namen 01_some_cron_job erstellt. Befehle werden in alphabetischer Reihenfolge ausgeführt, sodass die 01 sicherstellt, dass sie als erster Befehl ausgeführt wird.
Der Befehl nimmt dann den Inhalt einer Datei mit dem Namen some_cron_job.txt und fügt ihn einer Datei mit dem Namen some_cron_job in /etc/cron.d hinzu.
Der Befehl ändert dann die Berechtigungen für die Datei /etc/cron.d/some_cron_job.
Der key_only-Schlüssel stellt sicher, dass der Befehl nur auf der ec2-Instanz ausgeführt wird, die als Leader betrachtet wird. Anstatt auf jeder ec2-Instanz zu laufen, die Sie möglicherweise ausgeführt haben.
Erstellen Sie dann eine Datei mit dem Namen some_cron_job.txt im Ordner .ebextensions. Sie werden Ihre Cron-Jobs in dieser Datei platzieren.
Also zum Beispiel:
Dieser Cron-Job wird also jede Minute jeder Stunde eines jeden Tages als Root-Benutzer ausgeführt und verwirft die Ausgabe nach / dev / null. / usr / bin / php ist der Pfad zu PHP. Ersetzen Sie dann some-php-script-here durch den Pfad zu Ihrer PHP-Datei. Dies setzt natürlich voraus, dass Ihr Cron-Job eine PHP-Datei ausführen muss.
Stellen Sie außerdem sicher, dass die Datei some_cron_job.txt am Ende der Datei eine neue Zeile enthält, wie im Kommentar angegeben. Sonst läuft cron nicht.
Update: Bei dieser Lösung tritt ein Problem auf, wenn Elastic Beanstalk Ihre Instanzen skaliert. Angenommen, Sie haben eine Instanz, in der der Cron-Job ausgeführt wird. Sie erhalten eine Zunahme des Datenverkehrs, sodass Elastic Beanstalk Sie auf zwei Instanzen skaliert. Leader_only stellt sicher, dass zwischen den beiden Instanzen nur ein Cron-Job ausgeführt wird. Ihr Datenverkehr nimmt ab und Elastic Beanstalk reduziert Sie auf eine Instanz. Anstatt die zweite Instanz zu beenden, beendet Elastic Beanstalk die erste Instanz, die der Anführer war. Sie haben jetzt keine Cron-Jobs mehr ausgeführt, da sie nur auf der ersten Instanz ausgeführt wurden, die beendet wurde. Siehe die Kommentare unten.
Update 2: Machen Sie dies nur anhand der folgenden Kommentare deutlich: AWS ist jetzt vor automatischer Instanzbeendigung geschützt. Aktivieren Sie es einfach auf Ihrer Leader-Instanz und Sie können loslegen. - Nicolás Arévalo 28. Oktober 16 um 9:23 Uhr
quelle
01_some_cron_job
zu02_some_cron_job
und fügte hinzu ,01_remove_cron_jobs
mit dem folgenden:command: "rm /etc/cron.d/cron_jobs || exit 0"
. Auf diese Weise verfügt nach jeder Bereitstellung nur der Leiter über diecron_jobs
Datei. Wenn sich die Anführer ändern, können Sie sie einfach neu bereitstellen, und die Cron werden so repariert, dass sie nur noch einmal ausgeführt werden.leader_only
Eigentum zu verlassen. Es wird nur während des Einsatzes verwendet und wenn Sie skalieren oder Ihr „Führer“ Instanz versagt Sie sind verpflichtet , Probleme haben ReferenzDies ist der offizielle Weg, dies jetzt zu tun (2015+). Bitte versuchen Sie dies zuerst, es ist bei weitem die einfachste derzeit verfügbare Methode und auch die zuverlässigste.
Nach aktuellen Dokumenten kann man periodische Aufgaben auf der sogenannten Worker-Ebene ausführen .
Zitieren der Dokumentation:
Interessant ist auch der Teil über cron.yaml :
Update: Wir konnten diese Arbeit bekommen. Hier sind einige wichtige Fallstricke aus unserer Erfahrung (Node.js Plattform):
eb ssh
) und führen Sie es auscat /var/log/aws-sqsd/default.log
. Es sollte als meldenaws-sqsd 2.0 (2015-02-18)
. Wenn Sie keine 2.0-Version haben, ist beim Erstellen Ihrer Umgebung ein Fehler aufgetreten, und Sie müssen wie oben angegeben eine neue erstellen.quelle
In Bezug auf die Antwort von jamieb und wie bereits erwähnt, können Sie die Eigenschaft 'Leader_only' verwenden, um sicherzustellen, dass nur eine EC2-Instanz den Cron-Job ausführt.
Zitat aus http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html :
Ich versuche, eine ähnliche Sache auf meinem eb zu erreichen, also werde ich meinen Beitrag aktualisieren, wenn ich es löse.
AKTUALISIEREN:
Ok, ich habe jetzt arbeitende Cronjobs mit der folgenden eb-Konfiguration:
Im Wesentlichen erstelle ich eine temporäre Datei mit den Cronjobs und setze die Crontab so, dass sie aus der temporären Datei liest. Anschließend lösche ich die temporäre Datei. Hoffe das hilft.
quelle
Wie oben erwähnt, besteht der grundlegende Fehler beim Einrichten einer Crontab-Konfiguration darin, dass dies nur bei der Bereitstellung geschieht. Wenn der Cluster automatisch vergrößert und dann wieder heruntergefahren wird, wird bevorzugt, dass auch der erste Server ausgeschaltet wird. Außerdem würde es kein Failover geben, was für mich kritisch war.
Ich habe einige Nachforschungen angestellt und dann mit unserem AWS-Kontospezialisten gesprochen, um Ideen auszutauschen und die von mir entwickelte Lösung zu validieren. Sie können dies mit OpsWorks erreichen , obwohl es ein bisschen so ist, als würde man ein Haus benutzen, um eine Fliege zu töten. Es ist auch möglich, Data Pipeline mit Task Runner zu verwenden , dies hat jedoch nur begrenzte Möglichkeiten in den Skripten, die ausgeführt werden können, und ich musste in der Lage sein, PHP-Skripte mit Zugriff auf die gesamte Codebasis auszuführen. Sie können auch eine EC2-Instanz außerhalb des ElasticBeanstalk-Clusters zuweisen, haben dann aber kein erneutes Failover.
Hier ist also, was ich mir ausgedacht habe, was anscheinend unkonventionell ist (wie der AWS-Vertreter kommentierte) und als Hack angesehen werden kann, aber es funktioniert und solide mit Failover ist. Ich habe eine Codierungslösung mit dem SDK ausgewählt, die ich in PHP zeigen werde, obwohl Sie dieselbe Methode in jeder Sprache ausführen können, die Sie bevorzugen.
Gehen Sie dies durch und wie es funktioniert ... Sie rufen Skripte von crontab auf, wie Sie es normalerweise auf jeder EC2-Instanz tun würden. Jedes Skript enthält dies am Anfang (oder enthält jeweils eine einzelne Datei, wie ich es verwende), wodurch ein ElasticBeanstalk-Objekt erstellt und eine Liste aller Instanzen abgerufen wird. Es verwendet nur den ersten Server in der Liste und prüft, ob es mit sich selbst übereinstimmt. Wenn dies der Fall ist, wird es fortgesetzt, andernfalls stirbt es und wird geschlossen. Ich habe es überprüft und die zurückgegebene Liste scheint konsistent zu sein. Technisch gesehen muss sie nur etwa eine Minute lang konsistent sein, da jede Instanz das geplante Cron ausführt. Wenn es sich ändert, spielt es keine Rolle, da es wiederum nur für dieses kleine Fenster relevant ist.
Dies ist keineswegs elegant, entspricht jedoch unseren spezifischen Anforderungen - was nicht darin bestand, die Kosten durch einen zusätzlichen Service zu erhöhen oder eine dedizierte EC2-Instanz zu haben, und im Falle eines Ausfalls ein Failover hätte. Unsere Cron-Skripte führen Wartungsskripte aus, die in SQS abgelegt werden, und jeder Server im Cluster hilft bei der Ausführung. Zumindest kann dies Ihnen eine alternative Option bieten, wenn es Ihren Anforderungen entspricht.
-Davey
quelle
$instanceId = file_get_contents("http://instance-data/latest/meta-data/instance-id");
dann einfach diese $ instanceId var, um den Vergleich durchzuführen .Ich habe mit einem AWS-Support-Mitarbeiter gesprochen, und so haben wir das für mich zum Laufen gebracht. Lösung 2015:
Erstellen Sie eine Datei in Ihrem Verzeichnis .ebextensions mit Ihrem_Dateinamen.config. In der Konfigurationsdatei geben Sie Folgendes ein:
Diese Lösung hat zwei Nachteile:
Problemumgehung:
Vorbehalt:
Sie müssten die IAM-Rollen nicht festlegen, wenn Sie die Standard-Beanstalk-Rolle verwenden.
quelle
Wenn Sie Rails verwenden, können Sie den Edelstein für immer elastische Bohnenstiele verwenden . Sie können Cron-Jobs entweder auf allen oder nur auf einer Instanz ausführen. Es überprüft jede Minute, ob es nur eine "Leader" -Instanz gibt, und befördert automatisch einen Server zum "Leader", wenn es keine gibt. Dies ist erforderlich, da Elastic Beanstalk nur das Konzept des Leader während der Bereitstellung hat und jede Instanz während der Skalierung jederzeit herunterfahren kann.
UPDATE Ich habe auf AWS OpsWorks umgestellt und pflege dieses Juwel nicht mehr. Wenn Sie mehr Funktionen benötigen, als in den Grundlagen von Elastic Beanstalk verfügbar sind, empfehle ich dringend, zu OpsWorks zu wechseln.
quelle
Sie möchten wirklich keine Cron-Jobs auf Elastic Beanstalk ausführen. Da Sie mehrere Anwendungsinstanzen haben, kann dies zu Rennbedingungen und anderen merkwürdigen Problemen führen. Ich habe kürzlich darüber gebloggt (4. oder 5. Tipp auf der Seite). Die Kurzversion: Je nach Anwendung, verwenden Sie eine Job - Warteschlange wie SQS oder eine Lösung von Drittanbietern wie iron.io .
quelle
2017: Wenn Sie Laravel5 + verwenden
Sie brauchen nur 2 Minuten, um es zu konfigurieren:
installiere laravel-aws-worker
composer require dusterio/laravel-aws-worker
Fügen Sie dem Stammordner eine cron.yaml hinzu:
Das ist es!
Alle Ihre Aufgaben
App\Console\Kernel
werden nun ausgeführtDetaillierte Anweisungen und Erklärungen: https://github.com/dusterio/laravel-aws-worker
So schreiben Sie Aufgaben in Laravel: https://laravel.com/docs/5.4/scheduling
quelle
Eine lesbare Lösung unter Verwendung
files
anstelle voncontainer_commands
:Beachten Sie, dass sich das Format vom üblichen Crontab-Format dadurch unterscheidet, dass es den Benutzer angibt, unter dem der Befehl ausgeführt werden soll.
quelle
Mein 1 Cent Beitrag für 2018
Hier ist der richtige Weg, dies zu tun (mit
django/python
unddjango_crontab
App):Innerhalb des
.ebextensions
Ordners erstellen Sie eine Datei wie folgt98_cron.config
:Es muss
container_commands
statt seincommands
quelle
Jemand wunderte sich über die Probleme mit der automatischen Skalierung von Leader_only, wenn neue Leader auftauchen. Ich kann nicht herausfinden, wie ich auf ihre Kommentare antworten soll, aber siehe diesen Link: http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling- Umgebung/
quelle
Das neueste Beispiel von Amazon ist das einfachste und effizienteste (regelmäßige Aufgaben):
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features-managing-env-tiers.html
Hier erstellen Sie eine separate Worker-Ebene, um einen Ihrer Cron-Jobs auszuführen. Erstellen Sie die Datei cron.yaml und legen Sie sie in Ihrem Stammordner ab. Ein Problem, das ich hatte (nachdem cron anscheinend nicht ausgeführt wurde), war die Feststellung, dass meine CodePipeline nicht befugt war, eine Dynamodb-Änderung durchzuführen. Basierend darauf hat es nach dem Hinzufügen des FullDynamoDB-Zugriffs unter IAM -> Rollen -> Yourpipeline und dem erneuten Bereitstellen (elastische Bohnenstange) perfekt funktioniert.
quelle
Hier ist eine vollständige Erklärung der Lösung:
http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/
quelle
Wir haben also eine Weile damit zu kämpfen und nach einigen Diskussionen mit einem AWS-Vertreter habe ich endlich das gefunden, was ich für die beste Lösung halte.
Die Verwendung einer Worker-Ebene mit cron.yaml ist definitiv die einfachste Lösung. In der Dokumentation wird jedoch nicht klargestellt, dass der Job dadurch am Ende der SQS-Warteschlange steht, mit der Sie Ihre Jobs tatsächlich ausführen. Wenn Ihre Cron-Jobs zeitkritisch sind (wie viele), ist dies nicht akzeptabel, da dies von der Größe der Warteschlange abhängt. Eine Möglichkeit besteht darin, eine völlig separate Umgebung zu verwenden, um nur Cron-Jobs auszuführen, aber ich denke, das ist übertrieben.
Einige der anderen Optionen, z. B. die Überprüfung, ob Sie die erste Instanz in der Liste sind, sind ebenfalls nicht ideal. Was ist, wenn die aktuelle erste Instanz gerade heruntergefahren wird?
Der Instanzschutz kann auch mit Problemen verbunden sein - was ist, wenn diese Instanz gesperrt / eingefroren wird?
Es ist wichtig zu verstehen, wie AWS selbst die Funktionalität von cron.yaml verwaltet. Es gibt einen SQS-Daemon, der eine Dynamo-Tabelle verwendet, um "Leader-Wahlen" durchzuführen. Es schreibt häufig in diese Tabelle, und wenn der aktuelle Anführer in kurzer Zeit nicht geschrieben hat, übernimmt die nächste Instanz die Leitung. Auf diese Weise entscheidet der Dämon, welche Instanz den Job in der SQS-Warteschlange auslösen soll.
Wir können die vorhandene Funktionalität neu verwenden, anstatt zu versuchen, unsere eigene neu zu schreiben. Die vollständige Lösung finden Sie hier: https://gist.github.com/dorner/4517fe2b8c79ccb3971084ec28267f27
Das ist in Ruby, aber Sie können es leicht an jede andere Sprache anpassen, die das AWS SDK enthält. Im Wesentlichen wird der aktuelle Anführer und anschließend der Status überprüft, um sicherzustellen, dass er sich in einem guten Zustand befindet. Es wird eine Schleife ausgeführt, bis sich ein aktueller Leader in einem guten Zustand befindet. Wenn die aktuelle Instanz der Leader ist, führen Sie den Job aus.
quelle
http://docs.aws.amazon.com/autoscaling/latest/userguide/as-instance-termination.html#instance-protection
quelle
Ich hatte eine andere Lösung dafür, wenn eine PHP-Datei über Cron ausgeführt werden muss und wenn Sie NAT-Instanzen festgelegt haben, können Sie Cronjob auf NAT-Instanz setzen und PHP-Datei über Wget ausführen.
quelle
Hier ist ein Fix für den Fall, dass Sie dies in PHP tun möchten. Sie brauchen nur cronjob.config in Ihrem .ebextensions-Ordner, damit es so funktioniert.
Der Envvars ruft die Umgebungsvariablen für die Dateien ab. Sie können die Ausgabe in der Datei tmp / sendemail.log wie oben beschrieben debuggen.
Hoffe das hilft jemandem, da es uns sicherlich geholfen hat!
quelle
Basierend auf den Prinzipien der Antwort von user1599237 , bei der Sie die Cron-Jobs auf allen Instanzen , aber stattdessen zu Beginn der Jobs bestimmen, ob sie ausgeführt werden dürfen, habe ich eine andere Lösung gefunden.
Anstatt die laufenden Instanzen zu betrachten (und Ihren AWS-Schlüssel und Ihr Geheimnis zu speichern), verwende ich die MySQL-Datenbank, mit der ich bereits von allen Instanzen aus eine Verbindung herstelle.
Es hat keine Nachteile, nur positive:
Alternativ können Sie anstelle einer Datenbank auch ein gemeinsam genutztes Dateisystem (wie AWS EFS über das NFS-Protokoll) verwenden.
Die folgende Lösung wird im PHP-Framework Yii erstellt , Sie können sie jedoch problemlos für ein anderes Framework und eine andere Sprache anpassen. Auch der Exception Handler
Yii::$app->system
ist ein eigenes Modul. Ersetzen Sie es durch das, was Sie verwenden.Dies ist das Datenbankschema, das ich verwende:
quelle