~~NOTOC~~
====== LU10b - Multi-Node Lab mit Vagrant (verteilte Systeme) ======
**Ziel:** Du kannst mit **Vagrant** eine **reproduzierbare Multi-VM-Umgebung** (mehrere Nodes) definieren, starten, vernetzen und verwalten – als Praxis-Setup für **verteilte Systeme**.
===== Übersicht =====
^ Begriff ^ Kurz erklärt ^
| **Vagrant** | Tool, um **VM-Umgebungen als Code** zu definieren (Vagrantfile) und reproduzierbar zu starten. |
| **VM (Virtual Machine)** | Komplettes virtuelles Betriebssystem (Kernel + Userspace) auf einem Host. |
| **Provider** | VM-Backend, z.B. **VirtualBox**, VMware, Hyper-V (je nach System). |
| **Box** | Vorgefertigtes VM-Image (Basis-OS), z.B. Ubuntu. |
| **Provisioning** | Automatische Konfiguration nach dem Boot: Pakete installieren, Services konfigurieren, Dateien kopieren… |
| **Multi-Node** | Mehrere VMs als „Cluster“ (z.B. db/api/proxy) inkl. Netzwerk. |
===== Warum Vagrant im Modul „Verteilte Systeme“? =====
In verteilten Systemen geht es selten nur um „einen Dienst auf einem Rechner“. Typische Themen sind:
* **Mehrere Nodes** (Dienste sind verteilt)
* **Netzwerk & Ports** (Kommunikation zwischen Nodes)
* **Fehlersuche über Maschinen-Grenzen** (Logs, Connectivity, Firewall)
* **Reproduzierbarkeit** (alle Lernenden haben *dieselbe* Ausgangslage)
**Vagrant** liefert dir genau das:
**ein Vagrantfile** → **ein Befehl** → identische Multi-VM-Umgebung.
**Merke:** Container sind „leicht“ und schnell – aber manchmal brauchst du das **volle OS**: systemd, Kernel-nahe Tools, realistische Netzwerkkonfiguration, Legacy-Stacks. Dafür sind **VMs** top.
===== Vagrant Architektur in der Praxis =====
Vagrant ist im Kern ein Orchestrator um diese Teile:
* **Vagrantfile**: „Bauplan“ (Ruby-DSL, aber sehr lesbar)
* **Box**: Basis-System (z.B. Ubuntu)
* **Provider**: Virtualisierung (meist VirtualBox)
* **Communicator**: Kommunikation in die VM (typisch SSH)
* **Synced Folders**: Ordner zwischen Host und VM teilen
* **Networking**: NAT, Port-Forwarding, private/public network
* **Provisioning**: Shell/Ansible/etc. (kommt in LU10b)
===== Wichtigste Befehle (Workflow) =====
# im Projektordner
vagrant init # Vagrantfile erstellen (Basis)
vagrant up # VMs starten/erstellen
vagrant status # Status ansehen
vagrant ssh # in eine bestimmte VM einloggen
vagrant halt # sauber herunterfahren
vagrant reload # Neustart (Konfigänderungen übernehmen)
vagrant provision # Provisioning erneut ausführen
vagrant destroy -f # VMs löschen (Achtung: Daten weg)
**Typischer Fehler:** Änderungen am Vagrantfile werden oft erst nach **reload** oder **destroy/up** vollständig wirksam (je nach Änderung).
===== Netzwerk-Grundlagen (was du wirklich brauchst) =====
In Multi-Node Labs sind diese Netzwerkarten zentral:
==== NAT (Standard) ====
* VM kommt „raus ins Internet“
* andere VMs erreichen sie nicht zuverlässig über NAT
==== Port Forwarding ====
* Host-Port → VM-Port (z.B. localhost:8080 → VM:80)
* gut für „Service im Browser testen“
Beispiel:
config.vm.network "forwarded_port", guest: 80, host: 8080
==== Private Network (Host-only / internes Netz) ====
* Jede VM bekommt eine **fixe interne IP**
* VMs können sich direkt erreichen (perfekt für verteilte Systeme)
Beispiel:
config.vm.network "private_network", ip: "192.168.56.11"
**Didaktik-Tipp:** Für verteilte Systeme ist ein **Private Network mit fixen IPs** am besten: reproduzierbar, einfach zu debuggen, klare Topologie.
===== Beispiel: Multi-Node Setup (db / api / proxy) =====
Die Idee:
* **db**: Datenbank/Cache
* **api**: Anwendung/Service
* **proxy**: Reverse Proxy / Einstiegspunkt
==== Vagrantfile (Beispiel) ====
# Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
# Gemeinsame Defaults
config.vm.provider "virtualbox" do |vb|
vb.cpus = 2
vb.memory = 2048
end
# --- db node ---
config.vm.define "db" do |db|
db.vm.hostname = "db"
db.vm.network "private_network", ip: "192.168.56.11"
# Optional: DB nach aussen testbar machen (nur falls nötig)
# db.vm.network "forwarded_port", guest: 5432, host: 15432
end
# --- api node ---
config.vm.define "api" do |api|
api.vm.hostname = "api"
api.vm.network "private_network", ip: "192.168.56.12"
# api.vm.network "forwarded_port", guest: 8000, host: 18000
end
# --- proxy node ---
config.vm.define "proxy" do |proxy|
proxy.vm.hostname = "proxy"
proxy.vm.network "private_network", ip: "192.168.56.13"
# Reverse proxy nach aussen
proxy.vm.network "forwarded_port", guest: 80, host: 8080
end
end
==== Starten und testen ====
vagrant up
# in die proxy VM
vagrant ssh proxy
ip a
ping -c 2 192.168.56.12 # api
ping -c 2 192.168.56.11 # db
===== Synced Folders (Code teilen) =====
Standardmässig wird der Projektordner oft nach `/vagrant` gemountet.
vagrant ssh api
ls -la /vagrant
Das ist praktisch, wenn du z.B. „api-code“ auf dem Host bearbeitest, aber in der VM laufen lässt.
Synced Folders können je nach OS/Provider Performance kosten. Für grosse Projekte: bewusst einsetzen.
===== Debugging-Grundmuster (sehr prüfungsrelevant) =====
Wenn „verteiltes System“ nicht funktioniert, geh systematisch vor:
^ Ebene ^ Check ^
| **DNS/Hosts** | Können die Nodes Namen auflösen? (oder IPs nutzen) |
| **Routing/Netz** | Ping / traceroute / `ip a`, `ip r` |
| **Port offen?** | `ss -tulpn`, `nc -vz ` |
| **Firewall** | `ufw status`, iptables/nftables |
| **Service läuft?** | `systemctl status `, Logs |
Beispiel:
# von api -> db Port testen
nc -vz 192.168.56.11 5432
# offene Ports ansehen
ss -tulpn
# systemd Service prüfen
systemctl status nginx --no-pager
journalctl -u nginx -n 50 --no-pager
===== Grenzen & typische Stolpersteine =====
* **Provider-Probleme** (VirtualBox/Hypervisor nicht aktiv, CPU-VT)
* **Port-Kollisionen** (Host-Port 8080 ist schon belegt)
* **Netzwerk-Konflikte** (Host-only Netz kollidiert mit bestehendem Netz)
* **Performance** (VMs brauchen RAM/CPU – Multi-Node braucht Ressourcen)
Für Klassen: Lieber **kleine VMs** (1 CPU / 1024–2048 MB) und ein „Minimal-Cluster“ als zu viel auf einmal.
----
{{tag>M321-LU10}}
[[https://creativecommons.org/licenses/by-nc-sa/4.0/|{{https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png}}]] Kevin Maurizi