안녕하세요 서후아빠입니다. ^_^
이번 세션은 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 구성요소 생성하기
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 숫자 |
예제 쿼리는 "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/
'Management' 카테고리의 다른 글
[실습] AWS Backup으로 VMware 백업/복구 (0) | 2024.06.11 |
---|---|
[실습] Datadog 수집 정보 Private하게 연결 (0) | 2024.04.29 |
[실습] Control Tower 구성하기 - 3편 (보안과 규제 관리) (0) | 2023.02.10 |
[실습] Control Tower 구성하기 - 2편 (IAM Identity Center = SSO, Okta 연동) (0) | 2023.02.10 |
[실습] Control Tower 구성하기 - 1편 (배포, AWS 계정 관리, LifeCycle 이벤트, 메뉴) (0) | 2023.02.10 |