AWS

【CloudFormation】使い方と注意点【AWS】

どうも、Kohei(@koheinishino_)です。

今回はCloudFormationの使い方と注意点について解説します。

CloudFormationとは?

CloudFormation(クラウドフォーメーション)とは、各AWSリソースをまとめてコードで管理することでインフラ構築を自動化できるサービスです。

普通は「VPCを作成して、サブネットを作成して、インターネットゲートウェイを…」とコンソールからポチポチやってAWSリソースを構築すると思います。

CloudFormationを使えば、必要なリソースを記載したテンプレートファイルをAWSに読み込ませることで自動でリソースを構築できます。

インフラリソースをコードで管理すること(Infrastructure as Code)によって、主に下記のメリットがあります。

  • AWSリソースをまとめて管理することで、構築や削除をすばやく行える。
  • Gitなどのバージョン管理ツールで履歴が追跡しやすくなる。
  • テンプレートファイルを受け渡しできるため、全く同じインフラ構成を誰でもどのリージョンでも再現できる。

この記事を読むことでCloudFormationの使い方や躓きやすいポイントについて理解して、サーバーのテスト自動化をサクッと実現できるようになります。

初めてCloudFormationを導入することになったけど使い方がよくわからない…。

CloudFormationの使い方や注意点を知りたい!

と悩まれている方は是非最後までお読みください!

CloudFormationの使い方

まずはCloudFormationにおける2つのキーワードを解説します。

それがテンプレートスタックです。

テンプレートとスタック

テンプレートとは、CloudFormationでAWSリソースを作成するときに必要な設計図です。要は「どこに何をどのように作るのか」が書いてあります。

スタックとは、テンプレートで作成されるAWSのまとまりのことです。AWSリソースをスタックという単位にすることで、スタックを作成するとVPCやEC2が一気に立ち上がり、スタックを削除するとリソースを全て撤去できます。

CloudFormationの基本的な流れは下記のようなイメージです。

  1. ローカルでテンプレートファイルを作成する
  2. CloudFormationのコンソールにてテンプレートファイルをアップロードする
  3. スタックが作成されるのを気長に待つ

これだけですw つまり、テンプレートファイルをルール通り正しく作成できるかがキモになってきます。

テンプレートファイルの形式

テンプレートファイルはJSON形式かYAML形式で作成する必要があります。が、一般的に下記の理由からYAML形式で作成する人が多い気がします。

  1. カッコが不要
  2. コメントを記載できる

私もYAML派なので、ここからはYAML形式でテンプレートファイルを作成する前提で話を進めていきますね。

YAMLの場合は半角スペース2つでインデントとみなされるので、誤って全角スペース等を使用するとテンプレートを読み込ませたときにCloudFormationから怒られるので注意しましょうw

テンプレートファイルのセクション

ここからはテンプレートファイルの書き方について解説します。

CloudFormationのテンプレートファイルには下記の6つの上位セクションがあります。唯一Resoucesのみが必須ですが、これらは大体記載することが多いです。

  1. AWSTemplateFormatVersion
  2. Description
  3. Parameters
  4. Mappings
  5. Resources(必須)
  6. Outputs

AWSTemplateFormatVersion

ここにはテンプレートの形式バージョンを記載します。

本記事執筆時点では、下記が最新のフォーマットになります。ここは何も考えずにそのまま記載しましょう。

AWSTemplateFormatVersion: "2010-09-09"

Description

ここにはテンプレートファイルの説明を記載します。

何のテンプレートなのかを簡潔に記述しましょう。英語でも日本語でも問題ないですが、長く書くことはほぼないと思うので英語のほうが良さげかなと思います。

Description: >
  Here are some
  details about
  the template.

Parameters

ここにはスタック作成時や更新時にテンプレートに渡すことができる値を記載します。

下記のテンプレートファイルをCloudFormationに読み込ませると、スタック作成前にインスタンスタイプの選択画面が出てきます。

初期値は「t2.micro」で「t2.micro」「m1.small」「m1.large」の3つから選ぶような感じですね。

Parameters: 
  InstanceTypeParameter: 
    Type: String
    Default: t2.micro
    AllowedValues: 
      - t2.micro
      - m1.small
      - m1.large
    Description: Enter t2.micro, m1.small, or m1.large. Default is t2.micro.

特にDBのパスワード等の認証情報はテンプレートファイルにハードコーディングすると情報漏えいの観点から危険なので、なるべく外部から渡すようにしましょう。

また、EC2のAMI IDは最新のものを使うことが大半だと思いますので、Parametersを利用して最新のAMI IDを取得する方法も参考にしてみてください。

Mappings

ここにはテンプレートファイル内で使うキーと名前付きの一連の値を記載します。

定数を予め定義しておくイメージですね。よくある例としては、リージョンごとに使用するAMI IDを変えたいときがあります。

Mappings: 
  RegionMap: 
    us-east-1: 
      "HVM64": "ami-0ff8a91507f77f867"
    us-west-1: 
      "HVM64": "ami-0bdb828fd58c52235"
    eu-west-1: 
      "HVM64": "ami-047bb4163c506cd98"
    ap-southeast-1: 
      "HVM64": "ami-08569b978cc4dfa10"
    ap-northeast-1: 
      "HVM64": "ami-06cd52961ce9f0d85"

