スポンサーリンク

AWSのCloudFormationでマルチAZなWordPressを構築する(EFS)

WordPressのuploadsディレクトリを複数のEC2インスタンスで共有するために前回はS3をgoofysでマウントするという方法で解決しました。今回はElastic File System(以後EFS)というAWSのサービスを使った場合のテンプレート作成を行いました。

EFSについて

EFSを使うにあたって以下のタイプのリソースの作成が必要です。

  • AWS::EFS::FileSystem
    • 大元のEFSリソース
  • AWS::EFS::MountTarget
    • 大元のEFSリソースに1:nで紐づけるリソース
    • アベイラビリティゾーンごとに紐づけるサブネットを1つ選択して作る

AWS::EFS::FileSystemリソースはRefでマウントを行う際に使用するファイルシステムIDという値を返します。EC2インスタンスを立ち上げる際のスクリプト内で以下のようなmountコマンドと組み合わせて使用します。

"mount -t efs ",
{
    "Ref": "ElasticFileSystem"
},
":/ /var/www/html/",
{
    "Fn::If": [
        "WordPressInstallDirectoryNameIsEmpty",
        "",
        {
            "Fn::Join": [
                "",
                [
                    {
                        "Ref": "WordPressInstallDirectoryName"
                    },
                    "/"
                ]
            ]
        }
    ]
},
"wp-content/uploads\n",

NGパターン(サブネットとマウントターゲットの数が合わない件)

スタックを構築する時に入力パラメータで選択したサブネットに対応したマウントターゲットを作らないとけないのですが、サブネットは複数個選択できるのに対して、作成するリソースを可変にすることができませんでした。
私のAWSアカウントのデフォルトVPCには3個のサブネットが存在しているので最大で3つのサブネット上にインスタンスを構築することが出来ます。が、リソースとしてEFSマウントターゲットを1つしか作っていなかったため、マウントターゲットが作られなかったアベイラビリティゾーンに所属するインスタンスからのEFSマウントが行えない状態になってしまいました。

以下がNGパターンのテンプレートになります。一応パラメータの入力画面でサブネットの選択数とEFSマウントターゲットの個数が一致すれば正常にスタックが作成できると思います。
マウントターゲットが固定で1個:aws-cloudformation-templates/wordpress_efs.json at fae2c9a3a9009cc3f639ccb570f0e1f2b170fbfa
マウントターゲットが固定で2個:aws-cloudformation-templates/wordpress_efs.json at 7a9d0951b2e2ed1f0141400f40ab44cfb1fb1076

上記の「マウントターゲットが固定で1個」のテンプレートを使用して以下のようなパラメータで作りました。今回はどのように失敗してしまうのかを確認するため、サブネットのリスト項目でap-northeast-1cとap-northeast-1dの2つのサブネットを選択しています。

スタックの構築が完了した状態でそれぞれのインスタンスにSSH接続してdfコマンドを叩いてみたところの様子です。左側がap-northeast-1dで右側がap-northeast-1cになります。
ap-northeast-1cの方のみEFSのマウントが通っていることがわかります。

テンプレート内でEFSMountTarget1リソースのSubnetIdプロパティに対してサブネットパラメータで1つ目に選択したサブネットIDを指定しているため、2つ目の選択値となったap-northeast-1dに関連付いたマウントターゲットが作れませんでした。

このような問題を解決するためにスタックを作成するときにVPCとサブネットを新規作成することにしました。


以下は、手動でEFSのファイルシステムにap-northeast-1d用のマウントターゲットを追加してみたときの様子。

ap-northeast-1d用のマウントターゲットを追加したことで先ほどマウントに失敗したインスタンスでも一応EFSをマウントできることは確認できました。

VPC、サブネットを新規作成してから各リソースを作成する

新規作成するVPCには2つのパブリックサブネットを作成し、それぞれに対応したEFSマウントターゲットを作成します。
VPCとサブネットのパラメータは不要となるので削除し、Refで参照している箇所を書き換えました。
VPC、サブネットを作成するテンプレートはこちらの記事を参考にさせていただきました。
参考:CloudFormationを使ってVPCを構築する – Qiita
プライベートサブネットは今回使わないのでその辺は削りました。

