#目次
1.はじめに
2.前提
3.独自ドメインの取得
4.ネットワークの設定
5.セキュリティの設定
6.仮想サーバおよび独自ドメインの設定
7.通信のhttps化およびデータベースの設定
8.稼働確認
9.まとめ
10.cloudformationテンプレート
11.参考
#はじめに
WebアプリをAWSのEC2上へデプロイする場合、インフラ環境には以下のような様々なAWSリソースを使用することになり、毎回手作業で設定をしていくと、時間もかかりますし、設定ミスをする可能性も出てきます。そこで今回、Webアプリをインターネットに公開するためのインフラ環境を、AWSのCloudFormationでコード化し、構築しましたので、大まかな手順を整理します。
■ AWSインフラ環境で利用されるリソースの例
-
ネットワーク:VPC、サブネット、ルートテーブル、インターネットゲートウェイなど
-
アクセス制御:セキュリティグループ、IAMなど
-
仮想サーバ:EC2
-
負荷分散:ELB
-
DNS:Route53
-
データベース:RDS、DynamoDB、Redshiftなど
-
ストレージ:S3、EFSなど
-
証明書管理:ACM
#前提
今回、CloudFormationでコード化したAWS環境の構成は以下の通りとなります。
■ EC2へのSSH接続用キーペアを事前に準備
CloudFormationでPublicSubnet 1aにEC2を作成する際、キーペアを指定する必要があります。マネジメントコンソールから、事前にキーペアを作成しておきましょう。
■ 環境の特徴
- コスト重視で可用性は低めの設定とし、EC2およびRDSは冗長化しない。
- Route53で独自ドメインを設定する。
- ACMを利用し、ユーザからの通信をHTTPS化する。
- ALBが所属するSecurityGroup (以降、SGと記載) は任意のIPアドレスからの80番、443番のアクセスを許可
- EC2が所属するSGはALBが所属するSGからの80番、443番のアクセスを許可
- EC2が所属するSGは特定のIPアドレス(スタック作成時に指定)からの22番アクセスのみを許可
- RDSが所属するSGはEC2が所属するSGからの3306番のアクセスを許可
- ALBはユーザからのHTTPリクエストをHTTPSにリダイレクトする
- 作成するEC2にはユーザデータより、nginxをインストールした上で、index.htmlを配置する。
- 作成するEC2にはブラウザから「www.独自ドメイン名」でアクセス可能
■ 使用するCloudFormationテンプレート
上記の環境を構築する上で、CloudFormationのテンプレートを4種類に分割して作成しました。
- 「network.yml」」: VPC、IG (インターネットゲートウェイ) 、サブネット、ルートテーブルの設定用
- 「security.yml」」: セキュリティグループの設定用
- 「application-first.yml」」: EC2、ALB、Route53の設定用
- 「application-second.yml」」: ACM、RDSの設定用
以降、これらを使用した環境構築の手順を整理していきますが、各テンプレートの内容は長くなってしまいますので、最後にまとめて記載することにします。
#独自ドメインの取得
今回は、無料から利用できるドメインプロバイダ「Freenom」でドメインを取得していきます。
- 取得したい名前を検索し、ヒットした場合は利用可能なドメイン名を選択した上で「Checkout」を押下する。
- 利用したい期間を選択し、「Continue」を押下する。
- 利用条件を確認した上でチェックを入れ、「Complete Order」を押下する。
- 「Services」→「My Domains」を押下する。
- 先ほど作成したドメイン名が存在することを確認する。
以上、独自ドメインの取得は完了です。次にネットワークの設定をしていきます。
#ネットワークの設定
CloudFormationテンプレート「network.yml」を使用して、ネットワークの設定をしていきます。
- AWSにログインし、CloudFormationの「スタックの作成」画面にて、「テンプレートファイルのアップロード」を選択した上で、「ファイルの選択」を押下する。
- 「network.yml」を選択し、「次へ」を押下する。
- 今回はスタックの名前を「network」、導入予定のWebアプリ名を「AppName」に入力し、「次へ」を押下する。
※ 「Network-Config」では、必要に応じて、VPCやサブネットのCIDRをカスタマイズする。 ( 以下、デフォルト値 )
- 「スタックオプションの設定」画面に遷移するが、今回は特に設定せず「次へ」を押下する。
- 確認画面に遷移後、画面右下の「スタックの作成」を押下する。
- 数分待った後、「network」スタックの状態が「CREATE_COMPLETE」になることを確認する。
以上、ネットワークの設定は完了です。現在のAWS構成の状態は以下の通りです。
次にセキュリティの設定をしていきます。
#セキュリティの設定
CloudFormationテンプレート「security.yml」を使用して、セキュリティの設定をしていきます。
※ ネットワーク設定とほとんど手順が変わらないため、途中経過は割愛し、差分となる画面のみ添付します。
- 今回はスタックの名前を「security」、導入予定のWebアプリ名を「AppName」に入力、また、「SourceIP」には以降で作成するWebアプリデプロイ用EC2へのSSH接続を許可させたいIPアドレス を入力し、「次へ」を押下する。
※ Webアプリデプロイ用のEC2は以降でPublicSubnet1a内に作成される。作成したEC2にSSH接続をし、各種設定作業を実施する際を想定し、ここで許可させたいIPアドレスを指定する。 (例) 作業用端末のグローバルIPアドレスを指定 / PublicSubnet1aに踏み台ホスト(EC2)を作成し、そのIPアドレスを指定。
※ CIDR表記で入力すること。(例)10.0.0.5/32
- 「スタックの作成」を押下し、数分待った後、「security」スタックの状態が「CREATE_COMPLETE」になることを確認する。
以上、セキュリティの設定は完了です。現在のAWS構成の状態は以下の通りです。
次に仮想サーバおよび独自ドメインの設定をしていきます。
#仮想サーバおよび独自ドメインの設定
CloudFormationテンプレート「application-first.yml」を使用して、仮想サーバおよび独自ドメインの設定をしていきます。
※ 途中経過は割愛し、差分となる画面のみ添付します。
- 今回はスタックの名前を「application-first」、導入予定のWebアプリ名を「AppName」に入力、EC2接続に使用するキーペア名を「KeyName」、また、「DomainName」にはFreenomで取得した独自ドメイン名を入力し、「次へ」を押下する。
※ KeyNameには拡張子「.pem」は付けすに入力する
- 「スタックの作成」を押下し、数分待った後、「application-first」スタックの状態が「CREATE_COMPLETE」になることを確認する。
- 「Route53」→「ホストゾーン」から、上記のスタックにて作成されたホストゾーンが存在することを確認し、ドメイン名を押下する。
- NSレコードの「値/トラフィックのルーティング先」の内容を控える。
- Freenomの「MyDomains」画面に行き、「Manage Domain」を押下する。
- 「Management Tools」→「Nameservers」を押下する。
- 「Use custom nameservers (enter below) 」を選択し、Nameseverの欄に先ほど控えた値を入力し、「Change Nameservers」を押下する。
以上、仮想サーバおよび独自ドメインの設定は完了です。現在のAWS構成の状態は以下の通りです。
最後に通信のHTTPS化およびデータベースの設定をしていきます。
#通信のhttps化およびデータベースの設定
CloudFormationテンプレート「application-second.yml」を使用して、通信のHTTPS化およびデータベースの設定をしていきます。
※ 途中経過は割愛し、差分となる画面のみ添付します。
- 今回はスタックの名前を「application-second」、導入予定のWebアプリ名を「AppName」に入力、また、「DomainName」にはFreenomで取得した独自ドメイン名を入力する。
- また、「RDS-Config」にてDBのユーザ名、パスワードを入力し、「次へ」を押下する。
※ 「他の項目は必要に応じてカスタマイズする。 ( 以下、デフォルト値 )
- 「スタックの作成」を押下し、数分待った後、「application-second」スタックの状態が「CREATE_COMPLETE」になることを確認する。
以上、通信のHTTPS化およびデータベースの設定は完了です。冒頭に記載したAWSのインフラ構成が完成しました。
#稼働確認
それでは、ブラウザより独自ドメインにてアクセスをしていきます。せっかくなのでhttpでリクエストするとhttpsにリダイレクトされることを確認します。
httpsにリダイレクトされ、EC2のユーザデータによって作成されたindex.htmlの内容 (Hello World!) が表示されました。
#まとめ
以上で、Webアプリ公開のためのインフラ環境をCloudFormationを用いて、構築できました。しかし、アプリ公開のためには別途、今回作成したEC2内で各種設定をし、デプロイをしていく必要があります。以降の内容は以下の記事に記載いたしました。
Webアプリデプロイ方法(AWS EC2編)
最後になりますが、作成したCloudFormationテンプレートの内容をまとめていきます。
尚、この記事はAWS初学者を導く体系的な動画学習サービス「AWS CloudTech」の課題カリキュラムで作成しました。
#cloudformationテンプレート
AWSTemplateFormatVersion: 2010-09-09
# ------------------------------------------------------------#
# Description
# ------------------------------------------------------------#
Description:
VPC/InternetGateway/Subnet/RouteTable
# ------------------------------------------------------------#
# MetaData
# ------------------------------------------------------------#
#スタック作成時の画面入力パラメータの表示設定
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "ApplicationName"
Parameters:
- AppName
- Label:
default: "Network-Config"
Parameters:
- VpcCidr
- Public1aCidr
- Public1cCidr
- Private1aCidr
- Private1cCidr
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
#スタック作成時に入力する各種パラメータ
Parameters:
#アプリケーション名
AppName:
Type: String
#VPCのサイダー
VpcCidr:
Type: String
Default: "10.0.0.0/16"
#PublicSubnet-1aのサイダー
Public1aCidr:
Type: String
Default: "10.0.0.0/24"
#PublicSubnet-1cのサイダー
Public1cCidr:
Type: String
Default: "10.0.1.0/24"
#PrivateSubnet-1aのサイダー
Private1aCidr:
Type: String
Default: "10.0.2.0/24"
#PrivateSubnet-1cのサイダー
Private1cCidr:
Type: String
Default: "10.0.3.0/24"
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
#作成する各種AWSリソース
Resources:
#VPC
MyVpc:
Type: AWS::EC2::VPC
#以下、VPCのプロパティ
Properties:
#サイダー
CidrBlock: !Ref VpcCidr
#DNS解決
EnableDnsSupport: "true"
#DNSホスト名
EnableDnsHostnames: "true"
#テナンシー
InstanceTenancy: default
#タグ
Tags:
- Key: Name
Value: !Sub "Vpc-for-${AppName}"
#InternetGateway
InternetGateway:
Type: "AWS::EC2::InternetGateway"
#以下、InternetGatewayのプロパティ
Properties:
#タグ
Tags:
- Key: Name
Value: !Sub "igw-${AppName}"
#InternetGatewayのアタッチ
InternetGatewayAttach:
Type: "AWS::EC2::VPCGatewayAttachment"
#以下、アタッチのプロパティ
Properties:
#InternetGatewayの指定
InternetGatewayId: !Ref InternetGateway
#VPCの指定
VpcId: !Ref MyVpc
#AZ1a内のパブリックサブネット
PublicSubnet1a:
Type: AWS::EC2::Subnet
#以下、サブネットのプロパティ
Properties:
#AZの指定
AvailabilityZone: "ap-northeast-1a"
#VPCの指定
VpcId: !Ref MyVpc
#サイダー
CidrBlock: !Ref Public1aCidr
#タグ
Tags:
- Key: Name
Value: !Sub "PublicSubnet-1a-${AppName}"
#AZ1c内のパブリックサブネット
PublicSubnet1c:
Type: AWS::EC2::Subnet
#以下、サブネットのプロパティ
Properties:
#AZの指定
AvailabilityZone: "ap-northeast-1c"
#VPCの指定
VpcId: !Ref MyVpc
#サイダー
CidrBlock: !Ref Public1cCidr
#タグ
Tags:
- Key: Name
Value: !Sub "PublicSubnet-1c-${AppName}"
#AZ1a内のプライベートサブネット
PrivateSubnet1a:
Type: AWS::EC2::Subnet
#以下、サブネットのプロパティ
Properties:
#AZの指定
AvailabilityZone: "ap-northeast-1a"
#VPCの指定
VpcId: !Ref MyVpc
#サイダー
CidrBlock: !Ref Private1aCidr
#タグ
Tags:
- Key: Name
Value: !Sub "PrivateSubnet-1a-${AppName}"
#AZ1c内のプライベートサブネット
PrivateSubnet1c:
Type: AWS::EC2::Subnet
#以下、サブネットのプロパティ
Properties:
#AZの指定
AvailabilityZone: "ap-northeast-1c"
#VPCの指定
VpcId: !Ref MyVpc
#サイダーの指定
CidrBlock: !Ref Private1cCidr
#タグ
Tags:
- Key: Name
Value: !Sub "PrivateSubnet-1c-${AppName}"
#パブリックルートテーブル
PublicRouteTable:
Type: "AWS::EC2::RouteTable"
#以下、ルートテーブルのプロパティ
Properties:
#VPCの指定
VpcId: !Ref MyVpc
#タグ
Tags:
- Key: Name
Value: !Sub "public-route-${AppName}"
#プライベートルートテーブル
PrivateRouteTable:
Type: "AWS::EC2::RouteTable"
#以下、ルートテーブルのプロパティ
Properties:
#VPCの指定
VpcId: !Ref MyVpc
#タグ
Tags:
- Key: Name
Value: !Sub "private-route-${AppName}"
#ルーティング
PublicRoute:
Type: "AWS::EC2::Route"
#以下、ルーティングのプロパティ
Properties:
#ルートテーブルの指定
RouteTableId: !Ref PublicRouteTable
#宛先
DestinationCidrBlock: "0.0.0.0/0"
#ゲートウェイの指定
GatewayId: !Ref InternetGateway
#パブリックルートテーブルの関連付け
Public1aRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
#以下、関連づけのプロパティ
Properties:
#サブネットの指定
SubnetId: !Ref PublicSubnet1a
#ルートテーブルの指定
RouteTableId: !Ref PublicRouteTable
#パブリックルートテーブルの関連付け
Public1cRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
#以下、関連づけのプロパティ
Properties:
#サブネットの指定
SubnetId: !Ref PublicSubnet1c
#ルートテーブルの指定
RouteTableId: !Ref PublicRouteTable
#プライベートルートテーブルの関連付け
Private1aRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
#以下、関連付けのプロパティ
Properties:
#サブネットの指定
SubnetId: !Ref PrivateSubnet1a
#ルートテーブルの指定
RouteTableId: !Ref PrivateRouteTable
#プライベートルートテーブルの関連付け
Private1cRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
#以下、関連付けのプロパティ
Properties:
#サブネットの指定
SubnetId: !Ref PrivateSubnet1c
#ルートテーブルの指定
RouteTableId: !Ref PrivateRouteTable
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
#他のテンプレートで使用可能なパラメータを指定
Outputs :
MyVpc:
Value: !Ref MyVpc
Export:
Name: "VPC"
PublicSubnet1a:
Value: !Ref PublicSubnet1a
Export:
Name: "PublicSubnet-1a"
PublicSubnet1c:
Value: !Ref PublicSubnet1c
Export:
Name: "PublicSubnet-1c"
PrivateSubnet1a:
Value: !Ref PrivateSubnet1a
Export:
Name: "PrivateSubnet-1a"
PrivateSubnet1c:
Value: !Ref PrivateSubnet1c
Export:
Name: "PrivateSubnet-1c"
PublicRouteTable:
Value: !Ref PublicRouteTable
Export:
Name: "public-route"
PrivateRouteTable:
Value: !Ref PrivateRouteTable
Export:
Name: "private-route"
AWSTemplateFormatVersion: 2010-09-09
# ------------------------------------------------------------#
# Description
# ------------------------------------------------------------#
Description:
SecurityGroup
# ------------------------------------------------------------#
# MetaData
# ------------------------------------------------------------#
#スタック作成時の画面入力パラメータの表示設定
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "ApplicationName"
Parameters:
- AppName
- Label:
default: "IPAddress of BastionHost"
Parameters:
- SourceIP
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
#スタック作成時に入力する各種パラメータ
Parameters:
#アプリケーション名
AppName:
Type: String
#SSH接続を許可させるIPアドレス
SourceIP:
Type: String
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
#作成する各種AWSリソース
Resources:
#ALB用セキュリティグループ
AlbSG:
Type: AWS::EC2::SecurityGroup
#以下、セキュリティグループのプロパティ
Properties:
#セキュリティグループ名
GroupName: !Sub AlbSG-${AppName}
#セキュリティグループの説明
GroupDescription: AlbSGGroup
#所属するVPCの指定
VpcId: !ImportValue "VPC"
#インバウンド設定
SecurityGroupIngress:
#任意のIPアドレスからの80番ポートアクセスを許可
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp : 0.0.0.0/0
#任意のIPアドレスからの443番ポートアクセスを許可
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp : 0.0.0.0/0
#タグ
Tags:
- Key: Name
Value: !Sub "alb-sg-${AppName}"
#EC2インスタンス用セキュリティグループ
WebSG:
Type: AWS::EC2::SecurityGroup
#以下、セキュリティグループのプロパティ
Properties:
#セキュリティグループ名
GroupName: !Sub WebSG-${AppName}
#セキュリティグループの説明
GroupDescription: WebSGGroup
#所属するVPCの指定
VpcId: !ImportValue "VPC"
#インバウンド設定
SecurityGroupIngress:
#ALB用セキュリティグループからの80番ポートアクセスを許可
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId : !Ref AlbSG
#ALB用セキュリティグループからの443番アクセスを許可
- IpProtocol: tcp
FromPort: 443
ToPort: 443
SourceSecurityGroupId : !Ref AlbSG
#特定のIPアドレスからの22番ポートアクセスを許可
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp : !Ref SourceIP
#タグ
Tags:
- Key: Name
Value: !Sub "web-sg-${AppName}"
#RDS用セキュリティグループ
PrivateSG:
Type: AWS::EC2::SecurityGroup
#以下、セキュリティグループのプロパティ
Properties:
#セキュリティグループ名
GroupName: !Sub PrivateSG-${AppName}
#セキュリティグループの説明
GroupDescription: PrivateSGGroup
#所属するVPCの指定
VpcId: !ImportValue "VPC"
#インバウンド設定
SecurityGroupIngress:
#EC2用セキュリティグループからの3306番ポートアクセスを許可
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref WebSG
#タグ
Tags:
- Key: Name
Value: !Sub "private-sg-${AppName}"
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
#他のテンプレートで使用可能なパラメータを指定
Outputs :
AlbSG:
Value: !Ref AlbSG
Export:
Name: "alb-sg"
WebSG:
Value: !Ref WebSG
Export:
Name: "web-sg"
PrivateSG:
Value: !Ref PrivateSG
Export:
Name: "private-sg"
AWSTemplateFormatVersion: 2010-09-09
# ------------------------------------------------------------#
# Description
# ------------------------------------------------------------#
Description:
EC2/ALB/Route53
# ------------------------------------------------------------#
# MetaData
# ------------------------------------------------------------#
#スタック作成時の画面入力パラメータの表示設定
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "ApplicationName"
Parameters:
- AppName
- Label:
default: "DomainName"
Parameters:
- DomainName
- Label:
default: "KeyName"
Parameters:
- KeyName
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
#スタック作成時に入力する各種パラメータ
Parameters:
#アプリケーション名
AppName:
Type: String
#Route53で設定するドメイン名
DomainName:
Type: String
#EC2インスタンス接続に使用するキーの指定
KeyName:
Type: String
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
#作成する各種AWSリソース
Resources:
#EC2インスタンス
MyEC2:
Type: AWS::EC2::Instance
#以下、EC2インスタンスのプロパティ
Properties:
#紐付けるキーペア名
KeyName: my-key
#AMI (今回はAmazon Linux 2)
ImageId: ami-0ca38c7440de1749a
#インスタンスタイプ
InstanceType: t2.micro
#CloudWatch詳細モニタリングの有無
Monitoring: false
#所属するセキュリティグループ
SecurityGroupIds: [!ImportValue "web-sg"]
#配置するサブネット
SubnetId: !ImportValue "PublicSubnet-1a"
#ユーザデータ (Nginxのインストール・起動設定)
UserData:
Fn::Base64: |
#!/bin/bash
yum update -y
amazon-linux-extras install nginx1.12 -y
systemctl start nginx
systemctl enable nginx
echo "Hello World!" > /usr/share/nginx/html/index.html
#タグ
Tags:
- Key: Name
Value: !Sub "EC2-${AppName}"
#Elastic IPアドレス
ElasticIp:
Type: AWS::EC2::EIP
#以下、Elastic IPアドレスのプロパティ
Properties:
#紐づけるリソース (今回は上記で作成したEC2インスタンスに紐付け)
InstanceId: !Ref MyEC2
#VPC内で利用する
Domain: vpc
#ALB
ALB:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
#以下、ALBのプロパティ
Properties:
#ALB名
Name: !Sub "ALB-${AppName}"
#スキーム (インターネット向け/内部向け)
Scheme: "internet-facing"
LoadBalancerAttributes:
#削除保護の有無
- Key: "deletion_protection.enabled"
Value: false
#アイドルタイムアウト値
- Key: "idle_timeout.timeout_seconds"
Value: 60
#所属するセキュリティグループ
SecurityGroups:
- !ImportValue "alb-sg"
#配置するサブネット
Subnets:
- !ImportValue "PublicSubnet-1a"
- !ImportValue "PublicSubnet-1c"
#ALBのターゲットグループ
TargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
#以下、ターゲットグループのプロパティ
Properties:
#VPCの指定
VpcId: !ImportValue "VPC"
#ターゲットグループ名
Name: !Sub "tg-${AppName}"
#リクエスト送信で利用するプロトコル
Protocol: HTTP
#リクエスト送信で利用するポート
Port: 80
#ヘルスチェックで利用するプロトコル
HealthCheckProtocol: HTTP
#ヘルスチェックをするパス
HealthCheckPath: "/"
#ヘルスチェックで使用するポート
HealthCheckPort: "traffic-port"
#異常なターゲットが正常であると見なされるまでに必要なヘルスチェックの連続的な成功回数
HealthyThresholdCount: 5
#ターゲットが異常であると見なされるまでに必要なヘルスチェックの連続的な失敗回数
UnhealthyThresholdCount: 2
#秒単位の時間で、この間に応答がないと、ヘルスチェックが失敗していることになる
HealthCheckTimeoutSeconds: 5
#個々のターゲットのヘルスチェックの概算間隔
HealthCheckIntervalSeconds: 10
#ターゲットからの正常なレスポンスを確認するために使用する HTTP コード
Matcher:
HttpCode: 200
#ターゲット
Targets:
- Id: !Ref MyEC2
Port: 80
#ALBリスナー(HTTPSリダイレクト)
ListenerHTTP:
Type: "AWS::ElasticLoadBalancingV2::Listener"
#以下、リスナーのプロパティ
Properties:
#使用するポート
Port: 80
#使用するプロトコル
Protocol: HTTP
#HTTPSリダイレクト設定
DefaultActions:
- Type: redirect
RedirectConfig:
Host: '#{host}'
Path: '/#{path}'
Port: 443
Protocol: HTTPS
Query: '#{query}'
StatusCode: HTTP_301
#ロードバランサーの指定
LoadBalancerArn: !Ref ALB
# Route53ホストゾーン
Route53HostedZone:
Type: AWS::Route53::HostedZone
#以下、Route53ホストゾーンのプロパティ
Properties:
#ドメイン名
Name: !Sub "${DomainName}"
# Route53レコード
Route53Record:
Type: AWS::Route53::RecordSetGroup
#以下、Route53レコードのプロパティ
Properties:
#Route53ホストゾーンの指定
HostedZoneId: !Ref Route53HostedZone
RecordSets:
#レコード名
- Name: !Sub "www.${DomainName}."
#トラフィックのルーティング先
AliasTarget:
HostedZoneId: !GetAtt ALB.CanonicalHostedZoneID
DNSName: !GetAtt ALB.DNSName
#レコードタイプ
Type: A
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
#他のテンプレートで使用可能なパラメータを指定
Outputs :
Route53HostedZone:
Value: !Ref Route53HostedZone
Export:
Name: "Route53HostedZone"
ALB:
Value: !Ref ALB
Export:
Name: "ALB"
TargetGroup:
Value: !Ref TargetGroup
Export:
Name: "TargetGroup"
AWSTemplateFormatVersion: 2010-09-09
# ------------------------------------------------------------#
# Description
# ------------------------------------------------------------#
Description:
ACM/RDS
# ------------------------------------------------------------#
# MetaData
# ------------------------------------------------------------#
#スタック作成時の画面入力パラメータの表示設定
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "ApplicationName"
Parameters:
- AppName
- Label:
default: "DomainName"
Parameters:
- DomainName
- Label:
default: "RDS-Config"
Parameters:
- DBInstanceName
- MySQLMajorVersion
- MySQLMinorVersion
- DBInstanceClass
- DBInstanceStorageSize
- DBInstanceStorageType
- DBName
- DBMasterUserName
- DBPassword
- MultiAZ
ParameterLabels:
DBInstanceName:
default: "DBInstanceName"
MySQLMajorVersion:
default: "MySQLMajorVersion"
MySQLMinorVersion:
default: "MySQLMinorVersion"
DBInstanceClass:
default: "DBInstanceClass"
DBInstanceStorageSize:
default: "DBInstanceStorageSize"
DBInstanceStorageType:
default: "DBInstanceStorageType"
DBName:
default: "DBName"
DBMasterUserName:
default: "DBMasterUserName(min:1,max:20)"
DBPassword:
default: "DBPassword(min:8,max:30)"
MultiAZ:
default: "MultiAZ"
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
#スタック作成時に入力する各種パラメータ
Parameters:
#アプリケーション名
AppName:
Type: String
#ACMに紐づけるドメイン名
DomainName:
Type: String
#DBインスタンス名
DBInstanceName:
Type: String
Default: "rds"
#MySQLメジャーバージョン
MySQLMajorVersion:
Type: String
Default: "5.7"
AllowedValues: [ "5.5", "5.6", "5.7" ]
#MySQLマイナーバージョン
MySQLMinorVersion:
Type: String
Default: "26"
#DBインスタンスクラス
DBInstanceClass:
Type: String
Default: "db.t2.micro"
#ストレージサイズ(GiB)
DBInstanceStorageSize:
Type: String
Default: "20"
#ストレージタイプ
DBInstanceStorageType:
Type: String
Default: "gp2"
#DB名
DBName:
Type: String
Default: "db"
#DBユーザ名
DBMasterUserName:
Type: String
MinLength: 1
MaxLength: 20
#DBユーザパスワード
DBPassword:
NoEcho: true
Type: String
MinLength: 8
MaxLength: 30
#マルチAZ
MultiAZ:
Default: "false"
Type: String
AllowedValues: [ "true", "false" ]
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
#作成する各種AWSリソース
Resources:
#ACM
ACM:
Type: AWS::CertificateManager::Certificate
#以下、ACMのプロパティ
Properties:
#ドメイン名
DomainName: !Sub "${DomainName}"
DomainValidationOptions:
#ACMに紐づけるドメイン名
- DomainName: !Sub "${DomainName}"
#ACMに紐づけるRoute53ホストゾーン
HostedZoneId: !ImportValue "Route53HostedZone"
#ワイルドカード証明書の取得
SubjectAlternativeNames:
- !Sub "*.${DomainName}"
#検証方法
ValidationMethod: DNS
#ALBリスナー(HTTPS)
ListenerHTTPS:
Type: AWS::ElasticLoadBalancingV2::Listener
#以下、リスナーのプロパティ
Properties:
#使用するポート
Port: 443
#使用するプロトコル
Protocol: HTTPS
#使用するSSL証明書
Certificates:
- CertificateArn: !Ref ACM
DefaultActions:
#ターゲットグループの指定
- TargetGroupArn: !ImportValue "TargetGroup"
#指定されたターゲットグループにリクエストを転送
Type: forward
#ロードバランサーの指定
LoadBalancerArn: !ImportValue "ALB"
#RDSサブネットグループ
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
#以下、サブネットグループのプロパティ
Properties:
#サブネットグループ名
DBSubnetGroupName: !Sub "${DBInstanceName}-${AppName}"
#サブネットグループの説明
DBSubnetGroupDescription: !Sub "${DBInstanceName}-${AppName}"
#サブネットの指定
SubnetIds:
- !ImportValue "PrivateSubnet-1a"
- !ImportValue "PrivateSubnet-1c"
#RDSインスタンス
DBInstance:
Type: "AWS::RDS::DBInstance"
#以下、RDSインスタンスのプロパティ
Properties:
#DBインスタンス識別子
DBInstanceIdentifier: !Sub "${DBInstanceName}-${AppName}"
#エンジン
Engine: MySQL
#エンジンバージョン
EngineVersion: !Sub "${MySQLMajorVersion}.${MySQLMinorVersion}"
#インスタンスクラス
DBInstanceClass: !Ref DBInstanceClass
#ストレージサイズ
AllocatedStorage: !Ref DBInstanceStorageSize
#ストレージタイプ
StorageType: !Ref DBInstanceStorageType
#DB名
DBName: !Ref DBName
#DBユーザ名
MasterUsername: !Ref DBMasterUserName
#DBユーザパスワード
MasterUserPassword: !Ref DBPassword
#RDSサブネットグループ
DBSubnetGroupName: !Ref DBSubnetGroup
#パブリックアクセシビリティ
PubliclyAccessible: false
#マルチAZ
MultiAZ: !Ref MultiAZ
#バックアップウィンドウ
PreferredBackupWindow: "18:00-18:30"
#メンテナンスウィンドウ
PreferredMaintenanceWindow: "sat:19:00-sat:19:30"
#マイナーバージョンの自動アップグレード
AutoMinorVersionUpgrade: false
#DBパラメータグループ
DBParameterGroupName: !Ref DBParameterGroup
#所属するセキュリティグループ
VPCSecurityGroups:
- !ImportValue "private-sg"
#スナップショットにタグをコピー
CopyTagsToSnapshot: true
#バックアップ保持期間
BackupRetentionPeriod: 1
#タグ
Tags:
- Key: "Name"
Value: !Ref DBInstanceName
#スタックの削除時にリソースと (該当する場合) そのすべてのコンテンツを削除
DeletionPolicy: "Delete"
#RDSパラメータグループ
DBParameterGroup:
Type: "AWS::RDS::DBParameterGroup"
#以下、パラメータグループのプロパティ
Properties:
#ファミリー
Family: !Sub "MySQL${MySQLMajorVersion}"
#パラメータグループの説明
Description: !Sub "${DBInstanceName}-parm-${AppName}"
#参考
この記事は以下の情報を参考にして執筆しました。