Now that we’re done configuring our environment, we’ll jump right in and get started by creating an instance. An EC2 instance is, simply, a server running in the cloud. With a few quick clicks, we will have our first server up and running.
In this chapter, we will learn to create new instances and connect them. Then we will discuss how to start, stop, and terminate instances. We will learn various ways to access metadata and add custom metadata tags. In the exercises at the end of the chapter, we will build a PowerShell script to automate the launch process and customize the configuration of an instance.
Creating Instances
Let’s get started by creating a new instance. In this section we’ll launch a Windows Server 2019 instance. I’ll begin by using AWS Management Console. The console will give us a good overview of all the options available. Then, we will see how to do the same thing with a single line using PowerShell.
Launching an Instance with the Web Console
For this first exercise – launching an instance with the Web Console – we are going to include step-by-step instructions with figures. The Web Console changes often so don’t be surprised if the console screens look a bit different from the following figures.
On the instance details page, ensure that the instance type is set to t2 micro and click the button Next: Configure Instance Details (see Figure 3-4). The instance type is the virtual hardware we want to use. There are numerous combinations of processors, memory, network, and so on.
Skip the page labeled as “Step 3: Configure Instance Details” by clicking Next: Add Storage. Skip the page labeled as “Step 4: Configure Instance Details” by clicking Next: Add Tags. We will review all of these advanced options in future chapters.
We just launched our first server in the cloud. Click the View Instances button, and we will be taken to the EC2 Instances page. We should see our new instance in the list with a state of pending.
It will take about 10 minutes for the instance to launch. While we are waiting, let’s discuss how we can do the same thing in PowerShell using a single line of code.
Launching an Instance with PowerShell
In PowerShell, we use the New-EC2Instance command to create instances. This is a really rich command that can do everything the wizard can do. For now we will focus on the basics of the New-EC2Instance command.
An AMI is uniquely identified by an image ID value. The image IDs are different in each region. The ImageId parameter specifies which AMI we want to launch; therefore, the examples will use Get-EC2ImageByName to look up the correct ID in our currently defined default region. (We will discuss the Get-EC2ImageByName command in Chapter 7).
MinCount and MaxCount specify how many instances to launch. See the sidebar on reservations for details.
KeyName is the name of the key pair we created in the last chapter. It is used to encrypt the administrator password. Technically, this parameter is optional, but without it we will not be able to retrieve the administrator password.
InstanceType describes the hardware we wish to use, and again we will use the t2.micro.
Reservations
Let’s spend a minute talking about the MinCount and MaxCount parameters. New-EC2Instance always creates instances in batches called reservations. We are going to be using the reservation object in many of the scripts later in this chapter.
A reservation is a batch of instances launched at the same time. Even if we only want a single instance, we create a batch of size one. Every account has a limit on the number of runnable instances for each instance type per region. Some instance types support many dozens of launches by default, while some very powerful instance types may only allow one or two launches. Even Amazon has a finite number of instances available.
AWS will try to launch the number of instances specified in MaxCount. If it cannot launch the MaxCount due to account or regional capacity limits, Amazon will launch the largest possible number above MinCount. If the MinCount is more than Amazon EC2 will permit, no instances are launched and there will be a capacity or limit error.
By the way, although the attribute is called RunningInstance, it also contains instances that are in a stopped state.
Notice that we did not specify the security group (i.e., firewall). Unlike the Web Console wizard, the API will use the default group if we don’t specify one. There are numerous additional parameters to the New-EC2Instance command. These correspond to the options we skipped in the wizard. Don’t worry. We will talk about them all in later chapters.
Windows instances take about 10 minutes to launch regardless of how we create them. The instance(s) we launched with PowerShell are probably still launching, but the one we launched with the AWS Management Console is probably ready; let’s go check it now.
Checking the Instance Console Screenshot
Returning to the Web Console, let’s check on that instance we launched earlier. To view the running instances, select the services drop-down in the AWS Web Console. Either find and locate EC2 under the Compute group or use the find tool using EC2 as our search string and select EC2. When the EC2 dashboard console loads, select the Running Instances link.
We will now check on the instance using the Get Instance Screenshot tool. This tool will take a snapshot of our instances display output in its current state and show it to us. This can be a very useful for diagnosing instances that are not responding or are failing to launch. If a bug check occurred or service failed to start, we can usually find details by reviewing the instance screenshot.
Select Close on the bottom right corner of instance screenshot window to return back to the Instance Web Console.
Checking the Instance Console System Log
When an AWS provided image is launched, it performs some configurations and customizations at boot to prepare it for use. A summary log of these activities can be seen using the Get System Log tool.
Select Close on the bottom right corner of System Log window to return back to the Instance Web Console.
Connecting to an Instance
Great! Now we know how to create and connect to an instance using the Web Console.
Note
If the RDP connection fails, we may need to add a rule to the security group to allow Remote Desktop Protocol (RDP) access from our IP. Follow the following instructions. We will discuss security groups in detail in Chapter 6.
- 1.
From the EC2 Web Console selections on the left under Network & Security, choose Security Groups.
- 2.
Select the group named Default and choose the Inbound tab and select the Edit button.
- 3.
In the Edit inbound rules window, choose the Add Rule button.
- 4.
Under Type, select the drop-down and choose RDP.
- 5.
Under Source, select the drop-down and choose My IP.
- 6.
Finally, click the Save button.
We can, of course, retrieve the password using PowerShell. The PowerShell command is Get-EC2PasswordData command. Get-EC2PasswordData takes an instance ID and the path to the private key and returns the password.
Note that the instance ID will be different from these examples. Each instance has a different ID. We can get the ID from the instances page of the AWS Management Console.
The preceding code will return an error if the password is not available yet. Remember, it takes about 10 minutes to launch a new instance. We will discuss how to test for password availability in the first exercise at the end of this chapter.
Now that we know how to launch and connect to an instance, let’s talk about starting, stopping, rebooting, and terminating instances.
Managing the Instance Life Cycle
Now that we have a few instances created, we will want to manage them. We can Start, Stop, Reboot, and Terminate (i.e., Delete) an instance by right-clicking it in the AWS Management Console and highlighting Instance State. Figure 3-15 shows the context menu.
Note
Stop - Hibernate is a new AWS feature that allows instances to be stopped in a powered down hibernation state instead of using a full shutdown. This can be helpful for customers who need scale their servers up and down quickly. As of this writing, Windows Servers are not yet supported and will not be selectable. The latest information and configuration requirements can be found at https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Hibernate.html .
The equivalent PowerShell commands are pretty simple. They each have a parameter called Instance, which is the ID of the instance we want to start, stop, and so on.
Listing Instances and Metadata
Note that Get-EC2Instance returns a reservation object. Remember that New-EC2Instance always creates a batch called a reservation. When we call Get-EC2Instance, AWS returns the reservation that includes its collection of instances.
This will give us a great deal of information about the instance including storage, network, and other details. We will use this information throughout the rest of the book. Before we get into that, let’s look at one other way to access some instance metadata using the metadata URL.
Using the Metadata URL
Get-EC2Instance is a great way to get information about an instance, but there is another way. The metadata URL returns much of the same information as Get-EC2Instance, but always returns information about the current instance.
The metadata URL is a web service that runs under each instance that returns metadata about the current instance. The URL is http://169.254.169.254/latest/meta-data .
Note the metadata service is only available from executing queries and scripts directly on the EC2 instance. We cannot use the API from a machine outside AWS, nor can we use the metadata service to get information about another instance.
A common use of the metadata URL is to discover the ID of the current instance and then use it to make calls to the AWS API. This way, we can write a generic script that will run on any EC2 instance.
Using User Data
One of the options we skipped over in the section on launching new instances was user data. User data is similar to metadata, but it allows us to include any custom data we want. The user data is available via a web service call, just like the metadata in the prior section.
One common use of user data is to include information needed to bootstrap the instance, or configure it after launch. We will do this in the second exercise at the end of this chapter.
To include user data, simply type whatever we want into the text box at the bottom of the third page under Advanced Details of the Launch Instance wizard (see Figure 3-18).
Similar to the metadata URL, this URL will always return the user data for the running instance. Each instance has its own unique user data.
Note the @'...'@ syntax, this is just a convenient way to include a multiline string in PowerShell.
We can change the user data after launching an instance, but the instance must be in a stopped state. Let’s stop our instance and try replacing the user data with well-formed XML.
From the EC2 Instances Web Console, right-click our instance and highlight Instance State then select Stop. After a couple minutes, the instance should be in the stopped state.
There is one other really cool feature of user data. We can include scripts that we want to run when the instance boots the first time. We can include Windows command shell scripts inside <script>...</script> or PowerShell scripts inside <powershell>...</powershell> tags. We will do this in the second exercise at the end of this chapter.
Working with Tags
Every object in AWS supports tags. Tags are a great way to keep track of all our instances and other objects. A tag is simply a key/value pair used to describe the object. For example, we can use a tag to record the name of an instance or which department owns it. We can use tags to record any additional information we need.
Creating tags is a bit harder. A tag is a .Net object so there is no PowerShell command to create an EC2 tag. Instead, we use the generic new-object command to create a .Net object of type Amazon.EC2.Model.Tag. Once we have the new tag object, we can use the New-EC2Tag PowerShell command to set the Key and Value properties.
When there is only a few instances, it is relatively simple to keep track of everything. Once we launch ten or more, it quickly gets very confusing.
One trick is to tag everything. Each instance has at least one volume and one network interface attached. Whenever a new instance is created, tag the instance and all of the attached resources.
Notice that Start-Sleep in the previous command. When we create a new instance, the command may return before all of the resources have been allocated. Therefore, we may find that a volume or network interface is null if we move too quickly.
To get around this, we have the script sleep for a few seconds. Then we query AWS for an updated copy of the instance metadata. This gives AWS enough time to allocate resources.
Working with Filters
In the previous section, we used the Where-Object command to filter a collection and find a specific tag. This same method could be applied to other objects – for example, to find all of the instances owned by a given department.
AWS provides a better solution: filters. A filter allows us to specify search criteria to be executed on the server side. This way we don’t have to download metadata from hundreds of instances and sort through them when we are only interested in a handful.
The Get methods usually include a filter parameter. The filter allows us to return only those resources with a specific value for a given attribute. For example, if we want to return a list of instances that are currently in a running state, we can use the instance-state-code filter. A value of 16 indicates an instance is running.
The filter names and values are not always intuitive. They use the AWS CLI syntax, which may be foreign to a user of the PowerShell API. Included is a list of filters and values with each Get command in Appendix C.
When we filter on tags, we use the format tag, followed by the key name. Remember that keys and their values are case sensitive. When creating keys manually using the Web Console, be consistent.
Exercise 3.1: Waiting For an Instance to Launch
For this exercise let’s assume that we often receive requests to create new instances from developers in our organization and those developers don’t have access to the AWS Web Console. As AWS adoption has grown, this has become very time-consuming. It would be nice to script the build in PowerShell.
We can create a new instance and get the password with a few lines of code, and it would be great if a script could wait for the build to finish and then automatically e-mail the password to the requestor. But, how do we know when the server is finished?
One way to determine whether the server is finished is to poll the instance to check if the password is available. We can call the Get-EC2PasswordData command to check if a password exists. This provides a convenient way to check for password availability.
Let’s start by creating a new method, called GetPasswordWhenReady . This method checks once every minute until the password is ready and then returns it. The method takes three parameters. The first is the ID of the instance to wait on. The second is the location of the private key used to decrypt the password. The third is the number of minutes to wait for the password, after which the script will give up.
Exercise 3.2: Bootstrapping With User Data
At this point we know how to launch and manage instances. Before we close this chapter, let’s spend a minute talking about how we can customize instances. We could, of course, just log in and configure each instance manually, but the cloud is all about automation and standardization.
If we script the configuration of our server, the results will be more consistent and reproducible.
Amazon thought of this, and it included the capability to run configuration scripts when a server boots. In this exercise, we are going to configure our instance for remote administration. We will use a PowerShell script in the user data to complete the configuration.
Amazon includes the EC2Config or EC2Launch service agent (depending on the OS version) in every Windows AMI they provide. The first time an instance boots, this agent service will check the user data for <script>...</script> or <powershell>...</powershell> tags and then execute them at the command prompt or PowerShell prompt, respectively. By default, scripts are run only the first time an instance boots, but we can configure it to run every time the instance starts (we will look at this in Chapter 7).
We talked in the last chapter about specifying default credentials and a default region. We will use a server role to provide credentials, but remember that we still need to set the default region and we can use PowerShell in the user data to accomplish this. When a new AWS instance launches, it will be ready to run scripts without further configuration.
On our next instance launch, let’s make a few more changes with a user data script to enable PowerShell remoting for administration and Windows Management Instrumentation (WMI) for monitoring and management.
The complete script is available with the accompanying code in a file called Bootstrap.ps1. For information on downloading the sample code, see Chapter 1. We could use the “As file” option under advanced details in the Configure Instance page of the Launch Instance Wizard to open this file, but we are going to generate the user data and launch the instance using only PowerShell.
User data is a really powerful option. We can use this to make just about any customizations we need without ever logging into a server. As our adoption of AWS matures, we will likely begin to use features such as Auto Scaling, which deploys instances automatically in response to load. Obviously, it is critical that we can auto configure these instances at launch. (We will talk more about Auto Scaling in Chapter 8).
Summary
In this chapter, we got a good introduction to instances. We learned to launch and verify instances using both Web Console and PowerShell. We learned how to start, stop, and terminate instances. We also learned how to discover information about our instance using both PowerShell and the metadata URL. Next, we learned how to include custom data with user data and tags. Then we discussed how to use filters to find specific instances. In the examples we created a complete script to manage launching instances. Then we learned how to customize our instance at launch using user data.
In the next chapter, we will discuss storage including volumes and snapshots. Volumes are the disks that are attached to an instance, and snapshots are point-in-time backups of our volumes.