Vir­tu­elle Maschi­nen (VMs) in der Cloud kön­nen ver­schie­dene Ein­satz­zwe­cke haben: Sie kön­nen z.B. als Remote Ent­wick­lungs­um­ge­bung, als Self-Hos­ted Inte­gra­tion Run­time für die Azure Data Fac­tory oder auch als Node für ein selbst­ver­wal­te­tes Kuber­netes Clus­ter ver­wen­det wer­den. Um diese VMs in das DevOps-Arbeits­mo­dell zu inte­grie­ren, kann die Ein­rich­tung und Ver­wal­tung als Infra­struc­ture-as-Code (IaC) defi­niert und dadurch auch auto­ma­ti­siert wer­den. Hierzu eig­net sich das IaC Tool Ansible.

Mul­ti­pass: Loka­les Ent­wi­ckeln mit Cloud Images

Als ers­tes schauen wir uns das Tool Mul­ti­pass von Cano­ni­cal an, das wir zum Tes­ten von Ansi­ble ver­wen­den wol­len: Die­ses Tool ist eine lokale „Mini-Cloud“, mit dem cloud-style Ubuntu VMs in einer loka­len Ent­wick­lungs­um­ge­bung auf­ge­setzt und ver­wal­tet wer­den kön­nen. Hier­mit kön­nen Pro­to­ty­pen von Cloud Deploy­ments lokal ent­wi­ckelt und getes­tet wer­den. Da die Ubuntu Images genauso auf­ge­baut sind, wie die Ubuntu Images bei den Cloud Pro­vi­dern (AWS, Azure, Google Cloud), kön­nen diese Deploy­ments mit wenig Auf­wand in der Cloud umge­setzt wer­den. Somit eig­net sich die­ses Tool für unsere Tests mit Ansible.

 GUI von Multipass mit dem Willkommensbildschirm. Hier werden verschiedene Ubuntu Images aufgelistet, mit denen eine neue VM erstellt werden kann.
Abbil­dung 1: GUI von Mul­ti­pass mit dem Will­kom­mens­bild­schirm. Hier wer­den ver­schie­dene Ubuntu Images auf­ge­lis­tet, mit denen eine neue VM erstellt wer­den kann.
Erwei­terte Kon­fi­gu­ra­tion mit cloud-init Metadaten

Mit der Stan­dard GUI (siehe Abbil­dung 1) oder mit dem CLI von Mul­ti­pass kön­nen wir u.a. die Anzahl der ver­wen­de­ten CPUs, den ver­wen­de­ten Arbeits­spei­cher, sowie den Fest­plat­ten­spei­cher für die VMs ein­stel­len. Tie­fer­grei­fende Ein­stel­lun­gen, wie z.B. wei­tere User kön­nen über cloud-init Meta­da­ten kon­fi­gu­riert wer­den. Im fol­gen­dem Code ist eine cloud-init Kon­fi­gu­ra­tion beschrie­ben, mit der ein zusätz­li­cher Benut­zer erstellt wird. Die­ser Benut­zer hat einen Public Key zur Anmel­dung hin­ter­legt. Außer­dem kann er ohne Pass­wort­ab­frage auf der VM Kon­fi­gu­ra­tio­nen auch mit Admi­nis­tra­tor Rech­ten durchführen.

#cloud-config

users:
  - default
  - name: ansible
    sudo: ALL=(ALL) NOPASSWD:ALL
    lock_passwd: true
    ssh_authorized_keys:
      - ssh-ed25519 AAA.... ansible
Pro­vi­sio­nie­rung von Mul­ti­pass VMs mit Terraform

Das Erstel­len der Mul­ti­pass VMs kön­nen wir auch als IaC mit Ter­ra­form durch­füh­ren. Hierzu gibt es einen von der Com­mu­nity ent­wi­ckel­ten Pro­vi­der. Genaue Infor­ma­tio­nen zum Pro­vi­der kön­nen wir im Git­Hub Repo­si­tory nach­le­sen. Für die­sen Blog­post kön­nen wir mit den unten beschrie­be­nen Para­me­tern die VM erstel­len. Sie ent­hält den in cloud-init beschrie­be­nen Ansi­ble Benut­zer und hat 20 GB Fest­plat­ten­spei­cher. Wei­tere Infor­ma­tio­nen zu IaC mit Ter­ra­form gibt es in die­sem vor­he­ri­gen Blog­post.

resource "multipass_instance" "multipass_vm" {
  cloudinit_file = "./cloud-init.yaml"
  name = "ansible-test-1"
  disk = "20G"
  image = "noble"
}

Ansi­ble: High-Level Übersicht

