Talos Linux auf OpenStack: Schritt für Schritt

22 August, 2024

Daniel Bodky
Daniel Bodky
Senior Platform Advocate

Daniel kam nach Abschluss seines Studiums im Oktober 2021 zu NETWAYS und beriet zwei Jahre lang Kunden zu den Themen Icinga2 und Kubernetes, bevor es ihn weiter zu Managed Services zog. Seitdem redet und schreibt er viel über cloud-native Technologien und ihre spannenden Anwendungsfälle und gibt sein Bestes, um Neues und Interessantes rund um Kubernetes zu vermitteln. Nebenher schreibt er in seiner Freizeit kleinere Tools für verschiedenste Einsatzgebiete, nimmt öfters mal ein Buch in die Hand oder widmet sich seinem viel zu großen Berg Lego. In der wärmeren Jahreszeit findet man ihn außerdem oft auf dem Fahrrad oder beim Wandern.

von | Aug. 22, 2024

Die Wahl der richtigen Plattform für den Betrieb von Kubernetes Workloads ist eine wichtige strategische Entscheidung. Managed Kubernetes-Dienste bieten eine schnelle und einfache Möglichkeit, Kubernetes-Cluster bereitzustellen und zu verwalten, doch sie kommen oft mit Einschränkungen in Bezug auf Flexibilität und Kontrolle einher.
Für alle, die mehr Anpassungsmöglichkeiten oder eine stärkere Integration in ihre bestehende OpenStack-Infrastruktur suchen, bietet sich die Installation von Talos Linux auf OpenStack als interessante Alternative an.

In diesem Blogpost zeigen wir dir, wie Du mithilfe von Terraform Talos Linux auf OpenStack installierst und damit die Grundlage für ein sicheres, leichtgewichtiges Kubernetes-Cluster schaffst.

Baue dein Cluster noch heute!
Die NETWAYS Cloud und NETWAYS Managed Kubernetes lassen dir alle Optionen offen.

Warum Talos Linux?

alos ist eine extrem leichtgewichtige Linux Distribution, die explizit für den Betrieb von Kubernetes konzipiert wurde. Folgerichtig unterscheidet sie sich grundlegend von anderen Distributionen wie Ubuntu, Fedora, oder RHEL.
Einige der wichtigsten Unterschiede zwischen Talos und anderen Standarddistributionen sind

  • das minimalistische Design: Talos Linux kommt mit lediglich 12 Binaries aus! Es gibt keine Shell, keine Interpreter für Programmiersprachen wie Python usw., und nicht einmal einen Paketmanager.
  • das Kommunikationsmodell: Die Kommunikation, Installation und Konfiguration von Talos findet ausschließlich via API statt – keine SSH-Schwachstellen mehr!
  • das Dateisystem: Talos Linux setzt auf ein unveränderliches Root-Dateisystem, auf dem als overlayfs aufbauend lediglich einzelne Dateien geändert werden können (z.B. /etc/host).
  • der Fokus auf Kubernetes: Talos Linux wurde speziell für Kubernetes konzipiert. Erstellung, Troubleshooting und Upgrades von Kubernetes Clustern können direkt via Talos API auf sichere Weise vorgenommen werden.

Nachdem wir dir jetzt einen kurzen Überblick über seine Vorteile gegeben haben, lass uns die Installation von Talos Linux auf OpenStack angehen!

Unser Installationsplan

Wie eingangs erwähnt, werden wir für die Installation von Talos Linux auf OpenStack Terraform nutzen.

Infrastructure as Code (IaC) bietet gegenüber der manuellen Installation einige Vorteile, u.A. ReproduzierbarkeitGeschwindigkeit und Sicherheit. Typische Fehler des manuellen Betriebs (z.B. Tippfehler) können von vornherein ausgeschlossen werden.

Info: 2023 änderte Terraform sein Lizenzierungsmodell. Als direkte Reaktion darauf erstellte die Cloud-Native Community einen Fork des Projekts  namens OpenTofu.

Für dieses Tutorial kannst du beide Tools verwenden – ersetze einfach terraform durch tofu wenn nötig.

