Open8

AWSインフラ構築日記

概要

昔、noteでAWSインフラ構築日記という体で技術ブログを書いていました。

https://note.com/hashtag/インフラ構築日記

あまり長続きしなかったのですが、もう一度改めて書き直してみようと思います。
連載形式で進みたいと考えていますので、記事ではなくスクラップに順次追加していく形で追加していきます。

目的

AWSの資格勉強や読書、動画視聴だけでは身につかないことも多いので、実際に触って構築することでAWSのインフラ構築の仕組みを理解する。

対象読者

AWSの勉強をしたい人
AWSの資格(AWS SAAやAWS CP)は取ったが、実際にAWSを使ってインフラ構築をしたことがない人

内容

LAMP環境をベースにWordPressサイトを構築していきます。
最初はシンプルにEC2インスタンス一個の中にWordPressパッケージをインストールして必要最低限動くところから始めていき、徐々に冗長化、分散化と進めていき一般的な3層アーキテクチャ構成+監視実装まで持っていきたいと思います。

注意点

AWSリソースの解説ですが、AWS SAAに含まれる内容については簡単に説明しますが、範囲外のリソースに関しては詳しく説明しょうと思います。

目標

最終的にはスクラップ内容をまとめた技術同人誌を書けるくらいまでボリュームを持たせてみたいなーと考えています。

1日目

まずは第1回ということですので、至極単純なLAMP構成を構築していきます。

ALB配下に1個のEC2をぶら下げたのみの構成です。

LAMPの詳細は以下の通りになっています。

  • Linux(Ununtu 20.04)
  • Apache(Apache/2.4.41 (Ubuntu))
  • MariaDB(Ver 15.1 Distrib 10.3.25-MariaDB)
  • PHP(7.4.3)

AWSではLAMP環境をAmazon Linux2上で構築することが多いですが、Amazon Linux2の標準リポジトリでは、PHPのバージョンが5系と古く、WordPressが推奨するバージョンを満たさないため、若干手順が増えます。
昨年、CentOS8のサポート終了が早まったことからUbuntu上でWordPressを構築する機会が増えていくと思われますので、私もUbuntu上でWordPressサイトを構築していこうと思います。

WordPress構築

AWSのマーケットプレイスにはWordPressが入ったAMIがありますが、今回は一から作りますので、各種必要なミドルウェアを順次インストールします。

sudo apt update

sudo apt -y install apache2 
sudo systemctl enable apache2
sudo systemctl start apache2

sudo apt -y install php7.4 php7.4-mysql

sudo apt -y install mariadb-server mariadb-client
sudo systemctl enable mariadb
sudo systemctl start mariadb

cd /tmp
wget https://ja.wordpress.org/latest-ja.tar.gz
tar xvf latest-ja.tar.gz
sudo cp wordpress /var/www/html
cd /var/www/html
sudo chown -R www-data:www-data .

各種ミドルウェアのインストールが完了しましたら、設定作業を行います。

WordPress用データベース作成

sudo mysql

mysql > CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
mysql > GRANT ALL ON wordpress.* TO wordpress@localhost IDENTIFIED BY 'password';
mysql > FLUSH PRIVILEGES;

設定が完了しましたら、http://パブリックIP/wordpress でWordPressのインストール画面に移りますのでデフォルト設定のまま進んで初期設定を完了します。
(日本語版のWordPressはログインユーザとパスワードが最初から設定されています)


ダッシュボード画面が表示されましたらWordPressのインストールは完了しています。

今現在の構成ですが、単純にEC2が1台VPC内にあるだけです。

冒頭のインフラ構成に近づけるために作成したEC2インスタンスをALB配下に紐づけます。

ドメイン取得

ALBを作成する前にRoute 53でドメインを取得しておきましょう。

SSL証明書取得

次にSSL通信できるようにするために、AWS Certificate Manager(ACM)を利用してHTTPS暗号化を実現します。

https://aws.amazon.com/jp/certificate-manager/

ACMで発行されたパブリックSSL証明書は無料で使用できます。
Route53で取得したドメインを保護するためのSSL証明書を申請します。

