cloudtrail로 s3 객체 삭제 로그 남기기

dev_qorh·2022년 12월 6일
0

CatchCatch

목록 보기
18/18

문제 상황 분석

개요


퀴즈세트를 등록하고 나서, 추가 요청이 없는데도 불구하고 이미지 로딩이 안되는 문제가 발생했다. 확인결과 s3에서 원본 파일이 삭제되었다는 것을 확인할 수 있었다.
또한, 퀴즈 세트 썸네일을 변경하고 나면 5분 뒤에 변경된 이미지도 삭제되는 현상이 발생했다.

분석

현상은, 저번주에 이미지 삭제 로직을 구축하여 업로드한 이후 발생하였다.
이미지 삭제 로직은 aws-sdk를 사용하여 s3의 deleteObjects 함수를 사용하여 삭제할 파일 목록의 key를 요청하는 방식으로 구현되어 있었다.

특이하게 함수는 promise형태의 객체가 아니었다. 콜백으로 간단한 출력 함수를 걸었지만 실제 동작 소요가 오래 걸리는 것도 확인이 되어.. 크게 중요하지는 않았다. (그래서 현 상태에서는 삭제 요청에 대한 성공/실패 여부도 모르는 것이다.)

로그 확인

요청이 들어가 있는 상태에서 실제로 s3 객체가 삭제되기 까지 거의 분 단위의 시간이 소요되는 것으로 확인되었다. 이 현상 자체가 문제였고, 직관적으로 어떤 요청들이 처리되었는지 확인하고 싶어 s3에서의 로깅을 확인해보았다. 방법은 크게 두 가지가 있었다.

Server access logging

A버킷의 속성에서 다른 버킷 B를 지정한다. B버킷은 이후 관련 정책을 업데이트 받아 A버킷에 접근하는 요청의 정보를 로깅하게 된다. 하지만 이 또한 버킷의 정책 설정을 완벽하게 수행하지 못해 당장은 불가능 하였다.

cloudtrail

cloudtrail은 aws 리소스의 동작들을 모두 로깅할 수 있는 시스템이었다. 그래서 trail을 생성하지 않은 시점에서도 event 기록으로 람다 함수에 대한 logstream 생성이 주를 이루고 있었다. (이것은 불필요하기에 추후 삭제가 필요할 것으로 보인다. -> 추후 aws 리소스 사용량을 상세히 분석할 필요가 있다.)

생성할 때, trail의 추적정도를 설정해야 한다. 아래 이미지에서 확인할 수 있듯 기본적으로 trail은 management event는 리소스의 동작들을 캡쳐한다.
하지만 설정을 통해 리소스 내의 동작을 캡쳐할 수 있도록도 가능하다. 예컨대 lambda의 경우 위의 이미지처럼 createLogStream은 개별적인 lambda 리소스가 유저가 되는 Management event이고, ListIndexes 또한 Administrator가 유저가 되는 Management event임을 클릭하여 로그 내에서 살펴 볼 수 있다.
왼쪽은 createlogstream, 오른쪽은 listindexes.

공식문서에 따르면, cloudtrail에서 data event를 로깅하기 위해서는 data events를 직접 지정 및 설정해주어야 한다고 한다.
모든 s3에 대한 요청을 로깅하는 것으로 설정하여 trail을 새로 생성해주고 이미지를 삭제 및 업로드하며 경과를 지켜봤다.

정리

잠시동안 리소스들이 어떻게 움직이는 지 확인한 것을 정리하고자 한다.

  • cloudtrail의 event history는 management 레벨 로그만 보여준다. (잘 보니 써져있더라..)
  • log 들은 s3에 저장된다. 이 때, management 레벨까지 포함되어 있어 cloudtrail 자체의 s3 put 요청도 기록이 된다.
  • Lambda가 대상 s3에 대해 수행하는 api 콜은 정확하게 저장이 되어 있다.
  • Lambda의 Role과는 상관이 없었다. 정확하게는, 이미 s3에 대한 Lambda의 정책이 설정되어 있어 이 부분은 추가할 필요가 없었다.
  • cloudtrail은 자체적으로 정책을 갖는 듯 보였다.
  • cloudwatch를 통해 cloudtrail이 저장하는 포맷을 쉽게 metric화 할 수 있는 것으로 보인다.

이런 상황일 때 내가 수행할 수 있는 부분들은 다음과 같다.

  1. cloudtrail의 추적 정도를 eventname 레벨 (putObject, deleteObjects) 까지 지정하여 불필요한 정보가 로깅되지 않도록 설정완료
  2. deleteObject의 동작 명세를 확인하여 전송한 요청이 오류가 될 수 있는지 판단
  3. 불필요한 설정들을 모두 되돌리기

해결 해보기

로그 분석

관련 설정을 모두 해주고 나서 확인을 한 결과, deleteObjects의 parameter로 delete가 항상 공란인 것을 확인할 수 있었다.
하지만 실제로 삭제는 잘 되었고 조금의 딜레이 (약 1분 내외)가 있을 뿐이었다. cloudtrail로만으로는 판단하기 어려워 lambda의 log를 확인해보았다.

lambda에서는 정확하게 parameter들을 전달했다. 혹은 원래 delete log에서 파일 명은 명시가 안되는 것일까? 동작에 무리가 없는 현상을 두고 고민할 필요는 없다.
흥미로운 글을 발견했다. 공식 문서로 확인된 내용은 아니지만, deleteobjects가 cloudtrail에 key를 남기지 않는다는 글이었다. deleteobject를 사용하면 key를 확인할 수 있긴 한가본데, 비용이 너무 많이 들 것 같다는 생각이 들었다. (s3 api로의 요청이니까 결국)

수정한 내용

그리고 코드를 전체적으로 둘러봤다. 오류가 발생할 수 있는 지점이 몇 개 있었고, 해결하기로 하였다.

  • warmer call 분기 로직이 모호했다. 첫 호출이 warmer call인지 아닌지 확인하기 위해 비즈니스 로직을 실행 후, parameter 누락 등에 발생되는 에러에 의해 warmer call을 확정짓는 로직이었다. handler에서 공통 파싱 처리 모듈이 다 덮여있지 않아서 비즈니스 로직이 그냥 아무렇게 실행되는 경우가 발생했다. -> 에러가 정확하게 도출될 수 있도록 함수들을 모두 위치시켜주었다.
  • deleteObjects 함수를 실행하는 것을 callback으로만 지정해 사용하였다. -> 구글링으로 promise를 추가하는 예시를 적용해보았다. 즉각적인 삭제가 수행되는 것을 확인할 수 있었다.
  • 로그를 다시 확인해보니, 같은 파일 명에 대해 두번 요청이 들어가는 것을 확인했다. -> 코드 수정으로 에러를 해결한다.
  • 추가적으로 발견한 것
    나는 aws-sdk v2를 쓰고 있었다. 새로나온 v3와의 서로 다른 특징은 공식문서에 서술되어 있다. -> 추후 라이브러리를 교체하는 작업을 진행하여 module의 크기를 줄일 수 있을 것으로 기대된다.

결론

당장 해결할 수 없는 문제라고 판단한다. 하지만 cloudtrail + cloudwatch를 구축해두었기 때문에, 개발 기간 내에 팀원들이 사용하다가 생긴 동일 현상에 대해 제보를 받고 로그를 확인하여 문제를 수정할 수 있을 것으로 기대된다.

profile
기술로써 가치를 만들고 싶은 사람입니다.

0개의 댓글