← 목록

CloudWatch 알람 기반 EC2/ECS 통합 모니터링 구축

EC2 인스턴스와 ECS 서비스 전반에 걸친 CloudWatch 알람 체계 설계 및 구축. 이메일/문자/전화/Slack 다중 알림 채널 운영.

2024-08-05AWSMonitoringDevOpsCloudWatch

개요

운영 중인 EC2 인스턴스와 ECS 서비스 전반에 걸쳐 CloudWatch 알람 체계를 설계하고 구축했다.

단순 CPU 모니터링을 넘어 메모리, 디스크, IOPS, 시스템 상태, ECS Task Count까지 포괄하는 다층 알림 구조를 구성했으며, 심각도에 따라 이메일 / 문자 / 전화 / Slack으로 알림 채널을 분리했다.


알람 설계 원칙

심각도별 알림 채널 분리

단계지속 시간알림 방식설명
경고 (Warning)5분 (5/5)이메일초기 이상 감지
위험 (Critical)10분 (10/10)문자지속적 이상 상태
장애 (Down)1분 (1/1)문자 + 전화즉각 대응 필요
ECS 이상5분 (5/5)Slack태스크 수 변동 감지

EC2 모니터링 항목

EC2 인스턴스별로 다음 지표를 모니터링한다.

시스템 리소스

지표경고 (5분)위험 (10분)
CPUUtilization이메일문자
mem_used_percent이메일문자
swap_used_percent이메일-
disk_used_percent (OS 볼륨)이메일문자
disk_used_percent (SW 볼륨)이메일문자
평균 IOPS 사용량이메일-
StatusCheckFailed문자 + 전화 (1분)-

StatusCheckFailed는 인스턴스 다운을 의미하므로 1분 단위로 즉시 문자 + 전화 알림을 설정했다.

CloudWatch Agent 설치

메모리, 스왑, 디스크 지표는 기본 CloudWatch 지표에 포함되지 않으므로 CloudWatch Agent를 각 인스턴스에 설치해 수집한다.

# CloudWatch Agent 설치 (Amazon Linux 2)
sudo yum install amazon-cloudwatch-agent -y
 
# 설정 파일 적용
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
  -a fetch-config \
  -m ec2 \
  -s \
  -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

ECS 서비스 모니터링 항목

ECS 서비스는 Auto Scaling이 설정되지 않은 서비스의 경우 CloudWatch로 직접 모니터링한다.

모니터링 지표

지표알림 방식비고
CPUUtilization이메일5분 (5/5)
mem_used_percent이메일5분 (5/5)
disk_used_percent이메일5분 (5/5)
RunningTaskCountSlack태스크 수 감소 시 즉시 알림

Auto Scaling이 설정된 서비스는 스케일링으로 자동 대응되지만, 미설정 서비스는 RunningTaskCount 알람으로 태스크 다운을 감지한다.

RunningTaskCount 알람 설정 예시

import boto3
 
cloudwatch = boto3.client('cloudwatch')
 
cloudwatch.put_metric_alarm(
    AlarmName='ECS-Service-RunningTaskCount-Low',
    MetricName='RunningTaskCount',
    Namespace='AWS/ECS',
    Dimensions=[
        {'Name': 'ClusterName', 'Value': '[cluster-name]'},
        {'Name': 'ServiceName', 'Value': '[service-name]'},
    ],
    Statistic='Average',
    Period=300,        # 5분
    EvaluationPeriods=1,
    Threshold=1,
    ComparisonOperator='LessThanThreshold',
    AlarmActions=['[sns-topic-arn]'],  # Slack 연동 SNS
    TreatMissingData='breaching',
)

알림 채널 구성

SNS → 다중 채널 연동

CloudWatch Alarm
    ↓
SNS Topic
    ├── 이메일 구독 (Warning)
    ├── SMS 구독 (Critical)
    └── Lambda → Slack Webhook (ECS Task)

Slack 알림 Lambda 예시

import json
import urllib.request
 
def lambda_handler(event, context):
    message = json.loads(event['Records'][0]['Sns']['Message'])
    alarm_name = message['AlarmName']
    state = message['NewStateValue']
    reason = message['NewStateReason']
 
    payload = {
        "text": f":warning: *{alarm_name}*\n상태: {state}\n사유: {reason}"
    }
 
    req = urllib.request.Request(
        '[slack-webhook-url]',
        data=json.dumps(payload).encode(),
        headers={'Content-Type': 'application/json'}
    )
    urllib.request.urlopen(req)

모니터링 대상 범위

구축한 알람의 전체 범위:

EC2 인스턴스

ECS 서비스

모니터링 지표 총계


정리

이번 CloudWatch 알람 구축을 통해 다음을 달성했다.

핵심은 단순히 알람을 많이 만드는 것이 아니라, 심각도와 대응 방식에 맞게 알림 채널을 설계하는 것이다.


배운 점

알람을 많이 만들수록 안전해진다고 생각했는데, 실제로는 반대였다. 알림이 늘어나면 사람은 알림을 읽지 않게 된다. 그래서 이 작업의 핵심은 지표를 추가하는 일이 아니라 "이 상황은 이메일인가, 문자인가, 전화인가"를 정하는 일이었다.

기준은 결국 대응 시점이었다. 지금 일어나서 봐야 하는가, 아니면 내일 아침에 봐도 되는가. 이 질문 하나로 채널이 갈렸고, 감지 주기(5분/10분/1분)도 여기에 맞춰 정해졌다.

이 원칙은 이후 알림 작업의 기본값이 됐다. SNS + Lambda 기반 Slack 알림 구축에서 ECS Task 알림을 Slack으로 보낸 것도, AWS Connect 아웃바운드 콜 테스트에서 전화까지 붙인 것도 같은 기준을 따른 결과다.


이어 읽기