istio-ingressgateway HPA min replica 조정 (min=1을 피하는 이유)

운영 중인 EKS 클러스터의 istio-system 네임스페이스를 점검하다가, istio-ingressgateway HPA의 minReplicas1로 잡혀 있는 걸 봤습니다.

평소엔 HPA가 알아서 늘려주니까 큰 문제가 안 보였는데, 한 번 곱씹어 보니 이 1이라는 숫자가 운영 측면에서 위험한 자리에 앉아 있다는 게 느껴졌습니다.

이번 글에서는 그래서 minReplicas3으로 올린 과정과, 왜 min=1을 피해야 하는가에 대한 정리입니다.


1. 발단

평소처럼 클러스터 상태를 보다가 HPA 한 줄을 짚어봤습니다.

kubectl get hpa -n istio-system
NAME                    REFERENCE                          TARGETS   MINPODS  MAXPODS  REPLICAS
istio-ingressgateway    Deployment/istio-ingressgateway    23%/80%   1        5        1
istiod                  Deployment/istiod                  15%/80%   1        5        1

지금은 트래픽이 적어서 REPLICAS=1로 안정적으로 떨어져 있지만, 숫자가 의미하는 건 결국 다음과 같았습니다.

평시에는 ingressgateway 파드가 한 개만 떠 있고, 그 한 개로 모든 외부 트래픽을 받고 있다.

처음 클러스터를 만들 때 default 값으로 잡힌 그대로, 한참을 그대로 운영하고 있던 셈이었습니다.


2. min=1이 왜 위험한가

minReplicas 가 1이라는 건 HPA가 한 개까지 줄어들 수 있다는 의미이고, 한 개까지 줄었을 때 다음과 같은 시나리오가 모두 한 줄의 위험이 됩니다.

2-1. 노드 한 대 빠지면 전체 다운

ingressgateway 파드 한 개가 떠 있는 노드가 어떤 이유로든 사라지면 (스케줄링 변경, 노드 drain, AZ 장애, spot interruption 등) 외부 트래픽 진입점 자체가 잠시 사라집니다.

HPA가 곧바로 한 개를 새로 띄워주긴 하지만, 그 사이에 새 요청은 거절됩니다.

2-2. HPA는 reactive하다

HPA의 동작 방식은 단순합니다.

  • 현재 CPU/메모리 사용률을 측정 → 목표치를 넘으면 scale up

“넘은 뒤에 늘리는” 동작이라 트래픽 스파이크가 들이쳐 첫 몇 초~몇 분은 한 파드가 다 받습니다. 이 사이에 응답이 느려지거나 timeout이 발생할 수 있습니다.

특히 ingressgateway 같은 입구 컴포넌트는 한 번 막히기 시작하면 뒤쪽 서비스 응답까지 줄줄이 영향을 받습니다.

2-3. 워밍업이 필요한 컴포넌트

ingressgateway는 외부 TLS termination, Envoy 설정 reload 등 무거운 초기화를 수행합니다. 새로 뜨는 파드는 받자마자 정상 성능을 내지 못하는 경우도 있습니다.

평소 3개가 떠 있으면 새로 한 개가 늦게 뜨더라도 기존 두 개가 트래픽을 받쳐주는데, 1개만 떠 있는 상태에서 한 개가 새로 뜨는 동안은 정말로 그 한 개에 모든 게 걸립니다.


3. 어떤 값으로 올릴 것인가

운영 측면에서 보통 다음 두 가지를 함께 고려합니다.

기준 의미
노드/AZ 분산 한 AZ가 빠져도 다른 AZ의 파드가 트래픽 유지
평시 부하 분산 한 파드의 CPU/메모리 사용을 너무 높지 않게

EKS의 매니지드 노드 그룹이 3 AZ에 걸쳐 있는 경우라면, min=3 정도가 한 AZ당 한 파드씩 분산하기에 자연스럽습니다. max 는 기존 값(5)을 유지했습니다.

이번에는 다음과 같이 결정했습니다.

항목 변경 전 변경 후
minReplicas 1 3
maxReplicas 5 5
target CPU 80% 80% (유지)

target CPU 도 함께 조정 후보로 봤는데, 평시 사용률이 낮은 편이라 기존 80%를 그대로 두기로 했습니다.


4. 실제 변경

HPA 변경은 kubectl patch 한 줄로 끝납니다.

kubectl patch hpa istio-ingressgateway \
  -n istio-system \
  --type=merge \
  -p '{"spec":{"minReplicas":3}}'

