How-To
Simplifying the Amazon EC2 Instance Customization Process
AWS expert Brien Posey demonstrates how to automate EC2 instance customization by using PowerShell to simplify post-deployment tasks.
Although Amazon makes it relatively easy to fine-tune the instance configuration process, there is often quite a bit of work that must be done after a new instance has been created. Such tasks are usually specific to the OS that is being installed onto the instance. For example, you may need to set environment variables, map a network drive, or perform similar tasks. However, Amazon provides a mechanism that can simplify this post deployment configuration work.
EC2 makes it possible to automatically run a script within an instance. You can configure the script as a part of the instance creation process, or you can do it later on. Additionally, the technique that I am going to show you works for both Linux and Windows instances, although I am going to be focusing on Windows in this article.
The technique used to supply the script to the instance is identical for both Windows and Linux instances. If you are creating a brand-new instance, simply scroll to the bottom of the Launch an Instance screen and then expand the Advanced Details section. The last option presented within this section is something called User Data. This is where your script goes. As you can see in Figure 1, you can either type (or paste) your script into the text box or you can upload a script file. In either case, AWS will encode the script using Base64, so you will need to select the check box at the bottom of the screen if your script has already been Base64 encoded.
It's just as easy to modify an existing instance so that a script will run when the instance is booted. In order to do so however, you will need to shutdown the instance.
With the instance in the stopped state, select the instance and then select the Instance Settings > Edit User Data commands from the Action menu. This will cause the console to display a screen that allows you to supply a script or to modify an existing script. Once again, you can type the code manually, paste the script into a text box, or upload a script file. You can see what this looks like in Figure 2.
As previously mentioned, everything that I have discussed so far works regardless of whether an instance is running Windows or Linux. With that said, I want to show you a few things that you will need to know if you are planning on running scripts on Windows instances.
The first thing that you need to know is that EC2 requires you to tell the instance what type of script you are running. If you look back at the figure above, you will notice that the first line of code is <powershell>. This indicates to EC2 that the script contains PowerShell code.
Although it is not shown in the figure, EC2 also requires you to tell the instance where the PowerShell code contained within the user data ends. As such, the last line of code within your user data should be </powershell>.
One of the challenges that you may encounter when using User Data to automatically run a script is that there isn't typically going to be any sort of visual confirmation that the script has actually executed. After all, the script launches and terminates as a part of the instance's boot process, and therefore usually completes before you log in.
More importantly, the script does not run under a user context. As I was writing this article, I wrote a PowerShell that contained code designed to force the PowerShell session to remain open. When I logged into the instance, I was able to use Task Manager to confirm that a PowerShell session was indeed running on the machine, but I was unable to directly access that session.
So how can you verify that the User Data script is actually running and doing what it is supposed to do? The way that I solved this problem was to construct a script that wrote an event to the Windows Application log. Here is the code that I used within my script:
$Source = "EC2UserDataScript"
If (-Not (Get-EventLog -LogName Application -Source $Source -ErrorAction SilentlyContinue)) { New-EventLog -LogName Application -Source $Source }
# Write an event to the Windows Event Log
Write-EventLog -LogName Application -Source $Source -EventID 1001 -EntryType Information -Message "User data script ran successfully at $(Get-Date)"
The first line of code creates a variable called $Source. I set the source to EC2UserDataScript. This makes it possible to track log entries related to the User Data script.
The second line of code checks to make sure that the Application log exists. If for whatever reason the log is missing, then the script will create it.
The last line of code creates an event within the Application log confirming that the User Data script has been executed. You can see what this event looks like in Figure 3.
About the Author
Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.