We’ve set up CloudFormation templates for EC2 and RDS, so far we’re ready to add necessary stuff for failover application deployment.
By necessary stuff I mean scaling, load balancing, monitoring, security and notifications.
Sounds great, so let’s take a look at template:
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "nopCommerce single level app tier",
"Parameters" : {
"KeyName" : {
"Description" : "Name of an existing EC2 KeyPair",
"Type" : "AWS::EC2::KeyPair::KeyName",
"ConstraintDescription" : "must be the name of an existing EC2 KeyPair."
},
"RDPCidr" : {
"Description" : "IP Cidr that is allowed to RDP to EC2",
"Type" : "String",
"MinLength" : "9",
"MaxLength" : "18",
"AllowedPattern" : "^([0-9]+\\.){3}[0-9]+\\/[0-9]+$"
},
"SNSEndpoint" : {
"Description" : "Email for notifications",
"Type" : "String"
}
},
"Resources" : {
"NotificationTopic" : {
"Type" : "AWS::SNS::Topic",
"Properties" : {
"DisplayName" : "nopCommerce-demo",
"Subscription" : [ { "Endpoint": { "Ref" : "SNSEndpoint" }, "Protocol": "email" } ],
"TopicName" : "nopCommerce-demo"
}
},
"WebServerSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable http access from anywhere and RDP from office",
"SecurityGroupIngress": [
{"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"},
{"IpProtocol" : "tcp", "FromPort" : "3389", "ToPort" : "3389", "CidrIp" : { "Ref" : "RDPCidr" } }
]
}
},
"WebServerGroup" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"AvailabilityZones" : { "Fn::GetAZs" : ""},
"Cooldown" : "60",
"HealthCheckGracePeriod" : "120",
"HealthCheckType" : "EC2",
"LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
"MinSize" : "2",
"MaxSize" : "4",
"LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ],
"MetricsCollection" : [ {
"Granularity" : "1Minute"
} ],
"NotificationConfiguration" : {
"TopicARN" : { "Ref" : "NotificationTopic" },
"NotificationTypes" : [
"autoscaling:EC2_INSTANCE_LAUNCH",
"autoscaling:EC2_INSTANCE_LAUNCH_ERROR",
"autoscaling:EC2_INSTANCE_TERMINATE",
"autoscaling:EC2_INSTANCE_TERMINATE_ERROR"
]
}
},
"UpdatePolicy" : {
"AutoScalingRollingUpdate" : {
"MaxBatchSize" : "1",
"MinInstancesInService" : "0",
"MinSuccessfulInstancesPercent" : "100",
"WaitOnResourceSignals" : "true"
}
}
},
"LaunchConfig" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties" : {
"BlockDeviceMappings" : [ {
"DeviceName" : "/dev/sda1",
"Ebs" : { "VolumeSize" : "50" , "VolumeType" : "io1" , "Iops" : "1500" }
} ],
"IamInstanceProfile" : "arn:aws:iam::481443282809:instance-profile/aws-elasticbeanstalk-ec2-role",
"ImageId" : "ami-5f726935",
"InstanceMonitoring" : "true",
"InstanceType" : "m4.large",
"KeyName" : { "Ref" : "KeyName" },
"SecurityGroups" : [ { "Ref" : "WebServerSecurityGroup" } ]
}
},
"ElasticLoadBalancer" : {
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties" : {
"AvailabilityZones" : {
"Fn::GetAZs" : ""
},
"CrossZone" : "true",
"Listeners" : [ {
"LoadBalancerPort" : "80",
"InstancePort" : "80",
"Protocol" : "HTTP"
} ],
"HealthCheck" : {
"Interval" : "15",
"HealthyThreshold" : "3",
"Target" : "HTTP:80/",
"Timeout" : "3",
"UnhealthyThreshold" : "2"
}
}
},
"WebServerScaleUpPolicy" : {
"Type" : "AWS::AutoScaling::ScalingPolicy",
"Properties" : {
"AdjustmentType" : "ChangeInCapacity",
"AutoScalingGroupName" : { "Ref" : "WebServerGroup" },
"Cooldown" : "60",
"PolicyType" : "SimpleScaling",
"ScalingAdjustment" : "1"
}
},
"WebServerScaleDownPolicy" : {
"Type" : "AWS::AutoScaling::ScalingPolicy",
"Properties" : {
"AdjustmentType" : "ChangeInCapacity",
"AutoScalingGroupName" : { "Ref" : "WebServerGroup" },
"Cooldown" : "60",
"PolicyType" : "SimpleScaling",
"ScalingAdjustment" : "-1"
}
},
"CPUAlarmHigh" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"ActionsEnabled" : "true",
"AlarmActions" : [ {
"Ref" : "WebServerScaleUpPolicy"
},
{
"Ref": "NotificationTopic"
} ],
"AlarmDescription" : "Scale-up if CPU > 75% for 10 minutes",
"AlarmName" : "CPUAlarmHigh",
"ComparisonOperator" : "GreaterThanThreshold",
"Dimensions" : [ {
"Name" : "AutoScalingGroupName",
"Value" : { "Ref": "WebServerGroup" }
} ],
"EvaluationPeriods" : "2",
"MetricName" : "CPUUtilization",
"Namespace" : "AWS/EC2",
"Statistic" : "Average",
"Period" : "300",
"Threshold" : "75"
}
},
"CPUAlarmLow": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"ActionsEnabled" : "true",
"AlarmActions" : [ {
"Ref" : "WebServerScaleDownPolicy"
} ],
"AlarmDescription" : "Scale-down if CPU < 50% for 10 minutes",
"AlarmName" : "CPUAlarmLow",
"ComparisonOperator" : "LessThanThreshold",
"Dimensions" : [ {
"Name" : "AutoScalingGroupName",
"Value" : { "Ref": "WebServerGroup" }
} ],
"EvaluationPeriods" : "2",
"MetricName" : "CPUUtilization",
"Namespace" : "AWS/EC2",
"Statistic" : "Average",
"Period" : "300",
"Threshold" : "50"
}
},
"ELBLatency" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties": {
"ActionsEnabled": "true",
"AlarmActions": [
{
"Ref": "NotificationTopic"
}
],
"AlarmDescription": "ELB Latency",
"ComparisonOperator": "GreaterThanThreshold",
"Dimensions": [
{
"Name": "LoadBalancerName",
"Value": { "Ref" : "ElasticLoadBalancer" }
}
],
"EvaluationPeriods": "1",
"InsufficientDataActions": [
{
"Ref": "NotificationTopic"
}
],
"MetricName": "Latency",
"Namespace": "AWS/ELB",
"Statistic": "Average",
"Period": "300",
"Threshold": "1"
}
},
"ELBSpilloverCount" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties": {
"ActionsEnabled": "true",
"AlarmActions": [
{
"Ref": "NotificationTopic"
}
],
"AlarmDescription": "ELB SpilloverCount",
"ComparisonOperator": "GreaterThanThreshold",
"Dimensions": [
{
"Name": "LoadBalancerName",
"Value": { "Ref" : "ElasticLoadBalancer" }
}
],
"EvaluationPeriods": "1",
"InsufficientDataActions": [
{
"Ref": "NotificationTopic"
}
],
"MetricName": "SpilloverCount",
"Namespace": "AWS/ELB",
"Statistic": "Maximum",
"Period": "300",
"Threshold": "10"
}
},
"ELBSurgeQueueLength" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties": {
"ActionsEnabled": "true",
"AlarmActions": [
{
"Ref": "NotificationTopic"
}
],
"AlarmDescription": "ELB SurgeQueueLength",
"ComparisonOperator": "GreaterThanThreshold",
"Dimensions": [
{
"Name": "LoadBalancerName",
"Value": { "Ref" : "ElasticLoadBalancer" }
}
],
"EvaluationPeriods": "1",
"InsufficientDataActions": [
{
"Ref": "NotificationTopic"
}
],
"MetricName": "SurgeQueueLength",
"Namespace": "AWS/ELB",
"Statistic": "Maximum",
"Period": "300",
"Threshold": "512"
}
},
"ELBRequestCount" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties": {
"ActionsEnabled": "true",
"AlarmActions": [
{
"Ref": "NotificationTopic"
}
],
"AlarmDescription": "ELB RequestCount",
"ComparisonOperator": "GreaterThanThreshold",
"Dimensions": [
{
"Name": "LoadBalancerName",
"Value": { "Ref" : "ElasticLoadBalancer" }
}
],
"EvaluationPeriods": "1",
"InsufficientDataActions": [
{
"Ref": "NotificationTopic"
}
],
"MetricName": "RequestCount",
"Namespace": "AWS/ELB",
"Statistic": "Sum",
"Period": "300",
"Threshold": "10000"
}
},
"ELBHealthyHostCount" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties": {
"ActionsEnabled": "true",
"AlarmActions": [
{
"Ref": "NotificationTopic"
}
],
"AlarmDescription": "ELB Healthy Host Count",
"ComparisonOperator": "LessThanThreshold",
"Dimensions": [
{
"Name": "LoadBalancerName",
"Value": { "Ref" : "ElasticLoadBalancer" }
}
],
"EvaluationPeriods": "1",
"InsufficientDataActions": [
{
"Ref": "NotificationTopic"
}
],
"MetricName": "HealthyHostCount",
"Namespace": "AWS/ELB",
"Statistic": "Average",
"Period": "300",
"Threshold": "1"
}
},
"ELBHTTPCode4XX" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties": {
"ActionsEnabled": "true",
"AlarmActions": [
{
"Ref": "NotificationTopic"
}
],
"AlarmDescription": "ELB HTTPCode_ELB_4XX",
"ComparisonOperator": "LessThanThreshold",
"Dimensions": [
{
"Name": "LoadBalancerName",
"Value": { "Ref" : "ElasticLoadBalancer" }
}
],
"EvaluationPeriods": "1",
"InsufficientDataActions": [
{
"Ref": "NotificationTopic"
}
],
"MetricName": "HTTPCode_ELB_4XX",
"Namespace": "AWS/ELB",
"Statistic": "Sum",
"Period": "300",
"Threshold": "100"
}
},
"ELBHTTPCode5XX" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties": {
"ActionsEnabled": "true",
"AlarmActions": [
{
"Ref": "NotificationTopic"
}
],
"AlarmDescription": "ELB HTTPCode_ELB_5XX",
"ComparisonOperator": "LessThanThreshold",
"Dimensions": [
{
"Name": "LoadBalancerName",
"Value": { "Ref" : "ElasticLoadBalancer" }
}
],
"EvaluationPeriods": "1",
"InsufficientDataActions": [
{
"Ref": "NotificationTopic"
}
],
"MetricName": "HTTPCode_ELB_5XX",
"Namespace": "AWS/ELB",
"Statistic": "Sum",
"Period": "300",
"Threshold": "100"
}
},
"CostAlarm": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"ActionsEnabled" : "true",
"AlarmActions": [{
"Ref" : "NotificationTopic"
}],
"AlarmDescription": "Cost tracking",
"AlarmName" : "CostAlarm",
"ComparisonOperator": "GreaterThanThreshold",
"Dimensions": [{
"Name": "Currency",
"Value" : "USD"
}],
"EvaluationPeriods" : "1",
"InsufficientDataActions": [{
"Ref" : "NotificationTopic"
}],
"MetricName": "EstimatedCharges",
"Namespace": "AWS/Billing",
"Statistic": "Maximum",
"Period": "21600",
"Threshold": "100"
}
}
}
}
I hope this info will be useful for you, and if you need any help feel free to use contact from on the main page.