本連載では、以下のイメージの構成のようなマイクロサービスアーキテクチャにおける、基盤自動化環境の構築を実践していきます。

本連載で構築していく基盤自動化環境のイメージ

前回は、テンプレートのコード補完/文法チェック等を実行する検証プラグインのインストール方法や、統合開発環境「IntelliJ IDEA」の設定方法を概説しました。続く今回は、CloudFormationの簡単なサンプルを作成し、テンプレート記述の基本を解説した上で、実行するためのヘルパースクリプトや実行エラーの確認方法などについて説明します。

なお、実際のソースコードはGitHub上にコミットしています。以降のソースコードでは本質的でない記述を一部省略しているので、実行コードを作成する場合は、必要に応じて適宜GitHub上のソースコードも参照してください。

CloudFormationテンプレート記述の基本

連載第21回で説明した通り、テンプレートファイルではResources要素が必須となります。加えて、Template VersionやDescritpion、Parameters、Outputsなどが一般的によく使用される要素です。ここでは、シンプルにVPCを構築するテンプレート(test-cfn.yml)を作成してみましょう。

AWSTemplateFormatVersion: '2010-09-09'                                    #(A)

Description: Sample CloudFormation template with YAML - VPC               #(B)

Parameters:                                                               #(C)
  VPCName:                                                                #(D)
    Description: Target VPC Stack Name                                    #(E)
    Type: String
    MinLength: 1
    MaxLength: 255
    AllowedPattern: ^[a-zA-Z][-a-zA-Z0-9]*$
    Default: mynavi-sample-cloudformation-vpc
  VPCCiderBlock:
    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.0.0.0/16

Resources:                                                                #(F)
  VPC:                                                                    #(G)
    Type: AWS::EC2::VPC                                                   #(H)
    Properties:                                                           #(I)
      CidrBlock: !Sub ${VPCCiderBlock}                                    #(J)
      InstanceTenancy: default
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub ${VPCName}

Outputs:                                                                  #(K)
  VPCID:                                                                  #(L)
    Description: VPC ID                                                   #(M)
    Value: !Ref VPC
    Export:
      Name: !Sub ${AWS::StackName}-VPCID

テンプレートの記述の基本となるポイントは下表の通りです。

記述 説明
A テンプレートバージョンを指定します。2019年11月時点では、"2010-09-09"が唯一のバージョンです
B Description要素にはテンプレートの概要を記述します
C Parameter要素では、Stack構築時にパラメータとして動的に設定する値を記述します。パラメータ化する対象は、テンプレートの再利用性を踏まえて決定します
D Parameter要素の直下では、パラメータ論理名を任意に定義します。これはユニークな値でなければなりません。なお、テンプートに指定できるパラメータの数は最大60個です
E Parameter要素でパラメータの属性などを定義していきます。こちらに記載する内容は後述の表を参照してください。
F 記述が必須となるResources要素です。Stackとして構築するAWSリソースを定義していきます
G Resources要素の直下では、リソース論理名を任意に定義します。これはユニークな値でなければなりません
H AWSリソースのタイプを定義します。AWS::(ServiceName)::(Resource)のかたちで指定されます
I AWSリソースは必ず必須となるいくつかのプロパティと、オプションで設定するプロパティが存在します。各リソースタイプによりプロパティ定義は異なります
J プロパティ内で、パラメータ値を設定する場合、組み込みファンクション「!Sub」で変数を含む文字列を指定した変数値で置き換えます
K スタック構築後、コンソール上から表示させたいプロパティや、他のテンプレートに渡したいパラメータがある場合(クロススタックリファレンス)、Outputs要素を指定します
L Outputs要素の直下では、アウトプット論理名を任意に定義します。これはユニークな値でなければなりません
M Outputs要素では、論理名の配下に、出力値の説明であるDescription、実際の出力値となるValue(必須)、出力後の物理名となるExport:Name属性を指定します。詳細は、AWS公式サイトの「出力」を参照してください

以下に、Parameter要素で記載する「Parameters」の主なプロパティをまとめました。

プロパティ 説明 必須
Description プロパティの詳細な説明を記載します
Type パラメータのデータ型を指定します。String、Numner、List<Number>、CommaDelimitedList、AWS固有パラメータ、SSMパラメータが指定可能です。詳細は、AWS公式サイトの「パラメータ」を参照してください
MinLength 文字列型プロパティの最小文字数を設定します
MaxLength 文字列型プロパティの最大文字数を設定します
MinValue 数字型プロパティの最小値を設定します
MaxValue 数字型プロパティの最大値を設定します
AllowedPattern 入力可能な文字列のパターンを正規表現で設定します
AllowedValues 入力可能な文字列を一覧で指定します
NoEcho (AWSコンソールでの)入力時にマスク表示(*)する場合設定します
ConstraintDescription 入力値が制約に引っかかった時に表示する説明を記述します

