스타트업에 다니고 있다보니 당장 필요하지는 않지만, 로그 수집 시스템을 구축해야 했습니다.(당장 필요하지 않은데 왜 하는거지!!!) 라는 의문이 들 수 있는데…(들어야 정상입니다.), 사실 꼭 초반에 구성하지 않더라도 큰 문제는 없습니다. 아직 저희는 서비스가 출시 전이기 때문에, 출시 전에 로그를 수집하더라도 큰 문제는 없지만, 다음과 같은 생각이 있었습니다.(만구 제 생각입니다.)
- 서비스 출시 전으로 갈 수록 서비스 관련 이슈가 많으므로 로그 시스템을 구축할 수 있는 시간이 줄어들 것이다.
- 그러면, 실제로 필요한 로그들을 정리하기 어려워서 놓치는 부분들이 생기고, 필요한 로그들이 있는지 체크하기 어려울 것이다.
그래서 일단은 로그 수집 시스템을 구축하려고 했는데, 그렇다고 기존에 다른 회사에서 사용하던 로그 수집 시스템을 그대로 사용하기에는 관리 비용이 비싸다고 생각했습니다.
beanstalk 에서도 자체적으로 로그를 보여주게 되는데, Beanstalk 에서 로그가 보고싶은 environment를 선택하고 Logs 를 선택합니다.

그리고 Request Logs 를 선택하고 Last 100 Lines 나 Full Logs를 선택해서 원하는 로그를 볼 수 있습니다.

개발중에는 대략 이렇게 로그를 볼 수도 있습니다. 그런데 서비스를 진행하면서 이렇게 로그를 볼 수 는 없습니다. 왜냐하면 로그는 서비스의 현재와 과거의 모습, 그리고 우리가 어떻게 성장을 해야 하는지를 보여주는 핵심 지표이기 때문입니다.
예를 들어 로그를 모아서 다음과 같은 정보들을 나중에 보여주고 싶습니다.
- 현재 서비스의 사용자 수(DAU, WAU, MAU)
- 현재 가장 많이 발생하는 Exception(장애시 이런게 엄청 중요합니다.)
- 어떤 이벤트로 변하는 사용자 수
그래서 로그를 수집하는 일반적인 파이프라인은 다음과 같은 형태를 많이 사용합니다. 그리고 저기서 ELK 가 붙어서 비주얼라이제이션까지 처리를 많이 하게 되죠.

처음에는 위의 형태를 사용할까 생각을 했는데 몇 가지 고민이 생겼습니다.
- 우리는 AWS Beanstalk 를 쓰고 있다.
- beanstalk 라고 filebeat를 설치하는 것이 어렵지는 않습니다.
- Kafka를 써야 하나?
- Kafka는 굉장히 좋은 툴이고, AWS는 Managed Kafka 까지 제공해주고 있습니다. 그럼에도 불구하고, 우리가 Kafka의 운영에 신경을 써야 한다는 것이 고민 포인트였습니다.
- ELK를 다 써야 하나?
- elastic도 굉장히 좋은 솔루션인데, 스타트업에서는 살짝 고민되는 비용이기도 합니다.
- 사실, 반대로는 스타트업이라서 로그가 별로 없어서 써도 상관없는 비용이기도 한…(무슨 소리냐!!!)
그래서 이것 저것을 조사하다 보니, 소규모에는 CloudWatch Log 정도로도 충분할꺼라는 지인들의 조언을 많이 받게 되어서 (DataDog이나 어려가지 SaaS 솔루션의 추천도 많고, 예전에 써본 경험도 있긴 한데… 흑흑흑 쓸 수 없었던…) 해당 솔루션 들을 리서치 하게 되었다.
그래서 현재는 (아직 구축이 끝나지 않았다!!!) 다음과 같다. 현재 필요한 로그들을 cloudwatch 에 까지 보내는 것은 테스트가 되었고, 뒷 부분에 lambda 로 s3에 저장을 할지, firehose 로 저장을 할지를 고민중이다.(이것도 사실 테스트는 되었는데……)

