What Is CloudFormation and How To Use It

Posted By : Shubham Kamboj | 01-Sep-2020

Here we are creating an Auto-scaling with ELB then creating a SSL certificate for ELB and proving a Domain for ELB URL. Subsequently, you'll learn what is CloudFormation and how to use it.

 

About

  • Cloudformation is a programming language that is written in a JSON or YAML format which is called a template and it is a declaration of the AWS resources that make up a stack. In the template, we declare the AWS resources we want to create and configure.  Also, we have to make sure that the CloudFormation template body shouldn’t have any errors.
  • With the help of AWS CloudFormation we can automate every process in AWS.
  • AWS CloudFormation is a service that helps us to create and set up our Amazon Web Services resources so that we can spend less time managing those resources. By just one click we can set up the full structure without wasting our time.
  • AWS CloudFormation is a service that gives us an easy way to create a collection of related AWS resources and third party resources and provision them in an orderly and predictable fashion.
  • With the help of CloudFormation we can maintain and control over our AWS billing. Suppose If we have AWS resources that are not actively using or experimenting with, so we can use CloudFormation to temporarily tear down a stack when we don't need it. When we need it again, CloudFormation can easily rebuild it.
  • In the template body, we can define Resources, Parameters, etc. for eg:- 

 

    "Parameters": {

        "EnvironmentName": {

            "Description": "An environment name that will be prefixed to resource names",

            "Type": "String",

            "Default": "Production"

        },

        "AlternateDomainNames": {

            "Description": "CNAMEs (alternate domain names), if any, for the distribution. Example. test.codavel.com",

            "Type": "String",

            "Default": "abc.test.xvbn.com"

        }

   }

 

  • After that we can define mapping like if we want to map AMI’s Instance type whatever we want to map but that is not mandatory. Then we have to define Resources. In resources we provide the type like what we want to create VPC, EC2 Cloudfront etc.