SSL証明書のリクエストが完了しましたら、「Route53でのレコードの作成」ボタンをクリック後、SSL証明書が発行されて使えるようになります。

ターゲットグループ作成

ALBにEC2を紐づけるにはターゲットグループを作成します。
ターゲットタイプはインスタンスを選択し後はデフォルトの設定のままで作成します。
作成後はEC2インスタンスをターゲットグループに登録します。

ALB作成

ここでようやくALBを作成します。
新規作成時にリスナーにHTTPSを追加すれば次のステップでSSL証明書の選択方法が聞かれますので、「ACMから証明書を選択する」をチェックして、ACMで申請したSSL証明書をアップロードします。

ALB+SSL通信設定

ALB経由でSSL通信を実現するためには、wp-config.phpに以下の設定を追加する必要があります。

wp-config.php
# ALB + SSL通信
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
        $_SERVER['HTTPS'] = 'on';

サイトURLの変更

初期設定のままですとサイトURLがhttp://パブリックIP/wordpress のままですので、データベースを編集して、表示を直します。

update wp_options set option_value = "https://www.yuta-aws.name/wordpress" where  option_id in(1,2);

select option_name,option_value from wp_options where option_id in(1,2);
+-------------+-------------------------------------+
| option_name | option_value                        |
+-------------+-------------------------------------+
| siteurl     | https://www.yuta-aws.name/wordpress |
| home        | https://www.yuta-aws.name/wordpress |
+-------------+-------------------------------------+

表示確認



WordPressがhttps通信で表示できることが確認できました。

これでシンプルなLAMP構成によるWordPress構築の完成です。

感想

VPC含めて一から全部作るのは思ったよりも大変で結構時間がかかりました。
まずはここを最初の一歩として色々なインフラ構成を構築していきたいと思います。

参考文献

https://100webdesign.jp/services/wordpress/wp_result/wp_result-633/
https://qiita.com/cherubim1111/items/b259493a39e36f5d524b

作成おつかれさまでした。1点誤字を見つけたのでご報告します。

- これでシンプルなLAMP構成によるWordPress構築の感性です。
+ これでシンプルなLAMP構成によるWordPress構築の完成です。

ありがとうございます。
修正しました。

番外編

次の予定ではEC2インスタンス内のDBからAWS RDSへ移行する検証を予定していましたが、WordPressの構成が少し微妙でしたのでこちらの記事を参考にインストールをやり直しました。

https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-on-ubuntu-20-04-with-a-lamp-stack-ja

EC2インスタンスを作成しましたら、ターゲットグループに登録します。

登録したEC2インスタンスのヘルスチェックがhealthyになりましたら、旧EC2インスタンスの登録を解除します。

1日目に実施したALB+SSL通信設定とサイトURLの変更を行いましたら、サイトの表示を確認をします。

表示確認

/wordpressディレクトリがなくなり、ドメイン直下にWordPressサイトを表示させることができました。
こちらの方が見栄えがよろしいので次回以降はこのEC2インスタンスをメインで検証を進めていきたいと思います。

2日目

EC2インスタンスの中にLAMP環境を構築してWordPressを導入しましたが、EC2インスタンスはパブリックに配置していますのでDBも外部公開されていることからセキュリティ上不安な面があります。

そこで今回はEC2インスタンス内のMySQLからAWSのAuroraにDBを変更して、2層クライアント構成にします。
DBを変更しますので、既存DBから新規DBへのデータ移行作業も合わせて実施します。
(番外編にあるように1日目からLAMP環境の構築を変えましたので、MariaDBからMySQLにDBを変更しております)

ネットワーク図


Amazon Auroraはデフォルトでリードレプリカを作成してくれますので、高可用性を担保してくれます。

AWSリソース

  • EC2インスタンス
    • セキュリティグループ:自宅PCからのSSH通信許可、ALB経由での通信許可
  • ALB
    • セキュリティグループ:HTTP/HTTPS通信許可
  • Aurora
    • セキュリティグループ:EC2インスタンス経由での通信許可

作業手順

作業手順ですが、箇条書きにしますと以下のようになります。

  • Auroraをプライベートサブネットに構築
  • MySQL内のデータをRDSに移行
  • WordPressのDB接続先をRDSに変更

