By

Amazon ECS でスケーラブルな Mastodon インスタンスを立ち上げる

はじめに

今回は、Barcelona を使って、Amazon ECS 上に Mastodon のインスタンスを立ち上げる方法を紹介したいと思います。

単に Mastodon のサーバを起動するだけなら、VPSなどを使って一台のサーバで全部動かす方が簡単です。しかし、それではスケーラビリティの面で限界があり、ユーザが増えてきた時にいろいろ困ると思います。

ECSとさまざまな AWSのマネージドサービスを組み合せて構築することで、以下のようなメリットがあります。

  • ユーザが増えてきた時に負荷に応じてさまざまな方向に拡張できる
  • 一つのクラスタ内に複数のインスタンスを立ち上げ、1インスタンスあたりの費用と運用面の負荷を抑えることができる
  • バックアップの取得やレプリカの運用が簡単で、データを確実に守ることができる
  • セキュリティ面ではるかに安全である

デメリットとしては、初期費用が高いことと最初の構築がはるかに難しいことですが、構築の手間については、Barcelona というツールと、このチュートリアル用に書いたスクリプトでかなり簡単になります。記事内のコマンドをそのまま打っていけば、2,3時間で最初のインスタンスを立ち上げることができると思います。

この記事の目的は以下のとおりです。

  • 実用的なアプリケーションを前提とした Barcelona のチュートリアル
  • ECSクラスタ運用のある程度実用的なサンプル
  • 拡張性のある本格的なMastodonインスタンス運用のベース

私は、担当しているシステムを数ヶ月前に、ECS つまり、Dockerベースのクラスタに切り替えました。これによって、運用や監視がずっと楽になって、負荷の増減に対しても素早く柔軟に対応できるようになりました。ひとことでいうと、いろんな所が自由に伸び縮みするフリーサイズの服みたいなものです。

そして、そのクラスタを構築、運用する上で、Barcelona の効果は非常に大きいと感じています。これがなかったら、リソースがたくさんあって管理しきれません。

この二つを紹介したいとずっと思っていたのですが、そのためには具体的なアプリケーションがあった方がわかりやすいので、その題材として、ちょうど今はやっている Mastodon を使おうと思います。

Mastodon は、技術的には典型的な Ruby on Rails のアプリケーションですが、その運用のされ方にちょっと独特な面があります。ECS や Barcelona を使うことで、そこにうまく対応できると私は考えています。

デジカでは、このチュートリアルで構築するクラスタとよく似た構成で、さまざまなアプリケーションを運用しています。そのノウハウが、Mastodonの運用にも役に立つと思います。

最初にMastodonについて私見を述べてみたいと思います。技術的な内容の方に興味がある方は次の節は飛ばしてください。

近い将来 Wordpress サイトの数 = Mastodon インスタンスの数 になる?

Mastoron は、今、突然話題になっている分散型SNSです。これについては、既に多くの記事が書かれていますが、私は次の記事が一番わかりやすいと思います。

この記事の中ほどには、著者のいしたにさんの持つ3つのアカウントのプロフィールページのスクリーンショットがあります。

multi account on Mastodon

ユーザの立場から見た場合には、この「インスタンスごとにアカウントを持ち、それぞれの場に応じて使いわける」という点が最も重要だと思います。逆に言うと、インスタンスのテーマが明確でかつ絞りこまれている必要があるということです。つまり、運用する側も複数のインスタンスを立ち上げるのが普通になるのではないでしょうか。

どういうことかと言うと、私は、Mastodon が、今の Wordpress が果たしている役割を置き換えていくのではないかと思っています。

企業などの組織が、何かWeb上で情報発信したいと思った時に、Wordpress をベースにして、CMSやブログを運用することが一般的に行なわれています。多くの企業がそのようなサイトを運営し、いくつかは、双方向の問合せ窓口やユーザ(顧客)のためのフォーラムのような機能も果たしています。

このような Wordpress ベースのサイトを、目的別や製品カテゴリ別で複数持っている組織も多いでしょう。

Mastodon は、このような情報発信のベースとして使われると思います。そして、Wordpress と同じように、目的別、製品カテゴリ別に複数の Mastodon インスタンスが運用されるようになるでしょう。その中には、発信主体のものもあれば、双方向のやりとりやユーザ同士の交流を目的としたものもあるでしょう。

Wordpress が Plugin によって拡張され、当初の CMS という機能から大きくはみだした役割も果たすようになったように、Mastodon はボットによって拡張され、今では考えられないような様々な目的のために使われるのではないかと思います。

ユーザの立場から見ると、これらは全てリアルタイムの情報のストリームであり、Mastodon アカウントでフォローする以外にも、これを束ねるためのツールがいろいろ開発されていき、目的のためにそれを使いわけることが可能です。

