【AWS】CloudFormation Designer + 手直しで、VPCのテンプレート作成 【CloudFormation】

#はじめに
こんにちは。
クラウドの魅力の一つと言えば、自動化ですよね。
文系学生からインフラエンジニアになって２年目となりますが、今後インフラエンジニアの仕事を奪われてしまうのではないかと、今からひやひやしています・・・

今回、「Infrastructure as Code」の触りとして、CloudFormationを使ってみようと思います。
ちなみに、コードは、まだまだ修行中です・・・

#概要
CloudFormatinでネットワーク部分のテンプレートを作ります。
進め方としては、Designerを使い、ある程度の形を作り、それを修正していきます。

**今回作成する構成**
・VPC x 1
・パブリックサブネット   x  2
・プライベートサブネット  x  2
・ルートテーブル　x 2
・インターネットゲートウェイ x 1

#テンプレート作成

**まず、Designerを使い、目的の構成のコードを作ります。**
![スクリーンショット 2015-12-23 11.51.58.png](https://qiita-image-store.s3.amazonaws.com/0/95380/8303017a-87b2-7302-f3c8-dce00a124737.png)

この構成でコードを出力して中身を確認してみると、サービスとは関係なさそうなMetaDataがたくさんありました。
Designerを使って、テンプレートをつくるとDesignerの情報(位置情報等)もMetaData部分に入ってくるみたいです。
そのため、今回は、不要な部分の掃除もしました。

参考:[AWS リソースプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)

**出力したコードから変更した点**


・Designer向けの [MetaData] の削除
・論理IDをランダムのものから任意の値に変更
・[Properties] の編集及び追記 (Cidr、Tags、AZ等)
・IGWとVPCの関連付け
・ルートテーブルの作成(Public、Private)
・ルートテーブルとサブネットの関連付け

構文チェックは下記コマンドを実行することで可能です。(休日無くなるくらいには、エラーと戦いました！)
`aws cloudformation validate-template --template-body <JSONファイル>`


#完成したJSONコード

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "myVPC": {
      "Type": "AWS::EC2::VPC",
      "Properties": {
            "CidrBlock" : "10.0.0.0/16",
    	    "EnableDnsSupport" : "false",
    	    "EnableDnsHostnames" : "false",
            "InstanceTenancy" : "default",
            "Tags" : [ {"Key" : "Name", "Value" : "myVPC"} ]
         }
    },
    "myPublicSubnet1": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "VpcId": {"Ref": "myVPC"},
		"CidrBlock" : "10.0.0.0/24",
		"AvailabilityZone" : "ap-northeast-1a",
		"Tags" : [ {"Key" : "Name", "Value" : "myPublicSubnet1"} ]
      },
      "DependsOn": [
		  "myIGW"]
    },
	"mySubnetRouteTableAssociation1" : {
	         "Type" : "AWS::EC2::SubnetRouteTableAssociation",
	         "Properties" : {
	            "SubnetId" : { "Ref" : "myPublicSubnet1" },
	            "RouteTableId" : { "Ref" : "PublicRouteTable" }
	         }
	},
    "myPublicSubnet2": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "VpcId": {
          "Ref": "myVPC"
        },
		"CidrBlock" : "10.0.3.0/24",
		"AvailabilityZone" : "ap-northeast-1a",
		"Tags" : [ {"Key" : "Name", "Value" : "myPublicSubnet2"} ]
      },
      "DependsOn": [
        "myIGW"
      ]
    },
	"mySubnetRouteTableAssociation2" : {
	         "Type" : "AWS::EC2::SubnetRouteTableAssociation",
	         "Properties" : {
	            "SubnetId" : { "Ref" : "myPublicSubnet2" },
	            "RouteTableId" : { "Ref" : "PublicRouteTable" }
	         }
	},
    "myPrivateSubnet1": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "VpcId": {
          "Ref": "myVPC"
        },
		"CidrBlock" : "10.0.1.0/24",
		"AvailabilityZone" : "ap-northeast-1a",
		"Tags" : [ {"Key" : "Name", "Value" : "myPrivateSubnet1"} ]
      }
    },
	"mySubnetRouteTableAssociation3" : {
	         "Type" : "AWS::EC2::SubnetRouteTableAssociation",
	         "Properties" : {
	            "SubnetId" : { "Ref" : "myPrivateSubnet1" },
	            "RouteTableId" : { "Ref" : "PrivateRouteTable" }
	         }
	},
    "myPrivateSubnet2": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "VpcId": {
          "Ref": "myVPC"
        },
		"CidrBlock" : "10.0.2.0/24",
		"AvailabilityZone" : "ap-northeast-1c",
		"Tags" : [ {"Key" : "Name", "Value" : "myPrivateSubnet2"} ]
      }
    },
	"mySubnetRouteTableAssociation4" : {
	         "Type" : "AWS::EC2::SubnetRouteTableAssociation",
	         "Properties" : {
	            "SubnetId" : { "Ref" : "myPrivateSubnet2" },
	            "RouteTableId" : { "Ref" : "PrivateRouteTable" }
	         }
	},
    "myIGW": {
      "Type": "AWS::EC2::InternetGateway",
      "Properties": {}
    },
    "GWAttach": {
      "Type": "AWS::EC2::VPCGatewayAttachment",
      "Properties": {
        "InternetGatewayId": {
          "Ref": "myIGW"
        },
        "VpcId": {
          "Ref": "myVPC"
        }
      }
    },
	"PublicRouteTable" : {
	         "Type" : "AWS::EC2::RouteTable",
	         "Properties" : {
	            "VpcId" : { "Ref" : "myVPC" },
	            "Tags" : [ { "Key" : "Name", "Value" : "PublicRouteTable" } ]
	         }
	},
	"PublicRoute" : {
	         "Type" : "AWS::EC2::Route",
	         "Properties" : {
	            "RouteTableId" : { "Ref" : "PublicRouteTable" },
	            "DestinationCidrBlock" : "0.0.0.0/0",
	            "GatewayId" : { "Ref" : "myIGW" }
	         }
	},
	"PrivateRouteTable" : {
	         "Type" : "AWS::EC2::RouteTable",
	         "Properties" : {
	            "VpcId" : { "Ref" : "myVPC" },
	            "Tags" : [ { "Key" : "Name", "Value" : "PrivateRouteTable" } ]
	         }
	}
  }
}

```



#今回の反省点
・もっとDesignerで事前にサービスを追加しておけば、編集が必要な部分は減った。(AZ、ルートテーブルとか)
・そもそもJSONの仕組みを理解してないため、無駄なエラーが多かった。もっと勉強する。


#さいごに
かなり悪戦苦闘しましたがなんとか動きました。
一から大規模なコードを書くとなるとかなり難しいのではないかと感じました。
ただ、Designerである程度コードを作ることで、私のような素人エンジニアでもCloudFormation使うことできることがわかりました。



今回書いたコードで個別の値の部分(論理ID、Cidr、Tags)とかは、スタックを作成する際に入力する形にしたいと思っています。(宿題)


修正が必要な部分などありましたら、ご連絡お願いします！
それでは、失礼します！