Introduction
Your Kubernetes Horizontal Pod Autoscaler (HPA) is configured but pods aren't scaling despite high CPU or memory usage. The HPA remains at minimum replicas or shows errors when trying to scale.
Symptoms
HPA unable to get metrics:
```bash $ kubectl get hpa myapp-hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE myapp-hpa Deployment/myapp <unknown>/50% 1 10 1 5m ```
Metrics server not available:
```bash $ kubectl describe hpa myapp-hpa
Events: Type Reason Message ---- ------ ------- Warning FailedGetResourceMetric unable to get metrics for resource cpu Warning FailedComputeReplicas failed to compute desired replicas ```
Common Causes
- 1.Metrics Server not installed - HPA requires metrics-server
- 2.Missing resource requests - Pods without requests can't be autoscaled
- 3.Metrics Server not accessible - API aggregation issues
- 4.Wrong metrics type - Using custom metrics without adapter
- 5.Scaling cooldown - Stabilization window preventing scale
- 6.Resource quota limits - Quota preventing new pods
Step-by-Step Fix
- 1.Check logs for specific error messages
- 2.Verify configuration settings
- 3.Test network connectivity
- 4.Review recent changes
- 5.Apply corrective action
- 6.Verify the fix
Step 1: Verify Metrics Server Installation
```bash # Check if metrics-server is running: kubectl get pods -n kube-system | grep metrics-server
# If not installed, install metrics-server: kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# Verify metrics available: kubectl top nodes kubectl top pods
# If metrics-server fails, check logs: kubectl logs -n kube-system deployment/metrics-server
# Patch for development (insecure TLS): kubectl patch deployment metrics-server -n kube-system --type='json' -p='[ {"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"} ]' ```
Step 2: Check Pod Resource Requests
```bash # Check if deployment has resource requests: kubectl get deployment myapp -o yaml | grep -A 10 resources
# Add resource requests: kubectl patch deployment myapp --type='json' -p='[ {"op": "add", "path": "/spec/template/spec/containers/0/resources", "value": {"requests": {"cpu": "100m", "memory": "128Mi"}, "limits": {"cpu": "500m", "memory": "512Mi"}}} ]'
# Verify resource requests: kubectl describe deployment myapp | grep -A 5 "Containers:" ```
Step 3: Configure HPA Correctly
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50```bash # Create HPA: kubectl apply -f hpa.yaml
# Or use kubectl autoscale: kubectl autoscale deployment myapp --cpu-percent=50 --min=1 --max=10
# Verify HPA: kubectl get hpa myapp-hpa ```
Step 4: Debug Metrics Server API Access
```bash # Check API aggregation: kubectl get apiservices | grep metrics
# Test metrics API: kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/default/pods
# Check service and endpoints: kubectl get svc,endpoints -n kube-system metrics-server
# Check conditions: kubectl describe apiservice v1beta1.metrics.k8s.io ```
Step 5: Test Scaling Trigger
```bash # Generate load to trigger scaling: kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh # Inside pod: while true; do wget -q -O- http://myapp:8080; done
# Monitor HPA: kubectl get hpa myapp-hpa -w
# Check events: kubectl describe hpa myapp-hpa
# Verify new pods: kubectl get pods -l app=myapp -w ```
Step 6: Fix Common Configuration Issues
```bash # Check min/max replicas not equal: kubectl get hpa myapp-hpa -o yaml | grep -E "minReplicas|maxReplicas"
# Check target not too high: kubectl get hpa myapp-hpa -o jsonpath='{.spec.metrics[0].resource.target.averageUtilization}'
# Check scale target ref: kubectl get deployment myapp ```
Step 7: Handle Custom Metrics
```bash # Install Prometheus Adapter for custom metrics: helm repo add prometheus-adapter https://prometheus-community.github.io/helm-charts helm install prometheus-adapter prometheus-adapter/prometheus-adapter
# Verify custom metrics API: kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1
# Create HPA with custom metric: kubectl apply -f - <<EOF apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: myapp-hpa-custom spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myapp minReplicas: 1 maxReplicas: 10 metrics: - type: Pods pods: metric: name: http_requests_per_second target: type: AverageValue averageValue: 100 EOF ```
Step 8: Debug Scaling Failures
```bash # Check HPA conditions: kubectl get hpa myapp-hpa -o jsonpath='{.status.conditions}' | jq
# Check events: kubectl describe hpa myapp-hpa | grep -A 20 Events
# Check resource quotas: kubectl describe namespace default | grep -A 10 "Resource Quotas"
# Check cluster capacity: kubectl describe nodes | grep -A 5 "Allocated resources" ```
Step 9: Monitor HPA Performance
```bash # Monitoring script: kubectl get hpa myapp-hpa -o custom-columns=\ NAME:.metadata.name,\ TARGET:.spec.metrics[0].resource.target.averageUtilization,\ CURRENT:.status.currentMetrics[0].resource.current.averageUtilization,\ REPLICAS:.status.currentReplicas
# Prometheus metrics: # kube_horizontalpodautoscaler_status_current_replicas # kube_horizontalpodautoscaler_status_desired_replicas ```
Step 10: Production Best Practices
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15HPA Troubleshooting Checklist
| Check | Command | Expected |
|---|---|---|
| Metrics server | kubectl top pods | Metrics displayed |
| Resource requests | describe deployment | Requests defined |
| HPA created | kubectl get hpa | Shows targets |
| API aggregation | kubectl get apiservices | True status |
| Scaling works | load test | Replicas increase |
Verification
```bash # 1. Check HPA shows metrics kubectl get hpa myapp-hpa # Output: TARGETS shows actual/percentage
# 2. Generate load and watch scaling kubectl get hpa myapp-hpa -w
# 3. Verify new pods created kubectl get pods -l app=myapp
# Compare before/after: # Before: <unknown>/50%, 1 replica # After: 85%/50%, 5 replicas ```
Related Issues
- [Fix Kubernetes Metrics Server No Metrics](/articles/fix-kubernetes-metrics-server-no-metrics)
- [Fix Kubernetes Pod Pending](/articles/fix-kubernetes-pod-pending)
- [Fix Kubernetes Resource Quota Exceeded](/articles/fix-kubernetes-resource-quota-exceeded)
Related Articles
- [Fix Envoy Rate Limit Configuration with envoyproxy/ratelimit](envoyproxy-ratelimit-configuration-guide)
- [Fix Fix Argocd App Not Syncing Issue in Kubernetes](fix-argocd-app-not-syncing)
- [Fix Fix Argocd Sync Conflict Issue in Kubernetes](fix-argocd-sync-conflict)
- [Fix ArgoCD Sync Timeout](fix-argocd-sync-timeout)
- [How to Fix Cilium Identity Exhaustion and Endpoint Allocation Failed](fix-cilium-identity-exhaustion)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix Kubernetes Horizontal Pod Autoscaler Not Scaling", "description": "Troubleshoot Kubernetes HPA not scaling issues. Fix metrics server, resource requests, and autoscaling configuration.", "url": "https://www.fixwikihub.com/fix-kubernetes-horizontal-pod-autoscaler-not-scaling", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-12-11T16:27:45.497Z", "dateModified": "2025-12-11T16:27:45.497Z" } </script>