Kubernetes Pods, Deployments, and Services â Core Concepts with YAML Manifests and Rolling Updates
In this tutorial, you'll learn about Kubernetes Pods, Deployments, and Services. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Kubernetes is a container Orchestration platform that automates deployment, scaling, and management of containerized applications using declarative configurations and a powerful controller loop.
What You'll Learn
Why It Matters
Running containers on a single host with Docker works for development but breaks in production â containers crash, hosts fail, traffic spikes, and updates require zero downtime. Kubernetes solves these problems by giving you a self-healing, scalable platform where you describe the desired state and the system continuously works to match it.
Real-World Use
DodaTech runs Durga Antivirus Pro's backend services on a Kubernetes cluster with multiple Deployments (API servers, workers, scheduled jobs), Services for internal and external traffic routing, and ConfigMaps for environment-specific configuration â all managed through Git-versioned YAML manifests.
flowchart TD
subgraph User
A[Browser]
end
subgraph "Kubernetes Cluster"
B[Ingress / Service]
C[Deployment: API]
D[Deployment: Worker]
E[Deployment: CronJob]
F[StatefulSet: Postgres]
G[ConfigMap]
H[Secret]
end
A --> B
B --> C
C --> F
C --> G
C --> H
D --> F
D --> G
E --> F
style C fill:#326CE5,color:#fff
style D fill:#326CE5,color:#fff
style E fill:#326CE5,color:#fff
Prerequisites: Basic Docker and Containerization knowledge. A running Kubernetes cluster (minikube, kind, or Docker Desktop) for practice.
Pods â The Smallest Unit
A Pod is the smallest deployable unit in Kubernetes â one or more containers that share a network namespace, storage volumes, and lifecycle.
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-pod
labels:
app: web
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 3
periodSeconds: 5
Expected behavior: Kubernetes schedules this Pod on a healthy node. The kubelet pulls the nginx image, starts the container, and begins the readiness probe checks. The Pod is ready to serve traffic only after the probe succeeds.
# Create the Pod
kubectl apply -f pod.yaml
# Expected output:
# pod/web-pod created
# Check Pod status
kubectl get pods -w
# Expected output:
# NAME READY STATUS RESTARTS AGE
# web-pod 0/1 Pending 0 5s
# web-pod 0/1 ContainerCreating 0 10s
# web-pod 1/1 Running 0 15s
Expected output: The Pod progresses from Pending (scheduling) to ContainerCreating (image pull) to Running (ready). The -w flag watches for changes in real time.
Deployments â Declarative Updates
A Deployment manages a ReplicaSet that maintains the desired number of Pod replicas. It handles rolling updates, rollbacks, and self-healing.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 3
selector:
matchLabels:
app: api
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: myapp/api:1.0.0
ports:
- containerPort: 8080
env:
- name: DB_HOST
value: postgres-service
- name: DB_PORT
value: "5432"
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
Expected behavior: The Deployment creates 3 Pods matching the label selector app: api. If a Pod crashes, the Deployment replaces it immediately. Each Pod has health probes â liveness checks if the app is alive, readiness checks if it can serve traffic.
# Deploy the application
kubectl apply -f deployment.yaml
# Expected output:
# deployment.apps/api-deployment created
# Watch the rollout
kubectl rollout status deployment/api-deployment
# Expected output:
# Waiting for deployment "api-deployment" rollout to finish: 0 of 3 updated replicas...
# Waiting for deployment "api-deployment" rollout to finish: 1 of 3 updated replicas...
# deployment "api-deployment" successfully rolled out
# Perform a rolling update
kubectl set image deployment/api-deployment api=myapp/api:1.1.0
# Expected output:
# deployment.apps/api-deployment image updated
# Roll back if something goes wrong
kubectl rollout undo deployment/api-deployment
# Expected output:
# deployment.apps/api-deployment rolled back
Expected behavior: The rolling update replaces Pods one at a time (maxUnavailable: 1). If the new Pod fails its readiness probe, the update pauses. Rolling back reverts to the previous ReplicaSet.
Services â Stable Networking
Pods are ephemeral â they get new IP addresses when they restart. A Service provides a stable IP and DNS name that load-balances traffic across the Pods matching its selector.
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP # Default: internal-only
# LoadBalancer service for external access
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
type: LoadBalancer # Cloud providers provision an external LB
Expected behavior: ClusterIP services are accessible only within the cluster at api-service:80. LoadBalancer services expose the app externally through a cloud load balancer. Both distribute traffic across healthy Pods automatically.
# Expose the Deployment as a Service
kubectl expose deployment api-deployment \
--name=api-service \
--port=80 \
--target-port=8080
# Expected output:
# service/api-service exposed
# Get Service details
kubectl get svc api-service
# Expected output:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# api-service ClusterIP 10.96.123.45 <none> 80/TCP 10s
# Test internal access
kubectl run test-pod --image=busybox -it --rm -- \
wget -qO- http://api-service
# Expected output:
# <!DOCTYPE html>... (application response)
ConfigMaps and Secrets
Configuration and sensitive data should not be hardcoded in manifests. ConfigMaps store non-sensitive configuration, while Secrets store sensitive data.
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
NODE_ENV: production
LOG_LEVEL: info
API_URL: https://api.example.com
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData:
DB_USER: admin
DB_PASSWORD: supersecret # Base64-encoded in practice
# deployment-with-config.yaml
spec:
containers:
- name: api
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-credentials
Expected behavior: Environment variables from ConfigMaps and Secrets are injected into the container at runtime. Secrets are stored base64-encoded and should be encrypted at rest using Kubernetes encryption providers.
Horizontal Pod Autoscaling
Kubernetes can automatically adjust the number of Pod replicas based on CPU, memory, or custom metrics.
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-autoscaler
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-deployment
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Expected behavior: When CPU utilization across all Pods exceeds 70%, the HPA increases replicas up to 20. When utilization drops, it scales down to a minimum of 3.
Common Errors
Not setting resource requests and limits: Without resource requests, the scheduler places too many Pods on a single node, causing resource starvation. Without limits, a single Pod can consume all node memory.
Missing readiness probes: Without readiness probes, the Service routes traffic to Pods before the application is ready to handle requests, causing 502 errors during deployments and scaling events.
Using
latestimage tag:imagePullPolicydefaults toAlwaysforlatesttags, causing unnecessary pulls and making rollbacks impossible because the previous version is unknown.Overlooking Pod anti-affinity: Multiple replicas scheduled on the same node create a single point of failure. That node goes down and all replicas go with it.
Forgetting to set
terminationGracePeriodSeconds: When Kubernetes terminates a Pod, it sends SIGTERM then waits. If your app needs more than 30 seconds to drain connections, set this explicitly.
Practice Questions
What is the difference between a Pod and a Deployment? Answer: A Pod is a single instance of one or more containers. A Deployment manages a ReplicaSet that ensures the desired number of Pods are always running, and supports rolling updates and rollbacks.
How does a Service select which Pods to route traffic to? Answer: The Service uses label selectors. Any Pod with labels matching the Service's
spec.selectorreceives traffic. This is how Kubernetes achieves loose coupling between networking and workloads.What is the difference between liveness and readiness probes? Answer: Liveness probes determine if the app is alive â if they fail, the kubelet restarts the container. Readiness probes determine if the app can serve traffic â if they fail, the Service stops sending traffic to that Pod.
How does a rolling update ensure zero downtime? Answer: The
maxUnavailableandmaxSurgeparameters control how many old Pods are terminated and new Pods are created simultaneously. At mostmaxUnavailablePods are down at any time, ensuring enough replicas remain to serve traffic.
Challenge
Deploy a two-tier application: create a Deployment for a Node.js API with 3 replicas, resource requests/limits, liveness and readiness probes, and a rolling update Strategy. Expose it internally with a ClusterIP Service. Add a ConfigMap for environment configuration and a Secret for database credentials. Configure an HPA to scale between 3 and 10 replicas at 70% CPU. Perform a rolling update from v1 to v2, then roll back.
Mini Project
Write a complete set of Kubernetes manifests for a web application: a Deployment for the frontend with nginx, a Deployment for the API with health probes and rolling update Strategy, a Service for each, a ConfigMap with application configuration, a Secret for database credentials, and an Ingress to route external traffic. Deploy to a local cluster with minikube or kind, perform a rolling update, verify zero-downtime behavior by monitoring requests during the update, and practice rolling back a failed release.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro