Hallo zusammen! Mein Name ist Kirill und ich bin CTO bei Adapty. Der Großteil unserer Architektur basiert auf AWS, und heute werde ich euch erzählen, wie wir unsere Serverkosten um das Dreifache gesenkt haben, indem wir Spot-Instances in unserer Produktionsumgebung eingesetzt haben, sowie, wie man deren automatisches Scaling einrichtet. Zuerst gibt es einen Überblick über die Funktionsweise, gefolgt von einer detaillierten Anleitung zur Implementierung.
Was sind Spot-Instances?
Instances sind Server anderer AWS-Nutzer, die derzeit ungenutzt sind und zu stark reduzierten Preisen verkauft werden (Amazon spricht von bis zu 90 % Rabatt, laut unserer Erfahrung liegt der Durchschnitt bei etwa 3x, variierend je nach Region, AZ und Instanztyp). Der Hauptunterschied zu den regulären Instanzen besteht darin, dass sie jederzeit abgeschaltet werden können. Daher haben wir lange Zeit geglaubt, dass sie für Entwicklungsumgebungen oder für Berechnungen, bei denen Zwischenergebnisse in S3 oder in einer Datenbank gespeichert werden, geeignet sind, jedoch nicht für die Produktion. Es gibt Drittanbieter-Lösungen, die die Nutzung von Spot-Instanzen in der Produktion ermöglichen, aber für unseren Fall sind viele Workarounds erforderlich, weshalb wir sie nicht implementiert haben. Der in diesem Artikel beschriebene Ansatz funktioniert vollständig innerhalb der Standardfunktionalität von AWS, ohne zusätzliche Skripte, Cronjobs usw.
Im Folgenden zeige ich einige Screenshots, die die Preishistorie der Spot-Instanzen darstellen.
m5.large in der Region eu-west-1 (Irland). Der Preis ist in den letzten 3 Monaten überwiegend stabil gewesen, derzeit beträgt die Einsparung 2,9x.

m5.large in der Region us-east-1 (N. Virginia). Der Preis verändert sich ständig über einen Zeitraum von 3 Monaten, aktuell beträgt die Einsparung zwischen 2,3x und 2,8x, abhängig von der Verfügbarkeitszone.

t3.small in der Region us-east-1 (N. Virginia). Der Preis ist stabil über einen Zeitraum von 3 Monaten, aktuell beträgt die Einsparung 3,4x.

Architektur des Dienstes
Die grundlegende Architektur des Dienstes, über den wir in diesem Artikel sprechen werden, ist in der folgenden Abbildung dargestellt.