結果としてできることは、今の Twitter等の SNS と似ているかもしれませんが、情報の発信や流れの制御を一つの運営元が統一的に行なうのではなく、さまざまな主体が連携しながら行なうのです。

そして、その動きに主体的に関与していくためには、自前のインスタンス運用が必要になってくると考えています。

イメージ的に言うと、ちょうど、今運用している Wordpress のサイトの数が、近い将来の、Mastodon インスタンスの数になってくると考えればいいのではないでしょうか。

複数のインスタンスを効率的に運用するには

これをサーバを運用する側から見た場合には、次の二点がポイントになると思います。

  • 複数のインスタンスを効率的に運用する
  • 負荷の増減に素早く対応できるような仕組みで構築する

Mastodon は、典型的な Ruby on Rails のアプリケーションで、Dockerfile も公式のレポジトリに含まれているので、VPS上で一つのインスタンスを起動するのは、簡単だと思います。

しかし、単一サーバの運用ではインスタンスの数が増えるほど、費用も運用の負荷も比例して増大していくことになります。うまくリソースを共有する仕組みが必要だと思います。

また、Mastodon は、ユーザ(ユーザ間のフォローの数)が増えると急激にサーバの負荷が高くなります。これは実装の問題ではなく、OStatus というプロトコルの問題なので、しばらくは大幅に改善されることもないと思います。

そして、その負荷は、クライエントからの Get リクエストではなくて、サーバ同士の Push 通信なので、これまでのようにCDNやフロントエンドによる負荷分散の方法では解決できない部分もあります。

このチュートリアルでは、これらの問題に対応するために、ECS クラスタ上に Mastodon のインスタンスを構築します。

ECSを使えば、複数のマストドンインスタンスが、同じサーバ(EC2インスタンス)の上で稼動するので、リソースを共有できます。また、負荷の変動に対応する手段もいろいろ用意されています。

これからのインフラを考える上では、非常に面白い練習問題とも言えます。

そして、それを簡単に構築するツールとしての Barcelona を紹介したいと思います。

必要なもの

以下の手順に従えば、3時間くらいで、Mastodon のインスタンスが起動しますが、その代わり、事前にちょっと準備が必要です。

まず、管理者権限の使える Amazon AWS のアカウントが必要になります。なるべく新規に取得したものか、テスト用のアカウントにしてください。

その他に以下のものが必要になります。

  • github アカウント (そのアカウントが、何らかのgithub organizationに所属している必要がある)
  • 自由に設定できる DNS ホストネーム × 2
  • 上記 ホストネームの SSLサーバ証明書
  • 一時間あたり 約$0.2 の費用

ECSクラスタは、ロードバランサーが必要です。また、Docker でアプリケーションを動かすとサーバ内部に永続的なストレージを持つことが難しくなるので、RDS等のマネージドサービスをいくつか組み合わせる必要があります。そのため、どうしても最低限のクラスの費用が高くなってしまいます。

AWS は時間単位の完全従量制なので、試してみる場合には、動作確認してすぐに消してしまえば、$1もかからないと思います。しかし、作成したサーバ等のリソースを残しておくと思わぬ費用がかかりますので注意してください(最低月 $140 + 転送量の従量課金)。

github アカウントは、Barcelona のユーザ認証のために使用します。今の所、Barcelona は、github 上の organization を指定して「この organization のメンバーには使用を許可する」という認証しかできません。これは、今後のバージョンアップで改善されると思いますが、現状は、github アカウントが必要で、そのアカウントがどれかの organization に所属している必要があります。

それと、Barcelona も Mastodon も SSL が(ほぼ)必須となっています。これは時代の流れだと思って、SSL証明書を用意してください。Let’s Enrypt の無償のものでかまいませんが、AWS の Certificate Manager に証明書を登録し、証明書の ARN を取得する必要があります。

全消去の方法

最初に、このチュートリアルでAWS上に作成したリソースを全部消す方法を紹介しておきます。

このチュートリアルでは、Barcelona と、これを補助する Mastodon on Barcelona という二つのツールを使いますが、どちらも CloudFormation によって全てのリソースを確保します。

従って、CloudFormation の Stack を全部消すことによって、全てのリソースを削除できます。

AWS の Web Console から、CloudFormation を選択してください。その後、作成したStack をひとつづつ削除してください。

how to delete stack

このチュートリアルで作成される Stack は、「barcelona」か、district 名、 heritage 名(いずれも詳細は後述)を含んでいます。これと作成日時を手掛りに、関連する Stack を全部削除してください。逆に言うと、district名、heritage名として、他で使われてないユニークな名前をつけた方がいいかもしれません。

Stackで管理しているリソースが、他から使用されていたり、CloudFormation 以外からの変更があったりすると、エラーとなり「DELETE_FAIL」というステータスになります。この場合は、もう一度削除をしようとすると、削除できなかったリソースの一覧が表示されるので、これを手動で削除してから、再度実行してください。

