LY Corporation Tech Blog

LY Corporation과 LY Corporation Group(LINE Plus, LINE Taiwan and LINE Vietnam)의 기술과 개발 문화를 알립니다.

장애 Alert의 원인을 스스로 찾다: SRE Observer 개발기

들어가며

안녕하세요. LINE Plus에서 Home 서비스의 안정성을 책임지고 있는 Home SRE(Site Reliability Engineering) 팀입니다.

SRE Observer는 Alert를 받으면 여러 관측 신호를 연결해 원인을 분석하고, 대응에 필요한 정보를 정리해 주는 자동 대응 파이프라인입니다. 이 글에서는 SRE Observer를 만들게 된 배경과 주요 설계 과정을 소개하겠습니다.

새벽 3시. 장애 알림이 울렸습니다. 담당자는 보통 다음과 같은 순서로 원인을 추적하기 시작할 것입니다.

  1. 알림을 확인한다.
  2. 대시보드를 열어 메트릭을 확인한다.
  3. 로그 플랫폼으로 이동해 같은 시간대에 발생한 에러를 검색한다.
  4. 트레이스를 열어 어떤 요청이 문제였는지 확인한다.
  5. 필요하면 프로파일까지 확인한다.

Alert의 초기 대응은 여전히 사람의 몫이었습니다. 원인을 찾는 데 필요한 관측 신호는 이미 각 도구에 존재합니다. 문제는 그 신호들이 서로 다른 화면에 흩어져 있어, 이를 하나의 흐름으로 엮고 ‘그래서 원인이 무엇인가’를 판단하는 과정을 담당자가 직접 수행해야 한다는 점입니다. 알림을 인지하고 여러 도구를 오가며 신호를 연결하는 최초의 몇 분은 장애 대응에서 매우 중요한 시간입니다. 이 시간을 줄이기 위해 초기 대응의 시작점부터 자동화하고 싶었습니다.

목표는 단순했습니다.

‘Alert를 수신하면, 사람이 개입하기 전에 시스템이 먼저 상관분석을 수행하고, 근본 원인을 찾아 Slack에 보고까지 마친다.’

이 목표를 구현한 결과물이 SRE Observer입니다. 자체 관측성 스택(LGTM-P)과 Slack, Kubernetes 등의 데이터 소스를 기반으로 LLM(Large Language Model, 대규모 언어 모델)과 MCP(Model Context Protocol)를 활용해 근본 원인을 분석합니다.

SRE Observer를 도입한 결과, 초기 Alert 노이즈의 85~95%를 실시간으로 차단하고 평균 장애 식별 시간(MTTR)을 50% 단축하는 성과를 거두었습니다.

이 성과는 기존 장애 대응 과정에서 반복적으로 마주한 문제를 정리하는 데서 출발했습니다.

SRE 팀이 마주한 문제

크게 세 가지 어려움이 있었습니다. 알림이 너무 많이 쏟아졌고, 원인을 찾는 과정은 여전히 사람의 수동 판단에 의존했으며, 기존 도구만으로는 운영 환경에 맞는 수준의 제어권을 확보하기 어려웠습니다.

Alert 노이즈 폭탄

하나의 장애가 하나의 Alert만으로 끝나는 경우는 흔하지 않습니다. 업스트림 서비스 하나가 흔들리면 그에 의존하는 다운스트림 서비스들이 줄줄이 타임아웃을 내고, 각 서비스에서 개별 Alert가 발송됩니다. 결과적으로 하나의 근본 원인이 수십 개의 알림으로 쪼개져 담당자에게 도착합니다.

이렇게 되면 정작 중요한 신호가 노이즈에 묻힙니다. 담당자는 ‘이 알림들이 같은 장애인가, 다른 장애인가’부터 판단해야 했습니다.

수동 RCA의 한계

근본 원인 분석(RCA, Root Cause Analysis)을 하려면 메트릭, 로그, 트레이스, 프로파일을 사람이 각각 열어 직접 연결해야 합니다. LGTM-P 스택으로 데이터를 한곳에 모았지만, ‘메트릭에서 본 이상 징후를 어떤 로그와 트레이스로 이어 봐야 하는가’라는 신호 연결(signal correlation)은 여전히 사람의 머릿속에서만 일어났습니다.

기존 도구의 한계