Application Load Balancer → EC2 Target Group → Elastic Container Service
Als Lastenausgleich wird der Application Load Balancer (ALB) verwendet, der Anfragen an die EC2 Target Group (TG) sendet. Die TG sorgt dafür, dass die Ports auf den Instanzen für den ALB geöffnet werden und mit den Ports der Container im Elastic Container Service (ECS) verbunden sind. ECS ist das Pendant zu Kubernetes bei AWS und verwaltet Docker-Container.
Auf einer Instanz können mehrere Container mit identischen Ports gleichzeitig betrieben werden, weshalb wir diese nicht festlegen können. ECS informiert den TG, dass es einen neuen Task startet (dies wird in der Kubernetes-Terminologie als Pod bezeichnet). Anschließend wird eine Überprüfung der verfügbaren Ports auf der Instanz durchgeführt, und einer dieser Ports wird dem gestarteten Task zugewiesen. Zudem überprüft der TG regelmäßig, ob die Instanz und die API darauf durch einen Health Check funktionieren, und wenn Probleme festgestellt werden, werden keine Anfragen mehr dorthin geleitet.
EC2 Auto Scaling Groups + ECS Capacity Providers
Im obigen Diagramm ist der Dienst EC2 Auto Scaling Groups (ASG) nicht dargestellt. Aus dem Namen geht hervor, dass er für die Skalierung der Instanzen verantwortlich ist. Bis vor kurzem gab es in AWS keine integrierte Möglichkeit, die Anzahl der laufenden Maschinen direkt über ECS zu steuern. ECS erlaubte eine Skalierung der Anzahl der Tasks, zum Beispiel basierend auf der CPU-Nutzung, dem RAM oder der Anzahl der Anfragen. Doch wenn alle freien Instanzen von den Tasks belegt waren, wurden keine neuen Maschinen automatisch gestartet.
Mit dem Auftreten der ECS Capacity Providers (ECS CP) hat sich dies geändert. Jetzt kann jeder Service in ECS mit einer Auto Scaling-Gruppe (ASG) verknüpft werden. Wenn die Tasks nicht auf den laufenden Instanzen Platz finden, werden neue Instanzen gestartet (natürlich innerhalb der festgelegten ASG-Limits). Umgekehrt, wenn ECS CP ungenutzte Instanzen ohne Tasks erkennt, gibt es der ASG den Befehl, diese abzuschalten. ECS CP ermöglicht es auch, einen Zielauslastungsprozentsatz für die Instanzen anzugeben, sodass jederzeit eine bestimmte Anzahl an Maschinen verfügbar ist, um Tasks schnell zu skalieren. Darüber werde ich später noch mehr erzählen.
EC2 Launch-Vorlagen
Der letzte Service, über den ich sprechen möchte, bevor ich zur detaillierten Beschreibung der Erstellung dieser Infrastruktur übergehe, sind die EC2 Launch-Vorlagen. Sie ermöglichen es, eine Vorlage zu erstellen, nach der alle Maschinen gestartet werden, um dies nicht jedes Mal von Grund auf neu machen zu müssen. Hier kann man den Typ der zu startenden Maschine, die Sicherheitsgruppe, das Disk-Image und viele weitere Parameter auswählen. Außerdem kann man benutzerdefinierte Daten angeben, die auf alle gestarteten Instanzen angewendet werden. In den benutzerdefinierten Daten können Skripte ausgeführt werden, beispielsweise kann der Inhalt einer Datei bearbeitet werden. .
Einer der wichtigsten Konfigurationsparameter in diesem Artikel ist =true. Wenn dieser Parameter aktiviert ist, wechselt ECS alle Tasks, die auf einer Spothinstanz laufen, in den Status Draining, sobald ein Signal empfangen wird, dass die Spothinstanz abgezogen wird. Es werden keine neuen Tasks mehr auf diese Instanz zugewiesen; wenn es Tasks gibt, die gerade auf diese Instanz ausgerollt werden sollen, werden sie abgebrochen. Anfragen vom Load Balancer hören ebenfalls auf, zu kommen. Die Benachrichtigung über die Entfernung der Instanz erfolgt 2 Minuten vor dem tatsächlichen Ereignis. Daher können Sie Spothinstanzen ohne Datenverlust verwenden, wenn Ihr Dienst keine Aufgaben länger als 2 Minuten ausführt und nichts auf der Festplatte speichert.
Was die Festplatte betrifft – AWS hat kürzlich Die Nutzung des Elastic File System (EFS) zusammen mit ECS ist möglich; dabei stellt selbst die Festplatte kein Hindernis dar. Allerdings haben wir dies nicht getestet, da wir grundsätzlich keine Festplatte zur Speicherung des Zustands benötigen. Standardmäßig werden nach Erhalt eines SIGINT (dies wird zum Zeitpunkt des Wechsels des Tasks in den Status Draining gesendet) alle aktiven Tasks nach 30 Sekunden gestoppt, auch wenn sie nicht rechtzeitig abgeschlossen werden. Diese Zeit kann mit einem Parameter geändert werden. . Wichtig ist, diesen Wert nicht auf mehr als 2 Minuten für Spot-Instances zu setzen.
Erstellung eines Dienstes
Kommen wir nun direkt zur Erstellung des beschriebenen Dienstes. Im Verlauf werde ich einige nützliche Punkte erwähnen, die zuvor nicht angesprochen wurden. Im Grunde handelt es sich um eine Schritt-für-Schritt-Anleitung, jedoch werde ich einige sehr grundlegende oder sehr spezifische Fälle nicht behandeln. Alle Schritte werden in der visuellen AWS-Konsole ausgeführt, können jedoch auch programmatisch mit CloudFormation oder Terraform umgesetzt werden. Bei Adapty verwenden wir Terraform.
EC2 Launch-Vorlage
In diesem Dienst wird eine Konfiguration der Maschinen erstellt, die verwendet werden sollen. Die Verwaltung der Vorlagen erfolgt im Bereich EC2 -> Instances -> Launch templates.
Amazon Machine Image (AMI) — geben Sie das Abbild an, mit dem alle Instanzen gestartet werden. Für ECS sollten Sie in den meisten Fällen das optimierte Abbild von Amazon verwenden. Es wird regelmäßig aktualisiert und enthält alles Notwendige für den Betrieb von ECS. Um die aktuelle ID des Abbilds zu erfahren, gehen Sie zur Seite , wählen Sie die verwendete Region aus und kopieren Sie die AMI-ID dafür. Zum Beispiel ist für die Region us-east-1 die zum Zeitpunkt des Schreibens des Artikels aktuelle ID — ami-00c7c1cf5bdc913ed. Diese ID muss in das Feld "Specify a custom value" eingefügt werden.
Instanztyp — geben Sie den Typ der Instanz an. Wählen Sie denjenigen, der am besten für Ihre Aufgabe geeignet ist.
Schlüsselpaar (Login) — geben Sie das Zertifikat an, mit dem Sie sich bei Bedarf über SSH mit der Instanz verbinden können.
Netzwerkeinstellungen — geben Sie die Netzparameter an. Netzwerkplattform sollte in den meisten Fällen Virtual Private Cloud (VPC) sein. Sicherheitsgruppen — Sicherheitsgruppen für Ihre Instanzen. Da wir einen Load Balancer vor den Instanzen einsetzen, empfehle ich, hier eine Gruppe anzugeben, die eingehende Verbindungen nur vom Load Balancer zulässt. Das bedeutet, Sie haben zwei Sicherheitsgruppen: eine für den Load Balancer, die eingehende Verbindungen aus allen Quellen auf den Ports 80 (HTTP) und 443 (HTTPS) erlaubt, und eine zweite für die Maschinen, die eingehende Verbindungen von der Load Balancer-Gruppe auf beliebigen Ports zulässt. Die ausgehenden Verbindungen in beiden Gruppen sollten über das TCP-Protokoll für alle Ports zu allen Adressen geöffnet sein. Ports und Adressen für ausgehende Verbindungen können eingeschränkt werden, allerdings müssen Sie dann ständig überwachen, dass Sie nicht versuchen, auf einen geschlossenen Port zuzugreifen.
Speicher (Volumes) — wir geben die Festplattenspezifikationen für die Maschinen an. Das Festplattenvolumen darf nicht kleiner sein als das, was im AMI festgelegt ist, für ECS Optimized — 30 GiB.
Erweiterte Details — wir geben zusätzliche Parameter an.
Kaufsoption — möchten wir Spot-Instanzen kaufen. Wir möchten, werden diese Option hier aber nicht aktivieren, sondern in der Auto Scaling-Gruppe einstellen, wo es mehr Optionen gibt.
IAM-Instanzprofil — geben Sie die Rolle an, mit der die Instanzen gestartet werden. Damit die Instanzen in ECS funktionieren, benötigen sie Berechtigungen, die normalerweise in der Rolle liegen. ecsInstanceRole. In einigen Fällen kann sie erstellt werden, falls nicht, hier ist eine Anleitung dazu. Nach der Erstellung geben wir sie im Template an.
Es folgen viele Parameter, in den meisten Fällen können die Standardwerte beibehalten werden, aber jeder von ihnen hat eine verständliche Beschreibung. Ich aktiviere immer die Parameter EBS-optimized instance und T2/T3 Unlimited, wenn verwendet wird, Instanzen.
Benutzerdaten — wir geben die Benutzerdaten an. Wir werden die Datei bearbeiten, /etc/ecs/ecs.configin der die Konfiguration des ECS-Agenten gespeichert ist.
Ein Beispiel dafür, wie Benutzerdaten aussehen könnten:
#!/bin/bash
echo ECS_CLUSTER=DemoApiClusterProd >> /etc/ecs/ecs.config
echo ECS_ENABLE_SPOT_INSTANCE_DRAINING=true >> /etc/ecs/ecs.config
echo ECS_CONTAINER_STOP_TIMEOUT=1m >> /etc/ecs/ecs.config
echo ECS_ENGINE_AUTH_TYPE=docker >> /etc/ecs/ecs.config
echo "ECS_ENGINE_AUTH_DATA={"registry.gitlab.com":{"username":"username","password":"password"}}" >> /etc/ecs/ecs.configECS_CLUSTER=DemoApiClusterProd — dieser Parameter gibt an, dass die Instanz zum Cluster mit dem angegebenen Namen gehört, das heißt, dieser Cluster kann seine Aufgaben auf diesem Server ausführen. Wir haben das Cluster noch nicht erstellt, aber wir werden diesen Namen bei der Erstellung verwenden.
ECS_ENABLE_SPOT_INSTANCE_DRAINING=true — dieser Parameter gibt an, dass beim Empfang des Signals zum Ausschalten einer Spot-Instanz alle Aufgaben darauf in den Status Draining versetzt werden sollen.
ECS_CONTAINER_STOP_TIMEOUT=1m — Dieser Parameter gibt an, dass nach dem Empfang des SIGINT-Signals alle Aufgaben 1 Minute Zeit haben, bevor sie beendet werden.
ECS_ENGINE_AUTH_TYPE=docker — Dieser Parameter gibt an, dass das Docker-Schema als Authentifizierungsmechanismus verwendet wird.
ECS_ENGINE_AUTH_DATA=... — Verbindungsparameter für das private Container-Registry, wo Ihre Docker-Images gespeichert sind. Wenn es öffentlich ist, müssen Sie nichts angeben.
In diesem Artikel werde ich ein öffentliches Image aus Docker Hub verwenden, daher müssen keine Parameter angegeben werden. ECS_ENGINE_AUTH_TYPE und ECS_ENGINE_AUTH_DATA sind nicht notwendig.
Nützliche Information: Es wird empfohlen, AMIs regelmäßig zu aktualisieren, da in neuen Versionen Docker, Linux, der ECS-Agent usw. aktualisiert werden. Um dies nicht zu vergessen, können Sie über neue Versionen. Sie können Benachrichtigungen per E-Mail erhalten und manuell aktualisieren oder eine Lambda-Funktion schreiben, die automatisch eine neue Version des Launch-Templates mit dem aktualisierten AMI erstellt.
EC2 Auto Scaling-Gruppe
Die Auto Scaling-Gruppe ist verantwortlich für das Starten und Skalieren von Instanzen. Die Verwaltung der Gruppen erfolgt im Bereich EC2 -> Auto Scaling -> Auto Scaling-Gruppen.
Launch-Template — Wählen Sie das zuvor erstellte Template aus. Die Version lassen wir auf der Standardversion.
Kaufe Optionen und Instanztypen — Wir geben die Instanztypen für den Cluster an. Adhere to launch template verwendet den Instanztyp aus der Vorlage. Combine purchase options and instance types ermöglicht eine flexible Anpassung der Instanztypen. Wir werden ihn nutzen.
Optionale On-Demand-Basis — die Anzahl der regulären, nicht-spot Instanzen, die immer laufen werden.
On-Demand-Prozentsatz über der Basis — das prozentuale Verhältnis von regulären zu Spot-Instanzen; 50-50 würde gleichmäßig verteilen, 20-80 bedeutet, dass auf jede reguläre Instanz 4 Spot-Instanzen hinzugefügt werden. In diesem Beispiel gebe ich 50-50 an, aber in der Realität machen wir oft 20-80 und in einigen Fällen 0-100.
Instanztypen — hier können zusätzliche Instanztypen angegeben werden, die im Cluster verwendet werden. Wir haben das nie genutzt, da ich den Sinn dieser Funktion nicht ganz verstehe. Möglicherweise hängt es mit den Limits für bestimmte Instanztypen zusammen, aber diese können leicht über den Support erhöht werden. Wenn Sie eine Anwendung wissen, würde ich mich freuen, in den Kommentaren darüber zu lesen.)

