Created
March 14, 2014 09:35
-
-
Save miyamoto-daisuke/9544801 to your computer and use it in GitHub Desktop.
AWS CloudFormation tempate for PHP Blue-Green Deployment environment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "AWSTemplateFormatVersion" : "2010-09-09", | |
| "Description" : "PHP Blue-Green Deployment environment template", | |
| "Parameters" : { | |
| "KeyName" : { | |
| "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances", | |
| "Type" : "String", | |
| "MinLength" : "1", | |
| "MaxLength" : "64", | |
| "AllowedPattern" : "[-_ a-zA-Z0-9]*", | |
| "ConstraintDescription" : "can contain only alphanumeric characters, spaces, dashes and underscores." | |
| }, | |
| "DeveloperBlock" : { | |
| "Description" : "Lockdown SSH access to the bastion host (default can be accessed from anywhere)", | |
| "Type" : "String", | |
| "MinLength" : "9", | |
| "MaxLength" : "18", | |
| "Default" : "0.0.0.0/0", | |
| "AllowedPattern" : "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", | |
| "ConstraintDescription" : "must be a valid CIDR range of the form x.x.x.x/x." | |
| }, | |
| "DBUsername" : { | |
| "Default" : "admin", | |
| "Description" : "The database master account username", | |
| "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" : { | |
| "Description" : "Password of RDS master password", | |
| "Type" : "String", | |
| "MinLength" : "4" | |
| }, | |
| "DBSnapshotName" : { | |
| "Default" : "", | |
| "Description" : "The name of a DB snapshot (optional)", | |
| "Type" : "String" | |
| }, | |
| "HostedZone" : { | |
| "Description" : "The DNS name of an existing Amazon Route 53 hosted zone", | |
| "Type" : "String" | |
| }, | |
| "ProductionEnv" : { | |
| "Description" : "Production Environment name", | |
| "Default" : "blue", | |
| "Type" : "String", | |
| "AllowedValues" : [ "blue", "green" ], | |
| "ConstraintDescription" : "must specify blue or green." | |
| }, | |
| "BlueInstanceType" : { | |
| "Description" : "EC2 instance type for the Blue environment", | |
| "Default" : "t1.micro", | |
| "Type" : "String" | |
| }, | |
| "GreenInstanceType" : { | |
| "Description" : "EC2 instance type for the Green environment", | |
| "Default" : "t1.micro", | |
| "Type" : "String" | |
| }, | |
| "BlueFleetSize" : { | |
| "Description" : "Number of EC2 instances to launch for the Blue server", | |
| "Default" : "2", | |
| "Type" : "Number", | |
| "MaxValue" : "10", | |
| "MinValue" : "0" | |
| }, | |
| "GreenFleetSize" : { | |
| "Description" : "Number of EC2 instances to launch for the Green server", | |
| "Default" : "2", | |
| "Type" : "Number", | |
| "MaxValue" : "10", | |
| "MinValue" : "0" | |
| }, | |
| "BlueApplicationURL" : { | |
| "Description" : "Package URL for the Blue environment", | |
| "Type" : "String" | |
| }, | |
| "GreenApplicationURL" : { | |
| "Description" : "Package URL for the Green environment", | |
| "Type" : "String" | |
| }, | |
| "BlueDatabaseName" : { | |
| "Description" : "DB name for the Blue environment", | |
| "Default" : "production", | |
| "Type" : "String" | |
| }, | |
| "GreenDatabaseName" : { | |
| "Description" : "DB name for the Green environment", | |
| "Default" : "development", | |
| "Type" : "String" | |
| } | |
| }, | |
| "Conditions" : { | |
| "ProductionBlue" : { "Fn::Equals" : [ { "Ref" : "ProductionEnv" }, "blue" ] }, | |
| "ProductionGreen" : { "Fn::Equals" : [ { "Ref" : "ProductionEnv" }, "green" ] }, | |
| "UseDBSnapshot" : { "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "DBSnapshotName" }, "" ] } ] } | |
| }, | |
| "Mappings" : { | |
| "AWSAmazonLinuxAMI" : { | |
| "us-east-1" : { "name" :"Virginia", "201303" : "ami-3275ee5b", "201309" : "ami-35792c5c" }, | |
| "us-west-2" : { "name" :"Oregon", "201303" : "ami-ecbe2adc", "201309" : "ami-d03ea1e0" }, | |
| "us-west-1" : { "name" :"California", "201303" : "ami-66d1fc23", "201309" : "ami-687b4f2d" }, | |
| "eu-west-1" : { "name" :"Ireland", "201303" : "ami-44939930", "201309" : "ami-149f7863" }, | |
| "ap-southeast-1" : { "name" :"Singapole", "201303" : "ami-aa9ed2f8", "201309" : "ami-14f2b946" }, | |
| "ap-southeast-2" : { "name" :"Sydney", "201303" : "ami-363eaf0c", "201309" : "ami-a148d59b" }, | |
| "ap-northeast-1" : { "name" :"Tokyo", "201303" : "ami-173fbf16", "201309" : "ami-3561fe34" }, | |
| "sa-east-1" : { "name" :"SaoPaulo", "201303" : "ami-dd6bb0c0", "201309" : "ami-9f6ec982" } | |
| }, | |
| "AZ" : { | |
| "us-east-1" : { "primary" : "us-east-1b", "secondary" : "us-east-1c" }, | |
| "us-west-2" : { "primary" : "us-west-2a", "secondary" : "us-west-2b" }, | |
| "us-west-1" : { "primary" : "us-west-1a", "secondary" : "us-west-1b" }, | |
| "eu-west-1" : { "primary" : "eu-west-1a", "secondary" : "eu-west-1b" }, | |
| "ap-southeast-1" : { "primary" : "ap-southeast-1a", "secondary" : "ap-southeast-1b" }, | |
| "ap-southeast-2" : { "primary" : "ap-southeast-2a", "secondary" : "ap-southeast-2b" }, | |
| "ap-northeast-1" : { "primary" : "ap-northeast-1a", "secondary" : "ap-northeast-1c" }, | |
| "sa-east-1" : { "primary" : "sa-east-1a", "secondary" : "sa-east-1b" } | |
| }, | |
| "StackConfig" : { | |
| "VPC" : { "CIDR" : "10.0.0.0/16" }, | |
| "FrontendSubnet1" : { "CIDR" : "10.0.0.0/24" }, | |
| "FrontendSubnet2" : { "CIDR" : "10.0.1.0/24" }, | |
| "ApplicationSubnet1" : { "CIDR" : "10.0.2.0/24" }, | |
| "ApplicationSubnet2" : { "CIDR" : "10.0.3.0/24" }, | |
| "DatastoreSubnet1" : { "CIDR" : "10.0.4.0/24" }, | |
| "DatastoreSubnet2" : { "CIDR" : "10.0.5.0/24" }, | |
| "BastionServer" : { "InstanceType" : "t1.micro" }, | |
| "DBServer" : { "InstanceType" : "db.t1.micro", "AllocatedStorage" : "5" } | |
| } | |
| }, | |
| "Resources" : { | |
| "PowerUserRole" : { | |
| "Type" : "AWS::IAM::Role", | |
| "Properties" : { | |
| "AssumeRolePolicyDocument" : { | |
| "Statement" : [ { | |
| "Effect" : "Allow", | |
| "Principal" : { | |
| "Service" : [ "ec2.amazonaws.com" ] | |
| }, | |
| "Action" : [ "sts:AssumeRole" ] | |
| } ] | |
| }, | |
| "Path" : "/", | |
| "Policies" :[ { | |
| "PolicyName" : "PowerUserPolicy", | |
| "PolicyDocument" : { | |
| "Statement" : [ { | |
| "Sid" : "PowerUserStmt", | |
| "Effect" : "Allow", | |
| "NotAction" : "iam:*", | |
| "Resource" : "*" | |
| } ] | |
| } | |
| }] | |
| } | |
| }, | |
| "PowerUserProfile" : { | |
| "Type" : "AWS::IAM::InstanceProfile", | |
| "Properties" : { | |
| "Path" : "/", | |
| "Roles" : [ { "Ref" : "PowerUserRole" } ] | |
| } | |
| }, | |
| "VPC" : { | |
| "Type" : "AWS::EC2::VPC", | |
| "Properties" : { | |
| "CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]}, | |
| "EnableDnsSupport" : "true", | |
| "EnableDnsHostnames" : "true", | |
| "InstanceTenancy" : "default", | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Public" } | |
| ] | |
| } | |
| }, | |
| "InternetGateway" : { | |
| "Type" : "AWS::EC2::InternetGateway", | |
| "Properties" : { | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Public" } | |
| ] | |
| } | |
| }, | |
| "AttachGateway" : { | |
| "Type" : "AWS::EC2::VPCGatewayAttachment", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "InternetGatewayId" : { "Ref" : "InternetGateway" } | |
| } | |
| }, | |
| "PublicRouteTable" : { | |
| "Type" : "AWS::EC2::RouteTable", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Public" } | |
| ] | |
| } | |
| }, | |
| "PrivateRouteTable" : { | |
| "Type" : "AWS::EC2::RouteTable", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Protected" } | |
| ] | |
| } | |
| }, | |
| "PublicRoute" : { | |
| "Type" : "AWS::EC2::Route", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "RouteTableId" : { "Ref" : "PublicRouteTable" }, | |
| "DestinationCidrBlock" : "0.0.0.0/0", | |
| "GatewayId" : { "Ref" : "InternetGateway" } | |
| } | |
| }, | |
| "FrontendSubnet1" : { | |
| "Type" : "AWS::EC2::Subnet", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "AvailabilityZone" : { "Fn::FindInMap" : [ "AZ", { "Ref" : "AWS::Region" }, "primary" ]}, | |
| "CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "FrontendSubnet1", "CIDR" ]}, | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Public" } | |
| ] | |
| } | |
| }, | |
| "FrontendSubnet2" : { | |
| "Type" : "AWS::EC2::Subnet", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "AvailabilityZone" : { "Fn::FindInMap" : [ "AZ", { "Ref" : "AWS::Region" }, "secondary" ]}, | |
| "CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "FrontendSubnet2", "CIDR" ]}, | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Public" } | |
| ] | |
| } | |
| }, | |
| "ApplicationSubnet1" : { | |
| "Type" : "AWS::EC2::Subnet", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "ApplicationSubnet1", "CIDR" ]}, | |
| "AvailabilityZone" : { "Fn::FindInMap" : [ "AZ", { "Ref" : "AWS::Region" }, "primary" ]}, | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Public" } | |
| ] | |
| } | |
| }, | |
| "ApplicationSubnet2" : { | |
| "Type" : "AWS::EC2::Subnet", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "ApplicationSubnet2", "CIDR" ]}, | |
| "AvailabilityZone" : { "Fn::FindInMap" : [ "AZ", { "Ref" : "AWS::Region" }, "secondary" ]}, | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Public" } | |
| ] | |
| } | |
| }, | |
| "DatastoreSubnet1" : { | |
| "Type" : "AWS::EC2::Subnet", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "DatastoreSubnet1", "CIDR" ]}, | |
| "AvailabilityZone" : { "Fn::FindInMap" : [ "AZ", { "Ref" : "AWS::Region" }, "primary" ]}, | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Private" } | |
| ] | |
| } | |
| }, | |
| "DatastoreSubnet2" : { | |
| "Type" : "AWS::EC2::Subnet", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "DatastoreSubnet2", "CIDR" ]}, | |
| "AvailabilityZone" : { "Fn::FindInMap" : [ "AZ", { "Ref" : "AWS::Region" }, "secondary" ]}, | |
| "Tags" : [ | |
| { "Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } }, | |
| { "Key" : "Network", "Value" : "Private" } | |
| ] | |
| } | |
| }, | |
| "FrontendSubnet1RouteTableAssociation" : { | |
| "Type" : "AWS::EC2::SubnetRouteTableAssociation", | |
| "Properties" : { | |
| "SubnetId" : { "Ref" : "FrontendSubnet1" }, | |
| "RouteTableId" : { "Ref" : "PublicRouteTable" } | |
| } | |
| }, | |
| "FrontendSubnet2RouteTableAssociation" : { | |
| "Type" : "AWS::EC2::SubnetRouteTableAssociation", | |
| "Properties" : { | |
| "SubnetId" : { "Ref" : "FrontendSubnet2" }, | |
| "RouteTableId" : { "Ref" : "PublicRouteTable" } | |
| } | |
| }, | |
| "ApplicationSubnet1RouteTableAssociation" : { | |
| "Type" : "AWS::EC2::SubnetRouteTableAssociation", | |
| "Properties" : { | |
| "SubnetId" : { "Ref" : "ApplicationSubnet1" }, | |
| "RouteTableId" : { "Ref" : "PublicRouteTable" } | |
| } | |
| }, | |
| "ApplicationSubnet2RouteTableAssociation" : { | |
| "Type" : "AWS::EC2::SubnetRouteTableAssociation", | |
| "Properties" : { | |
| "SubnetId" : { "Ref" : "ApplicationSubnet2" }, | |
| "RouteTableId" : { "Ref" : "PublicRouteTable" } | |
| } | |
| }, | |
| "DatastoreSubnet1RouteTableAssociation" : { | |
| "Type" : "AWS::EC2::SubnetRouteTableAssociation", | |
| "Properties" : { | |
| "SubnetId" : { "Ref" : "DatastoreSubnet1" }, | |
| "RouteTableId" : { "Ref" : "PrivateRouteTable" } | |
| } | |
| }, | |
| "DatastoreSubnet2RouteTableAssociation" : { | |
| "Type" : "AWS::EC2::SubnetRouteTableAssociation", | |
| "Properties" : { | |
| "SubnetId" : { "Ref" : "DatastoreSubnet2" }, | |
| "RouteTableId" : { "Ref" : "PrivateRouteTable" } | |
| } | |
| }, | |
| "VPCDefaultSecurityGroup" : { | |
| "Type" : "AWS::EC2::SecurityGroup", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "GroupDescription" : "Allow all communications in VPC", | |
| "SecurityGroupIngress" : [ | |
| { "IpProtocol" : "tcp", "FromPort" : "0", "ToPort" : "65535", "CidrIp" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]} }, | |
| { "IpProtocol" : "udp", "FromPort" : "0", "ToPort" : "65535", "CidrIp" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]} }, | |
| { "IpProtocol" : "icmp", "FromPort" : "-1", "ToPort" : "-1", "CidrIp" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]} } | |
| ] | |
| } | |
| }, | |
| "SSHSecurityGroup" : { | |
| "Type" : "AWS::EC2::SecurityGroup", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "GroupDescription" : "Enable SSH access via port 22", | |
| "SecurityGroupIngress" : [{ | |
| "IpProtocol" : "tcp", | |
| "FromPort" : "22", | |
| "ToPort" : "22", | |
| "CidrIp" : { "Ref" : "DeveloperBlock" } | |
| }] | |
| } | |
| }, | |
| "PublicWebSecurityGroup" : { | |
| "Type" : "AWS::EC2::SecurityGroup", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "GroupDescription" : "Public Security Group with HTTP access on port 443 from the internet", | |
| "SecurityGroupIngress" : [ | |
| { "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0" }, | |
| { "IpProtocol" : "tcp", "FromPort" : "443", "ToPort" : "443", "CidrIp" : "0.0.0.0/0" } | |
| ] | |
| } | |
| }, | |
| "ApplicationSecurityGroup" : { | |
| "Type" : "AWS::EC2::SecurityGroup", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "GroupDescription" : "Marker security group for Application server." | |
| } | |
| }, | |
| "MySQLSecurityGroup" : { | |
| "Type" : "AWS::EC2::SecurityGroup", | |
| "Properties" : { | |
| "VpcId" : { "Ref" : "VPC" }, | |
| "GroupDescription" : "Marker security group for MySQL server." | |
| } | |
| }, | |
| "BastionDNSRecord" : { | |
| "Type" : "AWS::Route53::RecordSet", | |
| "Properties" : { | |
| "HostedZoneName" : { "Fn::Join" : [ "", [{ "Ref" : "HostedZone" }, "." ]]}, | |
| "Comment" : "A record for the Bastion instance.", | |
| "Name" : { "Fn::Join" : [ "", [ "bastion.", { "Ref" : "HostedZone" }, "." ]]}, | |
| "Type" : "A", | |
| "TTL" : "300", | |
| "ResourceRecords" : [ | |
| { "Ref" :"BastionInstanceEIP" } | |
| ] | |
| } | |
| }, | |
| "BastionLocalDNSRecord" : { | |
| "Type" : "AWS::Route53::RecordSet", | |
| "Properties" : { | |
| "HostedZoneName" : { "Fn::Join" : [ "", [{ "Ref" : "HostedZone" }, "." ]]}, | |
| "Comment" : "A record for the private IP address of Bastion instance.", | |
| "Name" : { "Fn::Join" : [ "", [ "bastion.local.", { "Ref" : "HostedZone" }, "." ]]}, | |
| "Type" : "A", | |
| "TTL" : "300", | |
| "ResourceRecords" : [ | |
| { "Fn::GetAtt" : [ "BastionInstance", "PrivateIp" ] } | |
| ] | |
| } | |
| }, | |
| "BastionInstanceEIP" : { | |
| "Type" : "AWS::EC2::EIP", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "Domain" : "vpc", | |
| "InstanceId" : { "Ref" : "BastionInstance" } | |
| } | |
| }, | |
| "BastionWaitHandle" : { | |
| "Type" : "AWS::CloudFormation::WaitConditionHandle" | |
| }, | |
| "BastionWaitCondition" : { | |
| "Type" : "AWS::CloudFormation::WaitCondition", | |
| "DependsOn" : "BastionInstance", | |
| "Properties" : { | |
| "Handle" : { "Ref" : "BastionWaitHandle" }, | |
| "Timeout" : "900" | |
| } | |
| }, | |
| "BastionInstance" : { | |
| "Type" : "AWS::EC2::Instance", | |
| "Properties" : { | |
| "InstanceType" : { "Fn::FindInMap" : [ "StackConfig", "BastionServer", "InstanceType" ]}, | |
| "KeyName" : { "Ref" : "KeyName" }, | |
| "SubnetId" : { "Ref" : "FrontendSubnet1" }, | |
| "ImageId" : { "Fn::FindInMap" : [ "AWSAmazonLinuxAMI", { "Ref" : "AWS::Region" }, "201309" ]}, | |
| "IamInstanceProfile" : { "Ref" : "PowerUserProfile" }, | |
| "SecurityGroupIds" : [ | |
| { "Ref" : "SSHSecurityGroup" }, | |
| { "Ref" : "VPCDefaultSecurityGroup" } | |
| ], | |
| "Tags" : [ | |
| { "Key" : "Name", "Value" : "Bastion" } | |
| ], | |
| "UserData" : { "Fn::Base64" : { "Fn::Join" : [ "", [ | |
| "#! /bin/bash -v\n", | |
| "yum update -y\n", | |
| "# Helper function\n", | |
| "function error_exit\n", | |
| "{\n", | |
| " /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", { "Ref" : "BastionWaitHandle" }, "'\n", | |
| " exit 1\n", | |
| "}\n", | |
| "# Install packages\n", | |
| "/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r BastionInstance ", | |
| " --region ", { "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-init'\n", | |
| "# All is well so signal success\n", | |
| "/opt/aws/bin/cfn-signal -e $? -r \"BastionInstance setup complete\" '", { "Ref" : "BastionWaitHandle" }, "'\n" | |
| ]]}} | |
| }, | |
| "Metadata" : { | |
| "AWS::CloudFormation::Init" : { | |
| "config" : { | |
| "packages" : { | |
| "yum" : { | |
| "mysql55" : [], | |
| "jq" : [], | |
| "python-magic" : [] | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }, | |
| "PublicLoadBalancerDNSRecord" : { | |
| "Type" : "AWS::Route53::RecordSetGroup", | |
| "Properties" : { | |
| "HostedZoneName" : { "Fn::Join" : [ "", [ { "Ref" : "HostedZone" }, "." ]]}, | |
| "Comment" : "Zone apex alias targeted to LoadBalancer.", | |
| "RecordSets" : [ | |
| { | |
| "Name" : { "Fn::Join" : [ "", [ { "Ref" : "HostedZone" }, "." ]]}, | |
| "Type" : "A", | |
| "AliasTarget" : { "Fn::If" : [ "ProductionBlue", | |
| { | |
| "HostedZoneId" : { "Fn::GetAtt" : [ "BlueElasticLoadBalancer", "CanonicalHostedZoneNameID" ] }, | |
| "DNSName" : { "Fn::GetAtt" : [ "BlueElasticLoadBalancer","CanonicalHostedZoneName" ] } | |
| }, | |
| { | |
| "HostedZoneId" : { "Fn::GetAtt" : [ "GreenElasticLoadBalancer", "CanonicalHostedZoneNameID" ] }, | |
| "DNSName" : { "Fn::GetAtt" : [ "GreenElasticLoadBalancer","CanonicalHostedZoneName" ] } | |
| } | |
| ]} | |
| } | |
| ] | |
| } | |
| }, | |
| "BlueLoadBalancerDNSRecord" : { | |
| "Type" : "AWS::Route53::RecordSetGroup", | |
| "Properties" : { | |
| "HostedZoneName" : { "Fn::Join" : [ "", [ { "Ref" : "HostedZone" }, "." ]]}, | |
| "Comment" : "Zone apex alias targeted to LoadBalancer.", | |
| "RecordSets" : [ | |
| { | |
| "Name" : { "Fn::Join" : [ "", [ "blue.", { "Ref" : "HostedZone" }, "." ]]}, | |
| "Type" : "A", | |
| "AliasTarget" : { | |
| "HostedZoneId" : { "Fn::GetAtt" : [ "BlueElasticLoadBalancer", "CanonicalHostedZoneNameID" ] }, | |
| "DNSName" : { "Fn::GetAtt" : [ "BlueElasticLoadBalancer","CanonicalHostedZoneName" ] } | |
| } | |
| } | |
| ] | |
| } | |
| }, | |
| "GreenLoadBalancerDNSRecord" : { | |
| "Type" : "AWS::Route53::RecordSetGroup", | |
| "Properties" : { | |
| "HostedZoneName" : { "Fn::Join" : [ "", [ { "Ref" : "HostedZone" }, "." ]]}, | |
| "Comment" : "Zone apex alias targeted to LoadBalancer.", | |
| "RecordSets" : [ | |
| { | |
| "Name" : { "Fn::Join" : [ "", [ "green.", { "Ref" : "HostedZone" }, "." ]]}, | |
| "Type" : "A", | |
| "AliasTarget" : { | |
| "HostedZoneId" : { "Fn::GetAtt" : [ "GreenElasticLoadBalancer", "CanonicalHostedZoneNameID" ] }, | |
| "DNSName" : { "Fn::GetAtt" : [ "GreenElasticLoadBalancer","CanonicalHostedZoneName" ] } | |
| } | |
| } | |
| ] | |
| } | |
| }, | |
| "BlueElasticLoadBalancer" : { | |
| "Type" : "AWS::ElasticLoadBalancing::LoadBalancer", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "Subnets" : [ | |
| { "Ref" : "FrontendSubnet1" }, | |
| { "Ref" : "FrontendSubnet2" } | |
| ], | |
| "Listeners" : [ | |
| { "LoadBalancerPort" : "80", "InstancePort" : "80", "Protocol" : "HTTP" } | |
| ], | |
| "HealthCheck" : { | |
| "Target" : "HTTP:80/healthcheck.php", | |
| "HealthyThreshold" : "2", | |
| "UnhealthyThreshold" : "2", | |
| "Interval" : "6", | |
| "Timeout" : "5" | |
| }, | |
| "SecurityGroups" : [ | |
| { "Ref" : "PublicWebSecurityGroup" } | |
| ] | |
| } | |
| }, | |
| "GreenElasticLoadBalancer" : { | |
| "Type" : "AWS::ElasticLoadBalancing::LoadBalancer", | |
| "DependsOn" : "AttachGateway", | |
| "Properties" : { | |
| "Subnets" : [ | |
| { "Ref" : "FrontendSubnet1" }, | |
| { "Ref" : "FrontendSubnet2" } | |
| ], | |
| "Listeners" : [ | |
| { "LoadBalancerPort" : "80", "InstancePort" : "80", "Protocol" : "HTTP" } | |
| ], | |
| "HealthCheck" : { | |
| "Target" : "HTTP:80/healthcheck.php", | |
| "HealthyThreshold" : "2", | |
| "UnhealthyThreshold" : "2", | |
| "Interval" : "6", | |
| "Timeout" : "5" | |
| }, | |
| "SecurityGroups" : [ | |
| { "Ref" : "PublicWebSecurityGroup" } | |
| ] | |
| } | |
| }, | |
| "BlueApplicationFleet" : { | |
| "Type" : "AWS::AutoScaling::AutoScalingGroup", | |
| "DependsOn" : "PublicRoute", | |
| "UpdatePolicy" : { | |
| "AutoScalingRollingUpdate" : { | |
| "MaxBatchSize" : "1", | |
| "MinInstancesInService" : "1", | |
| "PauseTime" : "PT2M30S" | |
| } | |
| }, | |
| "Properties" : { | |
| "AvailabilityZones" : [ | |
| { "Fn::GetAtt" : [ "ApplicationSubnet1", "AvailabilityZone" ] }, | |
| { "Fn::GetAtt" : [ "ApplicationSubnet2", "AvailabilityZone" ] } | |
| ], | |
| "VPCZoneIdentifier" : [ | |
| { "Ref" : "ApplicationSubnet1" }, | |
| { "Ref" : "ApplicationSubnet2" } | |
| ], | |
| "LaunchConfigurationName" : { "Ref" : "BlueApplicationServerLaunchConfig" }, | |
| "MinSize" : "0", | |
| "MaxSize" : "10", | |
| "DesiredCapacity" : { "Ref" : "BlueFleetSize" }, | |
| "LoadBalancerNames" : [ { "Ref" : "BlueElasticLoadBalancer" } ], | |
| "Tags" : [ | |
| { "Key" : "Name", "Value" : "BlueApplication", "PropagateAtLaunch" : "true" } | |
| ] | |
| } | |
| }, | |
| "GreenApplicationFleet" : { | |
| "Type" : "AWS::AutoScaling::AutoScalingGroup", | |
| "DependsOn" : "PublicRoute", | |
| "UpdatePolicy" : { | |
| "AutoScalingRollingUpdate" : { | |
| "MaxBatchSize" : "1", | |
| "MinInstancesInService" : "1", | |
| "PauseTime" : "PT2M30S" | |
| } | |
| }, | |
| "Properties" : { | |
| "AvailabilityZones" : [ | |
| { "Fn::GetAtt" : [ "ApplicationSubnet1", "AvailabilityZone" ] }, | |
| { "Fn::GetAtt" : [ "ApplicationSubnet2", "AvailabilityZone" ] } | |
| ], | |
| "VPCZoneIdentifier" : [ | |
| { "Ref" : "ApplicationSubnet1" }, | |
| { "Ref" : "ApplicationSubnet2" } | |
| ], | |
| "LaunchConfigurationName" : { "Ref" : "GreenApplicationServerLaunchConfig" }, | |
| "MinSize" : "0", | |
| "MaxSize" : "10", | |
| "DesiredCapacity" : { "Ref" : "GreenFleetSize" }, | |
| "LoadBalancerNames" : [ { "Ref" : "GreenElasticLoadBalancer" } ], | |
| "Tags" : [ | |
| { "Key" : "Name", "Value" : "GreenApplication", "PropagateAtLaunch" : "true" } | |
| ] | |
| } | |
| }, | |
| "BlueApplicationServerLaunchConfig" : { | |
| "Type" : "AWS::AutoScaling::LaunchConfiguration", | |
| "Properties" : { | |
| "InstanceType" : { "Ref" : "BlueInstanceType" }, | |
| "KeyName" : { "Ref" : "KeyName" }, | |
| "ImageId" : { "Fn::FindInMap" : [ "AWSAmazonLinuxAMI", { "Ref" : "AWS::Region" }, "201309" ]}, | |
| "SecurityGroups" : [ | |
| { "Ref" : "VPCDefaultSecurityGroup" }, | |
| { "Ref" : "ApplicationSecurityGroup" } | |
| ], | |
| "IamInstanceProfile" : { "Ref" : "PowerUserProfile" }, | |
| "InstanceMonitoring" : "false", | |
| "AssociatePublicIpAddress" : "true", | |
| "UserData" : { "Fn::Base64" : { "Fn::Join" : [ "", [ | |
| "#! /bin/bash -v\n", | |
| "yum update -y\n", | |
| "# Install packages\n", | |
| "/opt/aws/bin/cfn-init -v", | |
| " -s ", { "Ref" : "AWS::StackId" }, | |
| " -r BlueApplicationServerLaunchConfig", | |
| " -c create", | |
| " --region ", { "Ref" : "AWS::Region" }, " || exit 1\n", | |
| "cat << _EOF_ >>/etc/rc.local\n", | |
| "# Start up the cfn-hup daemon to listen for changes\n", | |
| "/opt/aws/bin/cfn-hup\n", | |
| "_EOF_" | |
| ]]}} | |
| }, | |
| "Metadata" : { | |
| "AWS::CloudFormation::Init" : { | |
| "configSets" : { | |
| "create" : [ | |
| "install_packages", | |
| "configure_cfnhup", | |
| "cleanup_application", | |
| "install_application" | |
| ], | |
| "update" : [ | |
| "install_packages", | |
| "configure_cfnhup", | |
| "cleanup_application", | |
| "install_application" | |
| ] | |
| }, | |
| "install_packages" : { | |
| "packages" : { | |
| "yum" : { | |
| "httpd24" : [], | |
| "mysql55" : [], | |
| "php54" : [], | |
| "php54-mbstring" : [], | |
| "php54-mysql" : [], | |
| "php54-pdo" : [], | |
| "jq" : [], | |
| "python-magic" : [] | |
| } | |
| } | |
| }, | |
| "configure_cfnhup" : { | |
| "files" : { | |
| "/etc/cfn/cfn-hup.conf" : { | |
| "content" : { "Fn::Join" : [ "", [ | |
| "[main]\n", | |
| "stack=", { "Ref" : "AWS::StackName" }, "\n", | |
| "interval=1\n", | |
| "region=", { "Ref" : "AWS::Region" }, "\n" | |
| ]]}, | |
| "mode" : "000400", | |
| "owner" : "root", | |
| "group" : "root" | |
| }, | |
| "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : { | |
| "content" : { "Fn::Join" : [ "", [ | |
| "[cfn-auto-reloader-hook]\n", | |
| "triggers=post.update\n", | |
| "path=Resources.BlueApplicationServerLaunchConfig.Metadata.AWS::CloudFormation::Init\n", | |
| "action=/opt/aws/bin/cfn-init -v", | |
| " -s ", { "Ref" : "AWS::StackName" }, | |
| " -r BlueApplicationServerLaunchConfig", | |
| " -c update", | |
| " --region ", { "Ref" : "AWS::Region" }, "\n", | |
| "runas=root\n" | |
| ]]} | |
| } | |
| } | |
| }, | |
| "cleanup_application" : { | |
| "commands" : { | |
| "remove" : { | |
| "command" : "rm -fr /var/www/html/*" | |
| } | |
| } | |
| }, | |
| "install_application" : { | |
| "sources" : { | |
| "/var/www/html" : { "Ref" : "BlueApplicationURL" } | |
| }, | |
| "files" : { | |
| "/etc/httpd/conf.d/envs.conf" : { | |
| "content" : { "Fn::Join" : [ "", [ | |
| "SetEnv RDS_HOSTNAME ", { "Fn::Join" : [ "", [ "rds.local.", { "Ref" : "HostedZone" } ]]}, "\n", | |
| "SetEnv RDS_PORT ", { "Fn::GetAtt" : [ "DBInstance", "Endpoint.Port" ] }, "\n", | |
| "SetEnv RDS_USERNAME ", { "Ref" : "DBUsername" }, "\n", | |
| "SetEnv RDS_PASSWORD ", { "Ref" : "DBPassword" }, "\n", | |
| "SetEnv RDS_DB_NAME ", { "Ref" : "BlueDatabaseName" }, "\n" | |
| ]]}, | |
| "mode" : "000644", | |
| "owner" : "apache", | |
| "group" : "apache" | |
| } | |
| }, | |
| "commands" : { | |
| "chown" : { | |
| "command" : "chown -R apache:root /var/www/html/* && chmod -R 644 /var/www/html/*" | |
| } | |
| }, | |
| "services" : { | |
| "sysvinit" : { | |
| "httpd" : { | |
| "enabled" : "true", | |
| "ensureRunning" : "true", | |
| "files" : [ "/etc/httpd/conf.d/envs.conf" ], | |
| "sources" : [ "/var/www/html" ] | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }, | |
| "GreenApplicationServerLaunchConfig" : { | |
| "Type" : "AWS::AutoScaling::LaunchConfiguration", | |
| "Properties" : { | |
| "InstanceType" : { "Ref" : "GreenInstanceType" }, | |
| "KeyName" : { "Ref" : "KeyName" }, | |
| "ImageId" : { "Fn::FindInMap" : [ "AWSAmazonLinuxAMI", { "Ref" : "AWS::Region" }, "201309" ]}, | |
| "SecurityGroups" : [ | |
| { "Ref" : "VPCDefaultSecurityGroup" }, | |
| { "Ref" : "ApplicationSecurityGroup" } | |
| ], | |
| "IamInstanceProfile" : { "Ref" : "PowerUserProfile" }, | |
| "InstanceMonitoring" : "false", | |
| "AssociatePublicIpAddress" : "true", | |
| "UserData" : { "Fn::Base64" : { "Fn::Join" : [ "", [ | |
| "#! /bin/bash -v\n", | |
| "yum update -y\n", | |
| "# Install packages\n", | |
| "/opt/aws/bin/cfn-init -v", | |
| " -s ", { "Ref" : "AWS::StackId" }, | |
| " -r GreenApplicationServerLaunchConfig", | |
| " -c create", | |
| " --region ", { "Ref" : "AWS::Region" }, " || exit 1\n", | |
| "cat << _EOF_ >>/etc/rc.local\n", | |
| "# Start up the cfn-hup daemon to listen for changes\n", | |
| "/opt/aws/bin/cfn-hup\n", | |
| "_EOF_" | |
| ]]}} | |
| }, | |
| "Metadata" : { | |
| "AWS::CloudFormation::Init" : { | |
| "configSets" : { | |
| "create" : [ | |
| "install_packages", | |
| "configure_cfnhup", | |
| "cleanup_application", | |
| "install_application" | |
| ], | |
| "update" : [ | |
| "install_packages", | |
| "configure_cfnhup", | |
| "cleanup_application", | |
| "install_application" | |
| ] | |
| }, | |
| "install_packages" : { | |
| "packages" : { | |
| "yum" : { | |
| "httpd24" : [], | |
| "mysql55" : [], | |
| "php54" : [], | |
| "php54-mbstring" : [], | |
| "php54-mysql" : [], | |
| "php54-pdo" : [], | |
| "jq" : [], | |
| "python-magic" : [] | |
| } | |
| } | |
| }, | |
| "configure_cfnhup" : { | |
| "files" : { | |
| "/etc/cfn/cfn-hup.conf" : { | |
| "content" : { "Fn::Join" : [ "", [ | |
| "[main]\n", | |
| "stack=", { "Ref" : "AWS::StackName" }, "\n", | |
| "interval=1\n", | |
| "region=", { "Ref" : "AWS::Region" }, "\n" | |
| ]]}, | |
| "mode" : "000400", | |
| "owner" : "root", | |
| "group" : "root" | |
| }, | |
| "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : { | |
| "content" : { "Fn::Join" : [ "", [ | |
| "[cfn-auto-reloader-hook]\n", | |
| "triggers=post.update\n", | |
| "path=Resources.GreenApplicationServerLaunchConfig.Metadata.AWS::CloudFormation::Init\n", | |
| "action=/opt/aws/bin/cfn-init -v", | |
| " -s ", { "Ref" : "AWS::StackName" }, | |
| " -r GreenApplicationServerLaunchConfig", | |
| " -c update", | |
| " --region ", { "Ref" : "AWS::Region" }, "\n", | |
| "runas=root\n" | |
| ]]} | |
| } | |
| } | |
| }, | |
| "cleanup_application" : { | |
| "commands" : { | |
| "remove" : { | |
| "command" : "rm -fr /var/www/html/*" | |
| } | |
| } | |
| }, | |
| "install_application" : { | |
| "sources" : { | |
| "/var/www/html" : { "Ref" : "GreenApplicationURL" } | |
| }, | |
| "files" : { | |
| "/etc/httpd/conf.d/envs.conf" : { | |
| "content" : { "Fn::Join" : [ "", [ | |
| "SetEnv RDS_HOSTNAME ", { "Fn::Join" : [ "", [ "rds.local.", { "Ref" : "HostedZone" } ]]}, "\n", | |
| "SetEnv RDS_PORT ", { "Fn::GetAtt" : [ "DBInstance", "Endpoint.Port" ] }, "\n", | |
| "SetEnv RDS_USERNAME ", { "Ref" : "DBUsername" }, "\n", | |
| "SetEnv RDS_PASSWORD ", { "Ref" : "DBPassword" }, "\n", | |
| "SetEnv RDS_DB_NAME ", { "Ref" : "GreenDatabaseName" }, "\n" | |
| ]]}, | |
| "mode" : "000644", | |
| "owner" : "apache", | |
| "group" : "apache" | |
| } | |
| }, | |
| "commands" : { | |
| "chown" : { | |
| "command" : "chown -R apache:root /var/www/html/* && chmod -R 644 /var/www/html/*" | |
| } | |
| }, | |
| "services" : { | |
| "sysvinit" : { | |
| "httpd" : { | |
| "enabled" : "true", | |
| "ensureRunning" : "true", | |
| "files" : [ "/etc/httpd/conf.d/envs.conf" ], | |
| "sources" : [ "/var/www/html" ] | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }, | |
| "DatabaseDNSRecord" : { | |
| "Type" : "AWS::Route53::RecordSet", | |
| "Properties" : { | |
| "HostedZoneName" : { "Fn::Join" : [ "", [ { "Ref" : "HostedZone" }, "." ]]}, | |
| "Comment" : "CNAME for the database.", | |
| "Name" : { "Fn::Join" : [ "", [ "rds.local.", { "Ref" : "HostedZone" }, "." ]]}, | |
| "Type" : "CNAME", | |
| "TTL" : "300", | |
| "ResourceRecords" : [ | |
| { "Fn::GetAtt" : [ "DBInstance", "Endpoint.Address" ] } | |
| ] | |
| } | |
| }, | |
| "DBParamGroup" : { | |
| "Type" : "AWS::RDS::DBParameterGroup", | |
| "Properties" : { | |
| "Description" : "Default parameter group", | |
| "Family" : "MySQL5.6", | |
| "Parameters" : { | |
| "character_set_database" : "utf8mb4", | |
| "character_set_client" : "utf8mb4", | |
| "character_set_connection" : "utf8mb4", | |
| "character_set_results" : "utf8mb4", | |
| "character_set_server" : "utf8mb4", | |
| "skip-character-set-client-handshake" : "TRUE" | |
| } | |
| } | |
| }, | |
| "DBSubnetGroup" : { | |
| "Type" : "AWS::RDS::DBSubnetGroup", | |
| "Properties" : { | |
| "DBSubnetGroupDescription" : "Database subnets for RDS", | |
| "SubnetIds" : [ | |
| { "Ref" : "DatastoreSubnet1" }, | |
| { "Ref" : "DatastoreSubnet2" } | |
| ] | |
| } | |
| }, | |
| "DBInstance" : { | |
| "Type" : "AWS::RDS::DBInstance", | |
| "DeletionPolicy" : "Snapshot", | |
| "Properties" : { | |
| "DBInstanceClass" : { "Fn::FindInMap" : [ "StackConfig", "DBServer", "InstanceType" ]}, | |
| "AllocatedStorage" : { "Fn::FindInMap" : [ "StackConfig", "DBServer", "AllocatedStorage" ]}, | |
| "Engine" : "MySQL", | |
| "MultiAZ" : "true", | |
| "EngineVersion" : "5.6.13", | |
| "MasterUsername" : { "Ref" : "DBUsername" }, | |
| "MasterUserPassword" : { "Ref" : "DBPassword" }, | |
| "BackupRetentionPeriod" : "35", | |
| "DBParameterGroupName" : { "Ref" : "DBParamGroup" }, | |
| "DBSubnetGroupName" : { "Ref" : "DBSubnetGroup" }, | |
| "DBSnapshotIdentifier" : { "Fn::If" : [ | |
| "UseDBSnapshot", | |
| { "Ref" : "DBSnapshotName" }, | |
| { "Ref" : "AWS::NoValue" } | |
| ]}, | |
| "PreferredBackupWindow" : "19:00-19:30", | |
| "PreferredMaintenanceWindow" : "sat:20:00-sat:20:30", | |
| "VPCSecurityGroups" : [ | |
| { "Ref" : "VPCDefaultSecurityGroup" }, | |
| { "Ref" : "MySQLSecurityGroup" } | |
| ] | |
| } | |
| } | |
| }, | |
| "Outputs" : { | |
| "SSHToBackendServer" : { | |
| "Value" : { "Fn::Join" :[ "", [ | |
| "ssh -i /path/to/", { "Ref" : "KeyName" }, ".pem", | |
| " -oProxyCommand='ssh -i /path/to/", { "Ref" : "KeyName" }, ".pem", | |
| " -W %h:%p ec2-user@", { "Ref" : "BastionDNSRecord" }, "'", | |
| " ec2-user@<private-ip>" | |
| ]]}, | |
| "Description" : "SSH command to connect to the backend servers" | |
| } | |
| } | |
| } |
Both Green and Blue instances application will be updated when you do a UpdateStack. I don't think that is the desire behaviour for blue green deployment. We want to update the group that is not currently in production only. Later, we will route traffic to the staging group.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_UpdateStack.html