How to Use Labels and Annotations Effectively
Organize and manage Kubernetes resources with labels and annotations. Implement labeling strategies for selection, filtering, and metadata.
π‘ 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 withkubectl 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 humansRecommended Labels
# 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: frontendCustom 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: 8080Network 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: frontendManage 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=trueCommon 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: nvidiaNamespace 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: restrictedQuery 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 linksValidate 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!

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