Im nächs­ten Schritt wer­den wir uns eine gene­relle Über­sicht über Ansi­ble schaf­fen: Ansi­ble ist ein IaC Tool zur auto­ma­ti­sier­ten Ver­wal­tung von Sys­te­men wie z.B. die Mul­ti­pass VM aus dem vor­he­ri­gen Schritt. Eine Über­sicht zur Funk­ti­ons­weise von Ansi­ble ist in Bild 2 dargestellt.

Abbil­dung 2: Gene­relle Über­sicht zur Funk­ti­ons­weise von Ansi­ble. Ein Con­trol Node ver­wal­tet ver­schie­dene Mana­ged Nodes mit Ansi­ble via SSH und Python.
Con­trol Node

Ein Con­trol Node ist ein Sys­tem, das Ansi­ble aus­führt und die Mana­ged Nodes ver­wal­tet. Das kann z.B. eine phy­si­sche Maschine, eine VM oder ein Con­tai­ner sein. Der Con­trol Node ver­bin­det sich stan­dard­mä­ßig via SSH mit den Mana­ged Nodes, um diese zu ver­wal­ten. Mit Plug­ins sind auch wei­tere Ver­bin­dungs­pro­to­kolle mög­lich. Eine Anlei­tung zur Instal­la­tion von Ansi­ble fin­den wir in der Ansi­ble Doku­men­ta­tion.

Mana­ged Node

Als Mana­ged Nodes oder auch Hosts wer­den Sys­teme bezeich­net, die durch den Con­trol Node mit Ansi­ble auto­ma­ti­siert ver­wal­tet wer­den sol­len. Mana­ged Nodes müs­sen eine SSH Ver­bin­dung vom Con­trol Node zulas­sen und Python muss instal­liert sein. Außer­dem muss ein Benut­zer auf dem Mana­ged Node ein­ge­rich­tet sein, mit dem sich der Con­trol Node anmel­den kann. Die Mul­ti­pass VM aus dem vor­he­ri­gen Schritt erfüllt diese Vor­aus­set­zun­gen: Python 3 ist vor­in­stal­liert und der Con­trol Node kann sich als der Benut­zer ansi­ble via SSH mit der VM verbinden.

Inven­tory

Das Inven­tory lis­tet die Mana­ged Nodes auf und ent­hält spe­zi­fi­sche Infor­ma­tio­nen zu die­sen, z.B. die IP-Adres­sen oder die Host Namen. Des Wei­te­ren kön­nen hier die Mana­ged Nodes zu Grup­pen hin­zu­ge­fügt wer­den und Varia­blen kön­nen den Nodes zuge­wie­sen wer­den. Je nach ver­wen­de­tem Plugin, kann das Inven­tory in ver­schie­de­nen Datei­for­ma­ten ange­ge­ben und auch dyna­misch vom Cloud Pro­vi­der bezo­gen wer­den. Die gän­gigs­ten Datei­for­mate sind dabei INI und YAML. Es ist auch mög­lich meh­rere Inven­tory Dateien zu ver­wen­den. Diese Dateien kön­nen in einem Ver­zeich­nis zusam­men­ge­fasst wer­den. Beim Aus­füh­ren von Ansi­ble kann dann nur das Ver­zeich­nis ange­ge­ben werden.

Grup­pen wer­den im Inven­tory ver­wen­det, um meh­rere Mana­ged Nodes zusam­men­zu­fas­sen. Die Grup­pen kön­nen dann im Play­book refe­ren­ziert wer­den, um bestimmte Nodes zu ver­wal­ten. Jeder Mana­ged Node ist in zwei oder mehr Grup­pen ent­hal­ten, in der Gruppe „all“ und in min­des­tens einer wei­te­ren. Wenn der Node kei­ner wei­te­ren Gruppe zuge­ord­net ist, ist die­ser auch der Gruppe „unma­na­ged“ zuge­ord­net. Es ist auch mög­lich, ver­schie­dene Grup­pen in Meta­grup­pen zusammenzufassen.

In den bei­den unte­ren Code­blö­cken ist unser Inven­tory ein­mal im INI For­mat und ein­mal im YAML For­mat ange­ge­ben. Unsere Mul­ti­pass VM ist hier mit der IP Adresse in der Gruppe „dev­ser­ver“ ein­ge­tra­gen. Für die Gruppe „all“ ist hier auch die Varia­ble „ansible_user“ ange­ge­ben. Wenn nichts wei­ter ange­ge­ben wurde, wird der Name in die­ser Varia­ble von Ansi­ble zur Anmel­dung auf dem Mana­ged Node ver­wen­det. Wei­tere Varia­blen, die im Inven­tory eine spe­zi­elle Bedeu­tung haben, fin­den sich in der Ansi­ble Doku­men­ta­tion.

