Home/Infrastructure/Production Kubernetes Cluster Checklist: HA, Security, and Observability
InfrastructureKubernetesContainers

Production Kubernetes Cluster Checklist: HA, Security, and Observability

Production Kubernetes is a completely different problem from local Minikube. You need to account for high availability, security, monitoring, and cost optimization.

Production Kubernetes Cluster Checklist: HA, Security, and Observability
Contents
  1. Production K8s vs. Development Environments
  2. Managed vs. Self-Managed
  3. Node Group Design
  4. Pod Anti-Affinity (High Availability)
  5. PodDisruptionBudget
  6. Resource Settings (Required)
  7. Security Hardening
  8. Monitoring Stack
  9. When Services Drop During Node Drains or Upgrades
  10. References: Official Documentation

Production K8s vs. Development Environments

Running Kubernetes in production is a completely different problem from local Minikube. You need to consider high availability, security, monitoring, and cost optimization.

Managed vs. Self-Managed

ApproachProsConsRecommended for
EKS/GKE/AKSNo control plane managementCost, vendor lock-inMost organizations
kubeadmFull controlHigh operational overheadOn-premises
k3sLightweight, edge-friendlyLimited featuresIoT, small-scale

Node Group Design

YAML
nodeGroups:
  - name: system
    instanceType: m5.large
    desiredCapacity: 3
    minSize: 3
    maxSize: 5

  - name: app-general
    instanceType: c5.2xlarge
    desiredCapacity: 3
    minSize: 2
    maxSize: 20
 spot: true #

Pod Anti-Affinity (High Availability)

YAML
affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchLabels:
          app: my-app
      topologyKey: kubernetes.io/hostname
topologySpreadConstraints:
- maxSkew: 1
  topologyKey: topology.kubernetes.io/zone
  whenUnsatisfiable: DoNotSchedule

PodDisruptionBudget

YAML
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: my-app

Resource Settings (Required)

YAML
resources:
  requests:
    cpu: "250m"
    memory: "256Mi"
  limits:
    cpu: "500m"
    memory: "512Mi"

Always set requests and limits. Without them, noisy-neighbor issues can take down an entire node.

Security Hardening

YAML
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 2000
containers:
- name: app
  securityContext:
    allowPrivilegeEscalation: false
    readOnlyRootFilesystem: true
    capabilities:
      drop: ["ALL"]

Monitoring Stack

Bash
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install monitoring prometheus-community/kube-prometheus-stack \
  --namespace monitoring --create-namespace

Essential alerts: node CPU > 80%, memory > 85%, Pod restarts > 5/hour, PVC utilization > 80%

The core of production Kubernetes operations is automation. Build a self-healing environment with HPA, Cluster Autoscaler, and GitOps.

When Services Drop During Node Drains or Upgrades

Outages during planned work (node replacement, version upgrades) in production clusters are mostly caused by missing settings.

Causes

  • Single-replica Deployments: a gap until the replacement Pod is up
  • PDB minAvailable equals the replica count, so ALLOWED DISRUPTIONS is 0 and the drain waits forever
  • No readinessProbe, so traffic hits new Pods before they're ready
  • The app doesn't handle SIGTERM, so in-flight requests are cut

Reproduce and verify

Bash
# PDBs with zero allowed disruptions
kubectl get pdb -A
# simulate a drain without evicting
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data --dry-run=server
# single-replica workloads
kubectl get deploy -A -o jsonpath='{range .items[?(@.spec.replicas==1)]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}'
# missing readinessProbe
kubectl get deploy <name> -o jsonpath='{.spec.template.spec.containers[*].readinessProbe}'

Fix

  • Give user-facing workloads at least two replicas and a PDB like maxUnavailable: 1.
  • Set a readinessProbe and terminationGracePeriodSeconds, and if needed a short sleep in preStop so the load balancer has time to remove the endpoint.
  • Use kubectl version to check versions (the --short flag was removed in recent kubectl).

Prevention

  • Encode these checks as policy-engine rules (Kyverno, OPA Gatekeeper) so single-replica or probe-less manifests are warned or rejected at deploy time.

References: Official Documentation

The primary source for the behavior, configuration, and errors covered in this post is the official documentation below. Check there for version-specific options and exact behavior.

✦ ✦ ✦
Sources and verification

Sources and checks vary by article. Only articles with a recorded check date, scope and sources below were checked, and only within that scope. For other articles, verify against the current docs for your version before applying anything, and email us about errors. Editorial policy · email us

This article has no recorded human check (date and scope) yet.

Published ·
Topic-related official docs (auto-linked · not per-claim sources)Kubernetes documentation ↗Docker documentation ↗

Comments

Be the first to comment.