kubectl apply vs set: Die richtige Wahl für Ressourcen-Updates

Verstehen Sie, wann Sie kubectl apply, set und edit verwenden sollten, ohne Abweichungen zwischen Live-Kubernetes-Objekten und Git zu erzeugen.

kubectl apply vs set: Die richtige Wahl für Ressourcen-Updates

Der Unterschied zwischen kubectl apply und kubectl set ist nicht nur Syntax. Es ist der Unterschied zwischen der Verwaltung von Kubernetes aus einer deklarierten Quelle der Wahrheit und der direkten Änderung von Live-Objekten. Beide sind nützlich. Beide können schaden, wenn Sie sie an der falschen Stelle einsetzen.

Verwenden Sie kubectl apply, wenn die Änderung zum gewünschten Zustand des Systems werden soll. Verwenden Sie kubectl set, wenn Sie eine gezielte Live-Änderung benötigen, die in der Regel temporär oder dringend ist. Verwenden Sie kubectl edit, wenn Sie ein Live-Objekt interaktiv inspizieren und patchen müssen, aber verstehen Sie, dass es der einfachste Weg ist, Abweichungen von Git zu erzeugen.

Ein Kubernetes-Objekt hat einen gewünschten Zustand, der im API-Server gespeichert ist. Ein Deployment legt fest, wie viele Replicas existieren sollen, welches Image laufen soll, welche Labels Pods identifizieren, welche Ressourcen angefordert werden und mehr. Controller arbeiten daran, die Realität an diesen gewünschten Zustand anzupassen. Ihr Update-Befehl ändert den gewünschten Zustand; die Controller erledigen den Rest.

Mit kubectl apply halten Sie diesen gewünschten Zustand in YAML- oder JSON-Dateien. Die Datei ist das, was Sie überprüfen, committen, promoten und zurücksetzen. Ein typischer Befehl ist einfach:

kubectl apply -f deployment.yaml

Wenn das Objekt nicht existiert, erstellt Kubernetes es. Wenn es existiert, aktualisiert Kubernetes es, um dem Manifest zu entsprechen. Das erneute Anwenden derselben Datei sollte keine neue Verhaltensänderung verursachen. Diese Idempotenz ist einer der Gründe, warum apply gut in CI/CD- und GitOps-Workflows funktioniert.

Client-seitiges kubectl apply verwendete historisch eine Last-Applied-Annotation, um Änderungen zu berechnen. Server-seitiges Apply, aktiviert mit --server-side, verfolgt Feldbesitz durch Managed Fields im API-Server. Die Details unterscheiden sich, aber die operative Idee ist dieselbe: Eine deklarierte Konfiguration besitzt den gewünschten Zustand.

Hier ist ein kleines Deployment-Manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

Wenn Sie das Image in der Datei ändern und kubectl apply -f deployment.yaml ausführen, wird das Deployment aktualisiert. Wenn die Datei in Git ist, kann die Änderung überprüft werden. Wenn der Rollout fehlschlägt, können Sie den Commit rückgängig machen oder den Kubernetes-Rollout-Verlauf verwenden, je nachdem, wie Ihr Deployment-Prozess Revisionen aufzeichnet.

kubectl set funktioniert anders. Es ändert ein bestimmtes Feld an einem Live-Objekt. Das häufigste Beispiel ist das Ändern eines Container-Images:

kubectl set image deployment/web nginx=nginx:1.26

Dieser Befehl ist schnell und lesbar. Während eines Vorfalls zählt Geschwindigkeit. Wenn das aktuelle Image defekt ist und Sie ein Deployment auf ein bekannt gutes Image umstellen müssen, kann kubectl set image der schnellste Weg sein. Die Gefahr liegt darin, was als nächstes passiert. Wenn deployment.yaml immer noch nginx:1.25 sagt, kann das nächste kubectl apply -f deployment.yaml die Workload zurück auf 1.25 verschieben.

