DEV Community

Deep Fix
Deep Fix

Posted on

Automating Kubernetes Pod Scaling Issues: Best Practices, Scripts & Real-World Solutions

Introduction

Kubernetes makes horizontal pod autoscaling (HPA) feel effortless, but real‑world clusters often hit scaling glitches that stall deployments and inflate costs. This guide walks you through diagnosing common scaling roadblocks and automating their resolution with scripts you can drop into your CI/CD pipeline.


Why Pods Fail to Scale

Symptom Typical Cause
HPA never fires Metrics Server missing or mis‑configured
Pods crash after scale‑up Resource limits too low
Scale‑down stalls Finalizers or dangling PVCs
Erratic scaling Custom metrics latency

Understanding the root cause is the first step toward automation.


Step‑by‑Step Troubleshooting

1️⃣ Verify the Metrics Server

# Check if the metrics API is reachable
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | jq .
Enter fullscreen mode Exit fullscreen mode

If you see a 403 or 404, reinstall the metrics server:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Enter fullscreen mode Exit fullscreen mode

2️⃣ Tune Resource Requests & Limits

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 2
  template:
    spec:
      containers:
      - name: app
        image: myrepo/web:latest
        resources:
          requests:
            cpu: "250m"
            memory: "256Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
Enter fullscreen mode Exit fullscreen mode

Adjust the numbers until the HPA can safely add more pods without OOM kills.

3️⃣ Validate HPA Configuration

kubectl describe hpa web-app-hpa
Enter fullscreen mode Exit fullscreen mode

Key fields to watch:

  • minReplicas / maxReplicas
  • targetCPUUtilizationPercentage
  • metrics (custom vs. resource)

4️⃣ Automate Health Checks & Remediation

Create a lightweight Bash script that runs as a CronJob and fixes the most common issues.

#!/usr/bin/env bash
set -euo pipefail

NAMESPACE="default"
HPA_NAME="web-app-hpa"

# 1️⃣ Ensure metrics server is alive
if ! kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | grep -q "items"; then
  echo "⚠️ Metrics server down – reinstalling..."
  kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
fi

# 2️⃣ Patch HPA if CPU target is too aggressive
CURRENT_CPU=$(kubectl get hpa $HPA_NAME -n $NAMESPACE -o jsonpath='{.spec.metrics[0].resource.target.averageUtilization}')
if [[ $CURRENT_CPU -gt 80 ]]; then
  echo "⚙️ Adjusting CPU target from $CURRENT_CPU% to 70%"
  kubectl patch hpa $HPA_NAME -n $NAMESPACE --type='merge' -p '{"spec":{"metrics":[{"type":"Resource","resource":{"name":"cpu","target":{"type":"Utilization","averageUtilization":70}}}]}}'
fi

# 3️⃣ Clean up stuck pods preventing scale‑down
kubectl get pods -n $NAMESPACE --field-selector=status.phase=Running | while read -r pod _; do
  AGE=$(kubectl get pod $pod -n $NAMESPACE -o jsonpath='{.metadata.creationTimestamp}')
  if [[ $(date -d "$AGE" +%s) -lt $(date -d "5 minutes ago" +%s) ]]; then
    continue
  fi
  # Example heuristic: delete pods with a specific label that never become Ready
  if kubectl get pod $pod -n $NAMESPACE -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' | grep -q False; then
    echo "🗑️ Deleting stuck pod $pod"
    kubectl delete pod $pod -n $NAMESPACE
  fi
done
Enter fullscreen mode Exit fullscreen mode

Save this as auto‑scale‑fix.sh and schedule it:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: autoscale‑fixer
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: fixer
            image: bitnami/kubectl:latest
            command: ["/bin/bash", "-c", "$(cat /scripts/auto-scale-fix.sh)"]
            volumeMounts:
            - name: script
              mountPath: /scripts
          restartPolicy: OnFailure
          volumes:
          - name: script
            configMap:
              name: autoscale‑script-cm
Enter fullscreen mode Exit fullscreen mode

5️⃣ Log Aggregation for Post‑Mortem

kubectl logs -l app=web-app -c app --tail=200 | grep -i "oom" > /tmp/oom‑alerts.log
Enter fullscreen mode Exit fullscreen mode

Feed the extracted logs into your observability platform (Prometheus, Loki, etc.) to spot recurring patterns.


Full Automation Pack

We've bundled the script, CronJob manifest, and a ready‑to‑apply Helm chart in a public repo. Download the pre‑configured script here, or if you prefer the whole package, Get the complete patch tool. For a deeper dive, Access the full repository fix.


Conclusion

Automating the detection and remediation of scaling hiccups saves time, reduces cloud spend, and keeps your services responsive. Integrate the snippets above into your GitOps workflow, monitor the metrics, and let the CronJob handle the rest.

Happy scaling!

Top comments (0)