Automating the operation of EC2 services

In this blog, I present a method by which we at Third Kind Games use AWS and associated APIs to manage and run our dedicated servers during game development; the aim of which being to allow all of us to launch our code in the cloud without the need for training or lengthy steps in order to get there.  It also removes the burden of having to worry about stopping instances at the right time and therefore incurring extra costs.


Why?

At the start of your project’s development; you may not have everything set up to utilise systems that automatically spin up cloud services, scaling etc… more likely you’ll be manually running servers, either hosting locally on your LAN or manually in the cloud.  Of course, you need to get to a stage where these things are happening automatically, but in the beginning, you’ll be doing things a bit more “hands-on”, so to speak.

To describe our first few steps, “in the beginning”, we’d have someone’s Client host the game or even have a Dedicated Server running on their machine whilst also running a Client so they could participate in games.  This is far from ideal – the real world use case is that a Dedicated Server is running in the cloud somewhere and all Clients connect to that or at the very least, having a dedicated PC run the Server.  With that in mind, my target was to be able to run our Dedicated Servers on AWS and have everyone who needed to play, be able to connect to that server.

The long hand (manual) method of running an exe requires a variety of logins and passwords, running remote desktop, syncing the correct build and then launching the server.  Again, in the beginning, I was manually doing all of this, however, I decided that it’d be interesting to see if I could automate this to a point where we could have anyone spin up Servers as and when they required, rather than having me on hand to do it.

What?

The things I wanted to achieve were:

  • Have fun!
  • Learn a bit about how AWS works under the hood
  • Reduce the number of, manual, steps required to launch our code in the cloud
  • Provide a way for our own staff to have easy access to the cloud and launch their own servers
  • Automate the process of stopping instances – These services cost money all the while they are running!

Given the aims of what I wanted to achieve, I set about looking into how I might automate those manual tasks I was already doing.  What I came across was Run Commands.

Enter Falken

This is Falken.  A simple console application I developed that does the following:

  • Start EC2 instances
  • Automatically schedules the stopping of EC2 instances
  • Can remotely sync the required build
  • Can remotely launch (and kill) our dedicated server

For the purposes of this blog, Falken isn’t the primary talking point.  It’s a C# application built upon the AWS APIs – this is just an example of what I did with them.  As you can see, there is no fancy GUI – what Falken does offer, however, is a way to manage AWS EC2 instances with a single command and no further training as to what happens underneath.  Of course, the above could be wrapped in a fancy GUI if desired.

First off!

There are a few different libraries you’ll need to pull in for the rest of the code to work, for your information, these are:

using Amazon;
using Amazon.EC2;
using Amazon.EC2.Model;
using Amazon.EC2.Util;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.SimpleSystemsManagement;
using Amazon.SimpleSystemsManagement.Model;

First thing I wanted to do was to be able to boot up AWS EC2 instances without having to go through the web interface.  For this, you’ll have to of setup and configured your instances in the first place.  Once you have that, it’s a simple case of grabbing the relevant instance ids and putting in the following code:

static List<string> s_idList = new List<string> { "i-1234567890abcdef0" }; // replace with  your actual id

static AmazonEC2Client m_ec2Client = null;
static AmazonSimpleSystemsManagementClient m_SSMClient = null;
static Instance m_instance = null;

public static void Main(string[] args)
{
    IAmazonS3 s3Client = new AmazonS3Client();
    m_ec2Client = new AmazonEC2Client();
    m_SSMClient = new AmazonSimpleSystemsManagementClient();

    StartInstancesRequest startRequests = new StartInstancesRequest(s_idList);
    m_ec2Client.StartInstances(startRequests);

    // ...
    // ...
    StopInstance();
}

Example of how you might boot up an AWS instance in C#

At the opposite end, of course, you’ll want to be able to stop an instance.  My very first version, or should I say, ver 0.1, started an instance on boot and stopped it on exit (as demonstrated above).

The C# code for stopping instances is super simple:

public static void StopInstance()
{
    StopInstancesRequest stopRequest = new StopInstancesRequest(s_idList);
    m_ec2Client.StopInstances(stopRequest);
}

In order to provide the end user (and myself; for debugging purposes) with information about their instances, you’ll also want to be able to query said instances.  This can be done as follows:

public static Instance QueryStatus(List<string> idList)
{
    var instanceDescribeRequest = new DescribeInstancesRequest { InstanceIds = idList };

    m_instance = m_ec2Client.DescribeInstances(instanceDescribeRequest).Reservations[0].Instances[0];

    return m_instance;
}

The returned instance object can provide things like Instance ID, Public Ip Address and more – very useful!

With this all working, I then expanded my investigations in the Run Command.

Run Command

So what is a “Run Command”?

‘Amazon EC2 Run Command provides a simple way of automating common administrative tasks’.  More specifically, for us, one of the things it allows you to do is run PowerShell Scripts; with which I knew I could likely accomplish everything I wanted.

Before this will work, you will need to ensure your AWS details/settings are setup correctly.  I won’t delve into the specifics of that here, however, more information can be found on the AWS docs:

What Is AWS Systems Manager? – AWS Systems Manager

AWS Systems Manager is a collection of capabilities for configuring and managing your managed instances at scale.

Assuming that is all setup correctly, onto the good stuff!

The rest of the work was figuring out how to execute a Run Command from code.  In C#, this is done as follows:

public static void ExecutePowerShellScript(List<string> script)
{
    Dictionary<string, List<string>> runCommand = new Dictionary<string, List<string>>();
    runCommand.Add("commands", script);

    string document = "AWS-RunPowerShellScript";
    SendCommandRequest commandRequest = new SendCommandRequest(document, s_idList);

    commandRequest.Parameters = runCommand;

    m_SSMClient.SendCommand(commandRequest);
}

Example of executing a PowerShell Script from C# to execute on your EC2 Instance

Falken is entirely based on executing blocks of PowerShell Scripts using the above function.

Scheduling AutoStops

AWS services cost money for as long as they are running.  Auto-stopping instances were key if I wanted to roll this out to a wider audience.  We wouldn’t want people accidentally leaving servers running after all!

Two things I built into Falken to facilitate this.  As soon as Falken spins up an EC2 instance, two PowerShell script commands are scheduled:

  1. The first being an arbitrary, “end of day” shutdown – in our case, I went with 6pm
  2. An auto shutdown, 1 hour after the launching of the instance – with an option to extend through the Falken interface.  One hour because (at the time of writing), a charge is incurred for one hour of use, regardless of if it is only used for two minutes.

Essentially what happens is that the PowerShell script will use the Windows scheduler on the target instance to execute the above code, triggering the stop command.

Closing remarks

That’s essentially it.

Using the above pieces of code, I was able to add extra functionality, such as remote Perforce synchronisation to required change lists, remotely running/killing software (in this case, our Dedicated Server) and more.

Using Falken, allows us to easily spin up Server instances on demand without requiring technical “know-how” on how to do it or be worried that something has accidentally been left running.

Not only is this kind of tool very useful whilst the various systems that can automatically handle this are not yet in place – it can be used for other things that may be needed during development that don’t necessarily need these heavyweight systems.

 

Leave a Reply