korean-docs
추가 기능
Alerts
동작 방식

Alerts 동작 방식

이 페이지에서는 Wave Alerts 시스템의 아키텍처, 평가 파이프라인, 전송 메커니즘을 기술적으로 상세히 다룹니다.

아키텍처 개요

Wave Alerts 아키텍처

데이터 모델

Alert 채널

Alert 채널은 다음과 같은 스키마로 저장됩니다.

struct AlertChannel {
    id: String,                        // UUID v7
    name: String,                      // Human-readable name
    alert_channel_type: AlertChannelType, // http | slack_webhook | slack_web_api
    metadata_json: AlertChannelData,   // Type-specific configuration
    created_at: i64,                   // Unix timestamp
    updated_at: i64,                   // Unix timestamp
    deleted_at: Option<i64>,           // Soft-delete timestamp
}

AlertChannelData의 종류:

// HTTP Webhook
struct AlertChannelHttpData {
    url: String,
    method: Option<HttpMethod>,        // POST | PATCH | PUT | DELETE
    headers: Option<HashMap<String, String>>,
    proxy: Option<String>,
}
 
// Slack Webhook
struct AlertChannelSlackWebhookData {
    webhook_url: String,
    proxy: Option<String>,
}
 
// Slack Web API
struct AlertChannelSlackWebApiData {
    token: String,                     // Bot token (xoxb-)
    channel: String,                   // Channel ID or name
    proxy: Option<String>,
}

Alert 규칙

Alert 규칙은 다음과 같은 스키마로 저장됩니다.

struct Alert {
    id: String,                            // UUID v7
    title: String,                         // Human-readable title
    event_type: AlertEventType,            // deployment_workload_metrics | etc
    event_targets: EventTargets,           // None | All | Specific
    event_rule_expression: String,         // JavaScript expression
    event_rule_check_interval_min: i32,    // Evaluation frequency
    alert_messages_json: Vec<AlertMessage>,// Messages to send
    created_at: i64,                       // Unix timestamp
    updated_at: i64,                       // Unix timestamp
    deleted_at: Option<i64>,               // Soft-delete timestamp
}

EventTargets의 종류:

enum EventTargets {
    None,                                  // Disabled
    All {
        resource_type: ResourceType        // deployment
    },
    Specific(Vec<Resource>)                // Targeted resources
}
 
struct Resource {
    resource_type: ResourceType,           // deployment
    namespace: Option<String>,             // None = all namespaces
    name: Option<String>,                  // None = all names
}

AlertMessage:

struct AlertMessage {
    alert_channel_id: String,              // Reference to AlertChannel.id
    message: String,                       // Template with ${variable} syntax
}

Alert 로그

Alert가 실행될 때마다 로그가 기록됩니다.

struct AlertLog {
    id: String,                            // UUID v7
    alert_log_group_id: String,            // Groups logs from same evaluation
    alert_channel_id: String,              // Which channel was used
    alert_id: String,                      // Which alert fired
    alert_title: String,                   // Alert title (denormalized)
    response_json: String,                 // HTTP response body
    is_error: bool,                        // Success/failure flag
    reason: String,                        // Error details
    created_at: i64,                       // Unix timestamp
}

로그 보관 기간: 30일 (설정 가능)


이벤트 유형과 스키마

1. Deployment 워크로드 메트릭

이벤트 유형: deployment_workload_metrics

설명: 특정 시간 구간 동안 수집한 CPU 및 메모리 사용률 집계 지표입니다.

사용 가능한 필드:

필드타입설명사용 컨텍스트
evaluation_period_minutesnumber메트릭을 수집한 기간규칙 표현식
cpu_utilization_arrnumber[]CPU 사용률(%) 배열규칙 표현식
memory_utilization_arrnumber[]메모리 사용률(%) 배열규칙 표현식
namespacestring리소스 namespace메시지 템플릿
workload_namestring워크로드 이름메시지 템플릿
alert_titlestringAlert 규칙 제목메시지 템플릿
alert_timestring트리거 시각 (ISO 8601)메시지 템플릿

사용 가능한 함수:

  • max(array) - 배열의 최댓값
  • min(array) - 배열의 최솟값
  • avg(array) - 배열의 평균값
  • sum(array) - 배열 값의 합

규칙 표현식 예시:

evaluation_period_minutes >= 5 &&
(max(cpu_utilization_arr) >= 80 || avg(memory_utilization_arr) >= 80)

메시지 템플릿 예시:

