Skip to content

Instantly share code, notes, and snippets.

@stojg
Forked from miyamoto-daisuke/bgd-php.template
Created June 3, 2014 03:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stojg/b70d5a519d9e9d3afc86 to your computer and use it in GitHub Desktop.
Save stojg/b70d5a519d9e9d3afc86 to your computer and use it in GitHub Desktop.
{
"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"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment