- Authors
- Name
- 들어가며
- SLI/SLO/SLA 개념 정리
- SLI 지표 선정 전략
- SLO 수치 설정
- Error Budget 정책
- Burn Rate 알럿
- Prometheus 기반 구현
- Grafana 대시보드
- 조직 도입 전략
- 실패 사례와 교훈
- 운영 체크리스트
- 참고자료

들어가며
Prometheus로 메트릭을 수집하고, Alertmanager로 알림을 구성했다. 그런데 장애가 발생할 때마다 "어디까지가 허용 범위인가?"라는 질문에 답하기 어렵다. CPU 사용률 80%에 알림을 걸었지만, 정작 사용자 체감 품질과는 무관한 알림이 반복되고 팀은 Alert Fatigue에 시달린다.
Google SRE 팀은 이 문제를 근본적으로 해결하기 위해 SLI(Service Level Indicator), SLO(Service Level Objective), Error Budget이라는 프레임워크를 정립했다. 이 프레임워크의 핵심은 단순하다. "사용자 관점에서 서비스 품질을 측정하고, 허용 가능한 실패 범위를 정량화하여, 신뢰성과 개발 속도 사이의 균형을 데이터로 결정한다."
이 글에서는 SLI/SLO/SLA의 개념 정리부터 시작하여 SLI 지표 선정, SLO 수치 설정, Error Budget 정책, Burn Rate 알럿, Prometheus 기반 구현, Grafana 대시보드, 조직 도입 전략까지 프로덕션 서비스의 신뢰성 관리 전체 파이프라인을 코드와 함께 구축한다.
SLI/SLO/SLA 개념 정리
SLI (Service Level Indicator)
SLI는 서비스 수준을 나타내는 정량적 지표다. Google SRE 책에서는 SLI를 "좋은 이벤트 수 / 전체 이벤트 수" 비율로 정의한다. 예를 들어 "전체 HTTP 요청 중 200ms 이내에 응답한 요청의 비율"이 하나의 SLI가 된다. SLI는 항상 0%에서 100% 사이의 값을 가진다.
SLO (Service Level Objective)
SLO는 SLI에 대한 목표치다. "응답 시간 SLI가 30일 동안 99.9% 이상이어야 한다"가 SLO의 예다. SLO는 내부 엔지니어링 팀이 설정하며, 사용자 기대와 엔지니어링 비용 사이의 균형점을 나타낸다. 100% SLO는 현실적으로 불가능하며, 추구해서도 안 된다.
SLA (Service Level Agreement)
SLA는 SLO에 법적/계약적 결과를 붙인 것이다. "가용성 99.95% 미달 시 크레딧 환불"처럼 위반 시 금전적 보상이나 계약 해지 조건이 포함된다. SLA는 비즈니스 계약이고, SLO는 엔지니어링 목표다. SLO는 항상 SLA보다 엄격해야 한다. SLA가 99.9%라면 SLO는 99.95% 이상으로 설정하여 내부적으로 더 높은 기준을 유지해야 한다.
Error Budget
Error Budget은 SLO에서 파생되는 개념이다. SLO가 99.9%라면 Error Budget은 0.1%다. 30일 기준으로 계산하면 약 43분의 다운타임이 허용된다. Error Budget은 "얼마나 실패해도 되는가"를 정량화한 것이며, 이를 통해 기능 개발 속도와 신뢰성 사이의 트레이드오프를 데이터 기반으로 관리할 수 있다.
| 개념 | 정의 | 예시 | 주체 |
|---|---|---|---|
| SLI | 서비스 수준 측정 지표 | 성공 요청 비율, 지연시간 분포 | 엔지니어링 |
| SLO | SLI에 대한 목표치 | 30일 가용성 99.9% 이상 | 엔지니어링 + 프로덕트 |
| SLA | SLO + 계약적 결과 | 99.95% 미달 시 크레딧 환불 | 비즈니스 + 법무 |
| Error Budget | 100% - SLO | 0.1% = 월 43분 다운타임 허용 | 엔지니어링 |
SLI 지표 선정 전략
서비스 유형별 SLI
서비스 유형에 따라 적합한 SLI가 다르다. Google SRE Workbook에서는 다음과 같이 분류한다.
| 서비스 유형 | 주요 SLI | 측정 방법 |
|---|---|---|
| Request-driven (API, 웹) | 가용성, 지연시간 | 성공 응답 비율, p50/p99 응답시간 |
| Pipeline (배치, ETL) | 신선도, 정확성 | 데이터 처리 지연, 결과 정확도 |
| Storage (DB, 캐시) | 내구성, 처리량 | 데이터 손실률, 초당 읽기/쓰기 수 |
| Streaming (Kafka, Pub/Sub) | 지연시간, 처리량 | end-to-end 지연, 초당 메시지 수 |
SLI 선정 원칙
- 사용자 여정(CUJ) 기반: 로그인, 검색, 결제 등 핵심 사용자 여정별로 SLI를 정의한다.
- 측정 용이성 우선: 복잡한 계측보다 기존 로그나 메트릭에서 추출 가능한 SLI를 먼저 선택한다.
- 합성 모니터링 병행: 서버 측 메트릭만으로는 CDN 캐시 히트나 클라이언트 렌더링 시간을 측정할 수 없으므로 Synthetic Monitoring을 병행한다.
- 다중 등급 SLO: 하나의 SLI에 여러 임계값을 설정한다. "90% 요청은 100ms 이내, 99% 요청은 400ms 이내"처럼 두 가지 목표를 동시에 추적한다.
SLO 수치 설정
SLO 수치별 허용 다운타임
SLO 수치가 높아질수록 허용 다운타임은 기하급수적으로 줄어든다.
| SLO | 월간 Error Budget | 연간 Error Budget |
|---|---|---|
| 99% | 7시간 18분 | 3일 15시간 |
| 99.5% | 3시간 39분 | 1일 19시간 |
| 99.9% | 43분 50초 | 8시간 46분 |
| 99.95% | 21분 55초 | 4시간 23분 |
| 99.99% | 4분 23초 | 52분 36초 |
SLO 설정 프로세스
- 현재 성능 측정: 최소 2주간의 실제 데이터를 수집하여 현재 서비스의 실제 신뢰성을 파악한다.
- 사용자 기대 조사: 사용자가 실제로 인지하는 품질 수준을 확인한다. 내부 도구와 외부 서비스는 기대치가 다르다.
- 비용-편익 분석: 99.9%에서 99.99%로 올리는 비용이 그에 합당한 비즈니스 가치를 가지는지 평가한다.
- 이해관계자 합의: 프로덕트 매니저, 엔지니어링 리드, 경영진이 모두 동의하는 수치를 설정한다.
- 반복 조정: 첫 SLO는 보수적으로 시작하고, 분기별로 검토하여 조정한다.
Error Budget 정책
Error Budget 정책은 Error Budget 소진 시 취해야 할 구체적 조치를 문서화한 것이다. Google SRE Workbook에서는 서면 정책을 권장한다.
Error Budget 정책 예시
# error-budget-policy.yaml
error_budget_policy:
service: payment-api
slo_window: 30d
slo_target: 99.9%
thresholds:
- level: green
budget_remaining: '>50%'
actions:
- 정상 기능 개발 진행
- 주간 SLO 리뷰 미팅
- level: yellow
budget_remaining: '25%-50%'
actions:
- 신규 기능 릴리스 전 신뢰성 리뷰 필수
- 기술 부채 해소 작업 병행
- 일간 SLO 리뷰 미팅
- level: orange
budget_remaining: '10%-25%'
actions:
- 신규 기능 릴리스 중단
- 엔지니어링 시간 50% 이상 신뢰성 작업에 투입
- 장애 원인 분석(Postmortem) 즉시 실행
- level: red
budget_remaining: '<10%'
actions:
- 모든 기능 개발 동결
- 전체 엔지니어링 리소스 신뢰성 복구에 집중
- 경영진 에스컬레이션
- SLO 미달 근본 원인 해소 완료 시까지 동결 유지
Error Budget 소진 시 대응 프로세스
Error Budget이 소진되었을 때의 대응은 조직의 신뢰성 문화를 보여주는 리트머스 테스트다. 핵심 원칙은 다음과 같다.
- 기능 동결(Feature Freeze): Error Budget 소진 시 신뢰성 복구가 최우선이다.
- Postmortem 필수: 모든 Error Budget 소진 이벤트에 대해 비난 없는 Postmortem을 실시한다.
- 자동화 강화: 수동 작업(Toil)이 원인인 경우 자동화를 우선 구현한다.
- SLO 재검토: 반복적으로 Error Budget을 소진한다면 SLO 자체가 너무 공격적인지 검토한다.
Burn Rate 알럿
Burn Rate 개념
Burn Rate는 Error Budget을 얼마나 빠르게 소진하고 있는지를 나타내는 배수다. Burn Rate 1은 SLO 윈도우(예: 30일) 동안 Error Budget을 정확히 다 소진하는 속도를 의미한다. Burn Rate 10이면 30일 예산을 3일 만에 소진하는 속도다.
알럿 방식 비교
| 알럿 방식 | 장점 | 단점 |
|---|---|---|
| 임계값 기반 (에러율 1% 초과) | 설정이 단순하다 | 사용자 영향과 무관한 알림이 많다 |
| Burn Rate 단일 윈도우 | SLO와 직접 연동된다 | 짧은 스파이크에 과민 반응한다 |
| Multi-Window Multi-Burn-Rate | 정밀한 감지가 가능하다 | 설정이 복잡하다 |
Multi-Window Multi-Burn-Rate 알럿
Google SRE Workbook에서 권장하는 방식이다. 두 개의 윈도우(긴 윈도우 + 짧은 윈도우)를 동시에 확인하여, 긴 윈도우는 실제 트렌드를 반영하고 짧은 윈도우는 이미 복구된 이슈에 대한 알림을 방지한다.
# multi-window-burn-rate-alerts.yaml
# Google SRE Workbook 권장 알럿 설정
groups:
- name: slo-burn-rate-alerts
rules:
# 페이지 알럿: 2% 예산을 1시간 내 소진 (Burn Rate 14.4)
- alert: SLOBurnRateHigh_Page
expr: |
(
sli:error_ratio:rate1h > (14.4 * 0.001)
and
sli:error_ratio:rate5m > (14.4 * 0.001)
)
for: 2m
labels:
severity: page
annotations:
summary: 'Error budget burn rate is very high'
description: 'Service is consuming error budget 14.4x faster than normal. 2% of 30-day budget will be consumed in 1 hour.'
# 페이지 알럿: 5% 예산을 6시간 내 소진 (Burn Rate 6)
- alert: SLOBurnRateMedium_Page
expr: |
(
sli:error_ratio:rate6h > (6 * 0.001)
and
sli:error_ratio:rate30m > (6 * 0.001)
)
for: 5m
labels:
severity: page
annotations:
summary: 'Error budget burn rate is elevated'
description: 'Service is consuming error budget 6x faster than normal. 5% of 30-day budget will be consumed in 6 hours.'
# 티켓 알럿: 10% 예산을 3일 내 소진 (Burn Rate 1)
- alert: SLOBurnRateSlow_Ticket
expr: |
(
sli:error_ratio:rate3d > (1 * 0.001)
and
sli:error_ratio:rate6h > (1 * 0.001)
)
for: 30m
labels:
severity: ticket
annotations:
summary: 'Error budget burn rate indicates slow degradation'
description: 'Service is steadily consuming error budget. 10% of 30-day budget will be consumed in 3 days.'
Prometheus 기반 구현
SLI Recording Rules
SLI를 효율적으로 계산하기 위해 Recording Rules를 사용한다. 다양한 시간 윈도우에 대해 에러 비율을 미리 계산해 두면 알럿 규칙에서 재사용할 수 있다.
# sli-recording-rules.yaml
groups:
- name: sli-recording-rules
interval: 30s
rules:
# 전체 요청 중 에러 비율 (다양한 윈도우)
- record: sli:error_ratio:rate5m
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
- record: sli:error_ratio:rate30m
expr: |
sum(rate(http_requests_total{status=~"5.."}[30m]))
/
sum(rate(http_requests_total[30m]))
- record: sli:error_ratio:rate1h
expr: |
sum(rate(http_requests_total{status=~"5.."}[1h]))
/
sum(rate(http_requests_total[1h]))
- record: sli:error_ratio:rate6h
expr: |
sum(rate(http_requests_total{status=~"5.."}[6h]))
/
sum(rate(http_requests_total[6h]))
- record: sli:error_ratio:rate3d
expr: |
sum(rate(http_requests_total{status=~"5.."}[3d]))
/
sum(rate(http_requests_total[3d]))
# 지연시간 SLI: 200ms 이내 응답 비율
- record: sli:latency_good_ratio:rate5m
expr: |
sum(rate(http_request_duration_seconds_bucket{le="0.2"}[5m]))
/
sum(rate(http_request_duration_seconds_count[5m]))
- record: sli:latency_good_ratio:rate1h
expr: |
sum(rate(http_request_duration_seconds_bucket{le="0.2"}[1h]))
/
sum(rate(http_request_duration_seconds_count[1h]))
Error Budget 잔여량 계산
# Error Budget 잔여율 (30일 윈도우, SLO 99.9%)
# 결과가 1이면 100% 남음, 0이면 완전 소진
(
1 - (
sum(increase(http_requests_total{status=~"5.."}[30d]))
/
sum(increase(http_requests_total[30d]))
)
- 0.999
) / 0.001
위 쿼리는 현재 30일간의 실제 에러 비율을 구하고, SLO 목표치(0.999)를 빼서 남은 Error Budget을 전체 Error Budget(0.001)으로 나눈 것이다. 결과가 0.5면 Error Budget의 50%가 남아있다는 의미다.
SLO Reporting 스크립트
#!/usr/bin/env python3
"""SLO 보고서 생성 스크립트"""
import requests
from datetime import datetime, timedelta
PROMETHEUS_URL = "http://prometheus:9090"
SLO_CONFIGS = [
{
"name": "payment-api-availability",
"sli_query": 'sum(rate(http_requests_total{job="payment-api",status!~"5.."}[30d])) / sum(rate(http_requests_total{job="payment-api"}[30d]))',
"slo_target": 0.999,
"window_days": 30,
},
{
"name": "payment-api-latency",
"sli_query": 'sum(rate(http_request_duration_seconds_bucket{job="payment-api",le="0.2"}[30d])) / sum(rate(http_request_duration_seconds_count{job="payment-api"}[30d]))',
"slo_target": 0.995,
"window_days": 30,
},
]
def query_prometheus(query: str) -> float:
"""Prometheus instant query 실행"""
resp = requests.get(
f"{PROMETHEUS_URL}/api/v1/query",
params={"query": query},
)
result = resp.json()["data"]["result"]
if not result:
return 0.0
return float(result[0]["value"][1])
def generate_report():
"""SLO 보고서 생성"""
print(f"=== SLO Report ({datetime.now().strftime('%Y-%m-%d %H:%M')}) ===\n")
for config in SLO_CONFIGS:
current_sli = query_prometheus(config["sli_query"])
slo_target = config["slo_target"]
error_budget_total = 1 - slo_target
error_budget_consumed = max(0, slo_target - current_sli)
error_budget_remaining = max(
0, (error_budget_total - error_budget_consumed) / error_budget_total
)
status = "OK" if current_sli >= slo_target else "VIOLATED"
budget_pct = error_budget_remaining * 100
print(f"Service: {config['name']}")
print(f" SLI (current): {current_sli:.4%}")
print(f" SLO (target): {slo_target:.4%}")
print(f" Status: {status}")
print(f" Error Budget: {budget_pct:.1f}% remaining")
if budget_pct < 25:
print(f" WARNING: Error budget below 25%!")
print()
if __name__ == "__main__":
generate_report()
Grafana 대시보드
SLO 대시보드 구성
Grafana 대시보드는 SLO 현황을 한눈에 파악할 수 있도록 구성한다. 핵심 패널은 다음과 같다.
- SLI 현재 값 (Stat Panel): 현재 가용성 SLI를 큰 숫자로 표시한다. 임계값 색상으로 상태를 직관적으로 보여준다.
- Error Budget 잔여율 (Gauge Panel): Error Budget의 남은 비율을 게이지로 표시한다. 50% 이하이면 노란색, 25% 이하이면 빨간색으로 전환된다.
- Burn Rate 추이 (Time Series Panel): 시간에 따른 Burn Rate 변화를 그래프로 보여준다. 알럿 임계값을 수평선으로 표시한다.
- Error Budget 소진 예측 (Time Series Panel): 현재 Burn Rate가 유지될 경우 Error Budget이 완전히 소진되는 예상 일자를 보여준다.
# grafana-slo-dashboard.json (패널 구성 요약)
panels:
- title: 'Current Availability SLI'
type: stat
targets:
- expr: '1 - sli:error_ratio:rate30d'
legendFormat: 'Availability'
thresholds:
- value: 0.999
color: green
- value: 0.995
color: yellow
- value: 0.99
color: red
- title: 'Error Budget Remaining'
type: gauge
targets:
- expr: |
clamp_min(
(0.001 - sli:error_ratio:rate30d) / 0.001,
0
)
legendFormat: 'Budget Remaining'
min: 0
max: 1
thresholds:
- value: 0.5
color: green
- value: 0.25
color: yellow
- value: 0
color: red
- title: 'Burn Rate (1h window)'
type: timeseries
targets:
- expr: 'sli:error_ratio:rate1h / 0.001'
legendFormat: 'Burn Rate (1h)'
overrides:
- matcher: 'Burn Rate Threshold'
properties:
- id: custom.lineStyle
value: dash
조직 도입 전략
단계별 도입 로드맵
SLI/SLO는 기술적 구현만으로는 성공하지 못한다. 조직 전체의 합의와 문화 변화가 필요하다.
1단계 - 파일럿 (1-2개월)
- 가장 중요한 서비스 1-2개를 선정한다.
- 기존 메트릭에서 추출 가능한 간단한 SLI로 시작한다.
- SLO는 현재 성능보다 약간 낮게 설정하여 달성 가능한 목표로 시작한다.
2단계 - 확산 (3-6개월)
- 파일럿 결과를 기반으로 주요 서비스로 확대한다.
- Error Budget 정책을 수립하고 이해관계자 합의를 확보한다.
- Burn Rate 알럿을 프로덕션에 적용한다.
3단계 - 성숙 (6-12개월)
- 모든 사용자 대면 서비스에 SLO를 적용한다.
- SLO를 인시던트 리뷰, 용량 계획, 릴리스 관리에 통합한다.
- 분기별 SLO 리뷰 프로세스를 정례화한다.
핵심 성공 요인
- 경영진 스폰서십: SLO 기반 의사결정은 기능 개발 동결을 포함하므로 경영진의 지지가 필수적이다.
- 프로덕트 매니저 참여: SLO 수치 결정에 PM이 반드시 참여해야 한다. 엔지니어만의 지표가 되면 실패한다.
- 점진적 접근: 처음부터 완벽한 SLO를 추구하지 않는다. "Wrong but useful"이 "Perfect but never shipped"보다 낫다.
- 자동화 투자: SLO 보고서 생성, Error Budget 추적, Burn Rate 알럿을 자동화하여 운영 부담을 최소화한다.
실패 사례와 교훈
사례 1: 너무 공격적인 SLO
한 팀이 외부 SLA 없이 내부 서비스에 99.99% SLO를 설정했다. 월간 Error Budget은 4분 23초에 불과하여 정상적인 배포조차 불가능했다. 배포마다 수 초의 다운타임이 발생하면 즉시 Error Budget이 소진되어 기능 개발이 사실상 중단되었다. 해결책은 SLO를 99.9%로 낮추고, 무중단 배포(Blue-Green, Canary)를 도입하는 것이었다.
사례 2: Burn Rate 알럿의 Alert Fatigue
Burn Rate 알럿을 도입했지만, 짧은 윈도우(5분)만 사용하여 순간적인 에러 스파이크마다 알림이 발생했다. 하루에 수십 건의 알림이 발생하자 온콜 엔지니어가 알림을 무시하기 시작했다. Multi-Window 방식으로 전환하고, 페이지 알럿과 티켓 알럿을 분리하여 해결했다.
사례 3: Error Budget 소진 시 정책 부재
Error Budget이 소진되었지만 "기능 동결" 정책이 없어 개발팀이 계속 새 기능을 릴리스했다. 결과적으로 장애가 반복되었고, 사용자 이탈이 발생했다. Error Budget 정책을 서면으로 수립하고, 경영진의 승인을 받아 정책 이행력을 확보한 후에야 문제가 해결되었다.
운영 체크리스트
프로덕션에 SLI/SLO/Error Budget을 도입할 때 확인해야 할 항목을 정리한다.
- 핵심 사용자 여정(CUJ)별 SLI가 정의되었는가
- SLI가 Prometheus Recording Rules로 자동 계산되는가
- SLO 수치에 대해 엔지니어링과 프로덕트 팀이 합의했는가
- Error Budget 정책이 서면으로 문서화되어 있는가
- Multi-Window Multi-Burn-Rate 알럿이 구성되어 있는가
- 페이지 알럿(즉시 대응)과 티켓 알럿(업무 시간 대응)이 분리되어 있는가
- Grafana 대시보드에서 SLI, Error Budget 잔여율, Burn Rate를 확인할 수 있는가
- SLO 보고서가 주간/월간으로 자동 생성되는가
- Error Budget 소진 시 기능 동결 프로세스가 경영진 승인을 받았는가
- 분기별 SLO 리뷰 미팅이 일정에 포함되어 있는가
- Postmortem 프로세스가 Error Budget 소진 이벤트에 연동되어 있는가
참고자료
- Google SRE Book - Service Level Objectives
- Google SRE Workbook - Implementing SLOs
- Google SRE Workbook - Alerting on SLOs
- Google SRE Workbook - Error Budget Policy
- Google Cloud Blog - SRE Fundamentals: SLIs vs SLOs vs SLAs
- Sloth - Prometheus SLO Generator
- SLODLC Handbook - SLO Development Life Cycle
- Grafana Cloud - Introduction to SLO