[AWS] ECS: 로그 수집 드라이버

[원본 링크]

ECS-Fargate에서는 기본적으로 Cloudwatch에 표준 로그를 쌓는 것을 기본 구성으로 사용한다.
하지만 필요에 따라서 로그 수집 방식이나 수집 저장소를 교체하는 것은 가능하다. 이에 대해 간단히 정리해본다.

로그 드라이버는 AWS ECS/Batch의 작업정의 - 컨테이너 계층에서 설정할 수 있다.
콘솔에서는 이런 식으로 뜬다.




기본값: Cloudwatch (awslogs)

가장 권장되는 기본 옵션은 당연히 그냥 Cloudwatch를 사용하는 것이다.
이걸 활성화하기만 해도, 표준 출력에 쓰이는 로그들을 자동으로 읽어서 Cloudwatch 로그 그룹에 전송해준다.

Cloudwatch에 로그를 쓰는 쓰기 비용과 저장비용은 당연히 추가 과금 요소다.
하지만 관리포인트가 매우 적고 간편하므로, 로그를 보관할만한 장소가 따로 없다면 이만한 것이 없다.

그리고 이것도 세부 조정 옵션이 꽤 있다.
awslogs-group을 바꾸면 로그를 쓸 로그 그룹의 이름을 변경할 수 있고, awslogs-region을 조정하면, 로그를 다른 리전의 로그 그룹에 쓰도록 할 수도 있다.


awslogs: blocking과 non-blocking

그리고 의외로, awslogs에는 발생 가능한 성능 병목 요소가 존재한다.
awslogs 드라이버가 cloudwatch에 로그를 복제하는 것은 blocking 방식으로 동작한다. 이 말인즉슨, 로그를 Cloudwatch에 완전히 쓰는 동안 애플리케이션이 멈출 수 있고, Cloudwatch 쓰기가 계속 실패한다면 애플리케이션 자체에도 문제가 생길 수 있다는 것이다.

위의 경우는 실제로 발생할 수 있고, 발생이 보고된 오류케이스다.
로그가 매우 빠르게 쌓이는 환경에서 모종의 네트워크 장애/지연으로 Cloudwatch 쓰기가 반복적으로 실패하자, 컨테이너가 로그 전송 시도를 멈추고 정지해버린 것이다. 이러면 로그만 못쓰는 것이 아니라 프로그램이 그냥 멈춘다. (정상화될때까지)

이런 장애를 방지하고자 한다면, 로그 구성을 non-blocking으로 바꾸는 것이 대안이 될 수 있다.
mode를 non-blocking으로, max-buffer-size를 적절히 넣어주면 된다. 아래에서는 25m(mb)로 설정했다.

이러면 awslogs는 Cloudwatch 전송이 실패하더라도 그걸 기다리지 않고 버퍼에 쌓은 다음에 대기한다.
하지만 이것도 문제는 있다. 버퍼가 가득 찬 상태에서 로그가 또 들어오면 그때부터는 로그가 손실되기 시작한다는 것이다.
그래서 버퍼 크기를 잘 잡는 것이 과제다.




FireLens 드라이버

FireLens는 오픈소스인 Fluentd 기반으로 구현된 로깅 드라이버로, 다양한 타겟에 로그를 던질 수 있는 기능을 제공한다. 그리고 awslogs보다 고급 설정이 가능하다.

위에서 언급한 awslogs 드라이버는 어쨌거나 Cloudwatch에 강하게 통합되어있는 드라이버다. 세팅이 편하긴 하지만 Cloudwatch 이외에는 쓸 수 없다는 것이 큰 단점이다.

Cloudwatch가 편하긴 하지만, 다른 로그 저장소에 로그를 저장하고 싶을 수도 있다.
그럴 때는 FireLens를 통해 로그 구성을 커스텀할 수 있다.

동작 방식을 그림으로 표현하면 대충 이렇다. 반드시 사이드카 컨테이너가 필요하다.

메인 컨테이너에서 로그를 쓰면, firelens driver가 그걸 가로채서 사이드카에 전송한다.
그럼 사이드카가 그걸 적당히 가공하거나 정제해서 실제 로그 저장소에 보내는 것이다.
기실 그렇게 복잡한 것은 없다. 사이드카 설정하는게 좀 귀찮을 뿐이다.

콘솔에서는 이런 식으로 뜨는데

Cloudwatch, S3, Opensearch 같은 AWS 내부 서비스에도 내보낼 수 있으며


규격만 적절히 맞추면 다양한 오픈소스 및 서드파티에 로그를 던질 수 있다. 위의 경우는 DataDog을 붙인 예다.

그리고 반드시 사이드카 컨테이너를 하나 띄워야 하는데, AWS에서 제공하는 공식 이미지가 있다.
다음과 같은 식으로 컨테이너를 추가하면 된다.

        {
            "name": "log_router",
            "image": "amazon/aws-for-fluent-bit:stable",
            "cpu": 0,
            "portMappings": [],
            "essential": true,
            "environment": [],
            "mountPoints": [],
            "volumesFrom": [],
            "user": "0",
            "systemControls": [],
            "firelensConfiguration": {
                "type": "fluentbit",
                "options": {
                    "enable-ecs-log-metadata": "true"
                }
            }
        }



기타: Splunk 드라이버

이건 아마 레거시로 취급되는 것일 것 같은데, splunk라는 모니터링 스택에 로그를 전송해주는 드라이버다.

쓸일은 거의 없을 것이다.



참조
https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html
https://docs.aws.amazon.com/ko_kr/batch/latest/userguide/using_awslogs.html
https://aws.amazon.com/ko/blogs/tech/preventing-log-loss-with-non-blocking-mode-in-the-awslogs-container-log-driver/
https://aws.amazon.com/ko/blogs/containers/choosing-container-logging-options-to-avoid-backpressure/