Diese Diskrepanz ist Konfigurationsdrift. Der Live-Cluster sagt eine Sache. Die Quelldatei sagt eine andere. Drift ist nicht immer katastrophal, aber es macht das Debuggen schwieriger, weil die Leute dem Repo nicht mehr vertrauen. Jemand fragt: "Was läuft in Produktion?" und die ehrliche Antwort wird: "Lass mich im Cluster nachsehen."

kubectl set hat mehrere nützliche Unterbefehle:

kubectl set image deployment/web nginx=nginx:1.26
kubectl set env deployment/web FEATURE_FLAG=true
kubectl set resources deployment/web -c=nginx --requests=cpu=200m,memory=256Mi --limits=cpu=500m,memory=512Mi

Diese sind praktisch für Entwicklungscluster, Demos, kurzlebige Tests und Notfall-Produktionsänderungen mit einem nachfolgenden Commit. Sie sind kein Ersatz für gepflegte Manifeste.

kubectl edit ruft das Live-Objekt ab, öffnet es in Ihrem Editor und sendet das geänderte Objekt zurück an den API-Server, wenn Sie speichern:

kubectl edit deployment/web

Es ist praktisch, weil Sie das vollständige Live-YAML sehen können, einschließlich Felder, die von Controllern hinzugefügt wurden. Es ist auch riskant, weil Live-Objekte viele Felder enthalten, die Sie nicht manuell verwalten sollten, wie status, generierte Metadaten, Ressourcenversionen und Managed Fields. Kubernetes wird einige ungültige Bearbeitungen ignorieren oder ablehnen, aber nicht jede schlechte Bearbeitung ist syntaktisch ungültig.

Eine häufige sichere Verwendung von kubectl edit ist ein schnelles Nicht-Produktionsexperiment: Replicas erhöhen, eine Annotation ändern oder einen Probe-Wert testen. Eine häufige unsichere Verwendung ist das wöchentliche manuelle Bearbeiten von Produktions-Deployments, ohne die Manifeste zu aktualisieren. Das erzeugt einen Cluster, den niemand zuversichtlich neu aufbauen kann.

Die praktische Regel ist diese: Wenn die Änderung das nächste Deployment überleben soll, setzen Sie sie in das Manifest und verwenden Sie apply. Wenn Sie nur das Live-Objekt anpassen müssen, verwenden Sie set oder edit und machen Sie die Änderung dann entweder rückgängig oder portieren Sie sie zurück nach Git.

Es gibt einige Fälle, in denen imperative Befehle nicht nur akzeptabel, sondern hilfreich sind. Beim Debuggen könnten Sie vorübergehend eine Umgebungsvariable hinzufügen, die die Log-Ausführlichkeit erhöht:

kubectl set env deployment/api LOG_LEVEL=debug

Nachdem Sie Logs gesammelt haben, entfernen Sie sie:

kubectl set env deployment/api LOG_LEVEL-

Wenn die Debug-Einstellung dauerhaft werden soll, committen Sie sie stattdessen in das Manifest. Verlassen Sie sich nicht auf Ihr Gedächtnis.

Ein weiterer Fall ist der Notfall-Rollback. Wenn Ihre Deployment-Pipeline hängt und Kunden betroffen sind, kann das direkte Setzen des Images angemessen sein:

kubectl set image deployment/api api=registry.example.com/api:2026-05-23-good
kubectl rollout status deployment/api

Der Folge-Schritt sollte sofort erfolgen: Öffnen Sie einen Pull-Request oder Commit, der das deklarierte Manifest mit dem Notfallzustand in Einklang bringt, oder führen Sie den normalen Rollback-Prozess durch, sobald die Pipeline wieder gesund ist. Der Live-Fix verschafft Zeit; er sollte nicht zur neuen undokumentierten Deployment-Methode werden.

