2. Experiment 2: [Infrastructur as Code with Ansible and Vagrant]

Datum: [18.04.2024] Thema: [Infrastructur as Code with Ansible and Vagrant]

2.1. Einleitung

Arbeitsumgebungen einrichten, virtuelle Maschinen konfigurieren oder Entwicklerumgebungen für Projekte vorbereiten – all dies sind organisatorische Aufgaben, die Entwickler im typischen Arbeitsalltag bewältigen müssen. Doch um diesen Prozess zu vereinfachen und Entwicklern wertvolle Zeit zu sparen, stehen Tools wie Ansible und Vagrant zur Verfügung, die diese Prozesse automatisieren.

2.1.1. Motivation

Da wir selber in einem separaten Versuch eine Datenbank konfigurieren müssen, entschieden wir uns in diesen Versuch eine Entwicklerumgebung mithilfe von Ansible und Vagrant aufzubauen, der die Umgebung automatisch zur Verfügung stellt.

2.1.2. Aufgabenstellung

Mit der getroffenen Entscheidung, gilt es als nächstes zu definieren, welche Programme und welche Datenbank wir in dieser Entwicklungsumgebung installieren und konfigurieren möchten. Da unser nächster Versuch ein Rust Projekt mit der Datenbank PostgresSQL ist, entschieden wir uns Rust mit Rust-Analyzer, VSCodium als IDE, Aptitude und PostgreSQL zu installieren. Als Betriebssystem entschieden wir uns für Linux.

2.2. Grundlagen

Als nächstes gilt grundsätzlich zu verstehen, was Vagrant und Ansible ist. „Vagrant ist ein Tool zur Erstellung und Verwaltung von virtuellen Maschinenumgebungen in einem einzigen Workflow.“ (Vagrant, 2024). Um für Vagrant virtuelle Maschinen einzurichten, benötigt man eine sogenannte Vagrantfile. Die Datei ist eine Konfigurationsdatei, die die Art der benötigten Maschine für ein Projekt beschreibt und angibt, wie diese Maschinen konfiguriert und bereitgestellt werden sollen. „Ansible [wiederum] ist eine Open-Source-IT-Automatisierungsplattform, die die Bereitstellung, Konfigurationsverwaltung, Anwendungsbereitstellung, Orchestrierung und viele andere IT-Prozesse automatisiert.“ (Ansible, 2024). In Ansible werden Konfigurationsdateien mit Hilfe von YAML oder INI Dateien erstellt. Wir haben uns für eine YAML Datei entschieden, da Ansible diese zum Ausführen und Konfigurieren von Knotenpunkten verwendet.

2.3. Versuchsdurchführung

Dieser Abschnitt beschreibt die Vorbereitung, Durchführung, erzielten Ergebnisse und eventuelle Probleme während des Versuchs.

2.3.1. Vagrant