‘Alert를 묶는 것’과 ‘원인을 찾는 것’은 이미 여러 도구가 시도하는 영역입니다. 그럼에도 직접 만든 이유가 있습니다.

첫 번째 이유는 Alertmanager grouping의 한계였습니다. Alertmanager는 라벨 기반으로 Alert를 그룹화할 수 있지만, 이는 정적인 라벨 일치에 의존합니다. 서로 다른 서비스에서 발생했더라도 하나의 업스트림 장애에서 비롯된 Alert를 ‘의존 관계’나 ‘증상의 의미적 유사성’으로 묶기는 어렵습니다. 라벨을 넘어 토폴로지와 의미까지 함께 보는 상관분석이 필요했습니다.

두 번째 이유는 상용 AIOps의 제약이었습니다. 상용 AIOps 솔루션도 상관분석과 RCA를 제공하지만, 운영 환경에 맞게 동작을 통제할 수 있는 제어권을 원하는 수준으로 확보하기는 어려웠습니다. 자체 호스팅형 LGTM-P 스택, 사내 인증과 권한 체계, 조직 고유의 심각도(severity) 정책과 대응 워크플로를 모두 반영해야 했기 때문입니다. 특히 ‘어떤 근거가 있을 때만 원인을 확정할지’, ‘어떤 작업까지 자동화하고 어디서 사람의 승인을 받을지’ 같은 정책은 직접 통제할 수 있어야 했습니다.

결론은 명확했습니다. 중요한 것은 자동화 자체보다 LLM 에이전트의 동작을 운영 환경에 맞게 통제할 수 있는 제어권을 확보하는 일이었습니다. SRE Observer는 Alert가 오는 순간 신호를 연결하고, 필요한 제어를 스스로 수행하는 시스템으로 설계했습니다.

SRE Observer 아키텍처: Alert에서 Post-Incident Knowledge까지

SRE Observer는 서비스 장애 Alert를 수신하면 상관분석과 AI 기반 근본 원인 분석(RCA)을 수행하고, 그 결과를 바탕으로 원인 진단과 대응 가이드를 제공합니다. 먼저 전체 처리 흐름을 정리한 뒤, 이를 가능하게 하는 세 가지 핵심 설계와 실제 동작 시나리오를 차례로 살펴보겠습니다.

SRE Observer의 처리 흐름

SRE Observer는 Alert 수신부터 상관분석 → AI RCA → 위험도 판단 → 1차/2차 대응 → 지식 축적까지를 하나의 파이프라인으로 잇습니다. 전체 흐름은 다음과 같습니다.

SRE Observer의 전체 흐름

  1. Alert Ingestion: Alert를 수신하는 단계입니다. Mimir Alertmanager는 메트릭 기반 규칙인 PromQL Rule(Mimir Ruler)과 로그 기반 규칙인 LogQL Rule(Loki Ruler)을 평가해 시스템의 이상 징후를 감지합니다. 조건에 맞는 이상 징후가 발견되면 Alert를 발생시키고, 이를 웹훅으로 발송합니다.
  2. Alert Correlation: Alert 간 관계를 분석하는 단계입니다. Temporal, Topology, Semantic의 세 축으로 채점해 단일 Incident로 묶습니다. 하나의 근본 원인에서 파생된 다수의 Alert를 소수의 Incident로 수렴시켜, 담당자가 확인해야 할 알림의 양을 크게 줄입니다.
  3. AI Analysis Agent: 원인을 분석하는 단계입니다. 가설-주도 RCA로 근본 원인과 영향 범위를 도출합니다.
  4. 위험도 판단: 분석 결과의 신뢰도를 평가하는 단계입니다. 근거 기반 가드레일(evidence guardrail)이 적용된 AI 신뢰도로 P1~P4를 확정하거나 미확정으로 둡니다.
  5. 1차 대응: 사람의 승인 없이 즉시 실행할 수 있는 대응 단계입니다. 심각도에 따라 Slack 담당팀 멘션과 에스컬레이션을 자동으로 실행합니다.
  6. 2차 대응: 시스템 상태를 바꾸는 작업을 실행하는 단계입니다. Pod 재시작, 롤백 같은 실제 작업은 승인(Approval Gate) 후 실행합니다.
  7. Post-Incident Knowledge: 장애 대응 결과를 지식으로 남기는 단계입니다. 확정된 P1 리포트를 사내 지식 베이스에 발행해 지식을 축적합니다.

