본문으로 건너뛰기
버전: 1.0.3

3.5. 오토스케일링

어떨 때 보는가

  • 부하가 몰리는 시간에 서비스가 느려질 때
  • 한가한 시간에 자원이 낭비될 때
  • 노드 점검 중에 서비스가 끊기지 않게 하고 싶을 때

자동 조절이 필요한 이유

부하가 늘 때 파드 수를 손으로 늘리면 대응이 늦습니다. 반대로 한가한 시간에 많은 파드를 그대로 두면 자원이 낭비됩니다.

COP 는 두 가지 자동 조절 방식을 제공합니다.

방식판단 기준반응
HPA현재 CPU·메모리 사용률부하가 오른 늘립니다
CronHPA정해진 시각부하가 오르기 전에 늘립니다

HPA

HPA(HorizontalPodAutoscaler)는 사용률을 보고 파드 수를 늘리거나 줄입니다.

워크로드 > 수평 자동 확장(HPA) 으로 들어갑니다.

HPA 목록
설명
이름HPA 이름
대상조절할 Deployment 등
최소 · 최대파드 수의 하한과 상한
복제본현재 파드 수
지표현재 사용률 / 목표 사용률

동작 방식은 이렇습니다.

  1. 대상 파드들의 평균 사용률을 잽니다.
  2. 목표 사용률과 비교합니다.
  3. 필요한 파드 수 = 현재 파드 수 × (현재 사용률 ÷ 목표 사용률) 로 계산합니다.
  4. 최소·최대 범위 안에서 조절합니다.

예를 들어 파드 2개가 평균 80% 를 쓰고 목표가 50% 면, 2 × (80 ÷ 50) = 3.2 → 4개로 늘립니다.

줄일 때는 늘릴 때보다 천천히 움직입니다. 부하가 잠깐 내려갔다고 바로 줄이면 다시 늘려야 하므로, 일정 시간 낮은 상태가 이어져야 줄입니다.

HPA 를 쓰려면 자원 요청량이 있어야 합니다

HPA 를 걸기 전에 대상 파드에 자원 요청량이 설정되어 있어야 합니다. 없으면 HPA 는 아무 일도 하지 않습니다. 이것이 HPA 가 동작하지 않는 가장 흔한 원인입니다.

왜 필요한가

앞의 계산식에 나오는 "사용률" 은 요청량 대비 비율 입니다. 노드 전체 용량이나 상한이 아닙니다.

사용률 = 실제 사용량 ÷ 요청량 × 100

요청량이 분모입니다. 요청량이 없으면 분모가 없어 사용률 자체를 구할 수 없고, HPA 목록의 지표 열에 <unknown> 이 뜬 채로 멈춥니다.

요청량·상한이 무엇이고 어떻게 정하는지는 3.1 장에 있습니다. 여기서는 HPA 가 그 값을 어떻게 쓰는지만 봅니다.

계산 예 — COP 샘플 애플리케이션

COP 가 넣어 주는 전자정부 샘플 애플리케이션의 실제 설정으로 따라가 보겠습니다.

항목
CPU 상한2 (2 코어)
CPU 요청량별도로 정하지 않음 → 상한과 같은 2 가 자동으로 채워집니다(3.1 장)
HPA 최소 파드 수2
HPA 최대 파드 수4
HPA 목표 사용률75%

여기서 목표 75% 는 "파드 하나가 평균 1.5 코어를 쓰는 상태" 를 뜻합니다.

2 코어(요청량) × 75% = 1.5 코어

파드 2개가 각각 1.8 코어를 쓰고 있다고 하면 이렇게 됩니다.

단계계산
현재 사용률1.8 ÷ 2 × 100 = 90%
필요한 파드 수2 × (90 ÷ 75) = 2.4 → 올림 → 3개
최대 범위 확인3 은 최대 4 이내이므로 그대로 3개