ただし、当然ですが、間違って他の CloudFormation Stack を削除することがないようにしてください。

このためには、できれば、新しいアカウントを使った方がいいかもしれません。それができない場合は、チュートリアルの開始前に、既存の Stack のリストをメモしておいた方がいいでしょう。

手順の概略

手順は以下のようになります。

  1. Barcelona の bootstrap
  2. Mastodon 用AWSリソースの確保
  3. Docker Image の準備
  4. Mastodon用 Heritage の作成
  5. 管理者用ユーザの登録

5 以外は、こちらで用意したスクリプトを実行するだけです。

ホスト名と SSL証明書の準備

このチュートリアルでは、二つのホスト名を使用します。

  • Barcelona API サーバ用のホスト名
  • Mastodon 用のホスト名

そのために、自由に使えるDNSのドメインを一つ確保しておく必要があります。

以下の例では、barcelona.sample.com(Barcelona API サーバのホスト名) と mstdn.sample.com(Mastodonインスタンス用のホスト名) として説明します。

Barcelona APIサーバのホスト名は、管理者のみが使用します。ユーザに公開するものは、Mastodon インスタンス用のホスト名の方で、これが Mastodon のアカウントのドメイン名になります。

また、この二つのホスト名に対応する SSL 証明書を用意して、AWS Certificate Manager に登録しておく必要があります。これについては、説明を省略しますが、SSL証明書の Arn をメモしてからチュートリアルに入ってください。

二つのホスト名は、別のドメインにあってもかまいません。また、同じドメインで使用する場合は、証明書はワイルドカード証明書(*.sample.com)を両方に使ってもかまいません。

district名と heritage名

以下では、district名とheritage名を入力する所がいくつか出てきます。両方とも、Barcelona 内部で使用する管理単位で、ユーザには見えません。

簡単に言うと、district は、ECSクラスタに対応します。既定値は “default” なので、これをそのまま使ってもかまいませんが、本チュートリアルでは “mstdn” を使用します。

heritage は、アプリケーションの管理の単位で、この例ではマストドンのインスタンスに対応します。ここでは “bcn-users”を使用します。

これらは、Barcelona が確保する AWS リソースの名前として使用されますので、目的に合わせてわかりやすいものを設定してください。たとえば、Mastodon インスタンスが使用する PostgreSQL の RDS インスタンスの名前は、上記の用に設定すると自動的に”mstdn-bcn-users-db” になります。

Step 1: Barcelona の bootstrap

さて、ここからチュートリアルに入っていきます。

Barcelona は、Railsで開発された Webサービスと、cliから構成されます。cliは Go言語で開発されているので、各プラットフォーム用のバイナリを一つインストールするだけですが、Webサービスの本体のインストールは大変です。普通の Rails アプリが稼動する環境なら何でもいいのですが、アプリケーションがECSで稼動するので、できればこの Webサービスの部分も ECS で動かした方が何かと便利です。

そのため、いきなり ECSクラスタを構築して、そこに Barcelona 本体をインストールする bootstrap スクリプトが用意されています。これを使うとコマンド一発でインストールできます。

管理者用IAMユーザの設定

まず、最初に、管理者権限(AdministratorAccessグループに所属する)のIAMユーザを用意して、その認証情報(AWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEY)を用意します。

なお、この認証情報は、インストール時に使用されるだけで、サーバ側に設定されることはありません。Barcelona の API サービスは、管理者権限ではなく、最小限の必要権限だけに設定されたRoleで動作します。

Dockerのインストール

bootstrap は Docker Image として提供されているので、このチュートリアルではクライアント側の Docker から実行します。他には特にインストールする必要のあるものはありません。

この Image は、Barcelonaのリポジトリ から Build され、CIによって自動更新されているものです。ただ、Image そのものの安全性は、Docker の仕組み上保証できませんので、管理者アカウントでの実行が、セキュリティや内部規約などの点で問題がないか確認してから実行するようにしてください。

一般的には、他の重要なデータを含まないテスト用のアカウントで実行するようにお願いします。

bootstrap の実行

下記のコマンドで bootstrap を実行します。

$ docker run --rm -it quay.io/degica/barcelona bin/bootstrap --region [リージョン] --acm_cert_[証明書のarn] --github_organization [organizationの名前] --district_name [district名]

これを実行すると、最初に指定した Docker Image をダウンロードして、その後、 AWS の認証情報を聞いてきますので、上記のIAMユーザの認証情報を入力してください。

実行例

$ docker run --rm -it quay.io/degica/barcelona bin/bootstrap --region ap-northeast-1 --acm_cert_arn arn:aws:acm:ap-northeast-1:1111111111:certificate/xxxxxx --github_organization degica --district_name mstdn

docker run --rm -it quay.io/degica/barcelona bin/bootstrap --region ap-northeast-1 --acm_cert_[証明書のarn] --github_organization [organizationの名前] --district_name [district名]
Provide your AWS access key ID and secret access key.
This access key will be used to bootstrap your Barcelona environment.
The best practice is to create a new access key with admin previleges and
delete it after the bootstrap is complete.
AWS Access Key ID: XXXXXXXXXXXXXXXXX
AWS Secret Access Key: (シークレットキーを入力)
Created database 'db/bcn_bootstrap.sqlite3'
Creating Network Stack......................
Creating Barcelona Database.................................................
Provisioning Barcelona service..
.................................

Barcelona Bootstrap Completed!
Endpoint: barcelona-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com

Set your DNS record to point to the above endpoint and run the following Barcelona client command

最後に、インストールされた API サーバの Endpoint が表示されますので、これを CNAME として、Barcelona APIサーバ用のホスト名(barcelona.sample.com)に登録しておいてください。

実行状況の確認

bootstrapの実行には、30分ほどかかります。実行状況は、CloudFormation の Web コンソールから確認できます。以下の6つの Stack が実行されると完了です。

  • barcelona-mstdn
  • mstdn-rds-barcelona-db
  • endpoint-barcelona
  • heritage-barcelona
  • mstdn-barcelona-web
  • mstdn-barcelona-worker

また、AWS CloudWatch Logs には、以下のロググループが作成されます。これらの内容から進捗状況を確認することもできます。

  • Barcelona/mstdn/barcelona
  • Barcelona/mstdn/instances

Barcelona API サーバにログイン

bootstrapが完了したら、barcelona-cli から、自分のクライアント用のバイナリをダウンロードして、Path の通ったディレクトリにインストールしてください。

その後下記のコマンドでログインします。パラメータはEndpointを登録した Barcelona API サーバのホスト名です。

$ bcn login https://barcelona.sample.com
Create new GitHub access token with read:org permission here https://github.com/settings/tokens/new
GitHub Token: (tokenを入力)

ここでは、read:orgの権限を持つ、github token が必要になります。ガイダンスに表示された URL に行くと、token を作成することができますので、それを入力してください。

下記のコマンドでログインができているか確認してください。自分の github ユーザ名や 設定した district 名が表示されていたら、ログインができていることになります。

bash-3.2$ bcn api get /user
{
  "user": {
    "districts": [
      "mstdn"
    ],
    "name": "essa",
    "public_key": "xxxxxxxx",
    "roles": [
      "developer",
      "admin"
    ],
    "token": null
  }
}
$

なお、このログイン情報は “~/.bcn” というディレクトリに保存されていますので、Barcelona の使用をやめる時は、これを削除しておいてください。

Step 2: Mastodon 用AWSリソースの確保

さて、ここまで来れば、あとはアプリケーションの Docker Image を用意するだけで、アプリケーションを ECS クラスタの配下で動かすことができます。

しかし、一般的な Webアプリケーションでは、データベースも必要です。Docker 配下のアプリケーションは、永続的なストレージを持つことができません。そこで、データベースのような永続的なストレージを必要とするプロセスは、RDS のようなマネージドサービスと組み合わせるか、なんらかの外部のストレージをマウントすることが必要になります。ここでは、RDS を使用します。

また、Mastdon の場合は、redis と画像フィアルを格納する S3 Bucket 等も必要になります。そして、これらのリソースは単体では使用することができなくて、Subnet Group や 権限設定用の IAM ユーザなども必要になります。

そこで、これらのAWSリソースをまとめて確保するスクリプトを作成しました。このチュートリアルでは、以下はこのスクリプトを使用して、必要なリソースを確保していきます。

スクリプトの実行準備

まず、クライアント側に以下のツールを用意してください。

  • ruby (2.3以降)
  • aws cli (1.10.34以降)
  • git

それから、AWSの認証情報として、Barcelona の bootstrap で使用した、管理者のアカウントとリージョンを環境変数として設定します。

$ export AWS_REGION=ap-northeast-1
$ export AWS_ACCESS_KEY_ID='AKxxxxxxx'
$ export AWS_SECRET_ACCESS_KEY='xxxxxxxx'

次に、スクリプトをチェックアウトします。

$ git clone https://github.com:essa/mastodon_on_barcelona.git
$ cd mastodon_on_barcelona
$ bundle install --path vendor/bundle

準備の最後のステップとして configuration を行ないます。

$ bundle exec bin/deploy_mastodon config --region [region] --name [heritage名] --district-name [district名] --hostname [Mastodonのホスト名] --certificate-arn=[ホスト名のSSLサーバ証明書のArn] --endpoint [endpoint名]

実行例