kubectl apply hat auch Fallstricke. Wenn Sie mehrere Tools mischen, die dieselben Felder verwalten, können Konflikte oder überraschende Überschreibungen auftreten. Zum Beispiel können ein GitOps-Controller, Helm und ein Mensch, der kubectl apply gegen dasselbe Deployment ausführt, alle glauben, einen Teil des Objekts zu besitzen. Wählen Sie klare Besitzverhältnisse. Wenn Helm die Ressource verwaltet, aktualisieren Sie die Helm-Werte und führen Sie den Helm-Release-Prozess aus. Wenn Argo CD oder Flux sie verwaltet, ändern Sie Git und lassen Sie den Controller abgleichen.

Seien Sie bei Secrets und Config besonders vorsichtig. kubectl set env kann schnelle Änderungen in ein Deployment einbringen, aber es kann Werte im Shell-Verlauf oder in Audit-Logs offenlegen. Für sensible Werte aktualisieren Sie das Secret über Ihren normalen Secret-Management-Prozess. Fügen Sie Produktionsanmeldeinformationen nicht in einen Ad-hoc-Befehl ein, es sei denn, Ihr Team hat diesen Workflow explizit akzeptiert.

Bevor Sie ein Live-Objekt ändern, inspizieren Sie es:

kubectl get deployment web -o yaml
kubectl diff -f deployment.yaml

kubectl diff wird zu wenig genutzt. Es zeigt, was apply ändern würde, bevor Sie die Änderung vornehmen. In der Produktion kann diese Vorschau Fehler abfangen, wie das versehentliche Entfernen eines Label-Selektors, das Weglassen eines Ressourcenlimits oder das Anwenden des Manifests der falschen Umgebung.

Für Server-seitiges Apply sieht der Befehl so aus:

kubectl apply --server-side -f deployment.yaml

Server-seitiges Apply kann nützlich sein, wenn mehrere Akteure verschiedene Felder verwalten, aber es beseitigt nicht die Notwendigkeit von Besitzdisziplin. Wenn zwei Manager versuchen, dasselbe Feld zu besitzen, kann Kubernetes einen Konflikt melden. Das ist ein Feature; es sagt Ihnen, dass der Workflow mehrdeutig ist.

Hier ist eine einfache Entscheidungshilfe, die ich in echten Clustern verwende. Neue Anwendungsversion? Ändern Sie das Manifest und verwenden Sie apply durch die Pipeline. Replicas für einen Lasttest im Staging erhöhen? kubectl scale oder kubectl set ist in Ordnung, wenn Sie es rückgängig machen. Hotfix für ein defektes Image in Produktion? kubectl set image kann akzeptabel sein, aber erstellen Sie sofort die Source-of-Truth-Änderung. CPU-Anfragen dauerhaft anpassen? Aktualisieren Sie das Manifest. Erkunden, welche Felder auf einer Ressource existieren? Verwenden Sie kubectl get -o yaml, bevor Sie zu edit greifen.

Wenn Teams das richtig machen, wird Kubernetes einfacher zu durchschauen. Das Repo erzählt die Geschichte. Der Cluster stimmt die meiste Zeit mit dem Repo überein. Temporäre Live-Änderungen werden als temporär gekennzeichnet und bereinigt. Vorfälle sind immer noch stressig, aber die Konfiguration wird nicht zu einem zweiten Rätsel.

Der Befehl selbst ist nicht der Punkt. Der Punkt ist, ob Sie den Cluster-Zustand morgen aus vertrauenswürdigen Dateien neu aufbauen können. kubectl apply unterstützt diese Gewohnheit. kubectl set und kubectl edit sind scharfe Werkzeuge für Momente, in denen direktes Handeln nützlich ist. Halten Sie diese Grenze klar und Sie werden viel vermeidbare Kubernetes-Verwirrung vermeiden.

Es gibt einen weiteren Befehl, den die Leute in denselben mentalen Eimer stecken: kubectl patch. Er ist auch imperativ, aber besser für präzise skriptgesteuerte Änderungen als edit. Zum Beispiel können Sie eine Deployment-Annotation patchen, um einen Neustart auszulösen oder ein kleines Feld in der Automatisierung zu aktualisieren. Dieselbe Drift-Regel gilt. Wenn das gepatchte Feld den langfristigen gewünschten Zustand darstellt, aktualisieren Sie auch das Quellmanifest.

