WordPress環境をECS+RDSの環境に変更を試みたので備忘その1(ECSで環境が起動するまで)

EC2 on Dockerの環境から変えようと思い立つ

3月にAmazon Linux2023に環境を変更し2ヶ月が経とうとしております。

Amazon Linux2023自体が大きく問題ということではなさそうですが、移行後に断続的にトラブルが起きていました。
5から10分程度の時間ですが、不定期にサイトに接続ができなくなっているようで通知などで気がついて環境を確認しようと思うとすでに復帰してしていたりという感じしたが証跡や通知メッセージを見る限りではこれと言って突然高アクセスが発生したり不明な通信があったりはないらしく、Amazon Linux2から機能や処理を増やしたりはしておらずDockerの稼働自体でなんらかのI/O待ちでボトルネックが発生しているような気がします。
もう少しいろいろと仕込んで当たればわかるんでしょうか、結局のところ切り分け切れていないです。
致命的にCPUが張り付き続けたりコンテナ自体が落ちたりとか、OSがダンマリになってオートスケールでのリカバリが発生するでもない生○しな状態でした。

そもコンテナはステートレスなものに限った方が良い

と言うことで悶々と答え探しをするよりは根本から改善してしまった方が早いじゃないかと言う結論に達しました。
元々、Dockerコンテナの環境にステートフルなデータストアの機能を担わせるのは考えものです。
これまでもDBコンテナでやらかしたのは一度や二度じゃないわけで抽象化されている分ハマるとリカバリに手こずるという具合です。
DBデータ自体は永続領域に持たせていても、オープンできくなったら意味がないです。
実際、過去にご紹介のコンテナ環境ではデータ層はRDSでステーフルな構成にしていたのでサボらずに基本に忠実に従った方がいざと言うときに無難なわけです。
今回はコンテナを稼働させるのにマネージドサービスを使えばクラウドで仮想マシンを使う必要もないでいっそサーバレスにしてOS層の面倒を見なくて済むようにしてみようかなとも思います。
と言うことで、下図のような構成にあらためることにしました。

こんなマネージドを使ったコンテナ構成にしてみようかと、

構成としてはこんな感じ

  • コンテナ Amazon ECSをFargate構成にしてコンテナ実行環境は意識しない作りに改める
  • DBをRDSに改めてデータの保全、トラブル時の復帰の利便性を高める
  • とりあえずコスト重視でRDSはマルチAZ構成にはせず、何かあればバックアップから復元して対応
  • 今まで通りデータ永続領域はESFで行う
  • EC2 on Dockernの既存環境からの切り替えはRoute 53のAレコード変更だけで行う。
  • CloudWatch、WAF、S3は継続して利用

環境移行の準備

EC2 on Docke環境のバックアップ

まずは現行環境の移行データ退避から始めます。
現在の環境はWordpressコンテナとMySQLコンテナをdocker-composeで制御しています。
EFSに永続領域を設けていますが今回、VPCから新設しようと思うのでEFSも新しいVPCに新たに作成するので必要なデータをtarで固めてS3に退避します。
MySQLはコンテナに入り、mysqldumpを出力して永続領域側からS3に退避します。

 $ docker-compose exec 【コンテナ名】 /bin/bash
 # cd /var/lib/mysql
 # mysqldump -u 【ユーザ名】 -p -x 【DB名】 > 【出力ファイル】

VPCの作成

今回はパブリックサブネットを二つ、プライベートサブネットを二つの構成とします。
ALB、EFS、RDS接続用SGを用意しますが、そもそもマネコンからVPCを作成するのが久しぶりで随分画面が変わっていて新鮮でした。というか、プレビューが大変わかりやすいです。

CIDRや名前などは左のVPCの変更で設定してきますが今回目的の構成はデフォルトで作成されます。
パブリックサブネットを前提とするとインターネットゲートウェイが、プライベートサブネットを前提にするとS3のVPCエンドポイントが自動で用意されるようになってるようです。

RDSの作成

前回はPostgreSQLでしたが今回はMySQLを使います。

DBサブネットグループの作成

RDSはプライベートサブネットに配置します。それ用にサブネットグループを作成。

