Der CNCF-Blog stellt ein betriebliches Rezept für den Aufbau eines Open-Source-Stacks zur Verwaltung von Secrets auf Kubernetes vor, der OpenBao und CloudNativePG kombiniert. OpenBao ist der Open-Source-Fork von HashiCorp Vault unter dem Dach der Linux Foundation, während CloudNativePG einen PostgreSQL-Cluster in einen selbstheilenden Dienst mit synchroner Replikation und zertifikatsbasierter Authentifizierung verwandelt. Das Rezept nutzt Kubernetes, ein aus der CNCF hervorgegangenes Projekt, sowie CloudNativePG, ein Sandbox-Projekt, das von der CNCF Technical Oversight Committee für den Übergang in die Inkubationsphase bewertet wird.
Die grundlegende Idee besteht nicht lediglich darin, PostgreSQL als gewöhnlichen Speicher zu verwenden, sondern OpenBao von einem hochverfügbaren PostgreSQL-Backend abhängig zu machen, ohne auf eine proprietäre, an einen bestimmten Anbieter gebundene Cloud-Datenbank zurückzugreifen. Das Rezept verwendet drei CloudNativePG-Instanzen mit quorumsgestützter synchroner Replikation, sodass eine einzige verfügbare synchrone Standby-Instanz ausreicht, um die Datenbeständigkeit zu gewährleisten. Im Gegenzug können Schreibvorgänge angehalten werden, wenn keine Standby-Instanz verfügbar ist, die die erforderliche Beständigkeitsbedingung erfüllt.
Was ändert sich am Design?
OpenBao verwendet den nativen PostgreSQL-Speicher mit aktiviertem Hochverfügbarkeits-Sperrtabellenmodus über die Option ha_enabled = true. Die Konfiguration erstellt zwei Tabellen: openbao_kv_store zur Speicherung der Daten und openbao_ha_locks zur Speicherung der Datensätze für Hochverfügbarkeitssperren. Das Rezept deaktiviert den standardmäßigen lokalen Speicher im OpenBao-Schema, da der gesamte Zustand in CloudNativePG verbleiben soll.
CloudNativePG betreibt einen PostgreSQL-Cluster mit drei Instanzen, die auf dedizierte Knoten gelenkt werden und mithilfe von Knotenselektoren, Toleranzen und Pod-Affinitätsbeschränkungen über getrennte Fehlerdomänen verteilt sind. Das Rezept verwendet einen Image Catalog, der die minimale PostgreSQL-Version 18 festlegt, statt manuell ein festes Image-Tag einzutragen, und zeigt außerdem einen Teststatus, bei dem ein anhand eines SHA-Digests abgesichertes Image verwendet wurde.
Authentifizierung ohne Passwörter
Ein wesentlicher Aspekt des Rezepts besteht darin, Passwörter aus der Verbindung von OpenBao zur Datenbank zu entfernen. CloudNativePG erstellt DatabaseRole-Objekte für eine Rolle, der das Schema gehört, sowie für eine eingeschränkte Betriebsrolle namens openbao-rw; beide erhalten ein TLS-Clientzertifikat. Die pg_hba-Regeln erzwingen für diese beiden Rollen eine TLS-Verbindung mit Clientzertifikat, während unverschlüsselte Verbindungen abgewiesen werden.
Dieses Detail ist wichtig, da die Erstellung des Zertifikats allein seine automatische Verwendung nicht erzwingt. Die PostgreSQL-Regeln legen für jede Verbindung fest, ob die Authentifizierung über ein Zertifikat, ein Passwort oder gar nicht erfolgt. Außerdem setzt das Rezept die Berechtigungen der in die Container eingebundenen Secret-Dateien auf 0640, da die libpq-Bibliothek private Schlüssel ablehnt, die für die Gruppe oder alle Benutzer lesbar sind, wenn sie mit dem Standardwert 0644 eingebunden werden.
Da DatabaseRole laut dem Artikel derzeit keine Vergabe von Berechtigungen auf Tabellenebene verwaltet, führt ein einmalig ausgeführter Job Befehle zum Erstellen der Tabellen sowie zur Vergabe der Berechtigungen SELECT, INSERT, UPDATE und DELETE an die eingeschränkte Rolle aus. Der Job entzieht PUBLIC außerdem die CONNECT-Berechtigung und PUBLIC die Nutzung des öffentlichen Schemas und gewährt openbao-rw anschließend die erforderlichen Mindestberechtigungen. In der OpenBao-Konfiguration wird die Option skip_create_table aktiviert, damit die Betriebsrolle nicht selbst versucht, die Tabellen zu erstellen.
Was bedeutet das praktisch für Kubernetes-Betreiber?
Das Rezept bietet einen lokalen Testpfad mit dem Repository cnpg-playground, das einen aus sechs Knoten bestehenden Kind-Cluster erstellt und CloudNativePG-Konfigurationen vorab enthält. Für den Test werden Docker, Kind, Helm und kubectl benötigt. Die Knotenverteilung in der Testumgebung bringt jedoch eine wichtige Einschränkung mit sich: Es gibt dedizierte und gekennzeichnete PostgreSQL-Knoten, sodass für die Verteilung von drei OpenBao-Replikas mit erzwungener Affinität nur zwei allgemeine Knoten übrig bleiben. Daher erlaubt das Rezept OpenBao vorübergehend die Nutzung eines Control-Plane-Knotens in der Kind-Umgebung und warnt ausdrücklich davor, diese Toleranz in die Produktion zu übernehmen. In einem Produktionscluster mit drei nicht gekennzeichneten Worker-Knoten ist diese Anpassung nicht erforderlich.
Nach der Installation des OpenBao-Charts muss der Cluster initialisiert und jede Instanz einzeln entsiegelt werden, wobei drei der fünf erforderlichen Shamir-Schlüssel verwendet werden. Das Entsiegeln der ersten Instanz entsiegelt die beiden anderen Instanzen nicht. Außerdem verzögert die standardmäßige OrderedReady-Richtlinie des StatefulSets die Erstellung der nächsten Instanz, bis die vorherige bereit ist. Daher sollten die Entsiegelungsschlüssel und das Root-Token sicher aufbewahrt und die Schlüssel für jede Instanz der Reihe nach eingegeben werden.
Nach der Initialisierung speichert OpenBao den Startzustand und seine Schlüssel in der Tabelle openbao_kv_store. Der Wert des Test-Secrets wird als verschlüsselte BYTEA-Daten gespeichert und liegt selbst bei direktem Zugriff auf die PostgreSQL-Tabelle nicht im Klartext vor. Der Artikel bestätigt den erfolgreichen Test des Schreibens und Lesens eines Secrets mit KV v2 und der eingeschränkten PostgreSQL-Rolle.
Betriebliche Einschränkungen und nicht abgedeckte Bereiche
Die Zertifikate werden von CloudNativePG automatisch erneuert. Ein CNPG-Clientzertifikat ist 90 Tage gültig und wird üblicherweise etwa eine Woche vor seinem Ablauf erneuert. OpenBao liest die Zertifikatsdateien jedoch nicht automatisch erneut ein, da das PostgreSQL-Speicher-Backend den Verbindungspool beim Prozessstart öffnet. Daher muss ein schrittweiser Neustart der OpenBao-Instanzen nach der Erneuerung geplant werden, vorzugsweise innerhalb des 83-tägigen Erneuerungsfensters vor Ablauf des alten Zertifikats.
Hochverfügbarkeit innerhalb eines Kubernetes-Clusters ist außerdem kein vollständiger Notfallwiederherstellungsplan. Das Rezept erstellt nicht automatisch Sicherungen oder eine Wiederherstellung nach dem vollständigen Verlust des Clusters. Für den Produktionseinsatz empfiehlt der Artikel, das Barman Cloud Plugin mit einem Objektspeicher wie Amazon S3, Google Cloud Storage oder Azure Blob Storage zu ergänzen und die Ressourcen Backup und ScheduledBackup zu verwenden, um WAL sowie Basissicherungen zu archivieren und eine Wiederherstellung zu einem bestimmten Zeitpunkt zu ermöglichen. RTO- und RPO-Ziele, die den Verlust eines gesamten Clusters überstehen müssen, erfordern einen asynchronen PostgreSQL-Cluster in einem zweiten Cluster oder einer zweiten Region.