Overview
알람 자동화 함수에 대상 AWS 서비스를 추가하고 스케쥴러를 설정하겠습니다.
![](https://blog.kakaocdn.net/dn/brVcbX/btsIhM6aTMv/C3tOhmtGN31KfhcFkki6Nk/img.png)
인프라 엔지니어가 내부 원리 및 테라폼과 관계없이 AWS 콘솔에서 태그만 설정하면 자동으로 알람이 설정하도록 구성하였습니다.
1. 람다 함수 트리거 설정
CloudWatchAutoAlarms 은 대상 자원이 생성/삭제되었을 때만 트리거가 호출됩니다. 인스턴스 자원이 이미 생성되어 있는 경우에는 알람 자동화 설정 대상에 제외되며 추가 설정이 필요합니다. 이에 람다 함수 트리거를 설정하여 스케쥴러를 설정하여 람다 함수가 호출되도록 설정하겠습니다.
![](https://blog.kakaocdn.net/dn/vc8iM/btsIhamigDK/KXJbfPE8cqyqZEqns9tcMk/img.png)
스케쥴러의 경우 예약 표현식에서 설정이 가능합니다.
# 1분마다 트리거 호출
rate(1 minute)
# 일일마다 트리거 호출
# cron(Minutes Hours Day-of-month Month Day-of-week Year)
cron(0 0 * * ? *)
2. 기존 AWS 서비스 알람 자동화
기존 AWS 서비스에 알람 자동화를 위해 트리거 추가와 람다 함수 수정이 필요합니다.
람다 로그를 확인하면 알람 설정 대상이 트리거를 호출한 AWS 서비스로 설정되어있기 때문입니다.
![](https://blog.kakaocdn.net/dn/bBuEv5/btsIjdO7XaJ/EmqPXY3mZEwfiT3coaygiK/img.png)
코드 로직을 확인하면 detail 블록을 통해 알람을 설정하는 것을 확인할 수 있습니다.
이를 전체 AWS 대상으로 수정하기 위해 코드 로직을 다음과 같이 수정하였습니다.
- event 대상이 아닌 전체 EC2 대상
- 반복문을 통한 태그 식별 및 설정 함수 호출
![](https://blog.kakaocdn.net/dn/bf425Z/btsIhWHtR1Y/kznwOW0ofclu9ZrwpkUmy1/img.png)
업데이트한 코드를 반영하고 스케쥴러 함수 로그를 확인하면 정상적으로 알람이 설정된 것을 확인할 수 있습니다.
![](https://blog.kakaocdn.net/dn/FQ4Wr/btsIiOovlYr/LLV8MmxfKpe6txWMokjxB0/img.png)
![](https://blog.kakaocdn.net/dn/05Xvh/btsIhU3Zllb/zb4ECV2jXEKYdl8PDOR4V0/img.png)
3. 알람 대상 AWS 서비스 추가
알람 자동화 대상이 EC2, Lambda, RDS 셋으로 서비스 대상을 추가하겠습니다.
추가 대상과 알람 설정은 깃허브 오픈소스를 참고하였습니다.
AWS 서비스
|
Metric
|
조건
|
AWS/RDS
|
CPUUtilization
|
GreaterThanThreshold, 5m, 1, Average, Created_by_CloudWatchAutoAlarms, 75
|
|
FreeableMemory
|
LessThanThreshold, 5m, 1, Average, Created_by_CloudWatchAutoAlarms, 75
|
AWS/EC2
|
CPUUtilization
|
GreaterThanThreshold, 5m, 1, Average, Created_by_CloudWatchAutoAlarms, 75
|
AWS/Lambda
|
Errors
|
GreaterThanThreshold, 5m, 1, Average, Created_by_CloudWatchAutoAlarms, 1
|
|
Throttles
|
GreaterThanThreshold, 5m, 1, Average, Created_by_CloudWatchAutoAlarms, 1
|
AWS/ApplicationELB
|
HTTPCode_ELB_5XX_Count
|
GreaterThanThreshold, 5m, 1, Sum, 100
|
|
HTTPCode_Target_5XX_Count
|
GreaterThanThreshold, 5m, 1, Sum, 100
|
|
TargetResponseTime
|
GreaterThanThreshold, 5m, 1, p99, 3
|
|
HealthyHostCount
|
LessThanThreshold, 5m, 1, Minimum, 1
|
AWS/NetworkELB
|
HealthyHostCount
|
LessThanThreshold, 5m, 1, Minimum, 1
|
AWS/ElastiCache
|
CPUUtilization
|
GreaterThanThreshold, 5m, 1, Average, Created_by_CloudWatchAutoAlarms, 75
|
|
DatabaseMemoryUsagePercentage
|
GreaterThanThreshold, 5m, 1, Average, Created_by_CloudWatchAutoAlarms, 75
|
![](https://blog.kakaocdn.net/dn/bxn57s/btsIhcxyjI3/wOlZwM0oRJCfg090HDIuaK/img.png)
1) 함수 로직 추가
다른 서비스의 알람 추가를 위해 람다 함수를 다음과 같이 수정하였습니다.
- cw_auto_alarms.py : Cloudwatch 메트릭 추가 및 로직 추가
- action.py: 함수 정의로 위 메트릭에 맞게 Cloudwatch 알람을 추가합니다.
2) 변수 추가
변수 임계 값을 변수화하여 알람 조건을 변수에 따라 조절되도록 설정하겠습니다.
![](https://blog.kakaocdn.net/dn/bTRy0f/btsIiw2FGOJ/x1up8rToY8NSFfC2AXFTY0/img.png)
3) 이벤트 추가
자원 변동에 따라 이벤트를 추가하기 위해 Cloudwatch 이벤트 규칙을 추가합니다.
이벤트에서 람다함수를 호출하기 위해 Rule 설정, 타겟 설정, 권한 부여가 필요합니다.
resource "aws_cloudwatch_event_rule" "elb_event_rule" {
name = "Initiate-CloudWatchAutoAlarmsELB"
description = "Creates and deletes CloudWatch alarms for ELB instances"
event_pattern = jsonencode({
source = ["aws.elasticloadbalancing"],
detail-type = ["AWS API Call via CloudTrail"],
detail = {
eventSource = ["elasticloadbalancing.amazonaws.com"],
eventName = ["CreateLoadBalancer", "DeleteLoadBalancer"]
}
})
state = var.event_state
}
resource "aws_cloudwatch_event_target" "elb_event_target" {
rule = aws_cloudwatch_event_rule.elb_event_rule.name
target_id = "elbEventTarget"
arn = aws_lambda_function.cloudwatch_auto_alarms.arn
}
resource "aws_lambda_permission" "elb_event_permission" {
statement_id = "AllowExecutionFromCloudWatchEventsELB"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.cloudwatch_auto_alarms.function_name
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.elb_event_rule.arn
}
- aws_cloudwatch_event_rule.elb_event_rule: ELB 인스턴스의 생성 및 삭제 이벤트를 처리하기 위한 규칙을 생성합니다.
- aws_cloudwatch_event_target.elb_event_target: ELB 이벤트가 발생하면 Lambda 함수를 호출하도록 설정합니다.
- aws_lambda_permission.elb_event_permission: ELB 이벤트에서 Lambda 함수를 호출할 수 있도록 권한을 부여합니다.
4) 권한 추가
Lambda 함수가 AWS서비스(EC2, ELB, RDS, ElastiCache) 를 조회하기 위해 권한을 추가해야 합니다. 테라폼 모듈 내 iam.tf 에 아래와 같이 조회 권한을 추가했습니다.
# iam.tf
...
{
Effect = "Allow"
Action = ["rds:ListTagsForResource", "rds:DescribeDBInstances"]
Resource = "*"
},
{
Effect = "Allow"
Action = ["ec2:DescribeInstances", "ec2:DescribeImages"]
Resource = "*"
},
{
Effect = "Allow"
Action = ["ec2:CreateTags"]
Resource = "arn:aws:ec2:*:*:instance/*"
},
{
Effect = "Allow"
Action = ["cloudwatch:DescribeAlarms", "cloudwatch:DeleteAlarms", "cloudwatch:PutMetricAlarm"]
Resource = "arn:aws:cloudwatch:*:*:alarm:${var.alarm_identifier_prefix}-*"
},
{
Effect = "Allow"
Action = ["cloudwatch:DescribeAlarms"]
Resource = "*"
},
{
Effect = "Allow"
Action = ["lambda:ListFunctions", "lambda:ListTags"]
Resource = "*"
},
{
Effect = "Allow"
Action = ["elasticache:DescribeCacheClusters", "elasticache:ListTagsForResource"]
Resource = "*"
},
{
Effect = "Allow"
Action = ["elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeTags"]
Resource = "*"
}
..
모듈 업데이트 후 테스트를 해보겠습니다. 모듈 업데이트는 테라폼 명령어을 통해 진행합니다.
terraform plan
terraform apply
![](https://blog.kakaocdn.net/dn/dkzApB/btsIhidj4Z6/MZVcEKHE9EHDqkHXn4nDkK/img.png)
임의의 ELB를 생성하여 알람 설정이 제대로 되는 지 확인하겠습니다.
임의의 ALB를 생성하고, Tag 키에 Create_Auto_Alarms를 추가합니다.
![](https://blog.kakaocdn.net/dn/vDsue/btsIhtFPnf2/fyba7k4WwqrBCXashVKFv1/img.png)
![](https://blog.kakaocdn.net/dn/buLTtJ/btsIidbfEgg/M1x01mlyhKuCJDfeVGtIYK/img.png)
4.1 UCMP 모듈 적용 (에러 사례)
모듈 테스트가 끝났다면 다른 인프라 구성 모듈에 적용하겠습니다.
구성 적용 인프라 모듈은 책, 테라폼으로 시작하는 IaC 마지막 챕터 UCMP 를 참고하였습니다.
# UCMP 모듈 다운로드
git clone https://github.com/terraform101/terraform-refactoring-and-modularity.git
# 브랜치 변경
git checkout -b modularity origin/modularity
# 경로 확인
tree .
.
├── README.md
├── Template_UCSI_1_prd.jpeg
├── main.tf
├── modules
│ ├── common
│ │ ├── README.md
│ │ ├── main.tf
│ │ ├── output.tf
│ │ └── variable.tf
│ └── eks
│ ├── README.md
│ ├── aws-iam-authenticator
│ ├── iam-policy.json
│ ├── kubectl
│ ├── main.tf
│ ├── output.tf
│ ├── template
│ │ ├── cert-manager.tpl
│ │ ├── crd.tpl
│ │ ├── eniconfig.tpl
│ │ ├── ingress.tpl
│ │ ├── kubeconfig.tpl
│ │ └── sa.tpl
│ └── variable.tf
├── output.tf
└── variable.tf
modules 아래에 알람 자동화 모듈(cloudwatch_auto_alarms)을 추가하고 모듈 호출과 변수를 추가합니다.
# main.tf
..
module "cloudwatch_auto_alarms" {
source = "./modules/cloudwatch_auto_alarms"
memory = var.memory
event_state = var.event_state
alarm_notification_arn = var.alarm_notification_arn
alarm_identifier_prefix = var.alarm_identifier_prefix
}
# variable.tf
...
variable "memory" {
description = "Memory to allocate to Lambda function"
type = number
default = 128
}
variable "event_state" {
description = "Create Cloudwatch event to trigger execution on instance start / terminate."
type = string
default = "ENABLED"
}
variable "alarm_notification_arn" {
description = "Enter the Amazon SNS Notification ARN for alarm notifications, leave blank to disable notifications."
type = string
default = ""
}
마지막으로 UCMP 모듈 태그에 Create_Auto_Alarms 를 추가합니다.
# main.tf
..
provider "aws" {
region = var.region
// test
access_key = var.AWS_ACCESS_KEY_ID
secret_key = var.AWS_SECRET_ACCESS_KEY
default_tags { // 모든 resource에 기본으로 설정되는 Tag
tags = {
Environment = var.env
Project = var.pjt
COST_CENTER = "${var.env}_${var.pjt}"
TerraformManaged = true
PrivateInformation = var.private_information
Create_Auto_Alarms = "" # 알람 추가
}
}
}
..
테라폼 클라우드는 본 장에서는 다루지 않는 내용으로 적용 전 내용을 삭제합니다.
terraform {
# cloud {
# organization = "LG-uplus"
# hostname = "app.terraform.io"
# workspaces {
# name = "iac-academy"
# }
# }
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.0.0, < 4.0.0"
}
}
}
인프라 배포시 알람 모듈 내에서 오류가 발생합니다.
![](https://blog.kakaocdn.net/dn/mkCXT/btsIidI6Okp/YIQLR3Q6K8Ja1h6ffQ1ok1/img.png)
![](https://blog.kakaocdn.net/dn/Iawf5/btsIici6TJf/ITjIEauNrj4iLBoOj1EM9K/img.png)
aws_cloudwatch_event_rule 사용 모듈 버전이 다르기 때문인데요. UCMP에서 사용하는 모듈 버전은 3.75.2 로 state 라는 변수가 없기에 발생하는 문제입니다.
모듈 문서 내용을 참고하여 state가 is_enable로 되어 있는 것을 확인하고 default 값이 true로 되어있어 삭제를 진행합니다.
그럼에도 불구하고 일부 자원을 생성하지 못합니다.
UCMP 모듈 내 유효하지 않은 값으로 EC2 AMI, EKS를 생성하지 못하는 것을 확인할 수 있습니다.
![](https://blog.kakaocdn.net/dn/bD7T9m/btsIg9AVSwO/cbeWFpEiNMOfBa8XPxGAwK/img.png)
모듈 자체 내 문제기에 다른 모듈에서 테스트하겠습니다.
4.2 3 tier 모듈 적용
3 티어 모듈을 가져와서 알람 자동화를 테스트하겠습니다.
해당 모듈은 dev/stage/prod 로 환경이 나눠져있기에 prod안에서 S3 버킷과 모듈 추가를 진행해줍시다.
# repo
git clone https://github.com/BJWRD/three-tier-architecture.git
cd three-tier-architecture/envs/prod
# State S3 설정
vi version.tf
..
backend "s3" {
bucket = "" # S3 설정
key = "terraform.tfstate"
region = "ap-northeast-2" # 지역 설정
}
..
# EC2, RDS 모듈 내 태그 추가
vi moudules/ec2.tf
..
locals {
required_tags = {
project = var.project_name,
environment = var.environment,
Create_Auto_Alarms = "" # 추가
}
}
vi modules/rds.tf
..
locals {
required_tags = {
project = var.project_name,
environment = var.environment,
Create_Auto_Alarms = "" # 추가
}
}
해당 모듈도 테라폼 지원 버전 오류로 에러가 발생합니다.
![](https://blog.kakaocdn.net/dn/bgIDPB/btsIizSBrKP/tcHzDA1ZfEYJQGHCPKJLqK/img.png)
![](https://blog.kakaocdn.net/dn/GdcPs/btsIgPvXwh4/Jqv7LC0aSDiKL67iFHAZGK/img.png)
맥 환경 기준 tfenv 를 통해 테라폼 버전을 맞춰줍시다.
# 테라폼 버전 설정
tfenv use 1.3.9
# 모듈 버전 업그레이드
terraform init -upgrade
# 모듈 초기화
terraform init
# 인프라 적용 및 배포
terraform plan
terraform apply
적용이 완료되고 cloudwatch를 확인하면 알람이 자동으로 추가된 것을 확인할 수 있습니다.
![](https://blog.kakaocdn.net/dn/bYmZtg/btsIgGsn02x/kin5NF14hNuhFd1KG0J5Tk/img.png)
![](https://blog.kakaocdn.net/dn/U0NZN/btsIhAkrPF1/RiydzzD5jJMdOrUxcwXVP1/img.png)
'Cloud Tech' 카테고리의 다른 글
EKS에서 Atlantis 구성하기 (0) | 2024.07.14 |
---|---|
EKS Karpenter로 부드럽게 Migration 하기 (2) | 2024.07.06 |
테라폼 모듈을 활용한 CloudWatch Alarm 자동화 (0) | 2024.06.22 |
Terraform 내부 로직 이해 (0) | 2024.06.15 |
SonarQube를 활용한 EKS CleanCode CI /CD 파이프라인 구축하기 (0) | 2024.04.20 |