[INFRA-02] docker-compose.observability.yml — LGTM + Collector (관측 백엔드)

작업 내용 (설계 의도)

근거 TDD: ../TDD.md “시스템 역할 경계”, ADR-002·003·004(개정). FR-3·FR-7.

senior-pm #4 반영: exporter 3종·Kafka UI는 INFRA-01(docker-compose.observability-agents.yml)로 분리됐다. 이 티켓은 관측 백엔드(LGTM + Collector + Grafana)만 소유한다. 데이터스토어는 ⑧ 소유라 정의하지 않는다.

변경 사항

관측 백엔드 컨테이너를 담는 신규 docker-compose.observability.yml을 생성한다(ADR-004 파일 분리).

  • otel-collector(4317/4318 수신, 8888 self-metric) — otel-collector-config.yaml(INFRA-03) 마운트
  • prometheus(9090) — prometheus.yml(INFRA-03) 마운트, exemplar 스토리지 옵션
  • tempo(3200) — tempo-config.yaml(INFRA-03) 마운트
  • loki(3100) — loki-config.yaml(INFRA-03) 마운트
  • grafana(3000) — provisioning(INFRA-04) 마운트
  • 공유 네트워크 observability-net (INFRA-01 agents·⑧ 데이터스토어와 공유)

이 티켓은 컨테이너 정의(서비스·포트·마운트 경로·네트워크)만 소유한다. config 파일 내용은 INFRA-03/04가 소유 — 마운트 경로는 TDD 계약으로 고정돼 파일이 아직 없어도 정의 가능(파일 교집합 0). 파일 소유는 docker-compose.observability.yml 단독 — INFRA-01(agents)과 disjoint.

롤백: docker compose -f docker-compose.observability.yml down — 앱·데이터스토어 무영향(수집·시각화만 중단).

의존

  • 없음 (wave 1, 독립 파일 — config 내용은 런타임 마운트라 authoring 시 불필요)

다이어그램

처리 흐름

sequenceDiagram
    participant D as docker compose
    participant C as otel-collector
    participant P as prometheus
    participant G as grafana
    D->>C: 기동 (config 마운트)
    D->>P: 기동 (scrape 잡 마운트)
    D->>G: 기동 (provisioning 마운트)
    P-->>G: 데이터소스 연결 대기

클래스 의존

flowchart LR
    OBS["docker-compose.observability.yml"] --> COL["otel-collector"]
    OBS --> PROM["prometheus"]
    OBS --> TEMPO["tempo"]
    OBS --> LOKI["loki"]
    OBS --> GRAF["grafana"]

테스트 케이스

  • docker compose -f docker-compose.observability.yml config가 유효하게 파싱된다.
  • 기동 후 otel-collector·prometheus·tempo·loki·grafana가 healthy가 된다.
  • Grafana(:3000)가 기동되고 로그인 페이지가 응답한다.
  • Collector OTLP 수신 포트(4317/4318)가 열린다.
  • 이 파일에 exporter·Kafka UI·데이터스토어 정의가 존재하지 않는다(INFRA-01과 소유 분리 검증).
  • config 파일 부재 시 해당 컨테이너만 기동 실패하고 나머지는 정상(격리 검증).