infra
Platform

모듈 맵

[Cloud] 오토스케일링 + 로드밸런서 — 탄력성의 실제

0 / 22 완료

펼치기
0 / 22 완료0%

클라우드 엔지니어링 · 05 / 22

[Cloud] 오토스케일링 + 로드밸런서 — 탄력성의 실제

수요에 따라 인스턴스를 자동으로 늘리고 줄이는 오토스케일링과, 트래픽을 여러 인스턴스로 분산하고 죽은 인스턴스를 빼는 로드밸런서를 함께 정리합니다

🚨INCIDENT ALERT
HIGH

이벤트 당일 오전 10시, 트래픽이 평소 30배로 치솟습니다. 인스턴스 한 대는 CPU 100%로 헉헉대다 다운, 사용자는 에러 화면을 봅니다. 반대로 새벽 3시엔 그 큰 인스턴스가 1% 부하로 돈만 먹습니다. 한 대 고정으로는 피크에 죽고 평소엔 낭비합니다. 오토스케일링과 로드밸런서는 "필요한 만큼 자동으로, 죽은 건 알아서 빼고"를 만들어 줍니다.

이번 챕터에서 배울 것
  • 1로드밸런서가 트래픽 분산과 헬스체크로 무엇을 해주는지 안다
  • 2오토스케일링 그룹이 지표 기반으로 늘고 주는 원리를 설명할 수 있다
  • 3오토스케일링의 전제인 '무상태' 설계의 이유를 안다
  • 4헬스체크 경로 설계가 왜 중요한지 예로 들 수 있다
  • 5탄력성이 가용성·비용에 동시에 기여하는 구조를 이해한다

분산과 자동 증감, 두 축

💡개념

로드밸런서 — 단일 진입점 + 죽은 놈 빼기

로드밸런서는 사용자에게 하나의 주소를 주고, 뒤에 있는 여러 인스턴스로 트래픽을 나눕니다. 동시에 각 인스턴스에 주기적으로 헬스체크를 보내, 응답 없는 인스턴스는 라우팅에서 빼고 복귀하면 다시 넣습니다. 그래서 인스턴스 한 대가 죽거나 배포 중이어도 사용자는 거의 모릅니다.

L7(애플리케이션) 로드밸런서는 URL 경로·호스트로 라우팅(/api는 이쪽, /img는 저쪽)까지 합니다.

💡개념

오토스케일링 그룹 — 지표를 보고 머릿수를 조절

오토스케일링 그룹(ASG)은 "최소 2대, 최대 10대, 평균 CPU 50% 목표" 식으로 정책을 둡니다. 부하가 올라 임계치를 넘으면 scale-out(추가), 내려가면 scale-in(제거)합니다. 새 인스턴스는 검증된 AMI(가상 서버(EC2))로 동일하게 찍어내고, LB가 헬스체크 통과 후 트래픽에 합류시킵니다.

핵심 전제: 인스턴스는 언제 추가·제거돼도 안전해야 합니다 — 즉 무상태여야 합니다.

💡개념

부하가 오르면 인스턴스가 어떻게 늘고 트래픽이 분산되나 — 요청부터 스케일까지 6단계

LB 주소로 요청 하나가 들어온 순간부터, 그 부하가 쌓여 새 인스턴스가 뜨고 트래픽을 나눠 받기까지는 여러 단계를 거칩니다. 이 흐름을 알면 "왜 스케일이 느리지", "왜 늘었다 줄었다 하지", "배포하면 왜 다 빠지지"를 각각 다른 단계의 문제로 좁힐 수 있습니다. 로드밸런서(분산)와 오토스케일(증감)이 실제로는 하나의 파이프라인으로 맞물려 돈다는 점이 여기서 드러납니다.

TEXT
[사용자]  요청 → LB의 단일 주소(DNS)
   │
   ① LB 수신 → 헬스체크 통과한 대상에만 분산
   │
   ② 오토스케일이 지표 관측        (평균 CPU · 요청수 · 큐 길이)
   │
   ③ 임계 초과 → 스케일아웃 결정    (desired 용량 +1 …)
   │
   ④ 새 인스턴스 기동 · 워밍업      (AMI로 부팅 → 앱 기동)
   │
   ⑤ 헬스체크 통과 → 대상 그룹 등록 → 트래픽 합류
   │
   ▼
   ⑥ 부하 감소 → 스케일인(축소)     (드레이닝 후 종료)

각 단계에서 무슨 일이 일어나고, 막히면 어떤 증상인가:

