GCP VM Alert 설정 w/Terraform
사내 리소스 생성시 GCP 콘솔 내에서 직접 생성하는 것을 지양하고 있지만, terraform으로 이관시의 우선순위상 아직 terraform으로 만들어진 적이 없고 콘솔에만 존재하는 것도 있습니다. 이 중 하나인 monitoring alert을 terraform으로 세팅한 과정입니다.
이를 통해 과거 산발적으로 만들어진 alert를 이관, 관리하고 앞으로 생성하는 alert들을 탬플릿화 및 상태 관리할 수 있습니다.
1. VM의 지표를 모니터링 하도록 설정
: VM이 boot disk image로 어떤 OS를 사용하는지 파악하고 detector 또는 agent 설정
일부 지표는 설정 없이도 모니터링 가능합니다. 하지만 VM의 observability 차트 또는 alert의 차트에 나오지 않는 데이터를 보려고 한다면 별도의 설정이 필요합니다. 설정 후 즉각 반영되는 경우도 있지만 10분 가량 기다려야 할 수도 있습니다.
https://cloud.google.com/monitoring/agent/ops-agent/installation#verify-agent-running-with-vm-instance-dashboard
위 페이지에서 VM Instance Dashboard에 들어가면 프로젝트 내 VM들에 어떤 Agent가 설치되어 있는지와 Agent 설치 가능 여부가 나옵니다.

Legacy Agent를 사용하고 있는 VM에 Ops Agent를 설치하는 경우 충돌이 일어날 수 있다고 합니다.
COS는 Ops Agent를 세팅할 수 없지만(not applicable) 다른 설정을 통해 모니터링 지표를 볼 수 있습니다. 다만 Agent를 쓸 때와 지표 종류 및 alert 설정시의 filter가 다르니 유의 바랍니다.
COS를 사용하는 VM
VM에 ssh 접속한 뒤
sudo bash
systemctl status google-osconfig-agent
systemctl status node-problem-detector
위 커맨드를 실행했을 때 첫번째는 active, 두번째는 inactive가 나온다면 node-problem-detector를 사용 설정해야 됩니다. (참고)
VM의 terraform 파일 metadata 블록 안에 google-monitoring-enabled = "TRUE" 또는 google-monitoring-enabled = true 를 추가해주세요. (둘 다 작동하니 팀의 convention에 맞추기)
Ubuntu를 사용하는 VM
VM에 ssh 접속한 뒤
sudo bash
systemctl status google-osconfig-agent
systemctl status google-cloud-ops-agent
위 커맨드를 실행했을 때 첫번째는 active, 두번째는 없다고 나오면 Ops Agent를 설치해야 됩니다.
쉽게는 GCP 콘솔에서 VM 모니터링 차트에 뜨는 install 버튼을 눌러도 된다고 합니다.
위 대신 VM에 접속해서 설치한다면 GCP 문서의 커맨드를 참고하세요.
Ops Agent를 설치한 뒤 상태를 확인하면 이렇게 permission 에러가 나있기도 합니다.

이 땐 VM의 terraform 파일에서 어떤 service_account를 사용하는지 확인하고, service_account_binded_roles 목록에 `"roles/logging.logWriter"`를 추가해주세요. (service account를 terraform을 통해 관리한다는 전제입니다)
반영하고 다시 확인했을 때 아래와 같이 뜨고, VM Instance Dashboard에선 Ops Agent가 뜨고, GCP 콘솔에서 install 버튼이 사라지면 끝입니다.

이후 3번 단계는 이 시점부터 10분 가량 기다리고 들어가세요. (바로 가면 설정하다가 뭐가 안 뜨곤 합니다)
2. slack 알림을 위한 세팅
alert 발생시 slack 알림을 받고자 한다면 GCP 콘솔에서 slack 채널을 등록하고, 그 링크를 alert 설정시 사용해야 됩니다.

edit notification channels 들어간 뒤 slack 부분에서 채널 등록 후
우측 Actions 링크 버튼을 통해 복사한 url을 추후 terraform에서 사용합니다.
비공개 채널이면 google cloud monitoring app을 초대해야 됩니다. (참고)
3. Alert 설정을 위한 terraform 파일 작성
alert policy는 condition을 여러개 가질 수 있는 그룹입니다.
terraform 파일 예시
resource "google_monitoring_alert_policy" "<리소스명>" {
display_name = "<alert policy명>"
project = local.gcp.project_id
severity = "CRITICAL"
combiner = "OR"
conditions {
display_name = "<alert policy 내 condition명>"
condition_threshold {
filter = "resource.type = \"gce_instance\" AND metric.type = \"compute.googleapis.com/guest/disk/bytes_used\" AND (metric.labels.device_name = \"sda1\" AND metric.labels.state = \"free\") AND metadata.system_labels.name = \"${<지정하려는 리소스가 remote 변수인 경우>}\""
duration = "0s"
comparison = "COMPARISON_LT"
threshold_value = <byte 단위 기준치>
trigger {
count = 1 # 한 번이라도 발생하면 alert
}
aggregations { # 설정된 값이 없으면 gcp console 상에서 chart 오류 발생
alignment_period = "60s"
per_series_aligner = "ALIGN_MEAN"
}
}
}
conditions {
display_name = "alert policy 내 condition명" #
condition_threshold {
filter = "resource.type = \"gce_instance\" AND metric.type = \"agent.googleapis.com/disk/percent_used\" AND (metric.labels.device = \"/dev/sda1\" AND metric.labels.state = \"free\") AND metadata.system_labels.name = \"<지정하려는 리소스가 terraform 내 변수로 선언되어있지 않다면 gcp 리소스명 사용>\""
duration = "0s"
comparison = "COMPARISON_LT"
threshold_value = 20 # 20%
trigger {
count = 1 # 한 번이라도 발생하면 alert
}
aggregations { # 설정된 값이 없으면 gcp console 상에서 chart 오류 발생
alignment_period = "60s"
per_series_aligner = "ALIGN_MEAN"
}
}
}
# 기본적으로 open, close시 전부 알림이 생성됩니다.
# provider에서 notification_prompts 설정을 지원하지 않으니 변견을 원할 경우 gcp console에서 직접 설정해주세요.
notification_channels = ["projects/<프로젝트명>/notificationChannels/<임의값>"]
alert_strategy {
auto_close = "1800s" # min 1800s
}
documentation {
subject = "<slack 알림 내 제목>"
content = "<slack 알림 내 내용. 사용자 그룹 태그 가능>"
mime_type = "text/markdown"
}
}
condition 블록 내의
- filter로 metric(지표) 종류와 대상 리소스를 특정합니다. 밑에서 더 설명하겠습니다.
- duration은 위양성 방지차 다시 비교하는 간격입니다. (=retest window). 0s는 즉각 판정입니다(no retest).
- comparison 값이 COMPARISON_LT이면 기준값보다 지표값이 낮을 때 alert을 줍니다. (반대 : COMPARISON_GT)
- threshold_value의 단위(byte, % 등)는 metric에 따라 다릅니다.
- aggregation은 차트에서 보고 기준값과 비교하는 대상 지표값을 만드는 규칙입니다. 없어도 apply는 되는데 차트에서는 값이 안 보입니다.
slack 알림이 갈 채널인 notification_channels의 값으로는 위의 2번에서 등록하고 복사한 url을 사용합니다.
slack 메세지의 내용인 documentation은 policy 내에서 공통적으로 사용합니다.
문장 내에 <!subteam^CJG07GZDK|@backend_team> (예시)형태를 삽입하여 slack 사용자 그룹을 태그할 수 있습니다.
다른 항목에 대해선 terraform 문서를 참고하되 provider에서 지원하지 않는 항목도 있음을 유의해주세요(e.g. incident open/close시 언제 알림 받을지 설정할 수 있는 notification_prompts 등).
metric & filter
alert policy에 사용할 metric(지표)를 정하고 원하는 리소스를 특정하는 filter를 찾아야 합니다.
이미 생성되어있는 policy의 json을 다운받아 보거나 terraform 파일을 참고해도 되지만,
GCP 콘솔에서 alerting policy를 직접 생성해본 뒤 policy의 json을 다운받아 보는게 가장 쉬운 방법입니다.
어떤 metric은 VM의 설정에 따라 사용 불가할 수도 있습니다.
e.g. Ubuntu+Ops Agent를 사용하는 VM 대상으로는 VM Instance - Disk Utilization metric을 사용할 수 있지만 COS+node-problem-detector를 사용하는 VM 대상으로는 사용할 수 없습니다.
terraform 파일 예시의 filter 값 내 항목 중
- resource.type은 없으면 에러납니다. name으로만 특정되지 않습니다.
- device, state는 metric의 특성에 따라 존재하는 항목입니다. metric을 다른 걸 사용하면 예시의 두 condition 처럼 유사한 개념이라 하더라도 항목명이 다르기도 하고(device, device_name), 값도 다를 수 있습니다. (sda1, /dev/sda1)
- disk 여유 공간을 특정하기 위해 state를 free로 설정하더라도 metric명 자체가 byte_used, percent_used기 때문에 콘솔상에서 아래와 같이 보입니다. 실제로는 여유공간의 용량과 %를 의미합니다.


terraform 파일에서 설정한 filter 값을 통해 특정되는 리소스가 없으면 apply시 에러납니다.
예시의 두번째 condition에서 filter로 준 /dev/sda1는 Ubuntu를 사용하는 실제 VM에서 확인했을 때 /dev/root인 등 GCP에서 인지하는 것과 차이가 있으니 유의해주세요.
참고
https://www.bespinglobal.com/google-cloud-insight/google-cloud-monitoring-alert/
https://cloud.google.com/composer/docs/composer-2/monitor-key-metrics#terraform
https://cloud.google.com/monitoring/alerts/concepts-indepth#duration-window
[https://velog.io/@shmoon2/GCP-Cloud-Monitoring-Alerting-옵션들](https://velog.io/@shmoon2/GCP-Cloud-Monitoring-Alerting-%EC%98%B5%EC%85%98%EB%93%A4)
https://sysadmin.atlassian.net/wiki/spaces/sysadmin/pages/2276688701/GCP+ops-agent