🔴 ${alert_title}

Workload: ${namespace}/${workload_name}
CPU Usage: ${max(cpu_utilization_arr)}%
Memory Usage: ${avg(memory_utilization_arr)}%
Evaluation Period: ${evaluation_period_minutes} minutes
Time: ${alert_time}

기본 설정:

  • 확인 주기: 1분
  • 기본 대상: 모든 deployment
  • 기본 규칙: evaluation_period_minutes >= 5 && (max(cpu_utilization_arr) >= 80 || avg(memory_utilization_arr) >= 80)

2. Deployment 스케줄링 단계

이벤트 유형: deployment_scheduling_phase

설명: deployment 라이프사이클의 START/END 이벤트를 모니터링합니다.

사용 가능한 필드:

필드타입설명사용 컨텍스트
phasestring"START" 또는 "END"규칙 표현식, 메시지 템플릿
deployment_countnumber해당 phase의 deployment 수규칙 표현식, 메시지 템플릿
scheduling_titlestring스케줄링 설정의 제목메시지 템플릿
occurred_atnumberphase가 발생한 시점의 Unix timestamp메시지 템플릿
alert_titlestringAlert 규칙 제목메시지 템플릿
alert_timenumberAlert가 발생한 시점의 Unix timestamp메시지 템플릿

규칙 표현식 예시:

phase == "START" || phase == "END"

메시지 템플릿 예시:

📦 Deployment ${phase == "START" ? "Started" : "Ended"}

${scheduling_title}: ${deployment_count} deployment(s) ${phase == "START" ? "started" : "ended"}
Time: ${alert_time}

기본 설정:

  • 확인 주기: 1분
  • 기본 대상: 없음 (직접 설정 필요)
  • 기본 규칙: phase == "START" || phase == "END"

3. Autopilot 로그 누락

이벤트 유형: autopilot_logs_missing

설명: Autopilot 로그가 일정 시간 이상 수신되지 않을 때 감지합니다.

사용 가능한 필드:

필드타입설명사용 컨텍스트
missing_duration_minutesnumber마지막 로그 수신 이후 경과 시간(분)규칙 표현식, 메시지 템플릿
error_duration_minutesnumberAutopilot 작업이 마지막으로 성공한 이후 경과 시간(분)규칙 표현식, 메시지 템플릿
namespacestring리소스 namespace메시지 템플릿
workload_namestring워크로드 이름메시지 템플릿
alert_titlestringAlert 규칙 제목메시지 템플릿
alert_timenumberAlert가 발생한 시점의 Unix timestamp메시지 템플릿

규칙 표현식 예시:

missing_duration_minutes >= 3 && error_duration_minutes >= 1

메시지 템플릿 예시:

⚠️ Autopilot Logs Missing

Workload: ${namespace}/${workload_name}
Missing for: ${missing_duration_minutes} minutes
Action: Check Autopilot pod health
Time: ${alert_time}

기본 설정:

  • 확인 주기: 1분
  • 기본 대상: 모든 deployment
  • 기본 규칙: missing_duration_minutes >= 3

평가 파이프라인

Alert 평가 파이프라인은 메트릭 수집부터 알림 전송까지 다섯 단계를 거쳐 이벤트를 처리합니다.

요청 흐름

메트릭 수집과 이벤트 생성

메트릭 수집기는 여러 소스에서 데이터를 가져옵니다.

  • Kubernetes API: Pod 메트릭, deployment 상태
  • Prometheus: CPU, 메모리 사용률
  • Autopilot 로그: 로그 timestamp, 갭 감지

이벤트는 세 가지 유형으로 집계됩니다.

  • deployment_workload_metrics: 평가 기간(예: 최근 5분) 동안 집계
  • deployment_scheduling_phase: 즉시 발생하는 START/END 이벤트
  • autopilot_logs_missing: 지속 시간을 계산하는 갭 감지

활성 Alert 로드

deleted_at IS NULL인 Alert를 데이터베이스에서 조회해 평가가 필요한 모든 활성 Alert 설정을 가져옵니다.

이벤트 유형별 필터링

alert.event_typeevent.event_type을 비교해 현재 이벤트와 관련 있는 Alert만 처리합니다.

대상별 필터링

이벤트 리소스가 Alert 대상과 일치하는지 확인합니다.

  • EventTargets::None: 평가 건너뜀 (Alert 비활성화)
  • EventTargets::All: 해당 유형의 모든 리소스와 일치
  • EventTargets::Specific: 목록에 지정된 리소스만 일치 (namespace/name 와일드카드 지원)

