はじめに
「大人の事情でSlackが使えない」という話をよく聞きます、うちの会社も例外ではなく同じ悩みを抱えておりRocket.Chatを使っています。前回は、AWS EC2にパッケージインストールしていたものをDocker Containersへ移行した。先日(Apr 8,2020)Fargateのプラットフォームバージョン1.4がリリースされ、コンテナにEFSをマウント出来る(EFSエンドポイントをサポート)様になったので思い切ってFargateに移行してみた。
Fargate タスクが Amazon Elastic File System (EFS) エンドポイントのサポートを開始
プラットフォームバージョン 1.4.0 を使用して、永続的な EFS ストレージで Fargate タスクを起動できるようになりました。この新機能は、Fargate タスク内に EFS ボリュームをマウントすることで、データの永続性と共有ストレージを必要とするアプリケーションを有効化します。お客様は、コンテンツ管理システム (WordPress や Drupal など) や共通のデータセットを共有するアプリケーションなどのアプリケーションを Fargate に移行できるようになりました。
モチベーション
- 個人的な趣味と学習のため。
- 社員が何気なく使っている環境でコッソリ遊んで反応を見てやるぜ。
- もう俺しか運用出来なくなるけど、どうなっても知らないぜ。
Rocket.Chatの構成
-
利用用途
社員(約50名)のコミュニケーションツール。 -
移行前(Docker on EC2)
[internet]--[EC2(Docker)] -
移行後(Fargate)
[internet]--[ALB]--[Fargate(Container)]
移行の流れ
- Fargeteクラスター作成
- セキュリティグループ作成
- ALB作成
- EFSファイルシステムを作成
- タスク定義を作成
- データ移行
- DNSの登録(ここから移行前のRocket.Chatは停止)
- サービスの作成と実行
- 起動確認
移行手順
1. Fargeteクラスター作成
後でもいいけど、はやる気持ちを押さえきれないので、先ずはFargateクラスターを作成。
ⅰ)Fargateコンソールから作成
移行作業を楽にするため移行前のRcoket.Chatと同じリージョンで。
ⅱ)クラスターテンプレートの作成
「ネットワーキングのみ(AWS Fargate を使用)」を選択
ⅲ)クラスターの設定
適当なクラスター名を入力。
今回は「VPCの作成」のチェックは外したまま。
(移行じゃ無くて新規にRocket.Chatを構築する場合はこの手順で作成しておいた方が楽かも)
「CloudWatch Container Insights」は有効にしておく。
ⅳ)クラスターの作成完了
2. セキュリティグループ作成
今回構築する環境に適用するセキュリティグループを3つ作成しておく。
ⅰ)rocketchat-alb(ALBに適用するグループ:インターネット公開用)
検証だけならHTTP(TCP/80)でも良いかも。
ソースは全ての送信元から許可。
ⅱ)rocketchat-fargate(Fargateに適用するグループ:ALBからの振分け用)
ソースは「rocketchat-alb」セキュリティグループから許可。
ⅲ)rocketchat-efs(EFSに適用するグループ:Fargateからのマウント用)
ソースは「rocketchat-fargate」セキュリティグループから許可。
3. ALB作成
コンテナにはパブリックIP割当てが出来るので、そのままでもインターネットからアクセス可能。
でも、EIP(固定)は設定できないのでコンテナ起動の度にパブリックIPは都度変わるのでロードバランサーを使う。なお、Fargateは、ALBおよびNLBのみサポートとのこと。(詳しくはココ)
ⅰ)EC2コンソールから作成
ⅱ)Application Load Balancerを選択
ⅲ)ロードバランサーの設定
入力項目は環境に応じていい感じに設定。
「ロードバランサーのプロトコル」は「rocketchat-alb」セキュリティグループで設定したポート。
VPCやアベイラビリティーゾーン(サブネット)は移行前のRcoket.Chatと同じもの。
ⅳ)セキュリティ設定の構成
リスナーにHTTPSを選択した場合はサーバ証明書の選択が必要なので、あらかじめACMで作成しておいた証明書を使う。HTTPなら必要ないかもしれないけど、セキュリティ警告メッセージが出たりする。セキュリティポリシーは社内システムなので適当に最強にしておいた。
ⅴ)セキュリティグループの設定
前の手順で作成しておいた「rocketchat-alb」を選択。
ⅵ)ルーティングの設定
入力項目は環境に応じていい感じに設定すればいいけど、ターゲットの種類は「IP」にする必要がある。
ここはちょっとハマった。(詳しくはココ)
ⅶ)ターゲットの登録
ここでは何もしない。
ⅷ)確認
ⅸ)作成完了
4. EFSファイルシステムを作成
以下の手順にて、アップロードしたファイルの保存用、MongoDBのデータ用の2個を作成しておく。
ⅰ)EFSコンソールからEFSを作成
ⅱ)ネットワークアクセスを設定する
VPCやアベイラビリティーゾーン(サブネット)は移行前のRcoket.Chatと同じもの。セキュリティグループは前の手順で作成しておいた「rocketchat-efs」を選択。
ⅲ)ファイルシステムの設定を行う
環境や好みに応じて設定。
ⅳ)クライアントアクセスを設定
環境や好みに応じて設定。
5. タスク定義を作成
ⅰ)Fargateコンソールから作成
ⅱ)起動タイプの選択
「FARGATE」を選択
ⅲ)タスクとコンテナ定義の設定
タスク定義名:適当
タスクロール:「なし」or「ecsTaskExecutionRole」
タスクの実行ロール:「ecsTaskExecutionRole」
タスクメモリ(GB):環境に応じて選択(0.5GBではメモリ不足のため起動しなかった気がする)
タスクCPU(vCPU):環境に応じて選択
なお、ecsTaskExecutionRoleが存在しない場合はこちらで作成しておく。
ⅳ)ボリュームの設定
コンテナの追加の前に一旦画面を下にスクロールしボリュームを追加しておく。
この作業をしておかないとコンテナからEFSをマウントできない。(2020/5/10:時点)
どうでもいいけど、AWSのUIってこう言うところ良くあるよね、結構気になります。
以下の手順にて、アップロードしたファイルの保存用、MongoDBのデータ用の2個を追加しておく。暗号化や認証は環境や好みに応じて設定。
- アップロードしたファイルの保存用
ⅴ)コンテナの追加
Rocket.Chatには3つのコンテナが必要です。
それぞれの設定内容(docker-compose.ymlとの相違点、ハマったポイント)を記載しておきます。
- rocketchat
コンテナ起動時の実行コマンドの書式が違うので、docker-compose.ymlからの単純コピペではエラーとなる。また、Docker Link機能が使えないので環境変数に定義するMONGOのURLはコンテナ名じゃなくて、127.0.0.1(localhost)を指定する必要がある。(詳しくはココ)。
"command": [
"bash",
"-c",
"for i in `seq 1 30`; do node main.js && s=$? && break || s=$?; echo \"Tried $i times. Waiting 5 secs...\"; sleep 5; done; (exit $s)"
],
- mongo
"command": [
"mongod",
"--smallfiles",
"--oplogSize",
"128",
"--replSet",
"rs0",
"--storageEngine=mmapv1"
],
- mongo-init-replica
コンテナの「環境」設定の「基本」パラメータのチェックを外しておく(false)。このコンテナは起動後すぐに停止するので、チェックが入っている(true)場合はコンテナの停止によりタスクも停止します。また、rocketchatコンテナの時と同じく、Docker Link機能が使えないのでコマンドに定義するmongoはコンテナ名じゃなくて、127.0.0.1(localhost)を指定する必要がある。あとは他と同じで実行コマンドの書式が違うところ。
"command": [
"bash",
"-c",
"for i in `seq 1 30`; do mongo 127.0.0.1/rocketchat --eval \"rs.initiate({ _id: 'rs0', members: [ { _id: 0, host: '127.0.0.1:27017' } ]})\" && s=$? && break || s=$?; echo \"Tried $i times. Waiting 5 secs...\"; sleep 5; done; (exit $s)"
],
6. データ移行
データ移行のやり方はいろいろあるけど、今回は移行前のRcoket.Chat(EC2)と同じVPC内に構築したので以下のやり方で実施。(新規にRocket.Chatを構築する場合は不要)
ⅰ)EFSに対し移行前のRcoket.Chat(EC2)からのマウントを許可する
EFSコンソールから「4. EFSファイルシステムを作成」で作成した2個それぞれのEFSの「ファイルシステムアクセスの管理」を選択。
セキュリティグループに移行前のRcoket.Chat(EC2)のセキュリティグループを追加する。今回の環境では「sg-00da03d099b4baf25 - default」です。
ⅱ)移行前のRcoket.Chat(EC2)にログイン
ⅲ)2個のEFSをマウント
手順は以下を参考。
ⅳ)dockerを停止(sudo docker-compose down)
ⅴ)「./data/db」を「<マウントポイント>/data/db」に丸ごとコピー
ⅵ)「./uploads」を「<マウントポイント>/app/uploads」に丸ごとコピー
ⅶ)2個のEFSをマウント解除
ⅷ)ⅰ)で追加したセキュリティグループを削除
7. DNSの登録
作成したALBのDNS名をRocket.ChatドメインのCNANEとして登録しておきます。なお、Rocket.ChatのドメインをAmazon Route 53で管理している場合は、ALIASレコードとして登録する方が良いです。(詳しくはココ)。これで、ALBのパブリックIPアドレスまで名前解決できるようになるはず。
8. サービスの作成と実行
いよいよ最後の手順です。
ⅰ)Fargateコンソールから作成
ⅱ)サービスの設定
プラットフォームのバージョンは明示的に「1.4.0」としなければならないようです。(2020/5/10:時点)後は、環境や好みに合わせて設定。
ⅲ)ネットワーク構成
VPCやアベイラビリティーゾーン(サブネット)は移行前のRcoket.Chatと同じもの。セキュリティグループは前の手順で作成しておいた「rocketchat-fargate」を選択。パブリックIPの自動割り当ては「ENABLED」としておく。
ヘルスチェックの猶予期間は「300」秒とした。
ロードバランサーの種類は「Application Load Balancer」を選択。ロードバランサー名は「RocketChat-ALB」(「3. ALB作成」で作成したALB名)
ターゲットグループも「3. ALB作成」で作成したALB名としておく。
Service Auto Scalingは「サービスの必要数を直接調整しない」を選択。
確認画面を経て、正常にサービスが作成された。
9.起動確認
起動後、しばらくするとコンテナのステータスが以下のようになる。
「Logs」タブにて3個のコンテナのログを確認。おおよそ、以下のようなログが出力されているはず。
- rocketchat
最後に
- ハマりにハマったが何とか移行できた。
- リソースを100%コンテナに割当てられるのでコストはトントンか?
- 信頼性についてはこれから検証。
- EFSをマウントすると「CloudWatch Container Insights」の値が取得できない。(2020/5/10:時点)
おしまい。