[all:vars]
ansible_user = ansible

[devserver]
192.168.64.22
all:
  vars:
    ansible_user: ansible

devserver:
  hosts:
    192.168.64.22:

Das Inven­tory kön­nen wir anschlie­ßend mit dem Ping Modul von Ansi­ble tes­ten. Dabei muss hier die Gruppe, der Pfad zum Private Key, der Pfad zum Inven­tory und unser Modul ange­ge­ben 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
Play­books

Ein Play­book ist eine geord­nete Liste von Plays im YAML For­mat. Diese Plays ent­hal­ten Varia­blen und Tasks, die den Mana­ged Nodes zuge­wie­sen und von Ansi­ble aus­führt wer­den. Im unte­ren Code­block haben wir als Bei­spiel den Play „Install packa­ges“. Schauen wir uns dafür die Play­book Key­words an:

  • name
    • Name des Plays
    • Die­ser Name wird beim Aus­füh­ren vom Play­book im CLI mit ausgegeben
  • hosts
    • Mana­ged Nodes, auf dem der Play aus­ge­führt wer­den soll
    • Hier kön­nen Grup­pen aus dem Inven­tory ange­ge­ben wer­den wie hier „dev­ser­ver“
  • remote_user
    • Gibt den Benut­zer auf dem Mana­ged Node an, mit dem der Play aus­ge­führt wer­den soll
    • Da wir im Inven­tory bereits den Benut­zer in „ansible_user“ gesetzt haben, kann die­ses Key­word weg­ge­las­sen werden
  • become
    • Gibt an, ob die Tasks im Play mit sudo Rech­ten aus­ge­führt wer­den sollen
    • Der ver­wen­dete Benut­zer muss diese sudo Rechte auch besit­zen, da der Play sonst fehschlägt
    • Unse­rem Benut­zer „ansi­ble“ haben wir diese Rechte mit der cloud-init Kon­fi­gu­ra­tion gegeben
  • tasks
    • Eine Liste mit Auf­ga­ben, die auf den Mana­ged Nodes aus­ge­führt wer­den sollen
    • Die hier ange­ge­be­nen Tasks haben alle Namen, die im CLI ange­ge­ben wer­den, und nut­zen das Modul für ansible.builtin.apt
    • Hier soll der Cache aktua­li­siert wer­den und zwei Pakete sol­len vor­han­den sein

Neben die­sen Key­words kön­nen noch wei­tere ange­ge­ben wer­den. Eine Liste mit mög­li­chen Key­words gibt es in der Ansi­ble Doku­men­ta­tion.

- 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 Tes­ten und Aus­füh­ren des Play­books kön­nen die Bash Befehle aus dem unte­ren Code­block aus­ge­führt wer­den. Durch die Flag „–check“ führt Ansi­ble das Play­book im Check Mode aus. Dabei wer­den keine Ände­run­gen auf den Mana­ged Nodes aus­ge­führt, son­dern nur aus­ge­ge­ben, was sich ver­än­dern 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
Coll­ec­tions

Coll­ec­tions sind ein For­mat, mit denen Dritt­an­bie­ter ihre Ansi­ble Inhalte für andere Benut­zer anbie­ten kön­nen. Diese Coll­ec­tions kön­nen Play­books, Roles, Modu­les oder Plug­ins beinhal­ten. Ein Cloud-Pro­vi­der kann so z.B. ein Plugin anbie­ten, mit dem bestimmte VMs dyna­misch in das Inven­tory gela­den wer­den. Über Ansi­ble Galaxy kön­nen diese Coll­ec­tions instal­liert wer­den. Mehr Infor­ma­tio­nen zur Hand­ha­bung von Coll­ec­tions kön­nen in der Ansi­ble Doku­men­ta­tion nach­ge­le­sen werden.

Zusam­men­fas­sung

In die­sen Blog­post haben wir uns die Grund­la­gen zu Ansi­ble und Mul­ti­pass ange­schaut. Mit Ansi­ble kön­nen wir Sys­teme, wie z.B. VMs, im DevOps-Arbeits­mo­dell via Play­books auto­ma­ti­siert ver­wal­ten. Diese Play­books kön­nen wir dank Mul­ti­pass lokal ent­wi­ckeln und anschlie­ßend mit wenig Auf­wand in der Cloud umset­zen. Durch die Kom­bi­na­tion die­ser bei­den Tools kön­nen wir Ubuntu VMs ein­rich­ten, tes­ten und ver­wal­ten, die z.B. als Remote-Ent­wick­lungs­um­ge­bung ver­wen­det wer­den sollen.