Kubernetes Guide 2026 — Deploy, Scale, and Manage Containers in Production

Sanjeev SharmaSanjeev Sharma
5 min read

Advertisement

Introduction

Why This Matters

Kubernetes (K8s) is the industry standard for running containerized workloads at scale. In 2026, every major cloud provider — AWS (EKS), Google Cloud (GKE), Azure (AKS) — offers managed Kubernetes. Once you have more than a handful of containers, you need K8s for rolling updates, health checks, and auto-scaling. This guide covers the production-ready patterns developers use every day.

Core Architecture

ComponentRole
API ServerEntry point for all kubectl commands
SchedulerAssigns pods to nodes
etcdDistributed store for cluster state
Controller ManagerReconciles desired vs actual state
kubeletAgent that runs pods on each node
kube-proxyHandles network routing

Deploying a Node.js Application

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
  namespace: production
  labels:
    app: api-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-server
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: api-server
    spec:
      containers:
        - name: api
          image: ghcr.io/myorg/api-server:v1.2.3
          ports:
            - containerPort: 3000
          env:
            - name: NODE_ENV
              value: production
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: database-url
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 15
            periodSeconds: 20
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: api-server

Services and Ingress

Expose your deployment internally with a Service, then route external traffic through Ingress:

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: api-server
  namespace: production
spec:
  selector:
    app: api-server
  ports:
    - port: 80
      targetPort: 3000
  type: ClusterIP
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  namespace: production
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rate-limit: '100'
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - api.myapp.com
      secretName: api-tls
  rules:
    - host: api.myapp.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-server
                port:
                  number: 80

ConfigMaps and Secrets

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: production
data:
  LOG_LEVEL: info
  MAX_CONNECTIONS: '100'
---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
  namespace: production
type: Opaque
stringData:
  database-url: postgresql://user:pass@db:5432/prod
  jwt-secret: your-secret-here

Reference them from your pod spec:

envFrom:
  - configMapRef:
      name: app-config
  - secretRef:
      name: app-secrets

Horizontal Pod Autoscaler

Scale pods automatically based on CPU or memory:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-server-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  minReplicas: 2
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300

Essential kubectl Commands

# Apply manifests
kubectl apply -f k8s/ -n production
 
# Check status
kubectl get pods -n production
kubectl describe pod api-server-xxxxx -n production
 
# Logs and debugging
kubectl logs -f deployment/api-server -n production
kubectl exec -it api-server-xxxxx -- sh
 
# Rolling update and rollback
kubectl set image deployment/api-server api=ghcr.io/myorg/api:v1.3.0 -n production
kubectl rollout status deployment/api-server -n production
kubectl rollout undo deployment/api-server -n production
 
# Port forwarding for local debugging
kubectl port-forward svc/api-server 3000:80 -n production

Common Mistakes

  • No resource requests/limits — pods without limits starve other workloads and cause OOM kills on nodes
  • Using latest image tag — makes rollbacks impossible; always tag images with a git SHA or semver
  • No liveness/readiness probes — Kubernetes will not know your app is unhealthy and keeps routing traffic to crashed pods
  • Deploying to the default namespace — always use dedicated namespaces per environment (production, staging)
  • No PodDisruptionBudget — node upgrades can take all replicas offline simultaneously without one

Best Practices

  • Set terminationGracePeriodSeconds to let in-flight requests complete before pod shutdown
  • Use PodDisruptionBudget to guarantee at least N replicas stay up during maintenance
  • Store secrets externally (AWS Secrets Manager, HashiCorp Vault) and sync with External Secrets Operator
  • Use topologySpreadConstraints to spread pods across multiple nodes for real HA
  • Tag all resources with app, version, and environment labels for observability filtering

Key Takeaways

  • Kubernetes continuously reconciles desired state (your YAML) with actual cluster state — crashed pods restart automatically
  • Deployments use rolling updates by default; set maxUnavailable: 0 to guarantee zero-downtime deploys
  • Services provide stable internal DNS and load balancing; Ingress routes external HTTP/HTTPS traffic to Services
  • HorizontalPodAutoscaler scales replica count based on CPU, memory, or custom Prometheus metrics
  • Always set resource requests (affects scheduling) and limits (caps consumption) on every container
  • Use readiness probes to prevent traffic from reaching a pod until it is fully started and healthy
  • Namespaces provide logical isolation between environments and teams within the same cluster
  • Managed Kubernetes on EKS, GKE, or AKS removes control-plane operational burden; you only manage worker nodes

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro

Related reading