평가 주기 확인

중복 Alert를 막기 위해 마지막 실행이 event_rule_check_interval_min 이내면 평가를 건너뜁니다.

JavaScript 컨텍스트 준비

이벤트 필드(예: cpu_utilization_arr, namespace, workload_name)로 JavaScript 평가 컨텍스트를 구성합니다.

규칙 표현식 실행

내장 JavaScript 엔진으로 event_rule_expression을 실행합니다.

  • 표현식은 반드시 boolean을 반환해야 합니다 (true = 트리거, false = 건너뜀)
  • 구문 오류가 있으면 평가가 실패합니다 (오류로 로깅됨)
  • 평가당 100ms 타임아웃
  • 메모리 제한: 평가당 10MB

JavaScript 엔진: 샌드박스 환경에서 실행되는 내장 JavaScript 런타임(QuickJS 또는 V8)을 사용합니다. 파일시스템, 네트워크, 시스템 API에는 접근할 수 없습니다.

표현식 결과 검증

결과가 boolean인지 확인하고, 필요하면 타입 강제 변환을 처리합니다.

Alert 채널 로드

alert_messages_json에 참조된 채널 설정을 가져옵니다.

메시지 템플릿 렌더링

각 메시지마다 이벤트 컨텍스트를 사용해 변수를 치환합니다.

Template: "CPU: ${max(cpu_utilization_arr)}%"
Context:  { cpu_utilization_arr: [70, 75, 82, 88] }
Result:   "CPU: 88%"

템플릿 문법:

  • ${variable} - 단순 변수 치환
  • ${function(array)} - 함수 호출 (max, avg, min, sum)
  • ${condition ? 'yes' : 'no'} - 삼항 연산자 (제한적으로 지원)

템플릿 함수 적용

배열 값에 내장 함수(max, avg, min, sum)를 실행해 집계 지표를 계산합니다.

템플릿 출력 검증

모든 변수가 정상적으로 치환됐는지 확인합니다. 변수가 누락되면 렌더링 오류가 발생하고 Alert가 전송되지 않습니다.

채널 설정 조회

alert_channel_id로 데이터베이스에서 채널을 조회해 엔드포인트 정보(URL, 인증, proxy 설정)를 가져옵니다.

HTTP 요청 구성

채널 유형(HTTP webhook, Slack webhook, Slack Web API)에 맞춰 적절한 헤더와 본문으로 HTTP 요청을 구성합니다.

전송 실행

적절한 인증과 헤더로 알림을 전송합니다. Alert 폭주를 막기 위해 자동 재시도는 하지 않습니다.

전송 결과 기록

timestamp, 응답, 상태, 오류 상세(있는 경우)를 담아 AlertLog 항목을 기록합니다. 로그는 30일간 보관됩니다.


전송 메커니즘

Wave는 세 가지 알림 전송 방식을 지원하며, 각각 요청 구성 방식과 오류 처리 방식이 다릅니다.

HTTP Webhook 전송

범용 HTTP webhook 전송은 HTTP 요청을 받을 수 있는 모든 엔드포인트를 지원합니다.

요청 구성:

POST /webhook HTTP/1.1
Host: example.com
Content-Type: application/json
Authorization: Bearer <token>
User-Agent: WaveAutoscale/1.0
 
{
  "text": "<rendered message>"
}

HTTP 요청 생성

설정된 method(POST/PUT/PATCH/DELETE)와 대상 URL로 요청을 만듭니다.

커스텀 헤더 추가

채널 설정에 지정된 커스텀 헤더(예: Authorization, Content-Type)를 적용합니다.

요청 본문 설정

렌더링된 메시지를 JSON으로 인코딩해 요청 본문으로 설정합니다.

Proxy 적용

설정돼 있으면 HTTP proxy를 통해 요청을 라우팅합니다 (인증이 필요한 proxy도 지원).

요청 실행

30초 타임아웃으로 요청을 보내고 응답을 기다립니다.

응답 파싱

HTTP 상태 코드와 응답 본문을 파싱합니다. 디버깅을 위해 로그로 남깁니다.

성공 기준:

  • HTTP 2xx 상태 코드
  • 응답 본문 수신 (디버깅용으로 로깅됨)

실패 처리:

  • HTTP 4xx/5xx → 상태 코드와 응답 본문을 포함해 오류 로깅
  • Timeout → 타임아웃 오류 로깅
  • Network 오류 → 연결 오류 로깅
  • 자동 재시도 없음 (Alert 폭주 방지를 위한 설계입니다)