Netzwerk — Netzwerkeinstellungen, wählen Sie VPC und Subnetze für die Maschinen; in den meisten Fällen sollten Sie alle verfügbaren Subnetze auswählen.
Lastenverteilung — Einstellungen des Load Balancers, aber das machen wir separat, hier fassen wir nichts an. Überprüfungen der Gesundheit werden später ebenfalls konfiguriert.
Gruppengröße — wir legen die Grenzen für die Anzahl der Maschinen im Cluster und die gewünschte Anzahl der Maschinen beim Start fest. Die Anzahl der Maschinen im Cluster wird nie unter die minimal angegebene Anzahl fallen und nie über die maximale Anzahl hinausgehen, selbst wenn die Metriken eine Skalierung erfordern.
Skalierungsrichtlinien — Parameter für die Skalierung, jedoch skalieren wir basierend auf den laufenden ECS-Aufgaben, daher werden wir die Skalierung später einstellen.
Instanz-Skalierungsschutz — Schutz der Instanzen vor der Löschung beim Herunterskalieren. Wir aktivieren dies, damit das ASG keine Maschine löscht, auf der aktive Aufgaben vorhanden sind. Der Schutz wird für Instanzen, auf denen keine Aufgaben laufen, vom ECS Capacity Provider deaktiviert.
Tags hinzufügen — es können Tags für die Instanzen angegeben werden (dafür muss die Option "Neue Instanzen taggen" aktiviert sein). Ich empfehle, das Tag "Name" anzugeben, damit alle Instanzen, die innerhalb der Gruppe gestartet werden, denselben Namen tragen und bequem in der Konsole betrachtet werden können.