Den Ablauf der Installation werden wir in drei Schritte untergliedern:

  1. Initialisierung des Terraform Projekts: Bevor wir mit Terraform auf OpenStack arbeiten können, müssen wir es entsprechend konfigurieren.
  2. Vorbereitung des OpenStack Projekts: Wir benötigen ein NetzwerkFirewallregeln, und ein Talos Linux Image von dem wir booten können.
  3. Einrichtung der Talos Linux VMs: Für diesen Artikel werden wir ein Cluster bestehend aus einem Controlplane Node und zwei Worker Nodes erstellen.
  4. Erstellung eines Kubernetes Clusters: Nach der erfolgreichen Installation von Talos Linux auf OpenStack werden wir uns anschauen, wie schnell und unkompliziert wir ein Kubernetes Cluster darauf einrichten können.

Lass uns also direkt anfangen!

Initialisierung des Terraform Projekts

Für die Installation von Terraform oder OpenTofu folge bitte den Verlinkungen. Nach erfolgreicher Installation der CLI erstellen wir ein neues Verzeichnis talos-openstack, in dem wir arbeiten werden. In diesem Verzeichnis erstellen wir eine neue Datei main.tf mit folgendem Inhalt:

terraform {
    required_providers {
        openstack = {
            source  = "terraform-provider-openstack/openstack"
            version = "~> 2.1.0"
        }
    }
}

provider "openstack" {
    auth_url    = "https://cloud.netways.de:5000/v3/"
    tenant_name = ""
    user_name   = ""
    password    = ""
    region      = "HetznerNBG4"
}

Mit diesen Informationen sagen wir Terraform, dass wir den offiziellen OpenStack Provider für Terraform benötigen und wie er sich zu unserem OpenStack Projekt verbinden soll.
Die obige Konfiguration ist für NETWAYS Cloud gedacht, je nach genutztem OpenStack müssen die Informationen entsprechend angepasst werden.

Mithilfe des folgenden Befehls können wir unser Terraform Projekt nun initialisieren und den OpenStack Provider herunterladen:

terraform init

Im Anschluss können wir mit der Installation von Talos Linux auf OpenStack beginnen!

Konfiguration des OpenStack Projekts

Um ein Kubernetes Cluster auf Talos Linux Nodes einzurichten, benötigen wir ein paar Dinge in unserem OpenStack Projekt, die wir allesamt mit Terraform provisionieren können:

  • ein Netzwerk + Subnet: Zur besseren Absicherung unseres Clusters und der darunterliegenden VMs bietet es sich an, ein dediziertes Netzwerk zu nutzen.
  • ein Netzwerkrouter: Um unser Cluster und die Talos Linux VMs über das Internet managen zu können, benötigen wir einen Router für die Verknüpfung unseres Netzwerks mit einem sog. Public Network.
  • eine Security Group + Regeln: Zur Definition von Firewallregeln benötigen wir eine sog. Security Group und entsprechende Regeln.
  • ein Talos Linux Boot Image: Zur Installation unserer VMs benötigen wir ein Image, von dem die VMs Talos Linux initial booten können.

Definition der Netzwerkressourcen

Zur besseren Gliederung unserer durch Terraform verwalteten Ressourcen erstellen wir eine neue Datei network.tf, in der wir alle Ressourcen mit Netzwerkbezug definieren werden.
Wir beginnen mit dem Netzwerk, Subnet und Netzwerkrouter:

resource "openstack_networking_network_v2" "talos" {
    name           = "talos-network"
    admin_state_up = true
}

resource "openstack_networking_subnet_v2" "talos-subnet-1" {
    name       = "talos-subnet-1"
    network_id = openstack_networking_network_v2.talos.id
    cidr       = "192.168.1.0/24"
}

resource "openstack_networking_router_v2" "talos-router" {
    name                = "talos-router"
    admin_state_up      = true
    external_network_id = data.openstack_networking_network_v2.public-network.id
}

resource "openstack_networking_router_interface_v2" "talos-router-interface" {
    router_id = openstack_networking_router_v2.talos-router.id
    subnet_id = openstack_networking_subnet_v2.talos-subnet-1.id
}

