큐돈은 사용자들이 업로드하는 그림이나 영상, 음성 데이터 같은 미디어들을 오브젝트 스토리지에 저장합니다. 어제까지는 DigitalOcean의 SFO2(샌프란시스코) 지역을 사용하고 있었습니다. (지금은 싱가포르 지역도 있지만 큐돈이 정착할 쯤에는 없었습니다)

하지만 sfo2 지역은 유독히 다운타임이 잦았고, 다운타임 알림은 아침에 일어나면 다운되었다는 메시지를 보내고, 저녁을 먹고 돌아오면 또 메시지가 오는 식이었습니다. 기분탓인줄 알았지만 정말로 하루에 1~2번씩 꼬박꼬박 다운이 되고 있었고 이건 가정용 홈서버보다도 못한 수준이라 판단했기에 갈아타기로 마음을 먹는데에 결정타를 날렸습니다 (쓰기 시간이 오래 걸리는 문제도 있고 CDN 관련해서 DNS 설정도 납득이 안 가는 문제가 더 있습니다) SFO2 지역이 한 달 동안 46회 총 3.8시간의 다운타임을 나타내는 표

원래는 클라우드플레어의 R2 서비스가 출시되면 그 때 옮기려고 했지만 다운타임이 없는 오브젝트 스토리지의 이동을 한 번 미리 경험해 볼 겸 다른 지역으로 이전하게 되었습니다. 오래 전에 로컬 스토리지에서 와사비로, 와사비에서 디지털오션으로 옮긴 적이 있지만 그 때는 다운타임이 느낄 수 없도록 짧았거나 정합성이 깨지는 문제가 있었습니다. (물론 누락은 없었고, 지워지지 않은 데이터는 나중에 자동으로 찾아서 지우는 방법을 사용할 수 있었습니다)

그래서 Flexify라는 서비스를 이용해서 다운타임이 없는 이전작업을 시도해보았습니다. Flexify는 flexify.io에서는 유료플랜을 제공하고 있지만, 셀프호스트가 가능하기 때문에 간단하게 도커를 이용해서 열어줍니다.

docker run -d --name flexify --restart unless-stopped -v flexify:/var/opt/flexify flexifyio/ce

Flexify의 구조는 간단합니다. 두 오브젝트 스토리지를 묶어서 가상의 오브젝트 스토리지를 만드는 것인데 응용프로그램은 이 새로운 가상의 스토리지를 바라보게 합니다. 그러면 Flexify는 새로운 파일은 새로운 B 저장소에 업로드 하게 되고 요청이 들어올 때는 B나 A 중에서 응답이 오는 쪽을 포워딩 해주게 됩니다. 삭제 요청이 들어오면 A, B 모두에서 삭제합니다. 이를 통해 Flexify를 통한 다운타임이 없는 이전작업의 과정은 다음과 같습니다.

  • Flexify를 열고 기존 스토리지와 새로 이동할 오브젝트 스토리지 연결
  • CDN 워커가 flexify를 바라보도록 설정
  • 마스토돈이 Flexify를 바라보도록 새로운 설정을 무중단 배포
  • Flexify에서 마이그레이션 실행
  • 마이그레이션이 완료되면 새로운 스토리지를 바라보도록 마스토돈을 재배포
  • CDN 워커 재설정
  • Flexify 종료

과정 자체는 아주 단순합니다. 하지만 시행착오가 있었기에 문제가 있었던 부분 또한 정리해 주는 것이 블로그의 미덕입니다.

Public read access

Flexify는 서브도메인을 지원하지 않습니다. qdon.sfo2.digitaloceanspaces.com/test.txt처럼 접속했다면 flexify.domain.tld/qdon/test.txt 형식으로 버켓을 경로로 지정해 접근해야 합니다. CDN 워커의 설정만 바꾸고 외부에서는 항상 동일한 bucket.qdon.space/test.txt로 요청할 수 있도록 둡니다.

또한 Flexify는 모든 오브젝트를 프라이빗 권한으로 저장합니다. flexify를 종료하고 원본 오브젝트 스토리지를 바라보도록 만든다면 모든 파일이 403 에러가 납니다. 마이그레이션 종료 후 다음 명령을 사용해 모든 파일을 퍼블릭으로 바꿀 수 있습니다. (물론 flexify를 그냥 유지하고 사용해도 됩니다)

s3cmd setacl s3://bucket-name --acl-public --recursive

PostProcessmediaWorker - COPY to local 에러

어째 외부에서 들어오는 이미지들은 잘 뜨는데 로컬에서 업로드하는 이미지는 실패가 뜹니다. 로그를 열어보니 위 제목과 같은 에러가 있었고, 실제로 이미지는 원본과 썸네일이 모두 저장은 되어 있었습니다. (하지만 메타데이터는 지우지 못한 것 같습니다. 게시물에 첨부되지 않은 미디어는 모두 하루가 지나면 자동으로 삭제됩니다) 디지털오션이 이전작업 중에 다운타임도 있었고 디지털션의 문제일지도 모르기에 여러가지로 찾아보니 Flexify의 문제가 맞았고 관련 이슈가 있었습니다. https://github.com/mastodon/mastodon/issues/16822

kt-paperclip의 문제였고 마스토돈에서의 해결 방법은 S3_FORCE_SINGLE_REQUEST=true 환경변수를 넣어주는 것입니다.

RequestEntityTooLarge 413

간혹 겪는 은근히 자주 보이는 문제입니다. nginx의 최대 업로드 제한을 초과해서 생기는 문제입니다. nginx 설정에 client_max_body_size 0; 등으로 업로드 제한을 풀어주면 됩니다.

기타 참고사항

tootctl media remove --days 7 명령을 사용하여 리모트에서 온 미디어들은 캐시를 삭제한 후 이전작업을 하면 좀 더 적은 용량을 이동할 수 있기 때문에 경제적으로 작업할 수 있습니다.