단계하는 일여기서 막히면
① LB 분산헬스체크를 통과한 대상에만 요청을 나눠 보낸다헬스체크 경로·임계가 틀리면 정상 인스턴스를 오판해 빼거나(전부 빠짐) 죽은 인스턴스에 계속 보냄
② 지표 관측평균 CPU·요청수·큐 길이 같은 지표를 주기적으로 수집수집·집계 주기만큼 반응이 늦어 급증에 한 박자 뒤진다
③ 스케일 결정지표가 임계를 넘으면 desired 용량을 올린다임계·쿨다운이 민감하면 늘렸다 줄였다 반복(플래핑)
④ 기동·워밍업새 인스턴스를 AMI로 부팅하고 앱이 뜰 때까지 준비기동에 수 분 걸려 순간 스파이크를 못 따라잡음(예측 스케일·여유 용량 필요)
⑤ 등록헬스체크 통과 후 대상 그룹에 넣어 트래픽 합류시작 유예(grace period) 부족 → 준비 전 트래픽 유입·롤링 폭주
⑥ 스케일인부하가 낮아지면 드레이닝 후 인스턴스 종료드레이닝 없이 즉시 종료하면 진행 중 요청이 끊긴다

핵심은 오토스케일이 '즉시'가 아니라 '관측 → 결정 → 기동 → 등록'의 파이프라인이라는 점입니다. 각 단계가 초~분 단위 지연을 더하므로, 갑작스런 스파이크는 예측 스케줄·여유 용량으로 미리 받아야 하고, 헬스체크(①·⑤)나 쿨다운(③)이 잘못되면 스케일 장치 자체가 플래핑·롤링 폭주 같은 사고를 만듭니다. 'unhealthy가 계속된다'(①·⑤), '트래픽은 그대로인데 인스턴스만 는다'(②③의 오판)를 단계로 나눠 보면 원인 구간이 좁혀집니다.

로드밸런서 + 오토스케일링 그룹 — LB가 트래픽을 ASG의 인스턴스들에 분산하고, ASG는 CPU 등 지표로 인스턴스를 자동 증감(scale-out/in). 새 인스턴스는 LB 헬스체크 통과 후 트래픽을 받고, 비정상 인스턴스는 교체. 트래픽 변화에 자동으로 용량을 맞추고 장애 인스턴스를 자가 치유확대

오토스케일링 정책 — CPU 지표 기반 확장·축소확대 위 그림처럼 CPU가 70%를 넘으면 Scale-Out, 30% 아래로 내려가면 Scale-In이 트리거됩니다. 쿨다운 설정으로 과민 반응을 방지합니다.

헬스체크 — LB가 살아있는 인스턴스만 선택한다확대 위 그림처럼 연속 실패한 인스턴스는 LB 풀에서 제외되고, 복구 후 연속 성공하면 자동으로 재등록됩니다.

💡개념

왜 무상태(stateless)가 필수인가

scale-in은 인스턴스를 죽입니다. 그 인스턴스 로컬에 세션이나 업로드 파일이 있었다면 함께 사라집니다. 다른 인스턴스는 그 세션을 모르니 사용자는 로그아웃됩니다. 그래서:

  • 세션 → 외부 캐시/DB(예: Redis)에 저장
  • 업로드 파일 → 오브젝트 스토리지(오브젝트·블록·파일 스토리지)에 저장
  • 인스턴스는 "아무 때나 죽여도 되는 일회용"으로

이 원칙을 지키면 인스턴스 수를 자유롭게 조절할 수 있습니다.

왜 무상태(stateless)가 필수인가 — 왼쪽은 상태를 인스턴스 로컬에 둔 나쁜 경우로, scale-in이 Instance A를 죽이면 A의 로컬 세션·업로드가 함께 사라지고 다른 인스턴스는 그 세션을 몰라 사용자가 로그아웃된다. 오른쪽은 상태를 외부로 뺀 좋은 경우로, 인스턴스는 무상태 일회용이 되고 세션은 외부 캐시/DB(Redis)에·업로드 파일은 오브젝트 스토리지(S3)에 두어 공유한다. 그러면 어느 인스턴스가 죽어도 사용자는 다른 인스턴스에서 같은 세션·파일을 그대로 본다. 무상태는 수평 확장의 전제로, 이 원칙을 지켜야 오토스케일로 인스턴스 수를 자유롭게 조절할 수 있으며, 상태가 로컬에 묶이면 scale-in이 곧 데이터 유실·세션 끊김 사고가 된다확대

스케일링 정책 — 무엇을 기준으로
부하가 불규칙·예측 어려움지표 기반(목표 추적)CPU/요청수 목표치 유지
매일 같은 시간 트래픽 급증(출근·점심)스케줄 기반예측된 시점에 미리 증설
큐 작업량에 비례하는 워커큐 길이 기반대기 메시지 수로 워커 수 조절
급증에 즉시 대응 + 비용 절감 병행스케줄+지표 혼합베이스는 스케줄, 변동은 지표
1대상 그룹 헬스체크 상태 확인

