Zum Inhalt springen

Installation mit OneDeploy

Auftrag

«Der Vorstand hat sich für OpenNebula entschieden», schreibt Simone Wyss. «Die Software ist frei, kommt aus Europa und läuft auf unseren drei Servern. Kannst du sie so installieren, dass wir das bei einem neuen Server jederzeit wiederholen können? Und schreib bitte auf, was danach wo läuft, damit wir es auch in einem Jahr noch wissen.»

Lernziele

Nach diesem Kapitel kannst du:

  • Erklären, wie Ansible mit Inventar, Playbooks, Tasks, Modulen, Rollen und Handlern arbeitet
  • Ein eigenes kleines Playbook ausführen und an seiner Ausgabe Idempotenz erkennen
  • Den Aufbau von OneDeploy beschreiben
  • OpenNebula 7.4 mit einem Lauf von OneDeploy installieren
  • Nennen, welche Dienste danach auf dem Front-end und auf den Knoten laufen und wie sie zusammenarbeiten
  • Die Meldung eines abgebrochenen Laufs lesen und den Fehler beheben

Eine Cloud mit drei Servern könntest du von Hand einrichten. Bei dreissig Servern oder bei einem Server, der nach einem Defekt neu aufgesetzt werden muss, wird das langsam und fehleranfällig. Werkzeuge für das Konfigurationsmanagement beschreiben deshalb den gewünschten Zustand der Server in Dateien und stellen ihn her. Ansible ist eines davon und das Werkzeug, mit dem das OpenNebula-Projekt seine Installationen automatisiert.

Ansible arbeitet ohne Agent. Auf den Zielrechnern braucht es nur SSH und Python. Ansible läuft auf einem Steuerrechner, im Lab auf dem Front-end. Von dort verbindet es sich mit den Zielrechnern, kopiert kleine Programme hinüber, führt sie aus und löscht sie wieder. Man nennt das ein Push-Modell, weil der Steuerrechner die Änderungen anstösst.

Ansible beschreibt Zielzustände. Ein Shell-Skript sagt «installiere Paket X», ein Task in Ansible sagt «Paket X ist installiert». Ist das schon so, tut Ansible nichts und meldet ok. Muss es etwas ändern, meldet es changed. Diese Eigenschaft heisst Idempotenz. Du kannst einen Lauf beliebig oft wiederholen, das Ergebnis bleibt dasselbe.

BegriffBedeutungBeispiel aus dem Lab
InventarListe der Zielrechner, in Gruppen, mit Variableninventory.yml mit den Gruppen frontend und node
PlaybookYAML-Datei mit einem oder mehreren Playsopennebula.deploy.main
Playordnet einer Gruppe von Rechnern Rollen oder Tasks zu«auf allen Knoten die Rolle kvm»
Taskein einzelner Schritt mit einem Modul«Paket opennebula-node-kvm ist installiert»
Moduldas Programm, das einen Task ausführtapt, copy, template, service, user
RolleBündel aus Tasks, Vorlagen, Standardwerten und Handlern für eine Aufgabedatabase, opennebula/server, gui, kvm
HandlerTask, der nur läuft, wenn ein anderer Task etwas geändert hatDienst neu starten, nachdem seine Konfiguration geändert wurde
VariableWert, der Tasks und Vorlagen steuertone_version: "7.4"
FactsAngaben, die Ansible über einen Zielrechner sammeltVersion von Ubuntu, Anzahl CPUs, Netzwerkkarten
becomeWechsel zu einem anderen Benutzer, meist root mit sudoansible_become: true
Collectionverpacktes Bündel aus Rollen, Modulen und Playbooksopennebula.deploy

OneDeploy ist eine Ansible-Collection des OpenNebula-Projekts. Sie installiert eine Cloud aus einem Front-end und mehreren Knoten, auf Wunsch auch mit hoher Verfügbarkeit, Ceph als Speicher oder einem gerouteten Netz. Der Kurs ist mit der Version release-1.4.1 getestet und nutzt davon nur den einfachsten Aufbau mit lokalem Speicher.

OneDeploy richtet das Lab ein Ansible auf dem Front-end liest das Inventar und die Playbooks von OneDeploy. Es richtet das Front-end lokal ein, mit oned, Scheduler und FireEdge. Die beiden Knoten richtet es über SSH ein, mit KVM und libvirt. EINGABEN STEUERUNG ZIELE lokal SSH SSH Inventar inventory.yml OneDeploy Playbooks, Rollen Ansible auf dem Front-end Front-end oned, Scheduler, FireEdge Knoten 1 KVM, libvirt Knoten 2 KVM, libvirt

