Published on

EKS에서 HPA가 안 늘어날 때 Metrics 오류 해결

Authors

서버 부하가 올라가는데도 EKS에서 HPA(Horizontal Pod Autoscaler)가 꿈쩍하지 않는 상황은 대부분 “스케일링 로직이 틀려서”가 아니라 “메트릭을 못 읽어서” 발생합니다. 특히 EKS에서는 Metrics Server, kubelet 인증/통신, API aggregation, (커스텀 메트릭이면) Prometheus Adapter까지 파이프라인이 길어서 한 군데만 삐끗해도 HPA가 Unknown 상태로 멈춥니다.

이 글은 HPA가 안 늘어날 때 흔히 보이는 Metrics 관련 오류 메시지를 기준으로, 원인-진단-해결을 빠르게 따라갈 수 있게 구성했습니다.

> 참고로 EKS에서 네트워크/IRSA 이슈가 함께 얽히는 경우도 많습니다. 예: DNS/통신 문제가 전반적으로 발생한다면 EKS TLS handshake timeout 해결 - IRSA·VPC·CoreDNS도 같이 점검하세요.

1) 증상부터 확인: HPA 이벤트/상태가 말해주는 것

먼저 “정말 메트릭 문제인지”를 HPA 상태에서 확인합니다.

kubectl -n <ns> describe hpa <hpa-name>

여기서 자주 보이는 신호:

  • Current CPU utilization: <unknown>
  • failed to get cpu utilization: unable to get metrics for resource cpu
  • the server could not find the requested resource (get pods.metrics.k8s.io)
  • unable to fetch metrics from resource metrics API
  • missing request for cpu (리소스 request 미설정)

또한 Metrics API 자체가 살아있는지 확인합니다.

kubectl get apiservices | grep -E 'metrics.k8s.io|custom.metrics.k8s.io|external.metrics.k8s.io'

정상이라면 v1beta1.metrics.k8s.ioAvailable=True로 보여야 합니다.

그리고 실제 메트릭 조회가 되는지:

kubectl top nodes
kubectl top pods -n <ns>

여기서 error: Metrics API not available가 뜨면 HPA는 사실상 멈춰 있다고 봐도 됩니다.

2) 가장 흔한 원인 1: Metrics Server 미설치/비정상

EKS는 기본적으로 Metrics Server가 “항상 자동 설치”되는 형태가 아닙니다(클러스터/애드온 구성에 따라 다름). kubectl top이 안 되면 Metrics Server부터 봅니다.

2-1) 설치 여부 확인

kubectl -n kube-system get deploy,po | grep -i metrics-server
  • Deployment/Pod가 없다면 설치가 필요합니다.

2-2) (권장) EKS Add-on으로 설치/업데이트

운영에서는 매니페스트 직접 적용보다 EKS Add-on이 관리가 편합니다.

aws eks describe-addon-versions --addon-name metrics-server --kubernetes-version <k8s-version>

aws eks create-addon \
  --cluster-name <cluster> \
  --addon-name metrics-server \
  --resolve-conflicts OVERWRITE

이미 설치돼 있다면 업데이트:

aws eks update-addon \
  --cluster-name <cluster> \
  --addon-name metrics-server \
  --resolve-conflicts OVERWRITE

2-3) 로그로 “왜 수집이 안 되는지” 확인

kubectl -n kube-system logs deploy/metrics-server --tail=200

자주 보는 에러 패턴:

  • x509: certificate signed by unknown authority
  • context deadline exceeded
  • no metrics to serve
  • unable to fully scrape metrics

이제부터는 케이스별로 해결합니다.

3) 가장 흔한 원인 2: kubelet TLS/인증 문제 (x509, unauthorized)

EKS에서 Metrics Server는 각 노드의 **kubelet(10250 포트)**에 붙어서 요약 메트릭을 가져옵니다. 여기서 인증서/인증 문제가 나면 kubectl top도, HPA도 모두 죽습니다.

