Webコンテナとデータコンテナを迅速に分離してマイグレートする

:warning: 警告: Linux システム管理者として働くことに慣れておらず、Docker コンテナの経験がない場合、マルチコンテナ構成への移行は困難を伴います。この場合、スタッフやボランティアは、launcher スクリプトによって完全に管理されるスタンドアロンの単一コンテナ構成に戻すよう適切に依頼します。

マルチコンテナ構成に移行してシステムが破損した場合、破損した両方の部品を保持する機会に直面する可能性があります。以下の指示を読み、コンテナ内部の仕組みが明確になるのではなく「魔法」のように感じられるなら、駆け足で ではなく*走って* 最寄りのデフォルトのスタンドアロン構成に戻ってください。それがあなたのためになります。

単一コンテナ構成からマルチコンテナ構成への移行に推奨される方法 は、本質的に以下の通りです:

  • Discourse のバックアップを取得する
  • すべてを破棄する
  • マルチコンテナ構成で最初からやり直す
  • バックアップを復元する

私のように、復元に数時間かかる大規模なサイトをお持ちの場合、より高速な方法があるのではないかと疑問に思うかもしれません。もう疑問に思う必要はありません!私は、スタンドアロン構成から Web、データ、Redis の 3 コンテナ構成への移行を、そのサイトの ./launcher rebuild app を通常実行する時間よりも短い時間で完了させました。(合計のダウンタイムは 12 分であり、アプリの再構築には 30 分以上かかることもありました。)私の経験に基づくと、将来は Redis を Postgres と一緒に単一の data コンテナに保つことをお勧めします。

この作業を行う場合、他のコンテナ(データ、そして私のように愚かにも Redis を分離している場合は Redis も同様)をいつ再構築する必要があるかを知る責任はあなたにあります。 ./launcher rebuild app によるすべての無料アップグレードは受けられなくなります。このプロセスを管理できるリソースがない場合は、スタンドアロン構成を使用するか、ホスト型 Discourse を購入してください。

テスト

このプロセスを使用して複数のコンテナへの移行を行う場合は、これを読み終わった後、複数のコンテナから単一のコンテナへ迅速に移行する方法も理解している必要があります。これを読み終わった後でもそれが明らかでない場合は、この投稿は十分に高度な技術(つまり、魔法と区別がつかない)であり、このプロセスが途中で破損したことに気づかない可能性もあります。その結果、後になってから破損した Discourse に気づくことになるかもしれません。そのような場合、破損した両方の部品を保持することになります。「壊したものは買う」という言葉があるように、自己責任です!

バックアップ

まずバックアップを取得し、サムネイルのバックアップもオンにしてください。そうすれば、復元時にすべてを再構築する必要がなくなります。ここでミスをした場合、最も簡単で安全かつ高速な回復方法は通常の手法(推奨される方法)に切り替えることになってしまう状況に簡単に陥ります。何か問題が発生した場合は、推奨される方法 にすぐに切り替える準備をしてください。

バックアップをダウンロードしてください。以下のコマンドは Discourse データ内のファイルを移動させるものであり、ミスをしてバックアップを削除してしまう可能性があります。したがって、ダウンロードしてください。また、バックアップにアップロードが含まれていない場合は、それらもバックアップしてください。それらもファイルを移動させる場所にあります。

真剣に、バックアップを取ってください。

私がこれを行った際、まずバックアップを作成し、次にリモートシステムのバックアップを作成してから、さらに進みました。

新しいマルチコンテナ構成の設定

少なくとも containers/web_only.ymlcontainers/data.yml が必要です。Redis を分離したい場合は、containers/redis.yml も必要です。まずは samples/data.yml(オプションで samples/redis.yml)を containers/ ディレクトリにコピーすることから始めます。

Redis を個別にデプロイする場合は、containers/data.yml ファイルの先頭にある Redis テンプレートを削除してください(ただし、十分な理由がない限り行わないでください。単に余分な作業になるだけです)。

web_only.yml の作成方法には 2 つあります。

  1. samples/web_only.ymlcontainers/ にコピーし、両方を containers/app.yml と比較する。新しい containers/data.yml 内の params: における Postgres 設定を保持する
  • containers/app.yml からの Postgres に関する params:containers/data.yml にコピーする
  • SOME_SECRET を置き換える一意のパスワードを作成する
  1. あるいは、containers/app.ymlcontainers/web_only.yml にコピーし、それを samples/web_only.yml と比較する
  • Postgres と Redis のテンプレートに関する参照をすべて削除する
  • Postgres 設定のみが含まれていた params: セクション全体を削除する
  • links: セクションを samples/web_only.yml からそのまま、または(Redis を別のコンテナでデプロイする場合)以下のように変更して追加する
  • samples/web_only.yml からデータベースセクションを追加し、SOME_SECRET を置き換える一意のパスワードを作成する
  • ボリューム定義を standalone から web_only に変更する

Redis を Postgres と組み合わせたデータコンテナという合理的なデフォルトではなく、独自のコンテナに分離する場合に使用する links: セクションは以下の通りです:

# コンテナをリンクするために 'links' キーを使用します(Docker --link フラグを使用)。links:
  - link:
      name: data
      alias: data
  - link:
      name: redis
      alias: redis

Redis と Postgres コンテナを単一のデータコンテナとして結合している場合は、redis リンクは不要です。これは何を行うべきかを示すための例です。

以下は、samples/data.yml 内の env にある現在の Postgres 設定のコピーです。SOME_SECRET を変更する必要があります:

  ## TODO: データベースへの接続を設定
  DISCOURSE_DB_SOCKET: ''
  #DISCOURSE_DB_USERNAME: discourse
  DISCOURSE_DB_PASSWORD: SOME_SECRET
  DISCOURSE_DB_HOST: data
  ## 単一のデータ+Redis コンテナを使用する場合、以下は「data」になります
  DISCOURSE_REDIS_HOST: redis

通常のデプロイ(マルチサイトではない)の場合、他の行を変更する必要はありません。DISCOURSE_DB_SOCKET は Postgres の Unix ドメインソケット用であり、ポート番号ではありません。

以下は、app.yml ではなく samples/web_only.yml からコピーした場合に web_only.yml の末尾で行う必要があるボリューム定義の変更の例です:

@@ -75,10 +80,10 @@
 ## Docker コンテナはステートレスです。すべてのデータは /shared に保存されます
 volumes:
   - volume:
-      host: /var/discourse/shared/standalone
+      host: /var/discourse/shared/web_only
       guest: /shared
   - volume:
-      host: /var/discourse/shared/standalone/log/var-log
+      host: /var/discourse/shared/web_only/log/var-log
       guest: /var/log

次に、containers/web_only.yml で使用した同じ秘密のパスワードを containers/data.ymlSOME_SECRET の代わりに設定してください。

これで移行の準備が整いました。

今が、高速移行を試みる前に最終的なバックアップを取得してダウンロードするタイミングです。 何か問題が発生した場合は、すぐに 推奨される方法 に移行してください。これほど強調しても強調しすぎることはありません。

データ(Postgres)と Redis コンテナを分離する場合:

cd /var/discourse

./launcher stop app
cd  shared
mkdir data
mkdir redis
mv standalone/postgres_* data/
mv standalone/redis_data/ redis/
mv standalone web_only
mkdir -p data/log/var-log
mkdir -p redis/log/var-log

cd ..

./launcher destroy app

./launcher bootstrap data
./launcher bootstrap redis
./launcher start redis
./launcher start data

./launcher bootstrap web_only
./launcher start web_only

Postgres+Redis を組み合わせたデータコンテナの場合:

cd /var/discourse

./launcher stop app
cd  shared
mkdir data
mv standalone/postgres_* data/
mv standalone/redis_data/ data/
mv standalone web_only
mkdir -p data/log/var-log

cd ..

./launcher destroy app

./launcher bootstrap data
./launcher start data

./launcher bootstrap web_only
./launcher start web_only

また、以前に外部 nginx を設定している場合、proxy_pass パスを新しい web_only ソケットの場所に合わせて変更する必要があります。例えば、http://unix:/var/discourse/shared/standalone/nginx.http.sock: から http://unix:/var/discourse/shared/web_only/nginx.http.sock: に変更します。

私の場合、2 コアの VM(RAM 4GB)で、ダウンロードなしの 600MB バックアップを持つサイトにおいて、このプロセスによるダウンタイムは 12 分でした。環境によって結果は異なる場合があります。

これまでのところ、これらは launcher を更新するものではありません。最新版ではない可能性があります(例えば、Postgres 12 のアップデートが利用可能になった後、適用する前にこれを実行しました。このプロセスの結果、Postgres 10 のままになりました。その後、次の作業としてデータアプリを再構築し、launcher を更新して Postgres 12 の更新プロセス を正常に完了させました)。

今後の更新時の対応

この移行後、Redis またはデータの更新が必要な場合は、まず Web アプリを停止する必要があります。手順は以下のようになります:

./launcher stop web_only
./launcher rebuild data # および/または redis
./launcher rebuild web_only

data(または postgresredis)コンテナを再構築する場合、新しい Web コンテナを作成して新しいデータコンテナと再接続する必要があります。web_only を再構築するか、再構築する必要がないと思われる場合は ./launcher destroy web_only; ./launcher start web_only で対応できます(「データコンテナが見つかりません」などのエラーが表示された場合は、これを行う必要があります)。