늘어난 뒤에는 같은 부하가 3개로 나뉘므로 파드당 1.2 코어, 사용률 60% 가 되어 목표 아래로 내려갑니다. 부하가 계속 오르면 4개까지 늘고, 4개로도 90% 를 넘으면 더는 늘지 않습니다. 그때는 최대값을 올리거나 다른 병목을 찾아야 합니다.

요청량을 잘못 잡으면 생기는 일

요청량은 배치에 쓰이는 값이면서 동시에 HPA 의 분모입니다. 한 값이 두 가지를 결정하므로 잘못 잡으면 양쪽이 함께 어긋납니다.

요청량배치에 미치는 영향HPA 에 미치는 영향
실제보다 크게노드에 파드가 몇 개 못 들어갑니다사용률이 낮게 나와 필요한데도 늘지 않습니다
실제보다 작게붐빌 때 밀려납니다사용률이 높게 나와 필요 없는데도 늘어납니다
없음자리를 잡지 않습니다HPA 가 동작하지 않습니다

예를 들어 요청량을 2 코어로 잡았는데 실제로는 0.2 코어밖에 쓰지 않는 애플리케이션이라면, 부하가 다섯 배로 뛰어 1 코어를 써도 사용률은 50% 라 목표 75% 에 못 미쳐 파드가 늘지 않습니다. 화면상 "HPA 는 정상인데 서비스는 느린" 상태가 됩니다.

실제 사용량을 먼저 재고 요청량을 정한 뒤 HPA 를 거십시오. 순서를 바꾸면 목표 사용률을 아무리 조절해도 맞지 않습니다.

메모리 기준으로 조절할 때

메모리 사용률로도 조절할 수 있지만 CPU 만큼 잘 맞지 않습니다. 자바처럼 힙을 미리 잡아 두는 런타임은 실제로 놀고 있어도 메모리 사용량이 줄지 않아, 파드를 늘려도 사용률이 내려가지 않습니다. 그러면 최대치까지 계속 늘어납니다.

메모리는 상한을 제대로 잡는 쪽이 맞고, 자동 조절은 CPU 를 기준으로 하는 편이 안전합니다.

만들기 — YAML

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
namespace: my-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75 # 요청량 대비 75%
항목설명
scaleTargetRef조절할 대상. 이름이 틀리면 지표가 <unknown> 으로 남습니다
minReplicas바닥. 2 이상을 권장합니다 — 1 이면 조절 중에 서비스가 끊길 수 있습니다
maxReplicas천장. 클러스터가 감당할 수 있는 값으로 둡니다
averageUtilization목표 사용률. 요청량 기준 입니다(위 절)

오르내림이 잦으면 반응 속도를 조절합니다.

behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 5분 동안 낮아야 줄입니다
scaleUp:
stabilizationWindowSeconds: 0 # 늘릴 때는 바로

줄이는 쪽만 늦추는 것이 요령입니다. 부하가 잠깐 내려갔다고 줄이면 곧 다시 늘려야 해 파드가 계속 오르내립니다.

HPA 가 동작하지 않을 때

지표 열에 <unknown> 이 보이면 사용량을 읽지 못하는 상태입니다.

원인확인할 것
대상 파드에 자원 요청량이 없음가장 흔한 원인입니다. 파드 상세의 요청·제한을 봅니다(위 절)
지표 수집기가 동작하지 않음운영 담당자에게 문의
대상 이름이 틀림상세 화면의 대상이 실제 Deployment 이름과 같은지
파드가 방금 떴음첫 측정값이 모이기까지 1분 안팎 걸립니다. 잠시 뒤 다시 봅니다

<unknown> 이 아니라 숫자는 나오는데 파드가 늘지 않는 경우 는 원인이 다릅니다.

증상원인
사용률이 목표보다 낮게만 나온다요청량이 실제보다 크게 잡혀 있습니다(위 절)
최대값에 머물러 있다최대 파드 수가 부족하거나 다른 곳이 병목입니다
늘었는데 Pending 에 머문다클러스터에 자리가 없습니다. 노드 자원을 확인합니다(2.1 장)