즉 지금 보는 솔루션은 beanstalk 에 awslogs 와 cwlogs 를 통해서 로그를 cloudwatch 로 저장하고 이를 다시 s3에 저장한 다음 분석 작업을 진행하는 것이다.(분석 작업은 현재 없다!!! 엉???)
그런데 beanstalk 가 조금 애매한 부분이 terraform 으로 environment 는 설정이 가능한데, 거기의 세세한 설정은 또 다른 방식으로 해야하는 것들이 있습니다. 예를 들어, 기본적으로 바로 beanstalk를 사용한다면, 기본 로그들 말고 우리가 남겨야 하는 custom log 들이 있습니다. 이런 것들을 어떻게 수집해야 할까요?
사실 beanstalk에서는 아주 간단하게 적용할 수 있는 방법을 제공합니다. 첫번째는 환경 설정에서 로그를 남기는 설정을 켜두는 것입니다.
Beanstalk 설정에서 Configuration 을 선택하고 Software 에서 Edit 를 누르면 설정을 쉽게 할 수 있습니다. 아래에서 Enabled 만 설정하시면 자동으로 cloudwatch에 로그가 남게 됩니다.

위의 설정을 켜고 CloudWatch 메뉴로 가서 Log groups 를 선택하게 되면 바로 기본적으로 로그가 남는 것을 알 수 있습니다. 예를 들어 자바 App을 구성하시면 5개의 로그가 기본적으로 생깁니다.(nginx 는 nginx를 proxy로 쓴다면…)
- /aws/elasticbeanstalk/{environment}/var/log/eb-engine.log
- /aws/elasticbeanstalk/{environment}/var/log/eb-hooks.log
- /aws/elasticbeanstalk/{environment}/var/log/nginx/access.log
- /aws/elasticbeanstalk/{environment}/var/log/nginx/error.log
- /aws/elasticbeanstalk/{environment}/var/log/web.stdout.log

