Kubernetes: Pods, Services, Deployments - Complete Guide
Understanding Pods, Services, and Deployments is fundamental to mastering Kubernetes. These core resources form the foundation of application deployment and management in Kubernetes clusters. This comprehensive guide covers concepts, practical examples, and production best practices.
Table of Contents
- Introduction
- Prerequisites
- Pods
- Services
- Deployments
- ReplicaSets
- Labels and Selectors
- Rolling Updates and Rollbacks
- Production Best Practices
- Troubleshooting
- Conclusion
Introduction
Kubernetes orchestrates containerized applications using several key resources:
- Pods: Smallest deployable units, encapsulating one or more containers
- Services: Stable network endpoints for accessing Pods
- Deployments: Declarative updates for Pods and ReplicaSets
Resource Hierarchy
Deployment
└── ReplicaSet
└── Pod(s)
└── Container(s)
Prerequisites
- Kubernetes cluster (kubeadm, minikube, or cloud provider)
- kubectl installed and configured
- Basic understanding of containers and Docker
- Familiarity with YAML syntax
Verify setup:
kubectl version --client
kubectl cluster-info
kubectl get nodes
Pods
Pods are the atomic unit of deployment in Kubernetes, representing one or more tightly coupled containers that share resources.
Pod Characteristics
- Ephemeral and disposable
- Share network namespace (single IP)
- Share storage volumes
- Scheduled together on same node
- Managed by higher-level controllers
Creating a Simple Pod
# simple-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
environment: dev
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
# Create pod
kubectl apply -f simple-pod.yaml
# Check pod status
kubectl get pods
# Describe pod
kubectl describe pod nginx-pod
# Delete pod
kubectl delete pod nginx-pod
Multi-Container Pod
# multi-container-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-app
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
volumeMounts:
- name: shared-data
mountPath: /app/data
- name: sidecar
image: log-collector:latest
volumeMounts:
- name: shared-data
mountPath: /logs
volumes:
- name: shared-data
emptyDir: {}
Pod with Resource Limits
# pod-resources.yaml
apiVersion: v1
kind: Pod
metadata:
name: resource-pod
spec:
containers:
- name: app
image: nginx:alpine
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
Pod with Environment Variables
# pod-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: env-pod
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DATABASE_HOST
value: "postgres.default.svc.cluster.local"
- name: DATABASE_PORT
value: "5432"
- name: API_KEY
valueFrom:
secretKeyRef:
name: api-credentials
key: api-key
Pod Lifecycle
# Check pod phases
kubectl get pods -w
# Pod phases:
# Pending - Waiting for scheduling
# Running - Pod scheduled, containers running
# Succeeded - All containers terminated successfully
# Failed - At least one container failed
# Unknown - Pod state cannot be determined
Services
Services provide stable networking for accessing Pods, offering load balancing and service discovery.
Service Types
- ClusterIP: Internal cluster access only (default)
- NodePort: Exposes on each node's IP at a static port
- LoadBalancer: Cloud load balancer (requires cloud provider)
- ExternalName: Maps to external DNS name
ClusterIP Service
# service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: ClusterIP
selector:
app: backend
tier: api
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
# Create service
kubectl apply -f service-clusterip.yaml
# Access from within cluster
kubectl run curl --image=curlimages/curl -it --rm -- sh
# curl http://backend-service
NodePort Service
# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # Optional: 30000-32767
protocol: TCP
# Create service
kubectl apply -f service-nodeport.yaml
# Access from outside cluster
curl http://<NODE_IP>:30080
LoadBalancer Service
# service-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: LoadBalancer
selector:
app: frontend
ports:
- port: 80
targetPort: 3000
protocol: TCP
# Create service
kubectl apply -f service-loadbalancer.yaml
# Get external IP (may take time)
kubectl get service frontend-service
# Access via external IP
curl http://<EXTERNAL_IP>
Service with Session Affinity
# service-session.yaml
apiVersion: v1
kind: Service
metadata:
name: sticky-service
spec:
type: ClusterIP
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
selector:
app: web
ports:
- port: 80
targetPort: 8080
Headless Service
# service-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: database-service
spec:
clusterIP: None # Headless service
selector:
app: database
ports:
- port: 5432
targetPort: 5432
Deployments
Deployments provide declarative updates for Pods and ReplicaSets, enabling scaling, rolling updates, and rollbacks.
Basic Deployment
# deployment-basic.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
# Create deployment
kubectl apply -f deployment-basic.yaml
# Check deployment
kubectl get deployments
kubectl get pods
# Scale deployment
kubectl scale deployment nginx-deployment --replicas=5
# Delete deployment
kubectl delete deployment nginx-deployment
Production-Ready Deployment
# deployment-production.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web
environment: production
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
version: v1.0.0
spec:
containers:
- name: app
image: myapp:1.0.0
ports:
- containerPort: 8080
name: http
env:
- name: ENVIRONMENT
value: "production"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
Deployment with ConfigMap and Secret
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_url: "postgres://db:5432"
log_level: "info"
---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
db_password: cGFzc3dvcmQxMjM= # base64 encoded
---
# deployment-with-config.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- configMapRef:
name: app-config
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: db_password
ReplicaSets
ReplicaSets ensure a specified number of Pod replicas are running. Typically managed by Deployments.
ReplicaSet Example
# replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:alpine
# Create ReplicaSet
kubectl apply -f replicaset.yaml
# Check ReplicaSet
kubectl get replicasets
kubectl get pods
# Scale ReplicaSet
kubectl scale replicaset frontend-replicaset --replicas=5
Labels and Selectors
Labels organize and select Kubernetes objects. Selectors query objects by labels.
Using Labels
# pod-with-labels.yaml
apiVersion: v1
kind: Pod
metadata:
name: labeled-pod
labels:
app: web
environment: production
tier: frontend
version: v1.2.3
spec:
containers:
- name: nginx
image: nginx:alpine
Label Selectors
# Equality-based
kubectl get pods -l app=web
kubectl get pods -l environment=production
# Set-based
kubectl get pods -l 'environment in (production, staging)'
kubectl get pods -l 'tier notin (database)'
# Multiple conditions
kubectl get pods -l app=web,environment=production
# Show labels
kubectl get pods --show-labels
Adding/Removing Labels
# Add label
kubectl label pods labeled-pod new-label=value
# Update label
kubectl label pods labeled-pod environment=staging --overwrite
# Remove label
kubectl label pods labeled-pod environment-
Rolling Updates and Rollbacks
Performing Rolling Update
# Update deployment image
kubectl set image deployment/nginx-deployment nginx=nginx:1.26-alpine
# Or update via edit
kubectl edit deployment nginx-deployment
# Watch rollout status
kubectl rollout status deployment/nginx-deployment
# Check rollout history
kubectl rollout history deployment/nginx-deployment
Update Strategy
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # Max pods above desired count
maxUnavailable: 25% # Max unavailable pods during update
Rollback Deployment
# Rollback to previous version
kubectl rollout undo deployment/nginx-deployment
# Rollback to specific revision
kubectl rollout history deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment --to-revision=2
# Pause rollout
kubectl rollout pause deployment/nginx-deployment
# Resume rollout
kubectl rollout resume deployment/nginx-deployment
Production Best Practices
Resource Requests and Limits
spec:
containers:
- name: app
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
Health Checks
spec:
containers:
- name: app
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
Pod Disruption Budgets
# pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: web
Anti-Affinity for High Availability
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
Security Context
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
Troubleshooting
Pod Issues
# Get pod details
kubectl describe pod <pod-name>
# View logs
kubectl logs <pod-name>
kubectl logs <pod-name> --previous # Previous container
# Execute in pod
kubectl exec -it <pod-name> -- sh
# Check events
kubectl get events --sort-by='.lastTimestamp'
Service Issues
# Check service endpoints
kubectl get endpoints <service-name>
# Test DNS resolution
kubectl run test --image=busybox:1.28 --rm -it -- nslookup <service-name>
# Check service connectivity
kubectl run curl --image=curlimages/curl --rm -it -- curl http://<service-name>
Deployment Issues
# Check deployment status
kubectl get deployment <deployment-name>
kubectl describe deployment <deployment-name>
# Check ReplicaSet
kubectl get rs
kubectl describe rs <replicaset-name>
# Check rollout status
kubectl rollout status deployment/<deployment-name>
Common Problems
# ImagePullBackOff
kubectl describe pod <pod-name> # Check image name and credentials
# CrashLoopBackOff
kubectl logs <pod-name> # Check application logs
# Pending pods
kubectl describe pod <pod-name> # Check node resources and scheduling
# Service not accessible
kubectl get endpoints <service-name> # Verify pods are selected
Conclusion
Pods, Services, and Deployments form the core of Kubernetes application management. Understanding these resources is essential for deploying scalable, resilient applications.
Key Takeaways
- Pods: Smallest deployable unit, ephemeral
- Services: Stable network endpoints, load balancing
- Deployments: Declarative updates, scaling, rollbacks
- Labels: Organize and select resources
- Health Checks: Ensure application reliability
- Resource Limits: Prevent resource exhaustion
Quick Reference
# Pods
kubectl get pods
kubectl describe pod <name>
kubectl logs <name>
kubectl exec -it <name> -- sh
kubectl delete pod <name>
# Services
kubectl get services
kubectl describe service <name>
kubectl get endpoints <name>
# Deployments
kubectl get deployments
kubectl describe deployment <name>
kubectl scale deployment <name> --replicas=5
kubectl set image deployment/<name> container=image:tag
kubectl rollout status deployment/<name>
kubectl rollout undo deployment/<name>
# Labels
kubectl get pods --show-labels
kubectl get pods -l app=web
kubectl label pods <name> key=value
Next Steps
- Practice: Deploy various applications
- Monitoring: Set up Prometheus and Grafana
- Logging: Implement centralized logging
- Security: Apply RBAC and pod security policies
- Networking: Configure Ingress controllers
- Storage: Implement persistent volumes
- CI/CD: Automate deployments
Master these fundamentals to build robust Kubernetes applications!


