Docker is phenomenal for packaging an application into an isolated container. However, what happens when you need to run 500 instances of that container across 20 different physical servers? What if server #4 catches fire? Who restarts the containers? Who handles the load balancing? Kubernetes (K8s) is the industry-standard orchestration system that manages the deployment, scaling, and self-healing of containerized applications.
Module 1: The Kubernetes Architecture
Kubernetes is a declarative system. You do not write scripts saying "run this container, then map this port". Instead, you write a YAML file describing the Desired State (e.g., "I want 3 instances of my Node.js app running at all times"). The K8s Control Plane constantly monitors the cluster, and if an instance crashes, it automatically creates a new one to match your desired state.
The K8s Vocabulary
- Pod: The smallest deployable unit. It contains one (or sometimes more) Docker containers. You never run containers directly; you run Pods.
- Node: A physical or virtual machine (e.g., an AWS EC2 instance) that runs your Pods.
- Cluster: A group of Nodes managed by a Control Plane.
- Deployment: A controller that manages a group of identical Pods and handles seamless rolling updates.
Module 2: Writing a Deployment
Let's deploy a Node.js backend. We define a Deployment.yaml.
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-api
labels:
app: backend
spec:
replicas: 3 # We want EXACTLY 3 pods running
selector:
matchLabels:
app: backend
template: # The blueprint for the Pod
metadata:
labels:
app: backend
spec:
containers:
- name: nodejs-app
image: my-docker-repo/backend-api:v1.0.0
ports:
- containerPort: 3000
resources:
limits:
memory: "512Mi"
cpu: "500m"Apply this to the cluster using kubectl apply -f deployment.yaml. Kubernetes will pull the image and distribute the 3 pods across your nodes.
Module 3: Exposing the App (Services)
Pods are mortal. They die, and K8s restarts them with entirely new IP addresses. You cannot rely on a Pod's IP. A Service provides a stable IP address and acts as an internal load balancer.
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: backend # This tells the Service to route traffic to any Pod with this label
ports:
- protocol: TCP
port: 80 # Port exposed inside the cluster
targetPort: 3000 # Port the Node.js app is listening on inside the PodModule 4: Ingress (Routing External Traffic)
A Service makes your app reachable inside the cluster. To expose it to the internet, you need an Ingress Controller (like Nginx). The Ingress acts as an API Gateway, routing traffic based on URL paths.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
spec:
rules:
- host: api.mycompany.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 80Module 5: ConfigMaps and Secrets
Never bake environment variables into your Docker image. K8s provides ConfigMaps for non-sensitive data and Secrets for passwords.
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
# Values must be Base64 encoded
db_password: c3VwZXJzZWNyZXQ=