AWS CloudFormationではじめるIaC入門

# この記事について
Infrastructure as Code(IaC)は、アプリのインフラ部分をコード化・ファイル化して管理する手法のことで、現代のイケてる開発では積極的に導入されています。
この記事では、IaCを導入することでどのようなメリットが得られるのか、またAWS CloudFormationを使って実際にIaCをするにはどうしたらいいのか、ということについて説明します。

## 前提条件
適切なIAMユーザーと紐付いたAWS CLIが既に用意・設定されているものとします。

# なぜIaCをやるのか
IaCを導入することによって得られるメリットは主に以下の通りです。

## 再現性の担保・複製を簡単にする
「本番環境と同じ構成の検証用・開発用環境を用意したい」という状況はよくあることと思います。
そのときに、「1年前に作ったこの環境を複製したいけど、Webコンソールでどうやって設定したんだっけ？？？」となってしまったら、目的を達成することは(当時の記憶・ドキュメントが残っていない場合)ほぼ不可能でしょう。

このときに、「このコードからインフラ構築をしました」という設定ファイルが残っていれば、もう一度そのファイルからインフラ生成をすれば簡単に同じ環境を構築することができるのです。

## 品質の担保
IaCを導入することのメリットとしてもう一つ、「失敗したらそれを一旦全部捨てて最初からやり直せる」ということが挙げられます。

インフラでよくありがちなのが、「一旦作って、後に不具合が出たから少しだけ直して……の繰り返しのうちに、何がどうなっているのか誰もわからなくなっている」というパターンです。
その場しのぎの修正を繰り返した結果、システム構成が非効率的なものになってしまうということも考えられます。そうなったときに、今動いているシステムに影響が出ないようにインフラ構成を再構築するというのは、もはや新規開発とコスト・労力は変わりません。
また、修正を繰り返した結果生まれた"うなぎのタレ"のようなインフラ構成は、もはや誰も同じものを作れないような代物になっていることでしょう。「失敗したらもう元には戻せない」以上、その場しのぎの修正をするのも大変にストレスの大きい作業です。

「失敗したらもう一度やり直せる」というのは、それはつまり「インフラ上に乗っているアプリケーションコードと同様のCI/CDパイプラインを組める」ということです。したがって、アプリと同じだけの品質をインフラでも簡単に保つことができるのです。

# CloudFormationでのIaC実践
ここからは、IaCを行うための実際の手順を紹介します。
IaCのためのツールはTerraformやOpsWorksなど様々なものが存在しますが、ここではAWSのCloudFormationを利用します。

## 0. CloudFormationの用語
CloudFormationで登場する概念・用語についてまず説明します。

- テンプレート: CloudFormationで使う、インフラをコードで表現した設定ファイルのこと。
- スタック: 1つのテンプレートから生成される複数のリソースのことをまとめてこう呼ぶ。インフラリソースの生成・更新・削除は基本的にスタック単位で行うことになる。

## 1. テンプレートファイルの作成
IaCというからには、インフラ構成をコード、つまりファイルの形で書く必要があります。
CloudFormationでは、jsonかyaml形式の2種類のフォーマットに対応しています。ここではyaml形式のものを紹介します。

```config.yml
AWSTemplateFormatVersion: 2010-09-09
Description: Main template for VPC

Resources:
    CFnVPC:
        Type: AWS::EC2::VPC
        Properties:
            CidrBlock: 10.0.0.0/16
            Tags:
                - Key: Name
                  Value: CFnVPC

Outputs:
    VPCID:
        Description: VPC ID
        Value: !Ref CFnVPC
        Export:
            Name: !Sub ${AWS::StackName}-VPCID
```
各項目の意味は以下の通りです。

- AWSTemplateFormatVersion: テンプレート記法のバージョン。現状利用できるのは"2010-09-09"のみ。
- Description: 何のテンプレートなのかの説明を書く
- Resources: EC2やVPCなど、AWSのどんなリソース(Type)をどんな設定(Properties)で作るかをここに列挙する
- Outputs: CloudFormationで作られたリソースの情報のうち、どれを出力するかを設定

