Kubernetes Pods, Deployments and Services
Complete guide to Kubernetes core objects including Pods, Deployments, Services, ReplicaSets, and how to manage containerized workloads.
# Kubernetes Pods, Deployments and Services
Introduction
Kubernetes core objects—Pods, Deployments, and Services—form the foundation of container orchestration. Pods are the smallest deployable units, Deployments manage the lifecycle of pod replicas, and Services provide stable network access to pods. This tutorial covers these core objects with practical examples and production patterns.
Learning Objectives
By the end of this tutorial, you will be able to:
- Create and manage Kubernetes Pods
- Deploy applications using Deployments and ReplicaSets
- Expose applications using Services (ClusterIP, NodePort, LoadBalancer)
- Configure resource requests and limits
- Implement health probes (liveness, readiness, startup)
- Manage rollouts and rollbacks
- Use environment variables and config maps
Technical Background
Core Object Relationships
flowchart TD
Deployment[Deployment] --> ReplicaSet[ReplicaSet]
ReplicaSet --> Pod[Pod]
Pod --> Container[Container]
Service[Service] -->|Selects| Pod
subgraph Object Hierarchy
Deployment
ReplicaSet
Pod
Container
endCore Objects Overview
| Object | Purpose | Lifecycle | |--------|---------|-----------| | Pod | Smallest deployable unit (1+ containers) | Ephemeral | | ReplicaSet | Maintains stable set of pod replicas | Managed by Deployment | | Deployment | Declarative updates for pods and ReplicaSets | Long-lived | | Service | Stable network endpoint for pods | Long-lived |
Prerequisites
- Running Kubernetes cluster
- kubectl configured
- Understanding of YAML syntax
- Container images available in registry
Hardware and Software Requirements
| Component | Requirement | |-----------|-------------| | Kubernetes Cluster | v1.25+ | | kubectl | v1.25+ | | Container Registry | Docker Hub, ECR, ACR, or GCR |
Step-by-Step Implementation
Phase 1: Pods
#### Create a Pod
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-pod
labels:
app: web
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
env:
- name: NGINX_PORT
value: "80"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"# Create pod
kubectl apply -f pod.yaml
# View pods
kubectl get pods
# View pod details
kubectl describe pod web-pod
# View pod logs
kubectl logs web-pod
# Delete pod
kubectl delete pod web-pod#### Multi-Container Pod
# sidecar-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: sidecar-pod
spec:
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: shared-logs
mountPath: /var/log/app
- name: log-shipper
image: fluent/fluentd:latest
volumeMounts:
- name: shared-logs
mountPath: /var/log/app
volumes:
- name: shared-logs
emptyDir: {}Phase 2: Deployments
#### Create a Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"# Create deployment
kubectl apply -f deployment.yaml
# View deployments
kubectl get deployments
# View rollout status
kubectl rollout status deployment/web-deployment
# View rollout history
kubectl rollout history deployment/web-deployment
# Scale deployment
kubectl scale deployment web-deployment --replicas=5
# Update image
kubectl set image deployment/web-deployment nginx=nginx:1.26
# Rollback
kubectl rollout undo deployment/web-deployment#### Deployment Strategies
| Strategy | Description | Use Case | |----------|-------------|----------| | RollingUpdate | Replace pods gradually | Production (default) | | Recreate | Stop all, start all | Development, non-critical |
Phase 3: Services
#### ClusterIP Service (Internal)
# service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP#### NodePort Service (External via Node)
# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
type: NodePort#### LoadBalancer Service (External via Cloud LB)
# service-lb.yaml
apiVersion: v1
kind: Service
metadata:
name: web-loadbalancer
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer# Create service
kubectl apply -f service-clusterip.yaml
# View services
kubectl get services
# View service details
kubectl describe service web-service
# Delete service
kubectl delete service web-servicePhase 4: Health Probes
#### Liveness, Readiness, and Startup Probes
# probes.yaml
apiVersion: v1
kind: Pod
metadata:
name: probe-pod
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
startupProbe:
httpGet:
path: /startup
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 30Phase 5: Resource Management
#### Resource Requests and Limits
# resources.yaml
apiVersion: v1
kind: Pod
metadata:
name: resource-pod
spec:
containers:
- name: app
image: myapp:latest
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"#### Quality of Service Classes
| QoS Class | Criteria | Use Case | |-----------|----------|----------| | Guaranteed | requests == limits for all containers | Critical workloads | | Burstable | requests < limits for at least one container | General workloads | | BestEffort | No requests or limits | Non-critical workloads |
Phase 6: Environment Variables and Configuration
#### Using Environment Variables
# env-vars.yaml
apiVersion: v1
kind: Pod
metadata:
name: env-pod
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DB_HOST
value: "db-service"
- name: DB_PORT
value: "5432"
- name: DEBUG
value: "true"#### Using ConfigMap
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DB_HOST: "db-service"
DB_PORT: "5432"
LOG_LEVEL: "info"
---
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- configMapRef:
name: app-config#### Using Secret
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
DB_PASSWORD: cGFzc3dvcmQ= # base64 encoded "password"
API_KEY: YXBpLWtleS0xMjM0NQ== # base64 encoded "api-key-12345"
---
apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: DB_PASSWORDExpected Output
- Pods running with proper configuration
- Deployments managing replica sets
- Services providing network access
- Health probes monitoring application health
- Resource limits preventing exhaustion
- ConfigMaps and Secrets managing configuration
Verification Procedures
| Check | Command | Expected Result | |-------|---------|-----------------| | Pod running | `kubectl get pods` | Status: Running | | Deployment available | `kubectl get deployments` | Available: 3/3 | | Service endpoints | `kubectl get endpoints` | Endpoints listed | | Health probe passing | `kubectl describe pod` | Probes: Success | | Rollout complete | `kubectl rollout status` | Successfully rolled out |
Troubleshooting Scenarios
| Issue | Diagnosis | Resolution | |-------|-----------|------------| | Pod in Pending | Insufficient resources or scheduling issue | Add nodes; reduce resource requests | | Pod in CrashLoopBackOff | Application crashing | Check logs; fix application | | Service not reachable | Selector mismatch | Verify labels match | | ImagePullBackOff | Wrong image or registry auth | Check image name; configure pull secret | | Deployment stuck | Probe failing or resource limits | Fix probe; increase limits |
Best Practices
- **Use Deployments:** Don't create pods directly; use Deployments
- **Set resource requests and limits:** Prevent resource starvation
- **Use health probes:** Configure liveness, readiness, and startup probes
- **Use labels:** Organize resources with meaningful labels
- **Use namespaces:** Separate environments and teams
- **Use ConfigMaps and Secrets:** Don't hardcode configuration
- **Pin image versions:** Use specific image tags, not `latest`
- **Set pod disruption budgets:** Ensure availability during disruptions
Security Considerations
- **Run as non-root:** Configure security context
- **Read-only root filesystem:** Where possible
- **Drop capabilities:** Remove unnecessary Linux capabilities
- **Secrets:** Use Kubernetes Secrets for sensitive data
- **Network policies:** Control pod-to-pod communication
- **Image scanning:** Scan container images for vulnerabilities
Conclusion
Pods, Deployments, and Services are the fundamental building blocks of Kubernetes. Understanding how to create, configure, and manage these objects is essential for running containerized workloads in production. Combined with health probes, resource management, and configuration patterns, you can build reliable and scalable applications on Kubernetes.
References
- Kubernetes Pods: https://kubernetes.io/docs/concepts/workloads/pods/
- Kubernetes Deployments: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
- Kubernetes Services: https://kubernetes.io/docs/concepts/services-networking/service/
- Kubernetes Configuration: https://kubernetes.io/docs/concepts/configuration/
- Kubernetes Security: https://kubernetes.io/docs/concepts/security/