🗒️ Content
- AWS CloudFormation 101
- One key pair f
- Hands-on Lab: Separately Manage Network and Server Stacks by Cross Stacks
1. AWS CloudFormation 101
1.1. Infrastructure as Code (IaC)
Treating infrastructure in the same way as developers treat code is one of the most fundamental principles of DevOps.
Infrastructure as code (IaC) means provisioning, configuring and managing your infrastructure resources using code and templates.
1.2. AWS CloudFormation
AWS CloudFormation is a service speeding up cloud provisioning with infrastructure as code
AWS resources and infrastructure architecture are modeled and described in CloudFormation templates written in JSON or YAML (recommended) formatted text file. After that CloudFormation takes care of provisioning and configuring those resources for you.
The CloudFormation workflow for creating stacks as the below diagram
CloudFormation Workflow (source: https://aws.amazon.com/cloudformation/)
2. CloudFormation Templates Structure
- Resource (mandatory): declare the AWS resources
- Parameters (optional): input custom values to template each time creating/updating a stack, using with
!Ref <parameter>
- Mapping (optional): map a key to a specific value, using with
!FindInMap [ <map_name>, <top_key>, <second_key> ]
- Condition (optional): control the creation of resources or outputs based on a condition
- Output (optional): return output values of stack
- Cross-stack: separate templates and refer values from different stacks, using with
Export
from one stack and!ImportValue <export_name>
from other stacks
3. Hands-on Lab: Separately Manage Network and Server Stacks by Cross Stacks
Assume that we are developing a simple web application with the following architecture
- One VPC, one public subnet, one EC2 instance
- One security group opening in port 80 (for HTTP from anywhere)
Separating our infrastructure into 2 templates may help us manage them easier.
3.1. LabNetworkStack
The content of lab_network_cfn.yml
:
Description: This template manages network components
Parameters:
ApplicationName:
Description: An application name that is prefixed to resource names
Type: String
Default: lab
VpcCidr:
Description: The IP range (CIDR notation) for VPC in form x.x.x.x/16-28
Type: String
AllowedPattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$"
Default: 10.192.0.0/16
PublicSubnetCidr:
Description: The IP range (CIDR notation) for public subnet in form x.x.x.x/16-28
Type: String
AllowedPattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$"
Default: 10.192.10.0/24
Resources:
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCidr
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub '${ApplicationName}-vpc'
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: !Ref PublicSubnetCidr
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub '${ApplicationName}-public-subnet'
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub '${ApplicationName}-igw'
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref Vpc
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
Tags:
- Key: Name
Value: !Sub '${ApplicationName}-rtb'
DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet
Outputs:
VpcId:
Description: The VPC ID of lab application
Value: !Ref Vpc
Export:
Name: !Sub '${AWS::StackName}-VpcId'
SubnetId:
Description: The Subnet ID of lab application
Value: !Ref PublicSubnet
Export:
Name: !Sub '${AWS::StackName}-PublicSubnetId'
The template can be deployed with AWS CLI
aws s3 cp lab_network_cfn.yml s3://<your_bucket>
aws cloudformation create-stack --stack-name LabNetworkStack --template-url https://<your_bucket>.s3.<your_region>.amazonaws.com/lab_network_cfn.yml
3.2. LabServerStack
The content of lab_server_cfn.yml
:
Description: This template manages servers components
Parameters:
ApplicationName:
Description: An application name that is prefixed to resource names
Type: String
Default: lab
Landscape:
Type: String
Default: develop
AllowedValues:
- develop
- production
NetworkStackName:
Description: The name of Network CloudFormation stack
Type: String
Default: LabNetworkStack
Mappings:
RegionMap:
ap-southeast-1:
AMI: ami-02ee763250491e04a
ap-southeast-2:
AMI: ami-0e040c48614ad1327
Conditions:
IsProduction: !Equals [ !Ref Landscape, production]
Resources:
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub 'Security group for ${ApplicationName} instances'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
VpcId: !ImportValue
'Fn::Sub': '${NetworkStackName}-VpcId'
Tags:
- Key: Name
Value: !Sub '${ApplicationName}-srg'
Ec2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [ RegionMap, !Ref 'AWS::Region', AMI ]
InstanceType: !If [ IsProduction, t2.small, t2.micro ]
KeyName: your_key_name
SubnetId: !ImportValue
'Fn::Sub': '${NetworkStackName}-PublicSubnetId'
SecurityGroupIds:
- !Ref SecurityGroup
BlockDeviceMappings:
- DeviceName: "/dev/sda1"
Ebs:
VolumeSize: 12
VolumeType: gp2
Encrypted: true
UserData:
"Fn::Base64":
!Sub |
#!/bin/bash
apt update
apt install apache2 -y
Tags:
- Key: Name
Value: !Sub '${ApplicationName}-ec2'
Outputs:
InstanceIp:
Description: The IP address of instance
Value: !GetAtt Ec2Instance.PublicIp
The template can be deployed with AWS CLI
aws s3 cp lab_server_cfn.yml s3://<your_bucket>
aws cloudformation create-stack --stack-name LabServerStack --template-url https://<your_bucket>.s3.<your_region>.amazonaws.com/lab_server_cfn.yml
Confirmation
- Confirm the status of stacks are all
CREATE_COMPLETE
- Confirm the default Ubuntu Apache web page
http://your_server_ip
3.3. Clean resources
The stacks can be deleted by consoles or AWS CLI in the following order
aws cloudformation delete-stack --stack-name LabServerStack
aws cloudformation delete-stack --stack-name LabNetworkStack
Top comments (0)