AWS SDK gem 버전 상승 및 새로운 AWS 데이터 무결성 보호 기능으로 인해 재빌드 불가

AWS SDK 유지보수 팀이 호환성을 깨뜨렸습니다. 이제 S3 클론 제공업체가 최신 상태로 업데이트하고 더 나은 호환성을 구현하여 우회 조치를 제거할 수 있도록 해야 합니다.

확인 차원에서 말씀드리면, 이는 assets 내의 JS/map/CSS 파일에만 영향을 미치고 업로드에는 영향을 미치지 않는 것이 맞나요?
즉, 고아 파일(오르페인 파일) 정리에도 영향을 주게 되나요?
참고로, 이 문제가 관리자 패널을 통한 Discourse 업데이트에도 영향을 미칠 수 있다고 생각하는데,
사실상 관리자 패널을 통한 업데이트가 저에게는 실패해서 재빌드(rebuild)를 수행했습니다.

네, assets에만 해당됩니다.

이 rake 태스크는 아닙니다.

하지만 AWS SDK 변경 사항이 호환되지 않는 클론에서 해당 기능도 깨뜨렸을 수 있습니다.

그건 아마도 잘못된 것 같습니다. 따라서 clean up uploads도 끄는 것이 필요할 것 같습니다. 하지만 그러면 실행 중 오류가 발생할 수 있습니다. 재빌드(rebuild)를 못 하는 문제는 아닙니다.

가능해 보입니다. 다른 제공업체들이 따라올 때까지 이 문제를 해결하기 위해 “skip_s3_delete” 설정이 필요할까요? 그리고 이미 깨진 것으로 알려진 제공업체의 경우 자동으로 설정하도록 하는 것이 어떨까요?

만료된 자산(assets)이 제거되는 유일한 방법이 그 rake 태스크인가요?

혹시 왜 S3에 저장하지 않고 Discourse 코어 서버에 에셋을 유지하는 옵션을 추가하지 않는지 궁금합니다.

업로드나 고아 파일 정리 과정에 영향을 주지 않는 한, 이는 실현 가능한 해결책처럼 보입니다.

네. 이는 큰 문제가 아닙니다. 가끔씩 업데이트하는 일반적인 사이트에서는 큰 차이를 느끼지 못할 것입니다.

이 부분에 관심이 있는 경우 사용자들은 자체적으로 라이프사이클 규칙을 설정할 수 있습니다.

clean up uploads = false를 설정하는 것이 이미 그런 것 아닌가요?

아니요, 절대 아닙니다. Discourse는 공식적으로 S3를 지원합니다. 전체 업로드용 S3 호환 객체 저장소 제공업체 구성 위키를 시작하고 클론 호환성을 높이기 위해 몇 가지 토글을 추가하는 데 제 노력을 기울였지만, 오늘 그쪽에 더 많은 시간을 투자할 계획은 전혀 없습니다.

커뮤니티가 호환성을 높이고 기본적으로 꺼져 있는 몇 가지 PR을 보내고 싶다면 #pr-welcome이지만, 모든 클론에 대한 공식 코어 지원을 곧 보기를 기대하지 마세요.

참고로, Digital Ocean은 백업 삭제나 누락된 자산의 만료 처리에 문제가 없는 것으로 보입니다.

서비스가 불안정한 프로바이더의 경우, 불필요한 자산이 실제 문제를 일으키기까지는 상당한 시간이 걸릴 것입니다. 그러나 방대한 데이터베이스와 모든 업로드 파일을 포함한 수많은 백업을 유지해야 한다면, 저장 공간에 대한 비용을 지불하고 있는 경우 상당한 문제가 될 수 있습니다.

안녕하세요 - 저는 Backblaze의 수석 기술 전도사(Chef Technical Evangelist)인 Pat Patterson입니다. 저는 자체 호스팅된 proof-of-concept Discourse 포럼을 운영하고 있으며, 포럼의 백업 및 업로드에 Backblaze B2를 설정하던 중 오늘 우연히 이 동일한 문제에 부딪히게 되어 이 스레드에 참여하게 되었습니다.