각 구성 요소는 독립적으로 동작하되, Incident별 Alert, 분석 결과, 증거 등을 저장하는 Incident Context Store를 통해 필요한 맥락을 공유합니다. 아래에서 핵심 설계 세 가지를 자세히 살펴보겠습니다.

핵심 설계 1. 세 가지 축을 활용한 상관분석 — 노이즈를 하나의 Incident로 묶기

Alert 노이즈를 줄이려면 단순히 알림 개수를 줄이는 것을 넘어, 여러 Alert가 같은 장애에서 비롯된 것인지 판단할 수 있어야 했습니다.

세 가지 분석 축과 가중치

Alert 하나마다 Incident 하나를 만들면 같은 장애가 여러 스레드로 찢어져 노이즈가 폭발합니다. 반대로 무조건 합치면 관계없는 장애까지 한 Incident로 묶여 분석이 오염됩니다.

그래서 SRE Observer는 새 Alert 그룹이 도착할 때마다 이미 열려 있는 Incident 각각에 대해 세 축의 점수를 계산합니다.

Alert 그룹 분류 로직

세 축의 기준과 가중치는 다음과 같습니다.

분석 축가중치 우선순위기준
Semantic1 (높음)LLM을 통한 증상 의미 유사도 판단
Topology2Tempo Trace 기반 서비스 의존 관계
Temporal3 (낮음)시간적 근접성 (발생 시점)

SRE Observer는 세 점수를 가중치에 따라 합산한 뒤, 임계치 이상일 경우에만 기존 Incident에 병합합니다. 시간적 근접성(Temporal)만으로는 같은 장애로 단정하기 어렵기 때문에, 의미적 유사성(Semantic)과 의존 관계(Topology)에 더 높은 가중치를 부여했습니다.

예시로 보는 join 판정

세 축의 점수가 각각 높게 나온 Alert 그룹을 생각해 보겠습니다. 예를 들어 Temporal은 높음, Topology는 중간, Semantic은 높음으로 판단된 경우입니다. 각 점수에 위 가중치를 곱해 더한 합산 점수가 임계치를 넘으면 기존 Incident에 병합하고, 넘지 못하면 별개의 신규 Incident로 분리합니다. 이렇게 하면 ‘같은 시각에 발생했지만 사실은 다른 장애’를 억지로 묶거나, ‘다른 시각에 이어진 같은 장애’를 놓치는 실수를 함께 줄일 수 있습니다.

한 축만 과신하지 않기

여기서 중요한 설계 결정이 있습니다. Semantic 축은 LLM이 계산하지만, 무조건 믿지는 않습니다. LLM이 pair별로 반환한 신뢰도(confidence)가 일정 기준에 못 미치면, 그 Semantic 점수를 0점으로 낮춥니다. LLM이 ‘애매하게 비슷하다’고 본 경우는 join 판단에서 사실상 제외되는 것입니다.

또한 세 축을 항상 모두 사용할 수 있는 것도 아니었습니다. 서비스 의존 그래프가 없으면 Topology를 0점으로 낮추고 나머지 점수로 계속 판단합니다. LLM 가중치도 0이고 그래프도 없으면 temporal-only fallback으로 동작합니다. fallback은 기능이 실패했다는 뜻이 아니라, 사용할 수 없는 축을 제외하고도 시스템이 계속 동작하도록 만든 안전장치입니다.

Topology는 Tempo(Trace)에서 서비스 간 통신 내역을 확인해 계산합니다. Alert가 발생한 서비스를 기준으로 업스트림/다운스트림 연관 서비스를 찾아 점수를 매깁니다.

핵심 설계 2. 가설-주도 RCA — 도구 하나로 조기 종결하지 않기

상관분석으로 Incident가 확정되면 AI Analysis Agent가 RCA를 시작합니다. 이때 중요한 것은 LLM이 도구 하나의 결과만 보고 성급하게 결론짓지 않도록 막는 일이었습니다.

그래서 SRE Observer의 RCA는 명시적인 가설-주도(hypothesis-driven) 방식으로 동작합니다.

가설-주도 RCA 흐름

가설-주도 RCA: 5개 핵심 가설로 체계적 분석

