# kubectl apply: Usage, Options & Common CI Errors

> kubectl apply declaratively creates or updates resources from manifests. Server-side apply, dry-run, and the validation and field-conflict errors in CI.

Source: https://latchkey.dev/learn/command-reference/kubectl-apply  
Updated: 2026-06-25

The declarative deploy command - apply a manifest, get the desired state.

kubectl apply is the workhorse of GitOps-style CI: it reconciles cluster state to the manifests you pass, creating what is missing and patching what changed. Understanding its merge behaviour prevents the surprising errors it throws.

## What it does

kubectl apply -f computes a three-way merge between the last-applied config, the live object, and your new manifest, then patches only the differences. With --server-side the API server owns the merge and tracks field managers, which is the modern default for CI. -k applies a kustomize directory; --prune deletes objects no longer in the manifest set.

## Common usage

```Terminal
kubectl apply -f manifests/                      # a directory of YAML
kubectl apply -k overlays/prod                   # a kustomize overlay
kubectl apply -f deploy.yaml --server-side
kubectl apply -f deploy.yaml --dry-run=server    # validate, no write
kubectl diff -f deploy.yaml                       # preview the change
```

## Common errors in CI

Two failures dominate pipelines. "error validating data: ValidationError(...): unknown field" means your manifest has a typo or targets an API version the cluster does not support - run kubectl apply --dry-run=server -f to validate against the live schema before committing. "Apply failed with N conflicts: conflict with \"<manager>\"" appears with server-side apply when another controller (or a prior client-side apply) owns a field; resolve it deliberately with --force-conflicts rather than blindly, since it transfers ownership.

## Options

| Flag | Effect |
| --- | --- |
| -f, --filename | Manifest file, directory, or URL |
| -k, --kustomize | Apply a kustomize directory |
| --server-side | Server-side apply with field managers |
| --dry-run=server | Validate against the API, no write |
| --prune | Delete objects no longer in the set |
| --force-conflicts | Take ownership on SSA conflicts |

## 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.

```Terminal
# 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
```

> Always set `--request-timeout` in CI. Without it an unreachable API server hangs until the job times out, which turns a thirty-second failure into a twenty-minute one.

## FAQ

### kubectl apply: Usage, Options & Common CI Errors?

kubectl apply is the workhorse of GitOps-style CI: it reconciles cluster state to the manifests you pass, creating what is missing and patching what changed. Understanding its merge behaviour prevents the surprising errors it throws.

### What it does?

kubectl apply -f computes a three-way merge between the last-applied config, the live object, and your new manifest, then patches only the differences. With --server-side the API server owns the merge and tracks field managers, which is the modern default for CI.

### Common errors in CI?

Two failures dominate pipelines. "error validating data: ValidationError(...): unknown field" means your manifest has a typo or targets an API version the cluster does not support - run kubectl apply --dry-run=server -f to validate against the live schema before committing.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
