CloudFormation テンプレートはコンパクトに

1つのVPC内で、異なる構成のサーバー群(スタック)を複数一気に立ち上げたり、一部を残して他を一気に削除したいことがあります。クラウドデザインパターン(CDP)Stack Deployment パターン の場面で、複数のスタックを扱うイメージです。( Multi Stack Deployment パターンと呼びたい...)


そこで今回、 CloudFormation のテンプレートを3つに分けて作成してみました。

作成したテンプレート

  1. Public サブネットと Private サブネットを Multi-AZ で持つ VPC (VPC)
  2. Public サブネットに EIP を関連づけた EC2 インスタンスを Multi-AZ で配置、 Private サブネットに RDS を Multi-AZ で配置 (Stack1)
  3. Public サブネットに AutoScaling グループを持つ ELB を作成、 Private サブネットに RDS を Multi-AZ で配置 (Stack2)

テンプレートの作り方

AWS CloudFormation Templates に、CloudFormation のサンプルテンプレートが公開されているので、それを参考にします。


では、作成したテンプレートを実行してみます。

テンプレートからスタックを作成

1つ目のテンプレートで VPC を作成します。 作成が終わったら Outputs ビューから VPCID と SubnetId を取得します。




2つ目、3つ目のテンプレートでは、パラメータとして作成済みの VPC の情報、作成したいDBの設定を入力できるようにしました。これで同じ VPC 上で構成や設定の異なるサーバー群を構築できます。



3つ目まで完了すると、スタックが3つあることを確認できます。




Stack2 を削除してみました。この方法で管理すると、不要になったスタックだけを削除することで VPC と他の構成だけを簡単に残すことができます。




VPC からインスタンスまでまとめて起動するテンプレートが適したケースもあるかと思いますが、少しでもコンパクトに分けておくと便利なのでおすすめです。


以下、作成したテンプレートになります。(ちょっと長いですが...)

作成したテンプレート

Public サブネットと Private サブネットを Multi-AZ で持つ VPC (VPC)