Das Playbook opennebula.deploy.main besteht aus zwei Teilen. Der Teil pre bereitet alle Rechner vor. Er prüft Python und die Namen der Rechner, verteilt SSH-Schlüssel und richtet die Zeitsynchronisation und die Protokollierung ein. Danach installiert der Teil site OpenNebula. Er besteht aus Plays für die Gruppen des Inventars:

  1. Alle Rechner mit der Rolle common, gemeinsame Pakete und die Paketquelle von OpenNebula
  2. Das Front-end mit den Rollen database, opennebula/server, gate, flow, form sowie gui
  3. Die Knoten mit den Rollen kvm, datastore/node sowie network/node
  4. Das Front-end noch einmal mit datastore/frontend und network/frontend, die Datastores und Netze anlegen und die Knoten als Hosts eintragen

Rollen für Funktionen, die das Inventar nicht einschaltet, etwa Ceph, ein geroutetes Netz oder Prometheus, überspringt der Lauf. Sie erscheinen in der Ausgabe als skipping.

Das Skript lab/one-deploy/install.sh installiert Ansible aus den Paketen von Ubuntu, holt OneDeploy in der Kursversion nach ~/cc-lab/one-deploy und installiert die Ansible-Collections, die OneDeploy braucht. Dieselben Schritte zeigt die Anleitung zu den Playbooks im Wiki von OneDeploy einzeln.

Terminal-Fenster
~/cc/lab/one-deploy/install.sh
install.sh
mkdir -p ~/cc-lab
if [ ! -d ~/cc-lab/one-deploy ]; then
git -c advice.detachedHead=false clone --quiet --branch "$ONE_DEPLOY_RELEASE" https://github.com/OpenNebula/one-deploy.git ~/cc-lab/one-deploy
fi
cd ~/cc-lab/one-deploy
# ansible.cfg of one-deploy looks for collections in ./ansible_collections only
ansible-galaxy collection install -r requirements.yml -p ./ansible_collections >/dev/null
echo "one-deploy $(git describe --tags) is ready in ~/cc-lab/one-deploy"

Beim Installieren der Collections meldet Git, es sei im Zustand «detached HEAD». OneDeploy verlangt eine Collection in einer festen Version, Git holt dafür einen Tag statt eines Branches. Die Meldung ist deshalb kein Fehler. Das Skript ist erfolgreich, wenn es mit der Zeile one-deploy release-1.4.1 is ready endet.

Das Inventar beschreibt dein Lab für OneDeploy. Das Skript make-inventory.sh schreibt es aus deinen persönlichen Parametern und erzeugt beim ersten Aufruf ein zufälliges Passwort für den Benutzer oneadmin, den Administrator von OpenNebula. Das Passwort liegt danach in ~/cc-lab/oneadmin.pass.

Terminal-Fenster
~/cc/lab/one-deploy/make-inventory.sh > ~/cc-lab/inventory.yml
chmod 600 ~/cc-lab/inventory.yml
make-inventory.sh
---
all:
vars:
# Ansible logs in as the course user and becomes root with sudo
ansible_user: $(id -un)
ansible_become: true
one_version: "7.4"
one_pass: "$(cat "$PASS_FILE")"
# one-deploy checks that every VM resolves the names of all others, prepare.sh wrote them
ensure_hostname: true
ensure_hosts: true
# Images reach the nodes over SSH, no shared storage is needed
ds:
mode: ssh
frontend:
hosts:
# Ansible runs on the front-end, so it reaches the front-end itself without SSH
$CC_FE_HOST: { ansible_host: $CC_FE_IP, ansible_connection: local }
node:
hosts:
$CC_NODE1_HOST: { ansible_host: $CC_NODE1_IP }
$CC_NODE2_HOST: { ansible_host: $CC_NODE2_IP }
EOF

Die Gruppe frontend enthält das Front-end, die Gruppe node die beiden Knoten. Weil Ansible auf dem Front-end läuft, verbindet es sich dort lokal statt über SSH. Diese Verbindungsart wählt ansible_connection: local. Unter vars stehen Werte, die für alle Rechner gelten. one_version legt die Version von OpenNebula fest, ds mit mode: ssh bedeutet, dass die Knoten Images über SSH erhalten und kein gemeinsamer Speicher nötig ist. Netze für die VMs deiner Mitglieder legst du in Kapitel 2.3 selbst an, das Inventar enthält deshalb noch keine. Wie Ansible Gruppen, Variablen und Verbindungsarten in einem Inventar liest, beschreibt die Anleitung zum Inventar von ansible-core 2.20.