AWS_REQUEST_CHECKSUM_CALCULATIONAWS_RESPONSE_CHECKSUM_CALCULATIONWHEN_REQUIRED으로 설정하는 것은 파일 업로드 및 다운로드의 기본적 경우에 유용한 우회책이지만, 다음을 포함한 여러 시나리오에는 적용되지 않는다는 점을 알아두는 것이 좋습니다:

  • 파일 삭제 - Discourse는 여러 파일을 단일 API 호출로 삭제하기 위해 DeleteObjects S3 연산을 사용하고 있으며, 이는 올바른 방식입니다.
  • 오브젝트 락(object lock)이 활성화된 버킷으로 파일 업로드.

문제는 이러한 연산에 대해 체크섬(Content-MD5 헤더 또는 새로운 체크섬 헤더 중 하나)이 단순히 지원되는 것을 넘어 필수라는 점입니다. 이로 인해 현재 AWS SDK들은 새로운 체크섬 헤더를 제공하게 됩니다. 제가 아는 한, 이를 오버라이드하여 SDK가 예전처럼 Content-MD5를 제공하도록 하는 방법은 없습니다.

저희 엔지니어들은 이 문제를 해결하기 위해 노력하고 있으며, 그 동안 최선의 완화 조치는 aws-sdk-s3 gem의 1.177.0 이하 버전을 사용하는 것입니다.

저는 Gemfile을 편집하여 다음을

gem "aws-sdk-s3", require: false
gem "aws-sdk-sns", require: false

다음으로 교체함으로써 PoC 배포 환경에서 AWS SDK gem 버전을 하향하는 것을 시도해 보았습니다.

gem "aws-sdk-core", "~> 3.215.1", require: false
gem "aws-sdk-kms", "~> 1.96.0", require: false
gem "aws-sdk-s3", "~> 1.177.0", require: false
gem "aws-sdk-sns", "~> 1.92.0", require: false

하지만 제 bundle 사용 실력이 부족하여, 다음과 같은 오류로 배포 환경을 망가뜨리는 데만 성공했습니다:

/var/www/discourse/config/initializers/100-sidekiq.rb:69:in `<main>': undefined method `logger=' for module Sidekiq (NoMethodError)

  Sidekiq.logger = Logger.new(nil)
         ^^^^^^^^^
	from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/engine.rb:689:in `load'
	from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/engine.rb:689:in `block in load_config_initializer'
...

아마도 중요한 단계를 놓친 것 같습니다.

Digital Ocean의 친구들에게 불이익을 주려는 의도는 아니지만, 그들은 서비스 업데이트를 통해 API 호출을 거부하는 대신 새로운 체크섬 헤더를 단순히 무시하는 방식으로 이 문제를 해결했습니다.

그들의 사고 보고서에는 다음과 같이 적혀 있습니다:

Spaces는 현재 업로드 요청의 일부로 AWS CLI 및 AWS SDK에서 전송하는 데이터 무결성 체크섬을 검증하지 않습니다.

우리는 API 클라이언트가 제공한 체크섬과 일치하지 않을 수 있는 데이터를 단순히 수락하고 저장하는 것은 잘못된 일이라고 판단했습니다.

게시해 주셔서 감사합니다!

네, 그리고 AWS SDK 유지보수자들은 이 문제에 대해 우리를 무시하고 있습니다.

B2 팀도 이 문제를 인지했다는 소식을 전해 듣게 되어 기쁩니다.

일시적인 해결 방법은 다음과 같습니다:
app.yml에서 S3와 관련된 모든 설정을 주석 처리하고 Discourse를 성공적으로 다시 빌드했습니다. 이는 이전에 업로드된 파일에 대한 사이트에 대한 액세스에 영향을 주지 않으며, 이 기간 동안 업로드된 첨부 파일은 로컬에 저장되며 어떤 문제도 발생하지 않습니다.

참고로, 왜 Discourse 코어 서버에 자산을 유지하는 옵션(S3에 저장하지 않고)을 추가하지 않는지 여전히 궁금합니다.

???

Discourse는 기본적으로 그렇게 작동합니다. 에셋을 오브젝트 저장소 서비스로 전송하려면 명시적으로 선택(opt-in)해야 합니다.