운영 환경에서 patch를 할 때는 변경 전 후 비교를 같이 캡처해 두는 게 좋습니다.

kubectl get hpa istio-ingressgateway -n istio-system -o yaml > /tmp/hpa-before.yaml

kubectl patch hpa istio-ingressgateway \
  -n istio-system \
  --type=merge \
  -p '{"spec":{"minReplicas":3}}'

kubectl get hpa istio-ingressgateway -n istio-system -o yaml > /tmp/hpa-after.yaml
diff /tmp/hpa-before.yaml /tmp/hpa-after.yaml

이렇게 두면 어떤 키가 정확히 어떻게 바뀌었는지 명확히 남고, 혹시 다른 필드가 의도치 않게 함께 바뀌었는지도 확인할 수 있습니다.


5. 변경 후 확인

kubectl get hpa -n istio-system

MINPODS3으로 바뀌었고, REPLICAS 가 곧바로 3으로 올라옵니다.

kubectl get pods -n istio-system -l app=istio-ingressgateway -o wide

이 명령으로 새로 뜬 파드들이 서로 다른 노드 / 다른 AZ에 분산되었는지 확인했습니다.

만약 같은 노드에 두 파드가 떠 있다면 anti-affinity 설정이 빠져 있을 가능성이 있어서, 그 부분은 별도 작업으로 추가 검토 대상이 됩니다.


6. 짚어두고 싶은 것들

6-1. min=1은 평시 비용 아끼는 자리가 아니다

minReplicas 를 낮춰서 평시 비용을 아끼고 싶은 생각이 들 수 있지만, ingressgateway는 외부 트래픽의 진입점이라 평시 비용보다 가용성이 우선입니다.

이 글에서 보고 있는 환경은 ingressgateway 파드 자체의 CPU/메모리가 그렇게 크지 않아서, 1 → 3 으로 늘려도 비용 영향이 미미했습니다.

6-2. HPA는 reactive — 미리 일정 수준은 띄워둬야 한다

HPA의 한계는 단순합니다.

  • 부하가 늘기 전에 미리 늘리지 않음
  • 측정 → 판단 → scale up 사이에 짧지만 의미 있는 지연

이걸 보완하는 방법은 단순합니다.

  • minReplicas 를 평시 안전 수준으로 잡아두기
  • 큰 이벤트(프로모션 등) 전에는 일시적으로 minReplicas 를 더 올렸다가 다시 내리기

6-3. PDB 도 같이 점검

min=3 으로 올리고 끝이 아니라, PDB(PodDisruptionBudget) 가 잡혀 있는지도 같이 확인했습니다.

PDB가 없으면 노드 drain 시 ingressgateway 파드 여러 개가 동시에 evict될 수 있어서, min=3 으로 만든 효과가 한순간에 무력화됩니다.

이번에는 PDB가 없는 상태라 별도 작업으로 추가하는 걸 후속 항목으로 메모해 뒀습니다.

참고: [Karpenter 잔재 NodeClaim · Node finalizer 정리 절차] 글에서도 같은 패턴을 다뤘습니다. 분산 파드에는 가능하면 PDB 부터 잡아두는 게 안전합니다.

6-4. 측정 지표는 80%가 만능이 아니다

target CPU 80% 는 default에 가까운 값이지만, 컴포넌트 특성에 따라 달라집니다.

  • ingressgateway 처럼 short-lived 요청 위주면 80% 도 무난
  • 백그라운드 처리/long-lived 연결 위주라면 더 낮은 값(예: 50~60%)이 안전

이 값은 한번 정하고 잊지 말고, 운영 메트릭(p99 응답 시간, 큐 깊이) 을 보면서 종종 다시 들여다보는 편이 좋습니다.


7. 마무리

처음 MINPODS=1 을 봤을 때는 단순히 “기본값이네” 정도였는데, 한 번 곱씹어 보니 입구 컴포넌트의 가용성을 한 줄로 좌우하는 값이라는 게 보였습니다.

운영의 기본값은 편의를 위해 잡혀 있는 경우가 많고, 실제 운영 요구는 그것보다 조금 더 보수적인 위치에 있다.

이번 변경은 단순히 숫자 한 자리를 바꾼 작업이지만, “min=1 이면 어떤 상황에서 어떻게 위험해지는가”를 같이 정리하는 계기였습니다.

같은 맥락으로 istiod 의 resource limits 도 점검 대상으로 남겨두었고, 그 부분은 별도 글로 이어서 정리해보려고 합니다.


This site uses Just the Docs, a documentation theme for Jekyll.