πŸ“šBook Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) β€” free book giveaway!RSVP Booking.com Event
Configuration beginner ⏱ 15 minutes K8s 1.28+

How to Use Labels and Annotations Effectively

Organize and manage Kubernetes resources with labels and annotations. Implement labeling strategies for selection, filtering, and metadata.

By Luca Berton β€’ β€’ πŸ“– 5 min read

πŸ’‘ Quick Answer: Labels are for selection and querying (Services select pods by labels). Annotations store metadata for tools and humans (not queryable). Use consistent labeling: app.kubernetes.io/name, app.kubernetes.io/version, app.kubernetes.io/component. Query with kubectl get pods -l app=myapp.

Key command: kubectl label pod mypod env=production; query with -l env=production,tier=frontend.

Gotcha: Labels are limited to 63 chars; annotations can be largerβ€”use annotations for JSON configs, URLs, descriptions.

Labels identify and select resources, while annotations store non-identifying metadata. A consistent labeling strategy is essential for managing Kubernetes at scale.

Labels vs Annotations

# Labels: For identification and selection
# - Used by selectors (Services, Deployments, etc.)
# - Queryable via kubectl
# - Keep values short (< 63 chars)

# Annotations: For metadata and tooling
# - Not used for selection
# - Can store larger values
# - Used by tools, controllers, and humans
# Kubernetes recommended labels
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app.kubernetes.io/name: myapp
    app.kubernetes.io/instance: myapp-prod
    app.kubernetes.io/version: "1.2.3"
    app.kubernetes.io/component: frontend
    app.kubernetes.io/part-of: ecommerce
    app.kubernetes.io/managed-by: helm
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
      app.kubernetes.io/instance: myapp-prod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp
        app.kubernetes.io/instance: myapp-prod
        app.kubernetes.io/version: "1.2.3"
        app.kubernetes.io/component: frontend

Custom Label Strategy

# Organization labels
metadata:
  labels:
    # Application identification
    app: myapp
    component: api
    version: v1
    
    # Environment
    environment: production
    tier: backend
    
    # Ownership
    team: platform
    owner: alice@company.com
    cost-center: engineering
    
    # Lifecycle
    release: stable
    canary: "false"

Label Selectors

# Equality-based selectors
kubectl get pods -l app=myapp
kubectl get pods -l environment=production
kubectl get pods -l 'app=myapp,environment=production'

# Set-based selectors
kubectl get pods -l 'environment in (production, staging)'
kubectl get pods -l 'environment notin (development)'
kubectl get pods -l 'team'           # Has label
kubectl get pods -l '!canary'        # Doesn't have label

# Combined selectors
kubectl get pods -l 'app=myapp,environment in (production, staging),!canary'

Service Selector

# Service selects pods by labels
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
    component: api
  ports:
    - port: 80
      targetPort: 8080

Network Policy Selectors

# Network policy using labels
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-policy
spec:
  podSelector:
    matchLabels:
      app: myapp
      component: api
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: myapp
              component: frontend

Manage Labels

# Add label
kubectl label pod myapp-pod environment=production

# Update label (overwrite)
kubectl label pod myapp-pod environment=staging --overwrite

# Remove label
kubectl label pod myapp-pod environment-

# Label multiple resources
kubectl label pods -l app=myapp release=v2

# Label all pods in namespace
kubectl label pods --all reviewed=true

Common Annotations

# Useful annotations
metadata:
  annotations:
    # Documentation
    description: "Main API server for user management"
    docs: "https://wiki.company.com/myapp"
    
    # Ownership and contact
    owner: "platform-team@company.com"
    slack-channel: "#platform-support"
    pagerduty: "platform-oncall"
    
    # Deployment info
    kubernetes.io/change-cause: "Update to v1.2.3 for security fix"
    deployment.kubernetes.io/revision: "5"
    
    # Build info
    build.git/commit: "abc123def"
    build.git/branch: "main"
    build.ci/pipeline: "12345"
    build.ci/url: "https://ci.company.com/build/12345"
    
    # Prometheus scraping
    prometheus.io/scrape: "true"
    prometheus.io/port: "8080"
    prometheus.io/path: "/metrics"

Ingress Annotations

# Ingress controller annotations
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    # nginx ingress
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    
    # cert-manager
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    
    # external-dns
    external-dns.alpha.kubernetes.io/hostname: "myapp.example.com"

Manage Annotations

# Add annotation
kubectl annotate pod myapp-pod description="Main API pod"

# Update annotation
kubectl annotate pod myapp-pod description="Updated API pod" --overwrite

# Remove annotation
kubectl annotate pod myapp-pod description-

# View annotations
kubectl get pod myapp-pod -o jsonpath='{.metadata.annotations}'

Label Nodes

# Add node labels for scheduling
kubectl label node node1 disktype=ssd
kubectl label node node1 gpu=nvidia
kubectl label node node1 topology.kubernetes.io/zone=us-east-1a

# Use in nodeSelector
spec:
  nodeSelector:
    disktype: ssd
    gpu: nvidia

Namespace Labels

# Namespace with labels
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    environment: production
    team: platform
    # Pod Security Standards
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted

Query Resources by Labels

# List pods with specific labels
kubectl get pods -l app=myapp --show-labels

# Get all labels for resources
kubectl get pods --show-labels

# Count resources by label
kubectl get pods -l environment=production --no-headers | wc -l

# Get unique label values
kubectl get pods -o jsonpath='{.items[*].metadata.labels.environment}' | tr ' ' '\n' | sort -u

# Find resources without required label
kubectl get pods -l '!team'

Labeling Best Practices

1. Use consistent naming conventions
   - Prefix custom labels: company.com/label
   - Use lowercase, alphanumeric, -, _, .

2. Required labels for all resources:
   - app: Application name
   - environment: dev/staging/prod
   - team/owner: Ownership

3. Don't put sensitive data in labels/annotations
   - They're not encrypted
   - Visible in kubectl output

4. Keep label values short
   - Max 63 characters
   - Alphanumeric, -, _, .

5. Use annotations for:
   - Build/deployment metadata
   - Tool configuration
   - Documentation links

Validate Labels with Admission

# Kyverno policy requiring labels
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-team-label
      match:
        resources:
          kinds:
            - Pod
      validate:
        message: "All pods must have a 'team' label"
        pattern:
          metadata:
            labels:
              team: "?*"

Summary

Labels identify and select resources - use them consistently for Services, NetworkPolicies, and kubectl queries. Recommended labels include app.kubernetes.io/name, version, component, and environment. Annotations store metadata for tools and documentation like build info, prometheus scraping, and ingress configuration. Use kubectl label and kubectl annotate to manage them. Establish a labeling strategy early and enforce it with admission controllers for consistent resource organization at scale.


πŸ“˜ Go Further with Kubernetes Recipes

Love this recipe? There’s so much more! This is just one of 100+ hands-on recipes in our comprehensive Kubernetes Recipes book.

Inside the book, you’ll master:

  • βœ… Production-ready deployment strategies
  • βœ… Advanced networking and security patterns
  • βœ… Observability, monitoring, and troubleshooting
  • βœ… Real-world best practices from industry experts

β€œThe practical, recipe-based approach made complex Kubernetes concepts finally click for me.”

πŸ‘‰ Get Your Copy Now β€” Start building production-grade Kubernetes skills today!

#labels #annotations #organization #selectors #metadata
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens