2019.01.21

【AWS】Cloudformationテンプレートの活用

Cloudformationとは

「テンプレートに記述されたAWSリソース群の構築とその管理するサービス」です。
Cloudformationによって管理されるAWSリソース群を「スタック」と呼びます。
Coudformationスタックを作成する際に使用する定義ファイルを「テンプレート」と呼びます。

テンプレートとしてAWSリソースをコードに落とし込むことができるので、インフラリソースをコードで管理することでもできますし、サクッと高品質なAWSリソースを構築することもできるようになります。

デモ用テンプレート

スタック構成

Cloudformationスタックのデモとして、VPCの簡単なスタックのテンプレートを作成しました。
https://github.com/YoshinoriSatoh/cloudformation-templates/blob/master/vpc/basic.yaml

2019 01 21 1

本テンプレートでは、以下のAWSリソースが作成されます。

  • VPC
  • サブネット
  • セキュリティグループ
  • ルートテーブル
  • インターネットゲートウェイ

上記の構成図のようなVPCネットワークが構築されます。

このネットワーク内に、例えばEC2やELBを配置したり、プライベートネットワークやNATゲートウェイを追加して、RDSを構築したりと、活用方法は様々です。

あくまでサンプル構成例ですので、あまり内容がわからない場合でも、以降の説明には支障ありません。

デモ用テンプレートの解説

デモ用テンプレートには、以下のセクションが記述されています。

  • Parameters
  • Resources
  • Outputs

Parameters

テンプレートには、マネジメントコンソールやCLIオプションなど、外部からパラメータを入力することができます。

デモ用テンプレートでは、VPCと各サブネットのCIDRブロックをパラメータとして指定できように、Parametersセクションを記述しています。

template.yaml

Parameters:
  VpcCidrBlock:
    Type: String
    Description: VPC CIDR Block.
    Default: 10.0.0.0/16

  PublicSubnetACidrBlock:
    Type: String
    Description: PublicSubnetA CIDR Block.
    Default: 10.0.1.0/24

  PublicSubnetCCidrBlock:
    Type: String
    Description: PublicSubnetC CIDR Block.
    Default: 10.0.2.0/24

Resources

Cloudformationテンプレートには、色々なセクションが存在しますが、最も基本的かつ必須なものは「Resources」セクションです。
Resources セクションには、構築したいAWSリソースを記述します。
(VPC RouterはVPC内に暗黙的に作成されるものなので、リソースとして意識することはありません。)

template.yaml

Resources:
  Vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidrBlock
      EnableDnsSupport: true
      EnableDnsHostnames: true
      InstanceTenancy: default

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc

  PublicSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      CidrBlock: !Ref PublicSubnetACidrBlock
      AvailabilityZone: ap-northeast-1a
      MapPublicIpOnLaunch: true

  PubSubnetARouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref PublicRouteTable

  PublicSubnetC:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      CidrBlock: !Ref PublicSubnetCCidrBlock
      AvailabilityZone: ap-northeast-1c
      MapPublicIpOnLaunch: true

  PubSubnetCRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetC
      RouteTableId: !Ref PublicRouteTable

  InternetGateway:
    Type: AWS::EC2::InternetGateway

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref Vpc
      InternetGatewayId: !Ref InternetGateway

  InternetRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGateway
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: SecurityGroup for ECS VPC
      VpcId: !Ref Vpc
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 0
          ToPort: 65535
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 0
          ToPort: 65535

Outputs

Cloudformationスタック内のAWSリソースの中で、参照頻度が高かったり、沢山あるリソースの中からは探しにくい値が出てきます。。
Outputsはそのような値を、Cloudformationスタックに紐づけて、コンソールやCLIから参照できるようにします。
デモ用テンプレートでは、サブネットIDはVPCネットワーク構成を把握する際に参照することが多いので、Outputsに指定しています。

template.yaml

Outputs:
  VPCId:
    Description: The ID of the VPC
    Value: !Ref Vpc
    Export:
      Name: !Sub "${AWS::StackName}-VPCID"

  PublicSubnetA:
    Description: The ID of the VPC Subnet
    Value: !Ref PublicSubnetA
    Export:
      Name: !Sub "${AWS::StackName}-PublicSubnetA"

  PublicSubnetB:
    Description: The ID of the VPC Subnet
    Value: !Ref PublicSubnetC
    Export:
      Name: !Sub "${AWS::StackName}-PublicSubnetC"

  SecurityGroup:
    Description: The ID of the SecurityGroup
    Value: !Ref SecurityGroup
    Export:
      Name: !Sub "${AWS::StackName}-SecurityGroup"

AWSリソース同士の関連を記述

テンプレートには、図に示しているAWSリソースの他に「リソース同士の関係性を定義するAWSリソース」が記述されています。

  • サブネットとルートテーブルを紐づけるリソース(SubnetRouteTableAssociation)
  • VPCとインターネットゲートウェイを紐づけるリソース(VPCGatewayAttachment)

これらは構成図にはリソースそのものとしては登場しません。
これらはマネジメントコンソールから操作する場合は、以下のような操作に相当します。

サブネットのルートテーブルの変更

2019 01 21 2

