CFN Cloud
Cloud Future New Life
en zh
2025-10-06 · 70 views

Declarative Object Configs

Manage resources with YAML and a reviewable change workflow.

Declarative config means you describe the desired state in files and manage everything through kubectl apply. It keeps changes reviewable, repeatable, and safer than ad-hoc imperative commands.

This quick start expands on the workflow with diff/preview, labels, patching, and GitOps-style practices.

Why it works

  • Changes are reviewable in git.
  • Rollbacks are simple by reapplying history.
  • Reapplying the same file is safe and idempotent.

Multi-object example

apiVersion: v1
kind: Namespace
metadata:
  name: demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  namespace: demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: nginx:1.25

Common flow

kubectl apply -f app.yaml
kubectl diff -f app.yaml
kubectl delete -f app.yaml

Order of operations

Start with namespaces, then RBAC, then workloads and services. This avoids dependency errors when applying multiple resources.

Labels and selectors

Use consistent labels so Services, Deployments, and monitors can discover Pods:

metadata:
  labels:
    app: api
    tier: backend

Server-side apply

Server-side apply makes field ownership explicit and helps avoid conflicts:

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

If you see conflicts, use field managers and avoid multiple systems writing the same fields.

Field ownership and managers

Server-side apply tracks which tool owns which fields. If you use multiple tools (for example, kubectl and a GitOps controller), define a clear owner for each field to avoid fights.

You can specify a field manager explicitly:

kubectl apply --server-side --field-manager=dev-cli -f app.yaml

Diff and preview

Use kubectl diff before applying to inspect changes. For CI, you can run:

kubectl diff -f app.yaml || true

Apply ordering by files

If you split manifests across files, consider a predictable naming scheme (e.g., 00-namespace.yaml, 10-rbac.yaml, 20-app.yaml) so CI and operators apply them in the correct order.

Patch vs apply

Use kubectl apply for full desired state. Use kubectl patch for small, targeted edits:

kubectl patch deploy api -p '{"spec":{"replicas":3}}'

In production, prefer commit + apply so the desired state stays in git.

Apply with prune

If you want to delete resources removed from your manifests, use prune with labels:

kubectl apply -f ./manifests -l app=api --prune

This keeps the cluster aligned with your repo.

Namespaces and resource scope

Remember that most resources are namespace-scoped. If you apply a manifest without a namespace set, it goes to the default namespace. Make namespaces explicit in your YAML or use -n when applying.

Dry-run

Validate changes without applying:

kubectl apply -f app.yaml --dry-run=server

Validation and linting

You can validate schemas with tools like kubeconform or kubectl apply --dry-run=server in CI to catch errors early. Even basic validation prevents broken manifests from reaching production.

Kustomize basics

Kustomize is built into kubectl and helps manage environments:

kubectl apply -k overlays/prod

Use it to manage image tags and environment-specific settings without copying YAML.

GitOps workflow

In GitOps, git is the source of truth and a controller applies changes automatically. This reduces manual drift and ensures every change is reviewed.

Even without a GitOps controller, you can follow the same idea by enforcing reviews and applying only from the main branch.

Example Kustomize overlay

A minimal structure:

# kustomization.yaml
resources:
  - ../../base
images:
  - name: nginx
    newTag: "1.26"

Apply it with:

kubectl apply -k overlays/prod

Immutable fields

Some fields cannot be updated (like selectors). If you need to change them, you must recreate the resource. Plan selectors carefully from day one.

Naming and directory structure

Organize manifests by app or environment. A common structure is:

  • base/ for shared resources.
  • overlays/dev, overlays/prod for environment overrides.

This keeps changes clear and reduces duplication.

Promotion workflow

Promote changes by merging to main, then applying from a CI pipeline or GitOps controller. This ensures the same change that was reviewed is what reaches production.

Drift and reconciliation

If manual changes happen, kubectl apply will bring resources back to the desired state. This is why declarative config pairs well with GitOps controllers.

Secrets and config separation

Keep secrets out of the main manifests. Use external secret managers or separate secret manifests with restricted access. This reduces the risk of accidental leaks during reviews. Never paste secrets into issue trackers or chat logs.

Practical tips

  • Use kubectl diff in CI to review changes.
  • Keep manifests small and focused.
  • Version your manifests with git tags to make rollback easy.
  • Use consistent indentation to avoid formatting noise.
  • Keep configs modular so teams can own their components.

Change review checklist

  • Are labels and selectors consistent?
  • Are resource requests set?
  • Are secrets handled separately?
  • Is a rollback path documented?

Policy and guardrails

Consider using admission controllers (like Gatekeeper or Kyverno) to enforce naming conventions, label requirements, and security constraints. This prevents invalid configs from reaching the cluster.

Ownership and handoff

If multiple teams share a repo, document ownership of each folder so reviews route to the right people. Clear ownership reduces merge conflicts and accidental overrides.

Common issues

  • Apply conflicts: multiple tools manage the same fields.
  • Missing namespace: resource applied before namespace exists.
  • Immutable fields: selectors or service types cannot be changed.

Diff hygiene

Normalize YAML formatting and key order to keep diffs clean. This makes reviews faster and reduces accidental noise.

State of the world vs desired state

Declarative workflows assume the manifests describe the source of truth. Avoid “fixing” production by hand; instead, change the manifest and reapply. This keeps your cluster reproducible.

Split configs by concern

Keep RBAC, config, and workloads in separate files. This makes reviews clearer and reduces the risk of accidental cross-cutting changes.

Auditing changes

Keep a changelog in git or use PR descriptions to capture the intent of each change. During incidents, this context saves time.

Consistency checks

Use pre-commit hooks or CI checks to enforce basic schema and formatting rules across the repo. Consistent validation reduces runtime surprises.

Debug workflow

kubectl get -f app.yaml
kubectl describe -f app.yaml
kubectl diff -f app.yaml

Apply from directory

You can apply a directory of manifests:

kubectl apply -f ./manifests

Combine with labels to target a subset in larger repos.

What this looks like in real life

Declarative config sounds abstract until you hit the first messy rollout.

The usual story goes like this: you change a value, run kubectl apply, and now half your Pods behave differently. At that point the most valuable thing isn’t another one-off command—it’s having a clean source of truth.

So the practical habit is boring but powerful: keep manifests in version control, apply from a directory, and treat diffs as part of the release.

When something feels off, start with evidence instead of guesses:

kubectl get nodes
kubectl get pods -A
kubectl get events -A --sort-by=.lastTimestamp
kubectl describe -f app.yaml
kubectl diff -f app.yaml

Two common ‘gotchas’ that show up in teams new to declarative workflows:

  • You edited the YAML, but applied it to the wrong namespace/context.
  • Labels/selectors drifted, so Services or controllers no longer match what you think they match.

If you only do one ‘production’ thing: write down the rollback path (what commit/tag do we go back to, and how do we apply it). It sounds obvious, but it’s the difference between a calm rollback and a panic rollback.

References