Streamlining AWS Infrastructure Setup with CloudFormation: A Step-by-Step Guide
Manish Kumar
Solutions Engineer (Infrastructure and Architecture) @ Sumo Logic | AWS Developer and Solution Architect
Are you tired of manually configuring your AWS infrastructure every time you start a new project? Discover how you can automate the setup process using CloudFormation templates. In this article, I'll walk you through creating a YAML template for setting up a Virtual Private Cloud (VPC), public subnets, and security groups. Streamline your AWS workflow and save time with this efficient approach.
Introduction:
Setting up AWS infrastructure can be time-consuming, especially when you have to repeat the process for multiple projects. Fortunately, AWS CloudFormation offers a solution to automate this process using infrastructure as code. In this article, I'll demonstrate how to create a CloudFormation YAML template for provisioning a VPC, public subnets, Internet Gateway, Route Table, NACLs, and security groups.
Here is the cloudformation template for creating a custom VPC, with two public subnets, an Internet Gateway, a public route table, an NACL, a security group for EC2, and a security group for the Application Load Balancer.
AWSTemplateFormatVersion: '2010-09-09'
Description: Create a VPC with two public subnets with an internet gateway, a public route table, and a security group
Parameters:
DeploymentBucket:
Description: Name of the deployment bucket
Type: String
Default: YOUR_BUCKET_NAME
VpcCidr:
Type: String
Default: 10.0.0.0/16
Description: CIDR block for VPC
PublicSubnet1Cidr:
Type: String
Default: 10.0.0.0/24
Description: CIDR block for public subnet 1
PublicSubnet2Cidr:
Type: String
Default: 10.0.1.0/24
Description: CIDR block for public subnet 2
EnvironmentName:
Description: Name of the environment
Type: String
Default: dev
AllowedValues:
- dev
- prod
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCidr
EnableDnsHostnames: 'true'
EnableDnsSupport: 'true'
InstanceTenancy: default
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-VPC
- Key: Environment
Value: !Ref EnvironmentName
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref PublicSubnet1Cidr
AvailabilityZone: !Select [ 0, !GetAZs ]
MapPublicIpOnLaunch: 'true'
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PublicSubnet1
- Key: Environment
Value: !Ref EnvironmentName
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref PublicSubnet2Cidr
AvailabilityZone: !Select [ 1, !GetAZs ]
MapPublicIpOnLaunch: 'true'
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PublicSubnet2
- Key: Environment
Value: !Ref EnvironmentName
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-InternetGateway
- Key: Environment
Value: !Ref EnvironmentName
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PublicRouteTable
- Key: Environment
Value: !Ref EnvironmentName
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
PublicNetworkAcl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PublicNetworkAcl
- Key: Environment
Value: !Ref EnvironmentName
InboundHTTPPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: '0.0.0.0/0'
PortRange:
From: '80'
To: '80'
InboundHTTPSPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: '101'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: '0.0.0.0/0'
PortRange:
From: '443'
To: '443'
InboundEmphemeralPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: '0.0.0.0/0'
PortRange:
From: '1024'
To: '65535'
OutboundHTTPPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: '0.0.0.0/0'
PortRange:
From: '80'
To: '80'
OutboundHTTPSPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: '101'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: '0.0.0.0/0'
PortRange:
From: '443'
To: '443'
OutboundEmphemeralPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: '0.0.0.0/0'
PortRange:
From: '1024'
To: '65535'
PublicSubnet1NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet1
NetworkAclId: !Ref PublicNetworkAcl
PublicSubnet2NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet2
NetworkAclId: !Ref PublicNetworkAcl
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${EnvironmentName}-ALBSecurityGroup
GroupDescription: Allow HTTP inbound traffic from anywhere.
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
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-ALBSecurityGroup
- Key: Environment
Value: !Ref EnvironmentName
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${EnvironmentName}-EC2SecurityGroup
GroupDescription: Allow HTTP and HTTPS inbound and outbound traffic from anywhere.
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
SourceSecurityGroupId: !Ref ALBSecurityGroup
- IpProtocol: tcp
FromPort: '443'
ToPort: '443'
SourceSecurityGroupId: !Ref ALBSecurityGroup
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-EC2SecurityGroup
- Key: Environment
Value: !Ref EnvironmentName
Outputs:
AccountId:
Description: AWS Account ID
Value: !Ref AWS::AccountId
RegionName:
Description: AWS Region Name
Value: !Ref AWS::Region
StackId:
Description: Current Stack ID
Value: !Ref AWS::StackId
StackName:
Description: Current Stack Name
Value: !Ref AWS::StackName
Environment:
Description: Environment name
Value: !Ref EnvironmentName
Export:
Name: !Sub ${EnvironmentName}-environment-name
DeploymentBucket:
Description: Deployment bucket
Value: !Ref DeploymentBucket
Export:
Name: !Sub ${EnvironmentName}-deployment-bucket
VpcId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub ${EnvironmentName}-vpc-id
PublicSubnet1Id:
Description: Public subnet 1 ID
Value: !Ref PublicSubnet1
Export:
Name: !Sub ${EnvironmentName}-public-subnet1-id
PublicSubnet2Id:
Description: Public subnet 2 ID
Value: !Ref PublicSubnet2
Export:
Name: !Sub ${EnvironmentName}-public-subnet2-id
EC2SecurityGroupId:
Description: EC2 security group ID
Value: !Ref EC2SecurityGroup
Export:
Name: !Sub ${EnvironmentName}-ec2-security-group-id
ALBSecurityGroupId:
Description: ALB security group ID
Value: !Ref ALBSecurityGroup
Export:
Name: !Sub ${EnvironmentName}-alb-security-group-id
Step 1: Create a private S3 bucket for the deployment
领英推荐
aws s3api create-bucket --bucket <YOUR_BUCKET_NAME> \
--region us-east-1
Step 2: Upload the template file to the s3
aws s3 cp /path/to/template/file/vpc.yaml \ s3://YOUR_BUCKET_NAME/templates/vpc.yaml
Step 3: Create a vpc stack
aws cloudformation create-stack --stack-name vpc --template-url https://YOUR_BUCKET_NAME.s3.amazonaws.com/templates/vpc.yaml \
--parameters \ ParameterKey=DeploymentBucket,ParameterValue=YOUR_BUCKET_NAME \
--region us-east-1
Step 4: Check the status of the stack
aws cloudformation describe-stacks --stack-name vpc \
--query "Stacks[0].StackStatus" --output text --region us-east-1
Step 4: Check all the outputs of the stack (When the stack is created successfully)
aws cloudformation describe-stacks --stack-name vpc \
--query "Stacks[0].Outputs" --output table --region us-east-1
Senior DevOps Engineer at Zyxware Technologies
9 个月Cloudformation templates is something powerful to automate the whole infrastructure kick start process