$ bundle exec bin/deploy_mastodon config --region ap-northeast-1 --name bcn-users --district-name mstdn --hostname mstdn.sample.com --certificate-arn=arn:aws:acm:ap-northeast-1:111111111:certificate/xxxxxxxxxx --endpoint mstdn

このコマンドは入力されたパラメータを含む config.yaml を作成します。

config:
  region: ap-northeast-1
  hostname: mstdn.sample.com
  district_name: mstdn
  heritage_name: bcn-users
  certificate_arn: arn:aws:acm:ap-northeast-1:111111:certificate/xxxxxxxxxxx
  db:
    user: mastodon_admin
    password: xxxxxxxxxxxxx
    allocated_storage: 5 # MB
    instance_class: db.t2.micro
    storage_type: gp2
    multi_az: false
  redis:
    cache_node_type: cache.t2.micro
    num_cache_nodes: 1
  mastodon_source:
    repository: https://github.com/essa/mastodon.git
    branch: barcelona
  ecs:
    instance_type: t2.small
    cluster_size: 2

動作検証を前提として、最低限必要な容量やインスタンスタイプを既定値として設定してあります。以下のステップでは、このファイルを使用しますので、実環境で使用される場合は、必要に応じて変更しておいてください。

また、DBのパスワードは自動生成したものを記録しています。管理作業において必要になることもありますので、このファイルを安全な所に保存しておいてください。

DBとS3 bucket の作成

最初に RDS のインスタンスと、画像ファイル等を保存する S3 bucket を作成します。

$ bundle exec bin/deploy_mastodon create_db

リソースの確保は、CloudFormation を利用して行ないます。従って、パラメータを変更して再実行した場合は、ほとんどの場合、前回確保したリソースに対する変更となります。ただし、一部のプロパティの変更については、リソースの変更ではなくて、既存リソースを削除してから再作成することがあります。

RDS と S3 は、運用時にはユーザデータが保存されることになりますので、意図しないで削除されてしまうと大変です。安全のために、実運用開始後には、このコマンドを再実行しないようにしてください。

なお、実際に確保されるリソースの詳細については、コマンド実行時に表示される CloudFormation のテンプレートを参照してください。

その他のリソースの確保

次に、それ以外に必要なリソースを一括で確保します。

$ bundle exec bin/deploy_mastodon manage_aws_resources

こちらは、基本的には、削除/再作成を行っても問題ないものですので、再実行しても問題ありません。確保されるリソースは以下の通りです。

  • ElastiCache の Redis のクラスター
  • S3 アクセス用の IAM ユーザ
  • ECR の Docker Repository

それぞれに、subnet group や access key などの関連するリソースが必要なので、同時に確保しながら、相互に関連させています。

なお、これらのステップで確保したリソースに関する情報は、resources.yaml に保存されて、後のステップで使用されます。このファイルには、IAMユーザのシークレットキーも含まれているので、扱いには充分注意してください。

Step 3: Docker Image の準備

次に Mastodon の Docker Image を準備します。

Dockerfile の修正

本チュートリアルの構成では、PreCompile済みの Assets を Docker Image に含める必要があります。

v1.3.3 に対して、この変更を行なったソースを https://github.com/essa/mastodon で公開していますので、本チュートリアルではこれを使用します。変更する場合は config.yaml のリポジトリのURLを変更してください。

この変更は、Assets の配信を Rails アプリ本体で行なうために必要となります。Barcelona では、CDN を併用することを前提として、このような構成になっています。

詳細は「Assets 配信について」を参照してください。

コマンド実行

$ bundle exec bin/deploy_mastodon push_docker_image

これによって、以下を実行します。

  1. 作業用ソースファイルをチェックアウト
  2. Docker Image の作成
  3. 作成した Image を ECR の Docker Repository に push

1は、作業ディレクトリ(./mastodon)が存在する場合は スキップしますので、必要な場合は、このディレクトリ内のソースを変更したりバージョンアップを行なった上で、再度このコマンドを実行して、Docker Repository 内のイメージを更新することができます。

その場合は、次にECSクラスタ内で起動した時から、新しいイメージで実行されます。

ECS クラスタの準備

次に、ECSクラスタの準備をします。

$ bundle exec bin/deploy_mastodon setup_ecs_cluster

ここで行なわれることは、次の二つです。

  1. クラスタ内の Host Instance を config.yamlに従って増やす(デフォルトでは、t2.small X 2)
  2. Host Instance に Docker Repository へのアクセス権を与える

Step 4: Mastodon用 Heritage の作成

さて、いよいよここで Mastodon が起動します。

Endpoint の作成

最初に Endpoint を作成します。Endpoint とは、ALB のロードバランサー(に対応した Barcelona 内の管理単位)です。

$ bcn endpoint create --district=[district名] --certificate-arn=[SSL証明書のArn] [endpoint名]