"Resources": {

        "VPC": {

            "Type": "AWS::EC2::VPC",

            "Properties": {

                "CidrBlock": {

                    "Ref": "VpcCIDR"

                },

                "EnableDnsHostnames": true,

                "Tags": [

                    {

                        "Key": "Name",

                        "Value": {

                            "Ref": "EnvironmentName"

                        }

                    }

                ]

            }

        }

  • You can see in this template here we are using our parameter EnvironmentName. 
  • After completing the resource part we can define the Output as well like what output we want after completing the template but that is also not mandatory.
  • So let’s have a quick example of setting up an Auto-Scaling with CPU policy and also setup ELB with it. Attach SSL certificate for 443 port and setup domain in Route53.

        {

 

    "Parameters": {

 

        "AlternateDomainNames": {

 

            "Description": "CNAMEs (alternate domain names), if any, for the distribution. Example. test.xcvn.com",

 

            "Type": "String",

 

            "Default": "myy.test-elb.xcvn.com"

 

        },

 

        "EnvironmentName": {

 

            "Description": "An environment name that will be prefixed to resource names",

 

            "Type": "String",

 

            "Default": "Production"

 

        },

 

        "amiID": {

 

            "Description": "Enter a Valid Ami ID",

 

            "Type": "String",

 

            "Default": "ami-0393a51ed48dd392f"

 

        },

 

        "VpcCIDR": {

 

            "Description": "Please enter the IP range (CIDR notation) for this VPC",

 

            "Type": "String",

 

            "Default": "10.0.0.0/16"

 

        },

 

        "PublicSubnet1CIDR": {

 

            "Description": "Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone",

 

            "Type": "String",

 

            "Default": "10.0.0.0/24"

 

        },

 

        "PublicSubnet2CIDR": {

 

            "Description": "Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone",

 

            "Type": "String",

 

            "Default": "10.0.1.0/24"

 

        },

 

        "PrivateSubnet1CIDR": {

 

            "Description": "Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone",

 

            "Type": "String",

 

            "Default": "10.0.2.0/24"

 

        },

 

        "PrivateSubnet2CIDR": {

 

            "Description": "Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone",

 

            "Type": "String",

 

            "Default": "10.0.3.0/24"

 

        }

 

    },

 

    "Resources": {

 

        "VPC": {

 

            "Type": "AWS::EC2::VPC",

 

            "Properties": {

 

                "CidrBlock": {

 

                    "Ref": "VpcCIDR"

 

                },

 

                "EnableDnsHostnames": true,

 

                "Tags": [

 

                    {

 

                        "Key": "Name",

 

                        "Value": {

 

                            "Ref": "EnvironmentName"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "InternetGateway": {

 

            "Type": "AWS::EC2::InternetGateway",

 

            "Properties": {

 

                "Tags": [

 

                    {

 

                        "Key": "Name",

 

                        "Value": {

 

                            "Ref": "EnvironmentName"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "InternetGatewayAttachment": {

 

            "Type": "AWS::EC2::VPCGatewayAttachment",

 

            "Properties": {

 

                "InternetGatewayId": {

 

                    "Ref": "InternetGateway"

 

                },

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                }

 

            }

 

        },

 

        "PublicSubnet1": {

 

            "Type": "AWS::EC2::Subnet",

 

            "Properties": {

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                },

 

                "AvailabilityZone": {

 

                    "Fn::Select": [

 

                        0,

 

                        {

 

                            "Fn::GetAZs": ""

 

                        }

 

                    ]

 

                },

 

                "CidrBlock": {

 

                    "Ref": "PublicSubnet1CIDR"

 

                },

 

                "MapPublicIpOnLaunch": true,

 

                "Tags": [

 

                    {

 

                        "Key": "Name",

 

                        "Value": {

 

                            "Fn::Sub": "${EnvironmentName} Public Subnet (AZ1)"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "PublicSubnet2": {

 

            "Type": "AWS::EC2::Subnet",

 

            "Properties": {

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                },

 

                "AvailabilityZone": {

 

                    "Fn::Select": [

 

                        1,

 

                        {

 

                            "Fn::GetAZs": ""

 

                        }

 

                    ]

 

                },

 

                "CidrBlock": {

 

                    "Ref": "PublicSubnet2CIDR"

 

                },

 

                "MapPublicIpOnLaunch": true,

 

                "Tags": [

 

                    {

 

                        "Key": "Name",

 

                        "Value": {

 

                            "Fn::Sub": "${EnvironmentName} Public Subnet (AZ2)"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "PrivateSubnet1": {

 

            "Type": "AWS::EC2::Subnet",

 

            "Properties": {

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                },

 

                "AvailabilityZone": {

 

                    "Fn::Select": [

 

                        0,

 

                        {

 

                            "Fn::GetAZs": ""

 

                        }

 

                    ]

 

                },

 

                "CidrBlock": {

 

                    "Ref": "PrivateSubnet1CIDR"

 

                },

 

                "MapPublicIpOnLaunch": false,

 

                "Tags": [

 

                    {

 

                        "Key": "Name",

 

                        "Value": {

 

                            "Fn::Sub": "${EnvironmentName} Private Subnet (AZ1)"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "PrivateSubnet2": {

 

            "Type": "AWS::EC2::Subnet",

 

            "Properties": {

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                },

 

                "AvailabilityZone": {

 

                    "Fn::Select": [

 

                        1,

 

                        {

 

                            "Fn::GetAZs": ""

 

                        }

 

                    ]

 

                },

 

                "CidrBlock": {

 

                    "Ref": "PrivateSubnet2CIDR"

 

                },

 

                "MapPublicIpOnLaunch": false,

 

                "Tags": [

 

                    {

 

                        "Key": "Name",

 

                        "Value": {

 

                            "Fn::Sub": "${EnvironmentName} Private Subnet (AZ2)"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "NatGateway1EIP": {

 

            "Type": "AWS::EC2::EIP",

 

            "DependsOn": "InternetGatewayAttachment",

 

            "Properties": {

 

                "Domain": "VPC"

 

            }

 

        },

 

        "NatGateway2EIP": {

 

            "Type": "AWS::EC2::EIP",

 

            "DependsOn": "InternetGatewayAttachment",

 

            "Properties": {

 

                "Domain": "VPC"

 

            }

 

        },

 

        "NatGateway1": {

 

            "Type": "AWS::EC2::NatGateway",

 

            "Properties": {

 

                "AllocationId": {

 

                    "Fn::GetAtt": [

 

                        "NatGateway1EIP",

 

                        "AllocationId"

 

                    ]

 

                },

 

                "SubnetId": {

 

                    "Ref": "PublicSubnet1"

 

                }

 

            }

 

        },

 

        "NatGateway2": {

 

            "Type": "AWS::EC2::NatGateway",

 

            "Properties": {

 

                "AllocationId": {

 

                    "Fn::GetAtt": [

 

                        "NatGateway2EIP",

 

                        "AllocationId"

 

                    ]

 

                },

 

                "SubnetId": {

 

                    "Ref": "PublicSubnet2"

 

                }

 

            }

 

        },

 

        "PublicRouteTable": {

 

            "Type": "AWS::EC2::RouteTable",

 

            "Properties": {

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                },

 

                "Tags": [

 

                    {

 

                        "Key": "Name",

 

                        "Value": {

 

                            "Fn::Sub": "${EnvironmentName} Public Routes"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "DefaultPublicRoute": {

 

            "Type": "AWS::EC2::Route",

 

            "DependsOn": "InternetGatewayAttachment",

 

            "Properties": {

 

                "RouteTableId": {

 

                    "Ref": "PublicRouteTable"

 

                },

 

                "DestinationCidrBlock": "0.0.0.0/0",

 

                "GatewayId": {

 

                    "Ref": "InternetGateway"

 

                }

 

            }

 

        },

 

        "PublicSubnet1RouteTableAssociation": {

 

            "Type": "AWS::EC2::SubnetRouteTableAssociation",

 

            "Properties": {

 

                "RouteTableId": {

 

                    "Ref": "PublicRouteTable"

 

                },

 

                "SubnetId": {

 

                    "Ref": "PublicSubnet1"

 

                }

 

            }

 

        },

 

        "PublicSubnet2RouteTableAssociation": {

 

            "Type": "AWS::EC2::SubnetRouteTableAssociation",

 

            "Properties": {

 

                "RouteTableId": {

 

                    "Ref": "PublicRouteTable"

 

                },

 

                "SubnetId": {

 

                    "Ref": "PublicSubnet2"

 

                }

 

            }

 

        },

 

        "PrivateRouteTable1": {

 

            "Type": "AWS::EC2::RouteTable",

 

            "Properties": {

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                },

 

                "Tags": [

 

                    {

 

                        "Key": "Name",

 

                        "Value": {

 

                            "Fn::Sub": "${EnvironmentName} Private Routes (AZ1)"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "DefaultPrivateRoute1": {

 

            "Type": "AWS::EC2::Route",

 

            "Properties": {

 

                "RouteTableId": {

 

                    "Ref": "PrivateRouteTable1"

 

                },

 

                "DestinationCidrBlock": "0.0.0.0/0",

 

                "NatGatewayId": {

 

                    "Ref": "NatGateway1"

 

                }

 

            }

 

        },

 

        "PrivateSubnet1RouteTableAssociation": {

 

            "Type": "AWS::EC2::SubnetRouteTableAssociation",

 

            "Properties": {

 

                "RouteTableId": {

 

                    "Ref": "PrivateRouteTable1"

 

                },

 

                "SubnetId": {

 

                    "Ref": "PrivateSubnet1"

 

                }

 

            }

 

        },

 

        "PrivateRouteTable2": {

 

            "Type": "AWS::EC2::RouteTable",

 

            "Properties": {

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                },

 

                "Tags": [

 

                    {

 

                        "Key": "Name",

 

                        "Value": {

 

                            "Fn::Sub": "${EnvironmentName} Private Routes (AZ2)"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "DefaultPrivateRoute2": {

 

            "Type": "AWS::EC2::Route",

 

            "Properties": {

 

                "RouteTableId": {

 

                    "Ref": "PrivateRouteTable2"

 

                },

 

                "DestinationCidrBlock": "0.0.0.0/0",

 

                "NatGatewayId": {

 

                    "Ref": "NatGateway2"

 

                }

 

            }

 

        },

 

        "PrivateSubnet2RouteTableAssociation": {

 

            "Type": "AWS::EC2::SubnetRouteTableAssociation",

 

            "Properties": {

 

                "RouteTableId": {

 

                    "Ref": "PrivateRouteTable2"

 

                },

 

                "SubnetId": {

 

                    "Ref": "PrivateSubnet2"

 

                }

 

            }

 

        },

 

        "AppLaunchConfig": {

 

            "Type": "AWS::AutoScaling::LaunchConfiguration",

 

            "Properties": {

 

                "AssociatePublicIpAddress": false,

 

                "EbsOptimized": false,

 

                "ImageId": {

 

                  "Ref": "amiID"

 

                },

 

                "InstanceType": "t3.small",

 

                "UserData": {

 

                    "Fn::Base64": {

 

                        "Fn::Sub": "#!/bin/bash\n s3fs hardata /home/ubuntu/work -o passwd_file=/etc/passwd-s3fs\n har-extractor /home/ubuntu/work/git.codavel.com.har --output /home/ubuntu/extract/\n"

 

                    }

 

                },




 

                "SecurityGroups": [

 

                    {

 

                        "Ref": "InstanceSecGroup"

 

                    }

 

                ],

 

                "BlockDeviceMappings": [

 

                    {

 

                        "DeviceName": "/dev/sda1",

 

                        "Ebs": {

 

                            "VolumeType": "io1",

 

                            "Iops": "100",

 

                            "DeleteOnTermination": "true",

 

                            "VolumeSize": "100"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

        "WebLoadBalancer": {

 

            "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",

 

            "Properties": {

 

                "Name": "ELBforWebApp",

 

                "Subnets": [

 

                    {

 

                        "Ref": "PublicSubnet2"

 

                    },

 

                    {

 

                        "Ref": "PublicSubnet1"

 

                    }

 

                ],

 

                "SecurityGroups": [

 

                    {

 

                        "Ref": "LBSecGroup"

 

                    }

 

                ]

 

            }

 

        },

 

        "DeployAppASG": {

 

            "Type": "AWS::AutoScaling::AutoScalingGroup",

 

            "Properties": {

 

                "AutoScalingGroupName": "AutoScalingGroupPrivate",

 

                "LaunchConfigurationName": {

 

                    "Ref": "AppLaunchConfig"

 

                },

 

                "VPCZoneIdentifier": [

 

                    {

 

                        "Ref": "PrivateSubnet2"

 

                    },

 

                    {

 

                        "Ref": "PrivateSubnet1"

 

                    }

 

                ],

 

                "MinSize": 1,

 

                "MaxSize": 8,

 

                "TargetGroupARNs": [

 

                    {

 

                        "Ref": "WebLBTarget"

 

                    }

 

                ]

 

            },

 

            "UpdatePolicy": {

 

                "AutoScalingReplacingUpdate": {

 

                    "WillReplace": true

 

                }

 

            }

 

        },

 

        "AppScaleUpPolicy": {

 

            "Type": "AWS::AutoScaling::ScalingPolicy",

 

            "Properties": {

 

                "AdjustmentType": "ChangeInCapacity",

 

                "AutoScalingGroupName": {

 

                    "Ref": "DeployAppASG"

 

                },

 

                "Cooldown": "60",

 

                "ScalingAdjustment": 1

 

            }

 

        },

 

        "AppScaleDownPolicy": {

 

            "Type": "AWS::AutoScaling::ScalingPolicy",

 

            "Properties": {

 

                "AdjustmentType": "ChangeInCapacity",

 

                "AutoScalingGroupName": {

 

                    "Ref": "DeployAppASG"

 

                },

 

                "Cooldown": "300",

 

                "ScalingAdjustment": -1

 

            }

 

        },

 

        "CPUAlarmHigh": {

 

            "Type": "AWS::CloudWatch::Alarm",

 

            "Properties": {

 

                "AlarmDescription": "Scale-up if CPU > 70% for 5 minutes",

 

                "MetricName": "CPUUtilization",

 

                "Namespace": "AWS/EC2",

 

                "Statistic": "Average",

 

                "Period": 300,

 

                "EvaluationPeriods": 2,

 

                "Threshold": 70,

 

                "AlarmActions": [

 

                    {

 

                        "Ref": "AppScaleUpPolicy"

 

                    }

 

                ],

 

                "Dimensions": [

 

                    {

 

                        "Name": "AutoScalingGroupName",

 

                        "Value": {

 

                            "Ref": "DeployAppASG"

 

                        }

 

                    }

 

                ],

 

                "ComparisonOperator": "GreaterThanThreshold"

 

            }

 

        },

 

        "CPUAlarmLow": {

 

            "Type": "AWS::CloudWatch::Alarm",

 

            "Properties": {

 

                "AlarmDescription": "Scale-down if CPU < 40% for 5 minutes",

 

                "MetricName": "CPUUtilization",

 

                "Namespace": "AWS/EC2",

 

                "Statistic": "Average",

 

                "Period": 300,

 

                "EvaluationPeriods": 2,

 

                "Threshold": 40,

 

                "AlarmActions": [

 

                    {

 

                        "Ref": "AppScaleDownPolicy"

 

                    }

 

                ],

 

                "Dimensions": [

 

                    {

 

                        "Name": "AutoScalingGroupName",

 

                        "Value": {

 

                            "Ref": "DeployAppASG"

 

                        }

 

                    }

 

                ],

 

                "ComparisonOperator": "LessThanThreshold"

 

            }

 

        },

 

        "LBSecGroup": {

 

            "Type": "AWS::EC2::SecurityGroup",

 

            "Properties": {

 

                "GroupDescription": "Allow HTTP & HTTPS for lb",

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                },

 

                "GroupName": "LBSecurityGroup",

 

                "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"

 

                    }

 

                ],

 

                "SecurityGroupEgress": [

 

                    {

 

                        "IpProtocol": "tcp",

 

                        "FromPort": 80,

 

                        "ToPort": 80,

 

                        "CidrIp": "0.0.0.0/0"

 

                    }

 

                ]

 

            }

 

        },

 

        "InstanceSecGroup": {

 

            "Type": "AWS::EC2::SecurityGroup",

 

            "Properties": {

 

                "GroupDescription": "SecurityGroupServer",

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                },

 

                "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"

 

                    },

 

                    {

 

                        "IpProtocol": "tcp",

 

                        "FromPort": 22,

 

                        "ToPort": 22,

 

                        "CidrIp": "0.0.0.0/32"

 

                    }

 

                ],

 

                "Tags": [

 

                    {

 

                        "Key": "name",

 

                        "Value": "Security Group"

 

                    }

 

                ]

 

            }

 

        },

 

        "WebLBTarget": {

 

            "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",

 

            "Properties": {

 

                "HealthCheckEnabled": true,

 

                "HealthCheckIntervalSeconds": 60,

 

                "HealthCheckPath": "/",

 

                "HealthCheckPort": 80,

 

                "HealthCheckProtocol": "HTTP",

 

                "HealthCheckTimeoutSeconds": 4,

 

                "HealthyThresholdCount": 2,

 

                "Name": "ELBTargetGroup",

 

                "Port": 80,

 

                "Protocol": "HTTP",

 

                "VpcId": {

 

                    "Ref": "VPC"

 

                }

 

            }

 

        },

 

        "WebLBListener": {

 

            "Type": "AWS::ElasticLoadBalancingV2::Listener",

 

            "Properties": {

 

                "LoadBalancerArn": {

 

                    "Ref": "WebLoadBalancer"

 

                },

 

                "Port": 443,

 

                "Certificates" : [

 

                {

 

                    "CertificateArn": {

 

                      "Ref": "certificatefordns"

 

                    }

 

                }],

 

                "Protocol": "HTTPS",

 

                "SslPolicy": "ELBSecurityPolicy-FS-1-2-Res-2019-08",

 

                "DefaultActions": [

 

                    {

 

                        "Type": "forward",

 

                        "TargetGroupArn": {

 

                            "Ref": "WebLBTarget"

 

                        }

 

                    }

 

                ]

 

            }

 

        },

 

 "certificatefordns":{

 

  "Type" : "AWS::CertificateManager::Certificate",

 

  "Properties" : {

 

      "DomainName" : "*.test-elb.xcvn.com",

 

      "ValidationMethod" : "DNS",

 

      "DomainValidationOptions": [

 

                {

 

                    "DomainName": "*.test-elb.xcvn.com",

 

                    "HostedZoneId": "Z01724793QXGY7AW"

 

                }]

 

    }

 

},

 

        "DNS": {

 

            "Type": "AWS::Route53::RecordSetGroup",

 

            "Properties": {

 

                "HostedZoneId": "Z01724793QXGY7AW",

 

                "RecordSets": [

 

                    {

 

                        "Name": {

 

                            "Ref": "AlternateDomainNames"

 

                        },

 

                        "Type": "A",

 

                        "AliasTarget": {

 

                            "HostedZoneId": {

 

                                "Fn::GetAtt": [

 

                                    "WebLoadBalancer",

 

                                    "CanonicalHostedZoneID"

 

                                ]

 

                            },

 

                            "DNSName": {

 

                                "Fn::GetAtt": [

 

                                    "WebLoadBalancer",

 

                                    "DNSName"

 

                                ]

 

                            }

 

                        }

 

                    }

 

                ]

 

            }

 

        }

 

    },




 

    "Outputs": {

 

        "WebLoadBalancer": {

 

            "Description": "The DNS path of Load Balancer",

 

            "Value": {

 

                "Fn::Join": [

 

                    "",

 

                    [

 

                        "http://",

 

                        {

 

                            "Fn::GetAtt": [

 

                                "WebLoadBalancer",

 

                                "DNSName"

 

                            ]

 

                        }

 

                    ]

 

                ]

 

            }

 

        }

 

    }

 

}


And finally we get an URL i.e https://myy.test-elb.xcvn.com

 

Learn more about our cloud app development services here. For project related queries, reach us out at [email protected].

About Author

Author Image
Shubham Kamboj

Shubham is a RHCE Certified Engineer who is having 2 years of experience in Linux and Cloud. He is a quick and active learner.

Request for Proposal

Name is required

Comment is required

Sending message..