ロードバランサーとマネージドデータベースクラスターを使用して談話展開をスケーリングする方法
序章
StackOverflowの創設者の1人によって作成されたDiscourseは、オープンソースのディスカッションプラットフォームです。 談話は、オンラインフォーラム、メーリングリスト、チャットルームなどを強化することができます。
Discourseは、DigitalOceanのワンクリックインストールを使用して単一のドロップレットでうまく機能しますが、コミュニティが成長するにつれて、単一のドロップレットよりも大きくなる可能性があります。 複数のドロップレットを使用すると、ドロップレットの1つがオフラインになった場合に、コミュニティに回復力が提供されます。 各ドロップレットは、帯域幅の許容量も増やします。 複数のドロップレットを使用する場合、ロードバランサーはデプロイを拡張し、Webアプリに高可用性をもたらすのに役立ちます。 最後に、マネージドデータベースインスタンスは、複数のドロップレット間で一貫したユーザーエクスペリエンスを保証します。
このチュートリアルを完了すると、DigitalOceanで実行される高可用性で簡単にスケーラブルなDiscourseデプロイメントができます。 新しいUbuntu20.04ドロップレットから始めて、ロードバランサー、マネージドPostgreSQLクラスター、Redisインスタンス(オプション)、および追加のドロップレットを含む、水平方向にスケーラブルなDiscourseインストールで終了します。
前提条件
このチュートリアルに従うには、次のものが必要です。
- root以外のユーザーで構成された2GB以上のRAMを搭載したUbuntu20.04サーバー
sudo
ガイド「Ubuntu20.04を使用したサーバーの初期設定」に従って実行できる特権とファイアウォール。 - サーバーにインストールおよび構成されたDiscourse。これは、チュートリアル Ubuntu20.04にDiscourseをインストールする方法に従って実行できます。
- DNSレコードがDigitalOceanによって管理されているドメイン名。これは、チュートリアル共通ドメインレジストラからDigitalOceanネームサーバーを指定する方法に従って実行できます。 サーバーでDiscourseを設定するときは、サブドメインではなくメインドメイン名を使用してください(たとえば、
yoursite.com
それよりもdiscourse.yoursite.com
). - チュートリアルDockerエコシステム:一般的なコンポーネントの概要から得られるDockerの知識。
- 製品ドキュメントに記載されているロードバランサーに関する知識。
ステップ1—DigitalOceanロードバランサーを談話サーバーに追加する
このステップでは、前提条件で作成したDiscourseサーバーにDigitalOceanロードバランサーを追加します。 DigitalOceanコントロールパネルにアクセスし、ネットワーク、ロードバランサー、ロードバランサーの作成の順にクリックします。
ロードバランサーのデータセンターリージョンを選択する必要があります。 談話ドロップレットに選択したのと同じ地域を選択してください。 ロードバランサーはプライベートネットワークを使用してドロップレットと通信するため、ドロップレットとロードバランサーの両方が同じリージョンにある必要があります。
次に、ドロップレットの名前をテキストフィールドに入力して、ドロップレットをロードバランサーに追加します。
Discourseは通常、インストールプロセス中に無料の Let’sEncrypt証明書を発行することでHTTPSを処理します。 ただし、Dropletがロードバランサーの背後にある場合、ドメインのIPアドレスがDropletのIPと一致しないため、Let’sEncryptは証明書を更新できません。
幸い、DigitalOceanロードバランサーは証明書を管理できます。 HTTPSの転送ルールをロードバランサーに追加する必要があります。 転送ルールは、特定の種類のトラフィックをドロップレットに転送するようにロードバランサーに指示します。
注:転送ルールの詳細については、ロードバランサーの製品ドキュメントを参照してください。
2つの転送ルールが必要です。1つはHTTP用、もう1つはHTTPS用です。 HTTPSの転送ルールを追加することにより、DigitalOceanは証明書を自動的に生成および更新できます。 HTTPSのサポートは、セキュリティとサイトのSEOにとっても重要です。
前提条件の一部としてドメインをDigitalOceanに追加したので、HTTPSサポートを追加するには数回クリックするだけです。 転送ルールセクションに、という新しいルールを追加します HTTPS
、ドロップダウンリストから選択できます。 次に、証明書をクリックしてから、+新しい証明書をクリックします。
ドメイン名をテキストフィールドに入力すると、自動入力されます。 次に、証明書に名前を付け、証明書の生成をクリックして、DigitalOceanが証明書を要求し、管理できるようにします。
ロードバランサーのセットアップはほぼ完了です。 詳細設定の編集ボタンをクリックし、プロキシプロトコルを有効にするというラベルの付いたボックスにチェックマークを付けます。 PROXYプロトコルが有効になっている場合、ロードバランサーはユーザーのIPアドレスなどのクライアント情報をロードバランサーの背後にあるドロップレットに転送します。 PROXYプロトコルがないと、Discourseはすべてのトラフィックが単一のユーザー(ロードバランサー)からのものであると見なし、すべてのログにユーザーの実際のIPアドレスではなくロードバランサーのIPアドレスが表示されます。
最後に、ロードバランサーの名前を選択し、ロードバランサーの作成をクリックします。
ロードバランサーを設定したので、Discourse構成ファイルを変更する必要があります。
ステップ2—談話構成ファイルの変更
このステップでは、Discourseに含まれているデフォルトの設定ファイルを変更します。 ドロップレットにSSHで接続し、 /var/discourse
このコマンドを使用するディレクトリ:
- cd /var/discourse
nanoまたはお気に入りのテキストエディタを使用して、で新しいファイルを作成して開きます。 templates
と呼ばれるディレクトリ loadbalancer.template.yml
:
- sudo nano templates/loadbalancer.template.yml
テンプレートフォルダには、Discourse構成のファイルが保持されます。 ここでは、新しいカスタムテンプレートを追加して、DiscourseインストールのPROXYプロトコルサポートを有効にします。
の loadbalancer.template.yml
、次の行を挿入します。
run:
- exec: "sed -i 's:listen 80: listen 80 proxy_protocol:g' /etc/nginx/conf.d/discourse.conf"
- exec: "sed -i 's:$remote_addr:$proxy_protocol_addr:g' /etc/nginx/conf.d/discourse.conf"
- exec: "sed -i 's:X-Forwarded-For $proxy_add_x_forwarded_for:X-Forwarded-For $proxy_protocol_addr:g' /etc/nginx/conf.d/discourse.conf"
最初の行は、Discourse Nginx構成を変更して、PROXYプロトコルのサポートを有効にします。 ロードバランサーでPROXYプロトコルが有効になっているが、Nginxでは有効になっていない場合、Discourseはサーバーエラーを返します。
2行目は、検索と置換を実行し、次のすべてのオカレンスを置き換えます。 $remote_addr
と $proxy_protocol_addr
. $proxy_protocol_addr
ロードバランサーから転送されたクライアントのIPアドレスが含まれます。 $remote_addr
通常はユーザーのIPアドレスが表示されますが、Discourseはロードバランサーの背後にあるため、ロードバランサーのIPアドレスが表示されます。
最後の行は、のすべての出現箇所を置き換えます X-Forwarded-For $proxy_add_x_forwarded_for
と X-Forwarded-For $proxy_protocol_addr
、確実に X-Forwarded-For
ヘッダーは、ロードバランサーのIPアドレスではなく、クライアントのIPアドレスを正しく記録します。
を押してファイルを保存して閉じます CTRL+X
に続く y
.
最後に行う必要があるのは、テンプレートをDiscourseにロードし、Discourseを再構築することです。
nanoまたはお気に入りのテキストエディタを使用して、というファイルを編集します app.yml
の中に containers
ディレクトリ:
- sudo nano containers/app.yml
まず、作成したテンプレートを追加します。 下 templates
、図のように強調表示された行を追加します。
templates:
- "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
- "templates/loadbalancer.template.yml"
必ず下の行に新しいテンプレートを追加してください templates/web.template.yml
.
次に、2行を確認します web.ssl.template.yml
と templates/web.letsencrypt.ssl.template.yml
両方ともポンド記号を追加してコメントアウトされます[#
]示されているように:
templates:
- "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
- "templates/loadbalancer.template.yml"
## Uncomment these two lines if you wish to add Lets Encrypt (https)
# - "templates/web.ssl.template.yml"
# - "templates/web.letsencrypt.ssl.template.yml"
最後に、表示されるまで数行下に移動します expose
. 行をコメントアウトする - "443:443" # https
ポンド記号を追加する[#
]示されているように:
...
expose:
- "80:80" # http
# - "443:443" # https
Discourseを再構築すると、DiscourseでHTTPSが無効になります。 HTTPS接続はロードバランサーで終了し、ロードバランサーはDigitalOceanの安全なプライベートネットワークを介してドロップレットと通信するため、DiscourseサーバーにHTTPSを直接設定する必要はありません。
を押してファイルを保存して閉じます CTRL+X
に続く y
.
構成を適用してDiscourseを再構築するには、次のコマンドを実行します。
- sudo ./launcher rebuild app
このコマンドにはスーパーユーザー権限が必要です。そのため、このコマンドの前に sudo
.
この時点で、Discourseとロードバランサーの構成は完了です。 次に、ドメイン名でロードバランサーのIPアドレスを指定します。
ステップ3—DNSを更新する
このステップでは、DropletのIPアドレスではなく、ロードバランサーのIPアドレスをドメインに指定します。
DigitalOceanのDNSホスティングを使用している場合は、コントロールパネルに移動し、ネットワーキングをクリックします。 ドメイン名をクリックして、ドロップレットを指すAレコードを探します。 レコードの詳細メニューを選択して、レコードを変更します。 このレコードの値をDropletのIPアドレスからLoadBalancerのIPアドレスに変更します。
DiscourseサーバーはDigitalOceanロードバランサーの背後で実行され、DigitalOceanが自動的に行うため、独自のSSL証明書を管理する必要はありません。
ドメイン名にアクセスして、Discourseのインストールが機能していることをテストします。 次のようなページが表示されます。
ドメインがロードバランサーを指しているので、管理対象データベースインスタンスを追加して、ユーザーに一貫したエクスペリエンスを提供します。
ステップ4—マネージドDigitalOceanデータベースの追加
このステップでは、DigitalOceanマネージドPostgreSQLインスタンスを作成し、それをDiscourseデプロイメントに追加します。
ロードバランサーの主な利点は、トラフィックを複数のドロップレットに分割することです。 これまで、データベース、Redisサーバー、およびWebサーバーはすべて単一のドロップレットで実行されていました。 2番目のDiscourseインスタンスを追加すると、独自のデータベース、Redisサーバー、およびWebサーバーがあり、完全に異なるWebサイトのように機能します。 訪問者は、さまざまなデータベースに接続されるため、投稿やユーザーが異なる他のWebサイトにアクセスしているように感じる場合があります。 この問題は、各Discourse Dropletで個別のデータベースを実行するのではなく、DigitalOceanのマネージドPostgreSQLインスタンスの1つを使用することで解決できます。
DigitalOceanコントロールパネルに移動して、DigitalOceanマネージドPostgreSQLインスタンスをセットアップします。 データベース、データベースクラスターの作成、最後に PostgresSQL を選択し、ドロップレットの場所に一致するリージョンを設定して、データベースクラスターの作成をクリックします。 ]。
データベースのプロビジョニング中に、Dropletを信頼できるソースとしてデータベースに追加します。 これにより、DropletはDigitalOceanの安全なプライベートネットワークを使用してデータベースと通信できるようになります。
次の画面でVPCネットワークを選択し、データベースホスト、ユーザー名、パスワード、およびポートの値をメモします。これらを追加する必要があります。 containers/app.yml
ファイル。
データベースクラスターが作成されたら、Discourseの構成を更新する必要があります。 開ける containers/app.yml
:
- sudo nano containers/app.yml
の中に templates
セクション、行をコメントアウト - templates/postgres.template.yml
示されているように:
templates:
# - "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
- "templates/loadbalancer.template.yml"
これにより、Discourseが再構築されたときに独自のPostgresサーバーをプロビジョニングできなくなります。
次に、 env
のセクション containers/app.yml
以下の行を追加して、値をデータベースのユーザー名、パスワード、ホスト、名前、およびポートの独自の値に置き換えます。
env:
DISCOURSE_DB_USERNAME: your_db_username
DISCOURSE_DB_PASSWORD: your_db_password
DISCOURSE_DB_HOST: your_db_host
DISCOURSE_DB_NAME: your_db_name
DISCOURSE_DB_PORT: your_db_port
これらの追加の変数により、Dropletは外部データベースに接続できます。
を押してファイルを保存します CTRL+X
に続く y
.
既存のDiscourseインストールがある場合は、バックアップとしてエクスポートする必要があります。 これを行うには、サイトの管理領域に移動し、バックアップをクリックしてから、バックアップをクリックします。
注:サイトのバックアップと復元の詳細については、Discourse製品のドキュメントDiscourseインスタンスを別のサーバーに移動するを参照してください。
構成を適用してDiscourseを再構築するには、次のコマンドを実行します。
- sudo ./launcher rebuild app
サイトをエクスポートした場合でも、新しい管理者アカウントを作成するには、DiscourseWebインストールを再度実行する必要があります。 新しいデータベースに接続したので、このアカウントを使用してDiscourseを復元できます。
最後に、1つの設定を変更して、ユーザーがサイトにアクセスしている間、同じドロップレットにとどまるようにします。
DigitalOceanコントロールパネルでロードバランサーの設定に戻ります。 ネットワーク、ロードバランサー、設定の順に移動し、スティッキーセッションを探します。 編集をクリックします。
StickySessionsをnoneからCookieに変更し、Saveをクリックします。
スティッキーセッションにより、ロードバランサーを介してWebサイトにアクセスする各ユーザーは、アクセスしている間、同じドロップレットに接続されたままになります。 各ドロップレットにはまだ独自のRedisインスタンスがあり、Redisは、ユーザーがログインしているときにDiscourseがユーザーを追跡する方法であるため、これは重要です。 スティッキーセッションがないと、ユーザーは1つのドロップレットにログインしてから、新しいページにアクセスし、(ユーザーには不明)、ログインしていない他のドロップレットにスワップすることができます。 スティッキーセッションは、ユーザーを同じドロップレットに保持することでこれを防ぎます。
データベースで行ったように、Redisを専用のインスタンスに移動すると、スティッキーセッションは不要になります。 次のステップでこれを試すことができます。
ステップ5—(オプション)DigitalOceanマネージドRedisインスタンスを追加する
この手順はオプションであり、DigitalOceanManagedRedisインスタンスが必要です。 この時点まで、Redisインスタンスはロードバランサーの背後にあるドロップレットに組み込まれていました。これには、ユーザーがログインしたままになるようにスティッキーセッションが必要です。 ドロップレットがダウンした場合、ロードバランサーは残りのドロップレット間でユーザーを共有します。 ただし、以前の設定では、セッション情報がドロップレットに保存されているため、ドロップレットを切り替えるとユーザーはログアウトしていました。
ドロップレットの外部にRedisサーバーを追加すると、この問題に対処できます。 これにより、Discourseの状態がドロップレットから効果的に移動します。 ドロップレットがオフラインになった場合、ユーザーはログアウトされません。実際、ユーザーは気付くことさえありません。
マネージドPostgreSQLデータベースを作成したのと同じ方法で、DigitalOceanマネージドRedisサーバーをセットアップできます。 DigitalOceanコントロールパネルに移動します。 データベース、作成、データベースの順にクリックし、データベースエンジンとしてRedisを選択します。 他のリソースと同じリージョンを選択して、それらが同じVPCネットワーク上にあることを確認します。 サーバーに名前を付けて、データベースクラスターの作成をクリックします。
Postgresデータベースを作成するときと同じように、はじめにの手順が記載されたウェルカム画面が表示されます。 [このデータベースクラスターを保護する]をクリックし、ドロップレットの名前を入力して、これらのインバウンドソースのみを許可するをクリックします。 これにより、DropletのみがRedisに接続できるようになります。
次に、Redisサーバーのエビクションポリシーを選択する必要があります。 allkeys-lruを選択します。 このポリシーは、Redisサーバーがいっぱいになると、最も古いエントリの削除を開始することを意味します。 これにより、しばらくの間Webサイトを使用していないユーザーがログアウトされますが、Redisがエラーを返し、動作を停止するよりはましです。
立ち退きポリシーを保存します。 PostgreSQLデータベースと同様に、接続の詳細画面で、VPCネットワークを選択します。
Redisインスタンスが作成されたら、Discourse構成を更新する必要があります。 開ける containers/app.yml
を使用して nano
:
- sudo nano containers/app.yml
Redis接続の詳細をに追加します env
ここに示されているセクション。 強調表示されたテキストを自分の情報に置き換えてください。 (ユーザー名フィールドを含める必要はありません。)
env:
DISCOURSE_REDIS_HOST: your_redis_host
DISCOURSE_REDIS_PASSWORD: your_redis_password
DISCOURSE_REDIS_PORT: your_redis_port
DISCOURSE_REDIS_USE_SSL: true
次に、 templates
セクション、行をコメントアウト - templates/redis.template.yml
示されているように:
templates:
# - "templates/postgres.template.yml"
# - "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
- "templates/loadbalancer.template.yml"
これにより、Discourseが独自のRedisインスタンスを作成できなくなります。
を押してファイルを保存して閉じます CTRL+X
に続く y
.
構成を適用してDiscourseを再構築するには、次のコマンドを実行します。
- sudo ./launcher rebuild app
マネージドRedisインスタンスを使用すると、スティッキーセッションは不要になります。 必要に応じてこのオプションをオフにすることもできますが、ユーザーはどちらの方法でも違いに気付くことはありません。
管理対象データベースを構成に追加したので、Discourseサーバーのスナップショットを作成してドロップレットを追加します。
ステップ6—追加の液滴を追加する
このステップでは、Discourse Droplet のスナップショットを作成します。これにより、新しいサーバーの作成が簡単になります。 スナップショットは、既存のドロップレットの完全なコピーを提供し、それらを使用して同じ内容の新しいドロップレットを作成できます。
DigitalOceanコントロールパネルに移動して、新しいスナップショットを作成します。 ドロップレットをクリックしてドロップレットを見つけ、スナップショットをクリックします。 スナップショットに名前を付けて、ライブスナップショットを作成をクリックします。
このスナップショットを使用して、ロードバランサーの背後にドロップレットを追加し、Webサイトの容量を増やすことができます。
新しいDropletを作成するたびに、PostgresサーバーとRedisサーバーの信頼できるソースを更新する必要があります。これはコントロールパネルから実行できます。 前の手順で行ったように、変更するデータベースインスタンスを選択し、概要に移動してから、このデータベースクラスターを保護します。 新しいDropletIPアドレスを信頼できるソースのリストに追加します。
このステップでは、スナップショットを使用して追加のドロップレットを作成し、それらを信頼できるソースとしてPostgreSQLおよびRedisインスタンスに追加しました。
結論
このチュートリアルでは、DigitalOceanロードバランサーの背後にDiscourseサーバーをセットアップします。 デプロイメントの拡張を支援するために、ManagedPostgreSQLデータベースとManagedRedisインスタンスも追加しました。 最後に、スナップショットとコントロールパネルを使用して、ドロップレットを追加しました。 コントロールパネルを使用すると、コミュニティの成長に合わせてリソースを追加できます。
ロードバランサーを設定したので、CanaryDeploymentsなどの他のDigitalOceanロードバランサーのユースケースを調べることができます。 チュートリアルStunnelとredis-cliを使用してTLSを介してマネージドRedisインスタンスに接続する方法に従って、コマンドラインを使用してRedisインスタンスに接続することもできます。 最後に、管理対象データベースのドキュメントとチュートリアル管理対象データベースの接続プールとpgbenchを使用したPostgreSQLベンチマークを使用して、DigitalOceanのデータベースとそのパフォーマンスについて詳しく知ることもできます。