本連載では、以下のイメージの構成にあるAWSリソース基盤自動化環境の構築を実践しています。
前回は、ALB、ElastiCache、S3といったリソースアクセス、SQSへのキュー送信を行うFrontend Webアプリケーションにおいて、Spring Cloud AWSを用いて取得したスタック情報を使ったアプリケーションの設定実装を紹介しました。
今回からは実装したアプリケーションを実行するためのECSクラスタ、タスク定義、サービスと、順次CloudFormationテンプレートを作成して実行していきます。
なお、実際のソースコードはGitHub上にコミットしています。以降のソースコードでは本質的でない記述を一部省略しているので、実行コードを作成する場合は、必要に応じて適宜GitHub上のソースコードも参照してください。
事前準備
事前準備として、前回実装したアプリケーションのコンテナイメージを作成し、DockerHubへプッシュしておきましょう。作業の方法は連載「AWSで作るクラウドネイティブアプリケーションの基本」の第7回を参考にしてください。Backend Serviceアプリケーションと、Frontend Webアプリケーションのコンテナイメージを作成するDockerfileのサンプルはそれぞれ以下の通りです。
# Dockerfile for sample service using embedded tomcat server
FROM centos:centos7
MAINTAINER debugroom
RUN yum install -y \
java-1.8.0-openjdk \
java-1.8.0-openjdk-devel \
wget tar iproute git
RUN rm -f /etc/rpm/macros.image-language-conf && \
sed -i '/^override_install_langs=/d' /etc/yum.conf && \
yum -y update glibc-common && \
yum clean all
ENV LANG="ja_JP.UTF-8" \
LANGUAGE="ja_JP:ja" \
LC_ALL="ja_JP.UTF-8"
RUN wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
RUN sed -i s/\$releasever/6/g /etc/yum.repos.d/epel-apache-maven.repo
RUN yum install -y apache-maven
ENV JAVA_HOME /etc/alternatives/jre
RUN git clone https://github.com/debugroom/mynavi-sample-aws-cloudformation.git /usr/local/mynavi-sample-aws-cloudformation
RUN mvn install -f /usr/local/mynavi-sample-aws-cloudformation/common/pom.xml
RUN mvn package -f /usr/local/mynavi-sample-aws-cloudformation/backend-service/pom.xml
RUN cp /etc/localtime /etc/localtime.org
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
EXPOSE 8080
CMD java -jar -Dspring.profiles.active=$ENV_TYPE /usr/local/mynavi-sample-aws-cloudformation/backend-service/target/mynavi-sample-cloudformation-backend-0.0.1-SNAPSHOT.jar
# Dockerfile for sample service using embedded tomcat server
FROM centos:centos7
MAINTAINER debugroom
RUN yum install -y \
java-1.8.0-openjdk \
java-1.8.0-openjdk-devel \
wget tar iproute git
RUN rm -f /etc/rpm/macros.image-language-conf && \
sed -i '/^override_install_langs=/d' /etc/yum.conf && \
yum -y update glibc-common && \
yum clean all
ENV LANG="ja_JP.UTF-8" \
LANGUAGE="ja_JP:ja" \
LC_ALL="ja_JP.UTF-8"
RUN wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
RUN sed -i s/\$releasever/6/g /etc/yum.repos.d/epel-apache-maven.repo
RUN yum install -y apache-maven
ENV JAVA_HOME /etc/alternatives/jre
RUN git clone https://github.com/debugroom/mynavi-sample-aws-cloudformation.git /usr/local/mynavi-sample-aws-cloudformation
RUN mvn install -f /usr/local/mynavi-sample-aws-cloudformation/common/pom.xml
RUN mvn package -f /usr/local/mynavi-sample-aws-cloudformation/frontend-webapp/pom.xml
RUN cp /etc/localtime /etc/localtime.org
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
EXPOSE 8080
CMD java -jar -Dspring.profiles.active=$ENV_TYPE /usr/local/mynavi-sample-aws-cloudformation/frontend-webapp/target/mynavi-sample-cloudformation-frontend-0.0.1-SNAPSHOT.jar
ECSクラスタスタック構築テンプレート
ECSクラスタは、連載「AWSで作るクラウドネイティブアプリケーションの基本」の第8回と同等のものを構築します。ECSクラスタをCloudFormationで構築する場合、リソースタイプが「AWS::ECS::Cluster」で、クラスタの実行に必要なIAMロール「AWS::IAM::Role」と、そのロールを設定したインスタンスプロファイル「AWS::IAM::InstanceProfile」、オートスケールルールを設定した「AWS::AutoScaling::AutoScalingGroup」に加えて、起動設定を定義した「AWS::AutoScaling::LaunchConfiguration」が必要です。プロパティとして設定可能な属性は、上記リンク先の通りですが、加えて、ECSを「商用環境」「ステージング環境」「開発環境」という3つのパターンに分けて作成するようにします。
テンプレートのサンプルは以下の通りです。
AWSTemplateFormatVersion: '2010-09-09'
// omit
Parameters:
ECSAMI:
Description: AMI ID
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> #(A)
Default: /aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id
EnvType:
Description: Which environments to deploy your service.
Type: String
AllowedValues:
- Dev
- Staging
- Production
Default: Dev
Mappings:
FrontendClusterDefinitionMap: #(B)
Production:
"InstanceType" : "r4.large"
"DesiredCapacity" : 1
"EC2InstanceMaxSizeOfECS": 3
"KeyPairName" : "test"
// omit
Resources:
ECSRole: #(C)
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: ec2.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
IamInstanceProfile: #(D)
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref ECSRole
FrontendECSCluster: #(E)
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub sample-frontend-cluster-${EnvType}
Tags:
- Key: Name
Value: !Sub FrontendECSCluster-${EnvType}
// omit
FrontendECSAutoScalingGroup: #(F)
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
VPCZoneIdentifier:
- Fn::ImportValue: !Sub ${VPCName}-PublicSubnet1
- Fn::ImportValue: !Sub ${VPCName}-PublicSubnet2
LaunchConfigurationName: !Ref FrontendECSLaunchConfiguration
MinSize: '0'
MaxSize: !FindInMap [FrontendClusterDefinitionMap, !Ref EnvType, EC2InstanceMaxSizeOfECS] #(G)
DesiredCapacity: !FindInMap [FrontendClusterDefinitionMap, !Ref EnvType, DesiredCapacity]
Tags:
- Key: Name
Value: !Sub FrontendECSCluster-${EnvType}
PropagateAtLaunch: true
CreationPolicy:
ResourceSignal:
Timeout: PT5M
UpdatePolicy:
AutoScalingReplacingUpdate:
WillReplace: true
FrontendECSLaunchConfiguration: #(H)
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !Ref ECSAMI
InstanceType: !FindInMap [FrontendClusterDefinitionMap, !Ref EnvType, InstanceType]
IamInstanceProfile: !Ref IamInstanceProfile
KeyName: !FindInMap [FrontendClusterDefinitionMap, !Ref EnvType, KeyPairName]
SecurityGroups:
- Fn::ImportValue: !Sub ${VPCName}-SecurityGroupFrontendEcsCluster
AssociatePublicIpAddress: true
UserData: #(I)
Fn::Base64: !Sub |
#!/bin/bash -xe
echo ECS_CLUSTER=${FrontendECSCluster} >> /etc/ecs/ecs.config
yum install -y aws-cfn-bootstrap
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource FrontendECSAutoScalingGroup --region ${AWS::Region}
// omit
ECSクラスタのテンプレートの記述の基本となるポイントは下表の通りです。
記述 | 説明 |
---|---|
A | 起動するECSのAmazon Linux AMIをSystems Manager Parameter Store経由で取得し、パラメータとして定義します |
B | パラメータEnvTypeに応じて、適用するパラメータ値を変更するよう、Mappings要素を定義します |
C | ECSクラスタの実行に必要なAmazonEC2ContainerServiceforEC2Roleポリシーが付与されたIAMロールを定義します。詳細はAWS::IAM::Roleを参照してください |
D | CのIAMロールが付与されたインスタンスプロファイルを定義します。詳細は AWS::IAM::InstanceProfileを参照してください。 |
E | ECSクラスタを定義します。詳細はAWS::ECS::Clusterを参照してください |
F | クラスタのオートスケーリンググループを定義します。詳細はAWS::AutoScaling::AutoScalingGroupを参照してください |
G | FindInMap関数を用いて、作成する環境に応じてパラメータを切り替えます |
H | ECSクラスタの起動オプション設定を定義します。詳細はAWS::AutoScaling::LaunchConfigurationを参照してください |
I | クラスタ起動に実行する起動スクリプトを定義します。ecs.configへのクラスタ定義の追加や、aws-cfn-bootstrapのインストール、cfn-signalの実行がECSクラスタの起動に必要になります |
なお、プライベートサブネットにECSクラスタを構築する場合は、起動スクリプト内のyumコマンドを実行するため、NATGatewayを設置して、ルートテーブルをプライベートサブネットに関連付けておく必要があります。上記ではNATGatewayの設定をテンプレート記述に含めていませんが、本連載の第27回を参考にNATGatewayを事前に設定しておいてください。
ヘルパースクリプトの実行
作成したテンプレートに対し、以下のように、スタック名とテンプレートパスを変更してヘルパースクリプトを実行します。
#!/usr/bin/env bash
stack_name="mynavi-sample-ecs-cluster"
template_path="sample-ecs-cluster-cfn.yml"
parameters="EnvType=Dev"
aws cloudformation deploy --stack-name ${stack_name} --template-file ${template_path} --parameter-overrides ${parameters} --capabilities CAPABILITY_IAM
実行が正常に終了すると、ECSクラスタが作成されます。
以上、今回はECSクラスタを構築するCloudFormationテンプレートを実装しました。次回は、ECSタスク定義を行うCloudFormationテンプレートを作成する手順を紹介します。
著者紹介
川畑 光平(KAWABATA Kohei) - NTTデータ
金融機関システム業務アプリケーション開発・システム基盤担当、ソフトウェア開発自動化関連の研究開発を経て、デジタル技術関連の研究開発・推進に従事。
Red Hat Certified Engineer、Pivotal Certified Spring Professional、AWS Certified Solutions Architect Professional等の資格を持ち、アプリケーション基盤・クラウドなど様々な開発プロジェクト支援にも携わる。AWS Top Engineers & Ambassadors選出。
本連載の内容に対するご意見・ご質問は Facebook まで。