회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
AWS 이용 중이라면 최대 700만 원 지원받으세요
국내 유명 IT 기업은 한국을 넘어 세계를 무대로 할 정도로 뛰어난 기술과 아이디어를 자랑합니다. 이들은 기업 블로그를 통해 이러한 정보를 공개하고 있습니다. 요즘IT는 각 기업의 특색 있고 유익한 콘텐츠를 소개하는 시리즈를 준비했습니다. 이들은 어떻게 사고하고, 어떤 방식으로 일하는 걸까요?
회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!
확인
국내 유명 IT 기업은 한국을 넘어 세계를 무대로 할 정도로 뛰어난 기술과 아이디어를 자랑합니다. 이들은 기업 블로그를 통해 이러한 정보를 공개하고 있습니다. 요즘IT는 각 기업의 특색 있고 유익한 콘텐츠를 소개하는 시리즈를 준비했습니다. 이들은 어떻게 사고하고, 어떤 방식으로 일하는 걸까요?
이번 글은 국내 화장품 시장의 정보 비대칭 문제를 해결하고 소비자 중심의 뷰티 시장을 만들어 가고 있는 ‘화해’의 데스옵스팀 이야기입니다. AWS EventBridge를 활용해 업무 자동화를 할 수 있는 방법을 소개합니다.
안녕하세요, 화해 데브옵스팀 장영석입니다.
AWS가 제공하는 서비스들은 대부분 모니터링 및 로깅을 제공합니다. 하지만 AWS 리소스에서 CloudWatch로 로그를 수집할 경우, 보관 주기를 CloudWatch의 AWS 콘솔이나 CLI를 사용하여 별도로 설정해줘야 하는 번거로움이 있습니다. 예를 들어 API Gateway stage의 로깅 설정 시 보관 주기 설정 기능이 없어 CloudWatch log group에서 재설정을 해야 합니다. 또 다른 예시로 CodeBuild 작업의 진행상황을 받아보려 해도 AWS 콘솔이나 CLI를 통한 알림 설정을 제공하지 않습니다.
이러한 불편함을 해소하기 위한 업무 자동화 방법 중 하나로 EventBridge를 소개합니다. 이번 글에서는 EventBridge의 여러 역할 중 AWS 서비스 이벤트 데이터 전송에 대해서 다루려 합니다.
EventBridge는 AWS 서비스 이벤트를 사용하여 이벤트 기반 애플리케이션을 대규모로 손쉽게 구축할 수 있는 서버리스 이벤트 버스로, 이벤트 소스의 실시간 이벤트 스트림을 원하는 대상으로 전송하는 역할을 합니다. 또한 이벤트 패턴을 기반으로 Rule을 설정하여 데이터를 필터링하고 전송할 대상을 선택할 수 있어 이벤트 생산자와 소비자의 분리가 가능합니다.
여러 이벤트 소스 중 AWS Service는 EventBridge의 Default EventBus를 사용하며 수많은 이벤트를 전송합니다. 현재 EventBridge가 지원하는 AWS 서비스 목록은 공식 문서에서 확인할 수 있습니다.
Default EventBus에 전송된 이벤트는 Rule을 통해 사용자가 설정한 이벤트 패턴을 기반으로 필터링되고 필요한 대상에게 전달됩니다. 대상은 다양한 방식으로 설정할 수 있습니다. 예를 들어 이벤트 데이터를 파싱 하여 원하는 메시지 형태로 Slack에 전송하는 AWS Lambda Function을 사용할 수 있습니다. 또는 SNS Topic으로 이벤트를 전송하고 해당 Topic을 Subscribe 하는 대상들이 이벤트를 처리하도록 구성할 수도 있습니다.
Rule의 역할은 이벤트 데이터를 필터링하고 특정 대상에게 전달하는 것입니다. 그중 필터링에 관해 얘기해보겠습니다.
대부분의 AWS Service 이벤트는 EventBridge의 Default EventBus에 JSON 형태의 콘텐츠를 전달합니다. Rule 작성 시 이벤트 패턴을 정의하여 이와 일치하는 데이터를 대상에게 전달할 수 있습니다. 이벤트 패턴에 작성하지 않은 필드는 일치 여부를 판단하지 않습니다.
단순한 설정이라도 사용자가 수동으로 설정해야 한다면 잘못된 값을 사용하거나 아예 작업 자체를 놓칠 가능성이 매우 큽니다. 이러한 상황을 개선한 몇 가지 자동화 사례를 소개해보겠습니다.
CodeBuild 프로젝트에서 빌드를 생성한 후 상태 변화를 발송하는 이벤트인 CodeBuild State Change Event
를 이용해, 특정 패턴과 일치하는 경우에만 대상으로 전송하는 예제를 만들어보겠습니다.
필터링 조건은 아래와 같습니다.
1. 상태가 SUCCEEDED | FAILED | STOPPED
인 경우
2. CodeBuild 프로젝트 이름이 test-codebuild-project
인 경우
이제 AWS Console을 사용해 Rule을 등록해보겠습니다.
AWS Console → Amazon EventBridge → Events → Rules → Create rule 버튼을 클릭해 새로운 Rule을 생성합니다.
패턴 정의 섹션에서 필요한 항목을 선택한 결과로 생성된 이벤트 패턴을 확인합니다.
이벤트 패턴을 직접 작성할 수도 있지만 대부분의 AWS service의 경우 기본으로 제공하는 이벤트 패턴을 선택할 수 있습니다. 아래 그림처럼 CodeBuild 이벤트 소스와 CodeBuild Build State Change 이벤트 타입을 선택합니다. Specific states는 다중 선택이 가능하므로 알림이 필요한 상태를 모두 선택합니다.
선택한 항목을 기반으로 이벤트 패턴이 정상적으로 생성되었는지 확인합니다. 자동 생성된 이벤트 패턴에서 build-status 값이 세 가지 상태를 포함한 리스트라는 걸 확인할 수 있습니다. 세 가지 상태 중 하나라면 해당 이벤트가 일치한다고 판단합니다.
{
...
"detail": {
"build-status": ["SUCCEEDED", "FAILED", "STOPPED"] # 세 가지 상태 중 하나만 일치한다면 통과
}
...
}
아래 그림처럼 원하는 이벤트 샘플을 미리 확인할 수도 있습니다.
아래 샘플을 참고하여 이벤트 패턴에 사용할 수 있는 필드를 확인할 수 있습니다.
# 샘플 이벤트
{
"version": "0",
"id": "bfdc1220-60ff-44ad-bfa7-3b6e6ba3b2d0",
"detail-type": "CodeBuild Build State Change",
"source": "aws.codebuild",
"account": "123456789012",
"time": "2017-07-12T00:42:28Z",
"region": "us-east-1",
"resources": ["arn:aws:codebuild:us-east-1:123456789012:build/SampleProjectName:ed6aa685-0d76-41da-a7f5-6d8760f41f55"],
"detail": {
"build-status": "SUCCEEDED",
"project-name": "SampleProjectName",
"build-id": "arn:aws:codebuild:us-east-1:123456789012:build/SampleProjectName:ed6aa685-0d76-41da-a7f5-6d8760f41f55",
"current-phase": "COMPLETED",
"current-phase-context": "[]",
"version": "1"
}
}
지금은 프로젝트 이름이 필요하니 detail.project-name을 사용하여 아래와 같이 이벤트 패턴에 추가합니다.
{
"source": "aws.codebuild",
"detail-type": "CodeBuild Build State Change",
"detail": {
"build-status": ["SUCCEEDED", "FAILED", "STOPPED"],
"project-name": "test-codebuild-project" # 프로젝트 이름 패턴 추가
}
}
완성된 패턴을 콘솔의 이벤트 패턴 항목에서 Edit pattern 버튼을 클릭하여 수정합니다.
Rule을 통과한 이벤트가 전달될 대상을 선택합니다. 대상은 다중 선택이 가능합니다.
슬랙에 이벤트를 전송하기 위해 생성해둔 lambda 함수를 대상으로 선택합니다.
원하는 대상을 선택한 후 Configure input 옵션을 선택하여 이벤트 콘텐츠를 원하는 형태로 대상에게 전달할 수 있습니다.
CodeBuild 서비스에서 생성된 값을 그대로 대상에게 전달하는 Matched events를 선택하고 하단의 Create 버튼을 통해 Rule을 생성합니다.
이제 Rule 작업이 완료되었습니다. Rule 상세화면의 Monitoring 탭에서 이벤트 패턴과 일치하는 케이스의 발생 지표를 확인할 수 있습니다.
AWS managed 서비스는 각각의 로깅 방식을 제공하고 대부분 Cloudwatch logs를 통해 지원합니다. API Gateway도 마찬가지로 AWS 콘솔에서 활성화하여 실행 로그와 액세스 로그를 기록할 수 있습니다. 하지만 로그 보관 주기 설정은 API Gateway 서비스의 자체 기능만으로는 불가능합니다. Cloudwatch logs 콘솔에서 해당 log group의 보관 주기를 직접 설정하거나 CLI를 사용하는 등의 추가 작업이 필요합니다.
API Gateway 로그 설정 방법과 커스텀 액세스 로그 포맷 구성을 위한 필드에는 무엇이 있는지 알아보고, Stage를 새로 생성할 때 로그 활성화 및 보관 주기 설정을 자동화하기 위한 EventBridge를 구성해보겠습니다.
로그 활성화는 API Gateway → API → Stage → Logs/Tracing 탭에서 가능하며 CloudWatch Settings 메뉴에서 실행 로그를, Custom Access Logging 메뉴에서 액세스 로그를 설정할 수 있습니다.
실행 로그에서는 오류 또는 요청 또는 응답 파라미터나 페이로드 데이터, 사용량 계획이 활성화되는지 여부 등의 정보가 포함되어 있습니다. 환경이나 목적별로 필요한 옵션들을 활성화하여 관리합니다.
\Option | Value | Description |
Enable CloudWatch Logs | true | execution 로그 기록을 활성화 |
Log level | Info | 기록될 로그 레벨 (Info | Error) |
Log full requests/response data | true | 요청/응답의 바디 데이터 기록 활성화 |
Enable Detailed CloudWatch Metrics | true | metric 데이터 기록 활성화 |
액세스 로그를 활성화하면 클라이언트 정보나 접근 경로, 응답 상태 코드, 지연시간 등의 다양한 정보를 조회할 수 있습니다. 제공되는 필드를 조합하여 커스텀 로그 포맷 설정도 가능합니다.
액세스 로그 저장소는 Cloudwatch와 Kinesis가 가능하나 이번 예시에서는 Cloudwatch를 사용합니다. 커스텀 로그 포맷은 아래와 같이 미리 제공되는 필드들을 값으로 사용할 수 있으며 키 값은 자유롭게 설정할 수 있습니다.
{
"requestId":"$context.requestId",
"ip": "$context.identity.sourceIp",
"requestTime":"$context.requestTime",
"httpMethod":"$context.httpMethod",
"resourcePath":"$context.resourcePath",
"status":"$context.status",
"protocol":"$context.protocol",
"responseLength":"$context.responseLength",
"integrationStatus":"$context.integrationStatus",
"integrationLatency":"$context.integration.latency",
"userAgent":"$context.identity.userAgent"
}
위 예시에서 사용되는 필드의 설명은 아래와 같습니다. 모든 필드에 대한 설명은 공식 문서를 참고합니다.
Key | Value | Description |
requestId | $context.requestId | API Gateway가 API 요청에 할당하는 ID |
ip | $context.identity.sourceIp | API Gateway 요청자 IP 주소 |
userAgent | $context.identity.userAgent | 요청 User-Agent 헤더 |
requestTime | $context.requestTime | CLF 형식의 요청 시간(dd/MMM/yyyy:HH:mm:ss +-hhmm) |
httpMethod | $context.httpMethod | 요청 메서드 타입. DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT |
path | $context.path | 요청 경로 |
resourcePath | $context.resourcePath | 리소스에 대한 경로. 예를 들어 https://{rest-api-id}.execute-api.{region}.amazonaws.com/{stage}/root/child의 요청 URI의 경우, $context.resourcePath 값은 /root/child |
stage | $context.stage | API 요청 stage 이름 |
status | $context.status | 메서드 응답 상태 코드 |
protocol | $context.protocol | 요청 프로토콜(예: HTTP/1.1) |
responseLength | $context.responseLength | 응답 페이로드 길이 |
responseLatency | $context.responseLatency | 응답 지연 시간(ms) |
integrationStatus | $context.integrationStatus | integration endpoint 응답 상태 코드 |
integrationLatency | $context.integration.latency | integration endpoint 에서 gateway 요청을 처리한 시간 |
로그 활성화 시 사용되는 execution, access log의 Cloudwatch log group의 보관 주기는 콘솔이나 AWS CLI를 통해 직접 수정해야 합니다.
CloudWatch → Log groups → Log group 선택 → Actions → Edit retention setting 진입하여 원하는 보관 주기를 설정합니다.
먼저 API Gateway 로그 활성화 이벤트를 파악해야 합니다. Stage 생성 시점에 lambda 함수를 사용하여 CloudWatch log group을 생성 후 로그 활성화 작업을 해보겠습니다.
API Gateway의 Stage가 생성되는 시점을 파악하기 위한 이벤트는 CreateStage 또는 CreateDeployment입니다.
boto3 SDK를 활용하여 아래 세 단계의 코드를 작성합니다. 각 단계의 괄호에 참고한 boto3 SDK 함수 링크를 참고합니다.
1. 로그 보관에 사용할 CloudWatch log group 생성 (create_log_group)
2. 1번에서 생성한 CloudWatch log group의 보관 주기 설정 (put_retention_policy)
3. API Gateway Stage의 로깅 활성화 (API Gateway update_stage)
CloudWatch log group 생성 및 보관 주기 설정, API Gateway UpdateStage 실행 권한이 필요하므로 lambda → Conguration → Permissions → Execution role에 아래 Policy를 추가합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "apigateway:PATCH",
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"logs:PutRetentionPolicy",
"logs:CreateLogGroup"
],
"Resource": "arn:aws:logs:ap-northeast-2:230667876840:*"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:ap-northeast-2:230667876840:log-group:/aws/lambda/hh-lmd-update-api-gateway-log-setting:*"
}
]
}
API Gateway의 Stage 생성 방식은 직접 생성과 리소스 배포 시 간접 생성 두 가지입니다. 두 이벤트 모두 로그 설정이 필요하므로 Eventbridge rule에 포함시킵니다.
EventBridge의 자세한 설정법은 이미 CodeBuild 작업 결과 자동화에서 다루었기에 생략합니다.
API Gateway에서 발생하는 CreateStage, CreateDeployment 이벤트가 발생할 경우 위에서 생성한 labmda가 실행되도록 대상으로 설정합니다.
{
"source": ["aws.apigateway"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["apigateway.amazonaws.com"],
"eventName": ["CreateStage", "CreateDeployment"]
}
}
여기까지 EventBridge를 사용한 설정 자동화 사례를 몇 가지 소개했습니다.
업무 자동화 활동은 단기적으로는 추가 업무로 생각될 수 있으나 장기적으로는 팀 동료들이 더 중요한 일에 집중할 수 있는 환경을 제공하는 데 큰 역할을 한다고 생각합니다. 화해 데브옵스팀은 동료들의 업무 생산성과 안정성을 위해 앞으로도 더 많은 자동화 작업을 계획하고 있습니다. 좀 더 흥미로운 사례를 모아 다시 찾아뵙겠습니다.
<원문>