How to Use Labels and Annotations Effectively
Organize and manage Kubernetes resources with labels and annotations. Implement labeling strategies for selection, filtering, and metadata.
How to Use Labels and Annotations Effectively
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!
📘 Get All 100+ Recipes in One Book
Stop searching — get every production-ready pattern with detailed explanations, best practices, and copy-paste YAML.
Want More Kubernetes Recipes?
This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.