LB 뒤 인스턴스들이 healthy인지 확인합니다. 배포·스케일 직후 unhealthy가 오래 남으면 헬스체크 설정을 의심합니다.

로컬 터미널
aws elbv2 describe-target-health --target-group-arn "$TG_ARN" \
  --query "TargetHealthDescriptions[].{Id:Target.Id,State:TargetHealth.State}" --output table
OUTPUT
+----------------------+-----------+
|  i-0aaa...           |  healthy  |
|  i-0bbb...           |  healthy  |
|  i-0ccc...           |  unhealthy|   ← 조사 대상
+----------------------+-----------+
aws elbv2 describe-target-health
2오토스케일링 그룹의 현재/목표 용량 확인

ASG가 최소·최대·희망 용량 사이에서 어떻게 동작 중인지 봅니다.

로컬 터미널
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names web-asg \
  --query "AutoScalingGroups[0].{Min:MinSize,Max:MaxSize,Desired:DesiredCapacity,InService:length(Instances)}"
OUTPUT
{ "Min": 2, "Max": 10, "Desired": 4, "InService": 4 }
aws autoscaling describe-auto-scaling-groups
🔍실행 후 확인할 것
  • describe-target-health에 unhealthy가 지속되는 인스턴스 — 앱 미기동인지(진짜 문제) 헬스체크 경로/타임아웃이 빡센지(오판) 구분
  • DesiredCapacity vs InService 수 일치 여부 — 불일치면 인스턴스 기동 실패·헬스체크 탈락 반복(롤링 폭주) 의심
  • scale 이벤트 로그의 빈도 — 짧은 시간에 늘었다 줄었다 반복(flapping)하면 임계치·쿨다운이 너무 민감. 쿨다운 늘리기
  • scale-in 시 사용자 로그아웃/업로드 유실 신고 — 상태가 인스턴스 로컬에 남아 있다는 신호. 외부 저장소로 분리

상황: 새 인스턴스가 헬스체크를 통과 못 해 LB가 빼고, ASG가 죽이고 또 띄우는 루프.

원인: ① 헬스체크 경로(/health)가 앱 준비 전에 호출됨(기동 시간 < 체크 시작), ② 경로가 200을 안 줌(앱 버그/포트 불일치), ③ 보안그룹이 LB→인스턴스 헬스체크 포트를 안 허용.

진단: 인스턴스에 직접 들어가 curl localhost:<port>/health 응답 확인 → LB 대상그룹 헬스체크 경로·포트·정상 임계 확인 → 보안그룹에서 LB SG로부터의 인바운드 허용 확인.

해결: 헬스체크에 시작 유예(health check grace period) 를 둬 기동 시간을 확보. 경로를 가볍고 정확한 /health로. 보안그룹에 LB로부터의 헬스체크 포트 인바운드 추가. 헬스체크 설계는 SLO·에러버짓·포스트모템의 가용성 측정과도 연결됩니다.

심화 — 늘리는 것보다 줄이는 것, 그리고 의심하는 것

💡개념

심화: 스케일 인의 규칙 — 누구를, 언제, 어떻게 내리는가

scale-out은 더하기지만 scale-in은 골라서 빼기입니다. 아무 인스턴스나 즉시 죽이면 진행 중인 작업이 함께 사라지므로, ASG에는 '내리는 쪽'을 위한 장치가 따로 있습니다.

  • 종료 정책(termination policy): 기본값은 ① AZ 간 인스턴스 수 균형을 맞추는 방향에서 ② 가장 오래된 시작 템플릿(구성)의 인스턴스를 먼저 고릅니다. 배포 후 신·구 구성이 섞여 있으면 구버전부터 자연스럽게 정리되는 효과가 있습니다.
  • scale-in 보호(instance protection): "이 인스턴스는 빼지 마라"는 표시입니다. 긴 배치 작업을 처리 중인 워커가 중간에 잘리면 안 될 때, 작업 시작 시 보호를 켜고 끝나면 푸는 패턴으로 씁니다.
  • 라이프사이클 훅(lifecycle hook): 종료 직전 인스턴스를 Terminating:Wait 상태로 붙잡아 마무리 시간을 줍니다 — 버퍼에 남은 로그 전송, 처리 중이던 큐 메시지 완료, 커넥션 정리. 연결 드레이닝이 LB 관점의 배웅이라면, 훅은 인스턴스 자신의 뒷정리 시간입니다. 기동 쪽 훅도 있어 웜업·캐시 예열에 씁니다.

이 장치들 없이 scale-in을 켜면 "줄어들 때마다 어디선가 로그와 작업이 사라지는" 시스템이 됩니다. 무상태 설계가 전제라면, 이 규칙들은 마무리입니다.