Agent는 조사를 시작할 때 다음 5개 원인 가설을 반드시 모두 열거하며, 검토 없는 결론 도출을 금지합니다.

검토 대상 가설의 분류는 다음과 같습니다.

  • deployment_change(배포 변경)
  • resource_exhaustion(자원 고갈)
  • external_dependency(외부 의존성)
  • code_bug(코드 결함)
  • infra_platform(인프라/플랫폼)

각 가설의 판단 결과는 다음 세 가지로 구분합니다.

  • rule-in: 직접적인 관측 신호로 가설 충족
  • rule-out: 반박 신호 확인
  • other(원인 미특정): 5개 가설이 모두 rule-out 또는 cannot-verify일 때 적용(근거 없는 추측 지양)

초기 탐색은 가설과 증상에 따라 필요한 도구를 먼저 조회하는 방식으로 진행합니다.

가설/증상필수 도구 및 액션
클러스터 이슈Kubernetes 도구 1개 이상
CPU/메모리 압박Pyroscope (Hot function 확인)
배포 후보get_annotations
지연/타임아웃query_prometheus + tempo_traceql-search

데이터 소스 조회 원칙

첫 번째 조회 결과가 비어있더라도 ‘데이터 없음’으로 단정하지 않습니다. 데이터 소스/tenant별로 라벨과 필드가 다를 수 있으므로, 반드시 다른 후보 데이터 소스를 재시도해야 합니다.

증상에서 원인으로 좁혀 가기

RCA 결과는 단순히 어떤 증상이 나타났는지가 아니라, 그 증상이 어디에서 비롯됐는지까지 설명해야 합니다. 그래서 SRE Observer는 증상별로 다음과 같은 질문에 답하도록 설계했습니다.

  • latency(지연): 어느 다운스트림 호출이나 span에서 지연이 발생했는가
  • CPU: 어느 컨테이너, 자원 사용 함수, 입력 볼륨이 문제를 유발했는가
  • error(오류): 어느 예외 클래스 또는 코드 경로에서 오류가 발생했는가
  • saturation(포화): 어떤 자원이 고갈됐고 어떤 워크로드가 이를 유발했는가

Evidence Ledger로 근거를 누적해 결론 검증하기

Agent가 도구를 호출할 때마다 provider_category, tool_name, query_summary, observation_summary, raw_excerpt를 Evidence Ledger에 계속 기록합니다. 최종 결론을 낼 때는 이 Ledger를 바탕으로 실제로 근거가 있는지 다시 검증합니다.

근거가 없는데도 LLM이 code_bugexternal_dependency 같은 구체적 원인을 말하면, 앱은 그 결론을 그대로 믿지 않고 categoryother로 낮춥니다. 여기서 other는 ‘정확한 원인을 아직 특정하지 못했다’는 정직한 상태입니다.

탐색 범위를 제한해 무한 루프 막기

무한 탐색을 막기 위해 세 가지 제한을 둡니다.

  • Soft timeout: 조사 단계 종료 신호. 이 시점이 지나면 추가 수집을 멈추고, 이미 모은 근거로 최종 결론을 준비한다.
  • Hard timeout: RCA 전체 실행 시간의 절대 상한
  • Tool budget: 도구 호출 횟수 상한으로, 탐색 폭이 과도하게 넓어지는 것을 막는다.

각 값은 운영 중 조정할 수 있는 설정으로 두어, 분석에 필요한 깊이는 확보하되 무한 루프와 비용 폭증은 막는 균형점을 찾아간다.

핵심 설계 3. 위험도 판단 — 근거 수준에 맞게 신뢰도를 제한하기

RCA가 끝나면 LLM이 suggested_severity(p1~p4)와 신뢰도를 제안합니다. 하지만 앱은 이 값을 그대로 받지 않고 근거 기반 가드레일(evidence guardrail)을 적용해 chosen_confidence를 산출합니다.

AI 기반 심각도 판단 로직

심각도를 확정하기 위해서는 다음 세 조건을 모두 만족해야 합니다.

  • 가드레일이 개입한 강등 사유(degrade_reason)가 없어야 한다.
  • Incident 자체가 확정 상태(incident_confirmation)여야 한다.
  • 보정된 신뢰도(chosen_confidence)가 확정 기준선 이상이어야 한다.

