Ich habe eine Einstellung in einer Kubernetes-ConfigMap auf Azure Kubernetes Service (AKS) geändert: die API-Version, von 1.0.0 auf 2.0.0. kubectl meldete „configured“, die ConfigMap zeigte 2.0.0. Meine laufende App antwortete weiter mit 1.0.0. Kein Fehler, kein Neustart.
Dieser Beitrag zeigt, warum ein laufender Pod alte Einstellungen behält, wann er neue übernimmt, und einen Namenstrick, der jede Änderung der Einstellungen zu einem Rollout macht, den Sie rückgängig machen können. Alles stammt aus der Übung des Microsoft-Learn-Moduls, ausgeführt in meinem eigenen Cluster.
Das Wichtigste
- Eine Umgebungsvariable ist eine Kopie vom Start. Kubernetes kopiert die Werte einer ConfigMap einmal in die Umgebung eines Containers, wenn er startet, und aktualisiert sie in einem laufenden Prozess nie.
- Eine geänderte ConfigMap startet nichts. Ein Deployment rollt neue Pods nur aus, wenn sich sein eigenes Pod-Template ändert. Das Template enthält den Namen der ConfigMap, nicht ihre Werte; die Rollout-Historie blieb bei einer Revision.
- Gemountete Dateien ziehen nach, etwa eine Minute später. Das kubelet aktualisiert eine gemountete ConfigMap nach eigenem Takt. In meinem Lauf wechselte die Datei nach 81 Sekunden. Eine per
subPathgemountete Datei änderte sich nie, und eine App, die ihre Einstellungen beim Start liest, bemerkte so oder so nichts. - Der Neustart ist das Update.
kubectl rollout restartschreibt einen Zeitstempel ins Pod-Template; das Deployment startet einen neuen Pod, und der kopiert die aktuellen Einstellungen. Eine neue, unveränderliche ConfigMap pro Version leistet dasselbe, mit Historie und Undo.
Beim Start kopiert
Eine ConfigMap ist ein Kubernetes-Objekt, das Einstellungen als Schlüssel und Werte hält, außerhalb Ihres Container-Images. Die Übung legt drei Einstellungen hinein: einen Namen, die API-Version und einen Log-Pfad. Ein Pod umschließt Ihren Container; ein Deployment hält Ihre Pods am Laufen, und sein Pod-Template ist das Rezept für jeden neuen Pod. In der Übung lädt dieses Rezept die ganze ConfigMap mit envFrom, einem einzigen Verweis über den Namen, sodass jeder Schlüssel zur Umgebungsvariable wird:
envFrom:- configMapRef:name: api-config
Ich habe die Änderung angewendet und Kubernetes nach dem Wert in der ConfigMap gefragt:
> kubectl get configmap api-config -o jsonpath="{.data.API_VERSION}"2.0.0
Dann habe ich die App über ihre öffentliche Adresse nach ihrer Version gefragt, und den Container selbst:
> python cfg.py get /healthzGET /healthz -> 200{"status":"alive",… "version":"1.0.0","student":"Ehsan"}> kubectl exec deploy/aks-config-api -- printenv API_VERSION1.0.0
Umgebungsvariablen werden einmal gesetzt, wenn der Container startet. Kubernetes schreibt sie in einem laufenden Prozess nie neu. kubectl describe pod zeigt beide Hälften davon: woher die Einstellungen kommen und dass der Container vor der Änderung gestartet ist, ohne Neustart seitdem.
Started: Wed, 28 Oct 2026 13:30:55 +0100Restart Count: 0Environment Variables from:api-config ConfigMap Optional: false
Kubernetes hat den neuen Wert gespeichert. Hat es dafür einen neuen Pod ausgerollt? Nein. Die Rollout-Historie, die Liste aller Versionen des Pod-Templates, hatte weiterhin einen Eintrag:
> kubectl rollout history deployment aks-config-apiREVISION CHANGE-CAUSE1 <none>
Ein Deployment startet neue Pods nur, wenn sich sein Pod-Template ändert. Das Template enthält den Namen der ConfigMap, nicht ihre Werte; eine geänderte ConfigMap ist also keine Änderung am Deployment.
Als Dateien gemountet
Eine ConfigMap lässt sich auch als Volume mounten: Jeder Schlüssel wird zu einer Datei in einem Ordner. Ich habe das im Deployment ergänzt und die API-Version zusätzlich als einzelne Datei per subPath gemountet:
volumeMounts:- name: config-volumemountPath: /etc/config- name: config-volumemountPath: /etc/api-versionsubPath: API_VERSION
Die Änderung am Template startete einen Rollout: ein neuer Pod, nach 22 Sekunden bereit. Der neue Pod kopierte die ConfigMap so, wie sie bei seinem Start war, und antwortete deshalb mit 2.0.0. In ihm lag in /etc/config eine Datei pro Schlüssel: API_VERSION, LOG_PATH, STUDENT_NAME.
Dann habe ich die ConfigMap auf 3.0.0 geändert. Ein kleines Skript von mir hat sie angewendet und drei Minuten lang jede Sekunde vier Stellen gelesen: die gemountete Datei, die subPath-Datei, die Umgebungsvariable und die Antwort der App.
> python cfg.py change k8s/configmap-v3.yaml --secs 1801.1s file 2.0.0 | subPath 2.0.0 | env 2.0.0 | app 2.0.01.7s applied: configmap/api-config configured81.1s file 3.0.0 (was 2.0.0)180.2s file 3.0.0 | subPath 2.0.0 | env 2.0.0 | app 2.0.0
| Was der Pod liest | Nach der Änderung |
|---|---|
Umgebungsvariable (envFrom) | nie, bis der Container neu startet |
Gemounteter Ordner (/etc/config) | nach dem nächsten Sync des kubelets: hier 81 s |
Einzelne Datei per subPath | nie, bis der Container neu startet |
| Eine App, die ihre Einstellungen beim Start liest | nie, bis sie neu liest oder neu startet |
Gemountete Dateien folgen der ConfigMap, aber nicht sofort. Das kubelet, der Kubernetes-Agent auf jedem Node, prüft gemountete ConfigMaps bei seinem regelmäßigen Sync (standardmäßig einmal pro Minute) und liest sie aus seinem eigenen Cache; rechnen Sie mit ein bis zwei Minuten, nicht mit einer Sekunde.
Wie ändert sich eine Datei, ohne dass ein Lesevorgang mittendrin bricht? Die Dateien sind Links in einen versteckten Ordner:
> kubectl exec deploy/aks-config-api -- ls -la /etc/config… ..data -> ..2026_10_28_12_33_19.3747003581… API_VERSION -> ..data/API_VERSION
Das kubelet schreibt einen kompletten neuen Ordner und schaltet dann den einen ..data-Link um. Deshalb änderte sich auch die subPath-Datei nie: subPath mountet die Datei selbst, so wie sie beim Start war, nicht den Link; die Umschaltung erreicht sie nie.
Und die App? Die API der Übung liest ihre Version einmal beim Start aus der Umgebungsvariable. Die Datei änderte sich unter ihr, und die App schaute nie hin. Eine gemountete Datei hilft nur, wenn Ihr Code die Datei liest, und sie erneut liest.
Den Rollout auslösen
Die Lösung ist ein Befehl, und die Übung nennt ihn als Tipp:
> kubectl rollout restart deployment aks-config-apideployment.apps/aks-config-api restarted
22 Sekunden später war der neue Pod bereit, die App antwortete mit 3.0.0, und auch die subPath-Datei zeigte 3.0.0. rollout restart fasst die ConfigMap nicht an. Es schreibt eine Annotation ins Pod-Template:
> kubectl get deployment aks-config-api -o jsonpath="{.spec.template.metadata.annotations}"{"kubectl.kubernetes.io/restartedAt":"2026-10-28T13:35:01+01:00"}
Für das Deployment ist das eine Änderung: Es startet einen neuen Pod, und der kopiert beim Start die aktuellen Einstellungen. Erst die ConfigMap ändern, dann das Deployment neu starten.
Ein Rollout, den Sie rückgängig machen können
Der Namenstrick: Geben Sie den nächsten Einstellungen eine neue ConfigMap mit neuem Namen, markieren Sie sie als unveränderlich, und lassen Sie das Deployment auf diesen Namen zeigen.
apiVersion: v1kind: ConfigMapmetadata:name: api-config-v4data:API_VERSION: "4.0.0"immutable: true
Der Name ist Teil des Pod-Templates; das Anwenden des Deployments rollte deshalb von selbst aus, und die App antwortete mit 4.0.0. Jede Änderung der Einstellungen ist jetzt eine Revision: kubectl rollout undo brachte das Deployment zurück zum Template mit api-config, und die App antwortete wieder mit 3.0.0. Und die unveränderliche ConfigMap lässt sich nicht versehentlich ändern:
> kubectl apply -f k8s/versioned/configmap-v4-edit.yamlThe ConfigMap "api-config-v4" is invalid: data: Forbidden: field is immutable when `immutable` is set
Umbenennen müssen Sie nicht von Hand: Kustomize, in kubectl eingebaut (kubectl apply -k), erzeugt die ConfigMap mit einem Hash ihres Inhalts im Namen und passt die Verweise an. Neue Einstellungen, neuer Name.
Was bei meinem Lauf passiert ist
Getestet am 28. Oktober 2026 in meinem eigenen Azure-Abonnement (AKS 1.36 in westeurope, Azure CLI 2.88.0, kubectl 1.36); danach wurde alles gelöscht. Der Cluster hatte einen Node Standard_D2s_v5 (erstellt in 271 s), und die API der Übung antwortete 51 s nach kubectl apply. Jeder Rollout (das Datei-Deployment, der Neustart, die neue ConfigMap, das Undo) dauerte 22–23 s. Die erste Anfrage direkt nach einem Rollout lief zweimal einmal in ein Timeout, bevor die nächste antwortete; das Skript des Laufs hat wiederholt und beides ausgegeben.
Was das Video auslässt
- Azure App Configuration: Ihr Kubernetes-Provider läuft im Cluster und erzeugt ConfigMaps aus Einstellungen, die in App Configuration liegen; mehrere Cluster teilen sich so einen Ort für Einstellungen.
binaryData, Verweise mitoptional: trueund das Limit von 1 MiB pro ConfigMap.- Die Checksum-Annotation von Helm am Pod-Template: dieselbe Idee wie der Namenstrick, umgesetzt von einem Chart.
- Secrets und persistenter Speicher, die beiden anderen Teile des Moduls (eigene Beiträge).
Weiterführende Links
- Microsoft-Learn-Modul: Configure applications on Azure Kubernetes Service
- ConfigMaps (Kubernetes-Dokumentation)
- Deployments (Kubernetes-Dokumentation)
- Azure App Configuration Kubernetes Provider


