Hi folks!
In the previous article, we have discussed about Ansible as an AWS EC2 Instance provisioning tool. With this article, we will be covering a lot of concepts to launch an EC2 instance in a Custom VPC. We will be using AWS CloudFormation - IaaC (Infrastructure as a Code) service in AWS.
CloudFormation uses a JSON/YAML format file to provision AWS Infrastructure. These files are called templates and the infrastructure which come up as a consequence of template run is called stack. So, we need to upload a template to let AWS CloudFormation create a stack.
In the Part1, we wrote a very simple stack with Resources section which is the only mandatory section of CloudFormation templates. But here, we will be writing a standard CloudFormation Template.
AWS Infra Requirement: Create a Dev Env comprising of a network having 3 public subnets and appropriate route configurations. Provision a Linux instance in one of the subnet having access via SSH and configure a running web server over the same instance.
To fulfill the above requirements, lets understand the scenario first with respect to AWS. We will break this into AWS Resources required.
R1. A Custom VPC can fulfill the network requirement.
R2. An InternetGateway must be attached to the VPC.
R3. The route tables associated with the public subnet must have a route to the Internet Gateway.
R4. The region is not specified in the requirement. So, we will try to make the template as immutable as possible such that lesser changes has to be made while creating stack in some other region. This is a very critical requirement.
R5. SSH access can be provided configuring Security Group.
R6. Webserver configuration is possible with UserData bootstrapping scripts/shell commands.
R7. Requirements does not specify the Linux OS and the type of Instance, in which case, we will go with default Amazon Linux. For Instance type, we try to provide flexibility to the Developer Team.
Till now, we have some basic idea about the environment. Some requirements are not clearly mentioned and it happens in real time also. Lets start writing the template.
1. There are two top-level objects in every template.
a. "AWSTemplateFormatVersion", which has only a single valid value as "2010-09-09" .
b. "Description", which appears in SpecifyParameters page of CreateStack wizard.
2. To fulfill R4 for EC2 instance type and R1 for Private IP address range inside VPC subnets, we will be using Parameters section to have user input.
Note: Do not get confused with my logical name "ClassB" for 10.XXX.0.0/16 CIDR. Feel free to use any logical name like ClassA or ClassC, etc.
3. Note that, AMI for every region has a unique ID. Its better to gather all the AMI Ids and create a Mappings Section. It provides ease of launching an EC2 instance in any region without any issues. One more mapping is used to converge the instance size to actual instance type as present in AWS.
4. Now, its time for the mandatory section of the template. Yes, we will be getting over to Resources Section. For every resource, there are three mandates to define i.e. Logical Name, Type and Properties.
We have to launch a VPC first. Then, for Internet Connection, going for an InternetGateway(igw). A VPCGatewayAttachment for connecting VPC to igw. Then, configure 3 subnets as SubnetA, SubnetB and SubnetC. Notice the attribute MapPublicIpOnLaunch to true, so that public ip get automatically allocated to instances present in the subnet. VPCRouteTable and InternetRoute are required for R3. Notice the dependency of VPCAttachmentGateway. Every Subnet must have a route table association with main RouteTable.
5. Security Group with port 80 and port 22 (ONLY ALLOW TRUSTED IPs, this is tutorial use case - 0.0.0.0/0) accessible via Internet.
6. At last, specify the EC2Instance resource. Feel free to visit AWS CloudFormation Docs for FindInMap instrinsic function. It returns the value corresponding to keys in a two level map of Mappings Section.
e.g. ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMALINUX] is returning the final value of AMALINUX key for the selected AWS::Region from the RegionMap.
Note: !Ref is used a lot in the template. Actually, its a very helpful intrinsic function which returns the specified parameter or resource.
7. In the same Resource, we have defined the UserData for WebServer Configuration with !Sub intrinsic function in the EC2Instance.
8. We have also configured an extras Outputs section. To share information between stacks Export is used in Outputs section. However, the purpose here is primarily to gather the details of AWS Infrastructure provisioned by the template. It has many advantages, in case of requirement change or requirement extensions.
Now the template is ready to be uploaded into the CloudFormation. In the first part of series, we have used AWS CLI for cloudformation. Here, I will go through the AWS Console.
1. Open the AWS Management -> Services -> (Management and Governance) -> CloudFormation.
2. I have selected the redesigned CloudFormation console, AWS is improving upon. Hit CreateStack.
3. Then upload Template, provide the Stack Name in next step.
4. Hit Next and then Create Stack at the bottom of Review Page. Note the default settings for Stack Creation which says that, RollbackonFailure is Enabled and TerminationProtection is Disabled.
5. Check the events and resources section and refresh till the Stack creation is taking place.
I suppose that older look is much better so, getting back to Previous Console.
When CREATE_COMPLETE is reflected, we can check for the EC2 instance.
Also check the working webserver by copying IP/DNS of instance in the browser.
See on your own, how the stack architecture looks like inside the CloudFormationDesigner - An alternate to template writing in CloudFormation.
And last but not the least, the advantage of AWS CloudFormation is to delete the complete stack and all the allocated resources just by clicking one option of DELETE_STACK in the Actions.
I hope you like this article. Feel free to reference each resource with attributes present in documentation. There are a lot of things, which you can try on your own. For example, try the same template to launch in any region. I suppose it might fail. And you will get the only error, that's why this template is not completely immutable. Find own your own. And rectify by creating that one thing, and launch the same template and it will work fine.
Okay! Let me tell you. The thing is KeyName in EC2Instance Resource section. If you want this template to work for you create a KeyPair as myCFNsi in that region. Also its a drawback with CloudFormation with this template. However, we can overcome it with Custom Resources.
The template is present on my Github.
This is how CloudFormation can be used to play with AWS Resources for Infrastructure Provisioning. In the next article, we will touch upon some more use cases with AWS and Ansible.
0 comments: