Amazon Elastic Container Service, Teil 2 – Praxis ECS auf EC2-Cluster-Basis provisionieren
Docker-Image, Container, Cluster, Container-Definition, Cluster-Manager, Task-Definition, Task, Service-Definition und Services sind die essenziellen Konzepte von ECS. Schauen wir uns nun an, wie man aus diesen Zutaten eine cloudnative App backt.
Anbieter zum Thema

Provisioniert man ECS mit Hilfe des Einrichtungsassistenten in der AWS Management Console, werden die geschilderten Zusammenhänge sehr schön visualisiert:
Wir wollen allerdings nun eine App auf ECS schrittweise auf Basis eines EC2-Clusters provisionieren, statt im Wizard auf Fargate-Basis. Als Beispiel verwenden wir den Sinatra-Service (Sinatra ist eine populäre Ruby-On-Rails-Alternative) von „tongueroo“, der auf dem Docker Hub zu finden ist und nicht weiter tut, als „die elementare Frage des Lebens“ mit „42“ zu beantworten.
Die erste Herausforderung bestünde nun darin, das Image auf der Elastic Container Registry (ECR) bereitzustellen, was aus Sicherheitsgründen durchaus zu empfehlen wäre. Wir behandeln diesen Punkt im nächsten Teil und beschränken uns hier darauf, in der Task-Definition das Docker-Repo zu verwenden. Der prinzipielle Ablauf zum Bereitstellen einer App auf ECS wäre dann
- 1. Erstellen des Clusters
- 2. Erstellen einer Task-Definition
- 3. Konfigurieren des Service
- 4. Konfigurieren des Clusters
- 5. Starten der Ressourcen
Erstellen des Clusters
Das Erstellen des Clusters in der Management-Console geht schnell von der Hand. Hier genügt im ECS-Dashboard im Abschnitt „Clusters“ ein Klick auf „Create Cluster“. AWS stellt hierzu drei verschiedene Templates „Networking only“, „EC2 Linux + Networking“ und „EC2 Windows + Networking“ bereit; wir entscheiden uns für die Linux-Variante.
Allerdings sollte man sich in der Praxis zunächst dem Thema Sicherheit widmen und neue Security-Groups für den Cluster erstellen, z. B. per Command Line Interface (CLI).
aws ec2 create-security-group --group-name ecs-sg --description ecs-sg
Andernfalls erstellt der Launch-Wizard passende Sicherheitsgruppen. In der Cluster-Konfiguration lassen sich dann die gewünschten, VPCs, Subnetze und Security-Groups verwenden.
Das Ergebnis lässt sich dann umgehend inspizieren und bei Bedarf weiter konfigurieren. Die GUI spendiert jeden der im ersten Teil beschriebenen Komponenten einen eigenen Tab: Services, Tasks, EC2 Instances, Metrics, Scheduled Tasks usw.
Es kann ein paar Minuten dauern, bis die Instanzen im Cluster registriert sind und im Tab „ECS Instances“ erscheinen. Für das Erstellen der Task-Definition stützen wir uns auf das erwähnte Sinatra-Docker-Image Tongueroo. Unter Praxisbedingungen würde man dies ggf. nun erst einmal lokal testen. Nun erstellen wir die Task-Definition direkt als JSON-File in einem beliebigen Editor:
{
"family": "sinatra-hi",
"containerDefinitions": [
{
"name": "web",
"image": "tongueroo/sinatra:latest",
"cpu": 256,
"memoryReservation": 256,
"portMappings": [
{
"containerPort": 4567,
"protocol": "tcp"
}
],
"command": [
"ruby", "hi.rb"
],
"essential": true
}
]
}
Dann registrieren wir die Task-Definition in ECS mit:
aws ecs register-task-definition --cli-input-json file://task-definition.json
Diese sollte dann auch in der AWS Console unter dem Punkt „Task Definitions“ auftauchen.
Nun erstellen wir den Load Balancer für unseren Service im gewünschten Subnet mit der passenden Security Group. Wir verwenden einen Advanced Load Balander (ALB) und müssen dazu eine Zielgruppe „target-group-ecs“ zum Registrieren der Instanzen festlegen. Als „Listener“ verwenden wir lediglich Port 80 zu Frontend und Backend. Das Registrieren der Instanzen im Load Balancer überspringen wir allerdings, da dies der Service-Scheduler erledigen wird.
Das Ergebnis lässt sich der Review-Seite des Load-Balancer-Assistenten entnehmen, die mit „Schritt 6“ gekennzeichnet ist und noch einmal sämtliche Details auflistet. Wie darin zu sehen ist, haben wir im Erstellungs-Assistenten für den Load Balancer eine Security Group erstellt, die Internetzugriff auf Port 80 erlaubt.
Jetzt müssen wir allerdings noch dafür sorgen, dass die Sicherheitsgruppe der beim Erstellen des ECS-Clusters erzeugten Instanzen ausschließlich Traffic vom Load Balancer akzeptiert. So ist denn auch gewährleistet, dass der gesamte ELB-Datenverkehr die Container-Instanz erreicht.
Auch für die nun noch fehlende Service-Definition kann man z. B. direkt eine JSON-Datei schreiben:
{
"cluster": "ECS-Demo",
"serviceName": "my-service",
"taskDefinition": "sinatra-hi",
"loadBalancers": [
{
"targetGroupArn": " arn:aws:elasticloadbalancing:eu-central-1:204730830381:targetgroup/target-group-ecs/826e2307393ebb98 ",
"containerName": "web",
"containerPort": 4567
}
],
"desiredCount": 1,
"role": "myecsRole"
}
Diese registriert man dann wieder mit …
aws ecs create-service --cli-input-json file://ecs-service.json
… in ECS.
Selbstverständlich lassen sich Task- und Service-Definitionen aber auch in der GUI erstellen, wie im vorhergehenden Bild zu sehen ist. Ausgangspunkt hierfür ist eine bestehende Task-Definition. Bei markierter Task-Definition findet sich im „Actions“-Menü der Eintrag „Create Service“.
Achtung: In dieser Abbildung würde automatisch eine neue Target-Gruppe für den angegebenen Load Balancer erstellt, was nicht mehr exakt zum geschilderten Workflow passt. Es zeigt aber, wie einfach sich Service-Definitionen in der GUI erstellen lassen, auch wenn in diesem GUI-Beispiel IP-basierte Ziele erstellt werden.
Sind alle Angaben korrekt, wird der Service auch GUI-basiert problemlos erstellt.
Der neue Service sollte sich dann auch im Cluster-Dashboard wiederfinden und zwar zunächst im Status „Provisioning“ und kurze Zeit später mit dem Status „Ready“. Demnach sollten sich nach kurzer Zeit auch gesunde Ziele in der zugehörigen Target-Group wiederfinden.
Sollten die Ziele nicht gesund werden, muss man noch einmal überprüfen, ob die Sicherheitsgruppe (bei uns „EC2ContainerService-ECS-Demo“) den gesamten Datenverkehr von der Sicherheitsgruppe SG-LB erlaubt. Außerdem kann man überprüfen, bzw. sollte man bedenken, dass der Load Balancer nur fehlerfreie Ziele in den jeweils konfigurierten AZs erkennen und benutzen kann. Bei IP-basierte Zielen sähe das so aus.
Schließlich kann man sich per SSH auch auf die jeweiligen Container-Instanzen einloggen und prüfen, dass der laufende Docker-Prozess eine passende Antwort zurückgibt. Dies gelingt mit den Kommandos:
ssh ec2-18-185-86-248.eu-central-1.compute.amazonaws.com
docker ps
Stoppen lässt sich der Service dann jederzeit in der ECS-GUI, siehe die Schaltfläche oben rechts.
(ID:45994360)