項目設定
名前【任意の名前】※1
説明任意で入力、省略可能
VPC作成したVPCを選択
アベイラビリティゾーン(AZ)ap-southeast-1a,ap-southeast-1c
サブネット上記AZに作成したプライベートサブネットを選択
※1 英数字、スペース、ハイフン、アンダースコア、ピリオド利用可能

RDSを作成

続いてRDSを作成します。
今回は無料枠が利用したいのでAuroraではなくRDS for MySQLで作成します。
コスト優先でトラブル時はスナップショットから戻すことを前提にシングルAZ構成とします。
以下設定したらデータベースの作成を押下する。

項目設定
データベース作成方法標準作成
エンジンのオプションMySQL
エディションMySQL Community
エンジンバージョンMySQL 8.0.32 ※1
テンプレート無料利用枠
DBインスタンス識別子【任意の名前】※2
AWS Secrets Manager で
マスター認証情報を管理する
チェックしない
マスターパスワード任意、もしくは自動生成にチェック
(自分は移行元DBと同様にしました)
Amazon RDS Optimized Writesチェックしない
インスタンスタイプdb.t4g.micro
ストレージタイプ汎用 gp3
ストレージ割り当て20GiB
ストレージの自動スケーリングを有効にするチェックする
最大ストレージしきい値1000GiB
コンピューティングリソースEC2 コンピューティングリソースに接続しない
ネットワークタイプIPv4
Virtual Private Cloud (VPC)作成したVPCを選択
DB サブネットグループ作成したDBサブネットグループ
パブリックアクセスなし
VPC セキュリティグループ (ファイアウォール)既存の選択
既存の VPC セキュリティグループ作成しRDS用セキュリティグループ
アベイラビリティーゾーンap-southeast-1a
RDS Proxy を作成チェックしない
認証機関 - 任意デフォルト
データベース認証パスワード認証
拡張モニタリングの有効化チェックを入れる
詳細度60秒
モニタリングロールデフォルト
追加設定
最初のデータベース名移行元DBと同じ名前
DB パラメータグループdefault.mysql8.0
オプショングループdefault:mysql-8-0
自動バックアップを有効にしますチェックを入れる
バックアップ保存期間コスト優先でとりあえず1日に設定
バックアップウィンドウィンドの選択
開始時間 期間16:00(UTC) 0.5時間 ※3
バックアップのレプリケーションチェックしない
暗号化を有効チェックを入れる
AWS KMS キーデフォルト
ログのエクスポート全てチェックを入れる
マイナーバージョン自動アップグレードの有効化チェックを入れる
メンテナンスウィンド設定なし
削除保護の有効化チェックを入れない
(一連の確認ができたら有効化)
※1 作成時点の最新
※2 英数字またはハイフン 60文字以内 1 字目は文字である必要あり
※3 日本時間 1:00 にバックアップ 取得時間30分以内を想定

ESFの作成

EFSの作成を選択後、ファイルの作成のウィンドが表示されたらカスタマイズをクリックします。

以下のように設定し、最後の確認画面で内容を確認後に「作成」をクリックします。

全般
名前-オプション【任意の名前】英数字またはハイフン
ストレージクラス標準
自動バックアップを有効化チェックを付ける
IAへ移行最後のアクセスから30日
IAから移行初回アクセス時
保管時のデータの暗号化を有効にするチェックを付ける
パフォーマンス設定
スループットモードバースト
ネットワーク
Virtual Privater Cloud(VPC)作成したVPCを選択
マウントターゲット
アベイラリティゾーンap-northeast-1a、ap-northeast-1c
サブネットID作成したプライベートサブネットを選択
IPアドレス自動
セキュリティグループ作成したEFS用セキュリティグループを選択
ファイルシステムポリシー - オプション何もせずに「次へ」をクリック

以下のように作成されます。ファイルシステムID、「fs-xxxxxx」は後のECSの設定で必要になります。

名前もしくはファイルシステムIDのリンクをクリックすると詳細が確認できます。

ECSの作成

Amazon Elastic Container Service(ECS)の設定をしていきます。過去、EKSで痛い目(お金的な意味で)をみてトラウマで避けてきましたが、今回はECSでしかもFargate利用。事前にcalculatorで金額シュミレーションして安全圏なのは確認済です。ECSの作成は以下のように進めます。

  1. クラスタ定義:ざっくりとコンテナ環境の大枠の定義
  2. タスク定義:コンテナの利用リソース、利用イメージなどの定義。今までのdocker-compose.ymlに相当
  3. サービス定義:起動環境(EC2 or Fargate)の設定、コンテナの実行数、Auto Scalingの設定、ELBとの関連付定義など

