Welcome to Day 74 of the “100 Days of DevOps with PowerShell”! For background on our goals in this series, see Announcing the “100 Days of Devops with PowerShell” Series here at SCC.
When we’ve been deploying new instances in the previous articles, the default has been to create the instances in what is called EC2 Classic, which is the original AWS IaaS envronment. A number of years ago AWS introduced Amazon Virtual Private Cloud (VPC) which allows you to create logically separate networks within the AWS cloud. The major benefit of VPC is that it allows you define your network infrastructure with far more granular control than you can with EC2 classic. Running instances in VPC as opposed to EC2 allows the following benefits:
- Assign static private IP addresses to your instances that persist across starts and stops
- Assign multiple IP addresses to your instances
- Define network interfaces, and attach one or more network interfaces to your instances
- Change security group membership for your instances while they’re running
- Control the outbound traffic from your instances (egress filtering) in addition to controlling the inbound traffic to them (ingress filtering)
- Add an additional layer of access control to your instances in the form of network access control lists (ACL)
One advantage of these benefits is that it allows you architect your network to meet your exact needs, and it is therefore possible to construct a VPC that closely represents your production environment. The ability to provision a network infrastructure through automation falls directly into the realm of DevOps. In more traditional data center environments creating network infrastructure including firewall rules, gateways and routers would be the responsibility of the network team and their inevitable delays. With a VPC the whole environment can be provisioned and configured with PowerShell and AWS.
Sidebar: It is worth noting here that the examples in this article are perhaps not the AWS recommended best practice for the deployment of a VPC, along with preconfigured instances. The recommended way is to use CloudFormation templates, which are declarative scripts (similar to PowerShell DSC scripts) in JSON format that describe how a VPC should be deployed and configured. We may revisit AWS CloudFormation templates in a future article, but the information contained here tries to provide an understanding on how a VPC can be configured and deployed at a PowerShell level. A well written PowerShell script is equally as affective as the equivalent CloudFormation template. You will find some examples of CloudFormation templates here.
in the example below we are looking to deploy an environment that would be a fairly typical of a web application on the Internet: a public facing web server in a subnet with the required ports open to the Internet. In turn the public subnet would communicate with a SQL server on the internal private network. A diagram of which is shown below:
Deploying a VPC with a public subnet an a private subnet
In the example below we are looking to accomplish the following with the script:
- Create a VPC with a IP subnet (Cidr block of 10.0.0.0/16 – which is the maximum allowed number of a IP addresses for a VPC). We have specified the region here, though it could use the region specified in your AWS defaults as described in Day 29.
- Randomly pick an availability zone. Availability zones are separate physical data center locations within a region and here we are randomly picking one of the four to host the the public and private subnets. It’s worth noting that you can have multiple subnets in multiple availability zones across a single VPC.
- Create and tag the public subnet giving it the subnet range of 10.0.1.0/24
- Create and tag the private subnet giving it the subnet range of 10.0.2.0/24
- Create an Internet gateway. An Internet gateway is required to provide Internet access to the public subnet and this is assigned to the VPC
- Create a route table allowing all traffic (“0.0.0.0/0”) to the Internet.
$Tag = New-Object amazon.EC2.Model.Tag
$Tag.Key = $Key
$Tag.Value = $value
New-EC2Tag -ResourceId $resourceId -Tag $Tag | Out-Null
#Create the subnets and Cidrblock for the VPC
$cidrBlock = '10.0.0.0/16'
$privateSubnetCidr = '10.0.1.0/24'
$publicSubnetCidr = '10.0.2.0/24'
#Create the VPC
$VPC = New-EC2Vpc -CidrBlock $cidrBlock -Region 'us-east-1'
#Choose the availability zone
$i = Get-Random -Minimum 0 -Maximum 3
$zone = Get-EC2AvailabilityZone -Region 'us-east-1'
$availabilityZone = $zone[$i].ZoneName
#Create the public subnet
$publicSubnet = New-EC2Subnet -VpcId $VPC.VPCId -CidrBlock $publicSubnetCidr -AvailabilityZone $availabilityZone
#Tag the subnet
Add-EC2Tag -key Name -value Public-Dev-01 -resourceId $publicSubnet.ResourceID
#Create the private subnet
$privateSubnet = New-EC2Subnet -VpcId $VPC.VPCId -CidrBlock $privateSubnetCidr -AvailabilityZone $availabilityZone
#Tag the subnet
Add-EC2Tag -key Name -value Private-Dev-01 -resourceId $privateSubnet.ResourceID
#Creating the internet gateway
$InternetGateway = New-EC2InternetGateway
Add-EC2InternetGateway -InternetGatewayId $InternetGateway.InternetGatewayID -VpcId $VPC.vpcID
#create a route table and add the public subnet
$routeTable = New-EC2RouteTable -VpcId $VPC.vpdID
New-EC2Route -RouteTableId $routeTable.routeTableID -DestinationCidrBlock '0.0.0.0/0' -GatewayId $InternetGateway.InternetGatewayID
Register-EC2RouteTable -RouteTableId $routeTable.routeTableID -SubnetId $publicSubnet.subnetId
We have created an environment not dissimilar to many web applications, in that everybody can access the web application in the public subnet but the database is protected in a private subnet. However, what we have not provided here is a how we provide the access to the public subnet and at the same time secure the private subnet. In the next article we will look at using network ACLs to secure the subnets and security groups for the instances. Please remember this distinction because it’s an important one: network ACLs = subnets and security groups = instances. More on that in the next article!
To see the previous installments in this series, visit “100 Days of DevOps with PowerShell”.