Nach der Erstellung der Gruppe öffnen Sie diese und gehen Sie zum Abschnitt "Erweiterte Konfigurationen", da nicht alle Optionen in der Konsole während der Erstellung sichtbar sind.
Beendigungsrichtlinien — Regeln, die beim Löschen von Instanzen zu beachten sind. Sie werden in der Reihenfolge angewendet. Wir verwenden normalerweise solche, wie im Bild unten. Zuerst werden die Instanzen mit dem ältesten Launch-Template gelöscht (zum Beispiel, wenn wir das AMI aktualisiert haben, wurde eine neue Version erstellt, und alle Instanzen sind bereits darauf umgestiegen). Danach werden die Instanzen ausgewählt, die am nächsten zur nächsten Abrechnungszeit liegen. Schließlich werden die ältesten Instanzen nach dem Startdatum ausgewählt.

Nützliche Information: Um alle Maschinen im Cluster zu aktualisieren, ist es praktisch, . Wenn Sie dies mit einer Lambda-Funktion aus dem vorherigen Schritt kombinieren, haben Sie ein vollständig automatisiertes System zur Aktualisierung der Instanzen. Vor dem Upgrade aller Maschinen müssen Sie den Instance Scale-In-Schutz für alle Instanzen in der Gruppe deaktivieren. Nicht die Gruppenverwaltung, sondern den Schutz der Maschinen selbst, dies erfolgt im Tab Instance Management.
Application Load Balancer und EC2 Zielgruppe
Der Lastenausgleich wird im Abschnitt EC2 → Load Balancing → Load Balancers erstellt. Wir werden den Application Load Balancer verwenden; die Gegenüberstellung verschiedener Typen von Lastenausgleich kann auf der .
Listeners — es macht Sinn, die Ports 80 und 443 einzurichten und eine Weiterleitung von 80 nach 443 mithilfe von Lastenausgleichsregeln einzurichten.
Verfügbarkeitszonen — in den meisten Fällen wählen wir alle Verfügbarkeitszonen aus.
Sicherheitseinstellungen konfigurieren — hier wird das SSL-Zertifikat für den Lastenausgleich angegeben, die bequemste Variante ist — in ACM zu erstellen. Die Unterschiede Sicherheitspolitik können im , die standardmäßig ausgewählt bleiben kann, ELBSecurityPolicy-2016-08. Nach der Erstellung des Lastenausgleichs sehen Sie seinen DNS-Namen, für den Sie CNAME für Ihre Domain einrichten müssen. So sieht das beispielsweise in Cloudflare aus.

