Dynamisches AWS-Inventory in ansible nutzen
Bei der Nutzung von AWS zusammen mit ansible ist es sinnvoll, sich das Inventory automatisch zu generieren. In diesem Zusammenhang war es mir wichtig, einen möglichst sprechenden Hostnamen zu haben, trotzdem mussten die EC2-Instanzen über die interne IPs angesprochen werden, da sie sich in einem nicht öffentlich erreichbaren VPC befanden. Hier habe ich sehr viel recherchiert und diverse Anleitungen gelesen. Als Ergebnis meiner Recherchen habe ich immer wieder die Antwort gefunden, dass man in der ini-Datei die folgenden Variablen setzen soll:
# die normale "Destination"-Variable, über die der Host angesprochen wird
destination_variable = ip_address
# mit dieser "Destination"-Variable wird die obere Variable überschrieben
vpc_destination_variable = private_ip_address
Leider hat das bei mir nie zum gewünschten Erfolg geführt und schlussendlich blieb mir nur übrig, die interne IP als Hostname zu setzen.
Darum habe ich mir den Code des AWS EC2-Plugin im Detail angesehen und bin dabei auf die Lösung gestoßen. Aufgrund der vielen, meiner Meinung nach fehlerhaften Anleitungen, will ich hier kurz meine Lösung aufzeigen.
Vorbereitungen
Um das Plugin zu nutzen wird die AWS-Bibliothek für Python (boto3) benötigt. Die Installation ist mit pip schnell erledigt.
pip install boto3
Nutzung des Plugins
Im ersten Schritt aktiviert man das Plugin. Dazu fügt man in der Datei ansible.cfg die folgende Zeile ein:
enable_plugins = aws_ec2
Jetzt kann man entweder auf gleicher Ebene eine Datei erstellen, die auf aws_ec2.yml endet oder, das ist meine präferierte Lösung, man erstellt einen Unterordner (z.B. aws-inventory) und legt dort seine YAML-Dateien ab. In der Datei ansible.cfg verweist man dann mit der folgenden Zeile auf den erstellten Unterordner:
inventory = aws-inventory
In diesem Unterordner legt man dann die Datei an. Wie oben bereits genannt muss die Datei zwingend auf aws_ec2.yml oder aws_ec2.yaml enden. Hier ein Besispiel für eine solche Datei (z.B inventory_aws_ec2.yml).
plugin: aws_ec2
aws_access_key: "MEIN_AWS_ACCESS_KEY"
aws_secret_key: "MEIN_AWS_SECRET_KEY"
hostnames:
- tag:Name
- private-ip-address
keyed_groups:
- key: tags
prefix: tag
- key: instance_type
prefix: instance_type
- key: placement.region
prefix: aws_region
filters:
vpc-id: vpc-12341234123412341
compose:
ansible_host: private_ip_address
Diese Konfigurations-Datei für das Plugin nutzt die folgenden Variablen:
- plugin: Zuordnung und Aktivierung des aws_ec2-Plugin
- aws_access_key und aws_secret_key: die Zugangsdaten zur Nutzung der AWS API
- hostnames: die aufgelisteten Variablen werden von oben beginnend durchgegangen und der erste gefundene Wert als Hostname verwendet. Im Beispiel oben wird als erstes nach einem Tag mit dem Schlüssel "Name" gesucht. Ist dieser nicht vorhanden, wird die private IP-Adresse als Bezeichnung des Hosts verwendet.
- keyed_groups: auf Basis der hier genannten Schlüssel werden Gruppen gebildet und die Hosts den jeweiligen Gruppen zugeordnet. In unserem Beispiel werden alle Tags verwendet und dem Gruppennamen wird ein "tag" vorangestellt (z.B. der Tag Environment=Prod führt zu dem Gruppennamen tag_environment_prod). Eine weitere Gruppe wird entsprechend des Instanztyps und der zugehörigen Region erstellt.
- filters: Hier filtert man die EC2-Instanzen vor. Ich lasse mir in diesem Beispiel nur die Instanzen eines spezifischen VPCs ausgeben.
- compose: Hier kann man ansible-Variablen individuell setzen. Genau diese Variable nutze ich zum Beispiel, um den Host über seine interne IP anzusprechen.
weitere Einstellungen
Wenn das Inventory häufig verwendet wird und sich die Instanzen nur selten ändern, dann sollte man ein Caching einrichten. Dazu setzt man folgende Variablen:
cache: yes
cache_connection: .cache/
cache_timeout: 86400
Es wird ein Unterordner .cache angelegt und dort die Daten der Instanzen für 24 Stunden gecacht. Die Cachezeit wird in Sekunden angegeben.