スポンサーリンク

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

CloudFormationを使ったWordPressスタックについておそらく最後の更新。

S3,goofysを使ったパターンEFSを使ったパターンNFSを使ったパターンの計3パターンでWordPressのスタック作成についてはやり切ったと思ってましたが、wp-cliでインストールしたプラグインのオプションの設定自体も行えることが分かっため、wp-cliでWordPressをインストール→S3連携用のプラグインをインストール→プラグインの設定を実施まで処理を自動化してみました。

wp-cliのインストールとそのためのパラメータ追加について

wp-cliでWordPressにプラグインをインストールするにはサイト名や管理者情報を入力する初回のセットアップを済ませておく必要があります。
スタック構築時のパラメータ項目としてサイト名と管理者のユーザー名、パスワード、メールアドレスの4項目を新規で追加しました。

上の画像のWordPressAdminEmail、WordPressAdminPass、WordPressAdminUser、WordPressSiteNameが追加されたパラメータです。サイト名はCloudFormationのパラメータに日本語を入力すると文字化けしてしまうため半角英数、半角スペースのみ入力可能としています。

"Parameters": {
~~~省略~~~
        "WordPressInstallDirectoryName": {
            "Description": "enter WordPress install directory name. If not entered, it will be installed directly under /var/www/html",
            "Type": "String",
            "Default": "wordpress"
        },
+        "WordPressSiteName": {
+            "Description": "enter WordPress site name.",
+            "Type": "String",
+            "AllowedPattern": "[a-zA-Z0-9 ]*",
+            "ConstraintDescription": "site name must contain only alphanumeric characters."
+        },
+        "WordPressAdminUser": {
+            "Description": "enter WordPress admin user. (min:4, max:32, alphanumeric)",
+            "Type": "String",
+            "MinLength": "4",
+            "MaxLength": "32",
+            "AllowedPattern": "[a-zA-Z0-9]*",
+            "ConstraintDescription": "admin user must contain only alphanumeric characters."
+        },
+        "WordPressAdminPass": {
+            "NoEcho": "true",
+            "Description": "enter WordPress admin pass. (min:8, max:32, alphanumeric)",
+            "Type": "String",
+            "MinLength": "8",
+            "MaxLength": "32",
+            "AllowedPattern": "[a-zA-Z0-9]*",
+            "ConstraintDescription": "admin pass must contain only alphanumeric characters."
+        },
+        "WordPressAdminEmail": {
+            "Description": "enter WordPress admin email.",
+            "Type": "String",
+            "AllowedPattern": "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$",
+            "ConstraintDescription": "admin mail address format is invalid."
+        }
    },

使用するS3連携プラグインについて

WP Offload Media Liteというプラグインを使用しました。

設定はS3フルアクセスが付いたIAMユーザーのアクセスキー、シークレットアクセスキーをwp-config.php内に所定の定数名でセットし、使用するS3バケットを管理画面で選択するだけ。
正確にはS3フルアクセスでなくてもいいのかもしれませんがちょっと調べた感じよくわからなかった;;
S3バケットの作成とIAMユーザーの作成自体はS3,goofysを使ったテンプレートの方で書いてるので今回はその辺は省略。

wp-cliでWordPressをインストール

最初にwp-cli自体のインストールを行い、apacheユーザーでwp core installコマンドによるWordPressのインストールを行っています。

"files": {
    "/tmp/create-wp-config": {
        "content": {
            "Fn::Join": [
                "",
                [
~~~省略~~~
                    "# wp-cli install and setting\n",
                    "mkdir -p /var/www/.wp-cli\n",
                    "chown apache: /var/www/.wp-cli\n",
                    "\n",
                    "curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar\n",
                    "mv wp-cli.phar /usr/local/bin/wp\n",
                    "echo export PATH='/usr/local/bin:$PATH' >> ~/.bashrc\n",
                    "chmod +x /usr/local/bin/wp\n",
                    "\n",
                    "# wordpress install.\n",
                    "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=\"http://",
                    {
                        "Fn::GetAtt": [
                            "ApplicationLoadBalancer",
                            "DNSName"
                        ]
                    },
                    "/",
                    {
                        "Ref": "WordPressInstallDirectoryName"
                    },
~~~省略~~~
                ]
            ]
        },
        "mode": "000500",
        "owner": "root",
        "group": "root"
    }
},

プラグインをインストールするときに/var/www/.wp-cliにインストールするプログラムをキャッシュする処理が働くようようになってたので、先にディレクトリを作成しています。ディレクトリを作成してなくてもアラートが出るだけでインストール自体は行えてたのでどっちでもいいのかも。
WordPressの本体は事前にAWS::CloudFormation::Initsourcesサービスで/var/www/html上に展開しているものがあるので、本体をダウンロードする処理は書きませんでした。
wp core installコマンドの–urlオプションで設定する値はwp_optionsテーブルのサイトURLを設定するのに使われるので必ずアクセス可能なURLを指定する必要がありました。

wp-cliでインストールするプラグインの名称とバージョンについて

wp-cliがインストールされている環境があるのであればwp plugin searchコマンドで調べられますが、そういった環境がない場合の調べ方。

  1. WordPress公式のプラグインを検索するページを開く
  2. wp-cliでインストールしたいプラグインを見つける
  3. プラグインの詳細画面を開いてURLをコピー
    1. 今回のS3連携用プラグインだと以下のURL
      ttps://ja.wordpress.org/plugins/amazon-s3-and-cloudfront/

URLの末尾がプラグイン名の模様。
今のところこの調べ方で問題起きてないですが、どこかで紹介されてた方法ではないので心配な方は調べてみると良いかも。

プラグインのバージョンはサイドメニューにある「詳細を表示」というリンクをクリックした先の詳細ページで確認できます。
画面下の方にプルダウンがあるのでソースを確認すると過去のバージョンが確認できます。

CFnテンプレートでプラグインのインストールと設定の自動化について

WordPressをインストールするコマンドの続きです。
せっかくなのでデフォルトでインストールされているakismetとhelloプラグインの削除を最初に行っています。
そのあとS3連携用のプラグインのインストールと設定を行っています。

"files": {
    "/tmp/create-wp-config": {
        "content": {
            "Fn::Join": [
                "",
                [
~~~省略~~~
                    "# wordpress default plugin setting.\n",
                    "sudo -u apache /usr/local/bin/wp plugin uninstall akismet hello\n",
                    "sudo -u apache /usr/local/bin/wp plugin install wp-multibyte-patch --activate\n",
                    "\n",
                    "# install wordpress s3 plugin and execute setting.\n",
                    "sudo -u apache /usr/local/bin/wp plugin install amazon-s3-and-cloudfront --version=2.3.1 --activate\n",
                    "sed -i -e \"/define( 'WP_DEBUG', false );/a //\\n/** for wp-s3-plugin */\\ndefine( 'AS3CF_AWS_ACCESS_KEY_ID', '",
                    {
                        "Ref": "S3BucketUserAccessKey"
                    },
                    "' );\\ndefine( 'AS3CF_AWS_SECRET_ACCESS_KEY', '",
                    {
                        "Fn::GetAtt": [
                            "S3BucketUserAccessKey",
                            "SecretAccessKey"
                        ]
                    },
                    "' );\" wp-config.php\n",
                    "sudo -u apache /usr/local/bin/wp option update tantan_wordpress_s3 '{\"bucket\": \"",
                    {
                        "Ref": "S3BucketName"
                    },
                    "\", \"copy-to-s3\": \"1\", \"force-https\": false, \"manual_bucket\": true, \"post_meta_version\": 8, \"region\": \"ap-northeast-1\", \"serve-from-s3\": \"1\"}' --format=json\n"
                ]
            ]
        },
        "mode": "000500",
        "owner": "root",
        "group": "root"
    }
},

プラグインインストール後、wp-config.phpにAS3CF_AWS_ACCESS_KEY_IDとAS3CF_AWS_SECRET_ACCESS_KEYという定数の追記を行っています。