최대까지 늘었는데도 느리면 파드 수 문제가 아닙니다. 데이터베이스나 외부 연동이 병목일 수 있으니 모니터링 화면에서 확인하십시오(9.2 장).

CronHPA

CronHPA 는 시각 기준으로 파드 수를 바꿉니다. 부하가 오르기 전에 미리 준비할 때 씁니다.

워크로드 > Cron 자동 확장(CHPA) 에서 봅니다.

일정 표기가 CronJob 과 다릅니다. CronJob 은 다섯 자리인데 CronHPA 는 초를 포함한 여섯 자리 입니다. 3.3 장의 표기를 그대로 쓰면 자리가 하나 밀립니다.

CronHPA 일정 표기
특수문자
*모든 값0 0 * * * * = 매시 정각
/간격0 */10 * * * * = 10분마다
,목록0 0 9,18 * * * = 09:00 과 18:00
-범위0 0 9-18 * * * = 09:00 부터 18:00 까지 매시

이 밖에 정해진 일정 대신 쓸 수 있는 표기가 있습니다.

표기
@hourly · @daily · @weekly · @monthly · @yearly매시 정각 · 매일 자정 · 매주 일요일 자정 · 매월 1일 자정 · 매년 1월 1일 자정
@every 1h30m1시간 30분마다
@date 2026-12-25 09:00:00그 날짜·시각에 한 번

@date 는 되풀이하지 않는 일정입니다. 행사나 이벤트처럼 날짜가 정해진 일에 씁니다.

어떨 때 쓰는가

상황왜 CronHPA 인가
업무 시간에만 부하가 몰린다출근 전에 미리 늘려 둡니다. HPA 는 부하가 온 뒤에야 움직입니다
기동이 오래 걸린다자바 애플리케이션처럼 뜨는 데 수 분이 걸리면 HPA 로는 이미 늦습니다
정산·마감처럼 시각이 정해져 있다매월 말일, 매일 새벽 배치 시간에 맞춰 늘립니다
야간·주말에 자원을 줄이고 싶다개발·검증 환경에서 밤에 0 또는 1로 줄여 자원을 아낍니다
행사 일정이 정해져 있다@date 로 시작·종료 시각을 지정합니다
지표로는 부하를 못 읽는다큐 대기열처럼 CPU·메모리에 드러나지 않는 부하

HPA 가 잘 맞지 않는 자리를 메우는 것이 CronHPA 입니다. HPA 는 부하가 오른 뒤 반응하므로 급격히 몰리는 순간에는 이미 느려진 뒤에 늘어납니다.

기본 사용 — 업무 시간에 맞춰 조절

가장 흔한 형태입니다. 평일 업무 시간에 늘리고 그 뒤 줄입니다.

apiVersion: autoscaling.openmaru.io/v1
kind: CronHPA
metadata:
name: app-cronhpa
namespace: my-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
jobs:
- name: scale-up-morning
schedule: "0 50 8 * * 1-5" # 평일 08:50:00
targetSize: 10
- name: scale-down-evening
schedule: "0 0 20 * * 1-5" # 평일 20:00:00
targetSize: 3
- name: weekend-minimum
schedule: "0 0 0 * * 6" # 토요일 00:00:00
targetSize: 2
항목설명
scaleTargetRef조절할 대상. apiVersion·kind·name 세 가지를 모두 적습니다
jobs일정 목록. 하나 이상이어야 합니다
jobs[].name이 CronHPA 안에서 겹치지 않는 이름. 상태 화면에 이 이름으로 나옵니다
jobs[].schedule언제 실행할지
jobs[].targetSize그때 맞출 파드 수. 0 도 넣을 수 있습니다

targetSize 는 "얼마나 늘릴지" 가 아니라 "몇 개로 맞출지" 입니다. 현재 파드 수와 무관하게 그 값으로 맞춥니다.

대상은 scale 조절이 가능한 자원이면 됩니다. Deployment, StatefulSet, ReplicaSet 을 쓸 수 있습니다.

HPA 와 함께 쓰기

