私たちのDiscourseホスティング構成

Michael Brown
Jan 27, 2015 • 4 min read

以前、Discourseサーバーのハードウェアについてお話ししました。今回はDiscourseネットワークについてお話しします。社会的な意味ではなく、物理的・ソフトウェア的な意味でのネットワークです。私たちはサーバー上でどのようにDiscourseをホストしているのでしょうか?

Discourseでは、超高速で手作りのコロケーション物理ハードウェア上でのホスティングを好んでいます。クラウドは特定の用途には最適ですが、Stack Exchangeと同様に、自社ハードウェアで運用するという決断を下しました。Rubyが私たちのテストでは仮想化がうまくいかなかったため、その決断は正しいものとなりました。

全体像

(そうです、これはDiaで作成しています。提供されているテンプレート画像が前世紀のものであるとはいえ、ネットワーク図作成においては今でも最速のツールです。)

タイ・インターセプター

アプリケーションへのインターネット全体からの攻撃に耐えられるよう、帝国の最高の技術がすべての前面に配置されています。

tieinterceptorサーバーはいくつかの重要な機能を担っています。

  • イングレス/エグレス: 職人手作りのiptablesファイアウォールルールがすべての受信トラフィックを制御し、特定のトラフィックがネットワークから外に出られないようにします。
  • メールゲートウェイ: インターセプターはメールが宛先に届くよう支援する役割を担っています。DKIMの署名、ハッシュキャッシュ(場合によっては)の署名、ヘッダーのクリーンアップを行います。
  • haproxy: haproxyを使用することで、インターセプターはロードバランサーとして機能し、リクエストをWebティアに振り分け、レスポンスを調整します。
  • keepalived: VRRPの実装のためにkeepalivedを使用しています。「haproxyが動作していない場合、このノードは優先されるべきではない」といったルールをkeealivedに設定し、そのルールに基づいてアクション(この場合、インターネット向けネットワークへの共有IPv4(およびIPv6)アドレスの追加または削除)を実行します。

タイ・ファイター(Web)

タイファイターは私たちのデス・スターの大艦隊、つまりDockerサーバー群を表しています。小さく、速く、同一の構成を持ち、多数存在します。

これらはステートレスなDockerコンテナ内でDiscourseサーバーアプリケーションを実行しており、Jenkinsを使ったDiscourseの継続的デプロイを簡単にセットアップできます。

各Dockerコンテナ内で動作しているものは何でしょうか?

  • Nginx: Webサーバーなしにはウェブは成り立ちませんよね?最速の軽量Webサーバーの一つであることから、Nginxを選択しました。
  • Unicorn: Discourseを提供するRubyプロセスの実行にはUnicornを使用しています。Unicornの数が増えるほど、同時リクエスト数も増えます。
  • Anacron: サーバーのスケジューリングはAnacronが担当しており、コンテナが再起動またはオフラインになった場合でも、スケジュールされたコマンドとスクリプトを追跡し続けます。
  • Logrotatesyslogd: ログ、ログ、ログ。すべてのコンテナはsyslogdを介して大量のログを生成し、ログのローテーションと最大ログサイズの管理にはLogrotateを使用しています。
  • Sidekiq: RubyコードレベルのバックグラウンドサーバータスクにはSidekiqを使用しています。

共有データファイルは、3-Distribute 2-Replicateのセットアップを使用して、Webティアのホスト間で共有される共通のGlusterFSファイルシステムに永続化されています。Glusterはかなりよく機能していますが、変更に対する耐性はあまり高くないようです。ノードの交換や再構築は、RAID10アレイからディスクを引き抜いて新しいものを挿し込み、レプリケーションがうまくいくことを祈るような、胃が痛くなる作業です。分散ファイルシステムストアとしてCephを検討したいと思っています。S3のようなインターフェースとマルチマウントPOSIXファイルシステムの両方を提供できるためです。

タイ・ファイター(データベース)

新しいSSDを搭載した3台のタイをPostgresデータベースサーバーとして使用しています。

  1. 1台はビジネスクラス(多数のサイトをホスティングする単一のDiscourseアプリケーションイメージ)コンテナとスタンダードティアプランのデータベースをホストします。
  2. 1台はエンタープライズクラスのインスタンスのデータベースをホストします。
  3. 1台はこれら両方のスタンバイです。プライマリDBMSからのストリーミングレプリケーションログを受け取り、深刻な障害が発生した場合にプロモートされる準備が整っています。

タイ・ファイタープライム

グループの中で最も強力なマシンはtiefighter1です。他のすべてのタイとは異なり、8プロセッサと128GBメモリで構成されています。過去1年間、このサーバーにできるだけ多くの作業を割り当てるよう努めてきました。その結果は成功と言えるでしょう。

ユーティリティおよびVMサーバーとしての側面もありますが、このサーバーが担う最も重要な役割の一つがredisのインメモリネットワークキャッシュです。

redisインスタンスを適切に分離することは、しばらく前から私たちの課題でした。すでにパーティショニングのために別々のデータベースを使用するよう設定されていましたが、それでもインスタンスが互いに影響を及ぼす可能性がありました。特に、同じredisサーバーに接続しながら異なるredisデータベースを使用するマルチサイト構成がその例です。

ひらめきがありました。redisサーバーが提供するパスワード機能を使って、同じパスワードを使用する接続を自動的に専用の独立したredisバックエンドに振り分けるというものです。新しいパスワードを設定すると、そのパスワードに紐付けられた新しいインスタンスが自動的に作成されます。分離、セキュリティ、使いやすさ。数日後、Samredismuxを持って戻ってきました。9月にDocker内に移行されてから、順調に稼働し続けています。

Jenkins

Jenkinsは「すべての」内部管理ルーティンを担っています。自動化できるのに、なぜ同じ作業を何度も繰り返すのでしょうか?もちろん、最大の課題はビルドとデプロイメントのプロセスです。GitHubの更新時に自動的に実行される一連のジョブが設定されています。

メインのGitHubリポジトリへのプッシュから本番環境でコードが動作するまでの総所要時間は12分で、そのうち8分は新しいマスターDockerイメージのビルドに費やされています。

Discourseのホスティングにおいて、ある程度安定した構成に到達するまでに約1年(そして非常に多くのDockerとDiscourseのベータ版)を要しました。この構成は時間とともに変化し続けると確信しており、成長に合わせてスケールアウトを続けていく予定です。

原文はこちら:


Good Loopでは、Discourseのセルフホスティングを安価で提供しています。開発元であるCDCK社の協力のもと、公式ブログ記事の翻訳・公開など、日本での普及にも努めています。

詳しくはこちら: Discourseの導入・運用支援・コンサルティング – Good Loop