Einführung in AWS-CLI, Teil 4 Tags mit AWS-CLI für EC2 erstellen

Autor / Redakteur: Dipl. -Ing. Thomas Drilling / Stephan Augsten

Das AWS Command Line Interface bietet zahlreiche Ansätze zum Steuern von EC2-Ressourcen. Hierbei spielen unter anderem Tags eine große Rolle, mit deren Hilfe sich Instanzen, Projekte, Kosten oder anderen AWS-Ressourcen zuordnen lassen. Eingebunden in eigene Operations-Skripte ergeben sich damit interessante Möglichkeiten.

Anbieter zum Thema

Tags lassen sich mit dem AWS Command Line Interface für verschiedenste Zwecke setzen und ändern.
Tags lassen sich mit dem AWS Command Line Interface für verschiedenste Zwecke setzen und ändern.
(Bild: Drilling / AWS)

Mit in Skripten verpackten CLI-Befehlen oder kleinen Programmen – für alle wichtigen Programmiersprachen ist die die AWS-SDK verfügbar – lassen sich auch komplexer Operations-Aufgaben erledigen. So lassen sich z. B. mit dem EC2-Sub-Command „create-tag“ Tags auch in der CLI erzeugen.

Im folgenden Beispiel wollen wir ein Versions-Tag erstellen. Um die Aufgabe etwas interessanter zu gestalten, sollten zwei AWS-CLI-Kommandos per Pipe-Operator einander zuarbeiten. Der erste Teil des folgenden kleinen Bash-Skriptes findet z. B. mittels „describe instances“ alle EC2-Instanzen in der Default-Region, in denen das Tag „Project“ auf „ERPSystem“ und das Tag „Envrionment“ auf „production“ gesetzt ist.

#!/bin/bash
ids=$(aws ec2 describe-instances –filter "Name=tag:Project,Values=ERPSystem" "Name=tag:Environment,Values=production" --query 'Reservations[*].Instances[*].InstanceId' --output text)
aws ec2 create-tags --resources $ids --tags 'Key=Version,Value=2.0'

Aufruf zum Ändern der Resource-Tags.
Aufruf zum Ändern der Resource-Tags.
(Bild: Drilling / AWS)

Das Skript nutzt den Befehl „aws ec2 describe-instances“, um die InstanceIDs aller Instanzen zu finden, welche die Tags Project=“ERPSystems und Envrionment=“production“ gesetzt haben und leitet das Ergebnis an das Kommando „aws ec2 create-tag“ weiter, welches das Tag „Version“ mit dem Wert „ 2.0“ überschreibt, falls es bereits existiert, oder anderenfalls ein neues erstellt.

Nachdem wir das Skript haben laufen lassen, verifizieren wir das Ergebnis mit …

aws ec2 describe-instances --filter "Name=tag:Project,Values=ERPSystem" --query 'Reservations[*].Instances[*].{ID:InstanceId,AZ:Placement.AvailabilityZone,Project:Tags[?Key==`Project`] | [0].Value,Environment:Tags[?Key==`production`] | [0].Value,Version:Tags[?Key==`Version`] | [0].Value}'

Ausputzer

Der PHP-Code für unser Stopinator-Skript.
Der PHP-Code für unser Stopinator-Skript.
(Bild: Drilling / AWS)

Damit EC2-Instanzen keine unnötigen Kosten verursachen, verwenden viele AWS-Systemoperatoren eine Lösung, die z. B. am Ende des Arbeitstages nach Instanzen sucht, die beendet werden können, und diese terminiert. Das kann unter anderem auch wieder auf Basis von Tags passieren. So könnte man beispielsweise ein kleines PHP-Programm schreiben, um entsprechende Instanzen zu identifizieren und dann entweder zu stoppen oder zu starten.

Unser „stopinator“-PHP-Skript nutzt die AWS-SDK für PHP, um Instanzen zu starten oder zu stoppen. Es akzeptiert zwei Argumente „-t“ (für Terminate), bzw „-s“ (für Start) von denen das Erste einen Satz von Tags im Format „name=value, name=value“ aufnimmt. Der zweite Parameter „-s“ ist vom Typ Boolean. Das Skript konvertiert die Tags allerdings für den zugehörigen PHP-API-Call „EC2::DescribeInstance()“ in das von diesem erwartete Format.

