kubectl create is an imperative command that creates new resources from file/CLI flags and fails if resource already exists (AlreadyExists error). One-time operation with no update capability. Use cases: (1) Quick testing/prototyping with fast resource creation. (2) One-off resources like Jobs, debug pods, temporary ConfigMaps. (3) Resource generation without applying: kubectl create deployment nginx --image=nginx:1.25 --dry-run=client -o yaml > deployment.yaml. Limitations: No updates (must use kubectl replace), no change tracking, not idempotent.
Kubectl Object Management FAQ & Answers
22 expert Kubectl Object Management answers researched from official documentation. Every answer cites authoritative sources you can verify.
General
22 questionskubectl apply is a declarative command that creates or updates resources from file (idempotent, safe to run multiple times). Tracks configuration changes via kubectl.kubernetes.io/last-applied-configuration annotation enabling three-way merge. Use cases: (1) GitOps workflows - manifests in Git, CI/CD applies on merge. (2) Production deployments with declarative config versioned in SCM. (3) Incremental updates - change one field, apply updates only that field. Best practice: always use apply in production for reproducibility and disaster recovery.
kubectl replace is an imperative command that replaces an existing object with a new one from YAML/JSON file. Requires the object to already exist (errors if not found). Key difference from apply: requires a COMPLETE spec including readonly properties like metadata.resourceVersion. Any unspecified fields use default values (not preserved). Use replace --force for fields that cannot be updated once initialized - this deletes and re-creates the resource. Use case: when you need to completely replace an object's spec, not merge.
kubectl patch updates specific fields of a live object without replacing the entire resource. Works with partial specs - only specify fields to change. Three patch types: strategic (default, Kubernetes-aware merging), merge (JSON merge per RFC 7386), json (JSON Patch per RFC 6902). Use cases: quick field updates without full manifests, scripted modifications, updating single fields in CI/CD. Example: kubectl patch deployment nginx -p '{"spec":{"replicas":3}}'. Does not create resources if they don't exist.
JSON merge patch (RFC 7386) REPLACES lists entirely - to update a list, you must specify the complete new list. Strategic merge patch is Kubernetes-specific and MERGES lists based on patchStrategy defined in source code. Example: containers field has patchStrategy:merge with patchMergeKey:name, so adding a container merges by name instead of replacing the entire list. Strategic merge is the default for kubectl patch. Critical limitation: strategic merge patch is NOT supported for Custom Resources - use JSON merge or JSON patch instead.
Server-side apply (--server-side flag, stable since Kubernetes 1.22) moves merge logic from client to API server with field ownership tracking. Benefits: (1) Field managers track which controller/user owns each field. (2) Faster - server-side diff without downloading full resource. (3) Handles large CRDs with 10,000+ fields without client memory issues. (4) Conflict detection - errors if field owned by different manager. Syntax: kubectl apply -f deployment.yaml --server-side --field-manager=my-ci-pipeline.
kubectl apply performs a three-way merge comparing: (1) Last applied configuration (from kubectl.kubernetes.io/last-applied-configuration annotation), (2) Current live state in etcd, (3) New desired state from manifest. This enables: detecting fields removed from manifest (present in last-applied but missing in new config), preserving fields managed by other controllers (HPA's replicas, Ingress status), calculating minimal patches. The annotation is updated after each successful apply.
This annotation stores the complete configuration from the last kubectl apply command as JSON. Written automatically by kubectl apply after each successful operation. Used for three-way merge to detect field deletions - if a field exists in last-applied but not in new config, it should be removed from live object. Can be manually set with kubectl apply set-last-applied -f file.yaml --create-annotation=true. Critical for declarative management but adds overhead to object size.
--dry-run=client: prints the object that would be sent without sending it. No API server validation - only client-side validation. Common use: generate YAML from commands (kubectl create deployment nginx --image=nginx --dry-run=client -o yaml). --dry-run=server: submits request to API server without persisting. Full validation including admission controllers, webhooks, and schema validation. Use when you need to validate against actual cluster policies. Introduced in v1.18, replacing deprecated --server-dry-run flag.
kubectl diff shows what changes kubectl apply would make without actually making them. Compares local file against live cluster state using server-side apply logic. Exit codes: 0 = no differences, 1 = differences found, >1 = error. Usage: kubectl diff -f deployment.yaml. Requires server-side apply (Kubernetes 1.18+). Customize diff tool with KUBECTL_EXTERNAL_DIFF environment variable (e.g., KUBECTL_EXTERNAL_DIFF='colordiff -N -u'). Essential for CI/CD pipelines to preview changes before applying.
Field management tracks which user or controller owns each field in an object, stored in metadata.managedFields. When using server-side apply, each applier declares a field-manager name. If you try to change a field owned by a different manager, the request is rejected with a conflict error. Two managers can share ownership if they set the same value. When a field value changes, ownership transfers to the manager making the change. Prevents accidental overwrites between kubectl, controllers, and operators.
When server-side apply returns a conflict, you have options: (1) Use --force-conflicts to override and take ownership (dangerous - use carefully). (2) Coordinate with other field managers to avoid conflicts. (3) Review managedFields to understand current ownership. (4) For controllers: always force conflicts on objects they own since they can't resolve interactively. The conflict response body includes machine-readable details about which fields conflict and which managers own them. Recommendation: controllers should only include fields they manage to minimize unnecessary conflicts.
Command comparison: kubectl create - Imperative, creates if not exists, fails on existing, requires full spec. kubectl apply - Declarative, creates or updates, idempotent, partial spec OK. kubectl replace - Imperative, fails if not exists, replaces entire object, requires full spec. kubectl patch - Imperative, fails if not exists, updates specific fields, partial spec OK. kubectl edit - Opens resource in editor for interactive changes. kubectl delete - Removes resources.
Imperative management: you tell Kubernetes WHAT TO DO (create this, delete that, scale to 3). Commands: kubectl create, run, expose, delete, scale. Good for quick tasks and learning. Declarative management: you describe the DESIRED STATE and Kubernetes figures out how to achieve it. Command: kubectl apply. Good for production, GitOps, reproducibility. Kubernetes compares desired state to actual state and reconciles. Best practice: use declarative (apply) for production, imperative for debugging and one-off tasks.
kubectl edit opens a resource in your default text editor (set by KUBE_EDITOR or EDITOR env var) for interactive modification. Saves changes on exit, applying them to the cluster. Performs a replace operation, not apply - doesn't update last-applied-configuration annotation. Use cases: quick debugging, one-time fixes, exploring resource structure. Avoid in production - changes aren't tracked in Git. Syntax: kubectl edit deployment/nginx or kubectl edit -f deployment.yaml.
managedFields is a metadata field that tracks field ownership for server-side apply. Each entry contains: manager (name of field manager), operation (Apply or Update), apiVersion, time, and fieldsV1 (set of fields owned). Automatically maintained by API server. View with kubectl get deployment nginx -o yaml. Enables conflict detection between different managers. Can be stripped with kubectl get deployment nginx -o yaml --show-managed-fields=false for cleaner output.
Use --dry-run=client -o yaml to generate manifests without creating resources. Examples: kubectl create deployment nginx --image=nginx:1.25 --dry-run=client -o yaml > deployment.yaml. kubectl create service clusterip nginx --tcp=80:80 --dry-run=client -o yaml. kubectl create configmap my-config --from-literal=key=value --dry-run=client -o yaml. kubectl run debug --image=busybox --restart=Never --dry-run=client -o yaml. Best practice for bootstrapping new manifests then customizing in Git.
kubectl apply set-last-applied sets the last-applied-configuration annotation to match a file's contents without modifying other parts of the object. Use case: fixing inconsistent state after using imperative commands (create, edit, replace) that don't update the annotation. Syntax: kubectl apply set-last-applied -f deployment.yaml --create-annotation=true. The --create-annotation flag is required if the annotation doesn't exist. After running, subsequent applies will work correctly with three-way merge.
kubectl apply --prune removes resources that are no longer in your manifest files but still exist in the cluster. Requires a selector (--selector or -l) to identify which resources to consider for pruning. Example: kubectl apply -f ./manifests/ --prune -l app=myapp. Only resources matching the selector and NOT in any applied file are deleted. Use --prune-whitelist to limit which resource types can be pruned. Dangerous if selector is too broad - can accidentally delete resources. Always dry-run first.
Use client-side apply (default) for: simpler setups, older Kubernetes clusters (<1.18), when you don't need field ownership tracking. Use server-side apply (--server-side) for: large CRDs (Istio, Crossplane), ConfigMaps >1MB, strict ownership requirements, production environments with multiple controllers/operators, avoiding last-applied-configuration annotation overhead. Server-side apply is recommended for modern production use. Client-side apply stores full config in annotation; server-side uses efficient managedFields.
JSON Patch (RFC 6902) uses an array of operations to modify resources. Syntax: kubectl patch deployment nginx --type=json -p='[{"op": "replace", "path": "/spec/replicas", "value": 3}]'. Operations: add, remove, replace, move, copy, test. Path uses JSON Pointer notation (e.g., /spec/containers/0/image). More precise than strategic/merge patches. Useful for: removing array elements by index, conditional updates with test operation, complex nested modifications. Supports all resource types including CRDs.
Best practices: (1) Always use kubectl apply -f for production deployments. (2) Store all manifests in Git - never use imperative commands in production. (3) Use kubectl diff in CI/CD before apply to preview changes. (4) Consider server-side apply for better conflict detection. (5) Use --prune cautiously with narrow selectors. (6) Set consistent field-manager names for traceability. (7) Use kustomize or Helm for environment-specific configs. (8) Never kubectl edit in production. (9) Version control before any manual fix, then apply the fix via Git.