Sicherheitsgruppe — wir erstellen oder wählen eine Sicherheitsgruppe für den Lastenausgleich aus. Darüber habe ich etwas weiter oben im Abschnitt EC2-Startvorlage → Netzwerkeinstellungen geschrieben.
Zielgruppe — wir erstellen eine Gruppe, die für das Routing von Anfragen vom Lastenausgleich auf die Maschinen verantwortlich ist und deren Verfügbarkeit überprüft, um sie im Falle von Problemen zu ersetzen. Zieltyp muss Instance sein, Protokoll und Port beliebig, wenn Sie HTTPS für die Kommunikation zwischen Lastenausgleich und Instanzen verwenden, müssen diese das Zertifikat hochladen. Im Rahmen dieses Beispiels werden wir das nicht tun und einfach den Port 80 belassen.
Überprüfungen der Gesundheit — Überprüfungsparameter des Dienstes. In diesem Dienst sollte dies eine separate Anfrage sein, die wichtige Teile der Geschäftslogik umsetzt; in diesem Beispiel lasse ich die Standardeinstellungen unverändert. Danach kann das Anfrageintervall, der Timeout, die Codes für erfolgreiche Antworten usw. ausgewählt werden. In unserem Beispiel geben wir die Erfolgscodes 200-399 an, da das Docker-Image, das verwendet wird, den Code 304 zurückgibt.

