Kubernetes: Production Container Orchestration
Kubernetes (K8s) is the industry standard for container orchestration — an open-source platform that automates deployment, scaling, networking, and management of containerized applications across clusters of machines. Originating from Google’s internal Borg system (designed in 2003), Kubernetes was open-sourced in 2014 and is now maintained by the Cloud Native Computing Foundation (CNCF). Over 96% of organizations in CNCF’s 2024 survey use Kubernetes in production, making it the de facto standard for container orchestration.
Core Concepts
Pods
A Pod is the smallest deployable unit in Kubernetes — one or more containers that share storage, network, and a specification for how to run. Containers in the same Pod are always co-located and co-scheduled on the same node. They share an IP address, port space, and can communicate via localhost.
Pods are designed to be ephemeral — they can be terminated, rescheduled, or replaced at any time. You should never interact with Pods directly for production workloads; instead, use higher-level abstractions like Deployments.
apiVersion: v1
kind: Pod
metadata:
name: app-pod
labels:
app: excellentwiki
tier: frontend
spec:
containers:
- name: web
image: nginx:alpine
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256MiDeployments
A Deployment provides declarative updates for Pods and ReplicaSets. You describe the desired state (replicas, container image, resource limits), and the Kubernetes controller works to maintain that state. Deployments support rolling updates with zero downtime, automatic rollback on failure, and horizontal scaling.
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: registry.example.com/excellentwiki-api:1.2.3
ports:
- containerPort: 8000
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8000
initialDelaySeconds: 3
periodSeconds: 5Services
A Service provides a stable network endpoint for accessing Pods. Since Pods are assigned dynamic IP addresses, Services maintain a consistent DNS name and load-balance traffic across healthy Pod replicas.
Kubernetes supports several Service types:
- ClusterIP (default) — internal virtual IP, accessible only within the cluster
- NodePort — exposes the service on a static port on each node’s IP address
- LoadBalancer — provisions a cloud load balancer (AWS ALB, GCP GLB, Azure LB) that routes external traffic to the Service
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api
ports:
- port: 80
targetPort: 8000
protocol: TCP
type: LoadBalancerIngress
Ingress provides HTTP/HTTPS routing rules for external traffic. It acts as an API gateway, routing requests to different Services based on hostnames and paths. Ingress controllers (NGINX, Traefik, HAProxy, AWS ALB Ingress Controller) implement the Ingress specification.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: excellentwiki-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- excellentwiki.com
secretName: excellentwiki-tls
rules:
- host: excellentwiki.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80Storage in Kubernetes
Kubernetes separates storage provisioning from storage consumption through two abstractions:
PersistentVolume (PV) — cluster-admin provisioned storage (network attached, cloud disk, local). A PV has its own lifecycle independent of any Pod.
PersistentVolumeClaim (PVC) — a user request for storage. Pods use PVCs as volumes. When a PVC is created, Kubernetes binds it to an available PV or provisions one dynamically (via StorageClass).
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
storageClassName: ssdConfigMaps and Secrets
Configuration should be externalized from container images. ConfigMaps store non-sensitive configuration data (environment variables, config files). Secrets store sensitive data (API keys, passwords, certificates) with base64 encoding and optional encryption at rest.
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
data:
APP_ENV: production
LOG_LEVEL: info
DATABASE_URL: postgresql://postgres:password@db-service:5432/wiki
---
apiVersion: v1
kind: Secret
metadata:
name: api-secrets
type: Opaque
data:
API_KEY: <base64-encoded>
JWT_SECRET: <base64-encoded>Reference ConfigMaps and Secrets in Pod specifications via environment variables or volume mounts. Changes to ConfigMaps are automatically propagated to running Pods (Secrets require a Pod restart or reload mechanism).
Helm: Kubernetes Package Manager
Helm packages Kubernetes resources into reusable charts — versioned packages that can be installed, upgraded, and rolled back as a unit. A single Helm chart can deploy an entire application stack with configurable parameters.
# Add a chart repository
helm repo add bitnami https://charts.bitnami.com/bitnami
# Install PostgreSQL with custom configuration
helm install postgres bitnami/postgresql \
--set auth.database=excellentwiki \
--set auth.username=app \
--set primary.persistence.size=100Gi \
--namespace database \
--create-namespace
# Upgrade with new values
helm upgrade postgres bitnami/postgresql -f prod-values.yaml
# Rollback to previous version on failure
helm rollback postgres 1Helm charts use Go templating with values files for customization. Popular charts include NGINX Ingress Controller, cert-manager, Prometheus/Grafana, and Elasticsearch.
RBAC: Role-Based Access Control
Kubernetes RBAC controls who can access the cluster and what actions they can perform. RBAC uses four resource types:
- Role — set of permissions within a namespace (verbs on resources)
- ClusterRole — set of permissions across the entire cluster
- RoleBinding — binds a Role to users/groups/service accounts within a namespace
- ClusterRoleBinding — binds a ClusterRole cluster-wide
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: development
name: pod-manager
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "services"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]Service Mesh
For advanced traffic management, security, and observability, a service mesh adds a sidecar proxy (Envoy) to each Pod. Istio and Linkerd are the most popular service meshes:
- Traffic management — fine-grained routing rules (weighted canary deployments, header-based routing, mirroring traffic to staging)
- Security — mutual TLS (mTLS) between all services, service-to-service authorization policies
- Observability — automatic metrics, distributed tracing, and access logs for all service-to-service communication
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api-routing
spec:
hosts:
- api-service
http:
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: api-service
subset: v2
weight: 100
- route:
- destination:
host: api-service
subset: v1
weight: 90
- destination:
host: api-service
subset: v2
weight: 10Linkerd is the lighter-weight alternative (5 MB control plane, no Envoy required) with automatic mTLS, HTTP/2 and gRPC support, and minimal latency overhead (~2ms p99).
Production Best Practices
Resource requests and limits — always set CPU and memory requests (guaranteed scheduling) and limits (throttling prevention). A Pod without resource limits can starve other workloads. Use the Vertical Pod Autoscaler for automated resource recommendations.
Horizontal Pod Autoscaler (HPA) — automatically scales Pod replicas based on CPU, memory, or custom metrics. Combine with Cluster Autoscaler for node-level scaling.
kubectl autoscale deployment api-deployment --cpu-percent=70 --min=2 --max=20Health probes — liveness probes restart unhealthy containers; readiness probes stop traffic to containers not ready to serve; startup probes delay liveness checks for slow-starting applications. Always implement at least readiness probes.
Pod Disruption Budgets (PDB) — limits how many Pods can be voluntarily disrupted during node maintenance or cluster upgrades. PDBs ensure availability during cluster operations.
Namespaces — isolate environments, teams, or workloads within a single cluster. Set resource quotas on namespaces to prevent resource exhaustion. Use network policies for cross-namespace access control.
Monitoring — deploy Prometheus for metrics collection and Grafana for dashboards. Export Kubernetes events, node metrics, Pod metrics, and application metrics. Alert on Pod crashes, high error rates, and resource saturation.
FAQ
What is the difference between Kubernetes and Docker Swarm? Kubernetes offers richer orchestration features (auto-scaling, self-healing, service mesh, storage orchestration, batch execution), a larger ecosystem (Helm, Operators, CNI plugins), and broader cloud provider support. Docker Swarm is simpler to set up but lacks advanced features. Kubernetes is the standard for production; Swarm is appropriate for simple single-host deployments.
Do I need Kubernetes if I only have one service? Not necessarily. A single service on a single node runs fine with Docker Compose. Kubernetes’ value grows with service count, team size, and operational complexity. Consider Cloud Run or AWS App Runner for simple workloads — they provide Kubernetes-like scaling without cluster management.
How do I manage secrets securely in Kubernetes? Enable encryption at rest for etcd (the cluster data store), use external secret managers (HashiCorp Vault, AWS Secrets Manager CSI Driver, GCP Secret Manager), implement RBAC for Secret access, and use tools like Sealed Secrets or External Secrets Operator to manage secrets in Git.
What is a Kubernetes Operator? An Operator extends Kubernetes with custom application-specific logic. Operators automate complex operational tasks — backups, upgrades, scaling, failure recovery — for stateful applications. Examples: PostgreSQL Operator (Crunchy Data), Prometheus Operator, cert-manager.
How should I handle stateful applications in Kubernetes? Use StatefulSets for ordered Pod creation and stable network identities. Use PersistentVolumeClaims for durable storage. Deploy operators for production databases (Crunchy PostgreSQL, KubeDB, MongoDB Operator). For development and testing, Helm charts with PVCs are sufficient.
Docker Containers Guide — Cloud Architecture Patterns — Cloud-Native Development
Related Concepts and Further Reading
Understanding kubernetes requires familiarity with several interconnected ideas and principles that together form a complete picture. Exploring these related concepts deepens your knowledge and provides context that makes the core material more meaningful and applicable. Each concept builds on the others, creating a web of understanding that supports deeper learning and practical application. Taking time to explore how these elements connect reveals patterns that accelerate comprehension and retention of new information.
The relationship between kubernetes and adjacent fields is worth particular attention. Many of the most important insights emerge at the boundaries between disciplines, where ideas from different areas combine to create new approaches and solutions that neither field could produce alone. Exploring these connections pays dividends in both breadth and depth of understanding, revealing patterns and principles that might otherwise remain hidden from view. Cross-disciplinary knowledge is increasingly valued as problems become more complex and interconnected.
For those looking to go beyond introductory material, several excellent resources provide deeper treatment of specific aspects of kubernetes. Academic journals, industry publications, authoritative reference works, and online courses each offer different perspectives and levels of detail. The key is to match your reading to your current learning goals and build knowledge progressively, focusing on quality over quantity in your study materials. A well-chosen resource that matches your current level is worth more than dozens of resources that are too basic or too advanced.