Für Netzwerk und Subnet benötigen wir je eine Ressourcendefinition, wobei wir dem Subnet eine CIDR zuweisen und das definierte Netzwerk referenzieren.
Der Router besteht aus zwei Komponenten, einmal dem Router selbst (der Verknüpfung zwischen Router und Public Network), und einmal seinem Interface (der Verknüpfung zwischen Router und unserem Subnet).

Dem aufmerksamen Beobachter wird nicht entgangen sein, dass wir das Public Network in der Routerdefinition via data.openstack_networking_network_v2.public-network.id referenzieren – diese sog. Datavariable müssen wir ebenfalls definieren.
Hierfür erstellen wir eine weitere Datei data.tf, die vorerst einen einzigen Eintrag erhält:

data "openstack_networking_network_v2" "public-network" {
    name = "public-network"
}

Wie bereits bei der Konfiguration von Terraform selbst ist auch hier die Definition auf die NETWAYS Cloud zugeschnitten – je nach OpenStack Umgebung ist es gut möglich, dass evtl. vorhandene Public Networks anders heißen.

Definition der Firewall

Als nächstes können wir die benötigte Security Group und zugehörige Security Rules erstellen. Davor sollten wir uns allerdings anschauen, welche Netzwerkverbindungen Talos Linux zur Kommunikation innerhalb des Clusters und via CLI nutzt.

Hier hilft uns die offizielle Dokumentation weiter:

Wir benötigen also Security Rules für die Ports 50000/50001 innerhalb des Subnets und für Port 50000 von remote (z.B. von unserer lokalen Talos CLI).
Zusätzlich werden wir eine Regel für Port 6443 erstellen, um mit der Kubernetes API kommunizieren zu können.

Hierfür erweitern wir network.tf um die folgenden Ressourcendefinitionen:

resource "openstack_networking_secgroup_v2" "talos-controlplane" {
    name        = "talos"
    description = "A Security Group for Talos Linux"
}

resource "openstack_networking_secgroup_v2" "talos-workers" {
    name        = "talos-workers"
    description = "A Security Group for Talos Linux workers"
}

resource "openstack_networking_secgroup_rule_v2" "k8s-api" {
    direction = "ingress"
    ethertype = "IPv4"
    protocol  = "tcp"
    port_range_min = 6443
    port_range_max = 6443
    remote_ip_prefix = "0.0.0.0/0"
    security_group_id = openstack_networking_secgroup_v2.talos-controlplane.id
}

resource "openstack_networking_secgroup_rule_v2" "talos-apid-controlplane" {
    direction = "ingress"
    ethertype = "IPv4"
    protocol  = "tcp"
    port_range_min = 50000
    port_range_max = 50000
    remote_ip_prefix = "0.0.0.0/0"
    security_group_id = openstack_networking_secgroup_v2.talos-controlplane.id
}

resource "openstack_networking_secgroup_rule_v2" "talos-trustd-controlplane" {
    direction = "ingress"
    ethertype = "IPv4"
    protocol = "tcp"
    port_range_min = 50001
    port_range_max = 50001
    remote_ip_prefix = openstack_networking_subnet_v2.talos-subnet-1.cidr
    security_group_id = openstack_networking_secgroup_v2.talos-controlplane.id
}

resource "openstack_networking_secgroup_rule_v2" "talos-apid-worker" {
    direction = "ingress"
    ethertype = "IPv4"
    protocol  = "tcp"
    port_range_min = 50000
    port_range_max = 50000
    remote_ip_prefix = openstack_networking_subnet_v2.talos-subnet-1.cidr
    security_group_id = openstack_networking_secgroup_v2.talos-workers.id
}

Auf diese Weise erstellen wir zwei Security Groups und eine handvoll Regeln, um die freizugebenden Verbindungen abzubilden.

Definition des Talos Linux Boot Images

Als letztes ToDo dieses ersten Abschnitts definieren wir nun noch das Talos Linux Boot Image. Für die Erstellung und einen einfachen Upload nutzen wir die Talos Image Factory.