実行例

$ bcn endpoint create --district=mstdn --certificate-arn=arn:aws:acm:ap-northeast-1:11111111111:certificate/xxxxxxxxx mstdn

最後に表示されたホスト名を CNAME として、Mastodon インスタンス用のホスト名に登録してください。

Heritage の作成

次のステップでいよいよ Mastodon がロードされて、上記のホスト名からアクセス可能になります。

$ bundle exec bin/deploy_mastodon create_heritage

このサブコマンドでは、以下の処理を実行します。

  1. barcelona.yml(後述)を作成する
  2. Barclona 上で 新しい heritage を作成する
  3. heritage に環境変数を設定する
  4. 作成した heritage 上で deploy のコマンド (bcn deploy) を発行する

途中で、前に起動した CloudFormation の Stack の実行完了を待つために、何度か待合せを行ないます。このステップは、20分から30分くらいで完了します。

なお、現在のバージョンでは、コマンド完了後に、ALB ターゲットグループの health check を一部変更する必要があります。これについては、「ALB のヘルスチェック変更」の節を参照してください。

また、このステップの中で ECS クラスタの作成、更新に時間がかかることがあります。5分ほど待って先に進まない場合は「desired countの変更」を参照して、このコマンド実行中だけdesired count を 0 にして、コマンド完了後に1に戻してください。

