Dynamisches Konfigurationsmanagement: Verwendung von ConfigMaps für Echtzeit-Anwendungsupdates
Verwenden Sie Kubernetes ConfigMaps als gemountete Dateien für Laufzeit-Konfigurationsupdates, mit Einschränkungen hinsichtlich Propagation, subPath und App-Neuladeverhalten.
Dynamisches Konfigurationsmanagement: Verwendung von ConfigMaps für Echtzeit-Anwendungsupdates
Kubernetes bietet robuste Mechanismen zur Verwaltung des Anwendungszustands, aber das Ändern von Anwendungseinstellungen erfordert oft das Neuerstellen von Images oder das Neustarten von Deployment-Pods. Für viele Microservices ist diese Ausfallzeit oder Störung inakzeptabel. Hier kommen ConfigMaps ins Spiel. ConfigMaps sind Kubernetes-Objekte, die dazu dienen, nicht-vertrauliche Konfigurationsdaten in Schlüssel-Wert-Paaren zu speichern und so die Konfiguration vom Anwendungscode zu entkoppeln.
ConfigMaps helfen beim dynamischen Konfigurationsmanagement, wenn Ihre App Einstellungen aus Dateien liest und diese neu laden kann. Der Kubernetes-Teil ist nur die Hälfte des Setups: Gemountete ConfigMap-Dateien können sich ändern, während der Pod weiterläuft, Umgebungsvariablen jedoch nicht, und Ihre Anwendung muss die neuen Werte dennoch erkennen und anwenden.
Grundlegendes zu ConfigMaps: Die Basis
Ein ConfigMap ermöglicht es Ihnen, Konfigurationsdaten als eine Reihe von Schlüsseln und Werten zu speichern. Im Gegensatz zu Secrets sind ConfigMaps für nicht sensible Konfigurationsdaten wie Logging-Level, externe Service-Endpunkte oder Feature-Flags gedacht.
Erstellen eines Beispiel-ConfigMaps
Konfigurationsdaten können direkt im YAML-Manifest definiert oder aus vorhandenen Dateien oder Verzeichnissen erstellt werden. Erstellen wir ein ConfigMap namens app-settings, das anwendungsspezifische Parameter enthält.
Beispiel: ConfigMap in YAML definieren
apiVersion: v1
kind: ConfigMap
metadata:
name: app-settings
data:
# Schlüssel-Wert-Paare
LOG_LEVEL: "INFO"
API_ENDPOINT: "https://api.default.svc.cluster.local"
# Mehrzeiliger Konfigurationsdatei-Inhalt
application.properties: |
server.port=8080
feature.toggle.new_ui=false
Dieses ConfigMap stellt drei Datenpunkte bereit: zwei einfache Schlüssel-Wert-Paare und einen komplexen Eintrag (application.properties), der eine Konfigurationsdatei simuliert.
Injizieren von Konfigurationen in Pods
Während ConfigMaps Umgebungsvariablen befüllen können, liegt der Schlüssel zu dynamischen Updates darin, sie als Volumes im Dateisystem eines Pods zu mounten. Wenn sie als Volume gemountet werden, behandelt Kubernetes jeden Schlüssel im ConfigMap als eine Datei im angegebenen Verzeichnis.
Methode 1: Verwendung von Volume-Mounts (Der dynamische Ansatz)
Um dynamische Updates zu erreichen, mounten wir das ConfigMap in die Pod-Spezifikation.
Beispiel: Pod-Spezifikation mit ConfigMap-Volume-Mount
apiVersion: v1
kind: Pod
metadata:
name: dynamic-app-pod
spec:
containers:
- name: my-app
image: my-registry/my-app:latest
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-settings
In diesem Setup:
- Das ConfigMap
app-settingswird mit dem Volume namensconfig-volumeverknüpft. - Das Volume wird unter
/etc/configim Container gemountet. - Kubernetes erstellt automatisch Dateien in
/etc/config, die den Schlüsseln im ConfigMap entsprechen:/etc/config/LOG_LEVELenthält den WertINFO./etc/config/application.propertiesenthält die mehrzeilige Konfiguration.
Methode 2: Verwendung von Umgebungsvariablen (Statischer Ansatz)
Für einfachere, statische Werte können Sie diese als Umgebungsvariablen injizieren. Hinweis: Auf diese Weise befüllte Umgebungsvariablen werden nicht automatisch aktualisiert, wenn sich das ConfigMap ändert; der Pod muss neu gestartet werden.
# Ausschnitt aus einer Deployment-Spezifikation
containers:
- name: my-app
image: my-registry/my-app:latest
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-settings
key: LOG_LEVEL
Best Practice: Verwenden Sie für dynamische Updates immer Volume-Mounts für Konfigurationsdateien.
Erzielen von Echtzeit-Updates: Überwachung auf Änderungen
Wenn ein ConfigMap aktualisiert wird, propagiert Kubernetes die Änderung schließlich an Pods, die es als Volume mounten. Der genaue Zeitpunkt hängt vom Synchronisationsverhalten des Kubelets, dem Cache-Verhalten und der Knotenlast ab. Behandeln Sie es daher als eventuelle Propagation und nicht als sofortigen Push der Steuerungsebene.
Wie das Kubelet Updates propagiert
Wenn ein als Volume verwendetes ConfigMap geändert wird:
- Das Kubelet prüft während seines Synchronisationszyklus regelmäßig auf Updates und kann Daten aus seinem lokalen Cache bereitstellen.
- Wenn ein Update erkannt wird, aktualisiert das Kubelet die gemounteten Dateien im Host-Dateisystem.
- Für den laufenden Container werden die Dateien im ConfigMap-Volume über den projizierten Volume-Mechanismus von Kubernetes aktualisiert.
Es gibt eine häufige Ausnahme: Wenn Sie einen einzelnen ConfigMap-Schlüssel mit subPath mounten, aktualisiert Kubernetes diese gemountete Datei nicht, wenn sich das ConfigMap ändert. Verwenden Sie einen normalen ConfigMap-Volume-Mount, wenn Sie Laufzeit-Updates erwarten.
Erkennung auf Anwendungsseite
Der entscheidende Schritt ist, dass Ihr Anwendungscode, der im Container läuft, so konzipiert ist, dass er diese Dateiänderungen erkennt und darauf reagiert.
Beispiel: Anwendungslogik für Dateiüberwachung (Konzeptionelles Python)
Die meisten modernen Anwendungen verwenden interne Mechanismen oder Bibliotheken, um Dateisystemereignisse zu überwachen (z.B. inotify unter Linux).
import time
import os
CONFIG_PATH = "/etc/config/application.properties"
def load_config(path):
# Funktion zum Lesen und Parsen des Dateiinhalts
with open(path, 'r') as f:
print(f"\n--- Konfiguration neu geladen ---\n{f.read()}")
# Logik zum erneuten Initialisieren von Diensten mit neuen Einstellungen
# Erstes Laden
load_config(CONFIG_PATH)
# Kontinuierliche Überwachungsschleife
last_modified = os.path.getmtime(CONFIG_PATH)
while True:
current_modified = os.path.getmtime(CONFIG_PATH)
if current_modified != last_modified:
print("Dateiänderung erkannt. Konfiguration wird neu geladen...")
load_config(CONFIG_PATH)
last_modified = current_modified
time.sleep(5) # Alle 5 Sekunden prüfen
Dieses Beispiel demonstriert das Abfragen der Dateiänderungszeit (mtime). Wenn das Kubelet die Datei aktualisiert, erkennt die Anwendung die Änderung und kann die Konfiguration dynamisch neu laden.
Achtung bei Dateiüberwachung: ConfigMap-Volume-Updates können Symlink-Ziele unter dem gemounteten Verzeichnis ersetzen. Wenn Ihr Überwacher nur einem geöffneten Datei-Handle folgt, kann er Updates verpassen. Überwachen Sie das Verzeichnis oder fragen Sie den Dateiinhalt ab, wenn Zuverlässigkeit wichtiger ist als sofortiges Neuladen.
Dynamischer Update-Workflow: Ein Schritt-für-Schritt-Beispiel
Lassen Sie uns das Aktualisieren von LOG_LEVEL von INFO auf DEBUG durchgehen, ohne den laufenden Pod zu berühren.
Schritt 1: Ausgangszustand
Stellen Sie sicher, dass Ihr Pod läuft und das ConfigMap über Volume-Mounts konsumiert.
Schritt 2: Aktualisieren des ConfigMaps
Ändern Sie das vorhandene ConfigMap mit kubectl edit oder kubectl apply.
# Verwenden von kubectl edit, um den Wert direkt zu ändern
kubectl edit configmap app-settings
# Finden und ändern Sie die Zeile:
# LOG_LEVEL: "INFO"
# ZU:
LOG_LEVEL: "DEBUG"
Schritt 3: Überwachung der Propagation
Warten Sie, bis das Kubelet die Änderung propagiert. Dies kann in manchen Clustern länger als ein paar Sekunden dauern.
Wenn Ihre Anwendung /etc/config/LOG_LEVEL überwacht:
- Das Kubelet aktualisiert die zugrunde liegende Datei.
- Die Anwendung erkennt die Änderung (basierend auf ihrem Überwachungsmechanismus).
- Die Anwendung lädt ihre interne Logging-Konfiguration auf
DEBUGneu.
Entscheidend ist, dass der Pod selbst unberührt bleibt, was eine vollständige Serviceunterbrechung verhindert.
Zusammenfassung und Überlegungen zum Konfigurationsmanagement
Die Verwendung von ConfigMaps mit Volume-Mounts ist die kanonische Methode, um dynamische Konfigurationsupdates in Kubernetes zu erreichen. Beachten Sie jedoch folgende Punkte:
- Sicherheit: ConfigMaps speichern Daten im Klartext. Verwenden Sie Secrets für sensible Informationen.
- Unveränderlichkeit: Erwägen Sie für kritische Konfigurationen, das ConfigMap nach der Erstellung unveränderlich zu machen (
immutable: truein der Spezifikation), um versehentliche Laufzeitänderungen zu verhindern. - Anwendungsbewusstsein: Die Dynamik ist nur möglich, wenn der laufende Container weiß, wie er die Konfigurationsdateien überwachen und neu laden kann.
- Rollback: Das Zurücksetzen einer Konfigurationsänderung erfordert das Aktualisieren des ConfigMaps auf den vorherigen Zustand und das Warten auf die Erkennung durch die Anwendung.
Durch die Entkopplung der Konfiguration von Bereitstellungsartefakten und die Nutzung von Volume-Mounts ermöglichen Sie robuste Updates mit null Ausfallzeiten für Konfigurationsparameter in Ihren Kubernetes-Workloads.