이 조건을 모두 만족할 때만 제안된 심각도를 확정합니다. 하나라도 어긋나면 심각도는 ‘추정’ 상태로 남습니다.

가드레일로 신뢰도 제한하기

근거 기반 가드레일은 분석 결과가 확보된 근거보다 더 높은 신뢰도를 갖지 못하도록 제한합니다. 구체적으로는 다음과 같은 경우에 원인 분류나 신뢰도를 낮춥니다.

  • 근거가 없는데 구체적 원인을 말하면 categoryother로 낮추고 신뢰도도 함께 낮춤
  • resource_exhaustion인데 추세 쿼리(trend query)나 재시작/OOM 확인이 없으면 신뢰도를 더 낮게 제한

신뢰도는 근거 수준에 따라 단계적으로 부여됩니다.

  • 가장 높은 단계: 직접적이고 구체적인 근거가 있을 때만 허용하며, 이 단계에서만 심각도를 확정한다.
  • 높은 단계: 원인이 증상과 구분되고, 메트릭 외에 추가 근거(corroborating signal)가 하나 더 있어야 한다.
  • 중간 단계: 기여 요인은 보이지만 근본 원인(root cause)은 아직 불확실하다.
  • 낮은 단계: 증상 확인 수준이거나 근거가 부족하다.

핵심은 ‘직접 근거가 있을 때만 높은 신뢰도를 허용한다’는 것입니다. 근거 없이 높은 신뢰도를 주장하는 것을 가드레일이 막습니다.

추정에서 확정으로 승격하기

심각도는 처음부터 항상 확정되는 것이 아니라, 근거 수준에 따라 ‘추정’ 상태로 남거나 ‘확정’ 상태로 승격됩니다. 판단 기준은 다음과 같습니다.

  • 확정(confirmed): 강등 사유가 없고, Incident가 확정 상태이며, 보정된 신뢰도가 확정 기준선 이상일 때
  • 추정에서 확정으로 승격: 미확정 상태에서 재분석이나 새 Alert 합류로 근거가 쌓이면 같은 P1이라도 추정에서 확정으로 승격 가능
  • 확정 고정(latch): 한 번 확정되면 재분석해도 추정으로 되돌아가거나 다른 등급으로 바뀌지 않음

실제 시나리오로 보는 SRE Observer의 동작

설계 설명만으로는 ‘그래서 실제로 무엇이 달라졌나’가 잘 와닿지 않을 수 있습니다. 공개 가능한 형태로 서비스명과 식별자를 일반화한 두 가지 시나리오를 소개합니다.

업스트림 장애가 다운스트림 Alert 폭탄으로 번졌을 때

한 서비스(service-a)의 배포 직후, 그에 의존하는 여러 다운스트림 서비스(service-b, service-c, service-d)에서 타임아웃 Alert가 짧은 시간에 쏟아졌습니다.

기존 방식이었다면 담당자는 도착한 다수의 Alert를 하나씩 열어 ‘이게 같은 장애인가?’부터 일일이 판단하고, 대시보드, 로그, 트레이스를 오가며 공통 원인을 추적해야 했습니다. 알림을 인지하고 분류하는 것만으로도 초기 대응 시간이 소모됩니다.

이런 경우 SRE Observer는 수동 분류 과정을 Alert가 도착하는 순간부터 자동으로 대신하고, 첫 Alert가 도착한 시점을 T+0으로 두어 다음 흐름으로 처리했습니다.

  1. T+0: service-b의 타임아웃 Alert가 도착한다. 열려 있는 Incident가 없어 신규 Incident를 생성한다.
  2. T+1분: service-c, service-d의 타임아웃 Alert가 연이어 도착한다. 각 Alert 그룹에 대해 세 축 점수를 계산한다.
    • Temporal 높음 (거의 동시 발생)
    • Topology 중간 이상 (Tempo trace상 service-a를 공통 업스트림으로 공유)
    • Semantic 높음 (LLM이 동일 업스트림 타임아웃 증상으로 판단)
    • 가중 합산 점수가 임계치를 넘어 기존 Incident에 병합
  3. T+2분: 다수의 Alert가 하나의 Incident로 수렴되고 RCA가 시작된다.
  4. RCA: 5개 가설을 열거한 뒤, alert window 내 service-a repo의 배포 annotation과 최근 commit을 get_annotations로 확인한다. 그 결과 deployment_change를 rule-in으로 판단하고, resource_exhaustion, external_dependency 등 나머지 가설은 반증 신호로 rule-out 처리한다.
  5. 위험도: 배포가 원인이라는 근거가 명확했고, 보정된 신뢰도가 확정 기준선을 넘었기 때문에 P1으로 확정한다.
  6. 보고: Slack 스레드에 ‘근본 원인: service-a의 최근 배포, 영향 서비스: b/c/d, 권장 대응: 롤백’을 근거 링크와 함께 게시한다.