基本的にDBはインターネットに公開すると情報漏えいのリスクがありますので、インターネットから隔離されたネットワークに配置するのがセオリーとなります。

Aurora構築

DBを作成する前に事前にDBサブネットを作成します。

作成するときはインターネットに繋がっていない=ルートテーブルにインターネットゲートウェイが登録されていないサブネットを選択します。

作成したAuroraがこちらになります。

作成しましたらMySQLからAuroraにデータを移行します。

データ移行

Auroraですが、MySQLとPostgreSQLの2つのDBをサポートしていますが、サポートバージョンが限られています。
2021年4月現在サポートしているMySQLのバージョンは5.7までです。

EC2インスタンス内で使っていたMySQLは8系なのでうまく移行できるか不安でしたが、mysqldumpコマンドを実行して問題なく移行することが出来ました。

sudo mysqldump --databases <データベース名> --single-transaction --compress --order-by-primary | sudo mysql -u <DBユーザー名> --port=3306 --host=<エンドポイント> -p<パスワード>

WordPressの接続DB変更

データ移行が完了しましたので、WordPressの接続先をAuroraに変更します。
接続先の変更は設定ファイルwp-config.phpの以下の記述を変更します。

wp-config.php
/** The name of the database for WordPress */
define( 'DB_NAME', 'データベース名' );

/** MySQL database username */
define( 'DB_USER', 'Auroraユーザー' );

/** MySQL database password */
define( 'DB_PASSWORD', 'Auroraパスワード' );

/** MySQL hostname */
define( 'DB_HOST', 'Auroraのエンドポイント' );

設定しましたらWordPressにアクセスして、移行前と差異がないか確認します。

所感

DBを移行して2層クライアントに変更しました。
WordPressでしたらここまでで十分かもしれませんが、よりセキュアな構成にするために次回は3層クライアントに挑戦します。

参考文献

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/MySQL.Procedural.Importing.SmallExisting.html

3日目

前回までの構築でEC2インスタンスとAuroraに分離した2層クライアントアーキテクチャを構築しました。
今回はよりセキュアな構成にするために3層クライアントアーキテクチャに挑戦していきたいと思います。

概要

前回作成したこちらの構成ですが、WebサーバであるEC2インスタンスがパブリックサブネット上に存在し、外部から見える状態になっています。

もちろん不要なアクセスを避けるためにセキュリティグループで通信許可をALBからの通信とローカルPCからのSSHアクセスだけに絞っています。
とは言え直接インターネットにつなげるのはセキュリティ上好ましくなく、個人情報や決済情報を取り扱うようなWebアプリケーションでしたらよりセキュアなアーキテクチャを採用するべきです。

そこで今回やることはEC2インスタンスもプライベートサブネットに配置してALBからのアクセスを許可するように設定することで、悪意ある攻撃者からの脆弱性攻撃への保護を行いたいと思います。

ネットワーク図


WebサーバであるEC2インスタンスをプライベートサブネットに配置し直しました。
ただ、何か障害が発生し調査目的でWebサーバへSSHする必要が出てくる時があります。
パブリックサブネットに踏み台サーバを作成し、踏み台サーバからSSH接続してもよいですが、管理するEC2インスタンスの数が増えてしまい手間がかかります。

そこで別の方法としてSSMを使用します。
AWSにはAWS Systems Manager Session Manager(SSM)というコンソール画面からEC2インスタンスにSSH接続機能が備わっています。

https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html
SSMを使えば新たにセキュリティグループでポートを開ける必要もなく、踏み台サーバを用意する必要もないので運用コストが下がります。

作業手順

それではパブリックサブネットにあるEC2インスタンスをプライベートサブネットに移管して、セッションマネージャーからSSH接続できるようにします。

事前準備

セッションマネージャーを使うためにEC2インスタンスにSSMエージェントをインストールする必要があります。
Ubuntu20.04には最初からインストールされていますが、一応確認します。

$ sudo snap services amazon-ssm-agent
Service                            Startup  Current  Notes
amazon-ssm-agent.amazon-ssm-agent  enabled  active   -