ただし、Postgres も Redis も更新を必要としない場合、それらのコンテナを再構築せずに済む方がはるかに高速であり、ほとんどのアプリの再構築は ./launcher rebuild web_only だけで済みます。

あるいは、さらにダウンタイムを短縮する方法もあります(報告により 15 秒から 2 分の間):

./launcher bootstrap web_only
./launcher destroy web_only && ./launcher start web_only

繰り返しになりますが、マルチコンテナ構成に移行した場合、それがいつ適切かを追跡するのはあなたの仕事です。 管理コンソールで更新に関する通知を受け取りますが、それは web_only コンテナにのみ適用されます。Postgres または Redis をいつ更新する必要があるかを示すものはありません。この方法を採用する場合は、すべてのバージョンアップグレードを行う前に お知らせカテゴリ を読み、アップグレードする、または経由するすべての新バージョンの リリースノート を読んでください。つまり、あるバージョンの更新をスキップする場合でも、スキップしたバージョンのリリースノートを読むことは省略しないでください。(リリースノートでウォッチを設定するか、フィードリーダーを https://meta.discourse.org/tag/release-notes.rss に購読して最新情報を入手することを検討してください。)

web_only コンテナの再構築にはデータベースの実行が必要であるため、2 つまたは 3 つのコンテナを並列に再構築して処理を高速化することはできません。毎回すべてを再構築する必要がある場合は、標準の推奨されるスタンドアロン構成を使用してください。複数のコンテナをやり取りするよりも高速です。

バックアップの確認

アップロードをデータベースとは別にバックアップしている場合、災害時に復元できるよう、アップロード用のファイルベースのリモートバックアップ体制を整えていることを願っています。

リモートバックアップの実装を見直し、/var/discourse/shared/standalone ではなく /var/discourse/shared/web_only 内のアップロードをバックアップするように確認してください。そうすれば、新しいマルチコンテナ構成においてもバックアップを最新の状態に保つことができます。

「いいね!」 22

こんにちは、mcdanlj さん!こちらには初めて来ました。Discourse には 2 つのデプロイ方法があるようです。1 つは app.yml のスタンドアロン モード、もう 1 つはデータベースと Redis キャッシュを web-only.ymldata.ymlredis.yml のマルチコンテナ モードに分割するという、あなたの方法です。しかし同時に、app.yml のパラメーター DISCOURSE_DB_HOSTDISCOURSE_REDIS_HOST を変更して Redis とデータベースに接続することもできることがわかりました。では、なぜ app.ymlweb-only.ymldata.ymlredis.yml に分割する必要があるのでしょうか?

既存のデータベースとRedis(例えば、RDSとElastiCache、または他の方法で自分で作成したもの)がある場合、独自のものを保持する必要はありません。

各Discourseには独自のRedisが必要であることに注意してください。

「いいね!」 1

ジェイさん、親切な説明をありがとうございます!でも、まだ混乱しています。Falco’s Tutorialを見ると、web-only.yml、data.yml、redis.ymlを設定する必要なく、AWSのRDSとElasticacheを簡単に使用できることに気づきました。Falco’s Tutorialではapp.ymlのパラメータを編集するだけです。しかし、mcdanlj’s Tutorialは異なります。それは彼のフォーラムが大きすぎるからでしょうか?そのため、Falcoが提供する簡単な方法を使用できないのでしょうか?

RDS と独自のデータベースサーバーを実行することは、まったく別のことです。お金と専門知識がたくさんあるなら、RDS は素晴らしいでしょう。何も知らないなら、単一コンテナのインストールは素晴らしいでしょう。お金があまりなく、ダウンタイムを減らしたいなら、2 つのコンテナのアプローチが良いでしょう。

ほとんどの場合、最も理にかなっているものを使用してください。

「いいね!」 1

ありがとうございます!シングルコンテナが私にとって最善の方法かもしれません :rofl: RDSと独自のデータベースサーバーの違いを、あなたが教えてくれるまで知りませんでした :joy:

「いいね!」 1

@ShawnLi 2つのコンテナシステムが複雑に思えるなら、1つのコンテナのデフォルトがあなたに適した選択である良い兆候です。2つのコンテナのデプロイは、更新時に月に1回程度、ダウンタイムを数分間節約できますが、より多くの理解が必要であり、新しいリリースごとに発表の詳細を手動でフォローする必要があります。

だからこそ、私は次のように始めました。

:grinning:

「いいね!」 2

mcdanljさん、ありがとうございます!チュートリアルは素晴らしく、多くの知識を学ぶことができました。シンプルなワンコンテナのデフォルト設定を選択することにしました。はい、実行しました:rofl:

「いいね!」 2