HAProxyでフロントエンドにした際の、一時的な503エラー

テストフォーラムを作成し、2つの web_only コンテナ、mail-receiver コンテナ、Postgres、Redis を Docker ネットワーク上に配置しました。2つの Web コンテナの nginx は HAProxy によってフロントエンドされていました。これらはうまく機能しましたが、2つの Web コンテナのうちの1つを再構築すると、常に 503 が返される短いダウンタイムが発生することがわかりました。

幸いなことに、完璧ではありませんが、軽減策を見つけました。


app1 を再構築する前に、次を実行します。

echo \"disable server be_discourse/app1\" | socat stdio /run/haproxy/admin.sock

そして app1 の再構築プロセスが完了した後、次を実行します。

echo \"enable server be_discourse/app1\" | socat stdio /run/haproxy/admin.sock


逆に、app2 を再構築するには、次を実行します。

echo \"disable server be_discourse/app2\" | socat stdio /run/haproxy/admin.sock

そして app2 の再構築プロセスが完了した後、次を実行します。

echo \"enable server be_discourse/app1\" | socat stdio /run/haproxy/admin.sock


これは /etc/haproxy/haproxy.cfgbe_discourse に関して一致していることに基づいています。まだ設定ファイルをコードブロックに貼り付けませんが、多くの人が必要とする場合は貼り付けるかもしれません。

これにより、HAProxy にダウンしているコンテナからの 503 が発生することを知る前にトラフィックを迂回するように指示することで、503 が軽減されます。


代わりにエラーページを作成することもできますが、うまくいかなかったため、さらに調査が必要だと感じています。ただし、これはダウンタイムの問題を実際には解決しません。

503エラーが発生した場合、次のサーバーに再ディスパッチしないのはなぜですか?

「いいね!」 1

いいですね!それは良いでしょう。また、Sidekiq について何か提案はありますか? discourse_docker/samples at main · discourse/discourse_docker · GitHub で Sidekiq がまったく見当たらないため、以下の変更をいずれかの YML に行うことになりました。


app1.yml

## Remember, this is YAML syntax - you can only have one block with a name
run:
  - exec: echo "Beginning of custom commands"
+  - exec: rm -f /etc/service/sidekiq/down
  ## If you want to configure password login for root, uncomment and change:

app2.yml

## Remember, this is YAML syntax - you can only have one block with a name
run:
  - exec: echo "Beginning of custom commands"
+  - exec: bash -lc 'mkdir -p /etc/service/sidekiq && touch /etc/service/sidekiq/down'
  ## If you want to configure password login for root, uncomment and change:

複数のWebコンテナを実行している場合、もう一つ考慮すべき点があります。それはSidekiqの実行場所です。

503エラーはWebリクエストにのみ影響しますが、Sidekiqがダウンすると、サイトはバックグラウンドジョブ(メール、ダイジェスト、バッジ、Webhook)の処理を静かに停止します。これを処理する簡単な方法は、Sidekiq専用のコンテナを用意し、Webノードでは無効にしておくことです。

Discourseは内部でrunitを使用しています。/etc/service/*内の各サービスは、そのディレクトリ内にdownという名前のファイルがない限り起動します。それだけで制御は十分です。

専用のSidekiqワーカーの例を以下に示します。

worker.yml — Sidekiqのみ
templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/sshd.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"

expose: []   # HTTPポートなし

env:
  DISCOURSE_DB_HOST: data
  DISCOURSE_REDIS_HOST: data
  DISCOURSE_HOSTNAME: "forum.example.com"
  # 既存のシークレット/SMTP設定と一致させる

hooks:
  after_code:
    - exec:
        cd: $home
        cmd:
          # Webサービスを無効にする
          - mkdir -p /etc/service/puma && touch /etc/service/puma/down
          - mkdir -p /etc/service/nginx && touch /etc/service/nginx/down
          # Sidekiqを有効にする
          - rm -f /etc/service/sidekiq/down

run:
  - exec: echo "Starting Sidekiq worker container"

Webコンテナ(app1/app2)では、その逆を行います。PumaとNginxを有効にしたまま、以下を追加します。

hooks:
  after_code:
    - exec:
        cd: $home
        cmd:
          - mkdir -p /etc/service/sidekiq && touch /etc/service/sidekiq/down

この設定により、HAProxyはWebコンテナのみをロードバランシングし、Sidekiqはワーカーで実行され続けます。これにより、Webノードの再構築やローテーション時にバックグラウンドジョブが中断されることはありません。

これを Installation > Hosting に移動しました。これはオープンな会話のように思われるためです。Support でこのようなものを作成しないようにしましょう。

「いいね!」 1