CloudFormationを使用して、Elastic BeanstalkのALB環境を構築
以下のページで、Elastic Beanstalkの最小構成をご紹介しました。
今回は上記を発展させて、Elastic BeanstalkでALB構成を作成します。
構築する環境
VPC内に、Elastic Beanstalk環境を構築します。
具体的には、ALBおよびAuto Scalingグループで構成されたWebサーバー環境を作成します。
プラットフォームはPython3.8を選択します。
VPCには2つのAZに2つずつサブネットを作成します。
それぞれパブリックサブネットとプライベートサブネットとします。
EC2インスタンス上で動作するPythonスクリプトを、自動的にビルドします。
具体的には、CodeBuildでスクリプトを作成後、S3バケットに配置します。
このCodeBuildを実行するトリガーは、CloudFormationカスタムリソースを使用します。
またElastic Beanstalkを構築を開始するタイミングを、CloudFormationのWaitConditionで制御します。
具体的には、CodeBuildによってS3バケットにソースバンドルの配置が完了後に、Elastic Beanstalkの構築が開始されるように工夫します。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-fa/tree/main/143
テンプレートファイルのポイント解説
(参考)VPC
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCidrBlock
IGW:
Type: AWS::EC2::InternetGateway
IGWAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref IGW
EIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NATGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt EIP.AllocationId
SubnetId: !Ref PublicSubnet1
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp1
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone1}"
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp2
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone2}"
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp3
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone1}"
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp4
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone2}"
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
RouteToInternet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref IGW
PublicSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
RouteToNATGateway:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NATGateway
PrivateSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable
PrivateSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable
Code language: YAML (yaml)
ALBおよびAuto Scalingグループの土台となるVPCやサブネット等を定義します。
特にポイントとなるリソースはNATゲートウェイです。
今回の構成では、Auto Scalingグループはプライベートサブネットに作成します。
つまりElastic Beanstalkで管理されるEC2インスタンスがプライベートサブネットに作成されることになります。
Elastic Beanstalkにおいて、プライベートサブネットにEC2インスタンスする場合、注意するべき点があります。
それはインターネットへの到達性です。
プライベートサブネット – インスタンスは NAT デバイスを使用してインターネットにアクセスします。
Amazon VPC で Elastic Beanstalk を使用する
上記に従い、パブリックサブネットにNATゲートウェイを配置します。
そしてプライベートサブネット用のルートテーブルに、同ゲートウェイ向けのルートを定義します。
Elastic Beanstalk
Resources:
Application:
Type: AWS::ElasticBeanstalk::Application
Properties:
ApplicationName: !Sub "${Prefix}-application"
ApplicationVersion:
Type: AWS::ElasticBeanstalk::ApplicationVersion
Properties:
ApplicationName: !Ref Application
SourceBundle:
S3Bucket: !Ref BucketName
S3Key: !Ref SourceBundleName
Environment:
Type: AWS::ElasticBeanstalk::Environment
Properties:
ApplicationName: !Ref Application
CNAMEPrefix: !Ref Prefix
EnvironmentName: !Sub "${Prefix}-env"
TemplateName: !Ref ConfigurationTemplate
Tier:
Name: WebServer
Type: Standard
VersionLabel: !Ref ApplicationVersion
ConfigurationTemplate:
Type: AWS::ElasticBeanstalk::ConfigurationTemplate
Properties:
ApplicationName: !Ref Application
OptionSettings:
- Namespace: aws:autoscaling:asg
OptionName: MaxSize
Value: !Ref MaxSize
- Namespace: aws:autoscaling:asg
OptionName: MinSize
Value: !Ref MinSize
- Namespace: aws:autoscaling:launchconfiguration
OptionName: IamInstanceProfile
Value: !Ref InstanceProfile
- Namespace: aws:ec2:instances
OptionName: InstanceTypes
Value: !Ref InstanceType
- Namespace: aws:ec2:instances
OptionName: SupportedArchitectures
Value: !Ref InstanceArchitecture
- Namespace: aws:ec2:vpc
OptionName: VPCId
Value: !Ref VPC
- Namespace: aws:ec2:vpc
OptionName: Subnets
Value: !Join
- ","
- - !Ref PrivateSubnet1
- !Ref PrivateSubnet2
- Namespace: aws:ec2:vpc
OptionName: ELBSubnets
Value: !Join
- ","
- - !Ref PublicSubnet1
- !Ref PublicSubnet2
- Namespace: aws:elasticbeanstalk:environment
OptionName: EnvironmentType
Value: !Ref EnvironmentType
- Namespace: aws:elasticbeanstalk:environment
OptionName: ServiceRole
Value: !Sub "arn:aws:iam::${AWS::AccountId}:role/service-role/aws-elasticbeanstalk-service-role"
- Namespace: aws:elasticbeanstalk:environment
OptionName: LoadBalancerType
Value: !Ref LoadBalancerType
SolutionStackName: !Ref SolutionStackName
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref InstanceRole
InstanceRole:
Type: AWS::IAM::Role
DeletionPolicy: Delete
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- ec2.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier
Code language: YAML (yaml)
本ページでは、Elastic Beanstalkを使用してALB環境を作成する方法を中心に取り上げます。
Elastic Beanstalkに関する基本的な事項については、以下のページをご確認ください。
Elastic Beanstalkを使用してALBを作成する上で、ConfigurationTemplateは重要なリソースです。
OptionSettingsプロパティでALB用の設定を行います。
以下に重要なパラメータを挙げます。
名前空間aws:autoscaling:asgでは、MaxSizeおよびMinSizeの2つを設定します。
これはAuto Scalingグループ内に作成するEC2インスタンスの最大値と最小値を指定するものです。
今回は両パラメータに「2」を指定します。
名前空間aws:ec2:vpcでは、SubnetsおよびELBSubnetsの2つを設定します。
前者はAuto Scalingグループを作成するサブネット、後者はELBに関連づけるサブネットを指定します。
今回の構成では、プライベートサブネットにAuto Scalingグループを作成しますので、前者に2つのプライベートサブネットを指定します。
そしてELBにはパブリックサブネットを関連づける必要がありますので、後者に2つのパブリックサブネットを指定します。
名前空間aws:elasticbeanstalk:environmentでは、EnvironmentTypeおよびLoadBalancerTypeの2つを設定します。
前者には「LoadBalanced」を、後者には「application」を指定することで、ALBを作成できます。
(参考)CodeBuildプロジェクト
Resources:
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Artifacts:
Type: NO_ARTIFACTS
Cache:
Type: NO_CACHE
Environment:
ComputeType: !Ref ProjectEnvironmentComputeType
EnvironmentVariables:
- Name: BUCKET_NAME
Type: PLAINTEXT
Value: !Ref BucketName
- Name: SOURCE_BUNDLE_NAME
Type: PLAINTEXT
Value: !Ref SourceBundleName
- Name: SOURCE_FILE_NAME
Type: PLAINTEXT
Value: !Ref SourceFileName
Image: !Ref ProjectEnvironmentImage
ImagePullCredentialsType: CODEBUILD
Type: !Ref ProjectEnvironmentType
PrivilegedMode: true
LogsConfig:
CloudWatchLogs:
Status: DISABLED
S3Logs:
Status: DISABLED
Name: !Ref Prefix
ServiceRole: !GetAtt CodeBuildRole.Arn
Source:
Type: NO_SOURCE
BuildSpec: !Sub |
version: 0.2
phases:
pre_build:
commands:
- |
cat << EOF > $SOURCE_FILE_NAME
import datetime
import subprocess
def application(environ, start_response):
result = subprocess.run(
['ec2-metadata', '-i'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding='utf-8'
)
start_response("200 OK", [
("Content-Type", "text/html")
])
return [bytes(result.stdout, 'utf-8')]
EOF
build:
commands:
- zip $SOURCE_BUNDLE_NAME -r * .[^.]*
post_build:
commands:
- aws s3 cp $SOURCE_BUNDLE_NAME s3://$BUCKET_NAME/
Visibility: PRIVATE
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- codebuild.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: PutS3ObjectPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:PutObject
Resource:
- !Sub "arn:aws:s3:::${BucketName}/*"
Code language: YAML (yaml)
CodeBuildを使用して、Elastic Beanstalk上で実行させるアプリケーションをビルドし、S3バケットに配置します。
実行するアプリケーションの内容ですが、アプリケーションを実行するEC2インスタンスのIDを返すものです。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- CodeBuildプロジェクト:fa-141
- S3バケット:fa-141
- Elastic Beanstalkアプリケーション:fa-143-application
- Elastic Beanstalk環境:fa-143-env
AWS Management Consoleから各リソースの作成状況を確認します。
CodeBuildプロジェクトの動作状況を確認します。
CodeBuildが自動実行されています。
これはCloudFormationカスタムリソースに紐づくLambda関数によって、自動的にプロジェクトが開始されたということです。
これを受けてElastic Beanstalk上で実行するソースバンドルがビルドされました。
S3バケットを確認します。
オブジェクトが配置されています。
CodeBuildプロジェクトによってビルドされたソースバンドルです。
このファイルがElastic Beanstalk上で実行されます。
動作確認
準備が整いましたので、Elastic Beanstalkを確認します。
まずElastic Beanstalkアプリケーションを確認します。
確かにアプリケーションが作成されています。
アプリケーションという枠組みの中に、Elastic Beanstalk環境が作成されています。
Elastic Beanstalk環境を確認します。
環境が正常に作成されています。
環境作成時のログを確認します。
確かにALB等が構築されていることがわかります。
そしてAuto Scalingグループ内に2つのEC2インスタンスが作成されていることもわかります。
このアプリケーションにアクセスします。
$ curl http://fa-143.ap-northeast-1.elasticbeanstalk.com
instance-id: i-04435211511b2387b
$ curl http://fa-143.ap-northeast-1.elasticbeanstalk.com
instance-id: i-03162d9ad59a56328
Code language: Bash (bash)
確かにALB配下の2つのインスタンスにアクセスできています。
このようにElastic Beanstalkを用いて、ALB環境を構築することができます。
最後にセキュリティグループについて確認します。
Elastic Beanstalkによって、自動的に2つのセキュリティグループが作成されます。
- ALB用
- EC2インスタンス用
それぞれを確認します。
1枚目がALB用です。
全送信元からのHTTP通信(80/tcp)を許可する内容です。
2枚目がEC2インスタンス用です。
ALB用セキュリティグループからのHTTP通信(80/tcp)を許可する内容です。
まとめ
Elastic BeanstalkでALB構成を作成しました。