Resources, Outputsの詳細については次の章で後述します。

## 2. テンプレートファイルのバリデーション
正しいフォーマットでテンプレートを書けているのかコマンドで確認してみましょう。
`config.yml`というテンプレートファイルをチェックするには、ファイルがあるディレクトリに移動して以下のコマンドを打ちます。

```bash
$ aws cloudformation validate-template --template-body file://config.yml
```

## 3. テンプレートからAWSリソースの作成
1つのテンプレートファイルに記載された内容は、1つのスタックとしてまとめられます。
テンプレートファイルから「stack-example」という名前をつけたスタックを作成するには、以下のコマンドを実行します。

```bash
$ aws cloudformation create-stack --stack-name stack-example --template-body file://config.yml
```

## 4. AWSリソースの変更・更新
`config.yml`の内容を修正して、その変更をAWSに反映したいという場合は、以下のようにスタック名とテンプレートファイルを指定して`update-stack`コマンドを実行します。

``` bash
$ aws cloudformation update-stack --stack-name stack-example --template-body file://config.yml
```

## 5. CloudFormationスタックの削除
CloudFormationのスタックで作成したAWSリソースを丸ごと削除したい場合は、スタック名を指定した`delete-stack`コマンドで可能です。

```bash
$ aws cloudformation delete-stack --stack-name stack-example
```

# テンプレートファイルの書き方
## Resourcesの部分
テンプレートファイルには、「このスタックでどのようなインフラリソースを生成するのか」というのを指定するResourcesという項目があります。

```config.yml
Resources:
    CFnVPC:
        Type: AWS::EC2::VPC
        Properties:
            CidrBlock: 10.0.0.0/16
            Tags:
                - Key: Name
                  Value: CFnVPC
```
上記の例の場合、VPCに、「CFnVPC」という変数名・論理名をつけたという状態です。
これがVPCであることは「Type」という項目に、VPCに行う設定は「Properties」という項目に記されています。
Type、Propertiesにどんな項目があるのかは、必要に応じて以下の公式ドキュメントを参照すれば良いでしょう。
参考:[AWS公式ドキュメント AWS リソースおよびプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)

## Outputsの部分
Outputsは、1つのスタックから生成されたリソースのIDやDBエンドポイントなどの情報を出力するための仕組みです。
例えば、上記の例ではOutputs項目は以下のようになっていました。

```config.yml
Outputs:
    VPCID:
        Description: VPC ID
        Value: !Ref CFnVPC
        Export:
            Name: !Sub ${AWS::StackName}-VPCID
```
ここでは、「ResourcesでCFnVPCという変数名をつけたVPCのID」を、「(スタック名)-VPCID」という名前で出力する、という意味です。

このテンプレートからスタックを生成した結果、CloudFormationのwebコンソールからは、このようにOutputsで指定した通りのリソース情報を確認することができます。
![スクリーンショット 2020-08-21 20.07.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520877/bc76c005-9103-4e36-c837-9f314c637e0f.png)

# IaCをやるときの心構え
ここまでの紹介でCloudFormationを導入する準備は整っていますが、CloudFormationでIaCをやるときには、「**Webコンソールで決してインフラを触らないという鉄の意志**」が必要です。
これは、自動で用意したインフラをCloudFormationの管轄範囲外でいじるとうまくいかなくなる、というのもそうですが、上で紹介した「再現性・品質の担保」といったIaCのメリットが享受できなくなってしまうからです。

IaCのメリットは、インフラをコードで**全て**完結させるからこそ生まれるものであって、手動での構築を少しでも含む中途半端なIaCはむしろやらない方がマシともいえるでしょう。

それでも「やる」と決めた方は、ぜひCloudFormationで始めてみませんか？

# 参考文献
- [AWS Hands-on for Beginners
AWS 環境のコード管理 AWS CloudFormationで Web システムを構築する](https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-cfn-2020-reg-event-LP.html?trk=aws_introduction_page)
- [[動画公開] AWS環境でIaCを使い始めて運用するためのメリットデメリットと注意点](https://dev.classmethod.jp/articles/aws-iac-operation-merit-and-demerit/)