Vor der Installation prüfst du, ob Ansible alle drei VMs erreicht.

Terminal-Fenster
cd ~/cc-lab/one-deploy
ansible -i ../inventory.yml all -m ping

Jede VM antwortet mit SUCCESS und ping: pong. Davor warnt Ansible für jede VM, dass es den Python-Interpreter selbst gesucht hat. Diese Warnung kannst du übergehen.

Das Beispiel des Kurses hinterlegt auf jedem Knoten einen Gruss mit dem Namen der Genossenschaft. Es installiert ein Paket, schreibt eine Datei mit Facts der Knoten und zeigt die Datei über einen Handler an.

motd.yml
---
# A first playbook: every node greets with the name of the cooperative when you log in.
# Run it twice and compare the recap, the second run changes nothing.
#
# ansible-playbook -i ~/cc-lab/inventory.yml ~/cc/examples/ansible/motd.yml
- name: Greeting on the nodes
hosts: node
become: true
# The ansible.cfg of OneDeploy turns automatic facts off, this play needs them
gather_facts: true
vars:
cooperative: Wolkenwerk Bern
tasks:
- name: Install htop to watch the load of a node
ansible.builtin.apt:
name: htop
state: present
update_cache: true
cache_valid_time: 3600
- name: Write the greeting
ansible.builtin.copy:
dest: /etc/motd
content: |
{{ cooperative }}, {{ inventory_hostname }}
Ubuntu {{ ansible_facts['distribution_version'] }}, {{ ansible_facts['processor_vcpus'] }} vCPU
mode: "0644"
notify: Show the greeting
handlers:
- name: Show the greeting
ansible.builtin.command: cat /etc/motd
changed_when: false

Starte es zweimal. Im ersten Lauf melden beide Tasks changed, worauf der Handler läuft. Den Gruss selbst siehst du bei der nächsten Anmeldung an einem Knoten oder mit cat /etc/motd. Der zweite Lauf meldet überall ok und changed=0. Der Handler läuft diesmal nicht, weil sich nichts geändert hat. Die Zeile gather_facts: true ist nötig, weil OneDeploy in seiner Konfiguration das automatische Sammeln von Facts abschaltet. Aufbau, Ablauf und Idempotenz eines Playbooks erklärt die Einführung in Playbooks von ansible-core 2.20.

Terminal-Fenster
cd ~/cc-lab/one-deploy
ansible-playbook -i ../inventory.yml ~/cc/examples/ansible/motd.yml

Der Lauf von OneDeploy dauert einige Minuten, im Lab des Kurses zwischen eineinhalb und drei, bei einem langsamen Netz deutlich länger. Ansible zeigt dabei jede Rolle und jeden Task mit dem Ergebnis pro Rechner. Den Ablauf mit Steuerrechner, Inventar und Playbooks beschreibt auch die Anleitung zu OneDeploy von OpenNebula 7.4.

Terminal-Fenster
cd ~/cc-lab/one-deploy
ansible-playbook -i ../inventory.yml opennebula.deploy.main | tee ../deploy.log

Am Ende steht der Abschnitt PLAY RECAP mit einer Zeile pro VM. Bei einer erfolgreichen Installation zeigt jede Zeile failed=0. Die Zahl bei ok gibt an, wie viele Tasks schon stimmten. changed zählt die Tasks, die etwas geändert haben, skipped die Tasks, die dein Lab nicht brauchte.

Nach dem Lauf ist OpenNebula vollständig installiert. Die folgenden Angaben stammen aus einem Lab des Kurses mit OpenNebula 7.4.1 auf Ubuntu 26.04.

