Introduction

The Horizontal Pod Autoscaler (HPA) is a Kubernetes feature that automatically scales the number of Pod replicas based on observed metrics such as CPU utilization or memory usage. For HPA to make intelligent scaling decisions, it requires real-time metrics data from the cluster. This data is provided by the Kubernetes metrics API, which is typically served by the metrics-server component.

When the metrics API is unavailable or the metrics-server is not functioning correctly, HPA objects display <unknown> instead of actual utilization values. This prevents the autoscaler from making scaling decisions, effectively disabling automatic scaling for the affected workloads. The HPA remains in a degraded state until metrics become available again.

Understanding the metrics pipeline is essential for debugging HPA issues. Metrics-server scrapes kubelet metrics from each node, aggregates them, and exposes them through the Kubernetes metrics API. HPA queries this API to retrieve current utilization. Any break in this chain—from kubelet scraping to API availability—will result in unknown metrics.

Symptoms

When HPA cannot retrieve metrics, you will observe these symptoms:

  • kubectl get hpa shows <unknown> instead of CPU or memory usage percentages
  • kubectl top nodes or kubectl top pods returns errors like "error: Metrics API not available"
  • HPA events indicate it did not receive metrics for ready Pods
  • Scaling stays flat even though workload demand is clearly rising
  • HPA status shows "unable to fetch metrics from resource metrics API"
  • The metrics-server pod may be missing, crashlooping, or showing errors

Common error output from HPA describe:

bash
Name:                                                  my-app-hpa
Namespace:                                             default
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):  <unknown> / 50%
Min replicas:                                          2
Max replicas:                                          10
Conditions:
  Type           Status  Reason                   Message
  ----           ------  ------                   -------
  AbleToScale    True    SucceededGetScale        the HPA controller was able to get the target's current scale
  ScalingActive  False   FailedGetResourceMetric  the HPA was unable to compute the replica count: failed to get cpu utilization: unable to fetch metrics from resource metrics API

Errors from kubectl top commands:

``` $ kubectl top nodes Error from server (NotFound): the server could not find the requested resource (get services metrics-server)

$ kubectl top pods Error from server (ServiceUnavailable): the server is currently unable to handle the request (get pods.metrics.k8s.io) ```

Common Causes

Several factors cause HPA to show unknown metrics:

  1. 1.metrics-server not installed: Many Kubernetes distributions do not include metrics-server by default. Without it, the metrics API is unavailable and HPA cannot function.
  2. 2.metrics-server unhealthy: The metrics-server deployment may be in a failed state, crashlooping, or unable to start due to resource constraints, image pull issues, or configuration errors.
  3. 3.Kubelet TLS certificate issues: Metrics-server validates kubelet certificates when scraping metrics. Self-signed or custom certificates may cause scraping failures unless TLS verification is disabled or certificates are properly configured.
  4. 4.Network connectivity issues: Metrics-server runs in the control plane or kube-system namespace and must be able to reach kubelet endpoints on worker nodes. Network policies, firewalls, or CNI misconfigurations can block this connectivity.
  5. 5.Missing resource requests: HPA calculates utilization as a percentage of requested resources. If pods don't define resource requests, HPA cannot calculate utilization and will show unknown metrics.
  6. 6.API service registration issues: The metrics API service (v1beta1.metrics.k8s.io) may be registered but pointing to an unavailable endpoint.
  7. 7.Insufficient permissions: Metrics-server may lack the RBAC permissions needed to access kubelet metrics endpoints.
  8. 8.Large clusters: In clusters with many nodes or pods, metrics-server may be overwhelmed, causing timeouts or failures to aggregate metrics quickly enough.

Step-by-Step Fix

Follow these steps to diagnose and resolve HPA unknown metrics issues:

Step 1: Check if metrics-server is installed and healthy

Verify the metrics-server deployment exists and is running:

```bash # Check if metrics-server deployment exists kubectl get deployment metrics-server -n kube-system

# Check metrics-server pods kubectl get pods -n kube-system -l k8s-app=metrics-server

# Check pod logs for errors kubectl logs -n kube-system -l k8s-app=metrics-server --tail=50

# Check deployment details kubectl describe deployment metrics-server -n kube-system ```

If metrics-server is not installed, install it:

```bash # Install metrics-server (method depends on cluster type) # For most clusters, apply the standard manifest: kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# For managed Kubernetes services, use provider-specific methods: # EKS: Addons may include metrics-server # GKE: Metrics server is typically pre-installed # AKS: May need manual installation ```

Step 2: Verify the metrics API is available

Check if the metrics API is registered and accessible:

```bash # Check API service status kubectl get apiservice v1beta1.metrics.k8s.io

# Expected output: # NAME SERVICE AVAILABLE AGE # v1beta1.metrics.k8s.io kube-system/metrics-server True 10d

# If showing False or Unknown, check the service kubectl describe apiservice v1beta1.metrics.k8s.io

# Test metrics API directly kubectl get --raw "/apis/metrics.k8s.io/v1beta1/namespaces/default/pods"

# Test kubectl top commands kubectl top nodes kubectl top pods -n kube-system ```

Step 3: Check kubelet TLS configuration

If metrics-server cannot scrape kubelet metrics due to TLS issues:

```bash # Check metrics-server logs for TLS errors kubectl logs -n kube-system -l k8s-app=metrics-server | grep -i tls

# Common error: # "x509: cannot validate certificate for <node-ip> because it doesn't contain any IP SANs"

# Fix by enabling insecure TLS (development/testing only) kubectl patch deployment metrics-server -n kube-system --type='json' \ -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'

# Better fix: Configure proper kubelet certificates # On each node, ensure kubelet cert includes node IP or use proper CA ```