このコマンドが完了してから 2、3分待つと、設定したホスト名(今回の例では、https://mstdn.sample.com/) にアクセスすると、Mastodon の初期画面が表示されるはずです。

Mastodon About

Step 5: 管理者用ユーザの登録

さてここまで来たら、後は、基本的には通常通りの運用になります。

ただし、現状では、アカウント登録用のメールが送信されませんので、管理者ユーザの登録と承認のためには、rakerails console を実行する必要があります。Barcelona には、このためのコマンドが用意されていますので、下記のコマンドを実行してください。

$ (cd mastodon && bcn run -e production rake ...)

bcn runコマンドは、Barcelona の環境設定ファイル(barceloya.yml)をカレントディレクトリから参照しますので、mastodon のディレクトリで実行する必要があります。

このコマンドによって、rails console など、Rails の CLI が Rails アプリと同じ環境で動きますので、Administration-guide にある、各種管理操作をこれで行なうことができます。

実運用のために

このチュートリアルと参照した スクリプト mstodon_on_barcelona の内容は、私としては、かなり大規模なインスタンス運用のベースとなるものと考えています。

ただ、現時点では、実際にそのような運用を行なって検証しているわけではないので、実際に使用される場合は、構築内容の検証を充分行なった上で展開されるようにお願いします。著者、および株式会社デジカでは、このスクリプトの結果起きたいかなる問題に関しても、保証はできませんので、その点をご了承ください。

参考のために、以下に、実運用において必要となる検討内容について書いておきます。

ALB のヘルスチェック変更

本チュートリアルでは、ロードバランサとして ALB を使用していますが、ALB では、EC2インスタンスの登録を行う前に、ヘルスチェックに応答するかをテストします。そして、このヘルスチェックリクエストについては、リクエストの Path しか指定できません。

Mastodon では、外部からのリクエストを処理する web と streaming の二つのプロセスに対して、ヘルスチェックを行うことになります。ここが、今回のチュートリアル用スクリプトを作成する上で一番苦労した所です。

streaming app は、token を持たないリクエストには、全てエラー応答を返すようです。下記の変更を行なうことで health check の機能を組込むことはできたのですが、本体の重要なソースへの変更になってしまうので、今後のバージョンアップへの追随が難しくなるので、この変更は最終的にはやめにしました。

web app は、/about の Path がヘルスチェックに使えるかと思ったのですが、テストしてみると、ALB からのリクエストには 301 のステータスを返します。これがどうして 200 にならないのか今の所は原因不明です。

そこで、現状の Mastodn をALB に組込むには、以下のようにして、ヘルスチェックで300番台、400番台のエラー応答を許容するように設定する必要があります。

ECS の Web Console から、サービスを選択し、その中の Load Balancing -> Target Group をクリックする

ECS service console

Target Group から、Health Check -> Edit をクリックする

target group

Sucess Code を “200-499” に変更してから “Save”

target group edit

この変更を、webとstreaming の二つのサービスに対して行なってください。

メールサーバの設定

Mastodon では、環境変数を設定することでメールサーバを設定します。SendGrid や AWS SES などの準備をして、下記のコマンドで、メールサーバを登録してください。

$ (cd mastodon && bcn env set -e production SMTP_SERVER=xxx.sample.com SMTP_PORT=587 SMTP_LOGIN=xxxxxxx)
$ (cd mastodon && bcn env set -e production SMTP_PASSWORD=xxxxxxxxxxx)

また、現在のバージョンの Barcelona では、デフォルトで、 outbound traffic に制限をかけています。メールの送信に、1024 以下のポートを使う場合は、以下の変更も必要になります。

VPC の Web Console から、Network ACLs をクリックして、barcelona-[district名]-public というACLを選択して、port 587 を許可する設定を行なってください。この名前のACLは二つありますので、二つとも同じように変更してください。

network acl

Barcelonaで構築した ECSクラスタは、インターネットと切り離された private network で動くので、DMZに設置された NAT gateway を使って外部への通信を行ないます。この設定は、private network から DMZ に指定したトラフィックを通すために必要となります。

barcelona.yml について

Barcelona では、Docker Image の場所や、リクエストを待ち受ける ALB などの情報は、barcelona.yml というファイルに記述して、アプリケーションのソースと一緒に管理することを前提としています。

このチュートリアルの場合は、bin/deploy_mastodonl create_heritage の中で、次のような内容で、このファイルを生成しています。

web_base: &web_base
  service_type: web
  force_ssl: true
  cpu: 256
  memory: 256

worker_base: &worker_base
  cpu: 128
  memory: 256

environments:
  production:
    name: bcn-users
    image_name: 822761295011.dkr.ecr.ap-northeast-1.amazonaws.com/mstdn-bcn-users-mastodon
    before_deploy: rake db:migrate
    scheduled_tasks:
      - schedule: cron(15 20 ? * * *)
        command: rake mastodon:daily
    services:
      - <<: *web_base
        name: web
        command: bundle exec rails s -p 3000 -b '0.0.0.0'
        listeners:
          - endpoint: mstdn
            health_check_path: /about
      - <<: *web_base
        name: streaming
        command: npm run start
        memory: 128
        listeners:
          - endpoint: mstdn
            rule_conditions:
              - type: path-pattern
                value: //api/v1/streaming/*
            health_check_path: /api/v1/streaming/health_check
            rule_priority: 10
      - <<: *worker_base
        name: worker
        command: bundle exec sidekiq -q default -q mailers -q pull -q push

一般的には、これをそのまま使用して問題ないと思いますが、日次バッチの起動スケジュールや、sidekiq job の構成などを変更する場合は、これを修正して bcn deploy -e production を実行してください。

Docker Image の更新 (バージョンアップ)

./mastodon に展開されたソースを修正後、下記のコマンドでその内容を新しいDocker Image として登録することができます。

$ bundle exec bin/deploy_mastodon push_docker_image

また、このコマンド実行中に表示されるコマンドをそのまま使用してもかまいません。

Mastodon インスタンスの追加

「Mastodon用 Heritage の作成」の内容を、heritage名を変えてそのまま行なうことで、新しいインスタンスを起動することができます。

なお、現在は、Heritage ごとに別の EndPoint を割り当てるようになっていますが、今後、一つの Endpoint(ALB) を複数の Heritage で共有する方法もサポートする予定です。

もし、インスタンス(Heritage)の追加によってECS クラスタのホストインスタンスのリソースが不足する場合は、下記の「ホストインスタンスの追加、入れ替え」を行なってください。

運用コスト概算

転送量とデータ容量に対する従量課金は除外して算出しています。試験的な運用ではこれらは無視できる程度ですが、アクセス数やユーザ数が増えると、特に転送量の課金が急激に増えますので注意してください。

district 及び barcelona heritageの費用(インスタンス数に関わらずかかる固定費)

  • EC2 Instance (t2.micro): $0.032 / 1 時間 × 2台
  • barcelona用 RDS Instance: $0.028 / 1時間
  • barcelona用 Application Load Balancer: $0.0243 / 1時間

合計: (0.032*2)+ 0.028 + 0.0243 = 0.1163 / 1時間

一ヶ月運用で 0.1163 * 24 * 30 = $84.74

Mastodon Instance 一つごとの料金

  • アプリケーション用 RDS Instance: $0.028 / 1時間
  • アプリケーション用 Application Load Balancer: $0.0243 / 1時間
  • アプリケーション用 ElastiCache Cluster: $0.026 / 1時間

合計: 0.028 + 0.0243 + 0.026 = $0.0783 / 1時間

一ヶ月運用で 0.0783 * 24 * 30 = $54.38

なお、ALBを共有したり、Redis を ElastiCache でなく、ECSクラスタ内で起動するなど、費用を削減する手段はいくつかあります。

Desired Count の変更

Desired Count とは、ECSクラスタ内で起動するコンテナの数です。ECS は、このコンテナ数を自動的に維持します。仮にコンテナが意図せずに終了してしまった場合には、この数になるまで自動的に再起動します。

初期設定時には、一時的にこの数を0に設定した方が、CloudFormation の実行は早くなります。

初期設定完了後は1にして動作確認を行ない、運用開始後は、負荷に合わせて適切な値を設定してください。

ECS Web コンソールから、各サービスごとにこの数を変更することができます。

サービスの画面で「Update」をクリックします

setting desired count 1

「Number of Tasks」を変更して、「Update Service」をクリックします。(他の項目は変更しないでください)

setting desired count 2

ホストインスタンスの追加、入れ替え

下記のコマンドで、ECSクラスタのホストインスタンスのインスタンスタイプや台数を変更することができます。

$ bcn api patch /districts/mstdn '{"cluster_size":5, "cluster_instance_type": "m3.large" }'
$ bcn api post /districts/mstdn/apply_stack

このコマンドは、旧のホストインスタンスを稼動させたまま新のインスタンスを起動して、その準備ができてから旧をシャットダウンするので、サービスを中断することがありません。

これを自由自在に簡単に行なえることが、Barcelona で ECS クラスタを運用することのメリットです。

Assets 配信について

このチュートリアルの構成では、Rails Web プロセスが、アセッツの配信を行ないます。

この方法では、アセッツの配信の負荷が高いので、多数のアクセスには耐えられません。本格的な運用を行なう場合は、ALB の前に CloudFront などの CDN を立てて、そこでキャッシュするようにしてください。

これはあまり一般的ではありませんが、Barcelonaでは、負荷の高いアプリケーションには、CDN を併用するのが普通であるという前提で、Docker Image 内に Assets を含めて Rails App で配信する方がシンプルかつ確実な運用になるだろうと考えて、このような構成となっています。

なお、Barcelona では、デフォルトで、Nginx がフロントエンドサーバとして配置されています。このサーバは、ALB の Connection Draining をスムーズに行うために配置されているのですが、このNginxの Docker Image を変更することも可能です。

今後、このフロントエンドサーバの Image として、Cache を行うバージョンを公開することも検討しています。これを使えば、デフォルトで Nginx によるキャッシュが行なわれますから、負荷の面では CDN が不要になります。

おわりに

AWS には、さまざまなサービスが用意されていて、それを組み合せる方法は無数にあります。自由度は高いのですが、その自由度を適切に活用するには、高度な知識と経験が必要になります。

Barcelona は、AWS の活用方法については、Rails と同じような意味で、Opinionated Software だと思います。つまり、以下のような構成が一番いいと決めつけて勝手にそれを作ってしまいます。

  • データベースやアプリケーションサーバは、外部と切り離された private subnet で運用すべし
  • 全ての要素を multi-az もしくはそれに準じた構成で配置すべし(耐障害性向上)
  • 全てのアプリケーションは、ロードバランサーを通してリクエストを受けるべき(サービス中断なしにバージョンアップができるように)
  • ECS の Host Instance は Auto Scaling Group の配下で起動すべし(ダウン時に自動再起動するように)
  • AWSリソースはなるべく CloudFormation で管理すべし

つまり、これは「動く Good Practice 集」とも言えます。「AWS で、小から中規模の Web アプリを動かすなら、とりあえずこうやっとけばだいたい間違いないよ」と我々が考えるような構成です。我々の業務の特性上、若干、セキュリティや耐障害性に重点が置かれていて、大量アクセスや負荷の大幅な変動への対処は不足しているかもしれません。

AWS初心者の方は、これを動かしてみて、各サービスがどこでどのように使われているのか確認していけばよい勉強になると思います。

AWSをよくご存知の方は、以上のようなポリシーや重視する項目に異存がなければ、構築、運用を大幅に省略可できる便利ツールとなるでしょう。

我々は、Barcelona を継続的に日々の運用に使っていますが、Barcelona は、初期設定用のツールとしてのみ使うことも可能です。これは、意図的に、「いつでも捨てられるツール」であることを目指しているからです。つまり、Barcelona にはランタイムはなくて、構築後の運用は、AWS標準の Console や CLI だけで行なえるように設計してあるからです。

ですから、もし作成したシステムに足りない所があれば、それを自由に拡張、変更していくことも可能です。(その場合は、Barcelona による新しいバージョンの deploy やアプリケーションの追加はできなくなりますが、AWS 標準のツールによる運用は可能です)

Mastodon は、ECS や Barcelona を重要な業務に適用する前の練習としては、非常に適していると思います。今の時点では、会社の命運を左右する重要なシステムにはならないし、それなりの適度なトラフィックは期待できるからです。

ぜひ、このチュートリアルを活用して、Barcelona を試してみてください。

なお、Barcelonaのサポートを目的とした Mastodon インスタンスを8月まで起動しています。

この記事に興味を持たれた方は、ぜひ参加してみてください。

一緒にユニークな決済サービスを作ってくれる Rails エンジニアを募集中です!
多国籍なメンバーと一緒に仕事をしてみませんか?詳細はこちらのリンクです:D