핵심은 담당자가 스레드를 열었을 때 이미 십수 개의 알림이 하나의 Incident로 묶여 있고 원인과 영향 범위, 대응안이 정리되어 있었다는 점입니다. 담당자는 알림을 분류하는 데 시간을 쓰는 대신, 정리된 근거를 바탕으로 판단부터 시작할 수 있었습니다.

근거가 부족할 때 '모른다'고 말하기

한 API 서비스(service-e)에서 요청 지연이 증가했습니다. 트레이스에는 1~2초 수준의 타임아웃 span과 HTTP 500이 반복적으로 나타났지만, 분석 시점에는 해당 서비스의 로그가 아직 Loki로 수집되기 전이었습니다.

RCA는 다음과 같이 진행됐습니다.

  • external_dependency, code_bug 등 여러 가설을 세웠지만, 로그 근거가 없어 대부분 cannot-verify로 남았습니다.
  • LLM은 초안에서 ‘다운스트림 의존성 문제’를 어느 정도 신뢰도와 함께 제안했습니다.
  • 하지만 근거 기반 가드레일이 개입했습니다. external_dependency를 rule-in할 직접 근거(트레이스가 지목한 업스트림/다운스트림 관계와 대상 서비스 내부 메트릭 정상 여부 등)가 부족했기 때문에, 앱은 categoryother로 강등했습니다. 구체적 원인을 확정할 근거가 없으면, 앱은 그럴듯한 원인 대신 ‘미특정(other)’으로 되돌립니다. 신뢰도도 함께 낮춰집니다.
  • categoryother로 강등되고 신뢰도가 확정 기준선에 못 미치면서, 심각도는 확정되지 않고 ‘추정’ 상태로 남았습니다.

Slack에는 다음과 같은 보고 메시지가 게시됐습니다.

현재 확보된 근거는 Tempo 트레이스이며, 서비스 내부에서 1~2초 지연과 status=error / HTTP 500이 발생했음을 보여 줍니다. 유력한 방향은 다운스트림 호출 지연이나, Loki 로그가 조회되지 않아 로그 기반 근거는 확보하지 못했습니다. 추가 근거 확보가 필요합니다.

이후 로그가 수집되면 Re-analyze 버튼으로 근거를 보강해 추정에서 확정으로 승격할 수 있습니다. 관측성 도구에서 ‘모른다’를 정직하게 말하는 것은 잘못된 확신을 주는 것만큼이나 중요합니다. 시스템이 근거 없이 단정하면 오히려 대응을 잘못된 방향으로 이끌기 때문입니다.

데모: Slack 스레드로 보는 Incident의 처리 흐름

앞의 시나리오가 실제로 어떻게 보이는지, Slack 화면으로 따라가 보겠습니다. SRE Observer의 인터페이스는 Slack이며, 하나의 Incident는 스레드 하나로 표현됩니다. 그 스레드는 시간이 지나면서 생성(Incident Created) → 병합(Alert Group Joined) → 분석(RCA Analyzing) → 결과(RCA Result)의 네 단계로 진행됩니다. 담당자는 이 스레드 하나만 열면 장애의 전체 맥락을 따라갈 수 있습니다.

1. Incident Created

첫 Alert가 도착하면 스레드가 생성되고, 하단에 Close Incident, Re-analyze 같은 작업자 버튼이 함께 표시됩니다.

Incident created

2. Alert Group Joined

세 가지 축 상관분석으로 같은 Incident라고 판단된 후속 Alert 그룹은 새 스레드를 만들지 않고 기존 스레드에 답글 형태로 합류합니다. 여러 알림이 하나로 묶이는 순간입니다.

Alert Group Joined

3. RCA Analyzing

RCA가 시작되면 가설 검증과 증거 수집 진행 상황이 스레드에 실시간으로 업데이트됩니다. 담당자는 자동화가 ‘지금 무엇을 하고 있는지’를 볼 수 있습니다.