내 생각은, Discourse 코어 자산(JS, CSS 등)은 로컬 서버에 유지하는 옵션이 있으면 좋겠다는 겁니다. 동시에 사용자 업로드 파일만 S3에 저장하면 됩니다.

"use_s3"를 활성화하지 않으면 그렇게 할 수 있습니다. 하지만 파일 크기가 작아서 그냥 올려놓고 공간 낭비에 대해 걱정하지 않는 편이 낫습니다.

정확하게 이해하고 있는지 확인해 주세요.
app.yml에서 DISCOURSE_USE_S3: false로 설정하라는 말씀이신가요?

제 디스커스(Discourse) 서버가 아시아에 있고 B2는 미국에만 서버가 있기 때문에 이렇게 설정하고 싶습니다.

또한, 이번 AWS SDK 문제는 에셋 관리와 관련이 있는 것이 맞나요?
그렇다면 에셋을 로컬 서버에 저장하면 문제가 해결될 수 있을 것 같습니다(상황을 올바르게 이해하고 있다면 말이죠).

이 문제는 S3에서 에셋을 제거하는 것과 관련이 있습니다. 현재 상태에서 사용하지 않는 에셋을 제거하려는 줄만 삭제하면 정상적으로 작동합니다. 그리고 곧 문제가 해결될 것으로 보입니다. 이것이 가장 쉬운 해결책입니다. 제가 추천하는 방법입니다. 제가 드릴 수 있는 최고의 무료 답변입니다.

감사합니다, 정말 도움이 많이 됩니다!

이유는 S3 API 정의에서 DeleteObjects 연산httpChecksum.requestChecksumRequiredtrue로 설정되어 있기 때문입니다. 이는 예를 들어 PutObject와 대비되며, PutObject는 이를 false로 설정합니다. 따라서 체크섬이 실제로 필요하기 때문에 SDK는 WHEN_REQUIRED 정책을 따르는 것입니다.

모든 AWS SDK는 이제 엣지 케이스를 처리하기 위한 최소한의 추가 코드와 함께 API 정의에서 생성됩니다. 코드는 DeleteObjects에 체크섬이 필요하다는 것을 확인하고, 이를 수행하는 방식은 이제 Content-MD5 대신 새로운 체크섬 중 하나를 사용하는 것입니다.

불행히도 AWS는 '이전처럼 Content-MD5를 사용하세요’라는 구성 옵션을 제공하지 않았습니다. 이들은 이러한 유형의 변경 사항을 할 때 제3자 오브젝트 스토리지 생태계를 고려하는 경향이 없는데, 이는 그들에게 그렇게 할 필요가 없기 때문입니다. 이러한 문제가 수정되는 유일한 시점은 우연히 그들의 자체 서비스 중 하나가 어떤 코너 케이스에서 문제를 일으켰을 때뿐입니다.

아시아에 계신 분들에게는 큰 도움이 되지 않을 수 있지만, 참고로 유럽(네덜란드 암스테르담)에도 데이터 센터가 있으며, 올해 초부터 캐나다(토론토)에도 데이터 센터를 운영하고 있습니다.

확약은 드릴 수 없지만, 아시아 지역 서버를 확실히 검토하고 있습니다.

또한, CDN을 사용하는 경우 원본 서버의 위치가 크게 중요하지 않습니다.

맞아요!

Backblaze는 x-amz-checksum-crc32지원하지 않으며, Discourse의 최신 AWS SDK 버전에서는 이 기능이 기본적으로 활성화되었을 수 있습니다.

그래서 앱에 들어갔습니다:

./launcher enter app

그리고 현재 설치된 AWS SDK 버전을 제거했습니다:

gem uninstall aws-sdk-s3 aws-sdk-core aws-sdk-kms

그다음 Backblaze 담당자가 작동한다고 알려준 버전을 설치했습니다:

gem install aws-sdk-core -v “~> 3.215.1”
gem install aws-sdk-kms -v “~> 1.96.0”
gem install aws-sdk-s3 -v “~> 1.177.0”

그 후 앱을 다시 빌드하니 정상적으로 작동했습니다!