CloudFormationでInternal ALBを作成してみたので、備忘録として書いておきます。
構築するリソース
前提
- EC2は既に構築済み
- 証明書はACMで作成済み
- ALBでTLS終端
- 構築するALBはInternal
リソース
- Internal ALB
- TargetGroup
- ターゲットはEC2インスタンス
- Listener
- HTTP (HTTPSへのリダイレクト)
- HTTPS
- SecurityGroup
- TargetGroup
CFnテンプレート
alb.yml
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
AlbName:
Type: String
VpcId:
Type: AWS::EC2::VPC::Id
TargetGroupName:
Type: String
SubnetId1:
Type: AWS::EC2::Subnet::Id
SubnetId2:
Type: AWS::EC2::Subnet::Id
ListenerCertificateArn:
Type: String
Ec2InstanceId:
Type: AWS::EC2::Instance::Id
AlbSecurityGroupName:
Type: String
AlbListenerSslPolicy:
Type: String
Resources:
AlbSecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupName:
Ref: AlbSecurityGroupName
GroupDescription: "this is test"
SecurityGroupIngress:
- CidrIp: "0.0.0.0/0"
FromPort: 80
IpProtocol: tcp
ToPort: 80
- CidrIp: "0.0.0.0/0"
FromPort: 443
IpProtocol: tcp
ToPort: 443
VpcId:
Ref: VpcId
# EC2をターゲットにする場合はTargetTypeをinstanceにする
# TargetsのIdにEC2インスタンスIDを指定
AlbTargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
HealthCheckEnabled: true
HealthCheckPath: /health.php
Name:
Ref: TargetGroupName
Port: 80
Protocol: HTTP
Targets:
- Id:
Ref: Ec2InstanceId
Port: 80
TargetType: instance
VpcId:
Ref: VpcId
# ALBなのでTypeにapplicationを指定
# InternalなのでSchemeにinternalを指定
InternalAlb:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
IpAddressType: ipv4
Name:
Ref: AlbName
Scheme: internal
SecurityGroups:
- Ref: AlbSecurityGroup
Subnets:
- Ref: SubnetId1
- Ref: SubnetId2
Type: application
# HTTPで受信したアクセスはHTTPSへリダイレクト
# RedirectConfigでリダイレクト先を編集できる
# 今回はリダイレクトする際のStatusCodeは301か302を選択できるが、違いはあれど好みの問題かなと個人的に思っている
AlbListenerHttp:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
DefaultActions:
- RedirectConfig:
Port: 443
Protocol: HTTPS
StatusCode: HTTP_301
Type: redirect
LoadBalancerArn:
Ref: InternalAlb
Port: 80
Protocol: HTTP
# HTTPSのListenerは証明書が必要なので必ずCertificateArnを指定
# HTTPSのアクセスの場合はターゲットグループに転送する = EC2にトラフィックを転送
AlbListenerHttps:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
Certificates:
- CertificateArn:
Ref: ListenerCertificateArn
DefaultActions:
- TargetGroupArn:
Ref: AlbTargetGroup
Type: forward
LoadBalancerArn:
Ref: InternalAlb
Port: 443
Protocol: HTTPS
SslPolicy: AlbListenerSslPolicy
Parameter管理ファイル
以下はParametersを管理するためのファイルです。ファイルで管理しておけばどのような設定をデプロイしたか覚えておく必要はありません。忘れたらこのファイルを見ればいいのですから。
alb.stg.ini
AlbName=
VpcId=
TargetGroupName=
SubnetId1=
SubnetId2=
ListenerCertificateArn=
Ec2InstanceId=
AlbSecurityGroupName=
AlbListenerSslPolicy=
デプロイ用シェルスクリプト
CFnのパラメータはiniファイルで管理し、かつコマンドライン引数からファイル名を割り出すためにiniファイルの命名規則を決めています。こうすればコマンドライン引数を多くせず使い回すことができます。
また、$(find $base_dir -type f -name "*.yml" -exec basename {} .yml \;)
でCFnのテンプレートファイルが集約されていれば一覧を表示することができます。わざわざ書かなくても良かったんですが、ちょっとした遊び心ですw
aws cloudformation deployのオプションはこちらに詳細が書かれていますので参照してください。
deploy.bash
#!/bin/bash
# -----------------------------------------------------------
# CloudFormationを実行
#
# Usage:
# bash deploy.bash $profile $stage $service
#
# parameter-overridesのファイル命名規則 = $service.$stage.ini
# ex) alb.stg.ini (ステージングのALB用の設定ファイル)
#
# -----------------------------------------------------------
profile="$1"
service="$2"
stage="${3:-stg}"
base_dir="$(cd $(dirname $0); pwd)"
if [ -z "$profile" ]; then
echo "profileを指定してください"
exit 1
fi
if [ -z "$service" ]; then
echo "サービス名を以下から選択してください"
echo "$(find $base_dir -type f -name "*.yml" -exec basename {} .yml \;)"
exit 1
fi
stack_name="$service-$stage"
params="$service.$stage.ini"
aws cloudformation deploy \
--profile $profile \
--region ap-northeast-1 \
--template-file $base_dir/$service.yml \
--stack-name $stack_name \
--parameter-overrides $(cat $base_dir/$params | tr '\n' ' ') \
--no-fail-on-empty-changeset