kubectl apply -k: Apply a Kustomization
kubectl apply -k <dir> renders the kustomization in that directory and applies the result to the cluster.
apply -k is the one-step deploy: kubectl has Kustomize built in, so you skip the separate build. Mind that the embedded version may differ from a standalone kustomize.
What it does
kubectl apply -k <dir> invokes kubectl built-in Kustomize to build the directory, then applies the resulting manifests just like apply -f. kubectl diff -k previews the change without applying. The -k flag also works with delete and other verbs that accept it.
Common usage
kubectl apply -k overlays/prod
kubectl diff -k overlays/prod # preview
kubectl delete -k overlays/prod # tear downFlags
| Flag | What it does |
|---|---|
| -k, --kustomize <dir> | Build and apply the kustomization in dir |
| --dry-run=client|server | Validate without persisting |
| --server-side | Use server-side apply |
| --prune | Delete resources no longer in the build (use with care) |
| -n, --namespace | Override the namespace at apply time |
In CI
kubectl embeds its own Kustomize, which often trails the standalone release and may lack newer fields or the --enable-helm support. For helmCharts or the latest fields, render with a pinned standalone kustomize build and pipe to kubectl apply -f - instead of relying on apply -k. Pin the kubectl version on the runner.
Common errors in CI
"error: unknown field" or "json: unknown field" from apply -k usually means the embedded Kustomize is older than the kustomization expects; render with a newer standalone kustomize. "must specify --enable-helm" cannot be passed through apply -k in older kubectl, so render separately. "namespaces ... not found" means the target namespace is not created by the build.
Using this in CI
A runner has no kubeconfig, no cached context, and no interactive auth. Every kubectl invocation in CI needs the context supplied explicitly, and most confusing CI failures here are the command running against the wrong cluster or no cluster at all.
# never rely on the ambient context on a runner
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" get pods
# confirm what you are actually connected to before mutating anything
kubectl config current-context
kubectl cluster-info
# fail fast instead of hanging on an unreachable API server
kubectl --request-timeout=30s get nodes