Zielregistrierung — Hier werden Maschinen für die Gruppe ausgewählt, aber in unserem Fall wird dies vom ECS erledigt, daher überspringen wir diesen Schritt einfach.
Nützliche Information: Auf der Ebene des Lastenausgleichs können Protokolle aktiviert werden, die in S3 in einem bestimmten . Von dort können sie in externe Dienste für die Analyse exportiert werden, oder man kann SQL-Anfragen direkt an die Daten in S3 mit richten. Das ist praktisch und funktioniert ohne zusätzlichen Code. Ich empfehle auch, die Protokolle aus dem S3-Bucket nach Ablauf einer bestimmten Zeit zu löschen.
ECS-Aufgabendefinition
In den vorherigen Schritten haben wir alles geschafft, was mit der Infrastruktur des Dienstes zu tun hat. Nun wenden wir uns der Beschreibung der Container zu, die wir starten werden. Dies geschieht im Bereich ECS → Task Definitions.
Kompatibilität des Starttyps — wir wählen EC2.
IAM-Rolle für die Ausführung von Aufgaben — wir wählen ecsTaskExecutionRole. Mit ihr werden Protokolle erstellt, der Zugriff auf geheime Variablen gewährt und mehr.
Im Bereich Container Definitions klicken wir auf Add Container.
Bild — Link zum Image mit dem Projektcode. In diesem Beispiel werde ich ein öffentliches Image von Docker Hub verwenden: .
Speicherlimits — Speichergrenzen für den Container. Harmlimit — harter Limit. Wenn der Container den angegebenen Wert überschreitet, wird der Befehl docker kill ausgeführt, und der Container wird sofort beendet. Weichlimit — weiche Begrenzung, der Container kann über den angegebenen Wert hinausgehen, aber bei der Platzierung von Aufgaben auf den Maschinen wird dieser Parameter berücksichtigt. Zum Beispiel, wenn auf der Maschine 4 GiB RAM vorhanden sind und die weiche Begrenzung des Containers 2048 MiB beträgt, können auf dieser Maschine maximal 2 Aufgaben mit diesem Container ausgeführt werden. In der Realität entsprechen 4 GiB RAM etwas weniger als 4096 MiB, dies kann auf der Seite ECS Instanzen im Cluster eingesehen werden. Die weiche Begrenzung darf nicht höher sein als die harte Begrenzung. Es ist wichtig zu verstehen, dass wenn in einer Aufgabe mehrere Container vorhanden sind, deren Begrenzungen sich summieren.
Portzuordnungen – dafür braucht man 10-mal weniger Hardware. Host-Port wenn wir 0 angeben, bedeutet das, dass der Port dynamisch zugewiesen wird und von der Zielgruppe überwacht wird. Container-Port — der Port, an dem Ihre Anwendung läuft, wird häufig im Ausführungsbefehl angegeben oder im Code Ihrer Anwendung, im Dockerfile usw. festgelegt. Für unser Beispiel verwenden wir 3000, da dies im verwendeten Image angegeben ist.
Health-Check — Parameter zur Überprüfung der Funktionalität des Containers, nicht zu verwechseln mit dem, der in der Zielgruppe konfiguriert ist.
Umgebung — Umgebungsparameter. CPU-Einheiten — ähnlich wie die Speicherkapazitäten, jedoch für den Prozessor. Jedes Prozessorkern entspricht 1024 Einheiten; wenn der Server also einen Dual-Core-Prozessor hat und der Container einen Wert von 512 hat, können auf einem Server 4 Aufgaben mit diesem Container ausgeführt werden. CPU-Einheiten entsprechen immer der Anzahl der Kerne, sie können nicht geringfügig geringer sein wie im Fall von Speicher.
Befehl — der Befehl zum Starten des Dienstes innerhalb des Containers, alle Parameter werden durch Kommas angegeben. Das kann gunicorn, npm etc. sein. Wenn nichts angegeben ist, wird der Wert der CMD-Direktive aus dem Dockerfile verwendet. Wir geben an npm,start.
Umgebungsvariablen — die Umgebungsvariablen des Containers. Dies können sowohl einfache Textdaten als auch geheime Variablen aus dem oder .
Speicherung und Protokollierung — hier konfigurieren wir das Logging in CloudWatch Logs (ein Logging-Dienst von AWS). Dazu reicht es, das Kontrollkästchen Auto-configure CloudWatch Logs zu aktivieren. Nach der Erstellung der Task Definition wird automatisch eine Protokollgruppe in CloudWatch erstellt. Standardmäßig werden die Protokolle dort unbegrenzt gespeichert; ich empfehle, den Aufbewahrungszeitraum von Never Expire auf den gewünschten Zeitraum zu ändern. Dies geschieht in den CloudWatch-Protokollgruppen, man muss auf den aktuellen Zeitraum klicken und einen neuen auswählen.

ECS-Cluster und ECS Capacity Provider
Gehen Sie zum Bereich ECS → Cluster, um einen Cluster zu erstellen. Wählen Sie als Vorlage EC2 Linux + Networking.
Clustername — sehr wichtig, verwenden Sie hier denselben Namen wie im Launch Template im Parameter ECS_CLUSTER, in unserem Fall — DemoApiClusterProd. Setzen Sie das Häkchen bei Create an empty cluster. Optional können Sie Container Insights aktivieren, um die Metriken der Dienste in CloudWatch zu betrachten. Wenn Sie alles richtig gemacht haben, sehen Sie im Bereich ECS Instances die Maschinen, die in der Auto Scaling-Gruppe erstellt wurden.