그런데 사실, 모든 출력을 web.stdout.log 로 출력을 해도 되지만, 관리를 위해서 필요한 로그를 추가를 하게 됩니다.
그렇다면 이 것은 어떻게 추가를 해야할까요? 일단 수동으로 하는 건 최대한 피해야 하고(수동으로 할 수 있는 방법도 없는 T.T)
beanstalk 는 이걸 위해 .ebextensions 에 확장을 위한 방법을 제공합니다. 사실 이미 aws 쪽에서는 이에 대한 Sample 을 제공하고 있습니다.(https://github.com/awsdocs/elastic-beanstalk-samples/blob/master/configuration-files/aws-provided/instance-configuration/logs-streamtocloudwatch-linux.config)
일단 초기에는 다음과 같이 설정했습니다.
packages:
yum:
awslogs: []
commands:
01-awslog:
command: systemctl enable awslogsd.service
02-awslog:
command: systemctl restart awslogsd
files:
"/etc/awslogs/awslogs.conf" :
mode: "000600"
owner: root
group: root
content: |
[general]
state_file = /var/lib/awslogs/agent-state
"/etc/awslogs/config/myservice.conf":
mode: "000600"
owner: root
group: root
content: |
[/var/log/myservice/myservice.log]
log_group_name = `{"Fn::Join":["/", ["/aws/elasticbeanstalk", "myservice", "var/log/myservice/myservice.log"]]}`
log_stream_name = {instance_id}
file = /var/log/myservice/myservice.log
"/opt/elasticbeanstalk/tasks/bundlelogs.d/myservice.conf" :
mode: "000755"
owner: root
group: root
content: |
/var/log/myservice/*.log
"/opt/elasticbeanstalk/tasks/taillogs.d/myservice.conf" :
mode: "000755"
owner: root
group: root
content: |
/var/log/myservice/*.log
위의 설정을 살펴보면 packages 는 Amazon linux 2 부터는 awslogs 가 설치가 안되어 있기 때문에 기본적으로 설치를 해주는 부분입니다.
packages:
yum:
awslogs: []
두 번째 commands 는 awslogs 를 설정하고 재시작 하는 부분입니다.
commands:
01-awslog:
command: systemctl enable awslogsd.service
02-awslog:
command: systemctl restart awslogsd
세 번째 files 섹션은 해당 파일들을 생성합니다. 여기에 적는 파일들은 설정파일들입니다. awslogs.conf 는 state_file을 저장하는 해당 파일은 filebeat 같은 종류의 파일들이 현재 데이터를 어디까지 보냈는지를 기록해두는 것처럼 awslogs가 보통 파일의 어디까지를 전송했는지 position 값을 가지고 있습니다.
"/etc/awslogs/awslogs.conf" :
mode: "000600"
owner: root
group: root
content: |
[general]
state_file = /var/lib/awslogs/agent-state
이제 custom 로그를 cloudwatch 로 보내는 설정입니다. /etc/awslogs/config 에 들어가는 설정이 cloudwatch로 보내는 설정들이라고 보시면 됩니다. 혹시나 추가하고 싶은 파일들이 더 있으면 더 만들어주거나 하면 됩니다.
"/etc/awslogs/config/myservice.conf":
mode: "000600"
owner: root
group: root
content: |
[/var/log/myservice/myservice.log]
log_group_name = `{"Fn::Join":["/", ["/aws/elasticbeanstalk", "myservice", "var/log/myservice/myservice.log"]]}`
log_stream_name = {instance_id}
file = /var/log/myservice/myservice.log
그리고 아래의 두 설정은 아까 beanstalk environment 설정에서 본 request logs 에서 Last 100 라인과 모두 보기를 위해서 추가해주는 설정입니다. 저기에 파일 내용을 보고 해당 파일들의 내용을 보여줍니다.
"/opt/elasticbeanstalk/tasks/bundlelogs.d/myservice.conf" :
mode: "000755"
owner: root
group: root
content: |
/var/log/myservice/*.log
"/opt/elasticbeanstalk/tasks/taillogs.d/myservice.conf" :
mode: "000755"
owner: root
group: root
content: |
/var/log/myservice/*.log
이렇게 실행을 시키고 보면, 실행이 안되었습니다. 이유를 살펴보니, Log를 생성해야 하는 폴더가 없고 권한이 없어서 App이 실행이 안되었습니다. 그래서 commands 섹션을 다음과 같이 바꿔줍니다. 필요한 폴더를 생성해주는 것입니다.
commands:
01-directory:
command: "sudo mkdir -p /var/log/myservice/"
02-directory:
command: "sudo chmod 777 /var/log/myservice/"
03-awslog:
command: systemctl enable awslogsd.service
04-awslog:
command: systemctl restart awslogsd
이렇게 하고 보니, 이제 beanstalk 환경에서는 마지막 100라인등의 로그에는 잘 추가가 되었는데 cloudwatch에는 보이지 않았습니다. 이상하다 싶어서 설정을 바꿔보고 이름을 바꿔봐도 T.T 로그가 보이지 않았습니다.
이때 문제를 확인하는 방법중에 하나가 직접 해당 인스턴스에 들어가서 설정 파일들을 살펴보는 것입니다. ssh로 접근을 해서 설정을 보아도 크게 이상한게 없었는데…(제 눈이 침침해서…)
위에서 AWS 공식 예제와 다른 부분을 살펴보면 다음 부분이 있습니다. 제가 실수했던 부분은 해당 파일이 있는지만 확인하고 넘어간 것이었는데…
"/etc/awslogs/awscli.conf" :
mode: "000600"
owner: root
group: root
content: |
[plugins]
cwlogs = cwlogs
[default]
region = `{"Ref":"AWS::Region"}`
ssh 로 직접 들어가서 해당 파일을 확인해보니… 파일 내용이 다음과 같았습니다.
[plugins]
cwlogs = cwlogs
[default]
region = us-east-1
네네, 제 Region은 ap-northeast-2 인데… 저 설정이 us-east-1 입니다. 제가 아까 awslogs 에 있는 설정은 cloudwatch 로그를 위한 것이라고 했습니다. cwlogs 가 cloudwatch logs인거죠.
그런데 이상한 부분은 일단 기존의 다른 로그들은 ap-northeast-2로 가고 있는데, custom 로그만 머나먼 버지니아(us-east-1)로 가고 있던 것입니다. 그래서 해당 region 의 cloudwatch를 보니… 로그가 거기에 쌓이고 있는…
이렇게 cloudwatch에 로그가 쌓이는 걸 확인했지만 사실 여기서 cloudwatch에 데이터를 보내는 것이 완료된 것이 아닙니다. 어떤 부분이 남아있을까요? 그것은 2부에서…