입사하고 빌링을 봤을 때 가장 많은 비용을 차지하는 게 S3 저장 비용이었다. 라이프 싸이클의 옵션을 알고 있었고, 비용 절감 가능성에 대해서 알고 있었다. 하지만 문제는 비즈니스의 이해였다. 객체들의 액세스 패턴을 알지 못했기에 섣불리 적용할 수 없었다. 

 

비즈니스를 파악하고, 적용하며 얻었던 지식이다.

 

S3 라이프 사이클 

 

aws s3의 라이프 사이클 옵션은 aws s3 lifecycle docs에서 확인할 수 있고, 중요점만 살펴보자.

 

기본적으로 s3를 만들고 객체를 생성하면 Standard 객체 클래스로 생성된다. 범용성 있게 사용할 수 있는 옵션이지만 저장 가격은 높다고 볼 수 있다. (ap-northeast-2 seoul 기준 GB당 0.025USD) 그렇기에 객체 액세스 패턴을 살펴보고 가격이 저렴한 클래스를 선택하는 게 비용 절감할 수 있는 포인트다. 

 

IA, IA One Zone, Glacier 종류는 요청을 하고 데이터를 받는 시간이 길거나, 검색 시 용량마다 비용이 발생하기 때문에 자주 요청하지 않는 객체들이 적합하다. 

 

반면에 Standard, Intelligent-tiering, Express One Zone 같은 경우 검색 하는데 비용이 발생하지는 않는다. 따라서 객체가 자주 액세스가 된다면 3개의 클래스 유형이 적합하고, 자주 액세스 되지 않는 다면 위의 클래스가 적합하다. 

 

우리 비즈니스의 경우 엑세스 패턴이 정해져 있지 않았다. 년 단위로 계약을 하고, 연장할 가능성도 있기 때문에 일정 기간 후 옮겨지는 라이프라이클로 저장 가격이 저렴한 클래스로 섣불리 옮길 수 없었다. 

 

그래서 AWS 내부의 모니터링으로 비용 절감을 해주는 Intelligent-tiering을 우선적으로 살펴봤다. 해당 클래스는 내부적으로 객체를 모니터링해서 Intelligent-tiering 내부의 클래스 우형에서 알아서 전환한다. 모니터링 비용과 객체 전환 비용이 추가로 발생하게 되는데, 처음에 우려했던 부분은 너무 작은 객체들은 오히려 모니터링 비용의 문제와 자주 유형이 변경됐을 때의 비용이었다. 하지만 128KB 이하의 경우 라이프사이클을 적용해도 이동하지 않는다는 것을 알 수 있었다. 또한 객체 전환 비용은 Standard -> 다른 클래스 유형으로 변경될 때 발생하는 비용이고, Intelligent-tiering 내에서의 변경은 비용이 발생하지 않는다는 것을 알았다.

 

Intelligent-tiering은 디폴트 내부 계층으로 3가지가 존재한다.

Frequent Access, Infrequent Access, Archive Instant 해당 계층들은 엑세스 하는데, 큰 변화는 없고, 저장 비용이 저렴해진다. 

 

FA -> 0.025USD

IA  -> 0.0138USD

AI  -> 0.005USD

 

생각보다 많은 비용 차이가 존재하는데, Intelligent-tiering 내부에서의 계층 변화는 앞서 말한 듯이 모니터링으로 진행된다. FA -> IA는 30일 동안 액세스하지 않은 객체 IA -> AI는 90일동안 엑세스하지 않은 객체가 이동된다. 한 번이라도 다시 엑세스 되면 FA로 변경되며, 일수를 세는 기준은 Intelligent-tiering으로 변경된 시점부터이다. 

 

즉 이전에 1년 동안 액세스가 없던 객체라도 Intelligent-tiering으로 변경한 후 AI로 바로 가는 것이 아닌 변경된 시점부터 90일이 지나야 AI로 가게되는 것이다.

 