{
    "AWSTemplateFormatVersion" : "2010-09-09",
    "Description" : "VPC with multiple subnets",

    "Resources" : {
    "CfnUser" : {
      "Type" : "AWS::IAM::User",
      "Properties" : {
        "Path": "/",
        "Policies": [{
          "PolicyName": "root",
          "PolicyDocument": { "Statement":[{
            "Effect":"Allow",
            "Action":"cloudformation:DescribeStackResource",
            "Resource":"*"
          }]}
        }]
      }
    },

    "VPC" : {
        "Type" : "AWS::EC2::VPC",
        "Properties" : {
        "CidrBlock" : "10.1.0.0/16",
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Public" }
        ]}},

    "PublicSubnetA" : {
        "Type" : "AWS::EC2::Subnet",
        "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "CidrBlock" : "10.1.10.0/24",
        "AvailabilityZone" : "ap-northeast-1a",
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Public" }
        ]}},
    "PublicSubnetB" : {
        "Type" : "AWS::EC2::Subnet",
        "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "CidrBlock" : "10.1.11.0/24",
        "AvailabilityZone" : "ap-northeast-1b",
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Public" }
        ]}},

    "InternetGateway" : {
        "Type" : "AWS::EC2::InternetGateway",
        "Properties" : {
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Public" }
        ]}},

    "AttachGateway" : {
        "Type" : "AWS::EC2::VPCGatewayAttachment",
        "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "InternetGatewayId" : { "Ref" : "InternetGateway" }
        }},

    "PublicRouteTable" : {
        "Type" : "AWS::EC2::RouteTable",
        "Properties" : {
        "VpcId" : {"Ref" : "VPC"},
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Public" }
        ]}},

    "PublicRoute" : {
        "Type" : "AWS::EC2::Route",
        "Properties" : {
        "RouteTableId" : { "Ref" : "PublicRouteTable" },
        "DestinationCidrBlock" : "0.0.0.0/0",
        "GatewayId" : { "Ref" : "InternetGateway" }
        }},

    "PublicSubnetRouteTableAssociationA" : {
        "Type" : "AWS::EC2::SubnetRouteTableAssociation",
        "Properties" : {
        "SubnetId" : { "Ref" : "PublicSubnetA" },
        "RouteTableId" : { "Ref" : "PublicRouteTable" }
        }},
    "PublicSubnetRouteTableAssociationB" : {
        "Type" : "AWS::EC2::SubnetRouteTableAssociation",
        "Properties" : {
        "SubnetId" : { "Ref" : "PublicSubnetB" },
        "RouteTableId" : { "Ref" : "PublicRouteTable" }
        }},

    "PublicNetworkAcl" : {
        "Type" : "AWS::EC2::NetworkAcl",
        "Properties" : {
        "VpcId" : {"Ref" : "VPC"},
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Public" }
        ]}},

    "InboundSSHPublicNetworkAclEntry" : {
        "Type" : "AWS::EC2::NetworkAclEntry",
        "Properties" : {
        "NetworkAclId" : {"Ref" : "PublicNetworkAcl"},
        "RuleNumber" : "10",
        "Protocol" : "6",
        "RuleAction" : "allow",
        "Egress" : "false",
        "CidrBlock" : "0.0.0.0/0",
        "PortRange" : {"From" : "22", "To" : "22"}
        }
    },

    "InboundHTTPPublicNetworkAclEntry" : {
        "Type" : "AWS::EC2::NetworkAclEntry",
        "Properties" : {
        "NetworkAclId" : {"Ref" : "PublicNetworkAcl"},
        "RuleNumber" : "20",
        "Protocol" : "6",
        "RuleAction" : "allow",
        "Egress" : "false",
        "CidrBlock" : "0.0.0.0/0",
        "PortRange" : {"From" : "80", "To" : "80"}
        }},

    "InboundDynamicPortsPublicNetworkAclEntry" : {
        "Type" : "AWS::EC2::NetworkAclEntry",
        "Properties" : {
        "NetworkAclId" : {"Ref" : "PublicNetworkAcl"},
        "RuleNumber" : "50",
        "Protocol" : "6",
        "RuleAction" : "allow",
        "Egress" : "false",
        "CidrBlock" : "0.0.0.0/0",
        "PortRange" : {"From" : "1024", "To" : "65535"}
        }
    },

    "OutboundHTTPPublicNetworkAclEntry" : {
        "Type" : "AWS::EC2::NetworkAclEntry",
        "Properties" : {
        "NetworkAclId" : {"Ref" : "PublicNetworkAcl"},
        "RuleNumber" : "20",
        "Protocol" : "6",
        "RuleAction" : "allow",
        "Egress" : "true",
        "CidrBlock" : "0.0.0.0/0",
        "PortRange" : {"From" : "80", "To" : "80"}
        }},

    "OutboundDynamicPortPublicNetworkAclEntry" : {
        "Type" : "AWS::EC2::NetworkAclEntry",
        "Properties" : {
        "NetworkAclId" : {"Ref" : "PublicNetworkAcl"},
        "RuleNumber" : "50",
        "Protocol" : "6",
        "RuleAction" : "allow",
        "Egress" : "true",
        "CidrBlock" : "0.0.0.0/0",
        "PortRange" : {"From" : "1024", "To" : "65535"}
        }},

    "PublicSubnetNetworkAclAssociationA" : {
        "Type" : "AWS::EC2::SubnetNetworkAclAssociation",
        "Properties" : {
        "SubnetId" : { "Ref" : "PublicSubnetA" },
        "NetworkAclId" : { "Ref" : "PublicNetworkAcl" }
        }},
    "PublicSubnetNetworkAclAssociationB" : {
        "Type" : "AWS::EC2::SubnetNetworkAclAssociation",
        "Properties" : {
        "SubnetId" : { "Ref" : "PublicSubnetB" },
        "NetworkAclId" : { "Ref" : "PublicNetworkAcl" }
        }},

    "PrivateSubnetA" : {
        "Type" : "AWS::EC2::Subnet",
        "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "CidrBlock" : "10.1.20.0/24",
        "AvailabilityZone" : "ap-northeast-1a",
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Private" }
        ]}},
    "PrivateSubnetB" : {
        "Type" : "AWS::EC2::Subnet",
        "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "CidrBlock" : "10.1.21.0/24",
        "AvailabilityZone" : "ap-northeast-1b",
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Private" }
        ]}},

    "PrivateRouteTable" : {
        "Type" : "AWS::EC2::RouteTable",
        "Properties" : {
        "VpcId" : {"Ref" : "VPC"},
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Private" }
        ]}},

    "PrivateSubnetRouteTableAssociationA" : {
        "Type" : "AWS::EC2::SubnetRouteTableAssociation",
        "Properties" : {
        "SubnetId" : { "Ref" : "PrivateSubnetA" },
        "RouteTableId" : { "Ref" : "PrivateRouteTable" }
        }},
    "PrivateSubnetRouteTableAssociationB" : {
        "Type" : "AWS::EC2::SubnetRouteTableAssociation",
        "Properties" : {
        "SubnetId" : { "Ref" : "PrivateSubnetB" },
        "RouteTableId" : { "Ref" : "PrivateRouteTable" }
        }},

    "PrivateNetworkAcl" : {
        "Type" : "AWS::EC2::NetworkAcl",
        "Properties" : {
        "VpcId" : {"Ref" : "VPC"},
        "Tags" : [
            {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} },
            {"Key" : "Network", "Value" : "Private" }
        ]}},

    "InboundPrivateNetworkAclEntry" : {
        "Type" : "AWS::EC2::NetworkAclEntry",
        "Properties" : {
        "NetworkAclId" : {"Ref" : "PrivateNetworkAcl"},
        "RuleNumber" : "100",
        "Protocol" : "-1",
        "RuleAction" : "allow",
        "Egress" : "false",
        "CidrBlock" : "10.1.0.0/16"
        }},

    "OutboundPrivateNetworkAclEntry" : {
        "Type" : "AWS::EC2::NetworkAclEntry",
        "Properties" : {
        "NetworkAclId" : {"Ref" : "PrivateNetworkAcl"},
        "RuleNumber" : "100",
        "Protocol" : "-1",
        "RuleAction" : "allow",
        "Egress" : "true",
        "CidrBlock" : "10.1.0.0/16"
        }},

    "PrivateSubnetNetworkAclAssociationA" : {
        "Type" : "AWS::EC2::SubnetNetworkAclAssociation",
        "Properties" : {
        "SubnetId" : { "Ref" : "PrivateSubnetA" },
        "NetworkAclId" : { "Ref" : "PrivateNetworkAcl" }
        }},
    "PrivateSubnetNetworkAclAssociationB" : {
        "Type" : "AWS::EC2::SubnetNetworkAclAssociation",
        "Properties" : {
        "SubnetId" : { "Ref" : "PrivateSubnetB" },
        "NetworkAclId" : { "Ref" : "PrivateNetworkAcl" }
        }}
    },

    "Outputs":{
    "PublicSubnetAId":{
        "Value":{"Ref": "PublicSubnetA"},
        "Description":"Id of PublicSubnetA"
    },
    "PublicSubnetBId":{
        "Value":{"Ref": "PublicSubnetB"},
        "Description":"Id of PublicSubnetB"
    },
    "PrivateSubnetAId":{
        "Value":{"Ref": "PrivateSubnetA"},
        "Description":"Id of PrivateSubnetA"
    },
    "PrivateSubnetBId":{
        "Value":{"Ref": "PrivateSubnetB"},
        "Description":"Id of PrivateSubnetB"
    },
    "VPCID":{
        "Value":{ "Ref" : "VPC" },
        "Description":"Id of VPC"
    }
    }
}