次にSSMへのアクセスに必要なIAMロールを作成します。
AWS管理ポリシーAmazonEC2RoleforSSMが含まれているIAMロールを作成し、EC2インスタンスへ割り当てます。

EC2インスタンスからAMIを作成します。

EC2インスタンス作成

作成したAMIを基にプライベートサブネットに配置するEC2インスタンスを作成します。
作成時にサブネットをプライベートサブネットに配置し、IAMロールに先ほど作成したAmazonEC2RoleforSSMを割り当てます。

その他はパブリックサブネットに配置したときと同じようにEC2インスタンスを作成します。

ターゲットグループ登録

作成したEC2インスタンスをターゲットグループに登録します。
ヘルスチェックがhealthyになりましたら既存のEC2インスタンスをターゲットグループから外します。

プライベートサブネットに配置されたEC2インスタンスのみでWordPressにアクセスできるか確認します。
Auroraへのアクセスも問題ないことを確認するために管理画面にもアクセスします。

3層クライアントアーキテクチャの構成ができましたので、次はSSMからEC2インスタンスに接続できるための設定を行います。

VPCエンドポイント作成

EC2インスタンスコンソール画面から接続ボタンをクリックして、セッションマネージャータブを選択すると以下のようにインスタンスに接続できないと表示されます。

SSMエージェントとIAMロールは設定していますが、プライベートサブネットに配置したEC2インスタンスはこれに加えて、VPCエンドポイントへアクセスできるようする必要があります。

VPCエンドポイントは以下3つを作成します。

  • com.amazonaws.region.ssm
  • com.amazonaws.region.ec2messages
  • com.amazonaws.region.ssmmessages

注釈:region部分は実際のリージョン名。東京リージョンなら、ap-northeast-1

VPCエンドポイントを作成する前にVPCのDNSホスト名の有効化にチェックを付けます。

このチェックを有効化しないとVPCエンドポイント作成時にエラーが発生しますので、事前にチェックしておきます。

次にVPCコンソール画面からエンドポイントの作成をクリックします。

サービスカテゴリはAWSサービスを選択し、サービス名は上記のVPCエンドポイントから1つ選択します。(複数選択はできませんので、3回繰り返します)

VPCとサブネットはプライベートサブネットを選択します。

セキュリティグループはVPC内のSubnet CIDRをソースにHTTPS通信を許可したものを作成して設定します。

そのほかの設定はデフォルトのままでエンドポイントの作成ボタンをクリックします。
VPCエンドポイントを3つ作成しましたらセッションマネージャーから接続します。

SSMからEC2インスタンスへ接続することができましたので、各種ミドルウェアの状態やWordPressのDocumentRoot配下を調べることが出来るようになりました。

所感

3層クライアントアーキテクチャに変更することで、よりセキュアなインフラ構成を構築することができました。
またSSMを活用することで、踏み台サーバの作成が不要になったのが運用コスト削減になり良かったと思います。
次回はEC2インスタンスの分散化に挑戦しようと思います。
先にS3によるストレージの分散化を実施しようと思います。

参考文献

https://dev.classmethod.jp/articles/ssm-session-manager-release/
https://dev.classmethod.jp/articles/tsnote-private-ec2-ssm-vpc-endpoint/

4日目

前回までの構築でELB+EC2+RDSによる3層クライアントアーキテクチャを実装致しました。
基本的なWebアプリケーションサービスはこの3層クライアントアーキテクチャで構成されているのは一般的です。
次に着手するのはストレージの分散化です。

概要

今現在、WordPress上で保存された画像ファイルや動画ファイルはEC2インスタンス内に格納される仕組みになっています。

動画ファイルのような容量サイズが大きいファイルがどんどんEC2インスタンス内に溜まると処理動作が重くなり、ユーザの利便性が下がってしまいます。

なので次に行うこととして、EC2インスタンス内にある画像ファイルや動画ファイルなどをS3に格納して運用改善を目指していきたいと思います。

ネットワーク図

EC2インスタンス内にある画像や動画ファイル、PDFファイルなどをS3にアップロードするようにし、EC2インスタンスには動画ファイルや画像ファイルを残さないようにします。

