01.はじめに
マネジメントコンソール作業に煩わしさを感じてきたので
wordpressサイトをほぼ一撃で構築できるCloudFormtionを作成した。
WEBサーバがパブリックサブネットにあるとセキュリティ的に不安が残るので
プライベートサブネットから出来るようにした。
なるべくお金をかけない主義でEC2、RDSともに無料利用枠で利用できるスペックを選定している。
02.構成図
EC2のユーザデータを利用してNATGW経由で
・httpdパッケージ等のyumで取得できるものをS3から取得
・wordpressパッケージをwgetでインターネットから取得
する構成にしている。
インストール後はwordpressの初期設定を実施する必要がある。
実施方法はSSHポートフォワーディングを利用してパブリックサブネットに配置してある
EC2経由で接続→設定する流れにしている。
03.テンプレート
ネットワークとEC2・RDSに分けてテンプレートを作成したので分けて記載する。
①ネットワーク
AWSTemplateFormatVersion: 2010-09-09
Description: DEV-Network
# ------------------------------------------------------------#
# パラメータ
# ------------------------------------------------------------#
Parameters:
#自宅のグローバルIP(SSHのセキュリティグループで使用する)
MYip:
Type: String
Description: Type of this MYip.
# ------------------------------------------------------------#
# リソース
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# VPC
# ------------------------------------------------------------#
CFDEVVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/21
EnableDnsSupport: true
Tags:
- Key: Name
Value: CFDEVVPC
# ------------------------------------------------------------#
# Internet Gateway
# ------------------------------------------------------------#
IGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: CFDEVigw
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref CFDEVVPC
InternetGatewayId: !Ref IGW
#------------------------------------------------------------#
# Nat GW ElasticIP
# ------------------------------------------------------------#
NatGatewayEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
# ------------------------------------------------------------#
# Nat GW
# ------------------------------------------------------------#
CFNatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId:
Fn::GetAtt:
- NatGatewayEIP
- AllocationId
SubnetId: !Ref DEVPublicSubnetA
Tags:
- Key: Name
Value: CFNatGateway
# ------------------------------------------------------------#
# Public Route Table
# ------------------------------------------------------------#
PublicRouteTable:
Type: AWS::EC2::RouteTable
DependsOn: AttachGateway
Properties:
VpcId: !Ref CFDEVVPC
Tags:
- Key: Name
Value: CFDEV-PublicSubnet_RouteTable
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref IGW
# ------------------------------------------------------------#
# Praivate Route Table
# ------------------------------------------------------------#
PraivateRouteTable:
Type: AWS::EC2::RouteTable
DependsOn: AttachGateway
Properties:
VpcId: !Ref CFDEVVPC
Tags:
- Key: Name
Value: CFDEV-PrivateSubnet_RouteTable
PraivateRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PraivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref CFNatGateway
# ------------------------------------------------------------#
# DEV Public Sunbet A
# ------------------------------------------------------------#
DEVPublicSubnetA:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: "ap-northeast-1a"
CidrBlock: 10.0.1.0/24
VpcId: !Ref CFDEVVPC
Tags:
- Key: Name
Value: CFDEVDEVPublicSubnetA
PublicRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref DEVPublicSubnetA
RouteTableId: !Ref PublicRouteTable
# ------------------------------------------------------------#
# DEV Private Sunbet A1
# ------------------------------------------------------------#
DEVPrivateSubnetA1:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: "ap-northeast-1a"
CidrBlock: 10.0.2.0/24
VpcId: !Ref CFDEVVPC
Tags:
- Key: Name
Value: CFDEVPrivateSubnetA1
PrivateRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref DEVPrivateSubnetA1
RouteTableId: !Ref PraivateRouteTable
#------------------------------------------------------------#
# DEV Private Sunbet A2
# ------------------------------------------------------------#
DEVPrivateSubnetC1:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: "ap-northeast-1a"
CidrBlock: 10.0.3.0/24
VpcId: !Ref CFDEVVPC
Tags:
- Key: Name
Value: CFDEVPrivateSubnetC1
# ------------------------------------------------------------#
# DEV Private Sunbet C2
# ------------------------------------------------------------#
DEVPrivateSubnetC2:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: "ap-northeast-1c"
CidrBlock: 10.0.4.0/24
VpcId: !Ref CFDEVVPC
Tags:
- Key: Name
Value: CFDEVPrivateSubnetC2
# ------------------------------------------------------------#
# 踏み台 Security Group
# ------------------------------------------------------------#
BassionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: CFDEV-Bassion-SG
GroupDescription: Allow ssh access from Myip
VpcId: !Ref CFDEVVPC
SecurityGroupIngress:
# ssh
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Sub ${MYip}
Tags:
- Key: Name
Value: CFDEV-Bassion-SG
# ------------------------------------------------------------#
# EC2 Security Group
# ------------------------------------------------------------#
WebServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
DependsOn: BassionSecurityGroup
Properties:
GroupName: CFDEV-EC2-SG
GroupDescription: Allow HTTP access from Bassion
VpcId: !Ref CFDEVVPC
SecurityGroupIngress:
# http
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref BassionSecurityGroup
# ssh
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref BassionSecurityGroup
Tags:
- Key: Name
Value: CFDEV-EC2-SG
# ------------------------------------------------------------#
# RDS Security Group
# ------------------------------------------------------------#
DEVRDSSecurityGroup:
Type: AWS::EC2::SecurityGroup
DependsOn: WebServerSecurityGroup
Properties:
GroupDescription: Allow RDS access from EC2
VpcId: !Ref CFDEVVPC
SecurityGroupIngress:
# DB
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref WebServerSecurityGroup
Tags:
- Key: Name
Value: CFDEV-RDS-SG
Outputs:
#サブネット
DEVPublicSubnetA:
Value: !Ref DEVPublicSubnetA
Export:
Name: DEVPublicSubnetA-Outputs
DEVPrivateSubnetA1:
Value: !Ref DEVPrivateSubnetA1
Export:
Name: DEVPrivateSubnetA1-Outputs
DEVPrivateSubnetC1:
Value: !Ref DEVPrivateSubnetC1
Export:
Name: DEVPrivateSubnetC1-Outputs
DEVPrivateSubnetC2:
Value: !Ref DEVPrivateSubnetC2
Export:
Name: DEVPrivateSubnetC2-Outputs
#セキュリティグループ
WebServerSecurityGroup:
Value: !Ref WebServerSecurityGroup
Export:
Name: WebServerSecurityGroup-Outputs
BassionSecurityGroup:
Value: !Ref BassionSecurityGroup
Export:
Name: BassionSecurityGroup-Outputs
DEVRDSSecurityGroup:
Value: !Ref DEVRDSSecurityGroup
Export:
Name: DEVRDSSecurityGroup-Outputs
#VPC
CFDEVVPC:
Value: !Ref CFDEVVPC
Export:
Name: CFDEVVPC-Outputs
パブリックサブネットにあるEC2のSSH接続許可はなるべく接続元を絞るべきなので、
「自宅のグローバルIP/32」を入れる。
Outputs関数は後続のテンプレートで使用する。
②サーバ・RDS
AWSTemplateFormatVersion: 2010-09-09
Description: DEV-EC2-RDS
# ------------------------------------------------------------#
# パラメータ
# ------------------------------------------------------------#
Parameters:
#自宅のグローバルIP(SSHのセキュリティグループで使用する)
MYip:
Type: String
Description: Type of this MYip.
#最新のAmazonLinux2のAMI
EC2AMI:
Type: String
Description: Type of this EC2AMI.
#RDSのデータベース識別名
DBInstanceIdentifier:
Type: String
Description: Type of this InstanceIdentifier.
#RDSのユーザ名
MasterUsername:
Type: String
Description: Type of this MasterUsername.
#RDSのパスワード名
MasterUserPassword:
Type: String
Description: Type of this MasterUsername.
# ------------------------------------------------------------#
# リソース
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# EC2
# ------------------------------------------------------------#
#踏み台用
#EC2本体
DEVmyEC2Instance1:
Type: AWS::EC2::Instance
Properties:
KeyName: <事前に取得してあるキーペア名>
ImageId: !Sub ${EC2AMI}
InstanceType: t2.micro
Monitoring: true
SecurityGroupIds:
- !ImportValue BassionSecurityGroup-Outputs
SubnetId: !ImportValue DEVPublicSubnetA-Outputs
Tags:
- Key: Name
Value: DEVCF-EC2-1
#EIP作成
EIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
#EIP紐づけ
EIPAsaign:
Type: AWS::EC2::EIPAssociation
Properties:
AllocationId: !GetAtt EIP.AllocationId
InstanceId: !Ref DEVmyEC2Instance1
#wordpress用
DEVmyEC2Instance2:
Type: AWS::EC2::Instance
Properties:
KeyName: <事前に取得してあるキーペア名>
ImageId: !Sub ${EC2AMI}
InstanceType: t2.micro
Monitoring: true
SecurityGroupIds:
- !ImportValue WebServerSecurityGroup-Outputs
SubnetId: !ImportValue DEVPrivateSubnetA1-Outputs
UserData:
Fn::Base64: |
#!/bin/bash
echo "===========yum -y update==========="
yum -y update
echo "===========amazon-linux-extras install php7.2 -y==========="
amazon-linux-extras install php7.2 -y
echo "===========yum -y install mysql httpd php-mbstring php-xml gd php-gd==========="
yum -y install mysql httpd php-mbstring php-xml gd php-gd
echo "===========systemctl enable/start httpd.service ==========="
systemctl enable httpd.service
systemctl start httpd.service
echo "=========== http://ja.wordpress.org/latest-ja.tar.gz ~/ ==========="
wget http://ja.wordpress.org/latest-ja.tar.gz
echo "=========== tar zxvf ~/latest-ja.tar.gz ==========="
tar zxvf latest-ja.tar.gz
echo "=========== cp -r wordpress/* /var/www/html/ ==========="
cp -r wordpress/* /var/www/html/
chown apache:apache -R /var/www/html
Tags:
- Key: Name
Value: DEVCF-EC2-2
# ------------------------------------------------------------#
# RDS SubnetGroup
# ------------------------------------------------------------#
CFDBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: DEVCF-DB-SubnetGroup
SubnetIds:
- !ImportValue DEVPrivateSubnetC1-Outputs
- !ImportValue DEVPrivateSubnetC2-Outputs
Tags:
- Key: Name
Value: DEVCFDBSubnetGroup
# ------------------------------------------------------------#
# RDS
# ------------------------------------------------------------#
DEVRDS:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: !Sub ${DBInstanceIdentifier}
DBInstanceClass: "db.t2.micro"
Engine: "mysql"
EngineVersion: "8.0.28"
MasterUsername: !Sub ${MasterUsername}
MasterUserPassword: !Sub ${MasterUserPassword}
DBName: "wordpress"
BackupRetentionPeriod: 0
MultiAZ: false
PubliclyAccessible: false
StorageType: "gp2"
AllocatedStorage: 20
StorageEncrypted: false
CopyTagsToSnapshot: false
DeleteAutomatedBackups: true
DBSubnetGroupName: !Ref CFDBSubnetGroup
VPCSecurityGroups:
- !ImportValue DEVRDSSecurityGroup-Outputs
Tags:
-
Key: "Name"
Value: "DEVCF-RDS"
04.wordpressの初期設定
➀マネジメントコンソールで踏み台EC2のパブリックIPを控える
➂Teratermの設定を下記にする
ローカルホストのポートは任意の(明らかにクライアントで使われてなさそうなやつであれば)ポート番号でOKなはず
➃ブラウザでhttp://localhost:500/にアクセスする
そうすると初期画面が表示される
➅【超初心者向け】やさしいWordPressの始め方!導入から初期設定まで徹底解説 (digitalidentity.co.jp)
「ブラウザからWordPressにログインしよう」を参考に設定する
※データベースのホスト名はRDSのエンドポイントに変更する
⑧➇C2にSSHログインして /var/www/html/wp-config.phpに下記を追記する(https通信した時の画面崩れ防止のため)
if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
$_SERVER['HTTPS'] = 'on';
$_ENV['HTTPS'] = 'on';
}
05.所感
パブリックサブネットから実施するのであれば、そこまで構成に悩まなかったと思うが
プライベートサブネットにあるっていうだけで実施難易度が上がった気がした。
たまたまSSHポートフォワーディングの存在を思い出して今回の方法が実施できた。
参考文献