Public サブネットに EIP を関連づけた EC2 インスタンスを Multi-AZ で配置、 Private サブネットに RDS を Multi-AZ で配置 (Stack1)

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "In an existing VPC and multiple subnets. The public subnets contains an instances with an Elastic IP address, the private subnets contains a RDS Multi-AZ DBInstances.",

  "Parameters" : {
    "KeyName" : {
      "Description" : "Name of and existing EC2 KeyPair to enable SSH access to the instance",
      "Type" : "String"
    },

	"VpcId" : {
      "Type" : "String",
      "Description" : "VpcId of your existing VPC"
    },

    "PublicSubnetA" : {
      "Type" : "String",
      "Description" : "The SubnetId in the region in your VPC"
    },

    "PublicSubnetB" : {
      "Type" : "String",
      "Description" : "The SubnetId in the region in your VPC"
    },

    "PrivateSubnets" : {
      "Type" : "CommaDelimitedList",
      "Description" : "The list of SubnetIds, one in each AZ in the region in your VPC"
    },

    "InstanceType" : {
      "Description" : "WebServer EC2 instance type",
      "Type" : "String",
      "Default" : "t1.micro",
      "AllowedValues" : [ "t1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m2.xlarge","m2.2xlarge","m2.4xlarge","m3.xlarge","m3.2xlarge","c1.medium","c1.xlarge","cc1.4xlarge","cc2.8xlarge","cg1.4xlarge"],
      "ConstraintDescription" : "must be a valid EC2 instance type."
    },

    "DBName": {
      "Default": "MyDatabase",
      "Description" : "MySQL database name",
      "Type": "String",
      "MinLength": "1",
      "MaxLength": "64",
      "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
    },

    "DBUsername": {
      "NoEcho": "true",
      "Description" : "Username for MySQL database access",
      "Type": "String",
      "MinLength": "1",
      "MaxLength": "16",
      "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
    },

    "DBPassword": {
      "NoEcho": "true",
      "Description" : "Password for MySQL database access",
      "Type": "String",
      "MinLength": "1",
      "MaxLength": "41",
      "AllowedPattern" : "[a-zA-Z0-9]*",
      "ConstraintDescription" : "must contain only alphanumeric characters."
    },

    "DBAllocatedStorage": {
      "Default": "5",
      "Description" : "The size of the database (Gb)",
      "Type": "Number",
      "MinValue": "5",
      "MaxValue": "1024",
      "ConstraintDescription" : "must be between 5 and 1024Gb."
    },

    "DBInstanceClass": {
      "Default": "db.m1.small",
      "Description" : "The database instance type",
      "Type": "String",
      "AllowedValues" : [ "db.m1.small", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge" ],
      "ConstraintDescription" : "must select a valid database instance type."
    },

    "MultiAZDatabase": {
      "Default": "true",
      "Description" : "Create a multi-AZ MySQL Amazon RDS database instance",
      "Type": "String",
      "AllowedValues" : [ "true", "false" ],
      "ConstraintDescription" : "must be either true or false."
    }
  },

  "Mappings" : {
    "AWSInstanceType2Arch" : {
      "t1.micro"    : { "Arch" : "64" },
      "m1.small"    : { "Arch" : "64" },
      "m1.medium"   : { "Arch" : "64" },
      "m1.large"    : { "Arch" : "64" },
      "m1.xlarge"   : { "Arch" : "64" },
      "m2.xlarge"   : { "Arch" : "64" },
      "m2.2xlarge"  : { "Arch" : "64" },
      "m2.4xlarge"  : { "Arch" : "64" },
      "m3.xlarge"   : { "Arch" : "64" },
      "m3.2xlarge"  : { "Arch" : "64" },
      "c1.medium"   : { "Arch" : "64" },
      "c1.xlarge"   : { "Arch" : "64" }
    },

    "AWSRegionArch2AMI" : {
      "us-east-1"      : { "32" : "ami-aba768c2", "64" : "ami-81a768e8" },
      "us-west-1"      : { "32" : "ami-458fd300", "64" : "ami-b18ed2f4" },
      "us-west-2"      : { "32" : "ami-fcff72cc", "64" : "ami-feff72ce" },
      "eu-west-1"      : { "32" : "ami-018bb975", "64" : "ami-998bb9ed" },
      "sa-east-1"      : { "32" : "ami-a039e6bd", "64" : "ami-a239e6bf" },
      "ap-southeast-1" : { "32" : "ami-425a2010", "64" : "ami-5e5a200c" },
      "ap-southeast-2" : { "32" : "ami-f98512c3", "64" : "ami-43851279" },
      "ap-northeast-1" : { "32" : "ami-7871c579", "64" : "ami-7671c577" }
    },
	
    "RegionMap" : {
      "us-east-1"      : { "AMI" : "ami-7f418316" },
      "us-west-1"      : { "AMI" : "ami-951945d0" },
      "us-west-2"      : { "AMI" : "ami-16fd7026" },
      "eu-west-1"      : { "AMI" : "ami-24506250" },
      "sa-east-1"      : { "AMI" : "ami-3e3be423" },
      "ap-southeast-1" : { "AMI" : "ami-74dda626" },
      "ap-southeast-2" : { "AMI" : "ami-b3990e89" },
      "ap-northeast-1" : { "AMI" : "ami-dcfa4edd" }
    }
  },

  "Resources" : {
    "WebServerSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Enable HTTP access on the configured port",
        "VpcId" : { "Ref" : "VpcId" },
        "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0" } ]
      }
    },

    "IPAddress1" : {
      "Type" : "AWS::EC2::EIP",
      "Properties" : {
        "Domain" : "vpc",
        "InstanceId" : { "Ref" : "Ec2Instance1" }
      }
    },

    "IPAddress2" : {
      "Type" : "AWS::EC2::EIP",
      "Properties" : {
        "Domain" : "vpc",
        "InstanceId" : { "Ref" : "Ec2Instance2" }
      }
    },

    "Ec2Instance1" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]},
        "SecurityGroupIds" : [{ "Ref" : "WebServerSecurityGroup" }],
        "SubnetId" : { "Ref" : "PublicSubnetA" },
        "KeyName" : { "Ref" : "KeyName" }
      }
    },
	
    "Ec2Instance2" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]},
        "SecurityGroupIds" : [{ "Ref" : "WebServerSecurityGroup" }],
        "SubnetId" : { "Ref" : "PublicSubnetB" },
        "KeyName" : { "Ref" : "KeyName" }
      }
    },

    "MySQLDBSubnetGroup" : {
      "Type" : "AWS::RDS::DBSubnetGroup",
      "Properties" : {
        "DBSubnetGroupDescription" : "Subnets available for the RDS DB Instance",
        "SubnetIds" : { "Ref" : "PrivateSubnets" }
      }
    },

    "MySQLDBSecurityGroup" : {
      "Type" : "AWS::RDS::DBSecurityGroup",
      "Properties" : {
        "GroupDescription" : "Security group for RDS DB Instance",
        "EC2VpcId" : { "Ref" : "VpcId" }
      }
    },

    "MySQLDB" : {
      "Type" : "AWS::RDS::DBInstance",
      "Properties" : {
        "DBName" : { "Ref" : "DBName" },
		"MultiAZ" : { "Ref": "MultiAZDatabase" },
        "AllocatedStorage" : { "Ref" : "DBAllocatedStorage" },
        "DBInstanceClass" : { "Ref" : "DBInstanceClass" },
        "Engine" : "MySQL",
        "EngineVersion" : "5.5",
        "MasterUsername" : { "Ref" : "DBUsername" } ,
        "MasterUserPassword" : { "Ref" : "DBPassword" },
        "DBSubnetGroupName" : { "Ref" : "MySQLDBSubnetGroup" },
        "DBSecurityGroups" : [ { "Ref" : "MySQLDBSecurityGroup" } ]
      }
  	}
  },

  "Outputs" : {
    "IPAddress1" : {
      "Value" : { "Ref" : "IPAddress1" },
      "Description" : "Public IP address of instance"
    },

    "IPAddress2" : {
      "Value" : { "Ref" : "IPAddress2" },
      "Description" : "Public IP address of instance"
    },
	
    "InstanceId1" : {
      "Value" : { "Ref" : "Ec2Instance1" },
      "Description" : "Instance Id of newly created instance"
    },

    "InstanceId2" : {
      "Value" : { "Ref" : "Ec2Instance2" },
      "Description" : "Instance Id of newly created instance"
    },

    "PDOConnectionString": {
      "Description" : "PDO connection string for database",
      "Value" : { "Fn::Join": [ "", [ "'mysql:host=",
                                      { "Fn::GetAtt": [ "MySQLDB", "Endpoint.Address" ] },
	  								  ";port=",
                                      { "Fn::GetAtt": [ "MySQLDB", "Endpoint.Port" ] },
	  								  ";dbname=",
                                      { "Ref": "DBName" },
	  								  "','",
                                      { "Ref": "DBUsername" },
									  "'"
									  ]]}
    }
  }
}