상황: 전날 저녁 배포 후 밤사이 scale-out이 연쇄로 발생. LB의 요청 수(RequestCount)는 평소와 같은데 모든 인스턴스의 CPU가 90%대라 ASG는 계속 증설했고, 최대치에 도달한 채 아침을 맞았습니다. 서비스는 멀쩡해 보여 알림도 없었습니다.

원인: 배포 코드에 들어간 재시도 폭주 버그. 외부 API 호출이 실패하면 대기 없이 무한 재시도하는 루프가 CPU를 태웠습니다. 오토스케일링은 이것을 장애가 아니라 '부하'로 해석해 돈으로 증상을 덮었습니다 — 자동 복구 장치가 버그의 은폐 장치가 된 셈입니다.

진단: 요청 수는 평평한데 인스턴스 수만 상승하는 구간을 확인(요청당 CPU 비용이 갑자기 뛴 것) → 인스턴스 수 증가가 시작된 시각과 배포 시각 대조 → 앱 로그에서 동일 요청의 재시도 반복 확인.

해결: ① 롤백으로 원인 제거 ② 재시도에 지수 백오프와 최대 횟수 도입 ③ '최대 용량 도달'과 '요청 수 대비 인스턴스 수 비율 급변'에 알림을 겁니다(관측과 거버넌스). 오토스케일링은 버그를 조용히 흡수할 수 있으므로, 스케일 이벤트 자체를 관측 대상으로 둬야 비용으로 배우는 일을 막습니다.

💼
실무 맥락
현업 패턴

면접 단골: "트래픽이 급증하면 어떻게 대응하나요?" → "오토스케일링 그룹으로 지표 기반 증설하고 앞에 로드밸런서를 둔다. 단, 앱을 무상태로 만들어 세션은 외부 캐시, 파일은 오브젝트 스토리지에 둔다"가 좋은 답입니다.

실무 함정: 오토스케일링은 만능이 아닙니다. 인스턴스 기동에 수 분이 걸리면 갑작스런 스파이크는 못 따라잡습니다(예측 스케일링·여유 용량 필요). 또 DB가 병목이면 웹 인스턴스만 늘려도 소용없습니다 — 병목 지점을 먼저 찾아야 합니다(관리형 데이터베이스(RDS)).

관련 모듈로 더 깊이:

  • 가상 서버(EC2) — 오토스케일링이 늘렸다 줄이는 대상인 가상 서버 자체
  • VPC와 서브넷 — 로드밸런서·인스턴스가 사는 네트워크와 퍼블릭/프라이빗 서브넷
  • 관측과 거버넌스 — 스케일링 판단의 근거가 되는 지표·관측 체계

다음 모듈에서는 이 인스턴스·LB가 사는 네트워크 자체 — VPC·서브넷·라우팅·게이트웨이 로 들어가, 퍼블릭과 프라이빗을 어떻게 나누는지 다룹니다.

지식 확인

퀴즈 — 8문제

Q1

로드밸런서(LB)의 핵심 역할로 가장 정확한 것은?

Q2

오토스케일링 그룹(ASG)이 인스턴스를 늘리고 줄이는 기준으로 흔히 쓰는 것은?

Q3

오토스케일링이 제대로 동작하려면 인스턴스(애플리케이션)가 갖춰야 할 성질은?

Q4

헬스체크(health check) 경로를 잘못 설정하면 생기는 문제는?

Q5

로드밸런서와 오토스케일링 그룹을 함께 쓰면 새로 늘어난 인스턴스가 자동으로 트래픽을 받게 되는 이유는?

Q6

스케일 인(축소)으로 인스턴스를 종료할 때 진행 중이던 요청이 끊기지 않게 하려면?

Q7

[심화] scale-out은 더하기지만 scale-in은 골라서 빼기다. 종료 직전 인스턴스를 붙잡아 버퍼에 남은 로그 전송·처리 중이던 큐 메시지 완료 같은 '인스턴스 자신의 뒷정리' 시간을 주는 장치는?

Q8

[심화] 트래픽(LB 요청 수)은 평소 수준인데 밤사이 ASG가 최대 20대까지 증설된 채 붙어 있고, 모든 인스턴스의 CPU가 90%대다. 원인을 좁히기 위해 가장 먼저 대조할 것은?

0 / 8 답변

🧪 실습으로 확인하기

GCP 오토스케일링 — MIG·헬스체크·스케일 정책 진단

중급

트래픽이 늘어도 인스턴스가 안 늘어난다. 관리형 인스턴스 그룹(MIG)의 오토스케일러가 동작하려면 (1) 오토스케일러 설정(목표 지표·min/max), (2) 헬스체크, (3) LB 연결이 맞물려야 한다. 현재 스케일 정책을 진단하고, CPU/부하 기준 스케일 정책을 바로잡고, 부하를 줘서 실제로 스케일 아웃·인 되는지 검증한다.

45📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요