Kubernetes: Container Orchestration
Modern applications are increasingly built as collections of containerized services. While containers solve the problem of packaging and running software consistently, they introduce a new challenge: how do you manage hundreds or thousands of containers across a fleet of machines? This is where Kubernetes comes in.
What Is Kubernetes?
Kubernetes (often abbreviated as K8s) is an open-source platform for automating the deployment, scaling, and management of containerized applications. Originally developed by Google and now maintained by the Cloud Native Computing Foundation (CNCF), it has become the de facto standard for container orchestration.
At its core, Kubernetes answers key operational questions:
- Where should a container run?
- What happens when a container crashes?
- How do you scale up during peak traffic?
- How do services discover and communicate with each other?
Core Architecture
A Kubernetes cluster consists of a control plane and a set of worker nodes.
Control Plane Components
- kube-apiserver — The front door to the cluster; all commands go through this REST API.
- etcd — A distributed key-value store holding the entire cluster state.
- kube-scheduler — Decides which node an unscheduled pod should run on.
- kube-controller-manager — Runs controllers that reconcile desired state with actual state.
Node Components
- kubelet — The agent running on each node that ensures containers are running as expected.
- kube-proxy — Manages network rules for pod communication.
- Container runtime — Software like containerd that actually runs the containers.
Key Objects and Concepts
Pods
The smallest deployable unit in Kubernetes is a Pod. A pod wraps one or more tightly coupled containers that share networking and storage.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
Deployments
You rarely create pods directly. Instead, you use a Deployment, which manages a set of identical pods and handles rolling updates and rollbacks.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
Applying this with kubectl apply -f deployment.yaml ensures three replicas are always running. If a pod dies, Kubernetes recreates it automatically.
Services
Pods are ephemeral—their IP addresses change. A Service provides a stable network endpoint and load-balances traffic across a set of pods.
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Common service types include:
| Type | Purpose |
|---|---|
ClusterIP |
Internal-only access within the cluster |
NodePort |
Exposes the service on each node's IP |
LoadBalancer |
Provisions an external load balancer (cloud) |
The Declarative Model
Kubernetes operates on a declarative philosophy. You describe the desired state in YAML manifests, and controllers continuously work to make the actual state match. This reconciliation loop is what makes Kubernetes self-healing.
Desired State (YAML) → API Server → Controllers → Actual State
▲ │
└──────────── continuous reconciliation ───┘
Scaling Applications
Scaling is straightforward. Manually:
kubectl scale deployment nginx-deployment --replicas=5
Or automatically with a Horizontal Pod Autoscaler based on metrics like CPU usage:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx-deployment
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Configuration and Secrets
Keep configuration out of your images using ConfigMaps and Secrets:
kubectl create configmap app-config --from-literal=LOG_LEVEL=debug
kubectl create secret generic db-creds --from-literal=password=s3cr3t
These can be injected into pods as environment variables or mounted files, keeping sensitive data separate from application code.
Best Practices
- Set resource requests and limits to help the scheduler and prevent noisy-neighbor problems.
- Use liveness and readiness probes so Kubernetes knows when to restart or route traffic to a pod.
- Adopt namespaces to logically isolate teams and environments.
- Store manifests in Git and apply them through CI/CD (GitOps).
- Never store secrets in plain YAML committed to source control.
Conclusion
Kubernetes abstracts away the complexity of running containers at scale, providing a resilient, declarative platform for modern applications. While the learning curve can be steep, mastering core concepts—p
Top comments (0)