クラスタ定義

ECSのサービス画面からクラスターの作成を選択します。

以下の設定を行い「作成」をクリックしてクラスタ定義を作成します。

クラスタ名【任意のクラスタ名】※1
ネットワーキング
VPC作成したVPCを選択
サブネット作成したパブリックサブネットを選択
(ap-northeast-1a,ap-northeast-1cのパブリックサブネット二つ)
デフォルトの名前空間 - オプション何もしない
インフラストラクチャ何もしない
(グレーアウトで AWS Fargate(サーバレス)が選択された状態)
※1 最大文字数は 255 文字です。有効な文字は、文字 (大文字と小文字)、数字、ハイフン、アンダースコア

タスク定義

クラスタ作成後、タスク定義の画面に移動し「新しいタスク定義の作成」をクリックします。

以下を設定し、設定確認画面まで進んだら「作成」をクリックしてタスク定義を作成します。
今回は今までの環境同様、docker hubのイメージを利用することを前提にします。

タスク定義ファミリー任意のファミリー名※1
コンテナ - 1
コンテナの詳細
名前任意の名前
イメージURIwordpress:latest
プライベートレジストリ有効化しない
ポートマッピング
コンテナポート80
プロトコルTCP
ポート名【自動で生成されたものを利用】
アプリケーションプロトコルHTTP
環境変数 - オプション
環境変数を追加コンテナ環境変数を参照
環境、ストレージ、モニタリング、タグの設定
環境
アプリケーションの環境AWS Fargate(サーバレス)
オペレーションシステム/アーキテクチャLinux/ARM64※2
タスクサイズ
CPU1vCPU
メモリ3GB
タスクロール-
タスク実行ロールecsTaskExecutionRole
ネットワークモードawsvpc
ストレージ-オプション
エフィメラルストレージ
21 GiB
Volumes
ボリュームの追加クリックする
ボリュームタイプEFS
ストレージ設定
ボリューム名作成したEFSの名前を設定
ファイルシステムID作成したEFSのファイルシステムIDを設定
ルートディレクトリ/
アクセスポイント ID-
コンテナマウントポイント
コンテナコンテナの詳細の名前で定義したコンテナ名を選択
ソースボリュームストレージ設定のボリューム名を選択
コンテナパス/var/www/html
読み取り専用いいえ
モニタリングとログ記録 
ログ収集の使用チェックを付ける
※1 最大 255 文字の英字 (大文字と小文字)、数字、ハイフン、アンダースコア
※2 現環境がARMなので合わせただけです、Linux/x86でも問題ありません

コンテナ環境変数

WORDPRESS_DB_USER以降の値は https://api.wordpress.org/secret-key/1.1/salt/ こちらで生成したセキュリティキーの値を設定します。
コンテナが自動的に増減した時に、キーがリセットされてユーザが再ログインを求められないようにするための措置です。
URLをクリックすると、以下のような形式で表示されます。
【表示例】

define('AUTH_KEY',         '<|b9]fh#f-&b+q|o!8.L4KAd&d}.g^n;z8ct8}7Yi+Tqe+K&Q>/G(QD.Nywa[{zc');

上記の表示の場合、環境変数は以下のように入力をします。注意点としては' '(シングルコート)で囲むことです。

'<|b9]fh#f-&b+q|o!8.L4KAd&d}.g^n;z8ct8}7Yi+Tqe+K&Q>/G(QD.Nywa[{zc'

キータイプ
WORDPRESS_DB_HOSTvalue作成したRDSのエンドポイントを記載
WORDPRESS_DB_NAMEvalue作成したRDSのEB名を記載
WORDPRESS_DB_PASSWORDvalueRDSで設定したパスワードを記載
WORDPRESS_DB_USERvalueRDSで設定したユーザ名を記載
WORDPRESS_AUTH_KEYvalue生成したキーを記載
WORDPRESS_AUTH_SALTvalue生成したキーを記載
WORDPRESS_LOGGED_IN_KEYvalue生成したキーを記載
WORDPRESS_LOGGED_IN_SALTvalue生成したキーを記載
WORDPRESS_NONCE_KEYvalue生成したキーを記載
WORDPRESS_NONCE_SALTvalue生成したキーを記載
WORDPRESS_SECURE_AUTH_KEYvalue生成したキーを記載
WORDPRESS_SECURE_AUTH_SALTvalue生成したキーを記載