デザイナー画面で出力してみたスタックの構成図は以下のようになりました。正直矢印だらけでよくわからないです(^q^

完成したテンプレートは以下になります。
VPCから新規作成するテンプレート:aws-cloudformation-templates/wordpress_efs.json at ee5faa7a3306d0d5c65b38a45ad6f03d1fd2006a

パラメータ画面からVpcIdとSubnetsが消えて以下のようになりました。

作成が完了したときのイベントの状況は画像だと1つにまとまらないくらい長くなってしまってたのでテキストをコピーしてみました。
約12分ほどで構築に完了していることがわかりました。やはりRDSの構築が微妙に長い。

タイムスタンプ	論理 ID	ステータス	状況の理由
2019-11-17 21:43:27 UTC+0900	teststack	CREATE_COMPLETE	-
2019-11-17 21:43:24 UTC+0900	WebServerGroup	CREATE_COMPLETE	-
2019-11-17 21:43:23 UTC+0900	WebServerGroup	CREATE_IN_PROGRESS	Received SUCCESS signal with UniqueId i-0aedf452f085ac537
2019-11-17 21:43:23 UTC+0900	WebServerGroup	CREATE_IN_PROGRESS	Received SUCCESS signal with UniqueId i-0b2bc5a774ce4fdda
2019-11-17 21:42:00 UTC+0900	WebServerGroup	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:41:59 UTC+0900	WebServerGroup	CREATE_IN_PROGRESS	-
2019-11-17 21:41:53 UTC+0900	LaunchConfig	CREATE_COMPLETE	-
2019-11-17 21:41:52 UTC+0900	LaunchConfig	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:41:52 UTC+0900	LaunchConfig	CREATE_IN_PROGRESS	-
2019-11-17 21:41:47 UTC+0900	DBInstance	CREATE_COMPLETE	-
2019-11-17 21:36:49 UTC+0900	EFSMountTargetC	CREATE_COMPLETE	-
2019-11-17 21:36:48 UTC+0900	EFSMountTargetA	CREATE_COMPLETE	-
2019-11-17 21:35:18 UTC+0900	DBInstance	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:35:17 UTC+0900	EFSMountTargetC	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:35:17 UTC+0900	EFSMountTargetA	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:35:16 UTC+0900	DBInstance	CREATE_IN_PROGRESS	-
2019-11-17 21:35:16 UTC+0900	EFSMountTargetC	CREATE_IN_PROGRESS	-
2019-11-17 21:35:16 UTC+0900	EFSMountTargetA	CREATE_IN_PROGRESS	-
2019-11-17 21:35:12 UTC+0900	EFSSecurityGroup	CREATE_COMPLETE	-
2019-11-17 21:35:12 UTC+0900	DBEC2SecurityGroup	CREATE_COMPLETE	-
2019-11-17 21:35:11 UTC+0900	DBEC2SecurityGroup	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:35:11 UTC+0900	EFSSecurityGroup	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:35:06 UTC+0900	DBEC2SecurityGroup	CREATE_IN_PROGRESS	-
2019-11-17 21:35:05 UTC+0900	EFSSecurityGroup	CREATE_IN_PROGRESS	-
2019-11-17 21:35:01 UTC+0900	WebServerSecurityGroup	CREATE_COMPLETE	-
2019-11-17 21:35:00 UTC+0900	WebServerSecurityGroup	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:34:55 UTC+0900	ALBListener	CREATE_COMPLETE	-
2019-11-17 21:34:55 UTC+0900	ALBListener	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:34:55 UTC+0900	WebServerSecurityGroup	CREATE_IN_PROGRESS	-
2019-11-17 21:34:55 UTC+0900	ALBListener	CREATE_IN_PROGRESS	-
2019-11-17 21:34:51 UTC+0900	ApplicationLoadBalancer	CREATE_COMPLETE	-
2019-11-17 21:32:34 UTC+0900	PublicSubnetCRouteTableAssociation	CREATE_COMPLETE	-
2019-11-17 21:32:34 UTC+0900	PublicSubnetARouteTableAssociation	CREATE_COMPLETE	-
2019-11-17 21:32:20 UTC+0900	DBSubnetGroup	CREATE_COMPLETE	-
2019-11-17 21:32:20 UTC+0900	DBSubnetGroup	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:32:19 UTC+0900	DBSubnetGroup	CREATE_IN_PROGRESS	-
2019-11-17 21:32:19 UTC+0900	PublicSubnetCRouteTableAssociation	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:32:19 UTC+0900	ApplicationLoadBalancer	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:32:18 UTC+0900	PublicRouteA	CREATE_COMPLETE	-
2019-11-17 21:32:18 UTC+0900	PublicRouteC	CREATE_COMPLETE	-
2019-11-17 21:32:18 UTC+0900	PublicSubnetARouteTableAssociation	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:32:18 UTC+0900	PublicSubnetCRouteTableAssociation	CREATE_IN_PROGRESS	-
2019-11-17 21:32:17 UTC+0900	ApplicationLoadBalancer	CREATE_IN_PROGRESS	-
2019-11-17 21:32:17 UTC+0900	PublicSubnetARouteTableAssociation	CREATE_IN_PROGRESS	-
2019-11-17 21:32:14 UTC+0900	PublicSubnetC	CREATE_COMPLETE	-
2019-11-17 21:32:14 UTC+0900	PublicSubnetA	CREATE_COMPLETE	-
2019-11-17 21:32:13 UTC+0900	InternetGatewayAttachment	CREATE_COMPLETE	-
2019-11-17 21:32:05 UTC+0900	ElasticFileSystem	CREATE_COMPLETE	-
2019-11-17 21:32:04 UTC+0900	ALBSecurityGroup	CREATE_COMPLETE	-
2019-11-17 21:32:03 UTC+0900	PublicRouteA	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:32:03 UTC+0900	PublicRouteC	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:32:02 UTC+0900	PublicRouteA	CREATE_IN_PROGRESS	-
2019-11-17 21:32:02 UTC+0900	ALBSecurityGroup	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:32:02 UTC+0900	PublicRouteC	CREATE_IN_PROGRESS	-
2019-11-17 21:31:58 UTC+0900	PublicRouteTableA	CREATE_COMPLETE	-
2019-11-17 21:31:58 UTC+0900	PublicRouteTableC	CREATE_COMPLETE	-
2019-11-17 21:31:58 UTC+0900	ALBTargetGroup	CREATE_COMPLETE	-
2019-11-17 21:31:57 UTC+0900	PublicSubnetA	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:31:57 UTC+0900	ALBTargetGroup	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:31:57 UTC+0900	PublicSubnetC	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:31:57 UTC+0900	InternetGatewayAttachment	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:31:57 UTC+0900	PublicRouteTableC	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:31:57 UTC+0900	PublicRouteTableA	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:31:57 UTC+0900	ALBSecurityGroup	CREATE_IN_PROGRESS	-
2019-11-17 21:31:57 UTC+0900	PublicSubnetA	CREATE_IN_PROGRESS	-
2019-11-17 21:31:57 UTC+0900	InternetGatewayAttachment	CREATE_IN_PROGRESS	-
2019-11-17 21:31:57 UTC+0900	ALBTargetGroup	CREATE_IN_PROGRESS	-
2019-11-17 21:31:57 UTC+0900	PublicRouteTableC	CREATE_IN_PROGRESS	-
2019-11-17 21:31:57 UTC+0900	PublicSubnetC	CREATE_IN_PROGRESS	-
2019-11-17 21:31:57 UTC+0900	PublicRouteTableA	CREATE_IN_PROGRESS	-
2019-11-17 21:31:53 UTC+0900	NewVPC	CREATE_COMPLETE	-
2019-11-17 21:31:51 UTC+0900	InternetGateway	CREATE_COMPLETE	-
2019-11-17 21:31:36 UTC+0900	NewVPC	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:31:35 UTC+0900	NewVPC	CREATE_IN_PROGRESS	-
2019-11-17 21:31:35 UTC+0900	InternetGateway	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:31:35 UTC+0900	ElasticFileSystem	CREATE_IN_PROGRESS	Resource creation Initiated
2019-11-17 21:31:35 UTC+0900	InternetGateway	CREATE_IN_PROGRESS	-
2019-11-17 21:31:34 UTC+0900	ElasticFileSystem	CREATE_IN_PROGRESS	-
2019-11-17 21:31:29 UTC+0900	teststack	CREATE_IN_PROGRESS	User Initiated

作成されたVPCについて確認。
Nameタグを入れるようにしたので少し見やすくなったような気がします。

サブネットは以下の通り。新規作成されたVPCと紐づいていることがわかります。

次にEFSリソースについて確認。作成されたサブネットとそれぞれ紐づいたマウントターゲットが作られていることがわかります。

画面の方は問題なく動作することを確認。
マウント中のuploadsディレクトリも正常に稼働している模様。

RLoginでSSH接続しての確認。
dfコマンドでEFSファイルシステムがマウントできていることを確認しました。
動作確認として左側でhogeファイルを作って、右側で中身を確認しました。
また、WordPressの管理画面で画像をアップロードして両方のインスタンスから参照できることを確認しました。

まとめ?

今回のEFSを使ったパターンはS3,goofysを使ったパターンよりも正しくAWSのサービスを使えているような気がする。
費用的なところがちょっとよくわかってない。以下の見積ツールでざっと調べてみた感じ数GB程度だと料金が変わりませんでした( ・`ー・´)??
参考:Amazon Web Services Simple Monthly Calculator

EFSでもS3も使用せずに、スケーリングしないEC2を1個立ててnfsサーバーを構築し共有するというパターンについてもそのうち書こうと思います。

その他(EC2のメタデータについて)

EC2インスタンス内からインスタンスのメタ情報を取得するhttp://169.254.169.254~~が便利でした。
参考:【小ネタ】EC2のインスタンスメタデータからリージョンを取得する | Developers.IO
今回は2つのインスタンスに接続した状態でそれぞれどのアベイラビリティゾーンに所属してるかを表示するのに使用しました。

EC2インスタンス内で自身のパブリックDNS名を取得して何らかのファイルに設定したい、みたいなケースのときにRefで参照すると循環参照となってしまいスタック作成時にエラーとなってしまいます。こういったときにメタデータをcurlで取得すると良いのかなーと思いました。
以下はwp-cliを使ってWordPressのインストールを行う際に–urlパラメータに指定するDNS名をメタデータから取得して設定してみたときのサンプルコードになります。

"sudo -u apache /usr/local/bin/wp core install --title='",
{
    "Ref": "WordPressSiteName"
},
"' --admin_user='",
{
    "Ref": "WordPressAdminUser"
},
"' --admin_password='",
{
    "Ref": "WordPressAdminPass"
},
"' --admin_email='",
{
    "Ref": "WordPressAdminEmail"
},
"' --url=\"https://$(curl -s http://169.254.169.254/latest/meta-data/public-hostname)/",
{
    "Ref": "WordPressInstallDirectoryName"
},
"\"\n",

その他(WordPressのアップデートについて)

WordPressが5.3にアップデートされたことが原因か、セキュリティSALTの辺りの自動設定処理がうまく行かなくなってしまいました。。
調べてみたとこdefine()の括弧内の前後に半角スペースが入るようになったことが原因でした。

sedによる置換処理を微修正して、プッシュしていますので今回のテンプレートを使ってみたい方がいらっしゃいましたらGitHubから最新のソースを取得するか以下のリンクからどうぞ。
SALTキーのとこ修正したやつ:aws-cloudformation-templates/wordpress_efs.json at f69d31b2fc199855f6bd0856ad9c5c50e3aefb3a

タイトルとURLをコピーしました