Virtuelle Maschinen (VMs) in der Cloud können verschiedene Einsatzzwecke haben: Sie können z.B. als Remote Entwicklungsumgebung, als Self-Hosted Integration Runtime für die Azure Data Factory oder auch als Node für ein selbstverwaltetes Kubernetes Cluster verwendet werden. Um diese VMs in das DevOps-Arbeitsmodell zu integrieren, kann die Einrichtung und Verwaltung als Infrastructure-as-Code (IaC) definiert und dadurch auch automatisiert werden. Hierzu eignet sich das IaC Tool Ansible.
Multipass: Lokales Entwickeln mit Cloud Images
Als erstes schauen wir uns das Tool Multipass von Canonical an, das wir zum Testen von Ansible verwenden wollen: Dieses Tool ist eine lokale „Mini-Cloud“, mit dem cloud-style Ubuntu VMs in einer lokalen Entwicklungsumgebung aufgesetzt und verwaltet werden können. Hiermit können Prototypen von Cloud Deployments lokal entwickelt und getestet werden. Da die Ubuntu Images genauso aufgebaut sind, wie die Ubuntu Images bei den Cloud Providern (AWS, Azure, Google Cloud), können diese Deployments mit wenig Aufwand in der Cloud umgesetzt werden. Somit eignet sich dieses Tool für unsere Tests mit Ansible.

Erweiterte Konfiguration mit cloud-init Metadaten
Mit der Standard GUI (siehe Abbildung 1) oder mit dem CLI von Multipass können wir u.a. die Anzahl der verwendeten CPUs, den verwendeten Arbeitsspeicher, sowie den Festplattenspeicher für die VMs einstellen. Tiefergreifende Einstellungen, wie z.B. weitere User können über cloud-init Metadaten konfiguriert werden. Im folgendem Code ist eine cloud-init Konfiguration beschrieben, mit der ein zusätzlicher Benutzer erstellt wird. Dieser Benutzer hat einen Public Key zur Anmeldung hinterlegt. Außerdem kann er ohne Passwortabfrage auf der VM Konfigurationen auch mit Administrator Rechten durchführen.
#cloud-config
users:
- default
- name: ansible
sudo: ALL=(ALL) NOPASSWD:ALL
lock_passwd: true
ssh_authorized_keys:
- ssh-ed25519 AAA.... ansible
Provisionierung von Multipass VMs mit Terraform
Das Erstellen der Multipass VMs können wir auch als IaC mit Terraform durchführen. Hierzu gibt es einen von der Community entwickelten Provider. Genaue Informationen zum Provider können wir im GitHub Repository nachlesen. Für diesen Blogpost können wir mit den unten beschriebenen Parametern die VM erstellen. Sie enthält den in cloud-init beschriebenen Ansible Benutzer und hat 20 GB Festplattenspeicher. Weitere Informationen zu IaC mit Terraform gibt es in diesem vorherigen Blogpost.
resource "multipass_instance" "multipass_vm" {
cloudinit_file = "./cloud-init.yaml"
name = "ansible-test-1"
disk = "20G"
image = "noble"
}
Ansible: High-Level Übersicht
Im nächsten Schritt werden wir uns eine generelle Übersicht über Ansible schaffen: Ansible ist ein IaC Tool zur automatisierten Verwaltung von Systemen wie z.B. die Multipass VM aus dem vorherigen Schritt. Eine Übersicht zur Funktionsweise von Ansible ist in Bild 2 dargestellt.

