ECS + Fargate 구축 과정에서 Log 를 보기 위해서는 아주아주 번거롭다.
Private Subnet에 구축된 서버리스 환경에 컨테이너에 접근하기 위해 EC2에 접근하고 컨테이너에 접근하여야하는데, 이마저도 ECS에 execute command 설정이 필요하다.
따라서 외부에서 로그를 편하게 볼 수 있는 방법에 대해 고민에 빠졌다.
Log Appender를 구축하여 클러스터 외부에 Fluent를 구축하여 한곳에서 로그를 받아 처리할까 했지만 AWS에서는 FireLens라는 기능을 출시했다하여 사용해본 과정과 후기를 적어보려고 한다.
Fluentd: 플러그인 구조를 갖고 있는 로그 라우팅, 정제, 변환, 수집을 담당하는 툴
Fluent Bit: Fluentd의 경량화 버전
AWS FireLens는 Amazon ECS (Elastic Container Service) 컨테이너에서 발생하는 로그 데이터를 쉽게 수집, 전송 및 처리할 수 있는 로그 라우팅 솔루션이라고 한다. FireLens는 컨테이너 내에서 생성되는 로그 데이터를 중앙 집중화된 로그 스토리지나 다양한 로그 분석 도구로 전달하거나 가공할 수 있도록 도와준다고 한다.
동작 원리는 다음과 같다. 간편하다. 사이드카로 동일한 Task안에 FluentBit 컨테이너가 생성되고 이는 외부 로깅 서비스에 전달한다.
아키텍쳐가 이해가 안간다면 이 그림으로 이해하면 될 것 같다.
FireLens의 작동 방식을 간단히 살펴보자면
- Log Router 컨테이너: Amazon ECS 컨테이너 내에 별도의 Log Router 컨테이너를 실행.
- 로그 드라이버: FireLens는 로그 라우팅 작업을 수행하기 위해 여러 가지 로그 드라이버를 지원. 예를 들어, Fluentd나 Fluent Bit과 같은 다양한 로그 드라이버를 선택하여 사용할 수 있음. 이러한 드라이버는 로그 데이터를 수집, 가공하고 원하는 대상으로 전송하는 역할을 수행함.
- 로그 전송 및 가공: FireLens 로그 드라이버는 컨테이너 내에서 발생하는 로그 데이터를 가로채고, 필요에 따라 변환하거나 여러 로그 저장소로 전송한다. 예를 들어, CloudWatch Logs, Amazon S3, Amazon Kinesis, OpenSearch 등으로 로그 데이터 전송이 가능하다.
- 로그 가시성 및 분석: FireLens를 사용하여 로그 데이터를 중앙 집중화된 로그 관리 시스템으로 전송하면, 로그 데이터의 가시성과 분석이 용이해진다.
실제 설정은 매우 간단했다.
{
"containerDefinitions": [
{
"name": container name,
"image": image,
"cpu": 0,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080,
"protocol": "tcp"
}
],
"essential": true,
"environment": [],
"logConfiguration": {
"logDriver": "awsfirelens",
"options": {
"AWS_Auth": "On",
"AWS_Region": "ap-northeast-2",
"Host": opensearch 주소,
"Index": "인덱스 명",
"Name": "es",
"Port": "443",
"Suppress_Type_Name": "On",
"tls": "On"
}
}
},
{
"name": "log-router",
//aws에서 제공하는 fluent-bit 이미지
"image": "906394416424.dkr.ecr.ap-northeast-2.amazonaws.com/aws-for-fluent-bit:stable",
"cpu": 0,
"memoryReservation": 50,
"essential": true,
"user": "0",
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-create-group": "true",
"awslogs-group": "firelens-container",
"awslogs-region": "ap-northeast-2",
"awslogs-stream-prefix": "firelens"
}
},
"firelensConfiguration": {
"type": "fluentbit",
"options": {
"config-file-type": "file",
"config-file-value": "/fluent-bit/configs/parse-json.conf"
}
}
}
],
"taskRoleArn": "arn:aws:iam:::role/role-ecs-task",
"executionRoleArn": "arn:aws:iam:::role/role-ecs-task",
"networkMode": "awsvpc",
}
공식문서에 내용을 복사했다고 봐도 무방하다.
조심해야하는 내용은 "Suppress_Type_Name": "On" 이 부분이다.
| Suppress_Type_Name | When enabled, mapping types is removed and Type option is ignored. Types are deprecated in APIs in v7.0. This options is for v7.0 or later. | Off | | Workers | Enables dedicated thread(s) for this output. Default value is set since version 1.8.13. For previous versions is 0. | 2
필자 처럼 7이상의 최신버전을 쓰는 환경에서 해당 옵션을 추가하지 않는다면 bulk insert error에 대한 오류를 맛 볼 수 있을 것이다. 얼마전에 고생한 내용이지만 벌써 에러 로그 내용이 기억이 안나기 시작했다.
추가로 OpenSearch 생성할 때 Access 설정, 인바운드 설정은 놓치지 말고 잘 확인하도록 한다.
Stdout로그를 바로 캐치해서 보는 것은 상당히 보기 불편한 것 같다. multiline parser를 활용해 여러줄에 대한 동일 요청의 로그를 묶을 필요가 있다.
AWS에서는 aws-for-fluent-bit:latest 이미지에 멀티라인 관련된 설정파일 parsers_multiline.conf을 만들어 도커라이징하여 활용하는 방법을 가이드하고 있다. 근데 이부분을 해봤는데 필자는 로그 형식을 컨버팅한 부분이 많아서 제대로 묶이지 않는 부분이 많았다.
필자는 Java/Spring으로 된 서비스를 운영하기에 FluentD Library를 dependency 받아서 이미 묶인 로그를 FluentD로 보내는 방식으로 바꿨다.
Java/Spring을 활용한다면 관련된 포스팅을 참고하면 좋을 듯 하다.
https://sh970901.tistory.com/148
참고 자료
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/firelens-example-taskdefs.html
https://aws-diary.tistory.com/152
'IT' 카테고리의 다른 글
[Java] CompletableFuture의 이해와 활용 (1) | 2024.02.19 |
---|---|
Gitlab-Runner .m2 Caching (0) | 2024.02.16 |
gitlab runner docker in docker 구조 (1) | 2024.01.28 |
Valve(ErrorReportVavle)를 이용한 내장 톰캣 스프링 톰캣 버전 감추기 (0) | 2024.01.20 |
Java heap dump, JVM OOM(Out of Memory) (1) | 2024.01.09 |