Cloud-Management über Ansible
Ansible ist vielen Unternehmen sicherlich ein Begriff. Es wird größtenteils dafür verwendet, eine Vielzahl an Linux-Systemen auf einem einzigen Host zentral zu managen und zu automatisieren. Doch Linux-Systeme sind nicht die einzigen Clients, die damit gemanagt werden können. Es können ebenfalls unter anderem Windows-Systeme, SQL-Datenbanken, Kubernetes-Container und Cloudumgebungen gemanaged werden. Diese Optionen werden allerdings nicht sehr häufig verwendet, obwohl sie einiges sicher vereinfachen würden. In diesem Blogartikel soll gezeigt werden, wie es möglich ist, Cloudumgebungen mithilfe von Ansible zentral auf einem Linux-Host zu managen. Dabei werden wir das Management von der Google Cloud Platform (GCP), Amazon Web Services (AWS) und Microsoft Azure (MA) genauer betrachten.
Voraussetzungen
Die wichtigste Voraussetzung, um überhaupt auf die verschiedenen Cloud-Plattformen zugreifen zu können, ist natürlich ein Account. Ohne einen gültigen Account sind keine Zugangsdaten vorhanden, die zur Verbindungsherstellung nötig sind.
Um mit der GCP eine Verbindung herzustellen, wird ein Service-Account benötigt. Bei AWS werden hier der Access und Secret Key als Zugangsdaten verwendet. Bei MA sind es die Client-ID, Subscription-ID, Tenant-ID und das Secret. Bei Bedarf könnten aus Sicherheitsgründen die Zugangsdaten separat gespeichert und z. B. mit Ansible Vault verschlüsselt werden.
Auf dem Linux-Host, von dem aus die Cloudumgebungen gemanaged werden, sollte möglichst die neuste Version von Ansible vorhanden sein. Zusätzlich müssen per Ansible Galaxy noch weitere Kollektionen für jede Cloudumgebung installiert werden. Für GCP wäre das google.cloud, für AWS amazon.aws und für MA ist es azure.azcollection. Um die Ansible Playbooks schließlich erfolgreich ausführen zu können, müssen teilweise auch Python-Pakete per pip installiert werden. Bei GCP wäre das beispielsweise das Paket google-auth. Der Befehl dafür würde so aussehen: pip3 install google-auth. Welche Pakete genau installiert werden müssen, lässt sich aus den Dokumentationen unter https://docs.ansible.com/ entnehmen. Andernfalls werden die Pakete auch in den Fehlermeldungen beim Ausführen der Playbooks angezeigt, falls diese noch nicht installiert wurden.
Anwendung und Beispiele
Nachdem alle Voraussetzungen erfüllt worden sind, hindert uns nichts mehr daran, ein paar Playbooks zu schreiben und auszuführen. Jede der Ansible-Galaxy-Kollektionen für die einzelnen Cloudumgebungen bietet im Großen und Ganzen dieselben Funktionen an. Es können virtuelle Maschinen, Cloud-Speicher, virtuelle Netzwerke, Datenbanken, Kubernetes Cluster und vieles mehr gemanagt werden. Hier werden wir genauer auf das Management von VMs, Speicher und Netzwerken eingehen.
Speicher (Object Storage)
Jeder Cloudanbieter bietet eine Form von Object Storage mit jeweils unterschiedlichen Bezeichnungen an: Cloud Storage in GCP, S3 in AWS oder Blob Storage in MA. Jedenfalls haben sie alle dieselbe Funktion: Daten speichern. Dabei handelt es sich nicht um Block Devices für VMs, sondern um einen reinen Object Storage. Dazu bietet Ansible jeweils die Module gcp_storage_bucket, aws_s3 und azure_rm_storageblob an. Aber bevor überhaupt etwas gespeichert werden kann, muss zuerst ein Bucket bzw. Container erstellt werden. Dies lässt sich mittels eines einfachen Ansible Playbooks ausführen. Bei AWS würde es beispielsweise so aussehen:
- name: create s3 bucket
aws_s3:
aws_access_key: "{{ access_key }}"
aws_secret_key: "{{ secret_key }}"
bucket: ansible-test-bucket
mode: create
permission: public-read
region: eu-central-1
Für die Authentifizierung ist es erforderlich, stets die entsprechenden Zugangsdaten bereitzustellen. In diesem Fall erfolgt der Authentifizierungsvorgang durch die Angabe des Access Keys sowie des Secret Keys. Zusätzlich können noch weitere Optionen angegeben werden, wie z. B. Speicherort, Speicherklasse, Zugangsbeschränkungen etc. Nachdem ein Bucket bzw. Container erstellt wurde, können dort auch mithilfe von weiteren Playbooks Daten hochgeladen, heruntergeladen und aktualisiert werden. Falls das Bucket bzw. der Container oder einige Dateien nicht mehr gebraucht werden, können mithilfe der Ausdrücke mode: delete/delobj oder state: absent die nicht mehr benötigten Objekte gelöscht werden.
Virtuelle Netzwerke
Virtuelle Netzwerke und Subnetze sind eine Notwendigkeit für das Erstellen von virtuellen Maschinen. Damit können private IP-Adressbereiche, die Zuteilung einer öffentlichen IP-Adresse, Sicherheitseinstellungen und der Standort festgelegt werden. Meistens sind bereits ein Default-Netzwerk und Subnetz enthalten, aber oft ist es besser, etwas Eigenes zu erstellen. Mit folgendem Playbook können für GCP Netzwerke ganz einfach erstellt werden:
- name: create a network
gcp_compute_network:
name: rih-net
auto_create_subnetworks: 'false'
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
state: present
Auf ähnliche Weise kann bei Bedarf auch zusätzlich ein Subnetz mit eigenem IP-Adressbereich erstellt werden. Falls auto_create_subnetworks: 'false', dann ist das sogar notwendig. Das Playbook dafür würde so aussehen:
- name: create a subnetwork
gcp_compute_subnetwork:
name: rih-net-sub
region: "{{ region }}"
network: rih-net
ip_cidr_range: 192.168.28.0/24
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
state: present
Mithilfe von weiteren Modulen können auch statische oder dynamische IP-Adressen, private oder öffentliche IP-Adressen sowie eigene Firewall-Regeln erstellt werden. Dazu gehören beispielsweise bei GCP die Module gcp_compute_firewall und gcp_compute_address.
Virtuelle Maschinen
Um VMs erstellen zu können, müssen zuerst eine Netzwerkadresse bzw. eine Netzwerkschnittstelle und ein Speichermedium (Block Device) erstellt werden. Wir gehen davon aus, dass die Schnittstelle bereits im vorherigen Schritt erstellt wurde. Es fehlt also nur noch ein Speichermedium. Ansible bietet dafür eigene Module an, doch ist es nicht immer notwendig, diese zu verwenden, da ein Speichermedium auch direkt über das VM-Instanzmodul mit erstellt werden kann. So auch hier in folgendem Playbook für das Erstellen einer VM mit Speichermedium für MA:
azure_rm_virtualmachine:
subscription_id: "{{ sid }}"
client_id: "{{ cid }}"
secret: "{{ sec }}"
tenant: "{{ ten }}"
resource_group: "{{ res_grp }}"
name: testvm
vm_size: Standard_B1s
storage_account: "{{ str_acc }}"
admin_username: "rih"
admin_password: "passwort"
network_interfaces: "{{ nif.state.id }}"
virtual_network_name: "rih-net"
subnet_name: "rih-net-sub"
managed_disk_type: Standard_LRS
os_disk_name: test-disk
os_disk_size_gb: 30
image:
offer: 0001-com-ubuntu-server-focal
publisher: canonical
sku: 20_04-lts-gen2
version: latest
state: present
Zusätzlich müssen neben dem Speichermedium auch CPU und RAM mit vm_size und ein Betriebssystem-Image mit image ausgewählt werden. In diesem Beispiel wurden ein CPU-Kern und 2 GB Arbeitsspeicher (vm_size: Standard_B1s) gewählt sowie ein Ubuntu 20.04 als Betriebssystem. Eine Liste aller CPU-/RAM-Sizes und Images findet sich in den Dokumentationen für die jeweilige Cloudumgebung.
VMs können per Ansible auch einfach gestartet, gestoppt und gelöscht werden. Eine Liste mit Informationen aller VMs lässt sich mithilfe des Inventory-Plugins ausgeben. Dazu muss zunächst eine Hosts-Datei erstellt werden, bei der das Plugin und die Zugangsdaten explizit angegeben werden. Der Inhalt dieser Datei (hier: hosts_azure_rm.yml → Naming Conditions beachten!) sieht bei MA wie folgt aus:
plugin: azure_rm
subscription_id: "{{ sid }}"
client_id: "{{ cid }}"
secret: "{{ sec }}"
tenant: "{{ ten }}"
Mit dem Befehl $ ansible-inventory --list -i hosts_azure_rm.yml | less wird dann jede vorhandene VM mit einer Vielzahl an Informationen aufgelistet, wie den Namen, Disks, Netzwerkschnittstellen, Maschinentypen etc.
Vergleich mit Vagrant
Vagrant ist ein Tool für das Erstellen und Managen von virtuellen Maschinen. VMs können für VMware, Virtual Box und verschiedene Cloud Provider bereitgestellt werden. Die verschiedenen Konfigurationen der VMs werden in einem „Vagrantfile” beschrieben und dann mithilfe des Befehls vagrant up automatisch durchgeführt. Im Gegensatz zu Ansible läuft Vagrant nicht nur auf Linux-Maschinen, sondern auch auf Windows und macOS.
Der Unterschied zwischen den beiden Ansätzen liegt in ihrer Natur. Ansible ist vorwiegend ein Tool für Serverkonfigurationen und Automatisierungen, während Vagrant sich auf das Management der virtuellen Maschinen selbst konzentriert. Man könnte also sagen, dass der Vagrant-Ansatz eine Abstraktionsebene höher liegt als der Ansible-Ansatz.
Welcher der beiden Ansätze besser ist, lässt sich nicht immer sagen, da beide ihre eigenen Vorzüge haben. Wenn es nur um das Erstellen von VMs in der Cloud geht und die Konfigurationen bei der Bereitstellung etwas tiefergehend sind, dann wäre der Vagrant-Ansatz besser. Wenn es darum geht, die VMs im laufenden Betrieb zu konfigurieren und nebenbei auch andere Cloudfunktionen zu managen, dann wäre der Ansible-Ansatz besser.
Vergleich mit Terraform
Terraform ist, sehr ähnlich zu Vagrant, ein Tool zum Erstellen und Managen von virtuellen Maschinen. Während Vagrant eher für das Management auf lokaler Ebene gedacht ist, so ist Terraform mehr für das Management auf Cloud- und Netzwerkebene gedacht. VMs können für die verschiedenen Cloud Provider, aber auch für vSphere bereitgestellt werden. Wie bei Vagrant wird eine Datei mit Code benötigt, um eine Infrastruktur von virtuellen Maschinen automatisch erstellen zu können.
Bei den drei Ansätzen (Ansible, Vagrant, Terraform) handelt es sich um sogenannte Infrastructure-as-Code (IaC) Ansätze. Das heißt, die gesamte Infrastruktur von virtuellen Maschinen und deren Konfigurationen wird als Code formuliert. Somit kann dieselbe Infrastruktur immer wieder durch Ausführung des Codes erstellt werden. Dies wäre vor allem sinnvoll, wenn die gesamte Infrastruktur nochmals an anderer Stelle dupliziert werden soll oder für Recovery-Fälle.
Fazit
Anhand der genannten Beispiele haben wir gesehen, dass wir viele Cloud-Funktionen ganz einfach auch per Ansible nutzen und konfigurieren können.
Dies ist insbesondere dann sinnvoll, wenn wir bestimmte Funktionen häufig auf ähnliche Weise verwenden möchten. Beispielsweise, wenn eine große Anzahl von VMs mit identischen oder unterschiedlichen Konfigurationsparametern erstellt werden soll. Auch bei Anforderungen an die Reproduzierbarkeit – wenn VMs immer wieder exakt gleich angelegt werden müssen – bietet sich dieser Ansatz an. Am effizientesten lässt sich dies über ein Ansible‑Playbook realisieren, alternativ auch mithilfe von Vagrant oder Terraform. Bei einmaligen Operationen, wenn z. B. nur einmal ein Netzwerk erstellt werden soll, wäre es sinnvoller, das direkt über die Cloud-Konsole zu machen.
Haben wir Ihr Interesse geweckt, Ihre Cloud-Umgebung mit Ansible oder einem anderen Infrastructure-as-Code-Tool Ihrer Wahl zu verwalten? Kontaktieren Sie uns gerne – wir freuen uns, Sie unterstützen zu dürfen.
Consultant
Kommentare