FluentBit + CloudWatch logs 로 Pods Application 로그 수집하기
AWS를 개인적으로 구성하면서 적다보니, 140만원이 청구되어 환경이 갖춰지기 전까진 글로만...

빨간색 부분에서 데몬셋으로 실행된 FluentBit가 각 Pods의 로그를 수집하여 CloudWatchLogs에 항목별로 쌓아주는 구성을 작성
참고글 : https://repost.aws/ko/knowledge-center/cloudwatch-stream-container-logs-eks
(작성하고 찾아보니 질문이 아닌 공식 문서에도 적혀있다)
Amazon EKS에서 컨테이너 로그를 CloudWatch로 스트리밍 | AWS re:Post
Amazon Elastic Kubernetes Service(Amazon EKS)에서 실행되는 컨테이너 로그를 CloudWatch Logs와 같은 로깅 시스템으로 스트리밍하고 싶습니다. 어떻게 해야 합니까?
repost.aws
위 참고 문서를 읽어보면 FluentD, FluentBit 두 개 다 구성 할 수 있으나, AWS에서는 FluentBit를 추천.
1. FleuntBit가 CloudWatchLogs에 알아서 쌓을 수 있도록,
CloudWatchAgentServerPoliy 권한을 가지고있는 Role를 만들기
1. IAM 역할 탭 접속후 역할 만들기 선택

2. 신뢰할 수 있는 엔터티 유형에서 웹 자격 증명 선택

3. EKS 지정된 클러스터에서만 동작 할 수 있도록 EKS의 자격 증명 공급자(OIDC) 선택
- 만약 EKS OIDC를 모른다면 EKS 페이지에서 클러스터 정보에서 OpenID Connect(OIDC)의 값을 확인

4. 권한 정책에서 정책 생성 선택

5. JSON 편집에서 해당 내용 작성
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
"cloudwatch:PutMetricData",
"ec2:DescribeVolumes",
"ec2:DescribeTags",
"logs:PutLogEvents",
"logs:DescribeLogStreams",
"logs:DescribeLogGroups",
"logs:CreateLogStream",
"logs:CreateLogGroup"
],
"Resource" : "*"
},
{
"Effect" : "Allow",
"Action" : [
"ssm:GetParameter"
],
"Resource" : "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*"
}
]
}
6. 검토에서 알맞은 이름 작성 후 정책생성

2. EKS에 FluentBit를 설치하고 IAM 역할을 부여하여 로그 수집후 CloudWatch logs에 전달하기
1. kubectl 명령어로 cloudWatch 용 namespace 생성
- 별 내용 없이 amazon-cloudwatch 라는 namespace가 생성됨
kubectl apply -f https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/cloudwatch-namespace.yaml
## create amazon-cloudwatch namespace
# apiVersion: v1
# kind: Namespace
# metadata:
# name: amazon-cloudwatch
# labels:
# name: amazon-cloudwatch
2. 클러스터에 지정할 configmap 작성
ClusterName=나의 클러스터 이름
RegionName=내 리전 (ap-northeast-ap2)
FluentBitHttpPort='2020'
FluentBitReadFromHead='Off'
[[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On'
[[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On'
kubectl create configmap fluent-bit-cluster-info \
--from-literal=cluster.name=${ClusterName} \
--from-literal=http.server=${FluentBitHttpServer} \
--from-literal=http.port=${FluentBitHttpPort} \
--from-literal=read.head=${FluentBitReadFromHead} \
--from-literal=read.tail=${FluentBitReadFromTail} \
--from-literal=logs.region=${RegionName} -n amazon-cloudwatch
3. 해당 문서를 yaml 로 생성하고 배포함
kubectl apply -f https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/fluent-bit/fluent-bit.yaml
4. 배포 된 fluentBit에 앞에서 생성한 role을 부여함 (위 문서에 annotation으로 붙음)
kubectl annotate serviceaccounts fluent-bit -n amazon-cloudwatch "eks.amazonaws.com/role-arn=arn:aws:iam::{AWS 계정}:role/{앞서 만든 role 이름}"
끗
1. 위에서 적용한 문서를 살펴보면..
application-log.conf, dataplane-log.conf, host-log.conf 3가지 설정으로 cloudwatch logs 에 쌓임.
나는 application 의 로그가 필요하므로 dataplane-log.conf, host-log.conf 두개의 설정을 모두 지움.
2. application-log.conf 중 INPUT 부분들을 살펴보면...
application-log.conf: |
[INPUT]
Name tail
Tag application.*
Exclude_Path /var/log/containers/cloudwatch-agent*, /var/log/containers/fluent-bit*, /var/log/containers/aws-node*, /var/log/containers/kube-proxy*
Path /var/log/containers/*.log
multiline.parser docker, cri
DB /var/fluent-bit/state/flb_container.db
Mem_Buf_Limit 50MB
Skip_Long_Lines On
Refresh_Interval 10
Rotate_Wait 30
storage.type filesystem
Read_from_Head ${READ_FROM_HEAD}
[INPUT]
Name tail
Tag application.*
Path /var/log/containers/fluent-bit*
multiline.parser docker, cri
DB /var/fluent-bit/state/flb_log.db
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10
Read_from_Head ${READ_FROM_HEAD}
[INPUT]
Name tail
Tag application.*
Path /var/log/containers/cloudwatch-agent*
multiline.parser docker, cri
DB /var/fluent-bit/state/flb_cwagent.db
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10
Read_from_Head ${READ_FROM_HEAD}
- tail 로 새로 생성된 로그의 꽁지 부분을 계속 가져간다.
- Excplude_Path 로 cloudwatch logs 로 올리고싶지 않은 패키지 + 파일이름을 지정 할 수 있다.
- path 로 올리고 싶은 패키지 + 파일이름을 지정 할 수 있다.
- 이전에 설치한 argoCd의 로그도 올라가기 때문에 Exclude_Path에 /var/log/containers/argoCd* 도 추가함
- DB를 보면 어디쪽에 쌓이는지 알 수 있다
3. application-log.conf의 OUTPUT부분을 살펴본다면
[OUTPUT]
Name cloudwatch_logs
Match application.*
region ${AWS_REGION}
log_group_name /aws/containerinsights/${CLUSTER_NAME}/application
log_stream_prefix ${HOST_NAME}-
auto_create_group true
extra_user_agent container-insights
- Match로 cloudwatch_logs의 path가 어느정도 지정된다
- log_group_name에서 클러스터의 이름대로 로그가 그룹핑된다.
- prefix의 값으로 다른 Pods들과 구분지어 로그가 쌓이게 된다.