← 목록으로AWS

ECS Task STOPPED 상태 감지 및 Slack 알람 구축

ECS 서비스의 RunningTaskCount가 0이 되는 장애 상황을 CloudWatch + SNS + Lambda로 감지하고 Slack으로 즉시 알림하는 모니터링 구축

AWSMonitoringCloudWatchAutomation
2024-12-05

배경

주말에 ECS 앱이 컨테이너 이미지를 찾지 못하는 에러(CannotPullContainerError)가 발생하여 서비스가 중단되었습니다. 문제는 즉시 감지되지 않았고, 업무 영향도 파악 요청이 들어온 후에야 인지되었습니다.

이를 계기로 ECS Task가 STOPPED 상태로 전환될 때 즉시 알람을 받을 수 있는 모니터링을 구축했습니다.


CloudWatch vs EventBridge 비교

감시 항목CloudWatch 지표EventBridge 이벤트
ECS 서비스 전체 상태가능가능
개별 태스크 STOPPED 감지불가능가능
STOPPED 사유 확인 (CannotPullContainerError 등)불가능가능
알람 연동 (SNS, 이메일 등)가능 (지표 기준)가능 (이벤트 기준)

Task 상태만 확인하면 되는 상황이므로 CloudWatch 지표(RunningTaskCount) 방식을 선택했습니다.

개별 태스크의 STOPPED 사유까지 추적해야 한다면 EventBridge 이벤트 룰을 사용하는 것이 적합합니다.


아키텍처

ECS Service (RunningTaskCount 지표)
    ↓
CloudWatch Alarm (RunningTaskCount <= 0, 5분 내 5회 연속)
    ↓
SNS Topic (ecs-task-alerts)
    ↓
Lambda (SendSlackNotification)
    ↓
Slack Webhook → 채널 알림

구축 과정

1. Slack Webhook URL 생성

Slack 앱에서 Incoming Webhook을 생성하여 알림을 받을 채널에 연결합니다.

Slack 워크스페이스 > 앱 관리 > Incoming Webhooks > 새 Webhook 생성
→ 알림 채널 선택 → Webhook URL 복사

2. Lambda 함수 생성 (Slack 알림 처리)

SNS 메시지를 받아 Slack으로 전달하는 Lambda 함수를 생성합니다.

import json
import urllib.request
import os
 
SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL']
 
def lambda_handler(event, context):
    # SNS 메시지 파싱
    sns_message = event['Records'][0]['Sns']
    subject = sns_message.get('Subject', 'ECS Alert')
    message = json.loads(sns_message['Message'])
 
    alarm_name = message.get('AlarmName', 'Unknown')
    new_state = message.get('NewStateValue', 'Unknown')
    reason = message.get('NewStateReason', '')
 
    # Slack 메시지 구성
    slack_message = {
        "text": f":rotating_light: *ECS Task Alert*",
        "attachments": [
            {
                "color": "#ff0000" if new_state == "ALARM" else "#36a64f",
                "fields": [
                    {"title": "Alarm", "value": alarm_name, "short": True},
                    {"title": "State", "value": new_state, "short": True},
                    {"title": "Reason", "value": reason[:200], "short": False},
                ],
            }
        ],
    }
 
    req = urllib.request.Request(
        SLACK_WEBHOOK_URL,
        data=json.dumps(slack_message).encode('utf-8'),
        headers={'Content-Type': 'application/json'},
    )
    urllib.request.urlopen(req)
 
    return {'statusCode': 200}

환경 변수:

  • SLACK_WEBHOOK_URL: Slack Webhook URL

3. SNS 주제 생성

AWS 콘솔 → SNS > 주제 > 새 주제 생성
  이름: ecs-task-alerts
  유형: 표준(Standard)

4. CloudWatch Alarm 생성

각 ECS 서비스마다 RunningTaskCount 알람을 설정합니다.

import boto3
 
cloudwatch = boto3.client('cloudwatch')
 
def create_ecs_task_alarm(cluster_name, service_name, alarm_name, sns_topic_arn):
    cloudwatch.put_metric_alarm(
        AlarmName=alarm_name,
        MetricName='RunningTaskCount',
        Namespace='AWS/ECS',
        Dimensions=[
            {'Name': 'ClusterName', 'Value': cluster_name},
            {'Name': 'ServiceName', 'Value': service_name},
        ],
        Statistic='Average',
        Period=60,              # 1분 간격 수집
        EvaluationPeriods=5,    # 5개 데이터 포인트
        Threshold=0,
        ComparisonOperator='LessThanOrEqualToThreshold',
        AlarmActions=[sns_topic_arn],
        TreatMissingData='breaching',
    )

알람 조건:

  • 지표: RunningTaskCount
  • 조건: <= 0
  • 기간: 1분 간격, 5분 내 5개 데이터 포인트 연속 충족 시 알람
  • 알림: SNS 주제 ecs-task-alerts

5. SNS → Lambda 연결

Lambda > SendSlackNotification 함수 > 트리거 추가
  트리거 유형: SNS
  SNS 주제: ecs-task-alerts
  → Lambda IAM 역할에 SNS 실행 권한 자동 부여

알람 흐름 정리

1. ECS 서비스의 Task가 모두 중지됨 (RunningTaskCount = 0)
2. CloudWatch가 1분 간격으로 수집, 5분 연속 0 감지
3. CloudWatch Alarm → ALARM 상태 전환
4. SNS Topic (ecs-task-alerts)에 알림 발행
5. Lambda (SendSlackNotification) 트리거
6. Slack 채널에 알람 메시지 전송

설계 포인트

5분 연속 조건으로 오탐 방지 배포 중 일시적으로 Task가 0이 되는 상황(롤링 업데이트 등)에서 불필요한 알람이 발생하지 않도록 5회 연속 조건을 설정했습니다.

TreatMissingData = breaching 데이터 포인트가 누락되는 경우에도 알람이 발생하도록 설정합니다. 서비스 자체가 삭제되거나 메트릭 수집이 불가능한 상황도 감지합니다.

서비스별 개별 알람 각 ECS 서비스마다 별도 알람을 생성하여 어떤 서비스에서 문제가 발생했는지 즉시 식별할 수 있습니다.


정리

  • ECS RunningTaskCount 지표 기반 Task 중단 감지
  • CloudWatch Alarm → SNS → Lambda → Slack 알림 파이프라인 구축
  • 5분 연속 조건으로 배포 중 오탐 방지
  • 서비스별 개별 알람으로 장애 서비스 즉시 식별
  • 주말/야간 장애 인지 지연 문제 해결