本連載では、以下のイメージの構成にあるAWSリソース基盤自動化環境の構築を実践しています。
前回は、S3およびSQSを構築するテンプレートを実装しました。続く今回は、これまで実装してきたテンプレートの親となるネストテンプレートを作成する方法を紹介します。
なお、実際のソースコードはGitHub上にコミットしています。以降のソースコードでは本質的でない記述を一部省略しているので、実行コードを作成する場合は、必要に応じて適宜GitHub上のソースコードも参照してください。
ネストテンプレートの作成
第21回で、CloudFormationがサポートする機能として、複数のテンプレートでネスト(親子)を構成する「NestedStack」があることを紹介しました。NestedStackはテンプレートを分割したり、複数のテンプレートをまとめて実行したいとき、共通のパラメータや定義を複数のテンプレートで共有したいときに利用します。ただし、制約として参照するテンプレートをS3へアップロードしておく必要があります。
NestedStackを使用する場合、リソースタイプが、AWS::CloudFormation::Stackであるリソース定義を使用します。プロパティとして設定可能な属性は、上記リンク先の通りですが、VPCとサブネット、インターネットゲートウェイ、セキュリティグループについては既に構築済みであることを前提とします。
今回はこれまでの連載で実装してきたRDS、ElastiCache、S3、SQSを構築するテンプレートを子テンプレートとして、開発環境として1つにまとめて実行するための親テンプレートを作成してみます。テンプレートのサンプルは以下の通りです。
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample CloudFormation template with YAML - parent stack for dev environment.
Parameters:
VPCName:
Description: Target VPC Stack Name
Type: String
MinLength: 1
MaxLength: 255
AllowedPattern: ^[a-zA-Z][-a-zA-Z0-9]*$
Default: mynavi-sample-cloudformation-vpc
EnvType: #(A)
Description: Which environments to deploy your service.
Type: String
AllowedValues: ["Dev"]
Default: Dev
LocalhostIpAddress: #(B)
Description: CiderBlock paramater for VPC
Type: String
MinLength: 9
MaxLength: 18
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
Default: 172.200.2.58/32
Resources:
RDSDevStack: #(C)
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: ./sample-rds-cfn.yml #(D)
Parameters: #(E)
VPCName: !Sub ${VPCName}
EnvType: !Sub ${EnvType}
SecurityGroupDev: !Ref SecurityGroupRdsPostgresForDev
DynamoDBDevStack: #(F)
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: ./sample-dynamodb-cfn.yml
Parameters:
VPCName: !Sub ${VPCName}
EnvType: !Sub ${EnvType}
# ElastiCache is not permitted public access, use local redis except dev environmant in vpc.
ElastiCacheDevStack: #(G)
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: ./sample-elasticache-cfn.yml
Parameters:
VPCName: !Sub ${VPCName}
EnvType: !Sub ${EnvType}
SecurityGroupDev: !Ref SecurityGroupElastiCacheRedisForDev
S3DevStack: #(H)
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: ./sample-s3-cfn.yml
Parameters:
EnvType: !Sub ${EnvType}
SQSDevStack: #(I)
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: ./sample-sqs-cfn.yml
Parameters:
EnvType: !Sub ${EnvType}
SecurityGroupRdsPostgresForDev: #(J)
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: SecurityGroupRdsPostgresForDev
GroupDescription: db access only local machine for dev
VpcId:
Fn::ImportValue: !Sub ${VPCName}-VPCID
Tags:
- Key: Name
Value: !Sub ${VPCName}-SecurityGroupRdsPostgresForDev
SecurityGroupIngressRdsPostgresForDev: #(K)
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref SecurityGroupRdsPostgresForDev
IpProtocol: tcp
FromPort: 5432
ToPort: 5432
CidrIp: !Ref LocalhostIpAddress
SecurityGroupElastiCacheRedisForDev: #(L)
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: SecurityGroupElastiCacheForDev
GroupDescription: elasticache access only local machine for dev
VpcId:
Fn::ImportValue: !Sub ${VPCName}-VPCID
Tags:
- Key: Name
Value: !Sub ${VPCName}-SecurityGroupElastiCacheRedisForDev
SecurityGroupIngressElastiCacheRedisForDev: #(M)
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref SecurityGroupElastiCacheRedisForDev
IpProtocol: tcp
FromPort: 6379
ToPort: 6379
CidrIp: !Ref LocalhostIpAddress
NestedStackとして作成した親テンプレートの記述の基本となるポイントは下表の通りです。
記述 | 説明 |
---|---|
A | パラメータとして、EnvTypeを指定します。今回は開発環境向けのテンプレートとするため、デフォルト値”Dev”のみを許容する設定としておきます |
B | パラメータとして、LocalhostIpAddressを指定します。開発環境の端末のIPアドレスを指定して、RDSおよびElastiCacheへのアクセスを許可するセキュリティグループへ渡す用途で使用します |
C | RDSを構築するテンプレートを開発環境用スタックとしてリソース定義します |
D | 以前実装したRDSテンプレートの相対パスを指定します。本来、S3にテンプレートをアップロードしてそのオブジェクトキーを指定しなければなりませんが、後述の手順でパスを置き換えるコマンドを実行します |
E | 親テンプレートから子テンプレートに渡すパラメータを指定します。子テンプレートに定義したParametersと同じ論理名を指定し、渡すパラメータを設定します |
F | DynamoDBを構築するテンプレートを開発環境用スタックとしてリソース定義します。子テンプレートに渡すパラメータの定義方法はEと同様です |
G | ElastiCacheを構築するテンプレートを開発環境用スタックとしてリソース定義します。子テンプレートに渡すパラメータの定義方法はEと同様です。なお、第31回でも記載しましたが、ElastiCacheのアクセスはVPC内にある開発端末にかぎりアクセスが許可されます |
H | S3を構築するテンプレートを開発環境用スタックとしてリソース定義します。子テンプレートに渡すパラメータの定義方法はEと同様です |
I | SQSを構築するテンプレートを開発環境用スタックとしてリソース定義します。子テンプレートに渡すパラメータの定義方法はEと同様です |
J | Eで定義したパラメータとして渡すセキュリティグループを定義します |
K | Jで定義した(RDSへのアクセスを許可する)セキュリティグループのインバウンド接続ルールを定義します |
L | Gで定義したパラメータとして渡すセキュリティグループを定義します |
M | Lで定義した(ElastiCacheへのアクセスを許可する)セキュリティグループのインバウンド接続ルールを定義します |
なお、生成するリソースの実行順序を制御するにはDependsOnプロパティを使用します。上記では、RDSやElastiCacheで使用するセキュリティグループを前もって作成する必要がありますが、リソース定義自体でセキュリティグループが参照されているため、自動でCloudFormationが実行順序を判断するので明示的に定義する必要はありません。
また、子テンプレートのパラメータを親テンプレートで参照したい場合は、子テンプレートでOutputs要素にパラメータを定義した後、GetAtt関数で参照します。例えば、子テンプレートに定義したRDSの開発環境のエンドポイントを参照したい場合、”!GetAtt RDSDevStack.Outputs.RDSDevInstanceEndPoint”となります。
テンプレートの生成
作成したテンプレートで指定した子テンプレートのURLは、本来S3にアップロードしてそのオブジェクトキーを指定しなければなりません。AWS CLIの「aws cloudformation package」コマンドで、特定のS3バケットを指定して実行することで、バケットへアップロードし、URLをオブジェクトキーに置き換えたテンプレートを生成できます。
事前にアップロード先のバケットを作成した上で(ここでは連載「AWSで作るクラウドネイティブアプリケーションの基本」の第25回と同様の手順で、「debugroom-mynavi-sample-cloudformation-package」というバケットを事前に作成しておきます)、パッケージを実行するヘルパースクリプトを以下のように作成して実行します。
#!/usr/bin/env bash
template_path="sample-infra-dev-cfn.yml"
output_template="sample-infra-dev-package-cfn.yml"
s3_bucket="debugroom-mynavi-sample-cloudformation-package"
aws cloudformation package --template-file ${template_path} --s3-bucket ${s3_bucket} --output-template-file ${output_template}
実行が正常に終了すると、URLのパスが置き換わったテンプレートが生成されます。
AWSTemplateFormatVersion: '2010-09-09'
#omit
Resources:
RDSDevStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.ap-northeast-1.amazonaws.com/debugroom-mynavi-sample-cloudformation-package/85f621985a23d88cd5c0be512e717b3f.template
Parameters:
VPCName:
Fn::Sub: ${VPCName}
EnvType:
Fn::Sub: ${EnvType}
SecurityGroupDev:
Ref: SecurityGroupRdsPostgresForDev
#omit
生成されたテンプレートを以下のようにヘルパースクリプトを用いて実行すると、定義したリソースがまとめて実行されます。
#!/usr/bin/env bash
stack_name="mynavi-sample-infra-dev"
template_path="sample-infra-dev-package-cfn.yml"
parameters="EnvType=Dev"
aws cloudformation deploy --stack-name ${stack_name} --template-file ${template_path} --parameter-overrides ${parameters} --capabilities CAPABILITY_IAM
以上、今回はNestedStackを使い、複数のリソースをまとめて一括構築するCloudFormationテンプレートを実装しました。次回は、CloudFormationを使って作成したリソースの情報にアクセスするSpringCloudAWSアプリケーションの実装方法について解説を進めていきます。
著者紹介
川畑 光平(KAWABATA Kohei) - NTTデータ 課長代理
金融機関システム業務アプリケーション開発・システム基盤担当を経て、現在はソフトウェア開発自動化関連の研究開発・推進に従事。
Red Hat Certified Engineer、Pivotal Certified Spring Professional、AWS Certified Solutions Architect Professional等の資格を持ち、アプリケーション基盤・クラウドなどさまざまな開発プロジェクト支援にも携わる。2019 APN AWS Top Engineers & Ambassadors選出。
本連載の内容に対するご意見・ご質問は Facebook まで。