Intro
Kubernetes Kustomization troubleshooting demands a structured, evidence-driven approach. When a Kustomization fails to apply or behaves unexpectedly, the difference between a quick fix and prolonged downtime often comes down to how systematically you observe, diagnose, and verify. This guide provides a practical field manual for developers, DevOps consultants, and technical startup teams who need to resolve Kustomization issues with confidence.
We will connect real-world error patterns to specific kubectl commands, log analysis techniques, and safe recovery procedures. Every recommendation is version-scoped and reversible where possible. The goal is operational safety: observe before changing, limit the blast radius, use placeholders instead of secrets, verify the result, and document recovery paths before an incident forces your hand.
Before diving into specific failures, establish your environment inventory. Confirm your Kubernetes version, the Kustomize binary or kubectl integration, and the exact component under inspection. For instance, if you are using kubectl v1.27 with Kustomize v5.0.1, verify with:
kubectl version --short
kubectl kustomize --version
If kubectl kustomize is unavailable, use the standalone kustomize binary. Inconsistent versions between your local tooling and the cluster can introduce subtle bugs. Once your baseline is clear, you can move from observation to targeted intervention.
Version and Environment Inventory
Start any Kustomization troubleshooting session by capturing the current state and timestamps. Never assume you know the configuration; inspect it directly. The first command should always be a read-only observation:
kubectl get kustomizations -A
This lists all Kustomization resources across namespaces, showing their status, age, and any conditions. If you use Flux or Argo CD, the output will include additional columns like READY and STATUS. For example:
NAMESPACE NAME READY STATUS AGE
default my-app False Applied revision: main@sha1:abc123 5m
If the Kustomization is not ready, the next step is to inspect its details:
kubectl describe kustomization my-app -n default
This reveals events, such as reconciliation failures, missing references, or RBAC errors. Pay attention to the Events: section; it often contains the exact error message.
Next, verify that the referenced resources exist and are accessible. A Kustomization typically points to a source (e.g., a Git repository or a ConfigMap). Check the associated source:
kubectl get gitrepositories -n default
kubectl describe gitrepository my-app-source -n default
If the source is healthy, inspect the generated resources. You can preview the manifests locally without applying them to the cluster:
kubectl kustomize ./overlays/production
This renders the final YAML. Compare this output with your expectations. If the output is empty or contains errors, the issue likely lies in the Kustomization configuration itself (e.g., missing patches, incorrect resource paths).
Document everything: the current status, relevant timestamps, and exact error messages. Use a structured note format:
Observation Time: 2025-04-10T14:30:00Z
Cluster: staging-cluster
Namespace: default
Kustomization: my-app
Status: False
Reason: Applying manifests failed
Message: CustomResourceDefinition apiextensions.k8s.io/v1 is not available
This record becomes invaluable for post-incident review and pattern recognition.
Safe Configuration Path
Misconfigured Kustomization files are the most common source of errors. Rather than guessing, follow a safe configuration path that minimizes risk. Always test changes locally first, then apply to a non-production environment, and finally promote to production with a rollback plan.
Common Configuration Mistakes
- Incorrect resource paths: In your
kustomization.yaml, ensure theresourcesfield points to existing files or directories. For example:
# kustomization.yaml
resources:
- ./deployment.yaml
- ./service.yaml
If deployment.yaml is missing, Kustomize will fail with:
Error: accumulating resources: accumulating resources from 'deployment.yaml': evalsymlink failure on 'deployment.yaml' : lstat ./deployment.yaml: no such file or directory
- Patch target mismatch: Patches must match the resource they intend to modify. A common mistake is using a patch with a name or namespace that doesn't exist. For example, if you have a Deployment named
webappbut the patch targetsweb, the patch silently does nothing. Always verify withkubectl kustomizeand check that the patch appears in the output.
- Secret and ConfigMap generators: When using
secretGeneratororconfigMapGenerator, ensure thebehaviorfield is set correctly (create,replace, ormerge). If you change the content without specifyingbehavior: replace, Kustomize may create a new resource with a different hash and leave the old one orphaned.
Safe Testing Procedure
- Render locally: Always run
kubectl kustomizelocally to see the full output. This catches syntax errors and missing files without touching the cluster.
kubectl kustomize ./overlays/dev > rendered.yaml
- Apply to a dry-run: Use
kubectl apply --dry-run=clientor--dry-run=serverto see what changes would be made without persisting them.
kubectl apply -k ./overlays/dev --dry-run=client
- Test in a sandbox namespace: Create a separate namespace for testing and apply the rendered manifests there. This isolates the blast radius.
kubectl create namespace test-kustomize
kubectl apply -k ./overlays/dev -n test-kustomize
kubectl get all -n test-kustomize
- Verify with port-forward: Before exposing via a load balancer, check the service locally:
kubectl port-forward svc/my-app 8080:80 -n test-kustomize
curl localhost:8080/healthz
If the health check returns 200, the application is responding within the cluster.
Advanced: Using Overlays and Components
For multi-environment deployments, use overlays to avoid duplicating base configurations. A typical structure:
base/
kustomization.yaml
deployment.yaml
service.yaml
overlays/
dev/
kustomization.yaml
patch-replicas.yaml
prod/
kustomization.yaml
patch-resources.yaml
The overlay's kustomization.yaml references the base and applies patches:
# overlays/dev/kustomization.yaml
resources:
- ../../base
patches:
- target:
kind: Deployment
name: my-app
patch: |-
- op: replace
path: /spec/replicas
value: 2
This separation reduces the chance of cross-environment contamination and makes troubleshooting easier because each environment's changes are explicit.
Verification and Diagnostics
Once a Kustomization is applied, verification is not optional; it is the core of troubleshooting. Rely on kubectl commands that provide clear signals of success or failure.
Pod and Deployment Checks
Start with a broad view and narrow down:
kubectl get pods -o wide -n default
Look for pods in CrashLoopBackOff, Pending, or Error states. If any pod is not Running, describe it:
kubectl describe pod <pod-name> -n default
The Events section will show why the pod cannot start. Common reasons include:
FailedScheduling: insufficient resources, taints, or node selectors.ImagePullBackOff: incorrect image name or registry authentication.CrashLoopBackOff: the application exits immediately after starting.
For crash loops, retrieve logs from the previous instance:
kubectl logs <pod-name> --previous -n default
Always check the previous logs because the current container may not have produced output before crashing.
Deployments managed by Kustomize should reach a stable state. Verify with:
kubectl rollout status deployment/my-app -n default
Successful output:
deployment "my-app" successfully rolled out
If the rollout is stuck, investigate with:
kubectl rollout history deployment/my-app -n default
kubectl rollout undo deployment/my-app -n default
The undo command reverts to the previous revision, providing a quick recovery if the new version is faulty.
Kustomization Controller Logs (for Flux)
If you use Flux, the Kustomization controller logs are invaluable. Access them with:
kubectl logs -n flux-system deployment/kustomize-controller
Look for Webhook validation errors, Git authentication failures, or manifest apply conflicts. For example, an admission webhook might reject a manifest due to policy violations. The log will show:
{
"level": "error",
"msg": "Reconciliation failed",
"kustomization": "default/my-app",
"error": "failed to apply manifests: admission webhook \"validation.gatekeeper.sh\" denied the request: Container image 'my-app:latest' is not allowed"
}
This precise error tells you to change the image tag or update the policy.
Real-time Monitoring
For ongoing verification, use kubectl wait to block until a condition is met:
kubectl wait --for=condition=Ready pod -l app=my-app -n default --timeout=60s
This is useful in scripts and CI pipelines.
Failure Modes and Recovery
Kustomization failures fall into predictable categories. Understanding these modes accelerates resolution.
1. Configuration Syntax Errors
As discussed, malformed YAML or invalid Kustomize directives cause immediate failures. Recovery is straightforward: fix the configuration and reapply. Always render locally before pushing to a shared repository.
Example error:
Error: accumulating resources: accumulating resources from 'deployment.yaml': yaml: line 10: could not find expected ':'
Fix the indentation or missing colon and re-render.
2. Resource Conflicts and Ownership
Kustomize-generated resources can conflict with existing resources if names collide or if the resources are managed by another controller. Server-Side Apply (SSA) adds fields like kubectl.kubernetes.io/last-applied-configuration; if you mix client-side and server-side applies, conflicts arise.
To diagnose, inspect the resource's metadata:
kubectl get deployment my-app -n default -o yaml | grep -A5 'last-applied'
Recovery: use kubectl apply -k consistently, or set force: true in the Kustomization spec if you use Flux (but understand the implications).
3. Dependency Failures
A Kustomization may reference a ConfigMap, Secret, or CRD that does not exist yet. For example, if you deploy a custom resource before its CRD is installed, the apply fails with:
Error from server (NotFound): the server could not find the requested resource (post mycrds.example.com)
Check the order of resources. In the kustomization.yaml, list the CRD first, then the custom resources:
resources:
- crd.yaml
- my-resource.yaml
Alternatively, deploy the CRD in a separate Kustomization that runs first.
4. Patching Failures
Patches that fail to apply might not produce an error immediately. Use kubectl kustomize and search for the expected change. Suppose you want to add an environment variable to a Deployment:
patches:
- target:
kind: Deployment
name: my-app
patch: |-
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: DEBUG
value: "true"
If the rendering does not show DEBUG: "true" in the container's environment, the patch target may be wrong. Verify the path using kubectl explain or a JSON path expression.
5. Image Pull Failures
If pods fail with ImagePullBackOff, check the image name and tag in the rendered manifest. Kustomize allows image transformations:
images:
- name: my-app
newName: registry.example.com/my-app
newTag: v1.2.3
If the tag is missing or incorrect, the pull fails. Confirm the image exists with docker pull or crane manifest.
Recovery Patterns
- Rollback: For Deployment changes, use
kubectl rollout undo. - Selective deletion: If a resource is orphaned and causes conflicts, delete only that resource, then reapply the Kustomization. But be cautious: deleting a resource managed by Kustomize may trigger recreation if the controller is active. Consider pausing reconciliation (e.g.,
flux suspend kustomization my-app) before manual interventions. - Snapshot and restore: Before making changes, export the current state:
kubectl get kustomization my-app -n default -o yaml > my-app-backup.yaml
If a change goes wrong, you can restore the original definition, though you must also address the underlying issue.
Operations Checklist
A disciplined checklist ensures nothing is missed during troubleshooting. Here is a ready-to-use checklist with concrete examples.
Before You Start
- [ ] Confirm cluster access and context:
kubectl config current-contextshould returnstaging-cluster. If not, switch withkubectl config use-context staging-cluster. - [ ] Record the Kustomization version and status:
kubectl get kustomization my-app -n default -o yaml > pre-incident-state.yaml. - [ ] Identify the relevant namespace:
kubectl get namespaces | grep my-appto ensure the namespace exists.
Observation Phase
- [ ] Run
kubectl get kustomization -n defaultand note theREADYstatus. Expected:Truefor a healthy Kustomization. IfFalse, proceed. - [ ] Run
kubectl describe kustomization my-app -n defaultand capture the event messages. Example:Unable to clone repository: authentication required. - [ ] Run
kubectl get pods -n default -l app=my-app -o wideand check pod states. Example: three pods inCrashLoopBackOff. - [ ] Collect logs:
kubectl logs deployment/my-app -n default --tail=50andkubectl logs <pod-name> --previous -n default.
Diagnosis
- [ ] Correlate the observed errors with the Kustomization spec. Open
kubectl get kustomization my-app -n default -o yamland review thespecfields (path, sourceRef, patches). - [ ] Render the manifests:
kubectl kustomize ./overlays/production > /tmp/rendered.yaml. Inspect for unexpected changes or missing resources. - [ ] Compare with last known good state: diff the rendered YAML against a backup from a previous successful apply.
- [ ] If using Flux, check controller logs:
kubectl logs -n flux-system deployment/kustomize-controller | grep my-app.
Intervention (Minimal and Reversible)
- [ ] Choose one change at a time. For example, if the image tag is wrong, update only that in the
kustomization.yamland render again. - [ ] Apply with a dry-run first:
kubectl apply -k ./overlays/production --dry-run=client. - [ ] Apply for real:
kubectl apply -k ./overlays/productionand immediately runkubectl rollout status deployment/my-app -n default. - [ ] If the rollout stalls, consider rolling back:
kubectl rollout undo deployment/my-app -n default.
Verification and Documentation
- [ ] Verify all pods are healthy:
kubectl get pods -n default -l app=my-appshould showRunningandReady. - [ ] Test the service endpoint:
kubectl port-forward svc/my-app 8080:80 -n defaultandcurl localhost:8080/healthshould return200 OK. - [ ] Document the incident: root cause, actions taken, and verification steps. Store in a shared location like a wiki or incident management tool.
- [ ] Review if the prevention can be automated: add a CI step to run
kubectl kustomizeas a lint check.
By following this checklist, you reduce guesswork and ensure consistent troubleshooting across teams.
Conclusion
Kubernetes Kustomization troubleshooting is a skill that improves with practice and a systematic mindset. The techniques in this guide—environment inventory, safe configuration paths, thorough verification, understanding failure modes, and a disciplined operations checklist—provide a foundation for resolving issues efficiently.
Remember that every recommendation must be version-scoped, observable, and reversible where the technology permits. Copying commands without understanding prerequisites and expected output is not an operations procedure; it is a gamble. Instead, treat each troubleshooting session as an opportunity to refine your procedures.
As a next step, choose one low-risk verification from this guide—such as rendering a Kustomization locally or performing a dry-run apply—and practice it in a development environment. Record the current state, run the documented check, and compare the result with the expected signal. Then, introduce the habit into your team's workflow, perhaps as a pre-commit hook or CI validation.
A reliable technical workflow makes failure visible, protects sensitive values, limits changes to the intended resource, and defines recovery verification before an incident forces the decision. With these practices, you will turn Kustomization errors from blockers into manageable, routine fixes.