ADMIN
2022
01
2022-01-01T12:00:00
Rechenzentrum und Netze verwalten
PRAXIS
052
Open-Source-Tipp
Datenserialisierung
Konfiguration mit YAML
An den Schalthebeln
von Thorsten Scherf
Veröffentlicht in Ausgabe 01/2022 - PRAXIS
In den letzten Jahren hat die Auszeichnungssprache YAML immer mehr an Popularität gewonnen und ist in vielen unterschiedlichen Bereichen die erste Wahl, wenn es um die Konfiguration von komplexen Umgebungen geht. Der Open-Source-Tipp in diesem Monat hilft Ihnen beim Einstieg in die Sprache und wirft auch einen Blick auf den YAML-Parser yq.

YAML [1] ist aus der DevOps-Welt nicht mehr wegzudenken. Tatsächlich ist es so, dass YAML eine Obermenge von JSON [2], JavaScript Object Notation, darstellt. Der Focus von JSON liegt dabei allerdings eher in der Serialisierung von Daten, also beispielsweise um diese über eine API zur Verfügung zu stellen.
Im Gegensatz dazu spielt YAML seine Stärken aus, wenn es als Konfigurationssprache zum Einsatz kommt, da das Format doch besser lesbar ist als JSON. Und Python-Programmierer lieben YAML sowieso, da im Gegensatz zu JSON keine Klammern zur Definition von Objekten zum Einsatz kommen, sondern stattdessen Einrückungen stattfinden.
Grundlegende YAML-Syntax
Listing 1 zeigt ein einfaches YAML-Dokument. Ein solches Dokument beginnt mit der Zeichenkette "---", wodurch eine Datei durchaus mehrere solcher Dokumente enthalten kann. Im Anschluss folgen typische Key/Value-Paare, die Sie wahrscheinlich schon von JSON kennen. Beim erstem Schlüsselpaar handelt es sich um einen einfachen Skalar mit einem String-Wert. Neben Strings sind natürlich auch Zahlen und Booleans zulässig. Im Anschluss folgt eine Liste, also ein Sammlung von Objekten. In diesem Fall kommen ausschließlich numerische Werte zum Einsatz, die jeweils mithilfe von Leerzeichen eingerückt sind.
YAML [1] ist aus der DevOps-Welt nicht mehr wegzudenken. Tatsächlich ist es so, dass YAML eine Obermenge von JSON [2], JavaScript Object Notation, darstellt. Der Focus von JSON liegt dabei allerdings eher in der Serialisierung von Daten, also beispielsweise um diese über eine API zur Verfügung zu stellen.
Im Gegensatz dazu spielt YAML seine Stärken aus, wenn es als Konfigurationssprache zum Einsatz kommt, da das Format doch besser lesbar ist als JSON. Und Python-Programmierer lieben YAML sowieso, da im Gegensatz zu JSON keine Klammern zur Definition von Objekten zum Einsatz kommen, sondern stattdessen Einrückungen stattfinden.
Grundlegende YAML-Syntax
Listing 1 zeigt ein einfaches YAML-Dokument. Ein solches Dokument beginnt mit der Zeichenkette "---", wodurch eine Datei durchaus mehrere solcher Dokumente enthalten kann. Im Anschluss folgen typische Key/Value-Paare, die Sie wahrscheinlich schon von JSON kennen. Beim erstem Schlüsselpaar handelt es sich um einen einfachen Skalar mit einem String-Wert. Neben Strings sind natürlich auch Zahlen und Booleans zulässig. Im Anschluss folgt eine Liste, also ein Sammlung von Objekten. In diesem Fall kommen ausschließlich numerische Werte zum Einsatz, die jeweils mithilfe von Leerzeichen eingerückt sind.
Listing 1: YAML-Objekte
---
name: starwars-kollektion
erscheinungsjahr:
- 1977
- 1980
- 1983
filme:
# An dieser Stelle werden lediglich Filme aus der Original-Trilogie (OT) aufgeführt.
ot:
- Episode IV – Eine neue Hoffnung
- Episode V – Das Imperium schlägt zurück
- "Episode VI – Die Rückkehr der Jedi-Ritter
Auf Tabs sollten Sie wenn möglich verzichten, da diese immer wieder zu Problemen bei der Verarbeitung der Daten führen können. Strings müssen Sie übrigens nicht zwingend in Klammern schreiben, wie das letzte Beispiel aus Listing 1 zeigt. Hierbei handelt es sich um ein Dictionary, also eine Sammlung von Key/Value-Paaren. Im Gegensatz zu JSON können Sie in YAML auch problemlos mit Kommentaren arbeiten. Diese werden am Anfang oder Ende einer Zeile mit dem "#"-Zeichen eingeleitet.
Um die so abgespeicherten Daten nun beispielsweise mit Python zu bearbeiten, können Sie auf das PyYAML-Modul zurückgreifen. Das Modul wandelt YAML-Objekte in ein Python-Dictionary (dict-Objekt), das Sie dann nach den eigenen Anforderungen weiter verarbeiten können. Listing 2 zeigt ein einfaches Beispiel. Das Python-Skript liest Daten aus der Datei starwars.yaml ein und formiert diese vor der Ausgabe.
Listing 2: starwars.py
#!/usr/bin/env python3
import yaml
from yaml.loader import SafeLoader
with open('starwars.yaml') as f: sw = yaml.load(f, Loader=SafeLoader) print(yaml.dump(sw, indent=4, default_flow_style=False))
Kommandozeilen-Parser für YAML
Zum Verarbeiten von in YAML geschriebenen Konfigurationsdateien eignet sich der Parser yq [3] ganz hervorragend. Dieser ist an den bekannten JSON-Parser jq [4] angelehnt und verwendet von daher eine sehr ähnliche Syntax. Ein netter Nebeneffekt ist auch, dass Sie mit yq ebenfalls JSON-Daten verarbeiten können. Sollte Ihre Linux-Distribution kein fertiges yq-Paket anbieten, installieren Sie die Software ganz einfach direkt von der GitHub-Seite mit
wget
https://github.com/mikefarah/yq/releases/download/v4.14.1/yq_linux_amd64 -O ~/bin/yq
chmod u+x ~/bin/yq
Auf macOS-Systemen können Sie mithilfe des Homebrew-Paket-Managers die Software ebenfalls einspielen.
YAML-Dokumente durchsuchen
Eine typische Aufgabe bei der Verarbeitung von YAML-Dateien ist die Suche nach einem bestimmten Schlüssel und dem Wert, der diesem Schlüssel zugewiesen wurde. Möchten Sie also beispielsweise aus der "starwars.yaml"-Datei sämtliche Erscheinungsjahre herausfiltern, sieht dies wie folgt aus:
yq eval ".erscheinungsjahr[]"
starwars.yaml
Wollen Sie lediglich wissen, wann der erste Film erschienen ist, setzen Sie einen Index auf das erste Element der Liste:
yq eval ".erscheinungsjahr[0]"
starwars.yaml
Listing 3: YAML zur Beschreibung von Objekten
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: db1-container
image: k8s.gcr.io/busybox
env:
- name: DB_URL
value: postgres://db_url:5431
- name: db2-container
image: k8s.gcr.io/busybox
env:
- name: DB_URL
value: postgres://db_url:5432
Listing 3 enthält ein etwas umfangreicheres YAML-Dokument, das einen Kubernetes-Pod beschreibt. Um einen ersten Überblick darüber zu bekommen, welche Schlüssel diese Datei enthält, rufen Sie das folgende Kommando auf:
yq eval keys pod.yaml
Eine Liste sämtlicher Container-Namen erhalten Sie nun wie folgt:
yq eval ".spec.containers[].name" pod.yaml
Mit der "select"-Funktion können Sie auch Filter verwenden:
yq eval
'.spec.containers[].env[].value | select(. == "*32")' pod.yaml
postgres://db_url:5432
Validierung von Werten
Zur Validierung bestimmter Werte kann es auch ganz nützlich sein, die Länge der Werte zu ermitteln. Hierfür existiert die "length"-Funktion:
yq eval ".spec.containers[].name | length" pod.yaml
Ein YAML-Template lässt sich mittels yq auch ganz leicht modifizieren, sodass Sie hiermit sehr einfach Konfigurationen für unterschiedliche Umgebungen erzeugen können. Möchten Sie beispielsweise im "pod.yaml"-Template in die URL-Variable des ersten Containers den Hostnamen Ihrer produktiven Datenbank einfügen, gelingt dies mit
yq eval
'.spec.containers[0].env[0].value = "postgres:// prod.example.com:5431"' pod.yaml > prod-pod.yaml
Damit die Änderung nicht nur auf dem Bildschirm sichtbar ist, haben wir das geänderte YAML-Dokument in die neue Datei "prod-pod.yaml" geschrieben. Diese enthält nun die vorgenommene Modifikation, wie das folgende Kommando beweist:
yq eval ".spec.containers[0].env[0].value" prod-pod.yaml
postgres://prod.example.com:5431
So stimmt’s
In der Dezember-Ausgabe wurde im Open-Source-Tipp der Markdown-Text nicht ganz korrekt wiedergegeben. So sollte die Ausgabe eigentlich aussehen:# Hallo IT-AdministratorMit Hilfe von pandoc können Sie Texte in eine Vielzahl von unterschiedlichen Formaten exportieren.Zu den unterstützten Formaten zählen beispielsweise- html- pdf- epub- docx- pptsEin Blick in die **pandoc** Hilfe Seite mittels `man pandoc` zeigt Ihnen *sämtliche* unterstützten Formate an.
Im Zusammenspiel mit Kubernetes erweist sich diese Funktion als extrem hilfreich, da Sie hiermit bestehende Konfigurationen unmittelbar ändern können. Dies führen Sie durch, indem Sie beispielsweise die Ausgabe des KubernetesTools kubectl einfach an yq weiterleiten (kubectl ...|yq eval ...)
und mittels kubectl apply
das Ergebnis direkt wieder zurück an Kubernetes schicken.
(dr)