本連載では、以下のイメージの構成にあるAWSリソース基盤自動化環境の構築を実践しています。
前回は、ALB、ElastiCache、S3といったリソースアクセス、SQSへのキュー送信を行うFrontend Webアプリケーションにおいて、Spring Cloud AWSを用いて取得したスタック情報を使ったアプリケーションの設定実装を紹介しました。 今回からは実装したアプリケーションを実行するためのECSクラスタ、タスク定義、サービス実行と順次CloudFormationテンプレートを作成し実行していきます。 実際のソースコードは GitHub 上にコミットしています。 ソースコード中で本質的でない記述を一部省略しているので、実行コードを作成する場合は、必要に応じて適宜GitHub上のソースコードも参照してください。
事前準備として、前回実装したアプリケーションのコンテナイメージを作成し、DockerHubへプッシュしておきましょう。 作業の方法は クラウドネイティブ基本第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クラスタは クラウドネイティブ基本第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)〜(G)の通りです。
記述 | 説明 |
起動するECSの Amazon Linux AMIをSystems Manager Parameter Store経由で取得 し、パラメータとして定義します。 | |
パラメータEnvTypeに応じて、適用するパラメータ値を変更するよう、Mappings要素を定義します。 | |
ECSクラスタの実行に必要なAmazonEC2ContainerServiceforEC2Roleポリシーが付与されたIAMロールを定義します。詳細は AWS::IAM::Role を参照してください。 | |
(C)のIAMロールが付与されたインスタンスプロファイルを定義します。詳細は AWS::IAM::InstanceProfile を参照してください。 | |
ECSクラスタを定義します。詳細は AWS::ECS::Cluster を参照してください。 | |
クラスタのオートスケーリンググループを定義します。詳細は AWS::AutoScaling::AutoScalingGroup を参照してください。 | |
FindInMap関数を用いて、作成する環境に応じてパラメータを切り替えます。 | |
ECSクラスタの起動オプション設定を定義します。詳細は AWS::AutoScaling::LaunchConfiguration を参照してください。 | |
クラスタ起動に実行する起動スクリプトを定義します。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等の資格を持ち、アプリケーション基盤・クラウドなど様々な開発プロジェクト支援にも携わる。