RCA Analyzing

4. RCA Result

분석이 끝나면 근본 원인, 영향 서비스, 신뢰도, 권장 대응이 정리된 최종 RCA 결과가 게시됩니다. 심각도에 따라 담당팀 멘션과 에스컬레이션이 함께 적용됩니다.

RCA result

이렇게 Alert 하나에서 시작한 스레드가 스스로 병합, 분석, 보고를 마치면, 담당자는 알림을 분류하는 데 시간을 쓰는 대신, 정리된 근거를 바탕으로 판단부터 시작할 수 있습니다.

Slack 기반 Human-in-the-Loop 설계

Slack 스레드로 Incident 처리 흐름을 확인했다면, 다음으로 중요한 것은 이 흐름 안에서 사람이 어디에 개입하는가입니다. Slack은 Incident 상태를 보여 주는 인터페이스일 뿐 아니라, 사람이 위험한 작업을 승인하는 제어 지점이기도 합니다.

자동 대응 파이프라인에서 중요하게 고려해야 할 것은 ‘자동으로 무엇까지 해도 되는가’입니다. SRE Observer는 이 기준을 승인 경계(Approval Gate)로 정의하고, 실제 Operation 실행에만 적용했습니다. RCA 결과 공유에는 승인 경계를 적용하지 않습니다.

즉, 분석 결과를 Slack에 보고하는 것은 자동으로 하되, Kubernetes Pod를 재시작하거나 롤백하는 것처럼 시스템 상태를 바꾸는 작업은 사람의 승인을 받습니다.

승인 경계를 기준으로 대응은 1차 대응과 2차 대응으로 나뉩니다. 1차 대응은 시스템 상태를 바꾸지 않는 알림과 에스컬레이션 중심의 작업이며, 2차 대응은 실제 운영 환경에 영향을 줄 수 있는 작업입니다.

1차 대응 (즉시 자동 실행)

1차 대응은 사람의 승인 없이 즉시 실행할 수 있는 작업입니다. 심각도별로 다음과 같이 차등 실행합니다.

  • P1(Critical): 담당팀 알림 채널에 팀 멘션, 대응 채널에 즉시 에스컬레이션, 티켓과 Runbook 링크 제공
  • P2(Warning): 담당팀 멘션, 티켓과 Runbook 링크 제공 (1시간 내 대응)
  • P3(Notice): 티켓 생성 (다음 근무일)
  • P4 또는 P1 미확정: 스레드 종료

2차 대응 (승인 후 실행)

2차 대응은 시스템 상태를 바꾸거나 운영 환경에 직접 영향을 줄 수 있는 작업입니다. 이런 작업은 승인 경계를 거친 뒤 실행합니다.

  • P1/P2: Pod 재시작, 롤백, 스케일 조정, Alert Rule 임계치 조정
  • P3: 코드 수정 PR 자동 생성, DB 쿼리 최적화 제안

Slack에서 사용자가 할 수 있는 것

Slack 스레드에서는 자동 대응 결과를 확인하는 것뿐 아니라, 필요할 때 사용자가 Incident 흐름에 직접 개입할 수도 있습니다.

  • Close Incident: Incident를 종료합니다. 더 이상 다른 Alert 그룹이 병합되지 않고 RCA도 중단됩니다.
  • Re-analyze: RCA를 재시도합니다. 근거가 부족하거나 새 데이터가 확보됐을 때 실행합니다.

Incident는 포함된 Alert가 모두 Resolved로 처리되면 자동으로 종료됩니다. 문제가 해결됐는데도 Alert가 한동안 Firing 상태로 유지될 것으로 판단되면, 노이즈 제거를 위해 수동 종료할 수 있습니다.

운영 도구로 만들며 배운 것

SRE Observer를 실제 운영에 적용하기까지 수많은 개선 작업을 거쳤습니다. 그 과정에서 얻은 주요 교훈 몇 가지를 공유합니다.

근거 없는 확신을 막아야 한다

자동 대응 파이프라인에서 가장 경계해야 하는 것은, LLM이 그럴듯하지만 근거 없는 원인을 자신 있게 단정하는 일이었습니다. 앞서 소개한 Evidence LedgerEvidence Guardrail이 바로 이 위험을 줄이기 위한 장치였습니다.

