What Are Important Deployment Annotations in Kubernetes?

intermediate|deploymentsdevopssrebackend developerCKACKAD
TL;DR

Deployment annotations store non-identifying metadata such as change causes, rollout triggers, and tool-specific configuration. The kubernetes.io/change-cause annotation is especially important for tracking why each revision was created.

Detailed Answer

Annotations in Kubernetes are key-value pairs attached to objects that store non-identifying metadata. Unlike labels, annotations are not used for selection — they carry information consumed by humans, tools, and controllers.

Key Deployment Annotations

kubernetes.io/change-cause

The most important Deployment annotation for operations. It records why a rollout happened:

# Set change-cause when applying
kubectl apply -f deployment.yaml
kubectl annotate deployment web kubernetes.io/change-cause="Upgraded nginx to 1.27 for CVE fix"

# Or use --record (deprecated but still common)
kubectl set image deployment/web nginx=nginx:1.27 --record

View the rollout history with change causes:

kubectl rollout history deployment web
# REVISION  CHANGE-CAUSE
# 1         Initial deployment
# 2         Upgraded nginx to 1.27 for CVE fix
# 3         Added resource limits per policy

CI/CD Metadata Annotations

Teams commonly use custom annotations to track deployment provenance:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
  annotations:
    deploy.example.com/git-sha: "a1b2c3d"
    deploy.example.com/pipeline-url: "https://ci.example.com/builds/1234"
    deploy.example.com/deployed-by: "jane@example.com"
    deploy.example.com/deployed-at: "2026-03-19T14:30:00Z"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
        prometheus.io/path: "/metrics"
    spec:
      containers:
        - name: api
          image: api-server:a1b2c3d
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: "250m"
              memory: "256Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"

Deployment-Level vs. Pod Template-Level Annotations

This distinction is critical:

| Location | Triggers Rollout | Persists Across Rollouts | |----------|-----------------|-------------------------| | metadata.annotations | No | Stays on the Deployment | | spec.template.metadata.annotations | Yes | Copied to ReplicaSet and Pods |

Changing a Pod template annotation triggers a new rollout because it changes the Pod spec hash. This behavior is sometimes used intentionally to force a restart:

# Force a rollout by adding a timestamp annotation to the Pod template
kubectl patch deployment web -p \
  '{"spec":{"template":{"metadata":{"annotations":{"restartedAt":"2026-03-19T14:30:00Z"}}}}}'

Common Tool-Specific Annotations

Prometheus Scraping

spec:
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9090"
        prometheus.io/path: "/metrics"

Istio Sidecar Configuration

spec:
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "true"
        sidecar.istio.io/proxyCPU: "100m"
        sidecar.istio.io/proxyMemory: "128Mi"

Linkerd Injection

spec:
  template:
    metadata:
      annotations:
        linkerd.io/inject: enabled

Best Practices for Annotations

  1. Use reverse-DNS prefixes for custom annotations: mycompany.com/annotation-name
  2. Always set change-cause during CI/CD deployments for rollback clarity
  3. Do not store secrets in annotations — they are visible in kubectl describe
  4. Keep values under 256KB — Kubernetes enforces a total annotation size limit per object
  5. Use annotations for tooling integration — Prometheus, Istio, ArgoCD, and Helm all rely on them

Inspecting Annotations

# View all annotations on a Deployment
kubectl get deployment web -o jsonpath='{.metadata.annotations}' | jq .

# View Pod template annotations
kubectl get deployment web \
  -o jsonpath='{.spec.template.metadata.annotations}' | jq .

# View annotations on the active ReplicaSet
kubectl get rs -l app=web -o jsonpath='{.items[0].metadata.annotations}' | jq .

Annotations vs. Labels Decision Guide

| Need | Use | |------|-----| | Select Pods for a Service | Labels | | Filter with kubectl | Labels | | Store git SHA or build URL | Annotations | | Configure Prometheus scraping | Annotations | | Group resources for billing | Labels | | Record change cause | Annotations |

Why Interviewers Ask This

Understanding annotations shows you can manage Deployment rollout history, integrate with CI/CD tools, and provide audit trails for production changes.

Common Follow-Up Questions

What is the difference between labels and annotations?
Labels are used for selection and grouping (selectors, services). Annotations store arbitrary non-identifying metadata that tools and humans can reference.
How does kubernetes.io/change-cause work?
When set on a Deployment template, it is recorded in the ReplicaSet's annotations. kubectl rollout history displays it alongside each revision number.
Can annotations trigger a rollout?
Only annotations on the Pod template (spec.template.metadata.annotations) trigger a rollout. Annotations on the Deployment itself do not.

Key Takeaways

  • kubernetes.io/change-cause provides human-readable context in rollout history.
  • Only Pod template annotations trigger new rollouts — Deployment-level annotations do not.
  • Annotations are commonly used for CI/CD metadata like git SHA, pipeline URL, and deployer identity.

Related Questions

You Might Also Like