Zuerst werden die Konfigurationen für Virtual Box deklariert. Diese werden in Form einer Vagrantfile angegeben. Um die Vagrantfile zu erstellen, wurde innerhalb eines leeren Ordners mithilfe des Kommandos $ vagrant init (https://developer.hashicorp.com/vagrant/docs/vagrantfile/version) eine Vorlage generiert. Der nächste Schritt war das Suchen eines kompatiblen Betriebssystems Image für Virtual Box. Wir entschieden uns für eine Ubuntu Distribution in der Version 22.04. (https://app.vagrantup.com/mhc-cs/boxes/Ubuntu-22-04-Xfce)

Damit das Image für die Virtuelle Box installiert wird muss man diese wie folgt innerhalb der Vagrantfile angeben:

Vagrant.configure("2") do |config|
config.vm.box = "mhc-cs/Ubuntu-22-04-Xfce"
config.vm.box_version = "1.0.0"

Als nächstes werden Anbieter spezifische Konfigurationen angegeben. In dem Fall geben wir dem Nutzer 4 GB RAM und eine grafische Benutzeroberfläche:

     config.vm.provider "virtualbox" do |vb|
     # Display the VirtualBox GUI when booting the machine
  vb.gui = true
 # Customize the amount of memory on the VM:
  vb.memory = "4096"
end

Zu guter letzt muss noch das Ausführen des Provision Skripts markiert werden. Dies wird über einen relativen Pfad angegeben und mithilfe von „Shell“ gekennzeichnet, dass es sich um Shell Befehle handelt.

# ausführen von provision Script
config.vm.provision "shell", path: "provision.sh"

Jetzt sind nun die Konfigurationen für Virtual Box abgeschlossen.

Als nächstes gehe ich näher auf die provision.sh Datei ein. Die Datei ist eine Konkatenation von Bash Befehlen.

Zuerst wird das System auf die aktuellste Version aktualisiert. Damit das System nicht nachfrägt, ob man diese Befehle wirklich ausführen möchte, gibt man als Option -y für yes an.

sudo -i
apt-get update
apt-get upgrade -y

Nun wird Aptitude, VSCodium, Rust mit Rust-Analyzer und PostgreSQL installiert.

# Aptitude installieren
apt-get install aptitude -y

# installieren von vscodium, siehe https://vscodium.com/#install
wget -qO - https://gitlab.com/paulcarroty/vscodium-deb-rpm-repo/raw/master/pub.gpg \
| gpg --dearmor \
| sudo dd of=/usr/share/keyrings/vscodium-archive-keyring.gpg
echo 'deb [ signed-by=/usr/share/keyrings/vscodium-archive-keyring.gpg ] https://download.vscodium.com/debs vscodium main' \
| sudo tee /etc/apt/sources.list.d/vscodium.list
apt-get update
apt-get install codium

# installieren von Rust, siehe https://doc.rust-lang.org/book/ch01-01-installation.html
su -l vagrant -c "
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf > sh.rustup.rs
chmod +x sh.rustup.rs
./sh.rustup.rs -y

# installieren von rust-analyzer
codium --install-extension rust-lang.rust-analyzer
"

# installieren von PostgreSQL siehe https://ubuntu.com/server/docs/databases-postgresql
apt-get install postgresql -y

Für die Einrichtung von PostgreSQL ist es guter Praxis einen Nutzer zu erstellen und anschließend diesen als Besitzer für die Datenbank zu registrieren. Hier wird der Nutzer todolist mit dem Passwort todolist erstellt und ihn anschließend die Rechte als Superuser gegeben.

# einrichten von PostgresSQL siehe Dokumentation: https://www.youtube.com/watch?v=RySuQtMiBxQ&t=131s
su -l postgres -c "
# EOF für Skript schreiben für postgres commands
psql <<EOF
-- nutzer todolist erstellen mit passwort 'todolist'
CREATE USER todolist WITH PASSWORD 'todolist';
-- nutzer todolist Rechte als superuser geben
ALTER USER todolist with superuser;
-- database example erstellen mit nutzer todolist
CREATE DATABASE todolist with owner todolist ENCODING='UTF8';
\q
EOF
"

Hier wird anschließend die Tabelle item erstellt.

2.3.2. Ansible

Um uns ein weiteres Tool in dem Bereich der Automatisierung von Konfigurationen anzusehen, haben wir uns zusätzlich für Ansible entschieden. Ansible verwendet YAML Dateien um Konfigurationen zu speichern. Der Vorteil von YAML Dateien ist, dass sie sehr lesbar sind und somit auch für Personen, die nicht mit Ansible vertraut sind, verständlich sind. Am Anfang der Datei wird die Hosts deklariert. In unseren Fall ist es localhost, da wir die Konfiguration auf der lokalen Maschine ausführen. Man könnte aber auch mehrere Hosts deklarieren, um so eine ganze Flotte von Maschinen zu konfigurieren.

---
- name: Setup Ubuntu with Rust, Rust Analyzer, and PostgreSQL
  hosts: localhost

Ansible YAML Dateien bestehen aus einer Reihe and Tasks welche mit einem „-“ beginnen. Diese werden dann chronologisch abgearbeitet. Ein Task kann dann verschiedene Module enthalten, die dann die eigentliche Arbeit machen. In unserem Fall haben wir die Module apt und shell verwendet. Man könnte alles als Shell Befehle machen, aber Ansible bietet eine Vielzahl von Modulen, die die Arbeit erleichtern und weniger fehleranfällig sind. Zusätzlich erlaubt Ansbile auch das Verwenden von Schleifen und Bedingungen, um so die Konfigurationen dynamischer zu gestalten. So haben wir in unserem Fall eine Schleife verwendet, um mehrere Pakete zu installieren, welche in einer Liste deklariert wurden. Das become: yes gibt an, dass der Task als root ausgeführt wird. Das ist nicht immer notwendig, aber in unserem Fall war es notwendig, da wir Pakete installieren und Datenbanken erstellen.

- name: Install necessary packages
become: yes
apt:
        name: "{{ item }}"
        state: present
loop:
        - rustc
        - cargo
        - clang
        - libssl-dev
        - pkg-config
        - git
        - llvm
        - build-essential
        - curl
        - postgresql
        - postgresql-contrib
        - python3-psycopg2

Da nicht alle Pakete im Standard Ubuntu Repository sind, haben wir VSCodium und rust-analyzer über Shell Befehle installiert.

- name: Install rust-analyzer
        become: yes
        shell: |
                curl -L https://github.com/rust-analyzer/rust-analyzer/releases/latest/download/rust-analyzer-linux -o /usr/local/bin/rust-analyzer
                chmod +x /usr/local/bin/rust-analyzer

2.3.3. Ergebnisse

Durch den Versuch haben wir festgestellt, dass Vagrant eine gute Möglichkeit ist, virtuale Maschinen relativ leicht zu konfigurieren sind und mithilfe von Skripten, in unserem Fall ein Shell Skript, weitere Funktionalität zu ergänzen. Ansible wiederum eignet sich hervorragend für die Automatisierung von Installationen sowie auch Konfigurationsmanagement, bei uns in diesen Fall die Konfiguration von PostgreSQL und das installieren von Rust. Ebenso hat Ansible den Vorteil, dass man mehrere Hosts konfigurieren kann und somit auch eine ganze Reihe an PCs oder Servern konfigurieren kann. Das könnte für Unternehmen interessant sein, die eine große Anzahl an Computern auf die gleiche Weise konfigurieren möchten.

2.3.4. Fazit

Die beiden Möglichkeiten Entwicklerumgebungen automatisch aufzubauen funktionieren einwandfrei. Durch die gute Dokumentation von den beiden Tools konnte man sich relativ gut in die Technologien einarbeiten.

2.4. Literaturangaben

[1] https://developer.hashicorp.com/vagrant/docs

[2] https://www.ansible.com/

[3] https://developer.hashicorp.com/vagrant/docs/vagrantfile/version

[4] https://app.vagrantup.com/mhc-cs/boxes/Ubuntu-22-04-Xfce

[5] https://vscodium.com/#install

[6] https://doc.rust-lang.org/book/ch01-01-installation.html

[7] https://ubuntu.com/server/docs/databases-postgresql

[8] https://www.youtube.com/watch?v=RySuQtMiBxQ&t=131s

[9] https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_intro.html#playbook-syntax