Last Update: Sep 04, 2024 | Published: Dec 02, 2014
In this article, I’ll show you how to provision a Windows Server 2012 R2 virtual machine (EC2 instance) with a static private IP address in a Virtual Private Cloud (VPC), all with the help of Windows PowerShell.
In a previous article, Provision Windows Server in Amazon Web Services using PowerShell, I walked through provisioning Windows Server EC2-Classic instances in Amazon Web Services (AWS), but there are two major limitations to this approach. The first is that when stopped, classic instances lose their private internal IP address, meaning that they can’t be used for workloads, such as Active Directory domain controllers. Secondly, classic instances always use shared resources and can’t be configured on single-tenant hardware.
The other type of instance is Virtual Private Cloud (VPC). An AWS VPC is the equivalent of an Azure virtual network (VNET), and any instances provisioned in VPCs automatically acquire static internal IP addresses. The only real difference between provisioning EC2-Classic and VPC instances is that for the latter, you must specify a subnet associated with a VPC, otherwise the provisioning process is identical.
Before continuing, you’ll need to be familiar with the process of provisioning an EC2-Classic instance as described in Provision Windows Server in Amazon Web Services using PowerShell on the Petri IT Knowledgebase. The article includes information about setting up and configuring the AWS Tools for Windows PowerShell on your PC, how to get an image name for the –ImageId parameter of the New-EC2Instance cmdlet, and creating a key pair, which is required to retrieve the administrator account password.
Depending on when your AWS account was created, you may have a default VPC in which you can launch instances. Unlike the default VPC, custom, non-default VPCs don’t have connectivity to the Internet by default, but this can be achieved with a little extra configuration. To determine if you have a default VPC:
Check the output for subnets associated with your default VPC, and make a note of the SubnetId in the region you’d like to use.
If you have a default VPC and are happy to use the private address range assigned to it, then you can skip the remainder of this article and run the code below to launch a new instance. All you need to do is replace subnet-915ab0f4 with the subnet ID you want to use.
A security group exists for the default VPC, but it doesn't permit inbound RDP traffic, so we'll need to add a rule to the group that permits inbound traffic from any IP address on TCP port 3389:
$ipPermissions = New-Object Amazon.EC2.Model.IpPermission –Property @{IpProtocol = “tcp”; FromPort = “3389”; ToPort = “3389”; IpRanges = $cidrBlocks} Grant-EC2SecurityGroupIngress -GroupName “default” -IpPermissions @($ipPermissions)
Check in the AWS management console that the status checks for the new instance have completed, and then connect using RDP.
You will need to create a new, non-default VPC if your AWS subscription doesn’t have a default VPC. You’ll also need to create a new non-default VPC if you want to use an address space different from the one that’s configured for the default VPC. To create a non-default VPC, run the following PowerShell cmdlet, replacing 10.0.0.0/16 with the private address block that you’d like to assign to the VPC. Make a note of the VpcId in the output as we’ll need it later.
$vpcId = $newvpc.VpcId
The next cmdlet is optional, but to assign instances with an external DNS hostname, we need to enable that feature for the new VPC:
To check if the new VPC is ready to use, type get-ec2vpc and press ENTER. Once the VPC is available, the State field will be set to available. Now we need to create an Internet gateway and attach it to the new VPC.
Create a New Subnet
For the purposes of this demonstration, let's create a subnet that uses the whole address space assigned to the VPC.
$subnetid = $newsubnetid.subnetid write-host $subnetid
Make a note of the Subnet ID in the command’s output. To check progress, type Get-EC2Subnet -SubnetIds $subnetid and press ENTER. Once the subnet is available, the State field will be set to available.
The default route table for the new subnet won’t contain a route to the Internet, so we need to create a custom route table with a route to the Internet.
$routetable = $newroutetable.routetableid New-EC2Route –routetableid $routetable –DestinationCidrBlock 0.0.0.0/0 –GatewayId $inetgate Register-EC2RouteTable -RouteTableId $routetable -SubnetId $subnetid
And finally, make sure there’s a public IP address available for when we launch the new instance:
Create a Security Group
A security group is needed to configure remote access to the VPC. In this example, I'll give all remote IP addresses (0.0.0.0/0) access on RDP port 3389.
$cidrBlocks = New-Object 'collections.generic.list[string]' $cidrBlocks.add("0.0.0.0/0") $ipPermissions = New-Object Amazon.EC2.Model.IpPermission –Property @{IpProtocol = “tcp”; FromPort = “3389”; ToPort = “3389”; IpRanges = $cidrBlocks} Grant-EC2SecurityGroupIngress -GroupId $groupid -IpPermissions @($ipPermissions)
Now we’re ready to launch a new VPC instance running Windows Server 2012 R2. The values for ImageId and KeyName have already been determined as per the instructions for launching an EC2-Classic instance in the article link above.
To get information about the status of the new instance, use the code below, replacing r-ee901de1 with the reservation ID from the output of the New-EC2Instance cmdlet.
$reservation.add("r-ee901de1") $filter_reservation = New-Object Amazon.EC2.Model.Filter -Property @{Name = "reservation-id"; Values = $reservation} (Get-EC2Instance -Filter $filter_reservation).Instances
Refer to the aforementioned article on the Petri IT Knowledgebase to learn how to retrieve the administrator password for the instance and connect using Remote Desktop. When you stop and restart the instance, notice that it retains the private IP address that it was initially assigned.