Alternative: Deploy metrics-server with insecure TLS enabled:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
spec:
  template:
    spec:
      containers:
      - name: metrics-server
        args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        - --kubelet-insecure-tls  # Add this flag for self-signed certs

Step 4: Check RBAC permissions

Verify metrics-server has permissions to access kubelet stats:

```bash # Check metrics-server service account kubectl get clusterrole system:aggregated-metrics-reader -o yaml

# Verify ClusterRoleBinding exists kubectl get clusterrolebinding metrics-server:system:auth-delegator -o yaml

# Check if service account has necessary permissions kubectl auth can-i get nodes.metrics.k8s.io --as=system:serviceaccount:kube-system:metrics-server ```

Create RBAC if missing:

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:aggregated-metrics-reader
  labels:
    rbac.authorization.k8s.io/aggregate-to-view: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods", "nodes"]
  verbs: ["get", "list", "watch"]

Step 5: Verify pods have resource requests

HPA requires resource requests to calculate utilization:

```bash # Check if target pods have resource requests kubectl get pods -l app=my-app -o jsonpath='{.items[*].spec.containers[*].resources.requests}'

# If empty, add resource requests to pod spec: kubectl patch deployment my-app --type='json' -p='[ {"op":"add","path":"/spec/template/spec/containers/0/resources/requests","value":{"cpu":"100m","memory":"128Mi"}} ]'

# Verify requests are set kubectl describe pod -l app=my-app | grep -A 5 Requests ```

Example pod spec with resource requests:

yaml
resources:
  requests:
    cpu: 100m      # Required for HPA CPU scaling
    memory: 128Mi  # Required for HPA memory scaling
  limits:
    cpu: 500m
    memory: 512Mi

Step 6: Check network connectivity

Ensure metrics-server can reach kubelet endpoints:

```bash # Get metrics-server pod IP METRICS_POD=$(kubectl get pods -n kube-system -l k8s-app=metrics-server -o jsonpath='{.items[0].metadata.name}')

# Test connectivity to a node's kubelet kubectl exec -n kube-system $METRICS_POD -- wget -qO- http://<node-ip>:10250/stats/summary

# Check if network policies block traffic kubectl get networkpolicies -n kube-system

# Verify node ports kubectl get nodes -o wide ```

Step 7: Scale metrics-server if needed

For large clusters, metrics-server may need more resources:

```bash # Increase resources for metrics-server kubectl patch deployment metrics-server -n kube-system --type='json' -p='[ {"op":"replace","path":"/spec/template/spec/containers/0/resources","value":{"requests":{"cpu":"100m","memory":"200Mi"},"limits":{"cpu":"500m","memory":"500Mi"}}} ]'

# Add more replicas for high availability kubectl scale deployment metrics-server -n kube-system --replicas=2

# Adjust metric resolution for large clusters kubectl patch deployment metrics-server -n kube-system --type='json' \ -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--metric-resolution=30s"}]' ```

Verification

After fixing metrics-server, verify HPA receives metrics:

```bash # Check metrics-server is healthy kubectl get pods -n kube-system -l k8s-app=metrics-server

# Verify metrics API is available kubectl top nodes kubectl top pods -n default

# Check HPA status kubectl get hpa my-app-hpa

# Expected output showing actual utilization: # NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE # my-app-hpa Deployment/my-app 25%/50% 2 10 3 5d

# Monitor HPA events kubectl describe hpa my-app-hpa | grep -A 20 Events ```

Prevention

To prevent HPA unknown metrics issues:

  1. 1.Monitor metrics-server as critical infrastructure: Metrics-server is essential for autoscaling. Set up alerts for pod failures, restarts, and API availability.
yaml
# Prometheus alert for metrics-server
- alert: MetricsServerDown
  expr: up{app="metrics-server"} == 0
  for: 5m
  severity: critical
  annotations:
    summary: "metrics-server is down"
    description: "metrics-server pod is not running, HPA cannot function"
  1. 1.Define resource requests on all HPA targets: Every workload using HPA must have CPU and memory requests defined. Include this in pod spec templates and linting rules.
  2. 2.Test metrics availability regularly: Include kubectl top checks in cluster health scripts or monitoring.
bash
# Health check script
kubectl top nodes > /dev/null 2>&1 && echo "Metrics API: OK" || echo "Metrics API: FAILED"
  1. 1.Review metrics-server configuration during cluster changes: When changing CNI, certificates, or network policies, verify metrics-server can still reach kubelets.
  2. 2.Document cluster-specific metrics-server setup: Different Kubernetes distributions have different metrics-server requirements. Document what's needed for your specific cluster type.
  3. 3.Use Horizontal Pod Autoscaler v2: For custom metrics and better configuration options, use HPA v2 (autoscaling/v2) which provides more control over scaling behavior.
  • [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": "Kubernetes HPA Showing Unknown Metrics Because metrics-server Is Missing or Failing", "description": "Resolve Kubernetes HPA unknown metrics by checking metrics-server health, the metrics API availability, kubelet TLS behavior, and whether Pods define resource requests for autoscaling math.", "url": "https://www.fixwikihub.com/kubernetes-hpa-metrics-server-unknown", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-01-23T14:56:44.292Z", "dateModified": "2026-01-23T14:56:44.292Z" } </script>