Aufruf des Stopinator-Skripts und Rückgabe der zu beendenden Instanzen.
Aufruf des Stopinator-Skripts und Rückgabe der zu beendenden Instanzen.
(Bild: Drilling / AWS)

Die Funktionsweise ist wie folgt: gibt man mit dem Parameter –t entsprechende Wertepaare an, werden die entsprechend getaggten Instanzen identifiziert und terminiert. Hängt man zusätzlich –s an, werden die betreffenden Instanzen gestartet, sollten sie terminiert sein. Das Skript ist ein im Operations-Management typischer „Aufräumer“, der z. B. am Ende eines jedes Arbeitstages die gewünschten „entsprechend getaggten“ Instanzen terminiert:

./stopinator.php –t "Project=ERPSystem;Environment=development"

Complicance-Kontrolle

Man kann die AWC-CLI im Zusammenhang mit Skripting auch hervorragend verwenden, um z. B. Instanzen, die nicht gemäß der unternehmenseigenen Richtlinien getaggt sind zu finden. Diese können entweder direkt gelöscht werden oder man definiert im Unternehmen eine Art „Übergangszeitraum“, während dessen die verantwortlichen Administratoren lediglich eine Benachrichtigung erhalten, das Tagging in einem vorgegebenen Zeitraum entsprechend zu korrigieren:

So kann man z. B. relativ einfach ein PHP-Programm schreiben, das in unserem Fall anhand zweiter Argumente „region“ und „subnetid“ im angegeben Geltungsbereich nach Instanzen sucht, die beispielsweise nicht mit dem „Umgebung“-Tag versehen sind – weil möglicherweise der zuständige Administrator geschlampt hat – und diese beendet.

Folgender Code-Teil verwendet die in der AWS-PHP-API definierte Methode „describeInstances()“ um alle Instanzen zunächst nach dem Envrionment-Tag zu filtern.

# Obtain a list of all instances with the Environment tag set.$goodInstances = array();
$terminateInstances = array();

$tagArgs = array();
array_push($tagArgs, array(
   'Name' => 'tag-key',
   'Values' => array('Umgebung')
));
$ec2DescribeArgs['Filters'] = $tagArgs;
$result = $ec2->describeInstances($ec2DescribeArgs);
foreach ($result['Reservations'] as $reservation) {
   foreach ($reservation['Instances'] as $instance) {
      $goodInstances[$instance['InstanceId']] = 1;
   }
}

Folgender Code-Block vergleicht die von Ersterem gelieferte Instanz-Liste mit allen Instanzen, bildet somit die Differenzmenge aller „nicht-getaggten“ Instanzen und führt diese einem neuen Array zu.

# Obtain a list of all instances.$subnetArgs = array();
array_push($subnetArgs, array(
   'Name' => 'subnet-id',
   'Values' => array($subnetid)
));
$ec2DescribeArgs['Filters'] = $subnetArgs;
$result = $ec2->describeInstances($ec2DescribeArgs);
foreach ($result['Reservations'] as $reservation) {
   foreach ($reservation['Instances'] as $instance) {
      echo "Checking " . $instance['InstanceId'] . "\n";
      if (!array_key_exists($instance['InstanceId'], $goodInstances)) {
         $terminateInstances[$instance['InstanceId']] = 1;
      }
   }
}

Mit der vom obrigen Code-Block gelieferten Liste wird dann eine Iteration für „terminateInstances“ gefüttert.

# Terminate all identified instances.if (count($terminateInstances) > 0) {
   echo "Terminating instances...\n";
   $ec2->terminateInstances(array(
      "InstanceIds" => array_keys($terminateInstances),
      "Force" => true
   ));
   echo "Instances terminated.\n";
} else {
   echo "No instances to terminate.\n";
}
?>

(ID:45097794)