CronHPA 를 Deployment 가 아니라 HPA 에 걸면 둘을 함께 쓸 수 있습니다. 이때 CronHPA 는 파드 수를 직접 바꾸는 대신 HPA 의 최소·최대 파드 수를 조절합니다.

apiVersion: autoscaling.openmaru.io/v1
kind: CronHPA
metadata:
name: app-cronhpa-with-hpa
namespace: my-app
spec:
scaleTargetRef:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler # Deployment 가 아니라 HPA 를 가리킵니다
name: my-app-hpa
jobs:
- name: peak-hours
schedule: "0 50 8 * * 1-5" # 평일 08:50 — 바닥을 5로 올림
targetSize: 5
- name: off-hours
schedule: "0 0 20 * * 1-5" # 평일 20:00 — 바닥을 2로 내림
targetSize: 2

동작은 이렇습니다.

시각CronHPA 가 하는 일그 뒤 HPA 가 하는 일
08:50HPA 최소 파드 수를 5로 올립니다부하가 더 오르면 최대까지 스스로 늘립니다
20:00HPA 최소 파드 수를 2로 내립니다부하가 낮으면 2까지 줄입니다

시각 기준으로 바닥을 정하고, 그 위는 HPA 가 실제 부하를 보고 조절합니다. 예측 가능한 부분은 CronHPA 가, 예측할 수 없는 부분은 HPA 가 맡는 구성입니다.

targetSize 가 현재 최대 파드 수보다 크면 최대값도 함께 올라갑니다. 최대를 넘어서는 값을 넣어도 실패하지 않습니다.

한 번만 실행

runOnce: true 를 넣으면 그 일정은 한 번 실행되고 목록에서 사라집니다.

jobs:
- name: one-time-scale-up
schedule: "0 0 9 * * *"
targetSize: 10
runOnce: true

@date 와 함께 쓰면 특정 날짜의 행사에 맞출 수 있습니다.

jobs:
- name: event-start
schedule: "@date 2026-10-03 00:00:00"
targetSize: 20
- name: event-end
schedule: "@date 2026-10-09 00:00:00"
targetSize: 3

특정 날짜에 건너뛰기

excludeDates 에 적은 날에는 모든 일정이 실행되지 않습니다. 공휴일이나 주말에 조절을 멈출 때 씁니다.

spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
excludeDates:
- "* * * * * 6" # 매주 토요일
- "* * * * * 0" # 매주 일요일
- "* * * 1 1 *" # 1월 1일
- "* * * 25 12 *" # 12월 25일
jobs:
- name: scale-up
schedule: "0 50 8 * * *"
targetSize: 5
- name: scale-down
schedule: "0 10 18 * * *"
targetSize: 1

excludeDates 도 크론 표기로 씁니다. 2026-01-01 같은 날짜 형식이 아닙니다. 여섯 자리 표기에서 날짜에 해당하는 자리만 지정하고 나머지는 * 로 둡니다.

제외일에는 늘리기도 줄이기도 하지 않습니다. 위 예에서 금요일 18:10 에 1개로 줄인 뒤 토요일·일요일에는 아무 일도 일어나지 않으므로, 월요일 08:50 까지 1개로 유지됩니다. 주말에도 최소 대수가 필요하면 excludeDates 대신 주말용 일정을 따로 넣으십시오.

상태 확인

Console 의 CronHPA 상세 화면에서 일정별 상태를 봅니다.

상태
Submitted등록되어 다음 실행을 기다립니다
Succeed마지막 실행이 성공했습니다
Failed마지막 실행이 실패했습니다. 사유가 함께 표시됩니다

각 일정마다 마지막 실행 시각다음 실행 예정 시각 이 나옵니다. 의도한 시각과 다르면 아래 시간대 항목을 확인하십시오.

주의할 것