作業手順

S3作成

早速ですが、ファイルを格納するS3の作成を行います。
S3のコンソール画面からデフォルト設定のまま作成しても大丈夫です。
作成後にアクセス許可の設定を行います。

パブリックアクセスをすべてブロックのチェックボックスを外し、全体公開できるように設定します。

バケットポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<bucket-name>/*"
        }
    ]
}

次にバケットポリシーを記述し、オブジェクト読み込みを許可します。
これでS3にあるファイルがHTTP経由で見れるようになります。

コンテンツの保存先の変更

WordPressの記事内に挿入された画像ファイルや動画ファイルなどはここに格納されています。
wp-content/uploads/YYYY/MM/
ここからはWordPressのプラグインを使うことにしますが、EC2インスタンスはプライベートサブネットに配置されておりインターネット接続されていないためプラグインをインストールすることができません。
一時的にインターネットにつなげるためにNATゲートウェイをパブリックサブネットに配置し、プライベートサブネットのルートテーブルからルーティングするようにします。

以下のWordPressプラグインをインストールします。
WP Offload Media Lite

https://ja.wordpress.org/plugins/amazon-s3-and-cloudfront/
インストールが完了しましたら、有効化して初期設定を行います。
古い記事ですとwp-config.phpにAWSのアクセスキーとシークレットキーを埋め込む方法がありますが、IAMロールで制御することも可能になりました。
(図の真ん中のチェックボックスを選択する)

公式ドキュメント引用

前回EC2にSSMのポリシーを割り当てるためにIAMロールを付与しましたが、そのロールにS3のアクセルロールも追加いたします。

ストレージの格納先がプロバイダーAWS、バケットを先ほど作成したS3に設定し、最後のADVANCED OPTIONSでサーバにはファイルを残さないようにします。

S3にファイルが保存されるか確かめてみます。WordPressの記事作成から画像や動画ファイルを挿入し、記事公開後S3を見てみます。

既にwp-content/uploadsの中にあるコンテンツですが、aws s3 mvコマンドを使ってS3へ移行させます。
ただ、既に公開済みの記事にあるファイルはリンク切れとなり表示されなくなりますので、こちらのプラグインをインストールしてリンクを変更します。
search-regex

https://ja.wordpress.org/plugins/search-regex/

検索の欄にリンク切れを起こしている記事内のURLを記載し、置換の欄にS3に移管したファイルのバケットのURLを記載します。

これでS3に画像ファイルや動画ファイルの保存先を移行することができました。

NATゲートウェイは高額でフル稼働させるとなかなかコストがかさむので、プラグインのインストールが完了したら削除します。
(お金に余裕がある人は稼働しっぱなしでも大丈夫です)

VPCエンドポイント作成

先程まではNATゲートウェイを繋いでましたので、EC2-S3間でインターネット通信が可能になりました。
NATゲートウェイを削除しましたらVPCエンドポイントを作成して、AWSネットワーク内の通信を実現いたします。

前回のSSMと同様にVPCのコンソール画面からエンドポイントを作成を選択し、S3のエンドポイントを選択します。

  • com.amazonaws.region.s3

ゲートウェイタイプでしたら無料で利用できますのでこちらを選びましょう。
プライベートサブネットのルートテーブルに設定し、エンドポイントを作成すればそのままプライベートサブネットのルートテーブルにS3のエンドポイントが設定されています。

これでWordPress内で使用される画像や動画ファイルはVPCエンドポイントを通して、EC2インスタンスからS3へ保存されるようになりました。

所感

サイズの大きいファイルをS3で保存することができました。
ここはインフラだけでなく、WordPressの知識も必要でしたので調べるのが少し大変でした。
次回はS3に保存されているファイルを高速で取得できるようにCloudFrontを使ってキャッシュによる高速レスポンスを実現しようと思います。

参考文献

http://tech-blog.tsukaby.com/archives/972
https://www.javadrive.jp/wordpress/plugin-list/index27.html
https://dev.classmethod.jp/articles/vpc-endpoint-gateway-type/
ログインするとコメントできます