Block 5: Observability & Operations

수집 → 샘플링 → 저장 → 리전 간 상관 → 비용 → 부하 테스트 → SLO → 출시 준비

텔레메트리는 리전 안에서 끝낸다

사용자 경로
CloudFront유일한 public 진입점
VPC origin → internal ALBX-Amzn-Trace-Id 추가
→
App Pod
OTel SDKW3C traceparent 전파
order, paymentcatalog, cart
→
Collector 2계층
Agent (DaemonSet)traceID로 분배
Gateway (Deployment)tail_sampling
→
리전 로컬 backend
Amazon Managed Service for Prometheus
Tempo on S3 또는 CloudWatch (X-Ray)
같은 스택을 두 번 us-east-1과 us-west-2에 동일하게 배포합니다. 한 리전 장애가 다른 리전의 관측을 끊지 않도록 합니다.
조회만 전역으로 Grafana가 두 리전 data source를 함께 조회합니다. 데이터 이동은 필요한 경우에만 합니다.

Collector는 2계층으로 나눈다

노드 로컬에서 받아 trace ID 기준으로 Gateway에 분배합니다.

receivers: otlp: protocols: grpc: { endpoint: "${env:MY_POD_IP}:4317" } processors: memory_limiter: { check_interval: 1s, limit_percentage: 80, spike_limit_percentage: 25 } exporters: loadbalancing: routing_key: traceID protocol: otlp: { timeout: 1s } resolver: k8s: { service: otel-gateway.observability, ports: [4317] }
processors: memory_limiter: { check_interval: 1s, limit_percentage: 80, spike_limit_percentage: 25 } batch: {} # 기본값 8192건, 200ms tail_sampling: decision_wait: 30s # 기본값 30s num_traces: 50000 # 기본값 50000 expected_new_traces_per_sec: 2000 policies: - name: keep-errors type: status_code status_code: { status_codes: [ERROR] } - name: keep-slow type: latency latency: { threshold_ms: 500 } - name: baseline type: probabilistic probabilistic: { sampling_percentage: 10 }
extensions: sigv4auth/traces: { region: us-east-1, service: xray } exporters: otlphttp/xray: compression: gzip traces_endpoint: https://xray.us-east-1.amazonaws.com/v1/traces auth: { authenticator: sigv4auth/traces } service: extensions: [sigv4auth/traces] pipelines: traces: receivers: [otlp] processors: [memory_limiter, tail_sampling, batch] exporters: [otlphttp/xray]

X-Ray OTLP endpoint는 Transaction Search 활성화가 전제입니다. us-west-2 Gateway는 region과 endpoint만 바꿉니다.

tail sampling은 같은 인스턴스가 전제

에러 trace
100%
status_code = ERROR
느린 trace
100%
latency ≥ 500ms
나머지
10%
probabilistic baseline
예시 보존량
약 12.7%
에러 1%, 느림 2% 가정: 3% + 97% × 10%
같은 trace, 같은 인스턴스
trace의 모든 span이 한 Collector에 모여야 판단할 수 있습니다. Gateway를 늘리면 앞단에 traceID 라우팅이 필수입니다.
메모리 = 유입률 × 대기
2,000 trace/s × 30s = 60,000개가 메모리에 머뭅니다. num_traces 50000보다 크면 판단 전에 밀려납니다.
늦게 오는 span
decision_wait 뒤에 도착한 span은 이미 내려진 결정을 따릅니다. 비동기 consumer가 긴 trace는 대기 시간을 따로 봅니다.

백엔드는 Tempo와 X-Ray 중 고른다

항목2026-10-15 기준
수집 경로OTLP endpoint, SigV4 (service: xray)
저장 위치CloudWatch Logs aws/spans log group
검색모든 span을 attribute로 검색, trace 최대 10,000 span
인덱싱수집 span의 1%는 trace summary로 무료 인덱싱
수집 요금$0.35/GB (첫 10 TB, us-east-1 list price)
항목내용
저장S3에 Parquet 블록 (storage.trace.backend: s3)
쓰기 경로3.0에서 ingester 제거, block-builder와 live-store
배포 모드monolithic은 Kafka 불필요, microservices는 Kafka 호환 큐
질의TraceQL, 구조 연산자 >>, >, ~
service graphmetrics-generator service_graphs, 기본 비활성
질문Transaction SearchTempo
운영 부담관리형클러스터 직접 운영
샘플링100% 수집 후 일부 인덱싱tail sampling 결과만 저장
AWS 연계Application Signals, SLOGrafana 생태계
비용 성격GB당 수집 요금S3 + 컴퓨트

