##概要
AWSリソースをコード化してくれるサービスで、テキストファイル(=テンプレート)にリソースの構造を記述してCloud Formationのサービス画面で読み込ませると、AWSリソースを自動作成してくれる。
自動生成だけでなく、変更や削除もできる。
テンプレートのファイル形式はXML,JSONなどあるが、YAMLをオススメしています。
理由: コメントの記述が可能な点、人間にとって読みやすい点です。
##スタック
テンプレートを読み取って作成されたAWSサービスの集合体のことをスタックと呼びます。
テンプレートの構文途中にエラーがあっても中途半端に生成されることはなく、自動でロールバックされる。
更新時
テンプレートを新しく更新して改めてCloudFormationに読み込ませることで、バージョン2のスタックに更新される。
削除時
スタック単位で作成していたもの全てが削除される。
##Drift Detection
テンプレートでスタックを作成した後、GUI(手動)でS3を削除した際差分が生まれてしまうケースがあります。
この差分を検知してくれる機能をDrift Detectionと言い、どこに差分があるのか検出できます。
##CloudFormationテンプレート
テンプレートはAWS独自の記述式となっていて、9つのセクションで分かれている。
1,AWSTemplateFormatVersion
このテンプレートのバージョン
2,Description
3,Metadata
4,Parameters
パラメーターを設定する領域
5,Mappings
6,Conditions
7,Transform
8,Resources
重要なのはResourcesセクションとなっている
9,Outputs
VPC,EC2,S3など作成したいAWSリソースに対してそれぞれ記述していく。
茶色の文字がCloudFormationで決められた形式で赤文字がユーザー側で記載していく。
Logical IDは論理ID(名前のようなもの)。
Typeは作成するAWSリソースを記載。
PropertiesはTypeについての詳細を記述。
この3セットを作成するリソース分記述する。
必要なプロパティなどは公式ドキュメントを読みながら記述していく。
##作成デモ用テンプレートファイル
テンプレートファイル (ver 1)
AWSTemplateFormatVersion: 2010-09-09
Resources:
MyVPC2:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.8.0/21
EnableDnsSupport: true
Tags:
- Key: Name
Value: MyVPC2fromCF
subnetName:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: "ap-northeast-1a"
VpcIp: !Ref MyVPC2
CidrBlock: 10.0.8.0/24
Tags:
- Key: Name
Value: subnet1formCF
<<手順>>
AWS CloudFormation < スタックの作成 < 新しいリソースを使用(標準)
スタックの作成
テンプレートの準備完了状態にチェック、
テンプレートソースはテンプレートファイルのアップロードにチェック、
上のyamlファイルをアップロードし、次へを選択
(一旦S3にアップロードされて、且つ形式などに誤りがある際はエラーが出る)
スタックの名前をつけて次へを選択
##テンプレート更新
作成したテンプレートファイル(ver 1)で作成したVPCと紐づいた状態で
そのファイルに追加で記述したものを、CloudFormationにアップロードすることで更新される。
更新方法は作成時と似ていて
該当のスタックを選択し、更新するボタンを選択 < 既存テンプレートを置き換えるを選択
ここでテンプレートの指定にテンプレートのアップロードを選択してファイルをアップロードします。(← この辺りは作成時と同じ)
テンプレートファイル (ver 2)
AWSTemplateFormatVersion: 2010-09-09
Resources:
MyVPC2:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.8.0/21
EnableDnsSupport: true
Tags:
- Key: Name
Value: MyVPC2fromCF
subnetName:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: "ap-northeast-1a"
VpcId: !Ref MyVPC2
CidrBlock: 10.0.8.0/24
Tags:
- Key: Name
Value: subnet1fromCF
secGroupName:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: GroupName-SG
GroupDescription: GroupDescription-SG
VpcId: !Ref MyVPC2
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- key: Name
Value: SGfromCF
必要なプロパティは公式を検索して記述していく
##Ref関数
組み込み関数 !Ref (リファレンスの略で参照の意味)
同じテンプレートファイル内で作成されたパラメータまたはリソースの値を返す。
同ファイル内にMyEC2Instanceが使用されていることを条件に
プロパティのインスタンスIDにMyEC2Instanceという論理IDを同一にすることで紐付けうことができる。
##クロススタック参照
実際の運用では、リソースの種類によってテンプレートファイルを分割する運用を推奨しており、上のテンプレートで作成されたVPC,subnet,SGとは別にEC2を作成するためのテンプレートファイルを作成していく。
その中で、お互いのリソースを参照し合うような状態(例: !Ref関数)が発生する事がある。
これをクロススタックという。
###Outputsセクション
クロススタックを行うにはOutputsという他のテンプレートから参照させる準備の領域が必要でこの設定を参照元に書いていく。
記述に必要なものは3つ
・論理ID(Subnet1)
名前のようなもの
・value
同じテンプレート内のデータをvalueとして取得
・Export
他のテンプレートから、Nameに指定した文字をImportValueで参照できる
Outputs:
Subnet1:
Value: !Ref subnetName
Export:
Name: Subnet1Name
Sg1:
Value: !GetAtt secGroupName.GroupId
Export:
Name: SG1Name
###ImportValue関数
参照したいファイルで記述
別のテンプレートファイルの中身を参照する(クロススタック)際はRef関数でなく、ImportValue関数を使用する。
###GetAtt関数
参照させたいファイルで記述
論理IDに.をつなぐことで中身を指定して取得できる。
どんな戻り値を取得できるか調べる際は公式ドキュメントを確認↓
##AWS CLIを使用したスタックの基本操作
###aws cloudformation deploy
AWSにSSH接続した後
スタック作成時のコマンド
$ aws cloudformation deploy --template-file stack_s3_param.yml --stack-name s3bucketcreate
オプション
--template-file → テンプレートを作成するためのファイル名
--stack-name → 作成されるスタックに名前をつける
###aws cloudformation delete-stack
スタック削除時のコマンド
$ aws cloudformation delete-stack --stack-name s3bucketcreate
--stack-name → スタック名を指定
###パラメーター値を指定する
コマンドラインで引数を指定
AWSTemplateFormatVersion: "2010-09-09"
Description: CloudTechDemoS3
Parameters:
S3BucketName:
Type: String
Description: Type of this BacketName.
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${S3BucketName}
$ aws cloudformation deploy --template-file stack_s3.yml --stack-name s3bucketcreate --parameter-overrides S3BucketName=samplecloudtechbucket
オプション
--parameter-overrides → S3BucketNameという変数にsamplecloudtechbucketという値を指定。
###外部設定ファイルからパラメーターを読み込む
ファイルに以下のコードを書いた状態
S3BucketName=samplecloudtechbucket2
$ aws cloudformation deploy --template-file stack_s3.yml --stack-name s3bucketcreate --parameter-overrides $(cat s3config.cfg)
$(cat s3config.cfg)部分でS3のバケット名に !Sub ${S3BucketName}と記述していたことで、s3config.cfgが使用される
###CloudFormationで作成したS3Bucketの論理IDを出力できる
$ aws cloudformation describe-stack-resource --stack-name s3bucketcreate --logical-resource-id S3Bucket
###設定ファイルと分けるメリット
テストや本番といった環境の変化によっても一つのテンプレートを使いまわせる。
RDS作成
Stack.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: CloudTechDemo
Parameters:
DatabasePassword:
Type: String
Description: Database password
NoEcho: "true"
ApplicationSubnets:
Type: List<AWS::EC2::Subnet::Id>
Description: Target subnets
VpcId:
Type: AWS::EC2::VPC::Id
Description: Target VPC
DBinboundCidrIPs:
Type: String
Description: SecurityGroupInboundIP
Resources:
ApplicationDatabase:
Type: AWS::RDS::DBInstance
Properties:
Engine: MySQL
EngineVersion: 5.7
DBInstanceClass: db.t2.micro
AllocatedStorage: 10
StorageType: gp2
MasterUsername: CloudTech
MasterUserPassword:
Ref: DatabasePassword
DBName: CloudTech
VPCSecurityGroups:
- !Ref ApplicationDatabaseSecurityGroup
DBSubnetGroupName: !Ref ApplicationDatabaseSubnetGroup
MultiAZ: "false"
AvailabilityZone: !Sub ${AWS::Region}a
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-db
ApplicationDatabaseSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Application Database Subnet Group
SubnetIds: !Ref ApplicationSubnets
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-db-subnet-group
ApplicationDatabaseSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub ${AWS::StackName} Application Database Security Group
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
CidrIp: !Ref DBinboundCidrIPs
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-db-sg
dev.cfg
DatabasePassword=xxxx
ApplicationSubnets=xxxx
VpcId=xxxx
DBinboundCidrIPs=xxxx
##最後に...
デモで作成したRDSはそのままだと料金が発生するのでスタックごと削除します。
$ aws cloudformation delete-stack --stack-name RDSmySQLcreate
スタック名がRDSmySQLcreateのスタックを削除するコマンドです。
##参考
この記事はAWS初学者を導く体系的な動画学習サービス
「AWS CloudTech」の課題カリキュラムで作成しました。