1からインフラを構築する機会があったのでどうせなら次やるときも楽できるようにある程度定義ファイルを用意することにしました
terraformと迷ったのですがterraformは以前個人的に使ったことがあったので今回はcloudformationを使うことにしました
yaml対応もされたようですしね
デザイナーでごにょごにょしてテンプレート生成するか、すでに誰かが作っているであろうテンプレートを使うか、1から使うか迷ったものの調べていて思ったのはなんかよくわからん!ということだけだったので1から作ってみて感覚をつかむことにしました
権限の追加
cliから実行するためにIAMロールに追加します
AWS Identity and Access Management によるアクセスの制御 - AWS CloudFormation
cloudformation:*とかで大丈夫ですが、ElasticacheやRDSなどを追加する場合は別途で権限が必要なので必要な場合は加えておく
簡単なサンプルを動作させてみる
まずは感じをつかむためVPCのみ作ってみます
- sample.template.yml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
myVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'false'
EnableDnsHostnames: 'false'
InstanceTenancy: default
Tags:
- Key: Name
Value: Sample
aws cloudformation create-stack \
--stack-name sample \
--template-body file:///home/vagrant/sandbox/cfn/sample.template.yml
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:111111111111:stack/sample/e97ffe10-4a09-11e7-8ce1-50a68a175a82"
}
マネジメントコンソールからVPCが作られたことを確認します

myVPCが論理IDということでこれを元にリソースを管理しているようです
stackの更新
先ほど作ったテンプレートに少し追加して更新してみます
- sample.template.yml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
myVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'false'
EnableDnsHostnames: 'false'
InstanceTenancy: default
Tags:
- Key: Name
Value: SampleVPC
簡単なところでタグのNameをSample -> SampleVPCに変更してみました
aws cloudformation create-stack \ --stack-name sample \ --template-body file:///home/vagrant/sandbox/cfn/sample.template.yml
マネジメントコンソールから確認します
変更する項目によってはidが変わってしまう(delete and createになってしまう)ようなので気をつける必要があります
ドキュメントに変更時の挙動が書いてあるので確認すればOKですね

リソース一覧
リソースの一覧が見れるのでcloudformationで作ったものは判断つきますね
デフォルトでcloudformationでつけたタグ以外に色々タグがつくようです(論理IDとか)

リソースの数は。。。35個!!(かもしれない)
引数
Parameters:以下でパラメータを指定できます
リージョンが変わっても対応できるようavailability zoneを指定できるようにしてみます
- sample.template.yml
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
AZ1Parameter:
Type: String
Default: 'ap-northeast-1a'
Description: select availability zone
AZ2Parameter:
Type: String
Default: 'ap-northeast-1c'
Description: select availability zone
Resources:
....
public0A:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone:
Ref: AZ1Parameter
CidrBlock: 10.0.0.0/24
Tags:
- Key: Project
Value: Sample
- Key: Name
Value: 'Public 0a'
VpcId:
Ref: myVPC
....
AZ1Parameterで値を渡しています
実行時は--parametersに渡してあげます
./aws cloudformation update-stack \ --stack-name sample \ --template-body file:///home/sawafuji.yuya/sandbox/cfn/sample.template.yml \ --parameters ParameterKey=AZ1Parameter,ParameterValue=ap-northeast-1a \ ParameterKey=AZ2Parameter,ParameterValue=ap-northeast-1c
ここら辺は理解しやすいですね
部分的に変数を扱う
下記参考にしました
【小ネタ】CloudFormationで文字列内に変数を入れる。(YAML版) | Developers.IO
設定例としてプロジェクトネーム+何かしらみたいな場合
myVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'false'
EnableDnsHostnames: 'false'
InstanceTenancy: default
Tags:
- Key: Name
Value: !Sub ${ProjectNameParameter}WithB
こんな感じで扱うことが出来ます

感想
大体どの記事もこれテンプレートです!みたいなのばかりでいきなり大量の記述量がドンと出てくるのでどうしよう。。。と思っていたのですが一つづつやっていくことで理解が出来ました
最初がとっつきにくいだけでドキュメントもしっかりあるしある程度エラーの場合も原因が書かれているのでとても書きやすかったです
書いてる時はマネジメントコンソールからぽちぽちやっているのとあんまり変わらない気がするのでドキュメントとにらめっこしながらこつこつやっていけそうな感じですね
ちなみにドキュメントは下記
AWS CloudFormation とは - AWS CloudFormation
結局こつこつ書いていくと気づけば500行を超えるテンプレートになっていてこれがテンプレートです!になるのは納得がいきました
色々書いていくと記述が結構冗長になる感じがするのですがスタック間参照を使ったりすることで解決できるようです
今回はそこまで試していませんが一旦叩くだけでサービス開始直前までのインフラ構築が出来るテンプレートを作ることが出来たので良かったです
気になった点
気になったのはロールバックやアップデートなど何かしらの原因で詰まってしまうことがあるようです。
しかも詰まってしまった場合は何も進まず、場合によっては対象リソースの変更などもできない。サポートセンター行きといった解決策しかなさそうなのがちょっと微妙だなと思いました。
うっかり変な変更をしようとしてしまってサービス止まったままサポートセンターへ問い合わせなんてなったら目も当てられませんw
そう考えると運用までずっと使うのは少し気がひけるなーという印象で新規の構築一発目などで使うのがいいのかなといったイメージでした
とはいうものの定義書くだけでデザイナー経由で図に落とし込めるのはとても便利ですね
途中経過ですがこんな図になりました