DienstPaketPortAufgabe
onedopennebula2633 (XML-RPC), 2634 (gRPC)der Kern von OpenNebula, verwaltet alle Objekte und bietet die API, über die CLI, Weboberfläche und OpenTofu arbeiten
Scheduleropennebulaein Treiber von oned, der für jede neue VM einen passenden Knoten wählt
onemonitordopennebula4124sammelt den Zustand der Knoten und VMs
MariaDBmariadb-server3306, nur lokalDatenbank von oned mit allen Benutzern, Hosts, Images, Netzen und VMs
FireEdgeopennebula-fireedge2616die Weboberfläche Sunstone
guacdopennebula-guacd4822zeigt die Konsole einer VM im Browser
OneFlowopennebula-flow2474Dienste aus mehreren VMs mit Regeln für die Elastizität, Thema von Kapitel 3.5
OneGateopennebula-gate5030, nur lokalüber OneGate melden VMs Werte an OpenNebula, OneFlow braucht das
OneFormopennebula-form13013stellt neue Cluster bei Anbietern bereit, im Kurs nicht genutzt
Hook-Manageropennebula2101 und 2102, nur lokalführt Skripte aus, wenn sich ein Objekt ändert
SSH-Agentopennebulahält den Schlüssel von oneadmin für die Verbindungen zu den Knoten

Dazu kommen der Benutzer oneadmin mit einem SSH-Schlüsselpaar, die Zeitsynchronisation mit chrony und die Konfiguration unter /etc/one/, vor allem oned.conf. In OpenNebula selbst legt der Lauf drei Datastores an. Der Datastore system mit der Nummer 0 hält die Disks laufender VMs, default mit der Nummer 1 die Images und files mit der Nummer 2 Dateien wie Kernel oder Skripte für den Kontext. Alle drei verwenden den Transfertreiber ssh.

DienstPaketAufgabe
KVM mit QEMUqemu-system-x86führt die VMs mit der Virtualisierung der CPU aus
libvirtlibvirt-daemon-systemverwaltet die VMs auf dem Knoten, dazu virtlogd für die Protokolle und virtlockd gegen doppelt geöffnete Disks
Knotenpaketopennebula-node-kvmrichtet den Benutzer oneadmin mit den Gruppen kvm und libvirt ein und konfiguriert libvirt für OpenNebula

Auf den Knoten läuft kein eigener Dienst von OpenNebula. Der Schlüssel von oneadmin aus dem Front-end steht dort in authorized_keys.

Startest du eine VM, legt oned sie in der Datenbank an und der Scheduler wählt einen Knoten mit genug freier CPU und genug Speicher. Das Front-end verbindet sich als oneadmin per SSH mit diesem Knoten. Der Transfertreiber ssh kopiert das Image der VM in den Datastore system des Knotens unter /var/lib/one/datastores/0/. Dann startet ein Treiber auf dem Knoten die VM über libvirt mit KVM. Die Treiber sind kleine Programme in Ruby und Shell, die das Front-end nach /var/tmp/one/ auf jeden Knoten kopiert. Das erledigt der Handler «Sync Remotes» am Ende eines Laufs. Von da an fragt onemonitord regelmässig den Zustand von Knoten und VMs ab, den oned in onehost list und in der Weboberfläche zeigt.

Bricht ein Lauf ab, steht weiter oben eine Zeile mit fatal: und dem Namen der VM, darunter die Meldung. Davor nennt Ansible den gescheiterten Task und die Datei, in der dieser Task steht. Lies zuerst die Meldung, dann den Task. Meist erklärt die Meldung den Fehler schon.

Bei der Entwicklung dieses Kurses brach der Lauf viermal ab. Das Vorbereitungsskript aus Kapitel 0.4 beugt heute jedem dieser Abbrüche vor:

MeldungUrsacheLösung im Kurs
Please make sure each cluster member can resolve all Front-end hostnamesDie VMs kannten die Namen der anderen nicht.prepare.sh schreibt alle Namen in /etc/hosts, das Inventar setzt ensure_hosts.
Could not find the requested service rsyslog.serviceDas minimale Ubuntu 26.04 enthält rsyslog nicht.prepare.sh installiert rsyslog auf allen VMs.
opennebula-fireedge ... Depends nodejs (<= 21)Ubuntu bietet ein neueres Node.js an, als die Weboberfläche verträgt.prepare.sh legt fest, dass Node.js aus dem Repo von OpenNebula kommt.
Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged userAnsible wechselt auf dem Front-end zum Benutzer oneadmin und braucht dafür das Paket acl.prepare.sh installiert acl auf dem Front-end.

Nach einer Korrektur startest du den Lauf noch einmal. Weil Ansible den Zielzustand beschreibt, ändert es nur, was noch nicht stimmt.