그렇게 엑세스 패턴을 명확하게 할 수 없을 때 Intelligent-tiering가 비용 절감에 도움이 된다는 것을 확인하고 전부 변경했다. 여기서 주의할 점은 라이프 사이클은 기존에 생성된 것들도 바꿔주기 때문에 아래에서 처럼 path에서 클래스를 수정하지 않아도 된다. path에서 클래스를 편집하면 객체가 복제되면서 유형이 변경되므로 버저닝을 켰다면 비용이 발생할 수 있다. 

 

콘솔로는 버킷 -> 관리 -> 수명 주기 규칙 생성이다. 

 

 

규칙 범위 선택: 버킷의 모든 객체에 적용할 것인지 혹은 아래의 필터를 이용할 것인지 결정하는 것으로 보통 필터를 사용하여 세부적으로 라이프 사이클을 운영한다.

 

접두사: S3의 path로 public으로 적는다면 public/**로 이하의 모든 객체들이 포함된다. 이때 중요한 것은 여러 개의 라이프 사이클이 있을 때 path가 겹치면 오류가 발생하므로 겹치지 않게 설계하는 것이 좋다.

 

객체 태그: 특정 태그를 기반으로 객체를 필터링한다. ex) expiration: 30 days 같이 30일 이후에 만료시킨다 같이 의미 있게 태그를 활용할 수 있다.

 

객체 크기: 객체를 전환하는 최대와 최소 크기를 지정할 수 있다. 최소는 0B이상, 최대는 1B이상으로 작성할 수 있다. 주의해야 할 점은 Glacier는 저장하며 별도의 오브젝트 해더를 Standard 유형으로 저장하는데, 최소를 너무 작게 하면 이러한 과정 때문에 과금이 더 발생할 수 있다.

 

 

스토리지 클래스 간에 객체의 현재 버전 전환

- 현재 최신 상태의 객체들의 변경 옵션

 

스토리지 클래스 간에 객체의 이전 버전 전환

- 버저닝을 켰을 때 최신 버전이 아닌 객체들의 변경 옵션

 

객체의 현재 버전 만료

- 현재 최신 상태의 객체를 만료로 변경하는 옵션

 

객체의 이전 버전 영구 삭제

- 버저닝을 켰을 때 최신 버전이 아닌 객체를 만료로 변경하는 옵션

 

만료된 객체 삭제 마커 또는 완료되지 않은 멀티파트 업로드 삭제
- 만료된 객체 삭제 마커는 이전 버전에서도 실질적인 객체가 남아있지 않고, 삭제 마커만 있는 경우로 용량만 차지하게 되는 경우를 삭제

- 완료되지 않은 멀티파트 업로드 삭제는 어떠한 이유로 큰 객체를 업로드하는 과정에서 완료하지 않은 경우로 대부분 용량만 차지하게 돼 삭제하는 게 좋다.

 

이렇게 모든 설정을 봤을 때 내가 선택한 옵션들은 다음과 같다.

 

접두사, 태그로 필터링을 진행했다. 이전부터 설계된 path를 봤을 때 접두사만으로 모든 것을 적절하게 이동시키는 것은 불가능했다. 따라서 태그를 추가하여 객체를 추가적으로 필터링했다.

 

현재 버전 전환, 이전 버전 전환, 만료된 객체 삭제 마커 또는 완료되지 않은 멀티파트 업로드 삭제다. 현재 버전과 이전 버전 모두 0일 Intelligent-tiering으로 설정하여 즉시 변경하도록 했고, 멀티파트 업로드 삭제는 파일이 큰 경우 오래 걸리는 케이스도 있어서 넉넉히 설정했다. 

 

여기서 라이프 사이클에 해당한다고 해서, 즉시 클래스 유형이 변경되지는 않는다. 대규모로 진행되는 이유로 생각되며 보통 하루가 지나면 적용되므로 신경 쓰지 않아도 된다. 

 

Terraform 코드 

 

대부분의 내용은 생략하고 버켓과 라이프 사이클만 존재하는 코드다. 

 

Github 코드