AWS CLI를 사용하여 CloudWatch Alarm 의 이상 탐지 알람 (Anomaly Detection alarm) 생성하기
안녕하세요, 임채정입니다.
이번 블로그에서는 AWS CLI를 사용하여 CloudWatch 의 이상 탐지 알람(Anomaly Detection Alarm) 을 생성하는 방법을 설명합니다.
CloudWatch 의 이상 탐지 알람(Anomaly Detection Alarm)은 과거 데이터의 패턴을 분석하여 비정상적인 패턴을 감지해서 지표 데이터가 비정상적으로 급변했을 때 알람을 보내는 기능입니다.
만약 자세한 내용을 알고 싶다면 아래 블로그를 참고해주세요.
만약 이상 탐지 알람(Anomaly Detection Alarm) 이 아니라 이상 탐지(Anomaly Detection) 를 생성하고 싶으시면 아래 블로그를 참고해주세요
1. 사전 준비
AWS CLI를 통해 이상 탐지 알람을 생성하기 전에 다음과 같은 사전 준비가 필요합니다.
- AWS CLI가 설치되어 있어야 합니다.
- CLI를 실행하는 IAM에 적절한 권한이 할당되어 있어야 합니다.
- 이상 탐지 알람을 생성할 대상 리소스가 있어야 합니다.
1.1. AWS CLI 설치
AWS CLI는 AWS 서비스를 관리하기 위한 명령행 인터페이스입니다.
AWS CLI를 설치하는 방법은 아래 링크를 참고해주세요.
1.2. IAM 권한 설정
이상 탐지 알람(Anomaly Detection Alarm) 생성, 삭제 등을 위해서는 아래 권한이 필요합니다.
CloudWatch에 대한 모든 권한을 가진 AWS 관리형 IAM 정책인 CloudWatchFullAccess
을 사용해도 되지만 되도록 필요한 범위의 권한만 할당하는 게 좋습니다.
cloudwatch:PutMetricAlarm
: 이상 탐지 알람을 생성/수정할 때 필요cloudwatch:DescribeAlarms
: 알람 정보를 조회cloudwatch:DeleteAlarms
: 알람을 삭제할 때 필요- 알림 작업 구성에 필요한 권한 (필요한 권한을 선택해서 할당)
sns:Publish
: SNS 토픽으로 알림 발송시 필요sqs:SendMessage
: SQS 큐로 메시지 발송시 필요lambda:InvokeFunction
: Lambda 함수 호출시 필요autoscaling:ExecutePolicy
: Auto Scaling 정책 실행시 필요
또한 옵션으로 지표 조회, 태그 관리 등 부가적으로 필요할 수 있습니다. (이번 블로그에서는 사용하지 않습니다.)
- 이상 탐지 조회하고 싶을 때
cloudwatch:DescribeAnomalyDetectors
: 이상 탐지 존재 여부 확인
- 지표 조회하고 싶을 때
cloudwatch:ListMetrics
: 사용 가능한 지표 목록을 조회cloudwatch:DescribeMetrics
: 지표의 상세 정보(네임스페이스, 차원, 통계 등)를 조회
- 태그 관리를 하고 싶을 때
cloudwatch:ListTagsForResource
: 리소스(알람, 대시보드 등)의 태그를 조회cloudwatch:TagResource
: 리소스에 태그를 추가cloudwatch:UntagResource
: 리소스에서 태그를 제거
1.3. 대상 리소스 준비
이번 블로그에서는 EC2 인스턴스의 지표 중에 하나를 사용해서 이상 탐지 알람을 생성해보겠습니다.
EC2 인스턴스의 스팩은 아래와 같습니다.
- 이름 :
Anomaly-detection-test
- OS :
Windows_Server 2025
- 인스턴스타입 :
t3.micro
2. 이상 탐지 알람(Anomaly Detection Alarm) 생성하기
다음으로 이상 탐지 알람을 생성하는 명령어에 대해서 알아보겠습니다.
2.1. 명령어 예시
aws cloudwatch put-metric-alarm \
--alarm-name [알람명] \
--comparison-operator [임계값 유형] \
--evaluation-periods [알람 평가에 사용할 연속 데이터 포인트 수] \
--threshold-metric-id [임계값으로 사용할 메트릭 ID] \
--alarm-actions "[알람을 보낼 SNS의 ARN]" \
--metrics '[
{
"Id": "[지표 식별자]",
"MetricStat": {
"Metric": {
"Namespace": "[지표 네임스페이스]",
"MetricName": "[지표명]",
"Dimensions": [
{
"Name": "[차원 이름]",
"Value": "[차원 값]"
}
]
},
"Period": [데이터 포인트 간격(초)],
"Stat": "[통계 방법]"
}
},
{
"Id": "[임계값 지표 식별자 (threshold-metric-id와 일치)]",
"Expression": "ANOMALY_DETECTION_BAND([지표 식별자], [이상 탐지 임계값])"
}
]'
aws cloudwatch put-metric-alarm 명령어의 옵션
옵션명 | 타입 | 필수/선택 | 설명 | 디폴트 값 | 비고 |
---|---|---|---|---|---|
--alarm-name |
string | 필수 | 알람의 이름 | 없음 | 사용 리전 내에서 이름 중복 금지 |
--alarm-description |
string | 선택 | 알람에 대한 설명 | 없음 | |
--actions-enabled |
boolean | 선택 | 알람 상태가 변경 시 작업 실행 | true | true/false--no-actions-enabled 와 동시에 사용 불가능 |
--no-actions-enabled |
boolean | 선택 | 알람 상태가 변경 시 작업을 실행하지 않음 | false | true/false 테스트용 알람이나 모니터링만 하고 싶을 때 사용 |
--ok-actions |
list | 선택 | OK 상태로 전환될 때 실행할 작업 | 없음 | SNS, Auto Scaling 등 |
--alarm-actions |
list | 선택 | 알람 상태일 때 실행할 작업 | 없음 | SNS, Auto Scaling 등 |
--insufficient-data-actions |
list | 선택 | 데이터 부족 상태일 때 실행할 작업 | 없음 | SNS, Auto Scaling 등 |
--metric-name |
string | 선택 | 알람을 모니터링할 지표 이름 | 없음 | 단일 메트릭 알람에서 사용 |
--namespace |
string | 선택 | 지표의 네임스페이스 | 없음 | 단일 메트릭 알람에서 사용 |
--statistic |
string | 선택 | 지표에 적용할 통계값 | 없음 | Average, Sum, Maximum, Minimum, SampleCount--extended-statistic 와 함께 지정 불가능 |
--extended-statistic |
string | 선택 | 백분위 기반 통계값 | 없음 | 예: p95, p99 등--statistic 와 함께 지정 불가능 |
--dimensions |
list | 선택 | 지표의 차원 | 없음 | Name=value 형태로 지정 단일 메트릭 알람에서 사용 |
--period |
integer | 선택 | 지표 데이터 포인트의 기간(초) | 300 | 10, 20, 30 및 60초의 배수여야 함 정적 임계값 기반 알람에 필수 |
--unit |
string | 선택 | 지표의 측정 단위 | 해당 지표의 기본 단위 자동 사용 | Seconds, Bytes, Percent 등 |
--evaluation-periods |
integer | 필수 | 알람 평가에 사용할 데이터 포인트 수 | 없음 | 1 이상의 정수 |
--datapoints-to-alarm |
integer | 선택 | 알람 상태로 전환하기 위한 데이터 포인트 수 | evaluation-periods 값 | evaluation-periods 이하의 양의 정수 |
--threshold |
double | 선택 | 알람 임계값 | 없음 | 정적 임계값을 기반으로 하는 알람에 필요 |
--comparison-operator |
string | 필수 | 임계값과 비교할 연산자 | 없음 | GreaterThanThreshold, LessThanThreshold 등 |
--treat-missing-data |
string | 선택 | 누락된 데이터 처리 방법 | missing | missing, notBreaching, breaching, ignore |
--evaluate-low-sample-count-percentile |
string | 선택 | 샘플 수가 적은 상황의 처리 방법 | evaluate | evaluate, ignore 백분위수 기반 알람에만 사용 |
--metrics |
list | 선택 | 사용할 여러 지표와 수식을 정의 | 없음 | 복합 알람(Composite Alarm)이나 수식 기반 알람을 만들 때 사용하는 옵션 |
--tags |
list | 선택 | 알람에 추가할 태그 | 없음 | Key=Value 형태 |
--threshold-metric-id |
string | 선택 | 임계값으로 사용할 지표의 ID | 없음 | 복합 알람에서 사용 |
※ AWS CLI 글로벌 옵션 등은 생략하고 있습니다.
알람을 설정할 때는 다음 3가지 항목이 필수입니다.
--alarm-name
--evaluation-periods
--comparison-operator
단, 알람에 사용할 지표가 단일 지표인지 복합 지표인지에 따라 추가로 요구되는 필수 항목들이 달라집니다.
- 단일 지표 알람 생성
--namespace
--metric-name
--statistic
--extended-statistic
(백분위수 사용 시--statistic
대신 사용)
--threshold
--dimensions
(차원이 있는 지표의 경우)
- 복합 지표 알람 생성
--metrics
--threshold-metric-id
※--namespace
+--metric-name
+--statistic
는 지정하지 않고--metrics
내부에서 정의
※--threshold
는--threshold-metric-id
대체해서 사용
두 알람의 차이점을 표로 정리하면 다음과 같습니다.
구분 | 단일 지표 | 복합 지표 |
---|---|---|
지표 정의 | 개별 옵션으로 지정 | --metrics 을 통해 JSON 지정 |
지표명 지정 | --metric-name |
--metrics 에서 정의 |
네임스페이스 | --namespace |
--metrics 에서 정의 |
통계방법 | --statistic |
--metrics 에서 정의 |
임계값 | --threshold |
--threshold-metric-id |
사용 사례 | 정적 임계값 모니터링 | 이상 탐지, 수식 계산, 여러 메트릭 조합 |
자세한 옵션 설명과 예시는 아래 페이지에서 확인할 수 있습니다.
2.2. 명령어 실행
이번에 사용할 지표는 EC2 인스턴스의 NetworkPacketsIn
입니다.
NetworkPacketsIn
는 모든 네트워크 인터페이스에서 인스턴스가 수신한 패킷 수로, 단일 인스턴스의 패킷 수를 기준으로 들어오는 트래픽의 양을 식별합니다.
선택 기준은 따로 없고 테스트를 위해 임의로 선택했습니다.
aws cloudwatch put-metric-alarm \
--alarm-name EC2_NetworkIn_Anomaly_Alarm \
--comparison-operator LessThanLowerOrGreaterThanUpperThreshold \
--evaluation-periods 2 \
--threshold-metric-id t1 \
--alarm-actions "arn:aws:sns:ap-northeast-1:123456789012:my-sns-topic" \
--metrics '[
{
"Id": "m1",
"MetricStat": {
"Metric": {
"Namespace": "AWS/EC2",
"MetricName": "NetworkIn",
"Dimensions": [
{
"Name": "InstanceId",
"Value": "i-xxxxxxxxxxxxxxxxx"
}
]
},
"Period": 300,
"Stat": "Average"
}
},
{
"Id": "t1",
"Expression": "ANOMALY_DETECTION_BAND(m1, 2)"
}
]'
3. 결과 확인하기
그럼 제대로 생성되었는지 확인해보겠습니다.
aws cloudwatch describe-alarms --alarm-names "EC2_NetworkIn_Anomaly_Alarm"
# {
# "MetricAlarms": [
# {
# "AlarmName": "EC2_NetworkIn_Anomaly_Alarm",
# "AlarmArn": "arn:aws:cloudwatch:ap-northeast-1:123456789012:alarm:EC2_NetworkIn_Anomaly_Alarm",
# "AlarmConfigurationUpdatedTimestamp": "2025-07-27T16:12:40.006000+00:00",
# "ActionsEnabled": true,
# "OKActions": [],
# "AlarmActions": [
# "arn:aws:sns:ap-northeast-1:123456789012:my-sns-topic"
# ],
# "InsufficientDataActions": [],
# "StateValue": "OK",
# "StateReason": "Thresholds Crossed: 2 datapoints [7090.0 (27/07/25 16:08:00), 1854.6 (27/07/25 16:03:00)] were not less than the lower thresholds [0.0, 0.0] or not greater than the upper thresholds [10882.146951771912, 8375.33042800286].",
# "StateReasonData": "{\"version\":\"1.0\",\"queryDate\":\"2025-07-27T16:13:29.164+0000\",\"startDate\":\"2025-07-27T16:03:00.000+0000\",\"period\":300,\"recentDatapoints\":[1854.6,7090.0],\"recentLowerThresholds\":[0.0,0.0],\"recentUpperThresholds\":[8375.33042800286,10882.146951771912],\"evaluatedDatapoints\":[{\"timestamp\":\"2025-07-27T16:08:00.000+0000\",\"value\":7090.0,\"threshold\":10882.146951771912}]}",
# "StateUpdatedTimestamp": "2025-07-27T16:13:29.167000+00:00",
# "Dimensions": [],
# "EvaluationPeriods": 2,
# "ComparisonOperator": "LessThanLowerOrGreaterThanUpperThreshold",
# "Metrics": [
# {
# "Id": "m1",
# "MetricStat": {
# "Metric": {
# "Namespace": "AWS/EC2",
# "MetricName": "NetworkIn",
# "Dimensions": [
# {
# "Name": "InstanceId",
# "Value": "i-xxxxxxxxxxxxxxxxx"
# }
# ]
# },
# "Period": 300,
# "Stat": "Average"
# }
# },
# {
# "Id": "t1",
# "Expression": "ANOMALY_DETECTION_BAND(m1, 2)"
# }
# ],
# "ThresholdMetricId": "t1"
# }
# ],
# "CompositeAlarms": []
# }
aws cloudwatch describe-alarms 명령어의 옵션
옵션명 | 타입 | 필수/선택 | 설명 | 디폴트 값 | 비고 |
---|---|---|---|---|---|
--alarm-names |
list | 선택 | 조회할 특정 알람 이름들 | 없음 | 특정 알람만 조회할 때 사용 여러 개의 알람 조회 가능 |
--alarm-name-prefix |
string | 선택 | 알람 이름 접두사로 필터링 | 없음 | 접두사가 일치하는 알람만 조회 |
--alarm-types |
list | 선택 | 알람 유형으로 필터링 | 없음 | CompositeAlarm, MetricAlarm |
--children-of-alarm-name |
string | 선택 | 복합 알람의 하위 알람들 조회 | 없음 | 복합 알람에서 사용 |
--parents-of-alarm-name |
string | 선택 | 지정된 알람의 상위 알람들 조회 | 없음 | |
--state-value |
string | 선택 | 알람 상태로 필터링 | 없음 | OK, ALARM, INSUFFICIENT_DATA |
--action-prefix |
string | 선택 | 액션 ARN 접두사로 필터링 | 없음 | 특정 알람 작업을 가진 알람만 조회 |
--starting-token |
string | 선택 | 페이지네이션 시작 위치를 지정하는 토큰 | 없음 | 페이지네이션 옵션 (list/describe 계열 명령어) |
--page-size |
integer | 선택 | 한 번의 호출에서 가져올 페이지의 크기 | 없음 | 페이지네이션 옵션 (list/describe 계열 명령어) |
--max-items |
integer | 선택 | 명령 출력에 반환할 총 항목 수 | 없음 | 페이지네이션 옵션 (list/describe 계열 명령어) |
※ AWS CLI 글로벌 옵션 등은 생략하고 있습니다.
aws cloudwatch cloudwatch describe-alarms
명령어는 필수 옵션이 없습니다.
아무런 옵션 없이도 실행할 수 있습니다.
하지만 원하는 알람 조회를 하기 위해 필터링 관련 선택 옵션을 사용하는 것이 좋습니다.
--alarm-names
--alarm-name-prefix
--state-value
--alarm-types
--action-prefix
- 페이지네이션 관련 옵션
--max-records
--next-token
자세한 옵션 설명과 예시는 아래 페이지에서 확인할 수 있습니다.
콘솔 페이지에서 확인해봐도 성공적으로 생성되었습니다.
이상 탐지의 정상 범위가 회색으로 출력되는 걸 확인할 수 있습니다.
(콘솔 화면에 이상 탐지가 출력되기까지는 다소 시간이 걸립니다.)
지표 데이터가 급증했을 때 알람이 발생합니다.
(지표 데이터가 너무 급증해서 잘 안보이지만 정상 상태일때의 데이터는 회색의 정상 범위 안에 있습니다.)
알람 발생 메일도 잘 도착합니다.
4. 알람 삭제하기
마지막으로 이상 탐지를 삭제해보겠습니다.
aws cloudwatch delete-alarms
명령어는 매우 간단합니다.
--alarm-names
옵션 이외의 항목은 모두 AWS CLI 글로벌 옵션입니다.
# 단일 알람 삭제
aws cloudwatch delete-alarms --alarm-names "EC2_NetworkIn_Anomaly_Alarm"
# 복수 알람 삭제
aws cloudwatch delete-alarms --alarm-names "alarm1" "alarm2"
aws cloudwatch delete-alarms 명령어의 옵션
aws cloudwatch delete-alarms
명령어는 삭제할 알람을 식별하기 위해 --alarm-names
옵션만 필수고, 그 외의 옵션들은 AWS CLI 글로벌 옵션들입니다.
옵션명 | 타입 | 필수/선택 | 설명 | 디폴트 값 | 비고 |
---|---|---|---|---|---|
--alarm-names |
list | 필수 | 삭제할 알람 이름들 | 없음 | 하나 이상의 알람 이름 지정 |
※ AWS CLI 글로벌 옵션 등은 생략하고 있습니다.
자세한 옵션 설명과 예시는 아래 페이지에서 확인할 수 있습니다.
삭제하고 결과를 확인해보면 생성했던 이상 탐지가 삭제되어 있습니다.
5. 마무리
이상으로 AWS CLI를 사용하여 CloudWatch 의 이상 탐지 알람 생성, 조회 및 삭제 명령어를 실행해봤습니다.
참고 자료
문의 사항은 클래스메소드코리아로!
클래스메소드코리아에서는 다양한 세미나 및 이벤트를 진행하고 있습니다.
진행중인 이벤트는 아래 페이지를 참고해주세요.
AWS에 대한 상담 및 클래스메소드코리아 멤버스에 관한 문의사항은 아래 메일로 연락주시면 감사드립니다!
Info@classmethod.kr