AWS CloudFormation, Teil 3 CF-Template für AWS-Ressourcen erstellen

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

Mit AWS CloudFormation lassen sich reproduzierbare Deployments nahezu beliebiger Komplexität unter Einbeziehung aller verfügbaren AWS-Ressourcen und Dienste realisieren. Dieser Beitrag widmet sich der Beschreibungssprache von CloudFormation-Vorlagen.

Anbieter zum Thema

Ein bestehendes JSON-File lässt sich in AWS CloudFormation importieren.
Ein bestehendes JSON-File lässt sich in AWS CloudFormation importieren.
(Bild: Thomas Drilling / AWS)

Die zwei wichtigsten Konzepte in AWS CloudFormation (CF) sind „Vorlagen“, also Templates, und „Stapel“ bzw. Stacks. Eine Vorlage ist eine Spezifikation der zu provisionierenden AWS-Ressourcen. Ein Stack ist eine Sammlung von AWS-Ressourcen, die aus dieser Vorlage erstellt werden, wobei der Nutzer einen Stapel auf Basis der gleichen Vorlage problemlos mehrmals bereitstellen kann.

Anders ausgedrückt: die im YAML- oder im JSON-Format verfasste Vorlagen-Datei ermöglicht es, eine „Sammlung“ von AWS-Ressourcen als eine Einheit (Stack) zu betrachten. Insofern fällt die CF-Syntax in die Kategorie einer Declarative Programming Language bzw. Domain-specific Language (DSL).

Der prinzipielle Aufbau eines CF-Templates findet sich in der sehr umfangreichen AWS-Dokumentation zur Template-Anatomie. Jedes Template-Dokument besteht dementsprechend aus den Sektionen „Format Version“, „Description“, „Metadata“, „Parameters“, „Mappings“, „Conditions“, „Transform“, „Resources“ und „Output“.

Beispiel-Template

Im folgenden Beispiel soll ein Template erstellt werden, mit dem Nutzer eine Virtual Private Cloud mit zwei Subnetzen (Private und Public einschließlich Routing-Tabelle und Internet-Gateway) und eine NAT-Instanz im öffentlichen Subnetz erstellen können. Hierbei gibt

"AWSTemplateFormatVersion" : "2010-09-09",

zunächst die CloudFormation-Template-Version an, der das Template entspricht. Hierzu muss man wissen, dass die Vorlagenformat-Version nicht mit der API- oder WSDL-Version identisch ist und unabhängig von der API und den WSDL-Versionen geändert werden kann. Die optionale „Description“ ist ein frei definierbarer Text-String.

"Description" : "Builds a simple VPC with one public subnet and one private subnet.",

Der ebenfalls optionale Abschnitt „Metadata“ nimmt ggf. Objekte auf, die zusätzliche Infos zur Vorlage bereitstellen.

Parameter

Es folgt nun der „Parameter“-Block. Hier gibt man Werte an, die zur Laufzeit an die Vorlage übergeben werden können, also in dem Moment der Erstellung oder Aktualisierung eines Stapels. Auf die hier angegebenen Parameter kann dann in den folgenden Abschnitten Ressourcen und Outputs Bezug genommen werden (Ref). Konkret handelt es sich bei Parametern um „Name/Wert“-Paare, deren Werte zur Laufzeit geliefert werden, also wenn die Vorlage benutzt wird.

Parameter können dann „in“ der Vorlage mithilfe einer speziellen Syntax referenziert und anstelle von Literalwerten verwendet werden. Parameter benutzt man, um Variablen anzugeben, die sich über Bereitstellungen der Vorlagen ändern können, hier z. B. die Namen von Amazon EC2-KeyPairs und Verfügbarkeitszonen. In unserem konkreten Beispiel soll der Parameter-Block wie folgt aussehen:

  • KeyName: Der Namen des Public-Key Schlüsselpaars, das für die von der Vorlage erstellte Amazon EC2-Instanz (hier die NAT-VM) verwendet werden soll. AWS akzeptiert Schlüsselpaare im OpenSSH Public-Key-Format, im Base64 kodierten DER-Format oder im SSH Public-Key-File-Format. Nutzt man einen Key-Generator, muss dieser zum Erzeugen von RSA-Keys konfiguriert sein. AWS unterstützt Schlüssellängen mit 1024, 2048 und 4096 Bit.
  • EabledVPCAZ: Die Verfügbarkeitszone, in der die Ressourcen des Stacks erstellt werden.
  • PublicSubnet1CIDR: Der Adressbereich in CIDR-Notation des öffentlichen Subnetzes, das als Teil der von dieser Vorlage erstellten VPC erstellt werden soll.
  • PrivateSubnet1CIDR: Der Adressbereich in CIDR-Notation des privaten Subnetzes, der als Teil der von dieser Vorlage erstellten VPC erstellt werden soll.
  • VPCCIDR: Der CIDR-Bereich für die Amazon VPC, die von der Vorlage erstellt wird.
