업로드용 S3 버킷 변경

안녕하세요!

저희는 현재 두 개의 다른 S3 호환 서비스(양쪽 모두 DigitalOcean Spaces입니다) 사이에서 업로드된 이미지들을 모두 마이그레이팅하고 있습니다. 그리고 지금은 상당히 좋지 않은 상태에 빠져 있다는 걸 깨달았습니다.

마이그레이션이 어떻게 진행되었는지 먼저 설명드리겠습니다:

  1. rclone을 사용하여 초기 버킷을 새 버킷으로 클론/동기화했습니다.
  2. Discourse 관리 화면의 Files 페이지에 있는 모든 참조를 새 엔드포인트로 업데이트했습니다.
  3. 리베이크(re-bake)를 실행했습니다.

불행히도 이 작업은 저희가 원했던 결과를 내지 못했고, 이제 포럼에서 모든 이미지가 “사라진” 상태입니다. 이미지들은 여전히 S3 버킷에 남아 있습니다(다행히에도 기존 버킷에도 여전히 남아 있습니다) 하지만 어떤 게시글도 해당 이미지를 찾을 수 없습니다.

버킷의 크기는 약 60GB로, 극단적인 수준은 아니지만 상당히 큰 양의 데이터입니다.

컨테이너를 재구성해 보고, 톰스톤(tombstone)에서 데이터를 복구해 보았으며, 지원 포럼이나 레이크 태스크(rake tasks)에서 찾을 수 있는 거의 모든 방법을 시도해 보았습니다.
또한 Discourse remap을 통한 데이터베이스 교체도 시도해 보았습니다.

현재 베이킹된 콘텐츠에서 각 이미지는 기본적으로 다음과 같은 형태입니다:

<img src="https://xxxx.xxxxx.xx/images/transparent.png" alt="image" data-orig-src="upload://h8UudilPhVsGnNmvlJ5lQYEr8PT.jpeg" width="375" height="500">

이것은 링크의 b64-sha가 깨졌거나, 어떤 이유로든 이미지의 sha가 변경되었음을 시사합니다.

혹시 이런 작업을 해보신 분이 계신가요? 모든 이미지가 영구적으로 사라진 건가요? (네, 네, 저는 백업과 기존 이미지들을 가지고 있으므로 방법이 있다는 걸 알고 있습니다.)

스페이스 버킷에 대해 제공된 CDN URI를 (rebake와 함께) 사용해 보았다는 점도 언급할 가치가 있을 것 같습니다.

누락된 업로드 출력:

rake posts:missing_uploads
Looking for missing uploads on: default
Fixing missing uploads:
🚫
17075 post uploads are missing.

16906 uploads are missing.
1 of 16906 are old scheme uploads.
14646 of 139801 posts are affected.

post_uploads에는 3448개의 항목이 있습니다.
optimized_images에는 25681개의 항목이 있습니다.
uploads에는 5764개의 항목이 있습니다.

Moving from one S3 bucket to another 링크를 확인하실 수 있습니다.

내일 게시해보려고 하는 howto 초안을 작성해 둔 것 같습니다.

정말 큰 도움이 될 것 같아요, 정말 감사합니다!

Hey @Jite !

이 방법으로 작동하는지 확인해 보세요. 작동한다면, 적절한 howto(사용법)를 작성하겠습니다.

이전 버킷

이 방법은 데이터를 이전 버킷에서 로컬 머신으로 옮기고, 다시 로컬에서 새 버킷으로 옮기는 도구를 설치하고 구성할 수 있다고 가정합니다. 관련 정보는 aws cli sync(비-AWS 버킷에 대한 구성이 가능)와 gsutil rsync를 참고하세요. 데이터 양이 매우 많거나 같은 프로바이더의 버킷 간 이동을 수행하는 경우, 데이터를 버킷 간에 직접 이동하는 방법을 조사해 보는 것이 좋습니다.

보관 공간으로 적합한 디렉터리로 이동하세요. (예: mkdir temp-bucket; cd temp-bucket) 그리고 아래와 같은 작업을 수행하세요. 여기 예시에는 -n과 --dry-run 스위치를 포함하여 어떤 일이 일어날지 보여줍니다. 원하는 결과처럼 보이면 해당 스위치 없이 명령을 다시 실행하세요.

이전 버킷에서 로컬로 이전 데이터 이동

    gsutil  rsync -r -n  gs://=OLD= .

또는

    aws s3 sync s3://=OLD= .

로컬에서 새 버킷으로 데이터 이동

    gsutil rsync -r -n . gs://=NEW=