Gehen Sie zum Tab Capacity Providers und erstellen Sie einen neuen. Denken Sie daran, dass dieser benötigt wird, um die Erstellung und das Herunterfahren von Maschinen je nach Anzahl der aktiven ECS-Tasks zu steuern. Es ist wichtig zu beachten, dass der Provider nur an eine Gruppe gebunden werden kann.
Auto Scaling-Gruppe — wählen Sie die zuvor erstellte Gruppe aus.
Managed Scaling — aktivieren, damit der Provider den Dienst skalieren kann.
Target capacity % — welcher Prozentsatz der Maschinenlasten benötigen wir für Aufgaben. Wenn wir 100 % angeben, sind alle Maschinen immer mit aktiven Aufgaben beschäftigt. Bei 50 % sind die Hälfte der Maschinen immer frei. In diesem Fall werden bei einem plötzlichen Anstieg der Last neue Aufgaben sofort auf die freien Maschinen geleitet, ohne dass es notwendig ist, auf die Bereitstellung von Instanzen zu warten.
Verwalteter Terminierungsschutz — aktivieren, diese Einstellung erlaubt dem Provider, den Schutz der Instanzen vor Löschung aufzuheben. Dies geschieht, wenn auf der Maschine keine aktiven Aufgaben vorhanden sind und ermöglicht Target capacity %.
ECS-Service und Skalierungseinstellungen
Der letzte Schritt :) Um einen Dienst zu erstellen, müssen Sie in den zuvor erstellten Cluster auf die Registerkarte Dienste gehen.
Starttyp — müssen Sie auf Switch to capacity provider strategy klicken und den zuvor erstellten Provider auswählen.

Aufgabenbeschreibung — wählen Sie die zuvor erstellte Aufgabenbeschreibung und deren Revision aus.
Service-Name — um Verwirrung zu vermeiden, geben wir immer die gleiche an wie die Aufgabenbeschreibung.
Diensttyp — immer Replica.
Anzahl der Aufgaben — die gewünschte Anzahl aktiver Aufgaben im Dienst. Diese Einstellung wird durch die Skalierung verwaltet, muss aber trotzdem angegeben werden.
Minimale gesunde Prozentzahl und Maximale Prozentzahl — bestimmen das Verhalten der Aufgaben während des Deployments. Die Standardwerte von 100 und 200 bedeuten, dass sich während des Deployments die Anzahl der Aufgaben vervielfacht und anschließend wieder auf den gewünschten Wert zurückkehrt. Wenn Sie 1 Aufgabe haben, min=0 und max=100, wird diese während des Deployments beendet und danach wird eine neue gestartet, was zu einer Unterbrechung führt. Bei 1 Aufgabe, min=50 und max=150, findet das Deployment überhaupt nicht statt, da eine Aufgabe nicht halbiert oder um das 1,5-fache erhöht werden kann.
Deploymentsart — wir lassen Rolling Update.
Platzierungsvorlagen — Regeln zur Platzierung von Aufgaben auf Maschinen. Standardmäßig wird AZ Balanced Spread verwendet, was bedeutet, dass jede neue Aufgabe auf einer neuen Instanz platziert wird, bis die Maschinen in allen Verfügbarkeitszonen gestartet sind. Wir verwenden normalerweise BinPack — CPU und Spread — AZ; mit dieser Politik werden die Aufgaben so dicht wie möglich auf einer Maschine pro CPU platziert. Bei Bedarf wird eine neue Maschine in einer neuen Verfügbarkeitszone erstellt.

Lastenausgleichstyp — wir wählen den Application Load Balancer.
Service IAM-Rolle — wir wählen ecsServiceRole.
Name des Lastenausgleichs — wir wählen den zuvor erstellten Lastenausgleichs.
Grace-Periode für Gesundheitsprüfungen — Pause vor der Durchführung von Überprüfungen zur Funktionsfähigkeit nach dem Rollout einer neuen Aufgabe, wir setzen normalerweise 60 Sekunden.
Container zum Lastenausgleich — im Feld Zielgruppennamen wählen wir die zuvor erstellte Gruppe aus, und alles wird automatisch ausgefüllt.

