Introduction: The Shift from Monoliths to Orchestrated Containers
Running microservices on virtual machines works fine for three or four services. But when you hit twenty? You start drowning in SSH sessions, manual restarts, and configuration drift. I’ve seen teams spend more time fixing broken deployments than writing new features.
Kubernetes (K8s) solves this by treating your infrastructure like software. It doesn’t just "run" containers; it actively maintains the desired state of your application. If a node dies, K8s reschedules the pod. If traffic spikes, it scales up. This guide isn’t just about definitions—it’s about how to actually run this in production without losing your mind.

Core Concepts: How K8s Actually Manages State
Before diving into YAML, understand the hierarchy. Kubernetes is declarative. You don’t tell it "start this container." You tell it "I want 3 replicas of this image running," and the Control Plane figures out how to make that happen.
- ●
Pods: The smallest deployable unit. Rarely created directly.
- ●
Deployments: The manager. Handles updates, rollbacks, and scaling.
- ●
Services: The network abstraction. Gives Pods a stable IP/DNS.
- ●
Ingress: The front door. Routes external HTTP traffic to internal Services.
1. Deployments: Beyond Basic Replicas
A Deployment ensures that a specified number of Pod replicas are running at any given time. But in production, you need to care about how they update.
apiVersion: apps/v1
kind: Deployment
metadata:
name: orders-api
labels:
app: orders-api
tier: backend
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Only create 1 extra pod during update
maxUnavailable: 0 # Never drop below 3 running pods (Zero Downtime)
selector:
matchLabels:
app: orders-api
template:
metadata:
labels:
app: orders-api
spec:
containers:
- name: api
image: company/orders-api:v1.2.4 # NEVER use 'latest' in production
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
Pro Tip: Always set resource requests and limits. Without them, a single memory-leaking pod can starve the entire node, causing a cascade failure across unrelated services.
2. Service Discovery & Networking
Pods are ephemeral—they die and get new IPs constantly. Hardcoding IPs is a recipe for disaster. Kubernetes Services provide a stable virtual IP and DNS name.
| Service Type | Use Case | Risk Level |
|---|---|---|
| ClusterIP | Internal service-to-service communication | Low |
| NodePort | Debugging/Testing only | High (Security Risk) |
| LoadBalancer | Exposing to internet via Cloud Provider | Medium |
| ExternalName | Mapping to external DBs/APIs | Low |
3. Ingress: The Traffic Controller
Ingress is not a Service; it’s a set of rules. Think of it as a reverse proxy (like Nginx) managed by K8s. It handles SSL termination and path-based routing.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod" # Auto-manage SSL
spec:
rules:
- host: api.example.com
http:
paths:
- path: /orders
pathType: Prefix
backend:
service:
name: orders-api
port:
number: 80
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
4. Configuration & Secrets Management
Never bake configuration into your Docker image. Use ConfigMaps for non-sensitive data (URLs, feature flags) and Secrets for passwords/keys. For production, consider integrating with HashiCorp Vault or AWS Secrets Manager rather than relying solely on K8s native secrets, which are base64 encoded, not encrypted by default.
5. Health Probes: Preventing "Zombie" Pods
Without probes, K8s thinks your app is healthy even if it’s deadlocked. You need two types:
- ●
Liveness Probe: "Are you alive?" If no, restart the container.
- ●
Readiness Probe: "Can you take traffic?" If no, remove from Service endpoints.
- ●
Startup Probe: "Are you still booting?" Prevents liveness checks from killing slow-starting apps.
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
6. Autoscaling: Handling Traffic Spikes
Horizontal Pod Autoscaler (HPA) adjusts replica count based on metrics. While CPU/Memory are standard, for web APIs, I recommend scaling on Requests Per Second (RPS) or latency using Custom Metrics Adapter, as CPU usage often lags behind traffic spikes.
7. Observability: Seeing Inside the Black Box
You cannot manage what you cannot see. A production cluster needs the "Three Pillars":
- ●
Metrics: Prometheus + Grafana (CPU, Memory, Request Rate).
- ●
Logging: ELK Stack or Loki (Centralized log aggregation).
- ●
Tracing: Jaeger or OpenTelemetry (Tracking requests across microservices).
Common Production Mistakes to Avoid
- ●
❌ Using
latesttag: You lose reproducibility and rollback ability. - ●
❌ Ignoring Resource Limits: One bad app kills the node.
- ●
❌ Single Replica Deployments: No high availability.
- ●
❌ Storing State in Pods: Pods are ephemeral; use PVCs or external DBs.
- ●
❌ Skipping Readiness Probes: Users get 502 errors during deployments.
"Kubernetes gives you powerful tools, but it also gives you enough rope to hang yourself. Start simple, enforce resource limits, and monitor everything."
Frequently Asked Questions
Is Kubernetes overkill for a small startup?
How do I handle database migrations in K8s?
What is the difference between HPA and VPA?
Conclusion
Mastering Kubernetes orchestration is a journey. Start with solid Deployments and Services, implement strict health checks, and gradually add autoscaling and advanced networking. The goal isn’t just to run containers—it’s to build a system that heals itself.
Looking for more DevOps guides? Check out our articles on [Docker Best Practices] and [CI/CD Pipelines for .NET].