その後、wp option updateコマンドによるWordPressのwp_optionsテーブルの設定を書き換えています。
最初wp-cliでこれが出来ないものと思って自動化を諦めてたのですが、ドキュメント調べてみたら普通にあった(^q^
ただし、CloudFormationによる自動化の手順を作るためには元の設定を知るために一度手動による構築を行う必要があります。手動でS3連携まで構築した環境のデータベースのデータダンプを取得し、wp_optionsテーブルのどのレコードが「WP Offload Media Lite」の設定なのかを調べます。
今回はバケット名の入力という分かりやすい設定があるのでそこから引っかけてどうにかなりましたがプラグインによってはソースを読んだりする必要があるかも(^^;
ちなみに「WP Offload Media Lite」のwp_options上の設定キーは「tantan_wordpress_s3」でした。

また、DBに入っている設定値はシリアライズされたjsonキーですがこれは、wp option updateコマンドのformatオプションでjsonと指定することで自動的に設定してくれるようです。そのためコマンドで設定する文字列は生のjsonテキストで良いということになります。

wp_optionsテーブルのオプションの書き換えについてまとめると以下のような作業内容となります。

  1. wp_optionsテーブルから更新対象のレコードを探す
  2. option_valueカラムのシリアライズされたjsonテキストコピー
  3. コピーした文字列をデシリアライズ(アンシリアライズ)する
    1. オンラインのツールとか使用すると良いと思う
      「デシリアライズ オンライン」とかで検索
  4. 差し替えたいところをRef関数で置換したり、エスケープしたりしてコマンドを頑張って組み立てる

成果物と動作確認

今回の成果物はこちら。後ほど更新するかもしれないのでヒストリー形式のリンクにしました。
GitHub:aws-cloudformation-templates/wordpress_s3_plugin.json at 0ea76d73a9de99255bbdc8317591f39842047c62

画像のリンクがs3から始まるバケットに直アクセスするためのURLになっていることがわかります。

S3バケットの方も確認しました。

まとめ

goofysを利用して物理的にS3をEC2に接続していたパターンより個人的にはいいんじゃないかなーと思います。WordPressはプラグインに任せられるところは任せておいた方がトラブルが起きにくい気がする。
ファイルアップロードのときにEC2インスタンス内に残る画像ファイルはロードバランサー配下のインスタンスごとに分かれてしまいます(下記画像参照)。

そのため画像に関するプラグインがうまく動かないということは考えられます。
WordPress上で管理される画像のwebp形式を配信するプラグインとして有名なEWWW Image Optimizerなんかは対応しているような情報をどこかで見たような気がします。
後ほど対応させたものをGitにプッシュするかも。

wp_optionsテーブルで管理されるプラグインの設定テキスト(シリアライズされたjson文字列)はバージョンアップなどで項目が増えたり減ったりすることが考えられるので、wp-cliでプラグインをインストールする手順を作る際はバージョンを固定しておいた方がよさそう。
バージョンの固定化自体は以下のリンクにあるようにオプションを指定するだけ。
参考:wp plugin install | WordPress Developer Resources

英語苦手なのにwp-cliのドキュメントはなぜかすらすら読める(^^)v

※12/2追記

wp_options.option_valueの書き換えが結構大変なんで調べたらwp option addコマンドで空の設定を作成し、wp option patchコマンドでjsonテキスト内の特定のキーごとに設定できることがわかりました。
参考:Using WP-CLI to Batch Update Serialized wp_options Settings
wp option patch <action> <key> <key-path>のような書式となる模様。
これが一番簡単かつ自動化手順における正解だと思います。
CloudFormationのテンプレートは以下のように書き換えてプッシュしました。

-"sudo -u apache /usr/local/bin/wp option update tantan_wordpress_s3 '{\"bucket\": \"",
-{
-    "Ref": "S3BucketName"
-},
-"\", \"copy-to-s3\": \"1\", \"force-https\": false, \"manual_bucket\": true, \"post_meta_version\": 8, \"region\": \"ap-northeast-1\", \"serve-from-s3\": \"1\"}' --format=json\n"
+"sudo -u apache /usr/local/bin/wp option add tantan_wordpress_s3 '{}' --format=json\n",
+"sudo -u apache /usr/local/bin/wp option patch insert tantan_wordpress_s3 bucket ",
+{
+    "Ref": "S3BucketName"
+},
+"\n",
+"sudo -u apache /usr/local/bin/wp option patch insert tantan_wordpress_s3 copy-to-s3 1\n",
+"sudo -u apache /usr/local/bin/wp option patch insert tantan_wordpress_s3 force-https false\n",
+"sudo -u apache /usr/local/bin/wp option patch insert tantan_wordpress_s3 manual_bucket true\n",
+"sudo -u apache /usr/local/bin/wp option patch insert tantan_wordpress_s3 post_meta_version 8\n",
+"sudo -u apache /usr/local/bin/wp option patch insert tantan_wordpress_s3 region ap-northeast-1\n",
+"sudo -u apache /usr/local/bin/wp option patch insert tantan_wordpress_s3 serve-from-s3 1\n"

また、設定済みのオプションもwp option getコマンドで取得できるので上の方で書いたwp_optionsテーブルの書き換え手順2の辺りは不要となりそうです。

最新のテンプレートはこちら
GitHub:aws-cloudformation-templates/wordpress_s3_plugin.json at cc4754955c41be443b10e16b8cb153ec5b4e3dfa

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