3-1) 대표 증상

  • Metrics Server 로그: x509: certificate signed by unknown authority
  • 또는 Forbidden (user=system:serviceaccount:kube-system:metrics-server, verb=get, resource=nodes/stats) 같은 RBAC 오류

3-2) 빠른 우회(권장 X): --kubelet-insecure-tls

보안적으로는 권장하지 않지만, 원인 분리가 급할 때 임시로 적용해 “TLS 문제인지” 확인할 수 있습니다.

kubectl -n kube-system patch deploy metrics-server \
  --type='json' \
  -p='[
    {
      "op": "add",
      "path": "/spec/template/spec/containers/0/args/-",
      "value": "--kubelet-insecure-tls"
    }
  ]'

이후 kubectl top nodes가 살아나면, kubelet 인증서 체인/통신 경로 문제일 가능성이 큽니다.

3-3) 정석 접근: kubelet 접근/권한/통신 경로 점검

  • Metrics Server가 노드로 라우팅 가능한지(보안그룹/네트워크 정책)
  • API aggregation이 정상인지
  • RBAC이 기본 제공 설정대로 적용됐는지

RBAC은 보통 Metrics Server 설치 시 함께 들어가지만, 커스텀으로 만지다 깨지는 경우가 있습니다.

kubectl get clusterrole system:aggregated-metrics-reader -o yaml
kubectl get clusterrolebinding | grep -i metrics

또한 EKS에서 전반적인 권한/인증 문제가 의심되면, 원인별로 정리된 Kubernetes 401 Unauthorized 원인별 해결 가이드 체크리스트대로 “누가/어디에” 인증 실패가 나는지 분리하는 게 빠릅니다.

4) 가장 흔한 원인 3: Metrics API Aggregation(apiserver) 문제

kubectl get --raw "/apis/metrics.k8s.io/v1beta1"가 실패하거나, apiservices에서 Available=False라면 aggregation 계층 문제입니다.

4-1) 상태 확인

kubectl get apiservice v1beta1.metrics.k8s.io -o yaml

여기서 status.conditions[].message에 원인이 드러납니다.

  • failing or missing response from ...
  • x509 관련
  • timeout 관련

4-2) 서비스/엔드포인트 확인

kubectl -n kube-system get svc,ep | grep -i metrics-server
  • Endpoint가 비어 있으면 Pod readiness 문제이거나 selector가 안 맞는 것입니다.

5) HPA가 CPU 기준인데도 안 늘어나는 “설정” 문제: requests 미설정

메트릭 파이프라인이 정상인데도 HPA가 스케일링을 못 하는 가장 흔한 설정 실수는 컨테이너 리소스 requests 미설정입니다.

CPU utilization 기반 HPA는 usage / request로 계산합니다. request가 없으면 계산할 수 없어서 이벤트에 다음이 뜹니다.

  • missing request for cpu

5-1) Deployment에 requests 추가 예시

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 2
  template:
    spec:
      containers:
      - name: api
        image: nginx:1.27
        resources:
          requests:
            cpu: "200m"
            memory: "256Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"

5-2) HPA 예시 (CPU 60% 타겟)

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60

적용 후 확인:

kubectl apply -f deploy.yaml
kubectl apply -f hpa.yaml
kubectl describe hpa api-hpa

6) 커스텀/외부 메트릭(HPA v2)일 때: Prometheus Adapter 계열 오류

CPU/메모리 리소스 메트릭이 아니라 QPS, latency, queue length 같은 지표로 HPA를 돌리면 보통 다음 중 하나를 씁니다.

  • custom.metrics.k8s.io (파드/네임스페이스 등 Kubernetes 객체에 붙는 메트릭)
  • external.metrics.k8s.io (클러스터 외부/논리적 지표)

이때는 Metrics Server가 아니라 **Prometheus Adapter(또는 KEDA 등)**가 핵심입니다.