"Parameters" : {
      "KeyName" : {
         "Description" : "Name of an existing EC2 KeyPair",
         "Type" : "AWS::EC2::KeyPair::KeyName"
      },
      "EnabledVPCAZ" : {
         "Description" : "Specify the AZ in which to create the network resources.",
         "Type" : "AWS::EC2::AvailabilityZone::Name"
      },
      "PublicSubnet1CIDR" : {
         "Description" : "CIDR block for our public subnet",
         "Type" : "String",
         "Default" : "10.50.1.0/24",
         "AllowedPattern" : "[a-zA-Z0-9]+\\..+"
      },
      "PrivateSubnet1CIDR" : {
         "Description" : "CIDR block for our private subnet",
         "Type" : "String",
         "Default" : "10.50.2.0/24",
         "AllowedPattern" : "[a-zA-Z0-9]+\\..+"
      },
      "VPCCIDR" : {
         "Description" : "CIDR Block for the entire VPC",
         "Type" : "String",
         "Default" : "10.50.0.0/16",
         "AllowedPattern" : "[a-zA-Z0-9]+\\..+"
      }
},

Typisierte Parameter helfen dabei, den Stack zu erstellen.
Typisierte Parameter helfen dabei, den Stack zu erstellen.
(Bild: Thomas Drilling / AWS)

Hierbei ist zu beachten, dass in diesem Beispiel „KeyName“ und „EnabledVPCAZ“ als „typisierte“ Parameter definiert sind. Wenn der Nutzer nachher in der AWS Management Console einen Stapel erstellt, füllt die GUI genau diese Felder mit gültigen Werten dieser Parametertypen für das AWS-Konto aus, in dem der Stack erstellt wird. Nach dem Parameter-Block folgt ein Abschnitt „Mappings“.

Mappings

Mappings können als benannte, statische Strings betrachtet werden. Sie werden normalerweise verwendet, um auf die Werte der aktuellsten AMIs in einer Region zu verweisen, da diese sich nicht nur nach Region unterscheiden, sondern sich im Laufe der Zeit ändern, wenn neue AMIs freigegeben werden. In diesem ordnet der Admin eine Prozessorarchitektur und eine Region den in dieser Region verfügbaren AMIs zu, z. B.:

"Mappings" : {
         "AmazonLinuxAMI" : {
            "us-east-1": {
               "AMI": "ami-b66ed3de"
            },
            "eu-central-1": {
               "AMI": "ami-c7ee5ca8"
            },
         }
},

Im Beispiel wurden AMI-IDs für Amazon-Linux spezifiziert. Erstellt der Nutzer nachher einen Stack in der von Ihm gewünschten Region, wählt CloudFormation das passende AMI, sofern es hier spezifiziert wurde.

Ressourcen

Nun folgt endlich der Abschnitt „Ressourcen“ der sich den zu erstellenden Ressourcen widmet. CloudFormation kann Ressourcen aus einer Vielzahl von AWS-Diensten wie Amazon EC2, S3, VPC, SNS, SQS, DynamoDB, RDS, RedShift und Route53 erstellen.

Dabei ist es auch möglich, Beziehungen und Abhängigkeiten zwischen Ressourcen anzugeben, um sicherzustellen, dass Ressourcen in der richtigen Reihenfolge erstellt werden. Ressourcen können per „Ref“-Aufruf andere Ressourcen referenzieren, etwa:

"Ref" : "VPC"

In unserem Beispiel wird u. a. eine VPC und eine NAT-Instanz erstellt. Hierbei ist zu erkennen, dass hier eine integrierte CF-Funktion

„Fn :: FindInMap“

zum Einsatz kommt, um den Wert für genau das oben spezifizierte AMI für die betreffende Region zu ermitteln. Darüber hinaus unterstützt speziell CloudFormation für EC2 eine Funktion

„CloudFormation :: Init“

… , mit der Anwendungen, Dateien und andere Ressourcen im Rahmen des Bereitstellungsprozesses auf Amazon EC2-Instanzen verteilt werden.

WaitCondition