Die Befehle von OpenNebula wie onehost oder onevm melden sich mit dem Benutzer und Passwort aus der Datei ~/.one/one_auth an der API an. Damit du nicht jedes Mal zu oneadmin wechseln musst, legst du diese Datei mit dem Passwort aus dem Inventar für deinen eigenen Benutzer an. Nur du darfst sie lesen. Welche Variablen und Dateien die CLI sonst noch liest, steht in der Konfiguration der CLI von OpenNebula 7.4.

Terminal-Fenster
mkdir -p ~/.one
(umask 077; echo "oneadmin:$(cat ~/cc-lab/oneadmin.pass)" > ~/.one/one_auth)

Für ein Lab ist das bequem. In einer echten Cloud arbeitet das Plattform-Team mit eigenen Benutzern statt mit oneadmin. Wie Benutzer und Gruppen in OpenNebula funktionieren, zeigt Kapitel 3.1.

Ob OpenNebula läuft und beide Knoten bereit sind, zeigt onehost list. In der Spalte STAT muss bei beiden Knoten on stehen. OneDeploy trägt die Knoten mit ihren IP-Adressen als Namen ein.

Terminal-Fenster
onehost list

Welche Dienste auf dem Front-end laufen und auf welchen Ports sie warten, zeigen systemctl und ss.

Terminal-Fenster
systemctl list-units 'opennebula*' mariadb.service
sudo ss -ltnp

Die Weboberfläche öffnest du im Browser des Clients, auf smartlearn die Kali-VM, mit eigenem Hypervisor dein PC. Sie ist auf Port 2616 des Front-ends erreichbar, zum Beispiel unter http://192.168.210.137:2616/. Du meldest dich als oneadmin mit dem Passwort aus ~/cc-lab/oneadmin.pass an.

Nach der Anmeldung zeigt Sunstone das Dashboard.

Das Dashboard von Sunstone nach der Anmeldung als oneadmin. Vier Kacheln zählen VMs, Hosts, virtuelle Netze und Images. Die Karte Hosts darunter zeigt, wie viel CPU und Arbeitsspeicher der Cluster schon an VMs vergeben hat. Das Bild stammt aus Teil 3, deshalb laufen hier schon neun VMs.

Der Check dieses Kapitels prüft den Dienst, die Version, beide Hosts und die Weboberfläche.

Terminal-Fenster
python3 ~/cc/checks/check.py install

Aufgabe Einstieg

Richte OneDeploy ein, erzeuge das Inventar und starte das Playbook motd.yml zweimal. Vergleiche die beiden PLAY RECAP und erkläre, warum der Handler beim zweiten Lauf nicht läuft.

Lösung

Der erste Lauf meldet bei beiden Knoten changed=2, weil htop neu installiert und /etc/motd neu geschrieben wurde. Der zweite Lauf meldet changed=0. Weil der Task «Write the greeting» nichts geändert hat, benachrichtigt er den Handler nicht, der deshalb auch nicht läuft.

Aufgabe Lab

Installiere OpenNebula 7.4 mit OneDeploy, richte die CLI für deinen Benutzer ein, prüfe die Hosts mit onehost list, melde dich an der Weboberfläche an und lade den Bericht des Checks install in dein Abgabe-Repo.

Lösung

Der Check endet mit «8 von 8 Prüfungen der Basis erfüllt». onehost list zeigt beide Knoten mit on in der Spalte STAT. Steht dort err, nennt onehost show mit dem Namen des Hosts den Grund im Abschnitt MONITORING INFORMATION, oft eine fehlende SSH-Verbindung vom Front-end zum Knoten.

Aufgabe Vertiefung

Ordne jeden Port, den sudo ss -ltnp auf deinem Front-end zeigt, einem Dienst aus der Tabelle zu. Welche Ports sind nur lokal erreichbar und warum ist das bei der Datenbank sinnvoll?

Lösung

Nur lokal, also auf 127.0.0.1, warten MariaDB auf 3306, OneGate auf 5030 und der Hook-Manager auf 2101 und 2102. Die Datenbank braucht nur oned auf demselben Rechner. Wäre sie im Netz erreichbar, könnte jemand mit ihrem Passwort alle Daten der Cloud lesen oder ändern, an der API von OpenNebula vorbei. SSH auf Port 22 und der lokale DNS-Cache systemd-resolved auf Port 53 der Adressen 127.0.0.53 und 127.0.0.54 gehören zu Ubuntu und fehlen deshalb in der Tabelle.

Texte und Abbildungen stehen unter CC BY-SA 4.0 und der Code unter der MIT-Lizenz. Die Quellen liegen auf GitHub.