항목내용
일정 표기 자리 수여섯 자리입니다. CronJob 표기(다섯 자리)를 그대로 쓰면 자리가 밀려 엉뚱한 시각에 실행됩니다
시간대컨트롤러의 시간대를 따릅니다. COP 는 기본으로 Asia/Seoul 로 설치합니다. 다른 시간대로 설치했다면 일정 시각도 그 기준입니다
targetSize: 00 을 넣으면 파드가 모두 내려가 서비스가 멈춥니다. 개발·검증 환경에서 야간에 자원을 아낄 때만 쓰십시오
되돌리는 일정을 반드시 함께 넣으십시오늘리는 일정만 두면 계속 그 상태로 남습니다
손으로 바꾼 파드 수는 다음 일정에 덮어써집니다Console 에서 복제본 수를 바꿔도 다음 실행 시각에 targetSize 로 되돌아갑니다
Deployment 에 직접 걸면 HPA 와 다툽니다함께 쓰려면 HPA 를 대상으로 지정하십시오(위 참고)
클러스터 여유를 넘겨 잡지 마십시오늘어난 파드가 Pending 에 머물면 오히려 상황이 나빠집니다

HPA 와 CronHPA 고르기

상황권장
부하가 언제 오를지 예측할 수 없다HPA
매일 같은 시간에 몰린다 (출근 시간, 정산 시간)CronHPA
예열 시간이 길어 부하가 온 뒤 늘리면 늦다CronHPA
야간·주말에 자원을 줄이고 싶다CronHPA
날짜가 정해진 행사가 있다CronHPA (@date)
둘 다 필요하다CronHPA 를 HPA 에 걸어 함께 씁니다(위 "HPA 와 함께 쓰기")

PodDisruptionBudget

PodDisruptionBudget 은 노드 점검 등으로 파드를 옮길 때 동시에 몇 개까지 내려도 되는지 정합니다.

워크로드 > Pod 중단 예산 에서 봅니다.

설정
minAvailable항상 남아 있어야 하는 최소 파드 수
maxUnavailable동시에 내려도 되는 최대 파드 수

둘 중 하나만 설정합니다. 개수 대신 비율(50%)로도 적을 수 있습니다.

설정하지 않으면 점검 중에 모든 파드가 한꺼번에 내려가 서비스가 끊길 수 있습니다. 노드 점검은 예고 없이 진행되기도 하므로 중요한 서비스에는 미리 설정해 두십시오.

너무 엄격하게 잡으면 노드 점검 자체가 진행되지 않습니다. 복제본이 2개인데 minAvailable: 2 로 두면 파드를 하나도 옮길 수 없어 점검이 멈춥니다.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
namespace: my-app
spec:
minAvailable: 2 # 또는 maxUnavailable: 1 (둘 중 하나만)
selector:
matchLabels:
app: my-app # 보호할 파드의 레이블

selectorDeployment 를 가리키는 것이 아니라 파드 레이블을 고릅니다. Deployment 의 spec.selector.matchLabels 와 같은 값을 쓰면 됩니다(3.2 장).

자동 조절을 함께 쓴다면 비율로 적는 편이 안전합니다. 개수로 적으면 파드가 줄었을 때 점검이 막힙니다.

maxUnavailable: 25%

함께 쓸 때 주의할 점

  • HPA 와 CronHPA 를 같은 Deployment 에 각각 걸지 마십시오. 서로 다른 값을 지시해 파드 수가 오르내립니다. 함께 쓰려면 CronHPA 의 대상을 HPA 로 지정 하십시오(위 참고).
  • 자동 조절을 설정한 대상의 복제본 수를 손으로 바꿔도 곧 되돌아갑니다.
  • ArgoCD 로 관리하는 자원에 자동 조절을 걸 때는 설정 저장소의 복제본 수 항목을 빼야 합니다. 그러지 않으면 ArgoCD 가 파드 수를 되돌립니다(4.7 장).
  • 최소값을 1 로 두면 조절 도중 서비스가 잠시 끊길 수 있습니다. 2 이상을 권장합니다.
  • 최대값은 클러스터가 감당할 수 있는 범위로 두십시오. 자원이 모자라면 늘어난 파드가 Pending 에 머물러 오히려 상황이 나빠집니다.