Ansible für fortgeschrittene Anfänger, oder angefangene Fortschreitende
Im vorherigen Teil haben wir das Setup besprochen. Jetzt geht es an’s Orchestrieren. Ich werde es noch einmal relativ einfach halten
Drei Mal VM, drei Mal Container
Ich habe noch drei Ubuntu VMs mittels Templates in Proxmox erstellt und das Inventory entsprechend angepasst:
[debian_ct]
debian1 ansible_host=192.168.0.46
debian2 ansible_host=192.168.0.47
debian3 ansible_host=192.168.0.48
[ubuntu_vm]
ubuntu1 ansible_host=192.168.0.51
ubuntu2 ansible_host=192.168.0.52
ubuntu3 ansible_host=192.168.0.53
Auch in der ansible.cfg
Konfigurationsdatei habe ich als Standarduser “ansible” festgelegt:
[defaults]
remote_user = ansible
private_key_file = /home/<user>/.ssh/id_ed25519
Qemu Guest Agent ausrollen
Als nächstes möchte ich automatisiert sicherstellen, dass das Paket qemu-guest-agent
auf allen VMs installiert ist, aber nicht auf den Containern, da es dort überflüssig ist. Zuerst möchte ich mit einem einfachen Playbook überprüfen um welche Art von Maschine es sich handelt. GPT-4o schlägt folgendes Playbook vor, welches ich als which-system.yml
im Unterordner playbooks
abspeichere:
---
- name: Check if the system is a container or VM
hosts: all
become: true
tasks:
- name: Detect if the system is a VM or container using systemd-detect-virt
command: systemd-detect-virt
register: systemd_virt_output
changed_when: false
failed_when: false
- name: Set fact if the system is a VM
set_fact:
is_vm: true
when: "'kvm' in systemd_virt_output.stdout or 'vmware' in systemd_virt_output.stdout or 'xen' in systemd_virt_output.stdout or 'hyperv' in systemd_virt_output.stdout"
- name: Set fact if the system is a container
set_fact:
is_container: true
when: "'lxc' in systemd_virt_output.stdout or 'docker' in systemd_virt_output.stdout or 'podman' in systemd_virt_output.stdout"
- name: Output result if the system is a VM
debug:
msg: "This system is a virtual machine."
when: is_vm is defined and is_vm
- name: Output result if the system is a container
debug:
msg: "This system is a container."
when: is_container is defined and is_container
- name: Output result if the system is neither a VM nor a container
debug:
msg: "This system is neither a VM nor a container."
when: is_vm is not defined and is_container is not defined
Der Befehl zum Ausführen schaut so aus:
ansible-playbook ./playbooks/which-system.yml -i ./inventory/hosts
Und der Output so:
Sehr schön, jetzt wissen wir über die Ansible-Ausgabe, dass wir jeweils drei VMs und Container haben. Als nächstes verwenden wir ein Playbook welches nach einem solchen Check qemu-guest-agent
installiert, aber nur, wenn es sich um eine VM handelt. GPT-4o schlägt wiederum folgendes Playbook vor, welches ich unter qemu.yml
abspeichere:
---
- name: Ensure qemu-guest-agent is installed on VMs
hosts: all
become: true
tasks:
- name: Detect if the system is a VM or a container using systemd-detect-virt
command: systemd-detect-virt
register: systemd_virt_output
changed_when: false
failed_when: false
- name: Set fact if the system is a VM
set_fact:
is_vm: true
when: "'kvm' in systemd_virt_output.stdout or 'vmware' in systemd_virt_output.stdout or 'xen' in systemd_virt_output.stdout"
- name: Set fact if the system is a container
set_fact:
is_container: true
when: "'lxc' in systemd_virt_output.stdout or 'docker' in systemd_virt_output.stdout or 'podman' in systemd_virt_output.stdout"
- name: Fail if the system is a container (and not a VM)
fail:
msg: "This system is a container. qemu-guest-agent installation is not needed."
when: is_container is defined and is_container
- name: Ensure qemu-guest-agent is installed on VMs
apt:
name: qemu-guest-agent
state: present
when: is_vm is defined and is_vm
- name: Skip task on non-VMs
debug:
msg: "This is not a VM. Skipping qemu-guest-agent installation."
when: is_vm is not defined or not is_vm
Befehl zum Ausführen:
ansible-playbook ./playbooks/qemu.yml -i ./inventory/hosts
Output:
Es tut wie es soll, die VMs haben qemu installiert bekommen und die Container nicht. In Proxmox sollten nun die IP-Adressen der VMs angezeigt werden. Das tun sie aber nicht, denn der systemd-Service läuft noch nicht (solche Dinge sind typisch bei LLM-entsprungem Code). Nach etwas hin und her, gibt GPT-4o nun dieses geupdatete Playbook aus:
---
- name: Ensure qemu-guest-agent is installed and running on VMs (skip containers)
hosts: all
become: true
tasks:
- name: Detect if the system is a VM or container using systemd-detect-virt
command: systemd-detect-virt
register: systemd_virt_output
changed_when: false
failed_when: false
- name: Set fact if the system is a VM
set_fact:
is_vm: true
when: "'kvm' in systemd_virt_output.stdout or 'vmware' in systemd_virt_output.stdout or 'xen' in systemd_virt_output.stdout or 'hyperv' in systemd_virt_output.stdout"
- name: Set fact if the system is a container
set_fact:
is_container: true
when: "'lxc' in systemd_virt_output.stdout or 'docker' in systemd_virt_output.stdout or 'podman' in systemd_virt_output.stdout"
- name: Fail if the system is a container (and not a VM)
fail:
msg: "This system is a container. qemu-guest-agent installation is not needed."
when: is_container is defined and is_container
- name: Install qemu-guest-agent on VMs
apt:
name: qemu-guest-agent
state: present
when: is_vm is defined and is_vm
- name: Start qemu-guest-agent service
systemd:
name: qemu-guest-agent
state: started
enabled: no
when: is_vm is defined and is_vm
- name: Check if the service is running
systemd:
name: qemu-guest-agent
state: started
register: qemu_service_status
when: is_vm is defined and is_vm
- name: Output service status![[Pasted image 20241005150336.png]]
debug:
msg: "The qemu-guest-agent service is {{ qemu_service_status.state }}."
when: is_vm is defined and is_vm
- name: Output message if it's neither a VM nor a container
debug:
msg: "This system is neither a VM nor a container."
when: is_vm is not defined and is_container is not defined
Also noch einmal ausführen – das stellt für Ansible kein Problem dar, denn es überprüft ja nur, ob der gewünschte Ziel-Zustand herrscht, wenn ja, dann tut es nichts mehr. Jetzt werden auch diese Task erledigt:
Und hier sieht man die Wichtigkeit, dass die Task alle einen erklärenden Namen haben, so weiß man gleich was passiert.
Jetzt zeigen alle VMs auf Proxmox auch die IP-Adresse an:
An diesem Beispiel sieht man, wie einfach es mit Ansible ist eine konsistente Umgebung zu replizieren. Auf allen VMs läuft jetzt der qemu-guest-agent
, die Container werden aber nicht angegriffen. Das Playbook ist flexibel genug gestaltet, dass es automatisch erkennt um welches System es sich handelt und geht entsprechend vor. Jetzt macht es auch nichts, wenn man auch unter Containern diese Playbook ausführt, es wird schlicht nichts installiert. Das kann sinnvoll sein, wenn man beispielsweise im Inventory noch eine andere VM-Gruppe mit apt
-nutzenden Distros hat, dann kann man im Playbook einfach die Einstellung bei hosts: all
belassen und muss nicht alle gewünschten Gruppen oder Hosts einzeln definieren. Wir haben also auch diesen Aspekt automatisiert.
Erweitertes Setup für Qemu Guest Agent
Aber was passiert, wenn man jetzt virtuelle Maschinen hat, die gar nicht den Paket-Manager apt
verwenden sondern apk
wie Alpine Linux? Es würde auf jeden Fall einmal nichts installiert werden. Ansible versucht apt
unter Alpine Linux und die Installation scheitert. Etwas eleganter ist es jedoch auch hier einen Check einzubauen:
---
- name: Ensure qemu-guest-agent is installed and running on Debian-based VMs
hosts: all
become: true
tasks:
- name: Detect if the system is a VM or container using systemd-detect-virt
command: systemd-detect-virt
register: systemd_virt_output
changed_when: false
failed_when: false
- name: Set fact if the system is a VM
set_fact:
is_vm: true
when: "'kvm' in systemd_virt_output.stdout or 'vmware' in systemd_virt_output.stdout or 'xen' in systemd_virt_output.stdout or 'hyperv' in systemd_virt_output.stdout"
- name: Set fact if the system is a container
set_fact:
is_container: true
when: "'lxc' in systemd_virt_output.stdout or 'docker' in systemd_virt_output.stdout or 'podman' in systemd_virt_output.stdout"
- name: Fail if the system is a container (and not a VM)
fail:
msg: "This system is a container. qemu-guest-agent installation is not needed."
when: is_container is defined and is_container
- name: Install qemu-guest-agent on Debian-based VMs
apt:
name: qemu-guest-agent
state: present
when: is_vm is defined and is_vm and ansible_facts['os_family'] == "Debian"
- name: Fail for unsupported OS
fail:
msg: "No apt package manager available. Unsupported OS."
when: is_vm is defined and is_vm and ansible_facts['os_family'] != "Debian"
- name: Start qemu-guest-agent service
systemd:
name: qemu-guest-agent
state: started
enabled: no
when: is_vm is defined and is_vm
- name: Check if the service is running
systemd:
name: qemu-guest-agent
state: started
register: qemu_service_status
when: is_vm is defined and is_vm
- name: Output service status
debug:
msg: "The qemu-guest-agent service is {{ qemu_service_status.state }}."
when: is_vm is defined and is_vm
- name: Output message if it's neither a VM nor a container
debug:
msg: "This system is neither a VM nor a container."
when: is_vm is not defined and is_container is not defined
Jetzt wird nur installiert, wenn apt
vorhanden ist, bzw. wenn es sich um ein Debian-artiges Linux handelt.
Alternativ kann man natürlich auch noch Multi-OS-Support einbauen:
---
- name: Ensure qemu-guest-agent is installed and running on VMs (dynamic OS handling)
hosts: all
become: true
tasks:
- name: Detect if the system is a VM or container using systemd-detect-virt
command: systemd-detect-virt
register: systemd_virt_output
changed_when: false
failed_when: false
- name: Set fact if the system is a VM
set_fact:
is_vm: true
when: "'kvm' in systemd_virt_output.stdout or 'vmware' in systemd_virt_output.stdout or 'xen' in systemd_virt_output.stdout or 'hyperv' in systemd_virt_output.stdout"
- name: Set fact if the system is a container
set_fact:
is_container: true
when: "'lxc' in systemd_virt_output.stdout or 'docker' in systemd_virt_output.stdout or 'podman' in systemd_virt_output.stdout"
- name: Fail if the system is a container (and not a VM)
fail:
msg: "This system is a container. qemu-guest-agent installation is not needed."
when: is_container is defined and is_container
- name: Detect package manager
package_facts:
when: is_vm is defined and is_vm
- name: Install qemu-guest-agent using appropriate package manager
package:
name: qemu-guest-agent
state: present
when: is_vm is defined and is_vm
- name: Start qemu-guest-agent service
systemd:
name: qemu-guest-agent
state: started
enabled: no
when: is_vm is defined and is_vm
- name: Check if the service is running
systemd:
name: qemu-guest-agent
state: started
register: qemu_service_status
when: is_vm is defined and is_vm
- name: Output service status
debug:
msg: "The qemu-guest-agent service is {{ qemu_service_status.state }}."
when: is_vm is defined and is_vm
- name: Output message if it's neither a VM nor a container
debug:
msg: "This system is neither a VM nor a container."
when: is_vm is not defined and is_container is not defined
Jetzt werden hier auch die Paketmanager apk
, yum
und dnf
berücksichtigt. Aber um all diese verschiedenen Distros zu probieren, brauche ich erstens mehr RAM (64GB liegen schon bereit) und zweitens sollte ich das Ausrollen von VMs (und Container) unter Proxmox dann auch gleich mit Ansible automatisieren. Also etwas für den nächsten Beitrag.
Fazit
Diese Playbooks haben sicher nicht den besten Code, aber die Tatsache, dass sie gleich funktionieren ist schon super. Wir werden sehen, was sonst noch alles geht.
Aja, der RAM ist jetzt doch etwas knapp geworden:
Gute Gelegenheit den Host auch noch einmal zu updaten. Beim nächsten Mal geht es weiter.