# Alert 시스템을 표준화하고 IaC로 운영하기

> Clean Markdown view of GeekNews topic #30986. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=30986](https://news.hada.io/topic?id=30986)
- GeekNews Markdown: [https://news.hada.io/topic/30986.md](https://news.hada.io/topic/30986.md)
- Type: news
- Author: [dongho42](https://news.hada.io/@dongho42)
- Published: 2026-07-01T09:09:22+09:00
- Updated: 2026-07-01T09:09:22+09:00
- Original source: [engineering.ab180.co](https://engineering.ab180.co/stories/standardizing-alert-system-with-iac)
- Points: 7
- Comments: 0

## Topic Body

#### 들어가며  
  
서비스가 커지면서 운영 중 확인해야 할 신호도 함께 늘어났습니다. 이 글에서는 **Alert을 코드로 관리하고**, **Slack과 PagerDuty로 이어지는 대응 흐름을 표준화한 과정**을 소개합니다.  
  
처음 목표는 단순했습니다. **Alert을 더 쉽게 만들고, 더 보기 좋게 보내고, 누가 봐야 하는지 명확히 하는 것.** 이후 운영을 이어가며 grouped Alert, 반복 정의, 대응 자동화, 모니터링 시스템의 안정성까지 함께 다듬었습니다.  
  
---  
  
#### 동기  
  
서비스의 가용성을 높이고 사용자 임팩트를 줄이는 방법은 여러 가지가 있음  
  
그중 이번 작업은 **Alert 시스템 개선**에 집중  
  
Alert은 장애 예방과 장애 대응 사이를 잇는 *운영 인터페이스*에 가까움. 위험 신호를 더 빨리 발견하면 실제 장애로 이어지기 전에 조치할 수 있고, 장애가 발생한 뒤에도 담당자가 더 빠르게 인지하고 대응을 시작할 수 있음  
  
당시 개선하고 싶었던 방향도 분명했음. **위험 신호를 더 잘 잡고**, **담당자가 더 빨리 알아차리게 하고**, **조사와 대응으로 곧바로 이어지게 하고**, **반복되는 대응 흐름은 줄이고 싶었음**  
  
처음부터 모든 것을 정량적으로 측정하고 시작한 것은 아니었지만, Alert이 단순한 알림이 아니라 **장애를 예방하고 대응으로 연결하는 운영 시스템**이 되어야 한다는 문제의식은 분명했음  
  
---  
  
#### Alert의 역할  
  
안정적인 서비스를 위해서는 장애를 예방하는 것도 중요하지만, 운영 중인 서비스의 이상 징후를 빠르게 감지하는 것도 중요함  
  
Alert은 이 지점에서 두 가지 역할을 함. 장애가 발생하기 전에는 **위험 신호를 빠르게 인지하고 실제 장애로 이어지기 전에 미리 조치**하게 돕고, 장애가 발생한 뒤에는 **담당자에게 문제를 알리고 상황 파악에 필요한 컨텍스트와 Runbook, Dashboard, Log, Silence 같은 다음 행동으로 연결**해줌  
  
즉 Alert은 단순히 `"문제가 생겼다"`고 알려주는 알림이 아니라, **장애 예방과 대응을 이어주는 운영 인터페이스**에 가까움  
  
---  
  
#### 기존 Alert들의 아쉬웠던 점  
  
기존 Alert에서 크게 아쉬웠던 점은 세 가지였음. **만들기 어렵고**, **받아도 바로 이해하기 어렵고**, **누가 대응하고 관리해야 하는지 명확하지 않았음**  
  
##### Alert을 만들기 어려움  
  
당시 Alert 생성과 전달에는 Grafana, Slack, PagerDuty, CloudWatch, EventBridge, Lambda 등 여러 시스템이 얽혀 있었고, 데이터 소스도 NewRelic, VictoriaMetrics, Steampipe, OpenSearch, Druid, MySQL 등으로 다양했음  
  
Alert마다 작업 방식도 달랐음. 어떤 Alert은 Grafana에서 Slack으로 바로 보냈고, 어떤 것은 CloudWatch Alarm 뒤에 Lambda를 붙였고, 어떤 것은 Steampipe로 AWS 리소스 상태를 조회해 판단했으며, PagerDuty 연동이 필요한 경우에는 별도 설정까지 고려해야 했음  
  
문제는 **조직 차원의 컨벤션이 부족했다는 점**이었음. 어떤 Alert을 어디에서 관리할지, Slack만 보낼지 PagerDuty까지 연결할지, 메시지에는 어떤 설명과 링크를 넣을지, 담당 팀과 전달 경로는 어디에서 관리할지 정리가 덜 되어 있었음  
  
결과적으로 Alert은 필요할 때마다 만들어졌지만, 시간이 지날수록 생성 방식과 관리 방식은 점점 **파편화**  
  
##### Alert을 보기 어려움  
  
Alert을 만들었다고 해서 실제 Slack 메시지가 항상 보기 좋은 형태였던 것은 아니었음. 만든 사람과 시스템에 따라 포맷과 정보의 품질이 달랐고, 어떤 Alert은 제목이 길고 복잡했으며, Value나 Labels 같은 내부 값이 그대로 노출되기도 했음  
  
링크가 있더라도 무엇을 먼저 봐야 하는지 명확하지 않은 경우가 있었고, Dashboard나 Log 버튼이 있어도 실제 연동이 안 된 경우도 있었음. 또 Alert의 context가 부족해 담당자가 서비스, 클러스터, 리소스, 시간 범위를 다시 찾아야 하는 경우도 많았음  
  
장애 상황에서는 몇 분 차이도 크게 느껴짐. 그래서 Alert을 받는 순간 **이게 무슨 문제인지**, **얼마나 중요한지**, **어느 서비스와 리소스의 문제인지**, **어디를 먼저 확인해야 하는지**, **다음 행동이 무엇인지** 바로 파악할 수 있어야 했음  
  
##### Alert의 대응 책임 관리가 어려움  
  
Alert이 울렸을 때 누가 확인하고 대응해야 하는지도 애매한 경우가 있었음. 담당 팀이나 담당자가 드러나지 않으면 Alert을 본 사람이 먼저 `"이건 내가 봐야 하나?"`, `"누구에게 물어봐야 하지?"`부터 판단해야 하고, 장애 상황에서는 이 짧은 판단도 대응 지연으로 이어질 수 있음  
  
또 Alert이 울린 뒤의 대응 책임뿐 아니라, **Alert 자체를 누가 소유하고 관리하는지**도 중요했음. 어떤 팀의 서비스와 관련된 Alert인지, 누가 조건을 변경할 수 있는지, 메시지나 임계치를 어떻게 검토할지, 오래된 Alert은 누가 정리할지까지 함께 드러나야 했음  
  
정리하면 개선하고 싶었던 상황은 다음과 같았음  
  
- **Alert을 만들고 관리하는 방식이 파편화**  
- **Alert을 받아도 무슨 의미인지 한눈에 파악하기 어려움**  
- **Alert이 울렸을 때 누가 확인하고 대응해야 하는지 애매함**  
- **Alert 자체를 어떤 팀이 소유하고 관리해야 하는지도 불명확**  
  
---  
  
#### 무엇을 어떻게 개선했나  
  
개선 방향은 세 가지였음. **Alert을 만드는 방식을 표준화하고**, **Slack 메시지에서 필요한 정보를 일관된 구조로 제공하고**, **Alert마다 담당자와 전달 경로가 드러나도록 구조를 정리하는 것**  
  
##### Alert 생성과 관리 방식 표준화하기  
  
먼저 Alert 생성과 관리 방식을 하나로 모음. Alert rule 평가와 실행은 **Grafana로 통일**했고, Grafana·Slack·PagerDuty 사이의 연동은 **Terraform Module로 추상화**했으며, 모든 Alert 정의는 사내 alerts 레포의 `alerts/` 디렉터리 아래에서 **IaC로 관리**하게 했음. Slack 채널 연결, PagerDuty 연동, 메시지 포맷, 공통 버튼 생성도 공통 모듈이 처리하도록 정리했음  
  
이제 Alert 작성자는 전체 Alert 파이프라인을 모두 이해하기보다, **어떤 조건을 감지할지**, **얼마나 중요한 Alert인지**, **누가 확인해야 하는지**, **대응에 어떤 정보가 필요한지**에 더 집중할 수 있게 됨  
  
레포 안에는 작성 방식, 디렉터리 구조, 필요한 필드, 권장 컨벤션을 함께 관리했고, Alert을 코드로 관리하면서 리뷰와 변경 이력도 PR과 커밋 단위로 남게 됨  
  
##### Alert 디렉터리 구조  
  
모든 Alert은 `{main-category}/{sub-category}/{severity}/{alert-name}.yml` 구조를 따르도록 정리했음  
  
예를 들면 다음과 같음  
  
- `infra/kubernetes/critical/pod-unhealthy.yml`  
- `data/airflow/warning/task-failed.yml`  
- `finops/aws/warning/cost-increase.yml`  
  
이 구조를 통해 파일 위치만 봐도 **어떤 영역의 Alert인지**, **어느 정도 심각도로 다루는지** 파악할 수 있게 했고, 특정 영역의 Alert을 모아보거나 중복 Alert과 오래된 Alert을 점검하거나 Slack 채널, PagerDuty Service, CODEOWNERS를 연결하는 기준으로도 활용할 수 있게 했음  
  
##### Alert 정의 방식  
  
각 Alert 파일에는 `datasource`, `query`, `threshold`, `condition`, `message` 같은 정보를 함께 넣음  
  
별도의 DSL을 새로 만들지는 않았음. Grafana Alert이 JSON으로 직렬화된 내용을 YAML로 표현한 것에 가까웠고, 덕분에 Grafana에서 정의할 수 있는 Alert이라면 대부분 같은 구조로 IaC화할 수 있었음  
  
최근에는 LLM도 활용하고 있음. 사람이 자연어로 `"어떤 조건에서 어떤 메시지로 Alert을 받고 싶다"`고 설명하면, LLM이 기존 예시와 컨벤션을 참고해 YAML 형태의 Alert 정의 초안을 만들어주는 방식. 덕분에 Alert 작성자는 복잡한 직렬화 형식보다 **무엇을 감지하고 왜 필요한지**에 더 집중할 수 있게 됨  
  
##### Alert 메시지를 바로 이해하고 대응할 수 있게 만들기  
  
Alert 메시지도 하나의 *인터페이스*라고 봤음. 장애 상황에서는 메시지를 천천히 해석할 여유가 많지 않기 때문에, 어떤 Alert이 오더라도 같은 위치에서 같은 종류의 정보를 확인할 수 있어야 했음  
  
그래서 Slack 메시지 구조를 일관되게 정리했음. 제목에는 Alert 이름, 상태, 심각도를 담고, 본문에는 사람이 바로 이해할 수 있는 설명과 담당자, 팀, 서비스, 리전, 리소스 이름, 주요 라벨을 넣음. 버튼도 공통 버튼과 선택 버튼으로 나눠, 기본적으로는 **IaC, PagerDuty, Silence**를 제공하고 필요할 때만 **Runbook, Dashboard, Log**를 표시하도록 했음  
  
공통 버튼은 시스템에서 자동 생성해 연결되도록 했고, Alert 상태 변화도 모두 Slack thread에 남기게 했음. 누가 Acknowledge 했는지, Slack에서 처리했는지 PagerDuty에서 처리했는지, 언제 Resolve 되었는지, 대응 중 어떤 메모가 남았는지까지 하나의 흐름으로 볼 수 있게 한 것  
  
결과적으로 누가 어떤 Alert을 만들더라도 Slack에서 보이는 형태가 비슷해졌고, 구성원들이 어디를 봐야 하는지 더 빠르게 판단할 수 있게 됨  
  
##### Alert 책임 구조를 명확히 하기  
  
Alert을 보고 바로 이해하는 것만큼 중요한 것은, 그 Alert을 **누가 책임지고 확인해야 하는지** 드러나게 하는 일이었음  
  
그래서 리소스의 태그와 레이블 정보를 대응 흐름에 활용했음. Alert마다 담당 팀이나 담당자를 직접 지정하기보다, 서비스·팀·리소스·환경 같은 메타데이터를 사용해 Slack 메시지에서 적절한 담당 팀과 담당자가 자동으로 mention되도록 했음  
  
전달 경로도 같은 규칙 안에서 정리했음. Alert의 분류와 severity를 기준으로 Slack 채널, PagerDuty Service, Escalation Policy가 자동 연결되도록 했고, Warning 수준의 Alert은 Slack 채널로만 전달하고, 사용자 임팩트나 장애 가능성이 큰 Critical Alert은 PagerDuty Incident까지 생성하게 했음  
  
CODEOWNERS도 함께 활용했음. Alert 파일은 카테고리와 서비스 영역에 따라 디렉터리로 구분하고, 각 경로별 담당 팀을 CODEOWNERS에 지정해 어떤 팀이 어떤 Alert 영역을 소유하는지 레포 안에서 드러나게 했음  
  
결과적으로 Alert 책임은 두 지점에서 관리되도록 함. **Alert이 실제로 울렸을 때는 태그와 레이블 기반으로 담당 팀과 담당자가 mention**되고, **Alert 정의를 변경할 때는 디렉터리 구조와 CODEOWNERS를 기준으로 어느 팀의 영역인지 확인**됨  
  
##### Alert proxy의 역할  
  
이 구조가 실제로 동작하려면 중간에서 Alert을 해석하고 전달하는 계층이 필요했음. 그래서 Grafana와 Slack, PagerDuty 사이에 **AWS Lambda 기반 proxy**를 둠  
  
Grafana는 Alert rule을 평가하고 webhook을 보냄. proxy는 이 webhook을 받아 category, severity, label, annotation, fingerprint 같은 Alert context를 해석하고, 어느 Slack 채널에 보낼지, 어떤 PagerDuty Incident를 만들지, 누구를 mention할지, 어떤 버튼을 붙일지, 기존 Slack thread를 어떻게 업데이트할지, Ack/Resolve lifecycle을 어떻게 관리할지를 결정함  
  
즉 Terraform module과 디렉터리 구조가 **"Alert을 어떻게 정의할 것인가"** 를 표준화했다면, proxy는 그 정의가 실제 운영 흐름에서 같은 방식으로 보이고 동작하도록 연결하는 역할을 맡은 셈임  
  
proxy 덕분에 Slack 메시지 포맷, 담당자 mention, PagerDuty 연동, Slack thread 업데이트, Ack/Resolve 상호작용을 한곳에서 일관되게 관리할 수 있었고, 이후 grouped Alert, custom action button, AI 에이전트 연동, 공통 Alert model 같은 개선도 수월하게 확장할 수 있었음  
  
---  
  
#### 뭐가 또 아쉬웠나  
  
첫 번째 개선 이후 Alert 정의는 IaC로 관리되었고, Slack 메시지와 전달 경로도 일관된 규칙 아래 동작하게 됨. 하지만 Alert 시스템은 한 번 만들고 끝나는 도구가 아니었음. 1년 가까이 운영해 보니, Alert이 많아질수록 같은 Alert 안에서 생긴 여러 instance를 어떻게 보여줄지, 반복되는 Alert 정의를 어떻게 관리할지, 사람이 Alert을 본 뒤 실제로 무엇을 할 수 있게 만들지, Alert 시스템 자체의 안정성을 어떻게 확보하고 검증할지 같은 새로운 문제가 보이기 시작함  
  
##### 같은 Alert이 여러 대상으로 동시에 울리면 보기 어려움  
  
Alert을 만들기 쉬워지면서 Alert 수도 자연스럽게 늘어남. 이때 특히 불편했던 것은 하나의 Alert rule이 여러 대상에 대해 동시에 울리는 경우였음  
  
Grafana에서는 같은 rule이라도 `region`, `name`, `node`, `pod`, `app` 같은 label 값이 다르면 각각을 별도 Alert instance로 봄. 예를 들어 Pod unhealthy Alert이 있을 때 여러 pod가 동시에 unhealthy 상태가 되면 pod마다 Alert instance가 생김  
  
Grafana에는 이미 Alert Grouping 기능이 있었지만, 단순히 group으로 묶는 것만으로는 부족했음. 중요한 것은 묶인 Alert의 상태를 운영자가 이해하기 쉽게 보여주는 것이었고, group 안에 어떤 대상들이 있는지, 누가 아직 firing인지, 누가 방금 resolve되었는지, 새로 추가된 대상이 있는지, 같은 group의 상태 변화가 하나의 흐름으로 이어지는지가 중요했음  
  
##### 반복되는 Alert 정의가 늘어남  
  
Alert 정의가 많아질수록 YAML을 복사해 조금씩 바꾸는 방식도 한계를 보임. SQS lag, CloudWatch error log, Pod OOM, ALB 5xx, Lambda error/throttle 같은 Alert은 반복적으로 만들게 되었고, 처음에는 기존 파일을 복사해 이름, query, threshold, label만 바꾸면 됐음  
  
하지만 파일이 많아지자 공통 동작을 고치기 어려워지고, 같은 의도의 Alert인데도 dashboard 링크, labels 구성, threshold 표현이 조금씩 달라지는 문제가 생김. 그래서 **반복되는 패턴을 재사용할 수 있는 구조**가 필요했음  
  
##### Alert을 보고 나서도 다음 행동까지 거리가 있음  
  
Slack 메시지에 Runbook, Dashboard, IaC, PagerDuty 버튼을 붙인 것은 도움이 됐지만, 실제 장애 대응에서는 링크만으로 충분하지 않은 경우가 많았음. 특히 Runbook은 효과가 분명했지만, 모든 Alert에 좋은 Runbook을 붙이고 계속 최신 상태로 유지하는 것은 쉽지 않았음  
  
또 실제 대응에서는 Kubernetes 로그 확인, pod 상태 확인, rollout history 확인, SQS·Lambda 지표 확인, error log 확인처럼 매번 비슷한 조사 작업이 반복됨. 이런 작업은 대부분 Slack 메시지 밖에서 이루어졌고, 담당자는 Alert에서 label과 value를 읽고 다른 도구로 이동해 값을 옮긴 뒤 결과를 다시 Slack thread에 공유해야 했음  
  
결국 첫 번째 개선으로 Alert을 더 잘 읽을 수 있게는 됐지만, 조사와 대응은 여전히 Alert 메시지 바깥에 많이 남아 있었음  
  
##### 모니터링 시스템에 SPOF가 늘어남  
  
Alert 시스템을 정리하면서 SPOF가 될 수 있는 지점도 늘어남. Alert rule의 정의와 배포는 alerts 레포와 Terraform에 모였고, Alert rule의 평가는 Grafana가 맡았으며, Slack 메시지·PagerDuty Incident·Ack/Resolve lifecycle은 proxy가 관리하게 됐음  
  
역할이 명확해진 것은 좋은 변화였지만, 그 지점이 실패했을 때 전체 Alert 흐름이 영향을 받을 가능성도 커짐. 더 어려운 점은 이런 실패가 겉으로 잘 드러나지 않을 수 있다는 것. 다른 시스템의 이상을 알려주는 경로가 조용히 멈추면, 실제 장애가 발생해도 아무도 모를 수 있음  
  
결국 *"모니터링 시스템은 누가 모니터링할 것인가"* 라는 질문으로 이어짐  
  
---  
  
#### 두 번째 개선  
  
첫 번째 개선으로 Alert 시스템의 기본 골격은 잡혔지만, Alert을 만들고 보내는 일이 쉬워지자 운영하면서 봐야 할 문제도 달라짐  
  
두 번째 개선에서는 네 가지에 집중했음. **같은 Alert rule에서 여러 대상이 동시에 울릴 때 상태 변화를 하나로 묶어 한눈에 보여주고**, **반복되는 Alert 정의를 공통 패턴으로 재사용할 수 있게 만들고**, **Runbook을 보완하면서 반복되는 조사와 제한적인 완화 작업을 Slack 버튼으로 연결하고**, **SPOF가 될 수 있는 Alert 정의·평가·전달 경로의 안정성을 측정하고 검증하는 것**  
  
##### Grouped Alert을 제대로 다루기  
  
먼저 grouped Alert의 표현 방식을 개선했음. 같은 Alert rule에서 여러 instance가 동시에 발화할 때 각각을 독립 메시지로 보내면 Slack 채널이 복잡해지고, 반대로 group 하나로만 뭉뚱그리면 실제로 어떤 리소스가 문제인지 놓치기 쉬움  
  
핵심은 **묶되, 묶인 안쪽의 상태를 잃지 않는 것.** Slack에서는 grouped Alert을 대표 메시지 하나로 보여주되 현재 영향을 받는 대상들을 함께 표시하도록 했고, 새 대상이 추가되거나 기존 대상이 해결되면 그 변화는 같은 thread에 남기게 했음. 상태 변화가 한 번에 많이 생길 때는 여러 변화를 batch로 묶어 보여주도록 했고, PagerDuty 쪽도 Slack에서 보는 grouped Alert과 같은 문제를 가리키도록 맞춤  
  
결과적으로 같은 원인에서 나온 여러 Alert을 Slack에서 **하나의 흐름**으로 볼 수 있게 됨  
  
##### 반복되는 Alert 정의 줄이기  
  
복사해서 조금씩 바꾸는 방식은 Alert 수가 늘어날수록 유지보수 비용과 실수 가능성을 키움. 이를 줄이기 위해 `global/templates`와 `matrix`를 추가했음  
  
`global/templates`는 반복되는 Alert 구조를 공통 template으로 정의하는 기능이고, `matrix`는 같은 Alert을 여러 리전, queue, datasource, service 조합으로 펼쳐 여러 Alert으로 생성하는 기능임  
  
SQS queue lag, CloudWatch error log, 여러 클러스터의 Pod OOM, ALB 5xx, Lambda error/throttle, ECS memory/CPU/max-capacity 같은 반복 패턴을 template으로 만들고, queue 이름, region, cluster, threshold, dashboard 변수처럼 달라지는 값만 matrix에 입력하도록 함  
  
이렇게 하니 공통 메시지 구조, 버튼, Runbook/dashboard 링크 처리, datasource 처리 방식을 한곳에서 고칠 수 있게 됐고, Alert이 많아질수록 생기는 불일치와 유지보수 비용도 줄일 수 있었음  
  
##### Slack 메시지에서 바로 대응 시작하기  
  
다음으로는 Slack 메시지 안에서 할 수 있는 일을 늘림. Runbook과 dashboard 링크는 여전히 중요하지만, 매번 비슷하게 반복하는 조회나 제한적인 완화 작업은 Slack 메시지 안에서 줄이고 싶었음  
  
그래서 기존 버튼 외에 **custom action button**을 추가했음. Alert YAML의 `message.actions`에 명령을 정의하면 Slack 메시지에 버튼으로 표시되고, 버튼을 누르면 proxy가 별도 Lambda invocation으로 명령을 실행한 뒤 누가 어떤 버튼을 눌렀는지와 실행 결과를 같은 Slack thread에 댓글로 남김  
  
이 버튼으로 로그 조회, Kubernetes rollout 상태 확인, 제한된 상황에서의 rollout restart, 단일 명령 실행, 여러 명령의 순차 실행 같은 작업을 제공할 수 있게 함  
  
가장 신경 쓴 부분은 **안전성**이었음. 버튼 이름이 `!`로 끝나면 Slack confirm dialog를 띄우고, `${labels.namespace}`, `${labels.pod}` 같은 label 값을 명령에 치환하되 shell quoting을 적용해 command injection을 막았고, 추가 권한이 필요한 작업은 `actionRole`을 통해 IAM role을 assume하도록 했음. 허용되지 않은 role 사용은 `fail-closed`로 처리했고, webhook과 Slack 상호작용도 각각 Bearer token, HMAC-SHA256 서명과 replay protection으로 검증함  
  
##### AI 에이전트와 연동하기  
  
Alert을 받은 뒤 필요한 정보를 모으는 과정도 줄이고 싶었음. 그래서 내부 AI 에이전트인 **abot**을 Alert 흐름에 연결했음  
  
Slack 메시지의 abot 버튼을 누르면 proxy가 Alert 이름, 설명, labels, values, IaC 링크, 사용자가 modal에서 추가로 입력한 context를 모아 분석 요청을 보냄. abot은 버튼을 누른 사람의 OAuth 기반 identity로 동작하도록 해, Grafana·AWS·Kubernetes 등 필요한 정보를 조회하더라도 사용자가 실제로 볼 수 있는 범위 안에서만 가져오도록 했음  
  
분석 결과는 같은 Slack thread에 댓글로 남김. 어떤 지표와 로그를 확인했는지, 어떤 가능성을 우선 의심할 수 있는지, RCA에 정리할 만한 단서가 무엇인지까지 함께 남기게 했고, 덕분에 여러 시스템을 열어 정보를 다시 모으는 시간을 줄일 수 있었음  
  
##### 모니터링 시스템 모니터링하기  
  
두 번째 개선에서는 Alert을 정의하고 평가하고 전달하는 과정 자체도 관측 대상에 포함했음  
  
먼저 proxy의 운영 지표를 모았음. Ack까지 걸린 시간, Resolve까지 걸린 시간, 지금 떠 있는 Alert 수, Alert이 얼마나 오래 떠 있는지, 같은 Alert이 다시 울린 횟수 같은 지표를 수집했고, Lambda가 timeout에 가까워지면 감지하는 watchdog도 추가했음. proxy가 처리 도중 실패하면 full stack trace와 원본 event payload를 함께 남기도록 했음  
  
하지만 proxy가 직접 알리는 방식에는 한계가 있었음. proxy가 그 알림조차 보내기 전에 죽으면, 보내졌어야 할 Alert이 그대로 누락될 수 있기 때문  
  
그래서 proxy 바깥에 서로 다른 시스템에 기대는 감지 장치를 둠. 하나는 Grafana로, proxy가 보낸 metric을 monitoring 도메인의 Alert으로 평가해 이상을 드러내도록 했음. 다만 Grafana와 VictoriaMetrics가 같은 EKS 위에 있기 때문에, EKS나 Grafana가 통째로 죽으면 감지할 수 없음  
  
다른 하나는 **deadman switch**였음. Grafana는 정상일 때 `/api/health`를 heartbeat로 내보내고, heartbeat는 EKS와 독립된 CloudWatch가 받음. CloudWatch alarm은 heartbeat가 떨어지거나 missing이면 장애로 판단하고, 이 경우 Grafana나 proxy를 거치지 않고 PagerDuty와 Slack으로 바로 알리게 했음  
  
감지하는 쪽과 감지되는 쪽을 서로 다른 인프라에 둔 셈이고, 덕분에 EKS와 CloudWatch가 동시에 죽지 않는 한 모니터링 시스템의 다운을 알 수 있게 됨  
  
---  
  
#### 이후 개선 과제  
  
두 번째 개선은 마쳤지만, 아직 더 개선해야 할 부분이 남아 있음  
  
##### 수집한 운영 지표를 제대로 활용하기  
  
proxy가 Alert 운영 지표를 수집하면서 어느 채널에 어떤 Alert이 얼마나 자주 울리는지, 특정 담당자나 팀에게 Alert이 과하게 몰리지는 않는지, 아무런 상호작용 없이 firing과 auto resolve만 반복하는 Alert은 없는지 같은 질문에 데이터로 답할 수 있게 됨  
  
하지만 데이터를 볼 수 있는 것과, 이를 근거로 실제 Alert을 다듬는 것은 별개의 일임. 아직은 임계치 조정, 비슷한 Alert 묶기, 불필요한 Alert 제거, noisy alert 줄이기, 인지 시간과 해결 시간을 실제로 줄이는 방향의 개선을 본격적으로 하지는 못했음  
  
##### Alert IaC 개선  
  
현재 Alert 정의는 alerts 레포에서 CI/CD로 배포되지만, 아직은 Grafana Terraform provider의 `grafana_rule_group` 리소스에 의존하고 있음. 문제는 rule 하나만 바꿔도 PR에서는 rule group 전체가 바뀐 것처럼 보여 diff가 보기 어렵고, `interval_seconds`가 rule group 단위라 Alert마다 다른 평가 주기를 주기 위해서는 group을 잘게 쪼개야 한다는 점임  
  
최근 Grafana에는 Alert rule을 Kubernetes 리소스처럼 다루는 새 alerting API가 생겼고, Terraform provider에도 `grafana_apps_rules_alertrule_v0alpha1` 리소스가 추가됨. 아직 alpha라 당장 도입은 보류하고 있지만, stable해지면 기존 `grafana_rule_group` 대신 옮기는 것을 검토하려 함  
  
기대하는 점은 분명함. **rule group과 rule을 분리해 정의하고**, **rule 하나만 바꿔도 그 변경만 깔끔하게 드러나는 diff를 얻고**, **rule마다 평가 주기를 세밀하게 조정하고**, **모니터링 자원을 더 효율적으로 사용하는 것**  
  
---  
  
#### 마치며  
  
처음 목표는 단순했음. **Alert을 더 쉽게 만들고, 받았을 때 한눈에 이해할 수 있게 하고, 누가 책임지는지 분명하게 만드는 것**  
  
1차 개선으로는 Alert 정의를 IaC로 모으고, Slack 메시지와 전달 경로를 표준화하고, 담당자 mention과 CODEOWNERS를 연결하고, proxy를 통한 Slack/PagerDuty lifecycle 관리를 정리했음  
  
운영을 이어가며 드러난 문제는 2차 개선에서 손봄. 같은 rule에서 쏟아지는 Alert을 하나로 묶어 보여주고, 반복되는 정의를 template과 matrix로 줄이고, Slack 메시지 안에서 조사와 완화를 시작할 수 있게 하고, 모니터링 시스템 자신이 멈췄을 때 알아차릴 장치도 마련했음  
  
덕분에 Alert을 만들고, 보내고, 대응하는 일은 전보다 수월해짐  
  
다만 데이터를 볼 수 있게 된 것과, 그 데이터를 근거로 실제 운영을 개선하는 것은 별개의 일임. 지금까지가 **Alert 시스템을 표준화하고 측정할 수 있게 만드는 일**이었다면, 이제부터는 그 수치를 보며 **실제로 줄이고 다듬는 일**이 남았음  
  
---  
  
이 글에는 분량상 담지 못한 내용이 있습니다. 더 자세한 내용이 궁금하신 분들은 원글도 함께 읽어보시는 것을 추천드립니다.

## Comments



_No public comments on this page._