Möchte man zusätzliche Anwendungen und Abhängigkeiten in einer Instanzen installieren, verlängert sich die Zeit, bis die neue Instanz vollständig konfiguriert ist, auch wenn die Instanz von einem EC2-Standpunkt aus (d. h. für SSH- oder RDP-Verbindungen) verfügbar wäre, bevor das System vollständig konfiguriert ist. Mit „WaitConditions“ kann der Nutzer an AWS zurückmelden, wenn alle „CloudFormation :: Init-Befehle“ erfolgreich ausgeführt wurden. Daher wird die CloudFormation-Vorlage erst als „vollständig" gekennzeichnet, bis alle in der Vorlage definierten WaitConditions ausgelöst wurden.

Outputs

Der Abschnitt „Ouputs“ einer Vorlage gibt von der Vorlage erstellte Zeichenfolgenwerte zurück, die für Benutzer der zugeordneten Ressourcen wichtig sein können. Erstellt man beispielsweise eine Amazon EC2-Instanz, die als öffentlicher Webserver fungiert, kann man den vollständigen öffentlichen DNS-Namen des Servers im Abschnitt Outputs angeben.

Unsere Beispiel-Vorlage soll daher im Abschnitt Outputs die ID des erstellten VPC einschließlich der beiden Subnetze (Public und Private) zurückgeben. Da die IDs die Standardeigenschaften dieser Ressourcen in AWS CloudFormation sind, ist eine weitere Qualifizierung des Ressourcennamens erforderlich. So verwendet der Abschnitt Outputs die Funktion

„Fn :: GetAtt“

... , um die öffentliche IP-Adresse der NAT-Instanz abzurufen, die ja eine Nicht-Standard-Eigenschaft. Die NAT-Instanz erhält ihre PublicIP ja nach jedem Start, bzw. Neustart aus dem Public-IP-Pool von AWS.

"NATPublicIpAddress" : {
         "Value" : { "Fn::GetAtt" : ["NAT", "PublicIp"] }

Bei „VpcID“,“ PublicSubnetID“ und „PrivateSubnetID“ hingegen genügt ein Referenzieren mit dem „Ref“-Kommando, auf die entsprechenden Ressource-Namen, wie sie weiter oben im Ressourcen-Block in der Vorlage spezifiziert wurden, z. B.

"PublicSubnet1Id" : {
         "Value" : { "Ref" : "PublicSubnet1" }

Stapel erstellen

Ein bestehendes JSON-File lässt sich in AWS CloudFormation importieren.
Ein bestehendes JSON-File lässt sich in AWS CloudFormation importieren.
(Bild: Thomas Drilling / AWS)

Ist die Vorlagendatei fertig, kann sie zum Erstellen eines Stapels verwendet werden. Der Weg dorthin wurde bereits beschrieben. Hierzu klickt der Nutzer im CloudFormation-Dashboard auf „Create new stack“. Statt nun aber ein Sample-Template zu verwenden, laden wir mit der Option „Upload a template to Amazon S3“ das eben erstellte JSON-File zu AWS hoch und klicken auf „Next“.

Was danach passiert, hängt vom Inhalt des Templates ab. Sofern AWS an der Template-Syntax nichts auszusetzen hat und der aktuell aktive Nutzer ausreichende Rechte zum Ausrollen von CF-Stacks hat, muss er wie in der Abbildung oben zu erkennen in die diesem Fall nur „EnabledVPCAZ“ und „KeyName“ aus der angebotenen Liste gültiger Parameter auswählen, denn „Private Subnet1CIDR“, „Pulic Subnet1CIDR“ und VPCCIDR wurde ja bereits im Parameter-Block fest eingestellt und sind daher hier (ausgegraut) voreingetragen.

Im Reiter „Events“ wird fein säuberlich die Erstellung des Stacks protokolliert.
Im Reiter „Events“ wird fein säuberlich die Erstellung des Stacks protokolliert.
(Bild: Thomas Drilling / AWS)

Hat man dann auf der Folgeseite ggf. die gewünschten Tags definiert und eine IAM-Rolle zugewiesen (falls gewünscht), kann man bei Bedarf noch unter „Advanced“ noch eine Benachrichtigung definieren, die nach Fertigstellung des Stacks z. B. an eine E-Mail-Adresse versandt wird und nach einem weiteren Klick auf „Next“, gefolgt von „Create“ wird der neue Stack erstellt.

Die Vorlage im Reiter „Template“
Die Vorlage im Reiter „Template“
(Bild: Thomas Drilling / AWS)

Das vollständige CF-Template findet man übrigens im Reiter „Template“. Wir haben es außerdem hier als Download angehängt.

Artikelfiles und Artikellinks

(ID:44986786)