10 AWS 프로덕션 사고가 나에게 가르쳐 준 실전 SRE
I’m happy to translate the article for you, but I need the full text of the article (or the portion you’d like translated) in order to do so. Could you please paste the content you want translated here? Once I have the text, I’ll keep the source line exactly as you provided and translate the rest into Korean while preserving the original formatting.
1️⃣ 3 AM 경보 – 403 오류
증상
- CloudWatch 알람: 4XX 오류 증가.
- 트래픽은 정상으로 보였지만 **≈ 30 %**의 요청이 403을 반환함.
내가 생각한 원인
- API Gateway 제한 또는 IAM 권한 문제.
실제 원인
- 코드 배포가 JWT 검증 로직을 변경함.
- 구버전 모바일 앱(사용자 약 30 %가 여전히 사용)에서 발급된 토큰이 거부되고 있었음.
해결 방법
# Roll back the problematic deployment
aws deploy rollback \
--application-name my-app \
--deployment-group-name prod
# Add backward‑compatible token validation
# (code change – omitted for brevity)
신속한 조치
- 배포를 롤백함.
- 구버전 토큰에 대한 호환성을 추가함.
- 앱 버전 분포를 모니터링하는 CloudWatch 메트릭을 설정함.
2️⃣ 피크 트래픽 시 5XX 급증
증상
- 5XX 오류가 급증하고, 로드밸런서 헬스 체크는 통과.
- **≈ 15 %**의 요청이 실패.
내가 생각한 원인
- 백엔드 서비스가 과부하.
실제 원인
- 트래픽 급증 중 콜드 스타트 때문에 Lambda 함수가 타임아웃되어 API Gateway를 통해 504 Gateway Timeout 반환.
해결 방법
# Enable provisioned concurrency for the hot functions
aws lambda put-provisioned-concurrency-config \
--function-name my-function \
--qualifier $LATEST \
--provisioned-concurrent-executions 100
- API Gateway 통합에 지수 백오프를 구현.
빠른 조치
- 트래픽에 민감한 Lambda에 프로비저닝된 동시 실행을 활성화.
- 동시 실행이 한계에 가까워질 때를 위한 CloudWatch 알람 추가.
3️⃣ 준비되지 않은 보조 리전으로의 Route 53 장애 조치
증상
- 오후 2시에 Route 53 장애 조치가 전체 트래픽을 보조 리전으로 라우팅했으며, 해당 리전은 곧 과부하가 발생했습니다.
내가 생각한 원인
- 기본 리전에 장애가 발생한 것으로 생각했습니다.
실제 원인
- 보안‑그룹 변경으로 Route 53 헬스‑체크 엔드포인트가 차단되었습니다.
- 서비스는 정상였지만 Route 53이 이를 확인할 수 없었습니다.
해결 방법
# Allow Route 53 health‑checker IP ranges
curl https://ip-ranges.amazonaws.com/ip-ranges.json |
jq -r '.prefixes[] | select(.service=="ROUTE53") | .ip_prefix' |
while read cidr; do
aws ec2 authorize-security-group-ingress \
--group-id sg-xxxxxx \
--protocol tcp \
--port 443 \
--cidr "$cidr"
done
# Quick health‑check test
curl -v https://api.example.com/health
신속한 조치
- 보안 그룹에 Route 53 헬스‑체커 IP 범위를 추가했습니다.
- 엔드포인트 접근성 및 실제 서비스 상태를 모두 검증하는 내부 헬스 체크를 구현했습니다.
4️⃣ “Connection Pool Exhausted” 오류 – RDS
증상
- 애플리케이션 로그: “connection pool exhausted”.
- RDS 지표: CPU ≈ 20 %, 연결 수가
max_connections보다 훨씬 낮음.
내가 생각한 원인
- DB의
max_connections를 늘려야 함.
실제 원인
- 예외 발생 후 애플리케이션이 연결을 해제하지 않아 풀에 좀비 연결이 남아 있었음.
해결 방법
# Example context manager to ensure proper cleanup
from contextlib import contextmanager
@contextmanager
def db_cursor(conn):
cur = conn.cursor()
try:
yield cur
finally:
cur.close()
conn.commit()
- 연결 타임아웃 설정, 서킷 브레이커 로직, 풀 상태를 추적하는 CloudWatch 대시보드 추가.
빠른 조치
- 위의 컨텍스트 매니저를 구현함.
- 풀 사용률이 **70 %**에 도달하면 알람을 설정(기존 95 % 대신).
5️⃣ Lambda “Rate Exceeded” Errors During a Batch Job
증상
- 배치 작업을 처리하는 동안 Lambda 함수가 Rate exceeded 오류로 실패했습니다.
- 작업이 완전히 중단되었습니다.
내가 생각한 원인
- AWS 서비스 한도에 도달했다고 생각했습니다.
실제 원인
- 배치 작업이 10 000개의 동시 DynamoDB 쓰기를 백오프 없이 수행하여 몇 초 만에 테이블의 쓰기 용량을 소진했습니다.
해결 방법
import time, random
from botocore.config import Config
def exponential_backoff_retry(func, max_retries=5):
for attempt in range(max_retries):
try:
return func()
except Exception as e:
backoff = (2 ** attempt) + random.random()
time.sleep(backoff)
if attempt == max_retries - 1:
raise e
# Use the built‑in retry config for the AWS SDK
config = Config(
retries={
'max_attempts': 10,
'mode': 'standard'
}
)
빠른 조치
- DynamoDB 쓰기를 재시도 헬퍼로 감쌌습니다.
- 쓰기 용량에 대해 DynamoDB 자동 스케일링을 활성화했습니다.
6️⃣ ALB 정상 인스턴스를 비정상으로 표시
증상
- ALB가 간헐적으로 인스턴스를 비정상으로 표시 → 일부 요청에서 502 오류 발생.
내가 생각한 원인
- 인스턴스가 실제로 부하 하에서 실패하고 있었다.
실제 원인
- 헬스‑체크 간격이 5 s이고 2 s 타임아웃이 설정되어 있었다.
- 짧은 CPU 스파이크가 헬스‑체크 응답을 방해해 잘못된 부정(negative) 헬스 보고가 발생했다.
해결 방법
# Adjust target‑group health‑check settings
aws elbv2 modify-target-group \
--target-group-arn arn:aws:elasticloadbalancing:... \
--health-check-interval-seconds 30 \
--health-check-timeout-seconds 5 \
--healthy-threshold-count 3 \
--unhealthy-threshold-count 3
- 헬스‑체크 엔드포인트를 경량화 (DB 쿼리 없음)했다.
모범 사례
| ✅ 할 일 | ❌ 하지 말아야 할 일 |
|---|---|
프로세스가 살아 있는지만 확인하는 헬스 체크 (예: /ping). | 비용이 많이 드는 작업을 수행하는 헬스 체크 (예: 전체 DB 쿼리). |
신속한 조치
- 헬스‑체크 구성을 업데이트했다.
- 경량
/ping엔드포인트를 배포했다.
7️⃣ 낮은 트래픽 시 P99 지연이 8 초로 급증
증상
- P99 지연이 8 초까지 급증했으며, P50은 조용한 기간 동안 200 ms를 유지했습니다.
내가 생각한 원인
- 백엔드 데이터베이스 성능 저하.
실제 원인
- Lambda 콜드 스타트. 함수가 유휴 기간 동안 종료되어 다음 요청 시 긴 시작 시간이 발생했습니다.
해결 방법
# 지연에 민감한 함수에 프로비저닝된 동시성 활성화
aws lambda put-provisioned-concurrency-config \
--function-name api-handler \
--qualifier $LATEST \
--provisioned-concurrent-executions 200
# EventBridge 일정(5분마다 실행)으로 함수를 따뜻하게 유지
aws events put-rule \
--name WarmLambdaRule \
--schedule-expression "rate(5 minutes)"
- 배포 패키지 크기를 ≈60 % 감소시켰습니다(사용하지 않는 라이브러리 제거).
신속한 조치
- 사용자‑대면 API에 프로비저닝된 동시성을 적용했습니다.
- 주기적인 “핑” 호출을 예약했습니다.
- 패키지 크기를 최적화했습니다.
8️⃣ DynamoDB ProvisionedThroughputExceededException 발생 보고서 생성 중
증상
- 쓰기는 성공했지만 일일 보고서 생성 중 ProvisionedThroughputExceededException 로 읽기가 실패했습니다.
내가 생각한 원인
- 읽기 용량 단위를 늘려야 한다.
실제 원인
- 보고서에서 페이지네이션 없이 Scan 작업을 사용해 핫 파티션이 발생했고, 몇 초 만에 모든 읽기 용량을 소모했습니다.
해결 방법
def paginated_query(table, key_condition):
items = []
last_evaluated_key = None
while True:
if last_evaluated_key:
response = table.query(
KeyConditionExpression=key_condition,
ExclusiveStartKey=last_evaluated_key
)
else:
response = table.query(
KeyConditionExpression=key_condition
)
items.extend(response["Items"])
last_evaluated_key = response.get("LastEvaluatedKey")
if not last_evaluated_key:
break
return items
- 가능한 경우 Query 로 전환했습니다.
- 페이지네이션과 지수 백오프를 구현했습니다.
- DynamoDB 자동 스케일링을 활성화하고 효율적인 접근 패턴을 위해 복합 정렬 키를 추가했습니다.
빠른 조치
- 위의 페이지네이션 쿼리를 사용하도록 보고서 작업을 리팩터링했습니다.
- 테이블에 자동 스케일링을 켰습니다.
9️⃣ 과도한 헬스‑체크로 인한 오탐
- 지나치게 공격적인 헬스‑체크 간격은 정상인 인스턴스를 비정상으로 표시할 수 있습니다.
- 균형: 실제 장애를 포착할 만큼 충분히 자주 수행하되, 일시적인 스파이크가 오경보를 일으키지 않을 정도로 조절합니다.
🔟 일반 교훈 및 요점
| 사건 | 핵심 교훈 |
|---|---|
| 1 – JWT validation | 버전 호환성이 중요합니다; 롤아웃 시 항상 구버전 클라이언트를 지원하세요. |
| 2 – Lambda cold starts | 프로비저닝된 동시성 + 워밍‑업 스케줄이 지연 스파이크를 완화합니다. |
| 3 – Route 53 health checks | 보안‑그룹 규칙이 헬스‑체커 IP 범위를 허용해야 합니다. |
| 4 – DB connection pools | 적절한 정리를 강제하고, 포화 상태에 도달하기 전에 풀 사용량을 모니터링하세요. |
| 5 – DynamoDB rate limits | 첫 날부터 지수 백오프와 재시도를 구현하세요. |
| 6 – ALB health checks | 헬스‑체크 엔드포인트를 가볍게 유지하고, 라우팅 체크와 깊은 체크를 분리하세요. |
| 7 – P99 latency | 콜드 스타트가 꼬리 지연을 지배하므로, 프로비저닝된 동시성이 해답입니다. |
| 8 – DynamoDB hot partitions | Scan보다 Query를 선호하고, 페이지네이션을 사용하며, 키 분포를 고르게 설계하세요. |
| 9 – Aggressive health checks | 너무 짧은 간격은 오탐을 유발하므로, 임계값과 타임아웃을 조정하세요. |
| 10 – (Overall) | 관측성 우선 – 인스트루멘테이션, 알람, 가정을 테스트하여 사고가 되기 전에 대비하세요. |
각 사건을 학습 기회로 삼고, 체계적이고 관측 가능한 해결책을 적용하면 혼란스러운 운영 대응을 예측 가능하고 회복력 있는 프로세스로 전환할 수 있습니다.
Incident 1 – Blue‑Green 배포 중 502 오류
증상
- **5 %**의 요청이 매 배포 시 502 Bad Gateway 오류와 함께 실패했습니다. Blue‑Green 배포 전략을 사용했음에도 불구하고 발생했습니다.
초기 가설
- 인스턴스가 너무 빨리 종료되고 있었습니다.
근본 원인
- ALB의 연결‑드레인 타임아웃(등록 해제 지연)이 30 초로 설정되어 있었지만, 일부 API 호출은 60 초까지 걸렸습니다.
- ALB가 요청 중에 해당 연결을 종료하면서 502 오류가 발생했습니다.
해결 방법
# 연결‑드레인 타임아웃(등록 해제 지연) 증가
aws elbv2 modify-target-group-attributes \
--target-group-arn arn:aws:elasticloadbalancing:region:account-id:targetgroup/name/xxxxxxxxxxxx \
--attributes Key=deregistration_delay.timeout_seconds,Value=120
- 배포 중에 진행 중인 요청이 삭제되지 않았는지 확인하는 배포 건강‑검사를 추가했습니다.
신속히 수행한 조치
- 등록 해제 지연 시간을 늘렸습니다.
- 애플리케이션에 우아한 종료 루틴을 구현했습니다(새 요청 수락 중단, 기존 요청 완료).
- 배포 전 검증 단계를 추가했습니다.
교훈
- 연결‑드레인 타임아웃은 가장 긴 요청 지연 시간보다 길어야 합니다.
- P99 지연 시간을 정기적으로 모니터링하고 그에 맞게 타임아웃을 설정하세요.
사건 2 – 배포 스크립트가 보안 그룹을 일관되지 않게 남김
증상
- 배포 스크립트가 중간에 실패하여 보안 그룹이 일관되지 않은 상태로 남음.
- 인스턴스에 SSH 접속이 불가능하고 배포를 롤백할 수 없음.
내가 생각한 것
- 보안 그룹을 수동으로 수정한다.
실제 원인
- 자동화 스크립트에 롤백 메커니즘이 없었으며 테스트 없이 프로덕션 보안 그룹을 변경함.
해결 방법
# Open a Session Manager session to the affected instance
aws ssm start-session --target i-1234567890abcdef0
-
현재 보안 그룹을 확인 (참고용).
-
원자적으로 변경 – 예: 필요한 규칙을 추가:
aws ec2 authorize-security-group-ingress \ --group-id sg-12345 \ --ip-permissions IpProtocol=tcp,FromPort=443,ToPort=443,IpRanges='[{CidrIp=0.0.0.0/0}]' -
변경이 정상적으로 적용됐는지 검증.
-
검증이 성공한 후에만 기존 규칙을 제거.
더 나은 접근법
- AWS CloudFormation(또는 기타 IaC 도구)으로 보안 그룹을 관리하여 원자적이고 버전‑관리된 업데이트를 보장한다.
신속히 취한 조치
- 모든 인스턴스에 Systems Manager Session Manager를 활성화.
- 보안 그룹 관리를 CloudFormation으로 전환.
- 변경 승인 워크플로우를 구현.
교훈
- 프로덕션에서 보안 그룹을 수동으로 수정하면 안 된다. 한 번의 실수로 접근이 차단될 수 있다.
- Infrastructure‑as‑Code와 Session Manager를 안전망으로 활용하라.
이를 쉽게 만드는 도구들
When incidents happen, speed matters. I built an Incident Helper script that automates the repetitive parts of incident response:
- Collects relevant CloudWatch logs.
- Checks service health status.
- Identifies common AWS misconfigurations.
실제 교훈
- Document 모든 사고를 기록합니다.
- runbooks 를 작성하고 유지합니다.
- 정기적으로 fail‑over 절차를 테스트합니다.
- 팀과 함께 주간 사후 검토 회의를 진행합니다.
다음 사고는 이미 예정되어 있습니다; 언제 일어날지는 모를 뿐입니다.
준비가 되어 있으면 모든 차이를 만들 수 있습니다.