본문 바로가기

Management

[실습] CloudWatch Log groups & Metrics (Agent 이용한 로그&지표 수집, 쿼리문 이용한 로그 검색, S3로 내보내기)

반응형

안녕하세요 서후아빠입니다. ^_^

이번 세션은 EC2에 설치된 CloudWatch Agent로부터 전달받은 서버 로그를 수집, 검색, 저장하는 프로세스에 대해서 실습을 해보겠습니다.


구성도

SSM 통신 경로를 통해서 CloudWatch Agent에서 수집한 로그를 CloudWatch 로그 그룹에 저장
EventBridge의 Cron Job을 통해 정기적으로 SNS Job을 수행
SNS에 구독된 SQS를 통해 Job을 큐에 저장해 놓고, Lambda는 SNS가 트리거가 되어 동작
Lambda function은 CloudWatch 로그 그룹을 지정된 S3 버킷으로 이동 복사 
S3는 LifeCycle에 따라 S3 Glacier 이동하여 보관

사전 작업

인프라 생성 : vpc, subnet, igw, routing table, iam, ec2  등은 설명 생략합니다. 

2022.07.02 - [Networking] - [실습] Amazon VPC 구성요소 생성하기

 

[실습] Amazon VPC 구성요소 생성하기

안녕하세요 서후아빠입니다. ^_^ 이번 세션은 VPC 관련 구성요소에 대해서 실습을 해보겠습니다. 구성도 1단계 : VPC 생성 VPC > Your VPCs > Create VPC 구분 VPC settings (VPC Only 방식) VPC settings (VPC and more 방

sh-t.tistory.com

1단계 : Private endpoint 생성

2022.09.23 - [Management] - [실습] AWS Systems Manager (Session Manager, Parameter Store, Run Command)-1편 의 1단계 참조 바랍니다.

2단계 : EC2에 IAM 권한 부여

IAM > Roles > 권한 부여할 Role 선택 > Permissions (tab) > Add permissions > Attach policies

AmazonSSMFullAccess, CloudWatchAgentServerPolicy, AmazonEC2RoleforSSM, AmazonSSMManagedInstanceCore, AmazonSSMPatchAssociation

신규로 IAM Role을 생성한 경우는 "EC2 > Instances > 권한 부여할 EC2 선택 > Actions > Security > Modify IAM role > 권한 부여된 Role 선택 > Update IAM role"로 적용합니다. 

CloudWatchAgentServerPolicy : EC2 인스턴스에서 CloudWatch로 지표 및 로그를 푸시하기 위한 Agent 설치/구성

3단계 : EC2에 CloudWatch Agent 설치

구분 내용
자동 설치 2단계 정책을 부여한 상태로 신규 EC2를 배포하면 자동으로 설치됨
수동 설치 (개별) [CentOS 계열 예시]
$ wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
$ sudo rpm -U ./amazon-cloudwatch-agent.rpm
$ sudo systemctl restart amazon-cloudwatch-agent.service
$ sudo systemctl enable amazon-cloudwatch-agent.service
$ sudo systemctl status amazon-cloudwatch-agent.service
수동 설치 (다중) [방법 1]
SSM > Quick Setup > Create > Host Management 의 Create
  - Configuration options : All check
  - Targets : Current Region, All instances

[방법 2]
SSM > Run Command > Run Command
  - Command document : AWS-ConfigureAWSPackage
  - Command parameters의 Name : AmazonCloudWatchAgent
  - Target selection : Choose instances manually

[결과 확인]
SSM > Fleet Manager : 확인 

4단계 : EC2에 설치된 CloudWatch Agent 설정

EC2에 SSH로 접속하여 CloudWatch Agent 구성합니다. (OS마다 조금씩 상이하며, 아래는 Amazon Linux 기준)

# Agent 구성 
sudo su
mkdir /usr/share/collectd
cd /usr/share/collectd
touch types.db

# config.json 생성 (설정값을 SSM > Parameter Store에 "AmazonCloudWatch-linux"로 저장됨)
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
=============================================================
= Welcome to the AWS CloudWatch Agent Configuration Manager =
=============================================================
On which OS are you planning to use the agent?
1. linux
2. windows
default choice: [1]:
Trying to fetch the default region based on ec2 metadata...
Are you using EC2 or On-Premises hosts?
1. EC2
2. On-Premises
default choice: [1]:
Which user are you planning to run the agent?
1. root
2. cwagent
3. others
default choice: [1]: 2
Do you want to turn on StatsD daemon?
1. yes
2. no
default choice: [1]:
Which port do you want StatsD daemon to listen to?
default choice: [8125]
What is the collect interval for StatsD daemon?
1. 10s
2. 30s
3. 60s
default choice: [1]:
What is the aggregation interval for metrics collected by StatsD daemon?
1. Do not aggregate
2. 10s
3. 30s
4. 60s
default choice: [4]:
Do you want to monitor metrics from CollectD?
1. yes
2. no
default choice: [1]:
Do you want to monitor any host metrics? e.g. CPU, memory, etc.
1. yes
2. no
default choice: [1]:
Do you want to monitor cpu metrics per core? Additional CloudWatch charges may apply.
1. yes
2. no
default choice: [1]:
2
Do you want to add ec2 dimensions (ImageId, InstanceId, InstanceType, AutoScalingGroupName) into all of your metrics if the info is available?
1. yes
2. no
default choice: [1]:
Would you like to collect your metrics at high resolution (sub-minute resolution)? This enables sub-minute resolution for all metrics, but you can customize for specific metrics in the output json file.
1. 1s
2. 10s
3. 30s
4. 60s
default choice: [4]:
Which default metrics config do you want?
1. Basic
2. Standard
3. Advanced
4. None
default choice: [1]: 3
... 생략...
Are you satisfied with the above config? Note: it can be manually customized after the wizard completes to add additional items.
1. yes
2. no
default choice: [1]:
Do you have any existing CloudWatch Log Agent (http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html) configuration file to import for migration?
1. yes
2. no
default choice: [2]: 1
Do you want to monitor any log files?
1. yes
2. no
default choice: [1]:
Log file path: /var/log/messages
Log group name: 미입력시 "Log file path" 기준으로 "messages"로 생성됨
default choice: [messages]
Log stream name:
default choice: [{instance_id}]
Do you want to specify any additional log files to monitor?
1. yes
2. no
default choice: [1]:
Log file path: /var/log/secure
Log group name: 미입력시 "Log file path" 기준으로 "secure"로 생성됨
default choice: [secure]
Log stream name:
default choice: [{instance_id}]
Do you want to specify any additional log files to monitor?
1. yes
2. no
default choice: [1]: 2
Saved config file to /opt/aws/amazon-cloudwatch-agent/bin/config.json successfully.
... 생략 ...
Please check the above content of the config.
The config file is also located at /opt/aws/amazon-cloudwatch-agent/bin/config.json.
Edit it manually if needed.
Do you want to store the config in the SSM parameter store?
1. yes
2. no
default choice: [1]:
What parameter store name do you want to use to store your config? (Use 'AmazonCloudWatch-' prefix if you use our managed AWS policy)
default choice: [AmazonCloudWatch-linux]
Trying to fetch the default region based on ec2 metadata...
Which region do you want to store the config in the parameter store?
default choice: [ap-northeast-2]
Which AWS credential should be used to send json config to parameter store?
1. ASIAZYLTNL6RST6A4O44(From SDK)
2. Other
default choice: [1]:
Successfully put config to parameter store AmazonCloudWatch-linux.
Program exits now.

# 특정 경로 디스크만 모니터링 하는 경우 config.json 내용을 아래처럼 일부 수정
{
  "agent": {
    "metrics_collection_interval": 3600
  },
  "metrics": {
    "append_dimensions": {
        "InstanceId": "${aws:InstanceId}"
    },
    "metrics_collected": {
      "disk": {
        "measurement": [
          "used_percent"
        ],
        "metrics_collection_interval": 3600,
        "resources": [
          "/"
        ]
      }
    }
  }
}
위와 같이 구성하면 EC2의 메모리, 디스크 사용율 등 지표도 수집됩니다. 

SSM > Parameter Store > AmazonCloudWatch-linux 생성 확인

Run Command를 이용하여 다른 EC2에 동일하게 CloudWatch Agent 구성합니다. 

SSM > Run Command > Run a Command

Command document Command parameters의 
Optional Configuration Location
Target selection
AmazonCloudWatch-ManageAgent AmazonCloudWatch-linux Choose instances manually

5단계 : 수집한 서버 로그를 이용하여 지표 추가 (SKIP 가능)

CloudWatch > Log groups > 생성된 로그 그룹 선택 (ex : messages, secure) > Actions > Create metric filter > ...

CloudWatch > All metrics > Custom namespaces에 수동으로 추가된 지표 확인됨

6단계 : 수집한 서버 로그를 쿼리문으로 로그 검색 (SKIP 가능)

CloudWatch > Log Insights > Select log groups(s)에서 검색하고자 하는 로그 그룹 선택 

형식 쿼리 예시문
필드명 지정 fields @필드A, @필드B
필터링 filter @필드 like /문자열/
filter @필드 like /^(?i)문자열/  : 시작(^), 대소문자 구분안함((?i))
filter (필드>2000)   
filter (필드A = 10 or 필드명B >20)
filter 필드 in [300,400,500]   : 300,400,500 있으면 반환
filter 필드 not in ["ab", "cd"]  : ab나 cd가 없는 것만 반환
통계 (avg, count, min, max) stats sum(필드B) by 필드A  : 필드A값을 필드B에 합계 반환 
stats avg(필드A) as 필드B   : 필드A 평균을 필드로 계산
정렬 sort @필드명 desc
쿼리 결과 수 제한 limit 숫자

[쿼리문 사용 예시 : message필드에서 DPD 문자열로 필터링]
[쿼리문 결과 예시 : DPD 문자열로 필터링된 100개 출력]

예제 쿼리는 "CloudWatch > Log Insights > 우측의 Queries > Lambda, VPC Flow Logs, CloudTrail, etc"를 참조 바랍니다. 

쿼리 실행 결과(로그, 시각화) 확인, 결과 내보내기, 대시보드 추가 기능도 있습니다.

7단계 : 수집한 서버 로그를 S3로 내보내기 (수동)

S3 > 버킷 선택(ex : mybucket) > Permissions(tab) > Bucket policy > Edit

# 예시 (버킷명 "mybucket", 리전 "ap-northeast-2", AWS 계정 "111111111111")
{
    "Version": "2012-10-17",
    "Statement": [
      {
          "Action": "s3:GetBucketAcl",
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::mybucket",
          "Principal": { "Service": "logs.ap-northeast-2.amazonaws.com" },
          "Condition": {
            "StringEquals": {
                "aws:SourceAccount": [
                    "111111111111"
                ]
            },
            "ArnLike": {
                    "aws:SourceArn": [
                        "arn:aws:logs:ap-northeast-2:111111111111:log-group:*"
                     ]
            }
          }
      },
      {
          "Action": "s3:PutObject" ,
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::mybucket/*",
          "Principal": { "Service": "logs.ap-northeast-2.amazonaws.com" },
          "Condition": {
            "StringEquals": {
                "s3:x-amz-acl": "bucket-owner-full-control",
                "aws:SourceAccount": [
                    "111111111111"
                ]
            },
            "ArnLike": {
                    "aws:SourceArn": [
                        "arn:aws:logs:ap-northeast-2:111111111111:log-group:*"
                    ]
            }
          }
      }
    ]
}
S3 > 버킷 선택(ex : mybucket) > Management(tab)에서 LifeCycle 설정을 진행합니다. 
  - LifeCycle 은 버킷 버전관리 활성화 상태에서 동작합니다. 

CloudWatch > Log groups > 로그 그룹 선택 > Actions > Export data to Amazon S3 

Define data export Choose S3 bucket
From : 기간 지정(yyyy/mm/dd hh:mm~yyyy/mm/dd hh:mm)
Stream prefix(옵션) : -
Select account : This account
S3 bucket name : mybucket
S3 bucket prefix(옵션) : -

7단계 : 수집한 서버 로그를 S3로 내보내기 (자동)

SQS > Queues > Create queue > Type(Standard), Name(my-sqs), 그외(기본값)

SNS > Topics > Create topic > Type(Standard), Name(my-sns), 그외(기본값)

SNS > Subscriptions > Subscriptions(tab) > Create subscription 

Details 그 외
Topic ARN : my-sns
Protocol : Amazon SQS
Endpoint : my-sqs
기본값

Lambda > Functions > Create function 

Basic information 그 외
Function name : my-function
Runtime : Python 3.10
Architecture : x86_64
기본값

Lambda > Functions > my-function 선택 > +Add trigger에서 SQS 선택 > SQS queue "my-sqs" 선택, 그 외 기본값 > Add

Lambda > Functions > my-function 선택 > Code(tab)

import boto3
import os
import datetime
 
GROUP_NAME = os.environ['GROUP_NAME']
DESTINATION_BUCKET = os.environ['DESTINATION_BUCKET']
PREFIX = os.environ['PREFIX']
PERIOD = os.environ['PERIOD']
PERIOD = int(PERIOD)
 
currentTime = datetime.datetime.now()
startDate = currentTime - datetime.timedelta(PERIOD)
endDate = currentTime - datetime.timedelta(PERIOD - 1)
 
fromDate = int(startDate.timestamp() * 1000)
toDate = int(endDate.timestamp() * 1000)
 
BUCKET_PREFIX = os.path.join(PREFIX, startDate.strftime('%Y{0}%m{0}%d').format(os.path.sep))
 
def lambda_handler(event, context):
    print(currentTime, startDate, endDate, PERIOD, fromDate, toDate)
    client = boto3.client("logs")
    client.create_export_task(
        logGroupName= GROUP_NAME,
        fromTime = fromDate,
        to=toDate,
        destination=DESTINATION_BUCKET,
        destinationPrefix=BUCKET_PREFIX
        )

Lambda > Functions > my-function 선택 > Configuration(tab) > Environment variables의 Edit

Key Value
DESTINATION_BUCKET mybucket
GROUP_NAME 로그그룹명 입력 (ex : messages)
PERIOD 1
PREFIX exported-logs
하루치의 로그를 mybucket으로 내보내기 위한 변수 

IAM > Roles > 람다 생성 시 자동 생성된 role 선택 > Permissions (tab) > Add Permissions > Attach policies >

AmazonSQSFullAccess, AmazonS3FullAccess, CloudWatchLogsFullAccess 

편의상 FullAccess 권한을 설정하였으나, 실제 운영 시에는 최소한의 권한 부여를 권고드립니다.

Amazon EventBridge > Schedules > Create schedule 

Specify schedule detail Select target Settings(옵션)
Schedule name and description
  - Schedule name : my-schedule
  - Schedule group : default 
Schedule pattern
  - Occurrence : Recurring schedule (or One-time schedule)
  - Schedule type : Cron-based schedule (or Rate-based schedule)
  - Cron expression : 0 0 * * ? *
  - Flexible time window : Off
Timeframe
  - Timezone (옵션) : (UTC +09:00) Asia/Seoul
  - Start date and time (옵션) : 2023/05/15 00:00
  - End date and time (옵션) : 2023/05/16 00:00
Target detail
  - Target API : Templated targets (or All APIs)
  - Amazon SNS Publish 선택 
Publish
  - SNS topic : my-sns 
기본값

하루마다 동작하는 Cron job 설정 (0 0 * * ? *)

지정된 버킷(ex : mybucket)에 prefix/year/month/day/UUID/로그 그룹이름 아래에 하루마다 객체가 저장
  ※ mybucket > exported-logs/ > 2023/ > 05/ > 15/ > 368************/ > messages / ****.gz

8단계 : 로그 그룹 보존 기간 설정

매일 S3로 로그가 이동되기 때문에 로그그룹의 보존기간은 최소한으로 수정합니다.

참고 URL 

S3 내보내기 : https://repost.aws/ko/knowledge-center/cloudwatch-push-metrics-unified-agent

특정 CloudWatch Logs 청구액 증가 확인 방법 : https://repost.aws/ko/knowledge-center/cloudwatch-logs-bill-increase    

CloudWatch Logs 중앙 집중화 
  - https://www.megazone.com/techblog_20200630_build-infrastructure-for-centralized-logging-using-aws-cdk/  

  - https://www.joinc.co.kr/w/man/12/aws/scenario/logging

반응형