CloudFormation　テンプレートからデプロイまで初学者向け解説

# CloudFormationテンプレート入門 - 基礎から実践まで
実務でAWS CloudFormationを使用する機会があったため、CloudFormationとは何か？どのように使うか？を調べてみました。

メモ・知識を整理がてら記載します。

<h2>ターゲット</h2>
CloudFormationの基本的な知識があり、これから構築しようとする方向け


## 目次

1. [CloudFormationとは何か？](#cloudformationとは何か？)
2. [テンプレートの基本構造](#テンプレートの基本構造)
3. [主要セクションの詳細解説](#主要セクションの詳細解説)
4. [実際に動かしてみる](#実際に動かしてみる)
5. [よくあるエラーと解決方法](#よくあるエラーと解決方法)
6. [ベストプラクティス](#ベストプラクティス)
7. [CloudFormation Designer](#Tips1CloudFormationDesignerの活用)
7. [IaC ジェネレーター](#Tips2IaCジェネレーターの活用)
8. [躓きやすいポイント](#躓きやすいポイント)

---

## CloudFormationとは何か？

AWS CloudFormationは、**インフラストラクチャをコードとして管理**する（Infrastructure as Code: IaC）ためのサービスです。従来の手動によるリソース作成とは異なり、JSON形式またはYAML形式のテンプレートファイルを使用して、AWS上のリソースを宣言的に定義・管理できます。
記載方法には、CloudFormationとSAMの2種類あります。SAM方式の方が記述量が少なく、比較的簡単に記載出来ますが、今回は基本的なCloudFormation形式で解説します。

### CloudFormationの主な利点
コンソールで作成すれば、簡単に作れるものを、コード化するのは正直面倒…ですが、コード化して資産を管理すると様々なメリットがあります。

| 利点 | 説明 |
| :--- | :--- |
| **再現性** | 同じテンプレートから何度でも同じ環境を構築可能 |
| **バージョン管理** | テンプレートをGitで管理し、変更履歴を追跡 |
| **自動化** | CI/CDパイプラインに組み込んでデプロイメントを自動化 |
| **依存関係管理** | リソース間の依存関係を自動的に解決 |
| **ロールバック機能** | デプロイに失敗した場合の自動復旧 |

---

## テンプレートの基本構造

CloudFormationテンプレートは以下の主要セクションから構成されます：

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'テンプレートの説明'

Parameters:
  # 実行時に指定するパラメータ

Mappings:
  # 静的な値のマッピング

Conditions:
  # 条件式の定義

Resources:
  # 作成するAWSリソース（必須）

Outputs:
  # 出力値の定義
```

### AWSTemplateFormatVersion
テンプレートの形式バージョンを指定します。現在は`'2010-09-09'`が最新版です。

### Description
テンプレートの目的や内容を簡潔に説明します。

### Parameters
スタック作成時にユーザーが指定できる値を定義します。CICDパイプラインなどを構成する場合など、環境ごとに異なる値（インスタンスタイプ、キーペア名など）を柔軟に設定することで、同じ伝プレートから異なる値でデプロイすることが出来ます。

---

## 主要セクションの詳細解説

### Resources（必須セクション）
実際に作成するAWSリソースを定義する最も重要なセクションです。Lambda、EC2、S3など、作成するリソースは全てこちらに記載します。

```yaml
Resources:
  SampleVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: MyVPC
```

### Outputs
作成されたリソースの情報を外部に出力します。他のスタックから参照したり、管理画面で確認したりできます。

```yaml
Outputs:
  VPCId:
    Description: 'VPCのID'
    Value: !Ref SampleVPC
    Export:
      Name: !Sub '${AWS::StackName}-VPC-ID'
```

### Mappings
静的な値のマッピングテーブルを定義します。リージョンごとのAMI IDなど、条件に応じて値を切り替える場合に使用します。

```yaml
Mappings:
  RegionMap:
    us-east-1:
      AMI: ami-0abcdef1234567890
    ap-northeast-1:
      AMI: ami-0987654321abcdef0
```

---

## 実際に動かしてみる

例として、簡単にS3を作成するテンプレートを記載しました。実際に作成するときは、一から書くのではなく、Qiitaの記事から近いリソースを作っているテンプレートを探したり、AWS公式サイトのサンプルから、カスタマイズしていくのが早いと思います。

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'S3バケット作成'

Parameters:
  BucketName:
    Type: String
    Description: 'S3バケット名'
    Default: 'cloudformation-bucket'

Resources:
  MyS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub '${BucketName}-${AWS::AccountId}'
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

Outputs:
  BucketName:
    Description: '作成されたS3バケット名'
    Value: !Ref MyS3Bucket
  BucketArn:
    Description: 'S3バケットのARN'
    Value: !GetAtt MyS3Bucket.Arn
```
### :point_up_2:デプロイの前に構文チェック！
テンプレートの記述によって作成されるものの、最初は正しく書けているのか不安だと思います。
デプロイのエラーで一番多いのがValidation Errorです。
デプロイ→失敗→エラーメッセージを元に修正→デプロイ→失敗の繰り返しを行わないためにも、事前に構文や記載のチェックを行うことを推奨します。
（私はこれを知らなかったため、デプロイしてみないと何が悪いかわからないという非常に非効率な状態でした）
- テンプレートの検証
    - AWS CLIにてテンプレートの検証
        - `aws cloudformation validate-template --template "自身のテンプレートファイルへのパス"`コマンド
    - CloudFormation Linterツールで文法・記載のチェック
        - `aws cloudformation validate-template --template "自身のテンプレートファイルへのパス" --lint`コマンド
- IDEのYAML拡張機能でリアルタイム検証


### デプロイ手順
<b>コンソールから実施する場合
1. AWS CLIまたはマネジメントコンソールからスタックを作成
2. テンプレートファイルをアップロード
3. パラメータを入力
4. スタック作成を実行

<b>CLIで実施する場合
1. AWS CLIまたはマネジメントコンソールからスタックを作成
2. テンプレートファイルをアップロード
3. パラメータを入力
4. スタック作成を実行


:::note info
初回実行時は、S3バケット名がグローバルでユニークである必要があるため、`${AWS::AccountId}`を含めています。アカウントIDやリージョンなどは、`${AWS::AccountId}`、`${AWS::Region}`と記載することで取得することが出来ます。
:::

---

## よくあるエラーと解決方法

### Rollback時の対処法
リソース作成に失敗すると、CloudFormationは自動的にロールバックを実行します。

**対処手順:**
1. CloudFormationコンソールでエラー詳細を確認
2. 失敗したリソースの設定を修正
3. スタックを削除してから再作成、またはChangeSetを使用して更新

### 権限不足エラー
IAMロールや権限設定の不備で発生します。

**解決方法:**
- 必要な権限をIAMロール/ユーザーに付与
- CloudFormation実行用の専用ロールを作成
- 最小権限の原則に従って権限を設定

---

## ベストプラクティス

### 命名規則
一貫した命名規則を採用することで、リソースの管理が容易になります。

```yaml
# 推奨パターン
Resources:
  WebServerInstance:      # PascalCase
    Type: AWS::EC2::Instance
    Properties:
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-WebServer-${AWS::StackName}'
```

### タグ付け
すべてのリソースに適切なタグを設定し、コスト管理や運用を効率化します。

```yaml
Parameters:
  Environment:
    Type: String
    AllowedValues: [prod, staging, dev]
  
Resources:
  MyResource:
    Type: AWS::EC2::Instance
    Properties:
      Tags:
        - Key: Environment
          Value: !Ref Environment
        - Key: Project
          Value: MyProject
        - Key: Owner
          Value: TeamA
```

### テンプレート分割の考え方
大規模なインフラでは、テンプレートを論理的な単位に分割します。
基本的には、なるべくテンプレート間の依存関係が増えないよう関連のあるリソースは同じテンプレートでの記載が良いと思います。

| レイヤー | 含まれるリソース |
| :--- | :--- |
| **ネットワーク層** | VPC、サブネット、ルートテーブル |
| **セキュリティ層** | セキュリティグループ、IAMロール |
| **アプリケーション層** | EC2、RDS、ALB |
| **監視層** | CloudWatch、SNS |

### Cross-Stack Reference

分割したテンプレート間でリソースを参照するには、Outputsで作成したリソースをエクスポートし、別のテンプレートにてImportします。

```yaml
# ネットワークスタックのOutputs
Outputs:
  VPCId:
    Value: !Ref MyVPC
    Export:
      Name: !Sub '${AWS::StackName}-VPC-ID'

# アプリケーションスタックでの参照
Resources:
  WebServer:
    Type: AWS::EC2::Instance
    Properties:
      VpcId: !ImportValue NetworkStack-VPC-ID
```

---

## Tips1：CloudFormation Designerの活用

CloudFormation Designerは、テンプレートを視覚的に編集できるWebベースのツールです。

### 効果的な使い方

| 用途 | 説明 |
| :--- | :--- |
| **初期設計** | 新しいテンプレートの構造を視覚的に設計 |
| **依存関係の確認** | リソース間の関係を図で確認 |
| **複雑なテンプレートの理解** | 既存テンプレートの構造を把握 |
| **プレゼンテーション** | アーキテクチャ図として活用 |

### Designer使用時の注意点
- Designerで生成されるテンプレートは読みにくい場合があるため、手動で整理
- 複雑な条件分岐やマッピングはDesignerでは表現困難
- 最終的にはテキストエディタでの編集が必要

---


## Tips2：IaC ジェネレーターの活用

IaC ジェネレーターは、既に手動で作成したリソースをテンプレート化してくれるサービスです。
コンソール上から作成・テストなどを行った後に、テンプレート化を行えば、作成の手間を大幅に削減することが出来ます。
また、指定したリソースに関連する別のリソースもテンプレートに含めるかどうか提案してくれるため、関連するIAMなどもまとめて作成できます。

### Designer使用時の注意点
- IaCジェネレーターが使用できるリソースは限られている
- SAMでの記述は出来ず、CloudFormation方式での記述のみ

---


## 躓きやすいポイント
私がよく引っかかったエラーなどをまとめます。

### YAMLのインデントエラー（スペース2つが基本）
YAMLはインデントに厳格です。必ずスペース2つでインデントし、タブ文字は使用しません。
このあたりの文法・記述方法はデプロイ前に必ずlintツールでチェックしましょう。

```yaml
# 正しい例
Resources:
  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16

# 間違った例（インデントが不正）
Resources:
MyVPC:
  Type: AWS::EC2::VPC
   Properties:
    CidrBlock: 10.0.0.0/16
```

### リソースの依存関係（DependsOnの適切な使用）
CloudFormationは自動的に依存関係を解決しますが、明示的な指定が必要な場合があります。
例えば、同じテンプレートでLambdaとRoleとPolicyを作っていた場合、記述の順序にもよりますが、明示的にPolicy→Role→Lambdaという依存関係を記載する必要がある場合があります。


```yaml
Resources:
  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
  
  MyInternetGateway:
    Type: AWS::EC2::InternetGateway
  
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MyVPC
      InternetGatewayId: !Ref MyInternetGateway
  
  # インターネットゲートウェイの接続完了後にルートテーブルを作成
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    DependsOn: AttachGateway  # 明示的な依存関係
    Properties:
      VpcId: !Ref MyVPC
```

### パラメータの大文字小文字区別
CloudFormationのパラメータ名や関数は大文字小文字を区別します。


## デバッグ用Outputsを常に設定

テンプレート開発時は、デバッグ用のOutputsを設定することを強く推奨します。

```yaml
Outputs:
  # 基本情報
  StackName:
    Description: 'スタック名'
    Value: !Ref AWS::StackName
  
  StackId:
    Description: 'スタックID'
    Value: !Ref AWS::StackId
  
  # 作成されたリソースの詳細
  VPCId:
    Description: 'VPC ID'
    Value: !Ref MyVPC
  
  VPCCidr:
    Description: 'VPC CIDR Block'
    Value: !GetAtt MyVPC.CidrBlock
  
  # デバッグ用
  AllParameters:
    Condition: IsDebugMode
    Description: 'デバッグ用 - 全パラメータ'
    Value: !Sub |
      Environment: ${Environment}
      InstanceType: ${InstanceType}
      KeyPairName: ${KeyPairName}
```

### デバッグ条件の設定

```yaml
Parameters:
  DebugMode:
    Type: String
    Default: 'false'
    AllowedValues: ['true', 'false']

Conditions:
  IsDebugMode: !Equals [!Ref DebugMode, 'true']
```

:::note warn
本番環境には、デバッグ用のOutputs記述は削除または無効化するようにしてください
:::

---

## まとめ

CloudFormationの基本的な使い方・私が詰まってしまったポイントについて解説しました。
一気に書き進めるのではなく、小さいところから記載・確認をしていきながら作成していくのがおすすめです。



## タグ

`#AWS` `#CloudFormation` `#IaC` `#YAML` `#インフラ` `#自動化` `#DevOps` `#初心者向け`

---

** 参考リンク**
- [AWS CloudFormation公式ドキュメント](https://docs.aws.amazon.com/cloudformation/)
- [CloudFormation Template Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-reference.html)
- [AWS CLI CloudFormation コマンドリファレンス](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/)

---