여기서 강조하고 싶은 것은 이 설계가 단순한 기술적 장치가 아니라 운영 철학의 반영이라는 점입니다. 시스템이 근거 없이 원인을 단정하면, 사람이 직접 대응할 때보다 오히려 더 위험할 수 있습니다. 잘못된 확신은 대응을 엉뚱한 방향으로 이끌기 때문입니다. ‘모른다(other)’고 정직하게 말하는 능력은 SRE Observer 설계 전체를 관통하는 원칙입니다.

관측성 응답은 생각보다 크다

로그와 트레이스 조회 결과는 금세 수백 KB 규모로 커집니다. 이를 그대로 LLM에 넣으면 컨텍스트 창이 빠르게 가득 찹니다. 그래서 개별 도구 결과 크기를 제한하고, 잘렸다는 표시를 붙였습니다. 최종 결론 입력은 원본 데이터를 길게 다시 전달하는 대신 신호 요약(signal summary) 중심으로 압축했습니다. 신호 요약에는 발생한 메트릭 위반과 주요 트레이스, 의존성, 로그 유무를 담았습니다.

이렇게 신호 계층별로 근거를 고르게 정리한 덕분에, Loki 로그가 드물게 남는 상황에서도 Prometheus와 Tempo 신호가 결론 입력에서 밀리지 않게 됐습니다.

데이터 소스와 라벨 차이는 자동화의 큰 복병이다

같은 서비스명이라도 Prometheus 계열은 service_name, Tempo는 resource.service.name을 사용합니다. Loki에서는 에러 레벨이 로그 본문 JSON이 아니라 구조화된 메타데이터에 들어 있기도 합니다. 이러한 차이를 명문화하지 않으면 Agent는 올바른 데이터 소스를 선택해도 결과를 찾지 못할 수 있습니다.

이를 해결하기 위해 여러 tenant를 순회하는 Mimir 조회, Loki tenant 라벨 주입, cAdvisor 라벨 기준 안내 등 데이터 소스별 조회 관습을 RCA 프롬프트에 지속적으로 반영했습니다.

앞으로의 계획

SRE Observer는 현재 운영 과정에서 얻은 피드백을 바탕으로 다음 영역을 계속 확장할 계획입니다.

  • Burn-rate-aware severity policy: error budget 소모 속도(Burn Rate)를 심각도 확정에 반영해, 단순 에러율이 아니라 ‘얼마나 급한가’를 판단에 넣을 예정입니다. 소모 속도가 빠를수록 높은 심각도로 매핑하는 방식입니다.
  • 2차 대응 자동 조치(remediation) 확대: 현재 승인 경계 안에서 제한적으로 동작하는 자동 조치를 안전하게 확대할 계획입니다.
  • 장애 대응 지식(post-incident knowledge) 강화: 확정된 P1 리포트를 사내 지식 베이스에 발행해 반복되는 장애 패턴을 조직 지식으로 축적합니다.

마치며

SRE Observer는 Alertmanager에 챗봇을 붙인 도구가 아닙니다. 목표는 사람이 알림을 인지하기도 전에 시스템이 스스로 신호를 연결하고, 근본 원인을 찾아 보고하는 자동 대응 파이프라인을 만드는 것이었습니다.

핵심은 ‘얼마나 많이 자동화했는가’가 아니라 ‘어디까지 자동화하고 어디서 사람의 판단과 승인을 받을 것인가’였습니다. 세 가지 축의 상관분석으로 노이즈를 줄이고, 가설-주도 RCA로 근거를 쌓고, 근거 기반 가드레일로 과신을 막고, 승인 경계로 위험한 작업을 통제하는 이 모든 설계가 그 질문에 대한 답이었습니다.

물론 모든 장애를 자동으로 해결할 수 있는 것은 아닙니다. 하지만 SRE Observer는 적어도 새벽 3시에 울린 알림 앞에서, 담당자가 도구를 열기 전에 이미 ‘어디를 봐야 하고, 어떤 근거가 있으며, 무엇이 부족한지’를 정리해 둡니다.

비슷한 고민을 하고 계신 SRE, 플랫폼 엔지니어, LLM 애플리케이션 개발자분들께 이 글이 작은 참고가 되기를 바랍니다. 읽어주셔서 감사합니다.