Da Talos Linux immutable ist, können benötigte Erweiterungen nicht einfach nachinstalliert werden. Die Talos Image Factory ermöglicht es deshalb, verschieden vorkonfigurierte Boot Images zu erstellen und herunterzuladen.

Für unser OpenStack Image können wir uns wie folgt durch den Dialog auf der Website klicken:

  1. Hardware Type: Cloud Server
  2. Choose Talos Linux Version: v1.7.5
  3. Cloud: OpenStack
  4. Machine Architecture: amd64
  5. System Extensions: keine
  6. Customization: keine

Wir landen nun auf einer Downloadseite, wo wir den Link unter First Boot > Disk Image kopieren.

Im Anschluss fügen wir ihn wie folgt in eine neue Datei compute.tf ein:

resource "openstack_images_image_v2" "talos-175" {
    name             = "Talos v1.7.5"
    image_source_url = "https://factory.talos.dev/image/376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba/v1.7.5/openstack-amd64.raw.xz"
    container_format = "bare"
    disk_format      = "raw"
    decompress       = "true"
}

Bei Ausführung von Terraform wird das referenzierte Image zuerst auf unsere lokalen Rechner heruntergeladen, dekomprimiert, und dann als Boot Image in OpenStack konfiguriert.

Wir können nun die Talos Linux VMs konfigurieren.

Einrichtung der Talos Linux VMs

Auch die Erstellung der VMs erfordert die Definition mehrerer Ressourcen in Terraform:

  • Ports: Zur Anbindung der VMs an das bereits definierte Subnet und zur Verknüpfung der Security Group(s)
  • Floating IP: Zur Verfügbarkeit des Controlplane Nodes über das Internet
  • Compute Instances: die tatsächlichen VMs, inklusive Ressourcen- und Imagedefinition.

Erstellung der Network Ports und Floating IP

Bevor wir endlich unsere Talos Linux VMs definieren, fehlen lediglich noch Network Ports, mit denen wir die VMs an das definierte Subnet und die jeweiligen Security Groups anschließen. Hierfür fügen wir folgende Ressourcen in compute.tf ein:

resource "openstack_networking_port_v2" "talos-controlplane" {
    depends_on         = [openstack_networking_subnet_v2.talos-subnet-1]
    name               = "talos-controlplane"
    network_id         = openstack_networking_network_v2.talos.id
    admin_state_up     = true
    security_group_ids = [openstack_networking_secgroup_v2.talos-controlplane.id]
}

resource "openstack_networking_port_v2" "talos-workers" {
    depends_on         = [openstack_networking_subnet_v2.talos-subnet-1]
    count              = 2
    name               = "talos-worker-${count.index}"
    network_id         = openstack_networking_network_v2.talos.id
    admin_state_up     = true
    security_group_ids = [openstack_networking_secgroup_v2.talos-workers.id]
}

Wir haben nun zwei Portdefinitionen, eine für den zu erstellenden Controlplane Node und eine für die Worker Nodes, die dank der Eigenschaft count = 2 zwei Ports in OpenStack erstellen wird, einen für jeden Worker Node.

Zusätzlich definieren wir ebenfalls in compute.tf die Floating IP und referenzieren unseren soeben definierten Port für den Controlplane Node sowie eines der Public Networks unserer OpenStack Umgebung:

resource "openstack_networking_floatingip_v2" "talos-controlplane" {
    pool    = "public-network"
    port_id = openstack_networking_port_v2.talos-controlplane.id
}

Da die konkrete Floating IP erst nach Provisionierung der Ressourcen durch Terraform bekannt ist, lassen wir sie uns nach erfolgreicher Erstellung ausgeben. Hierfür erstellen wir die Datei outputs.tf mit folgendem Inhalt:

output "control-plane-ip" {
    value = openstack_networking_floatingip_v2.talos-controlplane.address
}

Halbzeit: Erste Provisionierung mit Terraform

An dieser Stelle angekommen, werden wir nun zum ersten Mal die bisher definierten Ressourcen von Terraform provisionieren lassen.
Grund dafür ist, dass wir für die weiteren Schritte die Floating IP unseres Controlplane Nodes kennen müssen.

