DEV Community

qing
qing

Posted on

Build a Kubernetes Pod Autoscaler with Python

Build a Kubernetes Pod Autoscaler with Python

Imagine your Python app is suddenly hit with a traffic spike that doubles in seconds. Your server slows, users complain, and you’re manually scaling pods in a panic. That’s the nightmare every DevOps engineer fears. But what if you could build your own Kubernetes Pod Autoscaler in Python—custom, lightweight, and tailored to your app’s unique metrics? No more waiting for generic HPA rules. You get full control, real-time responsiveness, and the ability to scale based on your business logic, not just CPU.

Let’s build one today.

Why Build a Custom Autoscaler in Python?

Kubernetes comes with the built-in Horizontal Pod Autoscaler (HPA), which scales based on CPU or memory usage [3][4]. But HPA has limitations: it can’t scale based on custom metrics like queue length, request latency, or external API response times. For those cases, you need a Custom Pod Autoscaler.

Python is a perfect fit because:

  • It’s native to many cloud-native tooling stacks.
  • It has excellent Kubernetes client libraries (kubernetes).
  • You can write logic that’s easy to read, test, and extend.

In this guide, you’ll build a working Python autoscaler that monitors a custom metric (e.g., number of pending jobs in a queue) and scales your deployment accordingly.

Prerequisites

Before diving in, ensure you have:

  • A running Kubernetes cluster (Minikube, EKS, GKE, etc.)
  • kubectl installed and configured
  • Python 3.8+ with pip
  • The kubernetes Python client: pip install kubernetes

You also need the Metrics Server deployed so your autoscaler can read pod metrics if needed [4][5][7]. If you’re using Minikube:

minikube addons enable metrics-server
Enter fullscreen mode Exit fullscreen mode

Step 1: Define Your Scaling Logic

Let’s say your app processes jobs from a queue. You want to scale up when the queue has more than 50 pending jobs, and scale down when it’s under 10.

Here’s the core logic in Python:

import os
import time
from kubernetes import client, config
from kubernetes.client.rest import ApiException

# Load Kubernetes config (in-cluster or local)
config.load_incluster_config()  # or load_kube_config() for local

def get_queue_length():
    """
    Replace this with your actual logic to fetch queue length.
    Example: call an API, read from Redis, etc.
    """
    return 75  # Simulated value

def scale_deployment(deployment_name, namespace, replicas):
    apps_v1 = client.AppsV1Api()
    body = client.V1Deployment(
        metadata=client.V1ObjectMeta(name=deployment_name),
        spec=client.V1DeploymentSpec(replicas=replicas)
    )
    try:
        apps_v1.patch_namespaced_deployment(
            name=deployment_name,
            namespace=namespace,
            body=body
        )
        print(f"Scaled {deployment_name} to {replicas} replicas")
    except ApiException as e:
        print(f"Failed to scale deployment: {e}")

def main():
    deployment_name = "my-python-app"
    namespace = "default"
    min_replicas = 2
    max_replicas = 10

    while True:
        queue_length = get_queue_length()
        current_replicas = apps_v1.list_namespaced_deployment(namespace).items[0].spec.replicas

        if queue_length > 50 and current_replicas < max_replicas:
            scale_deployment(deployment_name, namespace, current_replicas + 1)
        elif queue_length < 10 and current_replicas > min_replicas:
            scale_deployment(deployment_name, namespace, current_replicas - 1)

        time.sleep(10)  # Check every 10 seconds

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

This script:

  • Fetches the current queue length
  • Checks current replica count
  • Scales up or down based on thresholds
  • Runs continuously in a loop

You can replace get_queue_length() with real logic—e.g., calling your job queue API or reading from Redis.

Step 2: Package and Deploy as a Kubernetes Pod

Now, turn this script into a container and deploy it as a pod in your cluster.

Create a requirements.txt

kubernetes
Enter fullscreen mode Exit fullscreen mode

Create a Dockerfile

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY autoscaler.py .

CMD ["python", "autoscaler.py"]
Enter fullscreen mode Exit fullscreen mode

Build and Push the Image

If you’re using Minikube:

eval $(minikube docker-env)
docker build -t my-autoscaler .
Enter fullscreen mode Exit fullscreen mode

For cloud clusters, push to Docker Hub or your registry:

docker build -t my-registry/my-autoscaler .
docker push my-registry/my-autoscaler
Enter fullscreen mode Exit fullscreen mode

Create a Deployment Manifest

apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-autoscaler
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python-autoscaler
  template:
    metadata:
      labels:
        app: python-autoscaler
    spec:
      containers:
      - name: autoscaler
        image: my-autoscaler  # or your registry path
        env:
        - name: DEPLOYMENT_NAME
          value: "my-python-app"
        - name: NAMESPACE
          value: "default"
      serviceAccountName: autoscaler-sa
Enter fullscreen mode Exit fullscreen mode

Create a Service Account with Permissions

Your autoscaler needs permission to patch deployments:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: autoscaler-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: autoscaler-role
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: autoscaler-binding
subjects:
- kind: ServiceAccount
  name: autoscaler-sa
  namespace: default
roleRef:
  kind: Role
  name: autoscaler-role
  apiGroup: rbac.authorization.k8s.io
Enter fullscreen mode Exit fullscreen mode

Apply everything:

kubectl apply -f serviceaccount.yaml
kubectl apply -f autoscaler-deployment.yaml
Enter fullscreen mode Exit fullscreen mode

Step 3: Test Your Autoscaler

Deploy your main Python app (my-python-app) with resource limits:

resources:
  requests:
    cpu: "100m"
  limits:
    cpu: "500m"
Enter fullscreen mode Exit fullscreen mode

Then simulate load. If you’re using a job queue, push 60 jobs. Your autoscaler should detect the spike and scale up. Monitor with:

kubectl get deployments
kubectl get pods -l app=my-python-app
Enter fullscreen mode Exit fullscreen mode

You’ll see replica counts change automatically.

What You Can Do Next

This is a minimal but fully functional autoscaler. Here’s how to level it up:

  • Add ** Prometheus metrics** instead of simulated queue length
  • Support multi-deployment scaling
  • Add alerting when scaling events occur
  • Use async/await for better performance
  • Integrate with external APIs (e.g., Slack, Datadog)

Ready to Ship This Today?

You just built a custom Kubernetes Pod Autoscaler in Python that scales based on your business logic—not just CPU. No YAML-only HPA, no black-box controllers. You control the thresholds, the metrics, and the logic.

Try it now:

  1. Copy the code above into autoscaler.py
  2. Build and deploy the pod
  3. Simulate load and watch your app scale

If this worked for you, drop a comment with your custom metric logic. Want a version that scales based on Redis queue length or HTTP latency? Let me know—I’ll write the next post.

Your app deserves an autoscaler that thinks like you. Build it. Deploy it. Scale it.


If you found this helpful, consider buying me a coffee ☕ — it keeps these articles coming!

Also check out my AI tools collection: AI 次元世界 — free AI tools for developers.


🛠️ Useful resource: **Content Creator Ultimate Bundle (Save 33%)* — $29.99. Check it out on Gumroad!*

Top comments (0)