インターネットゲートウェイをVPCにアタッチ

2019 01 21 3

上記のような操作に相当する設定を、CloudformationテンプレートではAWSリソースの定義として記述できます。
このように、

「AWSリソース自体の定義」

だけでなく、

「AWSリソース同士の関連性の定義」

もテンプレートに記述できます。
Cloudformationテンプレートの記述量が多くなることで、複雑で難しそうにも見えてしまいますが、関連する手順までをテンプレートという「単なる設定ファイル」に落とし込むことができます。

Cloudformationスタック作成・更新

上記のテンプレートを使用して、実際にCloudformationスタックを作成・更新する手順を説明します。
(記事では、Cloudformationデザイナーは使用しません)

サービスロール

Cloudformationにはサービスロールを指定することができます。
スタックを作成するユーザーが十分な権限を持っていれば、指定の必要はないのですが、指定されていた方が健全な運用と言えます。
Clloudformationとサービスロールについては、別記事でまとめていますので、こちらも参考にしてください。

【AWS】Cloudformationとサービスロール

マネジメントコンソールによる操作

2019年1月現在のマネジメントコンソールでの説明です。
少し前に新しいコンソールになって画面が変わっています。
本記事では新しいコンソールで説明しています。
また、この新しいコンソールではまだ日本語化されていませんが、そのうち日本語化されると思います。
(いつの間にかさらっと日本語化されると思います。)

予め、Upload a template file → 以下のGithubリポジトリのテンプレートをダウンロードしておいてください。
https://github.com/YoshinoriSatoh/cloudformation-templates/blob/master/vpc/basic.yaml

新規作成

マネジメントコンソールのCloudformation画面から「Create stack」をクリック

2019 01 21 4

以下それぞれ選択して「Next」をクリック

  • Prepare template → 「Template is ready」
  • Template source → 「Upload a template file」
  • Upload a template file → 先ほどダウンロードしたテンプレートを選択

2019 01 21 5

Stack nameは適当な名前を入力してください。(demo-vpcなど)
Parametersはデフォルト値が入力されているはずです。
VPCやサブネットのCIDRブロックを変更できます。

2019 01 21 6

AWSリソースに対してタグを付与することができます。
必須ではないですが、作成されたリソースがどのスタックによって作成管理されているものなのかがわかりやすくなるので、指定しておいたほうがいいです。

Permissionsには、Cloudformationに付与するサービスロールを指定します。
こちらも必須ではないのですが、サービスロールを適切に設定する方が健全と言えます。
こちらについては、別記事にまとめていますので、参考にしてください。
https://yoshinori-satoh.com/cloudformation_servicerole/

2019 01 21 7

テンプレートのレビュー画面では、内容を確認して、「Create stack」をクリック(スクショ割愛) スタック作成が完了すると、ステータスが「CREATE_COMPLETE」となります。

2019 01 21 8

更新

作成したスタックに対する更新のユースケースには、以下の2パターンがあります。

  • テンプレートのパラメータのみを変更する
  • テンプレート自体も変更する

テンプレートのパラメータのみを変更する

マネジメントコンソールのCloudformation画面から「Update stack」をクリック(スクショ割愛) Update stack画面で「User current template」を選択して「 Next」をクリック

2019 01 21 9

Parameters画面でパラメータを変更して「Next」をクリック ここでは、各サブネットのCIDRブロックを変更しています。

2019 01 21 10

以降の操作はCreate stackと同様です。

テンプレート自体も変更する

上記のUpdate stack画面で、「Replace current template」を選択して、変更したテンプレートをアップロードします。

2019 01 21 11

以降の操作はCreate stackと同様です。

AWS CLIによる操作

Coudformationに慣れるまではマネジメントコンソールを使用した方が簡単かもしれませんが、慣れてくるとCLIを使用した方が工数が少ないので楽です。
CICDにも組み込みやすいです。

再掲ですが、以下のGithubリポジトリには、parameters.json というパラメータが記述されたファイルも含まれています。
以降の各コマンドはダウンロードしたvpcディレクトリ配下で実行してください。

https://github.com/YoshinoriSatoh/cloudformation-templates/blob/master/vpc/basic.yaml

新規作成

新規作成には cloudformation create-stack を使用します。 パラメータはparameters.jsonに記述しているものが適用されます。

create stack

aws cloudformation create-stack \
  --stack-name demo-vpc \
  --template-body file://basic.yaml \
  --region ap-northeast-1 \
  --parameters file://parameters.json

更新

更新の場合は cloudformation update-stack を使用します。
オプションは基本的にcreate-stackと同じです。

update stack

aws cloudformation update-stack \
  --stack-name demo-vpc \
  --template-body file://basic.yaml \
  --region ap-northeast-1 \
  --parameters file://parameters.json

まとめ

本記事では、Cloudformationの簡単な解説とテンプレートを使用したスタック構築手順について説明しました。

デモとしてシンプルなVPCネットワークを構築しましたが、これをベースにしてもいいですし、汎用的なCloudformationテンプレートを用意して、使いまわしていくとサクッと品質の高いインフラやアプリケーション環境を構築できるようになります。

Cloudformationを活用し始める際には、ぜひ本記事を参考にしてください。