サービス定義

作成したクラスターからービスタグを選択し、「作成をクリック」します。

以下を設定し「作成」をクリックします。

環境
既存のクラスター作成したクラスター
コンピューティング設定((アドバンスト))起動タイプ
起動タイプFARGATE
プラットフォームのバージョンLATEST
デプロイ設定タスク
タスク定義
リビジョンの手動指定チェックを入れる
ファミリー作成したタスク定義を選択
リビジョン1 ※1
サービス名任意の名前
サービスタイプレプリカ
必要なタスク0 ※2
ネットーワーキング
VPC作成したVPC
サブネットパブリックサブネットを選択
(ap-northeast-1a、ap-northeast-1c)
セキュリティグループ既存のセキュリティグループを選択
セキュリティグループ名作成したセキュリティグループ全てを適用
パブリックIPオフになっています
ロードバランシング - オプション
ロードバランサーの種類Application Load Balancer
Application Load Balancer新しいロードバランサの作成
ロードバランサー名任意の名前
ロードバランス用のコンテナの選択【コンテナ名】80:80
リスナー
新しいリスナーを作成チェックを付ける
ポート80
プロトコルHTTP
ターゲットグループ
新しいターゲットグループの作成チェックを付ける
ターゲットグループ名任意の名前
プロトコルHTTP
ヘルスチェックパス/
プロトコルHTTP
ヘルスチェックの猶予期間0 ※3
サービスの Auto Scaling - オプション後で設定するためここでは設定しない
※1 初回作成であれば1、以降タスク定義のリビジョンを変えた場合は適用したいリビジョンをサービスの更新で指定する
※2 作成直後に起動しないように、0を定義しておく後ほど、サービスの更新で必要な起動数を設定する
※3 タイムアウトとインターバルはターゲットグループのデフォルトが採用される

コンテナ起動前にALBの追加設定

サービスを作成しても必要なタスクを0にしてあるためコンテナは起動しない状態です。
起動前にALBのターゲットグループのSuccess codesを追加します。
EC2サービスの画面に移動し、ターゲットグループを選択しHealth checksタブを選択後、Editをクリックします。

Advanced health check settingsのSuccess codesに「,301-302」を追加します。
コンテナの初期起動が完了したら後ほど302は削除します。

コンテナの起動と確認

準備が完了したらECSサービスの画面に移動しクラスターから作成したクラスタを選択します。
サービスタブを選択し、作成したサービスをチェックしたら「更新」をクリックします。
デプロイ設定の必要なタスクに1を入れて更新をクリックします。

更新後、サービスをクリックし正常性とメトリクスのステータスを確認します。
正常であれば、タスクが保留後、画面のように「1件が実行中」となります。
またALBのターゲットも「1件が正常」となります。
起動が正常に行われない場合、セキュティグループの設定と必要なリソース適用されいるかなどを確認してください。問題が出る場合は概ね適切なリソースと通信ができないパターンが多いです。

EC2サービス画面のターゲットグループでコンテナがターゲットとして登録されたことを確認します。

ALBのAレコード情報を確認します。
セキュティグループで一時的に80の接続を許可し、ブラウザから確認したAレコードで接続を確認します。

WordPressの初期設定画面が表示されれば成功です。
一旦、ECSのコンテナ環境としては起動が成功となります。

この後の設定

今回はコンテナ環境として正常に起動までの確認ですが、確認後は以下を実施が必要になります。
これらの備忘は次回に紹介します。

  1. 作業端末としてAWS Cloud9作成
  2. RDSへの dumpデータインポート
  3. EFS領域への既存環境データの移行
  4. 既存ALBの設定を新ALBに追加
  5. 新ALBにWAF適用
  6. ECSのAuto Scaling設定
  7. Route53のレコード修正を行いECS環境に切り替え