6-1) APIService 확인

kubectl get apiservices | grep -E 'custom.metrics.k8s.io|external.metrics.k8s.io'

Available=False면 adapter가 죽었거나 aggregation이 깨진 것입니다.

6-2) HPA 이벤트에서 힌트 찾기

kubectl -n <ns> describe hpa <hpa-name>

자주 보이는 메시지:

  • unable to get external metric ... no metrics returned from external metrics API
  • the server is currently unable to handle the request (get ...)

이 경우 adapter의 로그/서비스/엔드포인트를 확인하고, Prometheus 쿼리 자체가 데이터가 있는지부터 검증하세요.

7) 네트워크/DNS로 인해 Metrics Server가 노드에 못 붙는 경우

EKS에서는 보안그룹, NACL, CNI 설정, DNS(CoreDNS) 문제로 내부 통신이 간헐적으로 실패하며 Metrics 수집이 타임아웃 나는 경우가 있습니다.

7-1) 증상

  • metrics-server 로그: context deadline exceeded
  • apiservice message: timeout/no response

7-2) 빠른 확인 포인트

  • 노드 보안그룹에서 노드 간 통신(특히 10250) 경로가 막혀 있지 않은지
  • CoreDNS 장애로 서비스 디스커버리가 흔들리지 않는지

EKS에서 DNS/네트워크가 엮인 증상은 겉으로는 “메트릭이 안 보임”으로만 나타나기도 합니다. 클러스터 전반의 TLS/DNS 증상이 함께 있다면 EKS TLS handshake timeout 해결 - IRSA·VPC·CoreDNS에서 제시한 CoreDNS/IRSA/VPC 점검 루틴을 같이 수행하는 게 좋습니다.

8) 실전 10분 진단 체크리스트

장애 상황에서 순서대로 실행하면 원인 범위를 빠르게 줄일 수 있습니다.

8-1) HPA 자체 상태

kubectl -n <ns> describe hpa <hpa>
  • Unknown/failed to get metrics면 메트릭 파이프라인 문제
  • missing request for cpu면 리소스 설정 문제

8-2) Metrics API 확인

kubectl top nodes
kubectl get apiservice v1beta1.metrics.k8s.io
kubectl get --raw "/apis/metrics.k8s.io/v1beta1" | head

8-3) Metrics Server 상태/로그

kubectl -n kube-system get deploy metrics-server
kubectl -n kube-system logs deploy/metrics-server --tail=200
kubectl -n kube-system get svc,ep | grep -i metrics-server

8-4) 커스텀/외부 메트릭을 쓰는 HPA라면

kubectl get apiservices | grep -E 'custom.metrics|external.metrics'

9) 마무리: “HPA가 안 늘어남”은 대부분 관측 파이프라인 장애다

EKS에서 HPA 스케일아웃이 멈추는 이슈는 대개 다음 3가지로 귀결됩니다.

  1. Metrics Server/metrics.k8s.io가 죽었거나 aggregation이 실패
  2. kubelet TLS/권한/통신 문제로 스크래핑 불가
  3. CPU utilization 기반인데 requests 미설정

이 글의 커맨드들로 kubectl top이 정상화되면 HPA는 대부분 자동으로 회복됩니다. 만약 메트릭은 정상인데도 스케일이 안 된다면, 그때는 HPA의 behavior(stabilizationWindowSeconds), maxReplicas, 그리고 실제 부하가 request 대비 얼마나 올라가는지(타겟 계산)까지 들어가서 튜닝하면 됩니다.

추가로, EKS에서 특정 Pod만 외부 통신이 꼬이거나(예: NAT/WAF) 클러스터 내부 네트워크가 흔들리면 메트릭 수집도 연쇄로 깨질 수 있습니다. 그런 케이스는 EKS Pod만 외부 API 403 - NAT IP·WAF로 해결처럼 “네트워크 경계”부터 분리 진단하는 접근이 도움이 됩니다.