Slack Webhook 전송

Incoming webhook을 사용한 간단한 Slack 연동입니다.

요청 구성:

POST /services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXX HTTP/1.1
Host: hooks.slack.com
Content-Type: application/json
 
{
  "text": "<rendered message>"
}

Webhook URL로 POST 전송

메시지를 담은 JSON 본문으로 Slack webhook URL에 HTTP POST 요청을 보냅니다.

Slack 처리

Slack이 webhook을 처리해 설정된 채널에 메시지를 게시합니다.

응답 파싱

Slack은 "ok"(성공) 또는 오류 메시지로 응답합니다. 결과를 파싱해 로깅합니다.

성공 기준:

  • HTTP 200 상태
  • 응답 본문에 "ok" 포함

실패 처리:

  • Slack 오류 로깅 (invalid_token, channel_not_found 등)
  • Rate limiting 처리 (HTTP 429 → 로깅, 재시도 없음)

Slack Web API 전송

더 풍부한 기능을 위해 Web API를 사용하는 고급 Slack 연동입니다.

요청 구성:

POST /api/chat.postMessage HTTP/1.1
Host: slack.com
Content-Type: application/json
Authorization: Bearer xoxb-<token>
 
{
  "channel": "C1234567890",
  "text": "<rendered message>"
}

요청 인증

API 인증을 위해 Authorization: Bearer 헤더에 bot token을 포함합니다.

대상 채널 지정