テンプレート作成後、AWS CLIを使ってコマンド実行します。スタックを作成するには、aws cloudformation create-stackコマンドを実行するのが基本ですが、このコマンドでは、一度Stackを作成すると、アップデートなどを行う際も、いったんaws cloudformation delete-stackコマンドなどでスタックを削除してから再実行する必要があります。ChangeSetを同時に作成し、初回作成後もテンプレートを更新した場合もそのまま使用可能なaws cloudformation deployコマンドを使用して、スタックを作成しましょう。

コマンド実行の引数として、テンプレートのファイルパスや、入力パラメータなど毎回長いコマンドを実行するのも大変なため、実行のヘルパースクリプトを以下の通り作成します。

#!/usr/bin/env bash

stack_name="mynavi-sample-test"
template_path="test-cfn.yml"

#aws cloudformation create-stack --stack-name ${stack_name} --template-body file://${template_path} --capabilities CAPABILITY_IAM
# It is better cloudformation deploy option because command can execute even if stack existing(no need to delete existing stack).
aws cloudformation deploy --stack-name ${stack_name} --template-file ${template_path} --capabilities CAPABILITY_IAM

引数は、作成時のスタック名とテンプレートファイルのパスです。今回は関係ありませんが、IAMロールを作成する際に必要なcapabilitiesオプションを指定して実行しています。

上記はターミナルなどからも実行できますが、ここでは、テンプレート作成エディタで使っているIntelliJ IDEA上から作成したスクリプトを実行します。

IntelliJ IDEA上から作成したスクリプトを実行

コマンドが正常実行されると、下記の通り、AWSコンソール上のCloudFormationサービスからもスタックが作成されたことを確認できます。

AWSコンソール上のCloudFormationサービスからもスタックの作成を確認できる

一方、テンプレートに記述誤りがあり、CloudFormation実行中に誤ってエラーが発生した場合はどうなるのでしょうか? 単純な記法誤りなどは、前回のイメージにもあった通り、IntelliJ IDEAでコーディングしている段階でエラー検出されます。エラーが検出されている中で強引に実行しても、以下のように、スクリプト実行時にエラーで終了してしまいます。

エラー検出中に無理に実行しても、スクリプト実行時にエラー終了する

しかし、記法上問題なくても論理的にありえないエラーの場合などは実行中にエラーが発生します。以下は、VPC上のCIDRを論理的にありえないアドレス(172.256.0.0/16)になるように入力パラメータを変更して実行した場合の例です。

#!/usr/bin/env bash

stack_name="mynavi-sample-test"
template_path="test-cfn.yml"
parameters="VPCCiderBlock=172.256.0.0/16"

#aws cloudformation create-stack --stack-name ${stack_name} --template-body file://${template_path} --capabilities CAPABILITY_IAM
# It is better cloudformation deploy option because command can execute even if stack existing(no need to delete existing stack).

if [ "$parameters" == "" ]; then
    aws cloudformation deploy --stack-name ${stack_name} --template-file ${template_path} --capabilities CAPABILITY_IAM
else
    aws cloudformation deploy --stack-name ${stack_name} --template-file ${template_path} --parameter-overrides ${parameters} --capabilities CAPABILITY_IAM
fi

この場合、コマンド実行中にエラーとなり、それまでの処理はロールバックされます。AWSコンソール上で、CloudFormationサービスの対象のスタックで、イベントタブからエラーとなった原因を確認できます。

AWSコンソール上でエラー原因を確認できる

上記は単純な論理的エラーの例ですが、作成対象のリソースによっては、IAM権限不足や設定誤りなど、テンプレートの初回作成時は実行エラーになるケースがしばしば発生します。

都度ロールバックやテンプレートの修正、再実行の繰り返しになるため、上記のように記法誤りの早期検出や、ヘルパースクリプトの作成など繰り返し再実行がしやすい環境を用意して、テンプレートの実装を進めていくことを推奨します。

また、ある程度実装が進んだ段階になると、本番と同等相当のパラメータを使って、複数で構成されるテンプレートの挙動をまとめて確認し、結果を証跡として残したいといったニーズが出てくるかと思います。 そこで次回は、AWSから提供されている、マルチリージョンでテンプレートのテスト実行が複数同時に可能なオープンソースツール「taskcat」を使って、作成したテンプレートをテストする環境を構築し、結果を出力する方法の解説を進めていきます。

著者紹介


川畑 光平(KAWABATA Kohei) - NTTデータ 課長代理

金融機関システム業務アプリケーション開発・システム基盤担当を経て、現在はソフトウェア開発自動化関連の研究開発・推進に従事。

Red Hat Certified Engineer、Pivotal Certified Spring Professional、AWS Certified Solutions Architect Professional等の資格を持ち、アプリケーション基盤・クラウドなどさまざまな開発プロジェクト支援にも携わる。2019 APN AWS Top Engineers & Ambassadors選出。

本連載の内容に対するご意見・ご質問は Facebook まで。