Public サブネットに AutoScaling グループを持つ ELB を作成、 Private サブネットに RDS を Multi-AZ で配置 (Stack2)

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "In an existing VPC and multiple subnets, the public subnets contains an Auto Scaling group behind a load balancer, and the private subnets contains a RDS Multi-AZ DBInstances.",

  "Parameters" : {
    "KeyName" : {
      "Description" : "Name of and existing EC2 KeyPair",
      "Type" : "String"
    },

	"VpcId" : {
      "Type" : "String",
      "Description" : "VpcId of your existing VPC"
    },

    "PublicSubnets" : {
      "Type" : "CommaDelimitedList",
      "Description" : "The list of SubnetIds in your VPC"
    },

    "AZs" : {
      "Type" : "CommaDelimitedList",
      "Description" : "The list of AZs for your VPC"
    },

    "InstanceCount" : {
      "Description" : "Number of EC2 instances to launch",
      "Type" : "Number",
      "Default" : "1"
    },

    "WebServerPort" : {
      "Description" : "TCP/IP port of the web server",
      "Type" : "String",
      "Default" : "80"
    },

	"PrivateSubnets" : {
      "Type" : "CommaDelimitedList",
      "Description" : "The list of SubnetIds, one in each AZ in the region in your VPC"
    },

    "InstanceType" : {
      "Description" : "WebServer EC2 instance type",
      "Type" : "String",
      "Default" : "t1.micro",
      "AllowedValues" : [ "t1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m2.xlarge","m2.2xlarge","m2.4xlarge","m3.xlarge","m3.2xlarge","c1.medium","c1.xlarge","cc1.4xlarge","cc2.8xlarge","cg1.4xlarge"],
      "ConstraintDescription" : "must be a valid EC2 instance type."
    },

    "DBName": {
      "Default": "MyDatabase",
      "Description" : "MySQL database name",
      "Type": "String",
      "MinLength": "1",
      "MaxLength": "64",
      "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
    },

    "DBUsername": {
      "NoEcho": "true",
      "Description" : "Username for MySQL database access",
      "Type": "String",
      "MinLength": "1",
      "MaxLength": "16",
      "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
    },

    "DBPassword": {
      "NoEcho": "true",
      "Description" : "Password for MySQL database access",
      "Type": "String",
      "MinLength": "1",
      "MaxLength": "41",
      "AllowedPattern" : "[a-zA-Z0-9]*",
      "ConstraintDescription" : "must contain only alphanumeric characters."
    },

    "DBAllocatedStorage": {
      "Default": "5",
      "Description" : "The size of the database (Gb)",
      "Type": "Number",
      "MinValue": "5",
      "MaxValue": "1024",
      "ConstraintDescription" : "must be between 5 and 1024Gb."
    },

    "DBInstanceClass": {
      "Default": "db.m1.small",
      "Description" : "The database instance type",
      "Type": "String",
      "AllowedValues" : [ "db.m1.small", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge" ],
      "ConstraintDescription" : "must select a valid database instance type."
    },

    "MultiAZDatabase": {
      "Default": "true",
      "Description" : "Create a multi-AZ MySQL Amazon RDS database instance",
      "Type": "String",
      "AllowedValues" : [ "true", "false" ],
      "ConstraintDescription" : "must be either true or false."
    }
  },

  "Mappings" : {
    "AWSInstanceType2Arch" : {
      "t1.micro"    : { "Arch" : "64" },
      "m1.small"    : { "Arch" : "64" },
      "m1.medium"   : { "Arch" : "64" },
      "m1.large"    : { "Arch" : "64" },
      "m1.xlarge"   : { "Arch" : "64" },
      "m2.xlarge"   : { "Arch" : "64" },
      "m2.2xlarge"  : { "Arch" : "64" },
      "m2.4xlarge"  : { "Arch" : "64" },
      "m3.xlarge"   : { "Arch" : "64" },
      "m3.2xlarge"  : { "Arch" : "64" },
      "c1.medium"   : { "Arch" : "64" },
      "c1.xlarge"   : { "Arch" : "64" }
    },

    "AWSRegionArch2AMI" : {
      "us-east-1"      : { "32" : "ami-aba768c2", "64" : "ami-81a768e8" },
      "us-west-1"      : { "32" : "ami-458fd300", "64" : "ami-b18ed2f4" },
      "us-west-2"      : { "32" : "ami-fcff72cc", "64" : "ami-feff72ce" },
      "eu-west-1"      : { "32" : "ami-018bb975", "64" : "ami-998bb9ed" },
      "sa-east-1"      : { "32" : "ami-a039e6bd", "64" : "ami-a239e6bf" },
      "ap-southeast-1" : { "32" : "ami-425a2010", "64" : "ami-5e5a200c" },
      "ap-southeast-2" : { "32" : "ami-f98512c3", "64" : "ami-43851279" },
      "ap-northeast-1" : { "32" : "ami-7871c579", "64" : "ami-7671c577" }
    },
	
    "RegionMap" : {
      "us-east-1"      : { "AMI" : "ami-7f418316" },
      "us-west-1"      : { "AMI" : "ami-951945d0" },
      "us-west-2"      : { "AMI" : "ami-16fd7026" },
      "eu-west-1"      : { "AMI" : "ami-24506250" },
      "sa-east-1"      : { "AMI" : "ami-3e3be423" },
      "ap-southeast-1" : { "AMI" : "ami-74dda626" },
      "ap-southeast-2" : { "AMI" : "ami-b3990e89" },
      "ap-northeast-1" : { "AMI" : "ami-dcfa4edd" }
    }
  },

  "Resources" : {
    "ElasticLoadBalancer" : {
      "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
      "Properties" : {
        "SecurityGroups" : [ { "Ref" : "LoadBalancerSecurityGroup" } ],
        "Subnets" : { "Ref" : "PublicSubnets" },
        "Listeners" : [ {
          "LoadBalancerPort" : "80",
          "InstancePort" : { "Ref" : "WebServerPort" },
          "Protocol" : "HTTP"
        } ],
        "HealthCheck" : {
          "Target" : { "Fn::Join" : [ "", ["HTTP:", { "Ref" : "WebServerPort" }, "/"]]},
          "HealthyThreshold" : "3",
          "UnhealthyThreshold" : "5",
          "Interval" : "90",
          "Timeout" : "60"
        }
      }
    },

    "LoadBalancerSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Enable HTTP access on port 80",
        "VpcId" : { "Ref" : "VpcId" },
        "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0" } ],
        "SecurityGroupEgress" : [ { "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0" } ]
	  }
    },

    "WebServerGroup" : {
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
      "Properties" : {
        "AvailabilityZones" : { "Ref" : "AZs" },
        "VPCZoneIdentifier" : { "Ref" : "PublicSubnets" },
        "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
        "MinSize" : "1",
        "MaxSize" : "10",
        "DesiredCapacity" : { "Ref" : "InstanceCount" },
        "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ]
      }
    },

    "LaunchConfig" : {
      "Type" : "AWS::AutoScaling::LaunchConfiguration",
      "Properties" : {
        "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
                                          { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, 
                                          "Arch" ] } ] },
        "UserData" : { "Fn::Base64" : { "Ref" : "WebServerPort" }},
        "SecurityGroups" : [ { "Ref" : "WebServerSecurityGroup" } ],
        "InstanceType" : { "Ref" : "InstanceType" }
      }
    },

    "WebServerSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Enable HTTP access on the configured port",
        "VpcId" : { "Ref" : "VpcId" },
        "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "SourceSecurityGroupId" : { "Ref" : "LoadBalancerSecurityGroup" } } ]
      }
    },

    "MySQLDBSubnetGroup" : {
      "Type" : "AWS::RDS::DBSubnetGroup",
      "Properties" : {
        "DBSubnetGroupDescription" : "Subnets available for the RDS DB Instance",
        "SubnetIds" : { "Ref" : "PrivateSubnets" }
      }
    },

    "MySQLDBSecurityGroup" : {
      "Type" : "AWS::RDS::DBSecurityGroup",
      "Properties" : {
        "GroupDescription" : "Security group for RDS DB Instance",
        "EC2VpcId" : { "Ref" : "VpcId" }
      }
    },

    "MySQLDB" : {
      "Type" : "AWS::RDS::DBInstance",
      "Properties" : {
        "DBName" : { "Ref" : "DBName" },
		"MultiAZ" : { "Ref": "MultiAZDatabase" },
        "AllocatedStorage" : { "Ref" : "DBAllocatedStorage" },
        "DBInstanceClass" : { "Ref" : "DBInstanceClass" },
        "Engine" : "MySQL",
        "EngineVersion" : "5.5",
        "MasterUsername" : { "Ref" : "DBUsername" } ,
        "MasterUserPassword" : { "Ref" : "DBPassword" },
        "DBSubnetGroupName" : { "Ref" : "MySQLDBSubnetGroup" },
        "DBSecurityGroups" : [ { "Ref" : "MySQLDBSecurityGroup" } ]
      }
  	}
  },

  "Outputs" : {
    "URL" : {
      "Description" : "URL of the website",
      "Value" :  { "Fn::Join" : [ "", [ "http://", { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}]]}
    },
	
    "PDOConnectionString": {
      "Description" : "PDO connection string for database",
      "Value" : { "Fn::Join": [ "", [ "'mysql:host=",
                                      { "Fn::GetAtt": [ "MySQLDB", "Endpoint.Address" ] },
	  								  ";port=",
                                      { "Fn::GetAtt": [ "MySQLDB", "Endpoint.Port" ] },
	  								  ";dbname=",
                                      { "Ref": "DBName" },
	  								  "','",
                                      { "Ref": "DBUsername" },
									  "'"
									  ]]}
    }
  }
}

「コンパクト」に、という割に長いですね...