X-Ray SDK와 daemon은 2026-02-25부터 maintenance mode입니다. 보안 수정만 릴리스되며 X-Ray 서비스 자체는 계속 지원됩니다. 신규 계측은 OpenTelemetry(ADOT SDK 또는 upstream SDK)로 시작합니다.

trace ID는 리전을 넘어 이어진다

us-west-2
cart-servicetrace 시작, cloud.region = us-west-2
→
traceparent 헤더
같은 trace IDTGW peering 경유 사설 호출
→
us-east-1 (write primary)
order → paymentspan은 us-east-1 backend에 저장
A. 리전별 저장 (기본) 각 리전 backend에 그대로 두고 trace ID로 양쪽을 조회합니다. 장애 격리가 우선입니다.
B. sampled 사본만 이동 Gateway에 원격 exporter를 하나 더 둡니다. tail sampling 뒤라 바이트가 작지만 리전 간 전송 요금이 붙습니다.
# B 구성에서 한 Tempo에 두 리전 span이 있을 때 { resource.cloud.region = "us-west-2" } >> { resource.cloud.region = "us-east-1" && status = error }

OAM은 리전을 넘지 않는다

Cross-account observability (OAM)
  • sink와 link는 같은 Region에서만 연결
  • 계정당 Region별 sink 1개
  • monitoring 계정당 source 최대 100,000
  • metrics, logs, traces를 복제 없이 조회
Centralization rules
  • Organizations 기반, source Region 여러 개 선택
  • destination Region + backup Region
  • @aws.account, @aws.region 필드 보존
  • 첫 사본 무료, 추가 사본 $0.05/GB
Cross-account cross-Region 대시보드
  • metrics와 alarm 위젯용
  • logs와 traces는 지원하지 않음
  • alarm은 telemetry가 있는 Region에 생성
시나리오 적용 monitoring 계정에 us-east-1, us-west-2 sink를 각각 만들고, 로그는 Centralization rule로 us-east-1에 모으며 backup Region을 us-west-2로 둡니다.

변동비는 바이트 수가 정한다

300
100
50
20
13%
us-east-1 list price, 2026-10-15 Pricing API 기준, 30일/월, 730시간/월. 리전 간 $0.02/GB, NAT $0.045/GB와 $0.045/시간, Logs $0.50 또는 $0.25/GB, span $0.35/GB, EKS $0.10/시간.
-
리전 간 전송
-
NAT 데이터 처리
-
로그 수집
-
span 수집
-
고정: EKS 2개 + NAT GW 6개
-
변동비 중 리전 간 비중
-
월 합계 (컴퓨트, DB, 스토리지 제외)

최적화는 바이트를 줄이는 일

S3 gateway endpoint즉시
S3 트래픽을 NAT에서 빼면 GB당 $0.045 처리 요금이 사라집니다. gateway endpoint는 추가 요금이 없습니다.
sampled span만 이동즉시
원격 리전 exporter는 tail sampling 뒤에 둡니다. 원본 span을 리전 간으로 보내지 않습니다.
복제 범위 축소설계
MSK Replicator topic 필터, 리전 로컬로 재생성 가능한 cache와 search index는 복제 대신 재구축을 검토합니다.
로그 class 분리설계
감사, 디버그 로그는 IA class($0.25/GB)로 보냅니다. IA에서 쓸 수 없는 기능은 사전에 확인합니다.
컴퓨트 통합튜닝
stateless tier NodePool은 Spot과 Graviton을 허용하고 Karpenter consolidation을 켭니다. 할인 폭은 시점마다 다릅니다.
측정이 먼저상시
Cost Explorer를 usage type으로 묶어 USE1-USW2 전송, NAT, DataProcessing을 주 단위로 봅니다.

병목은 클라이언트 기본값에 숨는다

Valkey cluster mode
cluster-aware client가 아니면 다른 shard 키에서 MOVED 응답을 처리하지 못합니다.
조치 Python은 RedisCluster 계열 client로 교체
Go pgxpool
MaxConns 기본값은 max(4, NumCPU)입니다. 작은 Pod에서는 4개라 고부하에서 대기열이 생깁니다.
조치 pool_max_conns를 부하 테스트로 정하고 명시
PyMongo / Motor
maxPoolSize 기본 100입니다. Pod 수 × 100이 DocumentDB 연결 한도를 넘지 않는지 계산합니다.
조치 HPA 최대 Pod 수 기준으로 pool 크기 역산
Go http.Transport
DefaultMaxIdleConnsPerHost는 2입니다. 내부 API 호출이 많으면 연결을 계속 새로 맺습니다.
조치 공유 Transport에 MaxIdleConnsPerHost 상향
Quick win catalog의 GET 응답에 짧은 TTL cache를 두고, CloudFront cache behavior로 상품 조회 경로를 캐싱해 origin 요청을 줄입니다.