Control Node
Ein Control Node ist ein System, das Ansible ausführt und die Managed Nodes verwaltet. Das kann z.B. eine physische Maschine, eine VM oder ein Container sein. Der Control Node verbindet sich standardmäßig via SSH mit den Managed Nodes, um diese zu verwalten. Mit Plugins sind auch weitere Verbindungsprotokolle möglich. Eine Anleitung zur Installation von Ansible finden wir in der Ansible Dokumentation.
Managed Node
Als Managed Nodes oder auch Hosts werden Systeme bezeichnet, die durch den Control Node mit Ansible automatisiert verwaltet werden sollen. Managed Nodes müssen eine SSH Verbindung vom Control Node zulassen und Python muss installiert sein. Außerdem muss ein Benutzer auf dem Managed Node eingerichtet sein, mit dem sich der Control Node anmelden kann. Die Multipass VM aus dem vorherigen Schritt erfüllt diese Voraussetzungen: Python 3 ist vorinstalliert und der Control Node kann sich als der Benutzer ansible via SSH mit der VM verbinden.
Inventory
Das Inventory listet die Managed Nodes auf und enthält spezifische Informationen zu diesen, z.B. die IP-Adressen oder die Host Namen. Des Weiteren können hier die Managed Nodes zu Gruppen hinzugefügt werden und Variablen können den Nodes zugewiesen werden. Je nach verwendetem Plugin, kann das Inventory in verschiedenen Dateiformaten angegeben und auch dynamisch vom Cloud Provider bezogen werden. Die gängigsten Dateiformate sind dabei INI und YAML. Es ist auch möglich mehrere Inventory Dateien zu verwenden. Diese Dateien können in einem Verzeichnis zusammengefasst werden. Beim Ausführen von Ansible kann dann nur das Verzeichnis angegeben werden.
Gruppen werden im Inventory verwendet, um mehrere Managed Nodes zusammenzufassen. Die Gruppen können dann im Playbook referenziert werden, um bestimmte Nodes zu verwalten. Jeder Managed Node ist in zwei oder mehr Gruppen enthalten, in der Gruppe „all“ und in mindestens einer weiteren. Wenn der Node keiner weiteren Gruppe zugeordnet ist, ist dieser auch der Gruppe „unmanaged“ zugeordnet. Es ist auch möglich, verschiedene Gruppen in Metagruppen zusammenzufassen.
In den beiden unteren Codeblöcken ist unser Inventory einmal im INI Format und einmal im YAML Format angegeben. Unsere Multipass VM ist hier mit der IP Adresse in der Gruppe „devserver“ eingetragen. Für die Gruppe „all“ ist hier auch die Variable „ansible_user“ angegeben. Wenn nichts weiter angegeben wurde, wird der Name in dieser Variable von Ansible zur Anmeldung auf dem Managed Node verwendet. Weitere Variablen, die im Inventory eine spezielle Bedeutung haben, finden sich in der Ansible Dokumentation.
[all:vars]
ansible_user = ansible
[devserver]
192.168.64.22
all:
vars:
ansible_user: ansible
devserver:
hosts:
192.168.64.22:
Das Inventory können wir anschließend mit dem Ping Modul von Ansible testen. Dabei muss hier die Gruppe, der Pfad zum Private Key, der Pfad zum Inventory und unser Modul angegeben werden.
# ansible <group> --private-key <path-to-private-key> -i <path-to-inventory> -m <module-name>
# INI inventory and group all
ansible all --private-key ansible-key -i inventory.ini -m ping
# YAML inventory and group devserver
ansible devserver --private-key ansible-key -i inventory.yaml -m ping
Playbooks
Ein Playbook ist eine geordnete Liste von Plays im YAML Format. Diese Plays enthalten Variablen und Tasks, die den Managed Nodes zugewiesen und von Ansible ausführt werden. Im unteren Codeblock haben wir als Beispiel den Play „Install packages“. Schauen wir uns dafür die Playbook Keywords an:
- name
- Name des Plays
- Dieser Name wird beim Ausführen vom Playbook im CLI mit ausgegeben
- hosts
- Managed Nodes, auf dem der Play ausgeführt werden soll
- Hier können Gruppen aus dem Inventory angegeben werden wie hier „devserver“
- remote_user
- Gibt den Benutzer auf dem Managed Node an, mit dem der Play ausgeführt werden soll
- Da wir im Inventory bereits den Benutzer in „ansible_user“ gesetzt haben, kann dieses Keyword weggelassen werden
- become
- Gibt an, ob die Tasks im Play mit sudo Rechten ausgeführt werden sollen
- Der verwendete Benutzer muss diese sudo Rechte auch besitzen, da der Play sonst fehschlägt
- Unserem Benutzer „ansible“ haben wir diese Rechte mit der cloud-init Konfiguration gegeben
- tasks
- Eine Liste mit Aufgaben, die auf den Managed Nodes ausgeführt werden sollen
- Die hier angegebenen Tasks haben alle Namen, die im CLI angegeben werden, und nutzen das Modul für ansible.builtin.apt
- Hier soll der Cache aktualisiert werden und zwei Pakete sollen vorhanden sein
Neben diesen Keywords können noch weitere angegeben werden. Eine Liste mit möglichen Keywords gibt es in der Ansible Dokumentation.
- name: Install packages
hosts: devserver
# remote_user: ansible
become: true
tasks:
- name: Update cache
ansible.builtin.apt:
update_cache: true
- name: Install Podman
ansible.builtin.apt:
name: podman
state: present
- name: Install pip
ansible.builtin.apt:
name: python3-pip
state: present
Zum Testen und Ausführen des Playbooks können die Bash Befehle aus dem unteren Codeblock ausgeführt werden. Durch die Flag „–check“ führt Ansible das Playbook im Check Mode aus. Dabei werden keine Änderungen auf den Managed Nodes ausgeführt, sondern nur ausgegeben, was sich verändern würde.
# Testing
ansible-playbook --private-key ansible-key -i inventory.ini --check playbook.yaml
# Run playbook
ansible-playbook --private-key ansible-key -i inventory.ini playbook.yaml
Collections
Collections sind ein Format, mit denen Drittanbieter ihre Ansible Inhalte für andere Benutzer anbieten können. Diese Collections können Playbooks, Roles, Modules oder Plugins beinhalten. Ein Cloud-Provider kann so z.B. ein Plugin anbieten, mit dem bestimmte VMs dynamisch in das Inventory geladen werden. Über Ansible Galaxy können diese Collections installiert werden. Mehr Informationen zur Handhabung von Collections können in der Ansible Dokumentation nachgelesen werden.
Zusammenfassung
In diesen Blogpost haben wir uns die Grundlagen zu Ansible und Multipass angeschaut. Mit Ansible können wir Systeme, wie z.B. VMs, im DevOps-Arbeitsmodell via Playbooks automatisiert verwalten. Diese Playbooks können wir dank Multipass lokal entwickeln und anschließend mit wenig Aufwand in der Cloud umsetzen. Durch die Kombination dieser beiden Tools können wir Ubuntu VMs einrichten, testen und verwalten, die z.B. als Remote-Entwicklungsumgebung verwendet werden sollen.