Wir führen also folgenden Befehl aus, bestätigen die X ausstehenden Änderungen mit yes, und warten auf die erfolgreich abgeschlossene Provisionierung:

terraform apply

Unsere bisherige Konfiguration resultiert in 15 zu provisionierenden Ressourcen in OpenStack.

Hier sehen wir nach erfolgreicher Provisionierung auch zum ersten Mal unsere Floating IP – allerdings ist sie bisher noch mit keinem Workload verbunden.

Dank des von uns definierten Outputs erhalten wir die provisionierte Floating IP direkt nach Erstellung.

Erstellung der Talos Linux VMs

Nachdem wir erfolgreich (unter Anderem) eine Floating IP für unser Projekt provisioniert haben, können wir mit der Installation von Talos Linux auf OpenStack fortfahren.

Erstellung der Talos Konfigurationen

Falls noch nicht geschehen, ist jetzt der perfekte Zeitpunkt, um die Talos CLI zu installieren. Für Anweisungen folge bitte der Verlinkung.

Einmal installiert, generieren wir mit der CLI lokal die benötigten Konfigurationsdateien.
Zuerst generieren wir benötigte Secrets (CA-Keys, Tokens, etc.).
Dann erstellen wir die Konfiguration für Controlplane, Worker und die lokale CLI: Wir übergeben einen Clusternamen sowie den Kubernetes-Endpoint (https://:6443) und die zuvor erstellten Secrets – hierfür brauchen wir die zuvor erstellte Floating IP:

talosctl gen secrets
talosctl gen config talos-on-openstack https://:6443 --with-secrets secrets.yaml

Wir erhalten auf diese Weise vier Dateien:

  • secrets.conf mit den für die Konfiguration von Talos Linux und Kubernetes benötigten Secrets
  • talosconfig mit den für unsere lokale CLI notwendigen Informationen
  • controlplane.yaml mit der Konfiguration für unsere(n) Controlplane Node(s)
  • worker.yaml mit der Konfiguration für unsere Worker Nodes

Erstellung der Compute Instances

Für die Erstellung der Compute Instances benötigen wir neben dem bereits definierten Boot Image noch einen sog. Flavor, der u.a. CPU-Anzahl, Arbeits- und Festplattenspeicher der VMs bestimmt.

Hierfür erweitern wir data.tf, um Informationen über einen vorhandenen Flavor in unserem Terraform Projekt zu erhalten. Aufgrund des ressourcensparenden Designs von Talos Linux reicht für unsere Zwecke der Flavor s1.small:

data "openstack_compute_flavor_v2" "s1-small" {
    name = "s1.small"
}

Je nach OpenStack Umgebung müssen hier erneut Anpassungen vorgenommen werden, um einen vorhandenen Flavor abzufragen.

Mit Definition dieser Ressourcen bleibt nur noch die Erstellung der eigentlichen VMs übrig! Diese definieren wir ebenfalls in compute.tf und referenzieren als user_data unsere gerade generierten Konfigurationsdateien – so werden diese bei Erstellung der VMs direkt von Talos berücksichtigt:

resource "openstack_compute_instance_v2" "talos-controlplane" {
    name      = "talos-controlplane"
    image_id  = openstack_images_image_v2.talos-175.id
    flavor_id = data.openstack_compute_flavor_v2.s1-small.id
    user_data = file("controlplane.yaml")

    network {
        port = openstack_networking_port_v2.talos-controlplane.id
    }
}

resource "openstack_compute_instance_v2" "talos-workers" {
    count     = 2
    name      = "talos-worker-${count.index}"
    image_id  = openstack_images_image_v2.talos-175.id
    flavor_id = data.openstack_compute_flavor_v2.s1-small.id
    user_data = file("worker.yaml")
    network {
        port = openstack_networking_port_v2.talos-workers[count.index].id
    }
}

Analog zur Portdefinition haben wir auch hier zwei Ressourcen, eine für den Controlplane Node und eine für die Worker Nodes. Wir referenzieren außerdem das definierte Boot Image, den Flavor, sowie den jeweiligen Port.

Evtl. ist für uns auch die Subnet-interne IP der Worker-VMs relevant, z.B. um via Talos CLI und unserem zugänglichen Controlplane Node Änderungen an den Worker Nodes vorzunehmen.

Deswegen fügen wir auch für die Worker Nodes einen entsprechenden Eintrag in outputs.tf hinzu:

output "worker-ip" {
    value = openstack_compute_instance_v2.talos-workers[*].access_ip_v4
}

Provisionierung der Talos Linux VMs mit Terraform

Wir sind soweit – alle benötigten Ressourcen sind in *.tf-Dateien definiert, und wir können uns dem (fast) finalen Schritt zuwenden: Der tatsächlichen Provisionierung von Talos Linux auf OpenStack!

Hierfür nutzen wir erneut folgenden Befehl:

terraform apply

Terraform wird den Zustand unseres OpenStack Projekts mit dem lokal definierten, gewünschten Zustand abgleichen, und uns im Anschluss eine Zusammenfassung der noch ausstehenden Änderungen (unsere drei Compute Instances) anzeigen.

Terraform kennt den Livezustand der provisionierten Infrastruktur und wird lediglich die noch fehlenden Ressourcen erstellen.

Sind wir mit diesen Änderungen zufrieden, bestätigen wir erneut mit yes und warten, bis Terraform die Provisionierung durchgeführt hat. Am Ende sollten wir zusätzlich zur bereits bekannten Floating IP die beiden internen IPs unserer Worker Nodes als Output erhalten:

Auch unsere drei VMs wurden erstellt, und die IP-Adressen von Terraform ausgegeben.

Die Installation von Talos Linux auf OpenStack war erfolgreich! Kommen wir also zum letzten Schritt unseres Installationsplans: Der Einrichtung eines Kubernetes Clusters.

Bootstrapping von Kubernetes auf Talos Linux

Die Erstellung eines Kubernetes Clusters auf Talos geschieht durch folgenden Befehl gegen unseren Controlplane Node. Direkt im Anschluss können wir die resultierende kubeconfig speichern:

talosctl --talosconfig talosconfig bootstrap \
  --endpoints  \
  --nodes 

talosctl --talosconfig talosconfig kubeconfig \
  --endpoints  \
  --nodes

Nun warten wir einen Moment, bis das Cluster erfolgreich erstellt wurde:

talosctl --talosconfig talosconfig health \
  --endpoints  \
  --nodes

Ist das Cluster gestartet, können wir uns seinen Zustand anzeigen lassen. Wir müssen lediglich sicherstellen, dass wir den richtigen Kubernetes Kontext verwenden:

kubectl get nodes
NAME                 STATUS   ROLES           AGE     VERSION
talos-controlplane   Ready    control-plane   2m16s   v1.30.3
talos-worker-0       Ready                    2m17s   v1.30.3
talos-worker-1       Ready                    2m17s   v1.30.3

Talos Linux auf OpenStack + Terraform = ❤️

Mit der erfolgreichen Installation von Talos Linux auf OpenStack und der Einrichtung deines Kubernetes-Clusters hast du nun eine leistungsstarke und flexible Umgebung, die speziell für den Betrieb von Container-Workloads optimiert ist.

Durch die Kombination von OpenStack, Talos und Terraform hast du die volle Kontrolle über deine Umgebung, Die du jederzeit „von Null“ aus aufbauen, replizieren, oder beliebig anpassen kannst. Dieser Ansatz gibt dir die Freiheit, deine Kubernetes-Cluster genau nach deinen Anforderungen zu gestalten, sollten Managed Services einmal zu unflexibel sein.
So oder so – Du bist nun bestens gerüstet, um deine Cloud-native Anwendungen auf einer stabilen, sicheren und skalierbaren Plattform zu betreiben.

Um weiterhin am Ball zu bleiben möchten wir dir an dieser Stelle noch einmal empfehlen, unseren Newsletter zu abonnieren. So erhältst du regelmäßig neue, topaktuelle und interessante Einblicke in Cloud-native Praktiken, Tutorials, und Neuigkeiten.

Unser Portfolio

0 Kommentare

Einen Kommentar abschicken

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Wie hat Dir unser Artikel gefallen?