ロードバランサーとマネージドデータベースクラスターを使用して談話展開をスケーリングする方法

提供:Dev Guides
移動先:案内検索

著者はCOVID-19救済基金を選択し、 Write forDOnationsプログラムの一環として寄付を受け取りました。

序章

StackOverflowの創設者の1人によって作成されたDiscourseは、オープンソースのディスカッションプラットフォームです。 談話は、オンラインフォーラム、メーリングリスト、チャットルームなどを強化することができます。

Discourseは、DigitalOceanのワンクリックインストールを使用して単一のドロップレットでうまく機能しますが、コミュニティが成長するにつれて、単一のドロップレットよりも大きくなる可能性があります。 複数のドロップレットを使用すると、ドロップレットの1つがオフラインになった場合に、コミュニティに回復力が提供されます。 各ドロップレットは、帯域幅の許容量も増やします。 複数のドロップレットを使用する場合、ロードバランサーはデプロイを拡張し、Webアプリに高可用性をもたらすのに役立ちます。 最後に、マネージドデータベースインスタンスは、複数のドロップレット間で一貫したユーザーエクスペリエンスを保証します。

このチュートリアルを完了すると、DigitalOceanで実行される高可用性で簡単にスケーラブルなDiscourseデプロイメントができます。 新しいUbuntu20.04ドロップレットから始めて、ロードバランサー、マネージドPostgreSQLクラスター、Redisインスタンス(オプション)、および追加のドロップレットを含む、水平方向にスケーラブルなDiscourseインストールで終了します。

前提条件

このチュートリアルに従うには、次のものが必要です。

  • sudo権限を持つ非rootユーザーとファイアウォールで構成された少なくとも2GBのRAMを備えたUbuntu20.04サーバー。これは、ガイド「 Ubuntu20.04を使用したサーバーの初期設定」に従って実行できます。 。
  • サーバーにインストールおよび構成されたDiscourse。これは、チュートリアル Ubuntu20.04にDiscourseをインストールする方法に従って実行できます。
  • DNSレコードがDigitalOceanによって管理されているドメイン名。これは、チュートリアル共通ドメインレジストラからDigitalOceanネームサーバーを指定する方法に従って実行できます。 サーバーでDiscourseを設定するときは、サブドメインではなくメインドメイン名を使用してください(たとえば、discourse.yoursite.comではなく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に、次の行を挿入します。

テンプレート/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+Xyの順に押して、ファイルを保存して閉じます。

最後に行う必要があるのは、テンプレートをDiscourseにロードし、Discourseを再構築することです。

nanoまたはお気に入りのテキストエディタを使用して、containersディレクトリのapp.ymlというファイルを編集します。

sudo nano containers/app.yml

まず、作成したテンプレートを追加します。 templatesの下に、次のように強調表示された行を追加します。

コンテナ/app.yml

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.ymltemplates/web.letsencrypt.ssl.template.ymlの両方がコメント化されていることを確認します。

コンテナ/app.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の行をコメント化します。

コンテナ/app.yml

...
expose:
  - "80:80"   # http
# - "443:443" # https

Discourseを再構築すると、DiscourseでHTTPSが無効になります。 HTTPS接続はロードバランサーで終了し、ロードバランサーはDigitalOceanの安全なプライベートネットワークを介してドロップレットと通信するため、DiscourseサーバーにHTTPSを直接設定する必要はありません。

CTRL+Xyの順に押して、ファイルを保存して閉じます。

構成を適用して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行をコメントアウトします。

コンテナ/app.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サーバーをプロビジョニングできなくなります。

次に、containers/app.ymlenvセクションを探し、以下の行を追加して、データベースのユーザー名、パスワード、ホスト、名前、およびポートの値を独自の値に置き換えます。

コンテナ/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コントロールパネルでロードバランサーの設定に戻ります。 ネットワークロードバランサー設定の順に移動し、スティッキーセッションを探します。 編集をクリックします。

StickySessionsnoneから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構成を更新する必要があります。 nanoを使用してcontainers/app.ymlを開きます。

sudo nano containers/app.yml

次に示すように、Redis接続の詳細をenvセクションに追加します。 強調表示されたテキストを自分の情報に置き換えてください。 (ユーザー名フィールドを含める必要はありません。)

コンテナ/app.yml

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行をコメントアウトします。

コンテナ/app.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+Xyの順に押して、ファイルを保存して閉じます。

構成を適用して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のデータベースとそのパフォーマンスについて詳しく知ることもできます。