Resourcesの書き方は後述しますが、「!FindMap」という関数で上記の「RegionMap」というマッピングから現在のリージョンと一致するキーで「HVM64」 という名前の値を取得しています。

Resources: 
  myEC2Instance: 
    Type: "AWS::EC2::Instance"
    Properties: 
      ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", HVM64]
      InstanceType: m1.small

Resources(必須)

ここにはスタックに含めるAWSリソースを記載します。

ここが最も重要な部分ですね!そしてエラーになるときも大体このセクションのどこかが原因ですw

書き方は各AWSリソースによって異なるので詳細は割愛しますが、ポイントはリファレンスをしっかり読むことです。

例えばEC2インスタンスに関しては「AWS::EC2::Instance」のページを参照します。膨大な量のプロパティがありますが、各プロパティが必須かどうかも書いてあるため、まずは必須のプロパティを先に記載してしまうのがオススメです。

また、他のリソースを参照する際はRef関数を使いましょう。例えば、EC2ではサブネットを指定する必要がありますし、サブネットはVPCを指定する必要があります。

コンソールから手動でリソースを構築していたときに何を設定していたかを思い出しながらテンプレートを作るのが良いと思います。

Outputs

ここにはテンプレートファイルの中で外部から参照したい値を記載します。

特に後述するクロススタック参照やAWSコンソール上への出力(値の確認)等に使われます。

下記の例ではVPC IDを外部から参照できるようにしています。

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

CloudFormationの注意点

公式のユーザーガイドを参考にする

これには2つ理由があります。

  1. CloudFormation関連の技術記事は参考になるものが少ない
  2. 公式のマニュアルが意外と読みやすい

①について、本記事執筆時点でCloudFormation関連の有志の方々の技術記事は少なく、古いものが多いです。なので、参考になる部分が少ないのが正直なところ。

②について、「公式のマニュアルが絶対だ!」というのがエンジニア業界のセオリー的な側面もありますが、小難しく書かれていてアレルギーのある方も多いと思いますw

しかし、AWSの公式マニュアルは一見情報量は多いものの、しっかり読み込めば意外と分かりやすく書かれています。もちろん信頼性も一番高いです。

以上のことから、公式のユーザーガイドを参照しながら作業することをオススメします。

始めは少ないリソースでテンプレートファイルを作成する

これは私が実際に体験して感じたことです…。始めから大量のリソースを記載すると、エラーが発生したときに原因の調査に時間がかかります。

スタックの作成中のエラーメッセージが1つの場合でも、複数の原因が絡み合って1つしか出ていないこともよくあります。

そうすると「スタックの作成→やり直し」の作業が続いて時間を食ってしまうので、リソースを1つ記載したらスタックを作成してみるくらいのペース感が良いと思います。

このリソースの作成までは成功していたから、新しく記載したリソースに何か問題があるのでは?

というように問題の切り分けもしやすくなるので、細かい単位で一旦AWSに流してスタックを作成してみるのがオススメです。

クロススタック参照を活用する

1つのテンプレートファイルに必要なAWSリソースの情報をすべて記載しようと思うと、軽く1000行は超えてくると思います。行数の長いファイルって読む気が失せますよねw

テンプレートファイルが長くなりそうなときは、クロススタック参照を活用してファイルを分けるのがオススメです。

例えば、それぞれVPCとEC2のテンプレートファイルを作成し、EC2側からVPC側を参照するとします。

VPC側ではOutputsのセクションに参照させたいリソースを記載します。適当に論理IDを決めて、Valueに参照させたいリソースの論理IDを指定します。そして「Export:Name:」に参照側で指定するための名前を記載します。

Outputs:
    …
    PublicSubnet1a:
        Value: !Ref PublicSubnet1a
        Export:
            Name: PublicSubnet1a
    …

そしてEC2側のテンプレートファイルでサブネットを参照します。参照する側は「!ImportValue」という関数で「Export:Name:」の値を指定して参照します。

EC2: 
        Type: AWS::EC2::Instance
        Properties:
           …
            NetworkInterfaces: 
                - AssociatePublicIpAddress: true
                  DeviceIndex: 0
                  GroupSet: 
                    - !Ref SecurityGroupWeb
                  SubnetId: !ImportValue PublicSubnet1a
           …

私はこちらのリポジトリにあるようにリソースの種類ごとにファイルを分けました。参考にしてみてください。

クロススタック参照を活用してリソースを管理しやすくしましょう!

まとめ:CloudFormationでインフラ構築の自動化にチャレンジ

CloudFormationでテンプレートファイルをつくってしまえば、画面でポチポチしなくてもAWSに読み込ませて待っているだけで必要なインフラリソースを構成できます。

これは一度体験してみないと凄さが伝わりづらいと思いますので、是非CloudFormationでインフラ構築の自動化にチャレンジしてみてください!

ABOUT ME
Kohei Nishino
Web系エンジニア、ブロガーです。新卒未経験で開発エンジニアとして大手SIerに入社し約2年で退職→派遣エンジニアとして半年間インフラ構築業務→2020年11月から転職活動中。現在はDevOps系の技術を勉強しており、主にRails、AWS、Docker等の学習内容を発信しています。