アップロード用のs3バケットを変更

こんにちは!

私たちは、2 つの異なる S3 互換サービス(どちらも DigitalOcean Spaces です)間で、すべてのアップロード画像を移行しています。現在は非常に悪い状態に陥ってしまいました。

移行のやり方から説明します。

  1. rclone を使用して、初期バケットを新しいバケットにクローン/同期しました。
  2. Discourse 管理画面の「Files」ページにあるすべての参照を、新しいエンドポイントに更新しました。
  3. リベイク(re-bake)を実行しました。

残念ながら、これは期待した結果をもたらさず、現在フォーラムからすべての画像が「消えて」います。画像自体は S3 バケットにはまだ残っています(幸運なことに古いバケットにも残っています)が、どの投稿もそれぞれの画像を見つけることができません。

バケットのサイズは約 60GB で、極端というわけではありませんが、かなり大量のデータです。

コンテナを再構築したり、トーンストーン(tombstone)からデータを復元しようとしたり、サポートフォーラムや rake タスクで見つけられることはすべて試しました。
データベースの置換(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 が変更されてしまったのではないかと考えられます。

これまでにこのような経験をした方はいますか?すべての画像が永遠に失われてしまったのでしょうか?(はい、はい、バックアップと古い画像は持っていますので、解決策があることはわかっています。)

「いいね!」 2

スペースバケット用に提供された CDN URI も(リベイクを伴って)使用してみたことを付け加えておく価値があるかもしれません。

「いいね!」 1

欠落したアップロードの出力:

rake posts:missing_uploads
デフォルトの欠落したアップロードを検索中:
欠落したアップロードの修正中:
🚫
17075 の投稿アップロードが欠落しています。

16906 のアップロードが欠落しています。
そのうち 1 つは旧方式のアップロードです。
139801 の投稿のうち 14646 に影響があります。

post_uploads には 3448 件のエントリがあります
optimized_images には 25681 件のエントリがあります
uploads には 5764 件のエントリがあります

「いいね!」 1

Moving from one S3 bucket to another をご覧ください。

明日、投稿しようとしているハウツーのドラフトを完成させたと思います。

「いいね!」 5

それはとても助かります、ありがとうございます!

「いいね!」 1

@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 へ移行する場合(AWS ではエンドポイント不要)、設定を更新した新しいコンテナをビルドした後(または、設定が含まれるデータベースをリストアした後)、そのサイト設定をクリアする必要があります。

バケットを指すポストを S3 CDN ではなく S3 CDN として再構築する

新しい 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

「いいね!」 8

ご返信ありがとうございます。

前回と同様の対応を試みましたが、再度実施したところ、posts.count が 0 を返してしまいます。すべての投稿には、cooked 側で transparent.png ファイルが含まれており、uncooked 側にはハッシュ値が含まれています。
bake 時に画像を正しく解決させる方法はありますでしょうか?

「いいね!」 1

なるほど、その通りですね。その一時的な変更は再構築を回避するためだけのものです。再構築が機能しない場合、別の問題が発生している可能性があります。もしかすると、アセットが Discourse が想定している場所にないのかもしれませんね。

「いいね!」 1

まあ、可能ではありますけど、その「移動」はバケット内の全ファイルをほぼ 1:1 で移しただけなんですけどね、へへ…

「いいね!」 2

古いバケットの URL を新しいものに置き換えれば、問題なく動作しますか?

Uploads の値は正しいですか?

「いいね!」 1

古いバケットに戻すと、それらが「古い」と見なされてすべてトーンストーンへ移動させるジョブが開始されるのが少し怖いです。ただ、データベースは正しい(新しい場所の)画像を指しているようです。問題は、古い投稿が正しい画像に解決されないことだけだと思います(推測ですが)。

「いいね!」 1

toombstone recovery の rake タスクを実行し、その後 fix_missing_uploads の rake タスクを実行したところ、ついに画像の「修復」が開始されました。
どうやら画像をダウンロードして再度アップロードしているようで、非常に時間がかかり、リソースも大量に消費しますが、少なくともユーザーは画像を取り戻せるはずです!

@pfaffman さん、お手伝いいただきありがとうございます :slight_smile:

「いいね!」 3

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.