1 SRE 5축
1. Capacity Planning - 미래 부하·peak·burst 대비
2. SLO·SLI - 목표·측정·burn rate
3. Incident Response - 등급별 대응 절차·escalation
4. Toil Reduction - 반복 수작업 자동화
5. Disaster Recovery - 큰 장애·데이터 손실 복구
각 축이 다른 시간 척도와 다른 사람 부담: - Capacity·DR: 분기 단위·드물게 큰 작업 - SLO·Toil: 매일·매주 점진 개선 - Incident: 즉각 대응·후 회고
2 SLO vs SLA vs SLI
용어 혼용이 많아 명확히:
| 용어 | 정의 | 예 |
|---|---|---|
| SLI (Indicator) | 측정 지표 | p95 latency·success rate·thumbs_up rate |
| SLO (Objective) | 내부 목표 | p95 latency ≤ 3s (99% of 30d) |
| SLA (Agreement) | 외부 계약·법적 의무 | “99.9% uptime, 위반 시 환불” |
SLI < SLO ≤ SLA
↑ ↑ ↑
실측 내부 외부 계약
내부 SLO가 외부 SLA보다 strict — 외부 계약 위반 전에 내부 알림 시간 확보.
3 Capacity Planning
미래 부하 예측 → 인프라 사이즈 결정.
# scripts/capacity_plan.py
def project_load(growth_rate: float = 1.5, months: int = 6) -> dict:
current = current_metrics()
return {
f"month_{i}": {
"qps": current["qps"] * (growth_rate ** (i/12)),
"tokens_per_sec": current["tokens"] * (growth_rate ** (i/12)),
"concurrent_users": current["users"] * (growth_rate ** (i/12)),
}
for i in range(1, months + 1)
}3.1 Peak·Burst 분리
Average Load : 100 qps (일반)
Peak Hour : 300 qps (매일 오후 2~4시)
Daily Burst : 800 qps (분기 발표 후 30분)
Disaster Burst : 3000 qps (외부 사건 — incident 보고)
각 시나리오별 다른 인프라 전략: - Average: 평균 사이즈 - Peak: 시간별 auto-scale - Daily Burst: queue + backpressure 우선 - Disaster Burst: degraded 모드 (LLM 호출 줄이고 cache 응답 우선)
3.2 한도 결정
# config/capacity.yaml
infrastructure:
llm_concurrent:
soft_limit: 100 # 일반 운영
hard_limit: 200 # 비상
hard_limit_alert: warn # 100% 가까이면 알림
vector_search_qps:
soft: 500
hard: 1500
postgres_connections:
pool: 50
max: 100
scaling_targets:
cpu_utilization: 70 # 평균 CPU 70%면 scale-up
request_queue_depth: 100C25 Bulkhead 패턴이 인프라 차원 — 의존별 pool로 격리.
4 부하 관리
4.1 Auto-scaling
# Kubernetes HPA 예시
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
minReplicas: 3
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Pods
pods:
metric:
name: llm_request_queue_depth
target:
type: AverageValue
averageValue: "10"CPU만 보면 LLM-heavy workload에서 부정확 — request queue depth 같은 application-level 메트릭 추가.
4.2 Rate Limiting
# app/ops/rate_limit.py
import redis
class TokenBucket:
"""per-user·per-tenant rate limit."""
def __init__(self, redis_client, key: str, capacity: int, refill_per_sec: float):
self.redis = redis_client
self.key = key
self.capacity = capacity
self.refill = refill_per_sec
async def consume(self, n: int = 1) -> bool:
# Lua script for atomic operation
result = await self.redis.eval(LUA_SCRIPT, 1, self.key, self.capacity, self.refill, n)
return result == 1
# 사용
async def handle_query(query: Query):
user_bucket = TokenBucket(redis, f"rl:user:{query.user_id}", capacity=60, refill_per_sec=1)
if not await user_bucket.consume():
raise RateLimitExceeded()
...4.3 Backpressure
# 큐 깊이가 임계 초과면 새 요청 거부
async def check_backpressure():
queue_depth = await redis.llen("query_queue")
if queue_depth > MAX_QUEUE_DEPTH:
return False
return True
@app.post("/run")
async def run(query: Query):
if not await check_backpressure():
raise HTTPException(503, "system overloaded — try again")
...빠른 503보다 무한 대기가 사용자 경험 더 나쁨. Backpressure는 빠른 실패 원칙.
5 Incident Response
5.1 4 등급
| 등급 | 정의 | 응답 시간 | 알림 |
|---|---|---|---|
| P1 | 전체 down·데이터 누출·SLA 직접 위반 | 즉시 (< 15분) | 모든 on-call page + lead 호출 |
| P2 | 한 도메인 down·심각한 품질 회귀 | 1시간 내 | Domain on-call + Platform |
| P3 | 부분 영향·SLA 임박 | 4시간 내 | Slack channel |
| P4 | 운영 부담·미세 회귀 | 영업일 | Ticket·daily 회의 |
5.2 Incident Lifecycle
[탐지]
├── 자동 alert (SLO burn rate)
├── 사용자 신고 (support ticket)
└── 사람 운영 (점검 중 발견)
↓
[Acknowledge] (on-call이 받음)
↓
[Triage]
├── 등급 결정 (P1~P4)
├── Incident commander 지정
└── war room (P1·P2)
↓
[Mitigate] (사용자 영향 줄이기)
├── Kill Switch (C25)
├── Rollback (C26)
├── Traffic shift (Bandit·canary 강제)
└── Degraded mode
↓
[Resolve] (근본 원인 해결)
↓
[Post-mortem] (5 영업일 내 작성)
↓
[Action Items] (회귀 방지)
5.3 Incident Commander
P1·P2 incident마다 한 사람이 IC — 결정 속도 + 명확한 책임:
# Slack에 자동 IC 지정
@incident_handler.on_p1
def assign_ic(incident):
on_call = get_current_on_call()
notify(channel="#incident",
message=f"P1 incident — IC: @{on_call.name}, war room: {incident.url}")IC 책임: - 결정 (rollback·kill switch·escalate) - 의사소통 (status update 30분마다) - 사후 — post-mortem 리드
6 Post-mortem
# Post-mortem — Incident I-2026-04-23
## 요약
2026-04-23 14:30~15:42, 모든 사용자에 응답 latency p95 > 30s. 약 3,200 query 영향.
## 시간선
- 14:32 SLO burn rate alert (p95 latency)
- 14:35 IC @kim 지정, war room 시작
- 14:40 root cause 추정: vector store CPU saturation
- 14:45 Mitigate — vector store auto-scale max 강제
- 15:10 latency 정상 복귀
- 15:42 incident close
## Root Cause
Vector store가 5x 트래픽 spike에 auto-scale 따라가지 못함. 새 collection 도입 후 인덱스가 4× 커진 것이 underlying.
## What Went Well
- Alert가 4분 만에 트리거
- IC 결정 빠름 (15분 내 mitigate)
## What Went Wrong
- Auto-scale max가 너무 낮음 (사전 capacity planning 누락)
- 새 collection 영향 사전 추정 안 함
## Action Items
- [ ] Vector store auto-scale max 4×로 (kim, 2 days)
- [ ] 새 collection 도입 절차에 capacity 영향 추정 추가 (han, 1 week)
- [ ] Vector store CPU saturation alert 별도 (lee, 3 days)
## Blameless 원칙
사람이 아닌 시스템·절차 문제로 분석. "왜 이 사람이 안 했는가" 대신 "왜 시스템이 알람을 울리지 않았는가".Blameless culture가 핵심 — 비난하면 다음 incident 시 정보 숨김. 사실 발견·시스템 개선만 집중.
7 Toil Reduction
Toil = 반복적·자동화 가능한 수작업. 운영팀의 50%+가 toil이면 위험 신호.
# scripts/toil_audit.py
TOIL_INDICATORS = [
"수동 service restart",
"수동 cache invalidation",
"수동 user permission 변경",
"수동 stale data cleanup",
"수동 SSL cert 갱신",
...
]
def quarterly_toil_audit():
on_call_logs = load_oncall_logs(period="quarter")
toil_pct = count_matching(on_call_logs, TOIL_INDICATORS) / len(on_call_logs)
if toil_pct > 0.5:
alert("toil ratio > 50% — 자동화 우선순위")
return toil_pct7.1 Toil → 자동화 사례
| 수작업 | 자동화 |
|---|---|
| 수동 stale doc cleanup | C31 retention cron |
| 수동 user permission 변경 | RBAC + IdP sync |
| 수동 cache invalidation | event-driven (source webhook) |
| 수동 service restart | health check + auto restart |
| 수동 cost spike 점검 | cost burn rate alert |
| 수동 incident IC 지정 | rotation + auto Slack assign |
분기마다 — 가장 부담 큰 toil 1~3개 자동화.
8 Chaos Engineering
운영 중 의도적 실패 주입 — 시스템이 회복하는지 검증.
# scripts/chaos.py — staging 환경
async def chaos_experiments():
# 1. LLM provider 5분 down
await inject_failure(target="openai_api", duration_sec=300)
assert system_falls_back_to_anthropic()
# 2. Vector store 50% latency 추가
await inject_latency(target="vector_store", added_ms=2000, duration_sec=600)
assert circuit_breaker_trips()
# 3. 한 collection 전체 down
await disable_collection("finance_internal")
assert search_returns_fallback()분기마다 staging에서 — 운영 전 회귀 catch. Production은 careful (사용자 영향 큼).
9 Disaster Recovery
9.1 RTO·RPO
RTO (Recovery Time Objective) - 얼마나 빨리 복구해야 하는가
RPO (Recovery Point Objective) - 얼마나 많은 데이터 손실을 허용하는가
9.2 Backup 전략
| 데이터 | 빈도 | 보존 |
|---|---|---|
| Postgres | 매시간 + 매일 full | 30일 |
| Vector store | 매일 | 30일 |
| Audit log | 실시간 (S3 versioning) | 영구 |
| Config | git (영구) | 영구 |
| Secrets | encrypted backup | 30일 |
9.3 DR Drill
분기마다 — 백업에서 새 환경으로 복원 시도:
# scripts/dr_drill.py
def quarterly_dr_drill():
# 1. 별도 region·account에 새 인프라 provisioning
new_env = provision_new_environment()
# 2. 최근 backup으로 복원
restore_from_backup(new_env, snapshot=latest_backup())
# 3. 핵심 기능 smoke test
assert run_smoke_tests(new_env)
# 4. RTO 측정·RPO 검증
log_drill_metrics(rto=measure_rto(), rpo=measure_rpo())Drill 안 하면 — 실제 disaster 시 backup이 손상됐는지 모름.
10 24/7 On-call 디테일
10.1 Rotation Pattern
Follow-the-sun (글로벌)
US: 09:00-17:00 PT
EU: 09:00-17:00 CET
KR: 09:00-17:00 KST
→ 24/7 자연 커버, 야간 page X
Single-region (소규모)
주중 day shift (팀 내 rotation)
주말·야간 on-call (1주 한 번 page 가능 1~2회)
→ 비용 적음, 번아웃 위험
10.2 Compensation·Wellness
- On-call 시간 보상 (overtime·comp time)
- Page 발생 시 다음날 휴식
- 분기 on-call 회고 (피로도·문제 패턴)
- Mental health support
10.3 Handoff
[Daily handoff] (글로벌 rotation 전환 시)
- 진행 중 incident 인수
- 알림 임계 변경 사항
- 주의 영역 (최근 변경된 곳)
[Weekly review]
- 한 주의 incident 정리
- false positive alert tuning
- toil 패턴 식별
11 C25·C34와 결합
| 본 편 영역 | C25·C34에서 토대 |
|---|---|
| Capacity Planning | C34 metrics 시계열 |
| SLO·burn rate | C34 burn rate 계산 |
| Incident — Mitigate | C25 Kill Switch·Circuit Breaker·Rollback |
| Toil Reduction | C34 dashboard 자동화 |
| Chaos Engineering | C25 데코레이터로 inject |
| DR | C20 retention·C36 audit log |
Phase C-9가 toolkit, Phase C-10이 운영 절차로 묶음.
12 MINERVA 적용
app/ops/
├── capacity.py # 부하 예측·임계 결정
├── rate_limit.py # token bucket·per-user
├── backpressure.py # 큐 깊이·503 빠른 실패
├── incident.py # commander·triage·status
├── post_mortem.py # template·5일 내 작성 강제
├── toil.py # 운영 작업 분류·자동화 우선순위
├── chaos.py # staging chaos experiments
└── dr.py # 분기 drill·RTO·RPO 측정
scripts/
├── slo_burn.py # SLO 계산·alert 발화
├── oncall_handoff.py # daily handoff 보조
├── incident_war_room.py # P1·P2 자동 Slack channel·IC
└── dr_drill_runbook.py # 분기 DR drill 실행
infra/
├── runbooks/ # 절차 문서 (incident별·서비스별)
├── alerts/ # alert 정의
└── dashboards/ # SRE dashboard
13 자주 발생하는 함정
13.1 Alert Fatigue
너무 많은 alert → 운영 무시 → P1 놓침.
해법: - alert 개수 < 사람 처리 가능 - 분기마다 alert 정리 — false positive·중복 제거 - burn rate 기반 (메트릭 임계 X)
13.2 Toil 누적
분기 자동화 우선순위 결정 안 함 → toil 80% → 새 기능 0.
해법: - 분기 toil audit 의무 - 매 sprint 자동화 작업 1개 강제 - toil > 50% 시 인력 충원 또는 우선순위 재조정
13.3 MTTR 측정 안 함
incident 발생만 보고 회복 시간 추적 안 함 → 개선 가시화 X.
해법: - 매 incident에 detect·ack·mitigate·resolve 시간 기록 - 분기 MTTR 추세 review - 등급별 MTTR target (P1 < 1h, P2 < 4h)
13.4 Blame Culture
post-mortem이 비난 — 다음 incident 시 정보 숨김.
해법: - 명시적 blameless 정책 - post-mortem template에 “사람” 항목 X (시스템·절차만) - lead가 모범 — 자기 실수도 공개적으로 분석
13.5 DR Drill 미수행
backup 자동화는 됐지만 복원은 한 번도 안 함 → 실제 disaster 시 발견.
해법: - 분기 DR drill 의무 (운영 KPI) - 결과 (RTO·RPO 측정)·문제점 review - 외부 audit (SOC 2)이 강제하는 경우 활용
13.6 On-call 번아웃
작은 팀 24/7 → 야간 page 자주 → 사람 잃음.
해법: - 최소 4명 (1주에 1번 이내) - Follow-the-sun - Page 빈도 → 자동화 우선순위 - 보상·휴식·wellness 제도
13.7 Capacity 사후 대응
부하 spike 후 사후 scaling → 사용자 영향 발생 후.
해법: - 사전 capacity 예측 (분기마다) - 부하 테스트 분기 (load test) - 새 기능 도입 시 영향 추정 의무 (C19 spec)
13.8 Runbook Stale
incident runbook이 1년 전 — 인프라 바뀐 후 안 맞음.
해법: - post-mortem action item에 runbook 갱신 - 분기 runbook audit - 새 incident 시 runbook 따라가는데 안 맞으면 즉시 수정
14 정리
| 영역 | 핵심 |
|---|---|
| 5축 | Capacity·SLO/SLI·Incident·Toil·DR |
| 용어 | SLI(측정)·SLO(목표)·SLA(외부 계약) |
| Capacity | average·peak·burst·disaster 시나리오별 전략 |
| Incident | P1~P4 등급·IC·blameless post-mortem·5일 내 |
| Toil | 분기 audit·자동화 우선순위·50% 임계 |
| Chaos | staging·분기·핵심 의존 시뮬레이션 |
| DR | RTO·RPO·분기 drill·외부 audit 결합 |
| On-call | follow-the-sun·보상·번아웃 방지 |
| 함정 | alert fatigue·toil 누적·MTTR·blame·drill 미수행·번아웃·capacity 사후·runbook stale |
15 응용 분야
| 시나리오 | 핵심 |
|---|---|
| 신규 기능 도입 시 capacity 영향 | C19 spec에 capacity 추정 |
| 외부 LLM provider 장애 | Circuit Breaker + 자동 fallback (C25) |
| 분기 발표 후 트래픽 spike | auto-scale + queue + degraded mode |
| 데이터 누출 의심 | P1 + Kill Switch + audit replay |
| 회귀 발견 | rollback (C26) + post-mortem |
| 분기 DR 검증 | 별도 region 복원 + smoke test |
| Toil 초과 | 분기 자동화 sprint |
16 관련 주제
선행 학습 (선수)
- C25 실행 제어 — Timeout·Retry·Circuit Breaker·Kill Switch toolkit
- C26 에이전트 생명주기 — Rollback 절차
- C34 관측성 — SLO·burn rate·dashboard
- C36 보안·접근 제어 — audit log·incident 보안 측면
- C37 개발 조직 설계 — SRE 팀 정의
후속 (Phase C-10)
- C39 바이브 코딩에서 설계 기반 개발로 — Phase C 전체 클로저
Cross-reference
- C19 실험 파이프라인 — capacity·guardrail 통합
- C20 대화 로깅 — incident 분석 정보원
- Engineering: Docker Compose — staging 환경 구성
- Engineering: shell scripting — runbook·DR drill 토대