kubectl patch deployment web   -p '{"spec":{"template":{"metadata":{"annotations":{"restartedAt":"2026-05-24T10:00:00Z"}}}}}'

Für Neustarts bevorzugen Sie den zweckgebauten Befehl:

kubectl rollout restart deployment/web

Dieser Befehl ändert immer noch das Live-Objekt, aber seine Absicht ist klar: Starten Sie einen neuen Rollout aus der aktuellen Pod-Vorlage. Es ist kein Ersatz für die Änderung der Konfiguration in Git.

In GitOps-Umgebungen ist die Grenze noch strenger. Wenn Argo CD oder Flux ein Objekt besitzt, kann ein manuelles kubectl set image automatisch rückgängig gemacht werden, weil der Controller Drift sieht und zurück zu Git abgleicht. Das kann während eines Vorfalls überraschend sein. Bevor Sie eine manuelle Produktionsänderung vornehmen, wissen Sie, ob ein GitOps-Controller gegen Sie kämpfen wird. Manchmal ist die richtige Notfallmaßnahme, die Abgleichung für diese Anwendung zu pausieren, den Fix zu machen, dann die passende Git-Änderung zu committen und die Abgleichung fortzusetzen.

Sie sollten auch wissen, wie Sie einen Live-Unterschied erfassen, ohne generierte Felder blind zu übernehmen. kubectl get deployment web -o yaml enthält Status, Ressourcenversionen, Managed Fields und andere Daten, die nicht in ein sauberes Manifest gehören. Wenn Sie einen Hotfix zurückportieren müssen, bearbeiten Sie das Quellmanifest von Hand oder verwenden Sie ein Tool wie Kustomize oder Helm-Werte, führen Sie dann kubectl diff aus, um die beabsichtigte Änderung zu überprüfen. Ersetzen Sie Ihre Quelldatei nicht durch rohes Live-YAML, es sei denn, Sie bereinigen es sorgfältig.

Für Teams ist die gesündeste Richtlinie normalerweise kurz und explizit. Produktionsänderungen gehen durch Git. Notfall-Live-Änderungen sind erlaubt, wenn nötig, aber sie erfordern eine Folge-Quelländerung oder einen Rollback. Entwicklungscluster sind lockerer, aber alles, was über die Entwicklung hinaus befördert wird, muss deklariert sein. Diese Richtlinie ist einfacher zu befolgen als eine lange Liste verbotener Befehle.

Es gibt auch eine menschliche Seite. Während eines Ausfalls kann die Person mit Cluster-Zugriff den schnellstmöglichen Fix machen. Das ist in Ordnung, wenn das Team es als Notfall-Ausnahme behandelt. Es wird gefährlich, wenn diese Ausnahmen zum Normalbetrieb werden. Wenn die Produktion routinemäßig von Hand repariert wird, ist der Deployment-Prozess entweder zu langsam, zu fragil oder nicht vertrauenswürdig. Beheben Sie diesen Prozess, anstatt jedem mehr Live-Edit-Tricks beizubringen.

RBAC kann den Workflow verstärken. Viele Teams erlauben breiten kubectl-Zugriff in der Entwicklung, schränken aber Produktions-Schreibzugriffe auf CI/CD-Systeme, GitOps-Controller oder eine kleine Bereitschaftsgruppe ein. Das ist keine Bürokratie um ihrer selbst willen. Es reduziert die Anzahl der Pfade, die den gewünschten Zustand ändern können. Wenn sich etwas ändert, sind Audit-Logs und Git-Verlauf leichter nachvollziehbar.

Zum Lernen lohnt es sich dennoch, alle drei Befehle in einem Wegwerf-Namespace zu üben. Erstellen Sie ein Deployment mit apply, ändern Sie sein Image mit set, inspizieren Sie den Drift mit kubectl diff, aktualisieren Sie dann das Manifest und wenden Sie es erneut an. Den Drift einmal in einer sicheren Umgebung zu sehen, macht die Produktionsregel viel leichter zu merken.