本格SEもすなる、技術ブログといふものを、駄目SEもしてみむとて、するなり

温泉ハッカソンでCloudFormationの勉強してみました

さてさて、今日はAWSのCloudFormationを勉強してみました。

CloudFormation?

AWSのサイトには以下の様に書いています。

AWS CloudFormation は、関連する AWS リソースの集約を整った予測可能な方法でプロビジョニングおよび更新し、開発者やシステム管理者が容易にそれらを作成・管理できるようにします。

これだけ書かれても、あまり良く分かりませんね。
簡単に言うと、事前にjson形式で各コンポーネントの構成を定義すると、一気にその構成を作ってくれる機能です。

何勉強したの?

CloudFormationは、サンプルテンプレートがたくさんあるし、@さんが最近すごい勢いで書いているので、参考にするものが多いです。でも今回は、勉強のために公式ドキュメントだけを見てテンプレートを作ってみました。
公式ドキュメント:Welcome - AWS CloudFormation


*どんな内容?

CloudFormation初心者がCloudFormationを勉強するので、構成は簡単にしました。
「EIP付きのEC2インスタンスを既存VPC内に作成しよう!」です。
なお、前提条件として、VPC、セキュリティグループ、IAM Role等は事前に作成済みと言う事にしました。
で、作成したテンプレートが以下の内容です。

{
	"AWSTemplateFormatVersion" : "2010-09-09",

	"Description" : "Web Server Stack for maroon1st-Formation",

	"Parameters" : {
		"AMI" : {
            "Default": "ami-", 
            "Description": "AMI ID", 
            "Type": "String"
		},
		"WebServerAZ" : {
            "Default": "AAZ", 
            "Description": "AZ for Web Server ", 
            "Type": "String",
			"AllowedValues" : [
				"AAZ",
				"BAZ",
				"CAZ"
			]
		},
		"IAMRole" : {
            "Default": "", 
            "Description": "IAM Role", 
            "Type": "String"
		},
		"InstanceType" : {
            "Default": "t1.micro", 
            "Description": "Instance Type For Launching EC2", 
            "Type": "String",
			"AllowedValues" : [
				"t1.micro",
				"m1.small",
				"m1.medium",
				"m1.large",
				"m1.xlarge",
				"m2.xlarge",
				"m2.2xlarge",
				"m2.4xlarge",
				"c1.medium",
				"c1.xlarge",
				"cc1.4xlarge",
				"cc2.8xlarge",
				"cg1.4xlarge"
			]
		},
		"KeyPair" : {
            "Default": "", 
            "Description": "Key Pair", 
            "Type": "String"
		},
		"SecurityGroup" : {
            "Default": "sg-", 
            "Description": "This is SecurityGroup ID", 
            "Type": "CommaDelimitedList"
		},
		"InstanceName" : {
            "Default": "Maroon1st Web Server", 
            "Description": "Instance Name for EC2 Tag", 
            "Type": "String"
		},
		"UserData" : {
            "Default": "", 
            "Description": "UserData as Text", 
            "Type": "String"
		}

	},
	"Mappings" : {

		"SubnetMapPublic" : {
			"AAZ" : { "SubnetID" : "subnet-0f0f2066"},
			"BAZ" : { "SubnetID" : "subnet-020f206b"},
			"CAZ" : { "SubnetID" : "subnet-190f2070"}
		},

		"TokyoRegionAZ" : {
			"AAZ" : { "AZName" : "ap-northeast-1a"},
			"BAZ" : { "AZName" : "ap-northeast-1b"},
			"CAZ" : { "AZName" : "ap-northeast-1c"}
		}

	},

	"Resources" : {
		"WebServers" : {
			"Type" : "AWS::EC2::Instance",
			"Properties" : {
				"AvailabilityZone" : {
					"Fn::FindInMap" : [
						"TokyoRegionAZ" ,
						{ "Ref" : "WebServerAZ"},
						"AZName"
					]
				},
				"BlockDeviceMappings" : [], 
				"DisableApiTermination" : true,
				"EbsOptimized" : false,
				"IamInstanceProfile" : { "Ref" : "IAMRole" },
				"ImageId" : { "Ref" : "AMI" },
				"InstanceType" : { "Ref" : "InstanceType" },
				"KeyName" : { "Ref" : "KeyPair" },
				"Monitoring" : false,
				"SecurityGroupIds" : { "Ref" : "SecurityGroup" },
				"SourceDestCheck" : false,
				"SubnetId" : {
					"Fn::FindInMap" : [
						"SubnetMapPublic",
						{ "Ref" : "WebServerAZ" },
						"SubnetID"
					]
				},
				"Tags" : [
						{ "Key" : "Name", "Value": { "Ref" : "InstanceName" } },
						{ "Key" : "Server Type", "Value" : "Public Web Server" }
				],
				"Tenancy" : "default",
				"UserData" : {"Fn::Base64" : { "Ref" : "UserData" } }
			}
		},
		"WebServerIP" : {
		    "Type" : "AWS::EC2::EIP",
		    "Properties" : {
				"InstanceId" : { "Ref" : "WebServers" },
                "Domain" : "vpc"
		    }
		}
	},

	"Outputs" : {
		"InstanceID" : {
			"Description" : "ID for Launched Instance",
			"Value" : { "Ref" : "WebServers" }
		},
		"PublicIP" : {
			"Description" : "Public IP for Launched Instance",
			"Value" : { "Ref" : "WebServerIP" }
		},
		"AvailabilityZone" : {
			"Description" : "Launched AZ",
			"Value" : {"Fn::GetAtt" : [ "WebServers", "AvailabilityZone"]}
		},
		"PrivateIPAddress" : {
			"Description" : "Private IP Address Launched Instance",
		     "Value" : {"Fn::GetAtt" : [ "WebServers", "PrivateIp"]}
		 }
	}
}

でも、これってサンプルテンプレートに似てるのありました。orz
↓の名前でありました。
VPC_EC2_Instance_with_EIP_and_Security_Group.template

でもイイんです(川平栄治の感じで)
勉強だから!

作ってみて大変だった事

CloudFormationで一番は異変なのは、CloudFormationのファンクションを使う事だと分かりました。
"Fn::FindInMap"の中で、Fn:Joinの稀有t号した文字列は扱えなかったりするので嵌りました。

まとめると、、、

CloudFormationは、
まあ、RightScaleだとServer TemplateとかMacroがあるので同等のことができるんですが、CLOUDFORMATION*作ってみて大変だった事
CloudFormationはAWS謹製なので、すぐ新規機能がる使えるのが良いですね。

次は、Auto Scaling Group でEC2インスタンス出来るまで頑張るぞ!