채널 ID(예: C1234567890) 또는 채널 이름(예: #alerts)으로 대상 채널을 지정합니다.

API 엔드포인트로 POST 전송

Slack Web API의 chat.postMessage 엔드포인트로 요청을 보냅니다.

API 응답 파싱

Slack은 메시지 상세 정보 또는 오류 정보를 담은 JSON으로 응답합니다.

성공 기준:

  • HTTP 200 상태
  • ok: true가 포함된 JSON 응답

실패 처리:

  • 인증 오류 (invalid_auth, token_revoked)
  • 채널 오류 (channel_not_found, not_in_channel)
  • Rate limiting (HTTP 429)
  • 모든 오류는 Slack API 응답의 상세 정보와 함께 로깅됨

성능 특성

평가 처리량

  • 평가되는 Alert 수: 평가 주기당 최대 1000 alerts/second
  • 표현식 평가: 규칙당 약 1ms (JavaScript 실행)
  • 대상 매칭: O(n) (n = EventTargets에 지정된 리소스 수)

전송 지연 시간

  • 로컬 처리: 10ms 미만 (규칙 평가 + 템플릿 렌더링)
  • HTTP 전송: 100~500ms (엔드포인트 지연 시간에 따라 다름)
  • Slack 전송: 200~800ms (Slack API 지연 시간에 따라 다름)
  • 전체 End-to-End: 이벤트 생성부터 알림 전송까지 약 1~2초

리소스 사용량

  • 메모리: Alert 규칙 1000개당 약 50MB
  • CPU: 분당 100건 평가 시 약 0.1 core
  • 데이터베이스: Alert 규칙당 약 1KB, Alert 로그 항목당 약 500 bytes
  • 네트워크: 미미함 (알림 전송을 위한 outbound HTTP 요청만 발생)

확장성 한계

  • 클러스터당 최대 Alert 수: 10,000개 (soft limit, 설정 가능)
  • 클러스터당 최대 채널 수: 1,000개 (soft limit)
  • 최대 Alert 로그 보관 기간: 30일 (설정 가능)
  • 최대 메시지 크기: 4KB (Slack 제한)
  • 최대 동시 전송 수: 100 (connection pool 크기)

보안 모델

인증

  • API 접근: Alert/채널 CRUD에는 Bearer token 인증이 필요합니다
  • RBAC: 역할 기반 접근 제어 (Alert 관리에는 admin 권한 필요)
  • 감사 추적: 모든 변경 사항은 user ID와 timestamp와 함께 기록됩니다

채널 보안

HTTP Webhook:

  • HTTPS를 강력히 권장합니다 (HTTP도 허용되지만 권장하지 않음)
  • Bearer token/API key는 암호화해 저장합니다
  • 로그에는 자격 증명이 노출되지 않습니다 (AlertLog 항목에서 마스킹됨)

Slack 연동:

  • Bot token은 암호화해 저장합니다
  • Webhook URL은 secret으로 취급합니다
  • Token은 로그에 남거나 API 응답에 노출되지 않습니다

표현식 샌드박싱

  • 격리된 샌드박스에서 JavaScript 실행
  • 파일시스템, 네트워크, 시스템 콜에 접근 불가
  • 메모리와 CPU 제한 적용
  • 타임아웃으로 무한 루프 방지

네트워크 보안

  • Outbound 연결만 허용 (Alert 채널로부터의 inbound 없음)
  • 엔터프라이즈 환경을 위한 proxy 지원
  • TLS 인증서 검증 적용
  • 자격 증명 캐싱 없음 (전송마다 자격 증명을 새로 조회)

오류 처리와 디버깅

검증 오류

규칙 표현식 검증:

{
  "is_valid": false,
  "error": "Syntax error: Unexpected token '}'",
  "metadata": null
}

메시지 템플릿 검증:

{
  "is_valid": false,
  "error": "Invalid fields used: unknown_field. Allowed fields: cpu_utilization_arr, memory_utilization_arr",
  "metadata": {
    "used_fields": ["unknown_field"],
    "preview": null
  }
}

런타임 오류

규칙 평가 실패:

  • is_error: true로 AlertLog에 기록
  • 사유: "JavaScript execution error: < details> "
  • Alert는 계속 활성 상태로 유지됩니다 (자동으로 비활성화되지 않음)

전송 실패:

  • is_error: true로 AlertLog에 기록
  • 사유에는 HTTP 상태 코드와 응답 본문이 포함됩니다
  • 예시: "HTTP 401: Unauthorized - Invalid token"

디버깅 팁

  1. Alert 로그 확인: 무슨 일이 있었는지 파악하는 가장 확실한 방법입니다
  2. 채널 테스트: 프로덕션에 배포하기 전에 테스트 버튼을 사용하세요
  3. 표현식 검증: 규칙을 저장하기 전에 검증 API를 사용하세요
  4. 지연 시간 모니터링: AlertLog의 created_at을 추적해 전송 시간을 측정하세요
  5. 변경 사항 감사: updated_at timestamp를 확인해 문제와 설정 변경 사이의 연관성을 파악하세요

고급 주제

커스텀 함수

현재 규칙 표현식에서 지원하는 함수는 다음과 같습니다.

max(array)  // Maximum value
min(array)  // Minimum value
avg(array)  // Average (mean) value
sum(array)  // Sum of all values

사용 예시:

// Alert if max CPU in last 5min > 80% AND avg memory > 70%
evaluation_period_minutes >= 5 &&
max(cpu_utilization_arr) > 80 &&
avg(memory_utilization_arr) > 70

Alert 중복 제거

Alert는 기본적으로 중복 제거되지 않습니다. 규칙이 매 확인 주기마다 true로 평가되면 그때마다 알림이 전송됩니다.

권장 사항: Alert가 짧은 간격으로 연달아 발생하지 않도록 평가 기간 조건을 추가하세요.

// Without period requirement (alerts every minute if CPU > 80%)
max(cpu_utilization_arr) > 80
 
// With period requirement (alerts only if sustained 5+ minutes)
evaluation_period_minutes >= 5 && max(cpu_utilization_arr) > 80

다중 채널 전송

하나의 Alert는 여러 채널로 전송될 수 있습니다.

{
  "alert_messages_json": [
    {
      "alert_channel_id": "pagerduty-prod",
      "message": "CRITICAL: ${alert_title} - ${namespace}/${workload_name}"
    },
    {
      "alert_channel_id": "slack-ops",
      "message": "⚠️ Alert: ${alert_title}\nWorkload: ${namespace}/${workload_name}\nCPU: ${max(cpu_utilization_arr)}%"
    }
  ]
}

두 메시지는 각각 독립적으로 렌더링되고 전송됩니다. 하나가 실패해도 다른 하나는 전송을 계속 시도합니다.

Proxy 설정

HTTP proxy가 필요한 엔터프라이즈 환경을 위한 설정입니다.

{
  "type": "http",
  "data": {
    "url": "https://external-api.example.com/webhook",
    "proxy": "http://proxy.corp.example.com:8080"
  }
}

Proxy는 다음에 적용됩니다:

  • HTTP webhook 전송
  • Slack webhook 전송
  • Slack Web API 전송

Proxy 인증이 필요하면 proxy URL에 포함해야 합니다.

http://username:password@proxy.corp.example.com:8080