부하 테스트는 네 가지 모양으로

export const options = { vus: 100, duration: '10m', thresholds: { http_req_duration: ['p(95)<300', 'p(99)<500'], http_req_failed: ['rate<0.001'], 'http_req_duration{endpoint:orders}': ['p(95)<500'], }, }; // 트래픽 비율: browse 60, search 20, purchase 15, seller 5
export const options = { stages: [ { duration: '5m', target: 100 }, { duration: '10m', target: 500 }, { duration: '10m', target: 1000 }, { duration: '5m', target: 0 }, ], thresholds: { http_req_duration: [{ threshold: 'p(99)<1000', abortOnFail: true, delayAbortEval: '1m' }], }, };
export const options = { scenarios: { spike: { executor: 'ramping-arrival-rate', startRate: 500, timeUnit: '1s', preAllocatedVUs: 500, maxVUs: 3000, stages: [ { duration: '2m', target: 500 }, { duration: '1m', target: 2000 }, { duration: '5m', target: 2000 }, { duration: '2m', target: 500 }, ], }, }, }; // 관찰: Karpenter 노드 준비 시간, HPA 반응, 5xx

vus: 300, duration: '4h'로 4시간 유지합니다. 지표 대신 추세를 봅니다.

관찰 대상누수 신호
Pod 메모리시간에 비례해 증가
DB 연결 수pool 한도에 수렴 후 대기
goroutine, thread반환되지 않고 누적
tail sampling 메모리num_traces 도달 후 drop

SLO는 burn rate로 경보한다

99.9%
가용성, 30일
p95 < 300ms
전체 latency
p99 < 500ms
orders, payments
43.2분
30일 error budget
Application Signals SLO
period-based와 request-based 두 방식입니다. SLO당 burn rate 설정은 최대 10개입니다.
burn rate
baseline error rate = 100% - 목표입니다. 99.9%면 0.1%가 기준이고, 1보다 크면 budget을 빨리 씁니다.
리전별 SLO
SLO는 리전마다 따로 둡니다. 전역 평균은 한 리전 장애를 희석해 경보를 늦춥니다.

P0 네 개가 출시를 막는다

P0 출시 차단, 데이터 보호Phase 1, 2주
인증 미들웨어 없음gateway가 누구의 호출이든 통과
event bus가 mock publishMSK consumer 7개가 이벤트를 못 받음
MSK Replicator 미구성리전 간 topic, consumer offset 동기화 없음
Aurora Global DB 전환 준비 미흡rds.global_db_rpo 미설정, global writer endpoint 미적용
완료 기준: 인증 통합 테스트, 이벤트 end-to-end trace, us-west-2 topic 복제 lag 확인
P1 운영 위험Phase 2, 4주
WAF Bot Control이 synthetic 차단모니터링 체크 실패, scope-down 필요
search가 문자열 비교 mockOpenSearch 연동 전
함께 처리: 클라이언트 기본값 4건 수정
P2 개선Phase 3, 2주
CI/CD 수동 배포두 리전 동시 배포 파이프라인
Phase 4 상시: k6 4개 프로필, SLO 튜닝, 비용 최적화

Key Takeaways

1. 리전 로컬 관측
텔레메트리는 리전 안에서 끝내고 조회만 전역으로 모읍니다.
2. Collector 2계층
traceID 라우팅 없이는 tail sampling을 확장할 수 없습니다.
3. OTel이 표준
X-Ray SDK는 maintenance mode, OTLP endpoint와 Transaction Search로 갑니다.
4. OAM은 리전 안
리전마다 sink, 리전 간 집계는 Centralization rule입니다.
5. 바이트가 비용
리전 간 $0.02/GB, NAT $0.045/GB. 측정하고 줄입니다.
6. 출시는 P0부터
gap, 성능, 부하 테스트, 비용 순서로 리전별 SLO에 맞춥니다.

Knowledge Check (1/2)

Q1: tail sampling Gateway를 여러 개로 늘릴 때 반드시 필요한 것은?
Q2: CloudWatch cross-account observability(OAM)에 대한 설명으로 맞는 것은?

Knowledge Check (2/2)

Q3: us-east-1 → us-west-2 리전 간 데이터 전송 list price는? (2026-10-15 기준)

Thank You

Multi-Region Architecture Deep Dive, 감사합니다

수고하셨습니다!

← 목차로 돌아가기