Service Auto Scaling — Parameter für die Skalierung des Dienstes. Wir wählen 'Configure Service Auto Scaling', um die gewünschte Anzahl Ihrer Dienste anzupassen. Legen Sie die minimalen und maximalen Aufgabenanzahlen bei der Skalierung fest.
IAM-Rolle für Service Auto Scaling — wir wählen AWSServiceRoleForApplicationAutoScaling_ECSService.
Automatische Skalierungsrichtlinien für Aufgaben — Regeln für das Scaling. Es gibt 2 Typen:
- Target-Tracking — Verfolgung einer Zielmetrik (CPU/RAM-Nutzung oder Anzahl der Anfragen pro Aufgabe). Zum Beispiel wollen wir, dass die durchschnittliche CPU-Auslastung 85 % beträgt. Wenn sie darüber liegt, werden neue Aufgaben hinzugefügt, bis der Zielwert erreicht ist. Liegt die Auslastung darunter, werden Aufgaben entfernt, es sei denn, die Skalierungsschutzfunktion ist deaktiviert (Scale-in deaktivieren).
- Stufenskalierung — Reaktion auf ein beliebiges Ereignis. Hier können Sie eine Reaktion auf jedes Ereignis (CloudWatch Alarm) einrichten, sobald es eintritt. Sie können eine bestimmte Anzahl von Tasks hinzufügen oder entfernen oder auch eine genaue Anzahl von Tasks festlegen.
Der Dienst kann mehrere Skalierungsregeln haben, was nützlich sein kann. Wichtig ist, darauf zu achten, dass sie sich nicht gegenseitig behindern.
Fazit
Wenn Sie die Anweisungen befolgt und dasselbe Docker-Image verwendet haben, sollte Ihr Dienst diese Seite zurückgeben.

- Wir haben eine Vorlage erstellt, auf deren Grundlage alle Maschinen im Dienst gestartet werden. Zudem haben wir gelernt, die Maschinen bei Änderungen an der Vorlage zu aktualisieren.
- Wir haben die Verarbeitung des Stoppsignals für Spot-Instanzen eingerichtet. Daher werden innerhalb einer Minute nach Erhalt alle aktiven Tasks von der Maschine entfernt, sodass nichts verloren geht und keine Unterbrechung entsteht.
- Wir haben einen Lastenausgleich eingerichtet, um die Last gleichmäßig auf die Maschinen zu verteilen.
- Wir haben einen Dienst geschaffen, der auf Spot-Instanzen läuft, wodurch die Kosten für Maschinen um etwa das Dreifache gesenkt werden.
- Wir haben das automatische Scaling in beide Richtungen eingerichtet, um steigende Lasten zu bewältigen, ohne gleichzeitig für Leerlauf zu zahlen.
- Wir nutzen einen Capacity Provider, damit die Anwendung die Infrastruktur (Server) verwaltet und nicht umgekehrt.
- Wir machen das gut.
Wenn Sie vorhersehbare Lastspitzen haben, beispielsweise durch eine große E-Mail-Kampagne, können Sie das Scaling einfach nach .
einrichten. Es ist auch möglich, das Scaling auf Basis von Daten aus verschiedenen Teilen Ihres Systems zu steuern. Zum Beispiel haben wir die Funktionalität für an die Nutzer unserer mobilen Anwendung. Manchmal wird eine Kampagne an über 1 Million Personen versendet. Nach einer solchen Aktion beobachten wir immer einen starken Anstieg der API-Anfragen, da viele Nutzer gleichzeitig die App öffnen. Wenn wir sehen, dass die Warteschlange für das Versenden von Promo-Push-Nachrichten deutlich höher ist als die üblichen Werte, können wir sofort mehrere zusätzliche Maschinen und Tasks starten, um auf die Last vorbereitet zu sein.
Ich würde mich freuen, wenn Sie in den Kommentaren interessante Anwendungsfälle von Spot-Instanzen und ECS oder etwas über das Scaling erzählen.
Bald werden Artikel darüber veröffentlicht, wie wir Tausende von Analyse-Events pro Sekunde auf einem überwiegend serverlosen Stack (mit Kosteneffizienz) verarbeiten und wie der Deployment-Prozess von Services mittels GitLab CI und Terraform Cloud gestaltet wird.
Folgen Sie uns, es wird spannend!
Nur registrierte Benutzer können an der Umfrage teilnehmen. Sind Sie an Contour interessiert?
Nutzen Sie Spot-Instanzen in der Produktion?
22,2%Ja6
66,7%Nein18
11,1%Ich habe davon in einem Artikel erfahren und plane, sie zu nutzen3
Es haben 27 Nutzer abgestimmt. 5 Nutzer haben sich enthalten.
Quelle: habr.com
