LoginSignup
4
4

More than 1 year has passed since last update.

AWS CloudFormation

Last updated at Posted at 2021-05-29

概要

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

Resourcesセクション

CloudFormation2.004.jpeg

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を作成するためのテンプレートファイルを作成していく。

CloudFormation5.005.jpeg

その中で、お互いのリソースを参照し合うような状態(例: !Ref関数)が発生する事がある。
これをクロススタックという。

CloudFormation5.007.jpeg

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という値を指定。

外部設定ファイルからパラメーターを読み込む

ファイルに以下のコードを書いた状態

s3config.cfg
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
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
dev.cfg
DatabasePassword=xxxx
ApplicationSubnets=xxxx
VpcId=xxxx
DBinboundCidrIPs=xxxx

最後に...

デモで作成したRDSはそのままだと料金が発生するのでスタックごと削除します。

$ aws cloudformation delete-stack --stack-name RDSmySQLcreate

スタック名がRDSmySQLcreateのスタックを削除するコマンドです。

参考

この記事はAWS初学者を導く体系的な動画学習サービス
「AWS CloudTech」の課題カリキュラムで作成しました。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4