또는

    aws s3 sync . s3://=NEW=

새 버킷을 사용하도록 데이터베이스 업데이트

이 명령들은 Rails 콘솔에서 실행합니다. 콘솔에 접속하려면 다음을 수행하세요.

cd /var/discourse
./launcher enter app
rails c

새 버킷에 대해, 새 구성으로 이미지를 업로드하고 다음을 수행하세요:

Upload.last.url

다음과 같은 내용이 표시되어야 합니다.

=> "//discourse-bucket.s3.dualstack.us-east-2.amazonaws.com/`original/2X/7/12345fbea574afc4e02db80107e6682430aede2c.png"

이렇게 하면 새 버킷에 대해 discourse-bucket.s3.dualstack.us-east-2.amazonaws.com을 얻을 수 있습니다. 이전 버킷의 호스트 이름도 위에서 언급한 방법으로 유사하게 가져오세요.

업로드된 파일이 예상한 위치에 있는지 확인하려면 다음을 사용하세요:

Upload.order(Arel.sql('RANDOM()')).limit(10).pluck(:id, :url)

이제, 이전 버킷 대신 새 버킷을 사용하도록 데이터베이스를 업데이트합니다. DbHelper.remap은 모든 테이블에서 해당 문자열을 대체합니다.

DbHelper.remap("//=OLDHOST=/","//=NEWHOST=/")

AWS로 이동하는 경우 s3_endpoint을 비워야 할 수 있습니다.

참고: 데이터베이스의 SiteSettings에 s3_endpoint이 정의되어 있고 AWS로 전환하는 경우(엔드포인트가 필요 없음), 업데이트된 설정으로 새 컨테이너를 빌드한 후(또는 해당 설정이 포함된 데이터베이스를 복원한 후) 해당 사이트 설정을 비워야 합니다.

S3 CDN이 아닌 버킷을 참조하는 게시글 다시 생성(Rebake)

새 s3 버킷으로 직접 링크하는 게시글이 있는 경우(예: 이전에 s3_cdn_url이 정의되어 있지 않았던 경우), 필요한 게시글만 다시 생성하는 방법은 다음과 같습니다.

게시글을 가져옵니다:

  posts=Post.where("cooked like '%=NEWHOST=%'")

개수를 확인합니다:

  posts.count

해당 게시글을 다시 생성합니다:

  posts.each do |p| p.rebake! end

또는, 버킷을 cdn으로 직접 대체합니다:

posts.each do |p|
  p.cooked.gsub!(/=NEWHOST=/,"=CDN=")
  p.save!
end

답변해 주셔서 감사합니다.

이번에 한 작업은 기본적으로 지난번에 했던 것과 동일하지만, 다시 시도해 보았습니다. 문제는 posts.count가 0을 반환한다는 점입니다. 모든 게시글의 cooked 콘텐츠에는 transperant.png 파일이 포함되어 있고, uncooked 콘텐츠에는 해시 값이 들어 있습니다.
bake 과정에서 이미지가 올바르게 해석되도록 하는 방법이 있을까요?

음. 맞아요. 그 cooked 변경사항은 리메이크를 피하기 위해만 작동합니다. 리메이크가 작동하지 않는다면 다른 문제가 있는 거예요. 아마도 Discourse가 생각하는 위치와 자산이 다른 곳에 있는 건 아닐까요?

음, 가능은 하지만 그 '이동’은 사실 버킷 안의 모든 파일을 거의 1:1로 옮긴 거라, 헤헤…

그러면 기존 버킷 URL을 새 URL로 교체하면 정상적으로 작동하나요?

Uploads의 값들이 올바르게 설정되어 있나요?

이제 "구식"이 되었다는 이유로, 모든 것을 tombstone으로 이동하는 작업이 시작될까 봐 조금 걱정이 됩니다. 하지만 네, 데이터베이스는 올바른(새 위치) 이미지들을 가리키고 있으며, 기본적으로 기존 게시물들이 올바른 이미지로 해석되지 않는 것뿐인 것 같습니다(추측입니다만).

toombstone 복구 rake 태스크를 실행한 후 fix_missing_uploads rake 태스크를 실행하니 마침내 이미지가 "복구"되기 시작했습니다.
이미지를 다운로드한 후 다시 업로드하는 것 같고, _매우 많은 시간_과 _많은 리소스_가 소모되지만, 적어도 사용자들은 자신의 이미지를 되찾을 수 있을 것입니다!

도와주셔서 감사합니다 @pfaffman :slight_smile: