ECS 환경에서 야무지게 로깅하기 (feat. Utern, AWS Session Manager)

Joshua_Kim·2023년 7월 21일
11

🛠️ Devops 삽질기

목록 보기
1/2
post-thumbnail

🌱 0. 서론

🔧 회사 서비스 운영 환경에 ECS 를 도입하다.

올해 초, 컨테이너 오케스트레이션 환경으로 ECS 를 도입했다.

마음은 k8s를 사용하고 싶었지만 아래의 이유로 ECS 를 도입하게 되었다.

  1. 나 자신이 k8s 에 대한 이해도가 부족하다.
  2. 우리 서비스가 k8s 가 필요한 만큼 방대하지 않다.
  3. 회사 인프라 환경이 AWS 의존도가 높다.
  4. k8s 의 러닝 커브가 높으므로 팀원들에게 부담이 된다.
  5. 서버리스 환경인 Fargate 를 통해 손쉽게 컨테이너를 관리할 수 있다.

혼자 인프라를 구축해야 하는 상황이었기 때문에 😢
여러가지 삽질 끝에 운영환경을 ECS 로 전환했다. (해당 삽질 내용은 후에 써볼....수 있을까?)

서버리스로 전환하여 얻게된 이득이 상당했다.

AWS 콘솔을 통해 매우 쉽게 배포된 컨테이너들의 상태를 확인 할 수 있었고,
CPU나 메모리 사용량도 대시보드를 통해 손쉽게 모니터링 할 수 있었다.
물론 이후에 APM 툴로 Pinpoint 를 붙여서 모니터링을 했다.
(ECS 환경에서 Pinpoint 구축하는 것도 삽질을 했었다. 이 내용도 가능하다면 추후에 기록해 볼 예정)


🚨 하. 지. 만

ECS 환경으로 배포된 컨테이너 로깅이 매우 힘들었다. 🤬

CloudWatch 를 통해 AWS 콘솔에서 로그를 확인 할 수 있었으나 매우 매우 매우 불편하다.

CloudWatch'Log Group' 으로 수집된 로그 정보를 AWS 콘솔에 노출 하게 되는데,
Log Group 으로 쌓이는 로깅 정보들이 일정시간 딜레이가 있어서 실시간 로깅은 불가능했다.

심지어 한 서비스 내부에 배포된 Task 가 여러 개였기 때문에 불편한 CloudWatch AWS 콘솔 환경에서 운영하고 있는 서비스를 로깅하기란 매우 힘들었다.

ELK 를 도입하고 싶었으나 이것 또한 내가 아직 이해도가 없었고, 현재 서비스에서는 로깅만이 목표였기 때문에 과하다고 생각이 들었다.


🧠 방법을 찾아야 했다.

이번 포스팅을 통해 ECS 환경에서 로깅을 하기위해 삽질과 공부를 병행한 결과를 공유한다.

현재 우리팀에서는 운영환경 로깅을 아래와 같은 방법으로 진행하고 있다.

  1. 현재 배포된 Task 들의 실시간 로깅 -> AWS CLI 와 Session Manager 통한 로깅
  2. 비교적 가까운 과거 (Cloud Watch 로그가 삭제되지 않고 남아있는 기간) 의 로깅 -> 오픈소스 Utern 활용
  3. 이미 Cloud Watch 로그가 삭제 된 비교적 오래 전 시기의 로깅 -> S3 에 저장된 log 확인

3번 같은 경우를 위해 AWS Lambda 를 통해 CloudWatch 로그정보를 S3 에 저장하는 아키텍쳐를 개발 했다.
해당 내용은 이 포스팅 (클릭) 에서 자세하게 다루고 있다.

서론이 길었다.

그럼, 자세히 알아보자!


🍭 1. ECS 실시간 로깅

1> TaskDefinition 수정

ECS 클러스터가 명세된 TaskDefinition 에 "taskRoleArn" 을 추가해야한다.

{
  "family": "{ECS Family}-task-definition",
  "containerDefinitions": [
    {
    ...(중간 생략)
   ],
  "taskRoleArn": "ecsTaskRole", << ✅ 이 부분
  "executionRoleArn": "ecsTaskExecutionRole",
  "cpu": "4096",
  "memory": "8192",
  "networkMode": "awsvpc",
  "requiresCompatibilities": [
    "FARGATE"
  ]
}

수정 한 후에 수정된 TaskDefinition 으로 명세된 ECS 배포를 진행한다.


2> AWSCLI 및 AWS Session Manager 설치

터미널을 통해 AWSCLI 를 설치한다.

이미 설치되어 있다면 넘어가도 된다.😋

AWSCLI 설치

$ brew install awscli

설치를 완료한 후에 버전을 확인해 보자

awscli 버전 확인

$ aws --version

ACCESS KEY 와 SECRET KEY 로 AWS 자격증명을 해야한다.

AWS 자격 증명

$ aws configure
  • 해당 명령어를 실행하면 AWS ACCESS KEY, SECRET KEY, Region 정보, DATA Format 을 순서대로 입력하게 된다.
  • AWS ACCESS KEY, SECRET KEY 는 AWS 본인 계정으로 진행한다.
  • Region 정보는 ap-northeast-2
  • DATA Format 은 json 으로 입력한다.
  • direnv 를 사용하고 있다면 direnv 로 폴더를 분리하여 자격증명 하는 것을 권장한다.

AWSCLI 설치가 완료되었으니 AWS Session Manager 를 설치해보자.

AWS Session Manager 다운로드

$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac_arm64/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"

압축해제

$ unzip sessionmanager-bundle.zip

AWS Session Manager 설치

sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/bin/session-manager-plugin

installation successful! 이 뜨면 설치 완료! 🎉


3> ECS 태스크 execute command 활성화 하기

AWSCLISession Manager 를 통해 ECS 에 배포된 컨테이너에 접근하기 위해서는 executeCommand 상태를 enable 로 변경해줘야 한다.

우선 변경하지 않은 상태에서 Task 상태를 조회해보겠다.

ECS Task executeCommand 상태 확인

$ aws ecs describe-tasks --cluster {ECS 클러스터 이름} --tasks {확인하고자 하는 ECS 서비스 내부의 TASK 값} | grep enableExecuteCommand

위에 사진에서 보이듯 해당 Task 는 활성 상태가 false 임을 확인할 수 있다.

이제 해당 클러스터와 서비스의 executeCommand 상태를 true로 변경해주자.

ECS Task executeCommand 활성화

$ aws ecs update-service --cluster {ECS 클러스터 이름} --service {ECS 클러스터 서비스 이름} --enable-execute-command
  • 위의 명령어를 실행하면 아무 반응이 없다. 지극히 정상이니 당황하지 말자 ! 😋

  • 하지만 다시 상태를 확인해도 false가 뜬다. 당연하다. 상태 변경 적용을 위해 ECS 클러스터를 다시 재배포 해줘야 한다. 🔑

배포 후 다시 ECS Task executeCommand 상태 확인

$ aws ecs describe-tasks --cluster {ECS 클러스터 이름} --tasks {확인하고자 하는 ECS 서비스 내부의 TASK 값} | grep enableExecuteCommand

  • 배포가 다시 되었으므로 Task 의 값이 변했다.
  • enable-execute-command 를 진행한 것은 Task 상위 단계인 Service 에 적용한 것이므로 재배포 되어도 앞으로는 Task 들의 상태는 true 로 유지된다.

4> 드.디.어. ECS 에 배포된 컨테이너에 Session Manager 를 통해 접근 !

이제 모든 준비가 끝났다.

서버리스인 ECS 에 마치 EC2 마냥 접근 할 수 있게 되었다. 😋

접근해보자!

Session Manager 를 통해 컨테이너 접근

$ aws ecs execute-command --cluster {ECS 클러스터 이름} --task {접근하고자하는 컨테이너가 있는 Task 값} --container {접근하고자 하는 컨테이너 이름} --command "bin/sh" --interactive

  • 마치 EC2 에 접근한 것과 같이 ECS 에 배포된 컨테이너에 접근 할 수 있다.

  • {접근하고자 하는 컨테이너 이름} 에는 TaskDefinition 에 명세한 컨테이너 이름을 적어주면 된다.

  • 물론 AWS 콘솔에서도 ECS 화면에서 배포된 컨테이너 목록을 확인할 수 있다. 나는 web 컨테이너에 접근한 것이다.

  • 나는 WEB 컨테이너 내부에 /logs/web 이라는 폴더를 Dockerfile 에 volume 설정으로 명세를 해놓았고, WAS 설정으로 로그 저장을 사전에 해놓았기에, 컨테이너 내부에 저런 폴더 경로에 .log 파일들이 생성 되는 것이다.

  • 해당 .log 파일을 실시간으로 보고싶다면 tail -f {log 파일 명}.log 명령어를 통해 로깅이 가능하다.


🍭 2. 현재 배포된 Task 가 아닌, 예전 Task 를 로깅 해보자

1> Session Manager 를 통한 로깅의 한계

Session Manager 를 통한 로깅은 '실시간 로깅' 에 특화 되어있다.

  • ECS 배포가 새로 되면 Cluster 내부의 Task 는 새롭게 배포된다.
  • 즉, 컨테이너 내부의 로그 파일들은 삭제가 된다.
  • 그러므로 과거의 로그를 찾기에는 한계가 있다.

2> CloudWatch 를 통한 로깅

왓?

위에서 그렇게 CloudWatch 에 대해 불편하다고 했는데 이게 무슨 말인가... 🫢

일단, ECS 의 모든 로그 정보는 CloudWatch 에 전달 되어 보관된다.
(해당 설정은 TaskDefintion 의 logConfiguration 설정을 통해 가능하다.)

그렇기에, 컨테이너가 재배포된다고 해도 컨테이너 Task 로그가 사라지는 것이지, 과거 ECS 클러스터의 로그들이 사라지는 것은 아니다.
(하지만, CloudWatch 저장 기한을 설정 하는 것을 권한다. 이 내용은 CloudWatch 로그를 S3 로 이관한 내용을 다룬 포스팅 에서 더 자세히 다룬다..)

당.연.히
AWS Console 을 통한 CloudWatch 로깅을 하지 않을 것이다. 🤖


3> Utern 을 활용한 로깅

CloudWatch 로그를 조금 더 쉽게 볼 수 있게 해주는 서드파티 툴인 Utern 을 소개한다. 👏

reference : https://github.com/knqyf263/utern

Utern 설치

$ brew tap knqyf263/utern
$ brew install knqyf263/utern/utern
  • 두 명령어를 입력해줘야 한다.

설치가 되었으면 끝이다 ! 🍭

물론, 위에서도 언급했지만 direnv 를 통해 AWS 자격 증명을 하는 것을 권장한다.

위 사진과 같이 direnv 가 적용된 폴더에 들어가게 되면 어떤 내용이 exporting 되는지 확인이 가능하다.

Utern 을 통한 Log group 로깅

$ utern --since 2023-07-20T13:00:00+09:00 --timestaps --filter error {log group 이름}
  • 2023년 7월 20일 13시 (한국시간기준) 으로 'error' 를 뱉고있는 로그정보를 {log group} 에서 가져와달라는 명령

  • 위의 사진은 간단하게 50분 전 모든 로그를 불러오는 명령어의 결과다.

  • Utern 을 통해 로그 정보를 불러오면 배포된 모든 Task 정보의 로그를 가져온다.

  • 다른 Task 의 로그들은 색깔로 구분되어 노출된다.


🍭 3. 예~~엣날 로그들은?

CloudWatch 에 모든 로그를 적재하면 안된다.

겁나 비싸다.
비싸. 비싸. 💸

그렇기에 우리팀은 일주일만 ECS 로그 정보들을 CloudWatch Log Group 에 저장한다.

그렇다면 일주일이 지난 로그는 어떻게 해야할까?

S3 만세 🙃

일주일이 지난 CloudWatch 로그들은 S3에 적재한다.
AWS Lambda 를 통해 적재하도록 자동화 아키텍쳐를 구축했다.
이 내용은 여기를 참고해달라!


🎉 4. 결론 및 정리

현재 배포된 ECS 컨테이너의 실시간 로깅은 Session Manager

  • 컨테이너에 실시간으로 쌓이는 log 파일에 접근하여 로깅.
  • linux 명령어 (tail, grep 등) 을 통해 로깅 필터 가능
  • Task 별로 따로 로깅을 해야하므로 iterm 등의 터미널로 split 하여 로깅.
  • ECS 클러스터가 재배포되면 새로운 Task 값으로 접근해야함.

로그 그룹에 존재하는 과거의 정보 로깅은 Utern

  • CloudWatch Log Group 에 저장된 로그에 접근.
  • --since, --from, --filter 등 명령어로 로그 정보를 추릴수 있음.
  • Task 별 로깅 정보가 한번에 나옴. - 색깔별로 구분됨.

먼 과거의 정보 로깅은 S3 에 적재된 파일 확인


혹시나 ECS 로깅에 대해 더 좋은 방법이 있거나 피드백이 있으시면 언제든 댓글로 말씀 부탁드립니다 🥰

profile
인문학 하는 개발자 💻

4개의 댓글

comment-user-thumbnail
2023년 7월 22일

고민한 흔적이 느껴지는 포스팅 잘 보았습니다!

1개의 답글
comment-user-thumbnail
2023년 7월 22일

누구 남편인진 모르겠지만 부인이 참 부럽네요 ㅠ

1개의 답글