Amazon’s EC2 platform has a very in-depth console which allows you to do a lot, but what if you want to automate some of the processes or handling servers? I’ve been working with EC2 a lot recently and automating server starting/stopping based on parameters of the system we use here at MediaSkunkworks and thought I’d share some knowledge.
Getting Started
You’ll want to grab yourself the AWSSDK; this can be from the installer at http://aws.amazon.com/sdkfornet/ or as a NuGet package in your VS project. If you use the installer, be sure to add a reference to the AWSSDK.dll file (should be at C:\Program Files (x86)\AWS SDK for .NET\bin\AWSSDK.dll) on a 64-bit OS.
Set-up
In the Amazon namespace there is a class called AWSClientFactory which is a factory class (kind of obvious I suppose!) used to create “clients” for the various services Amazon offers. In this case we’ll be using the method CreateAmazonEC2Client. You will need your access key and secret access key to call this function, they can be found on the security credentials page in your account – if you’ve not created them yet, they can be created here too.
To get an instance of the client, the method is called as follows:
AmazonEC2 client = AWSClientFactory.CreateAmazonEC2Client( "YOUR_ACCESS_KEY", "YOUR_SECRET_ACCESS_KEY", new AmazonEC2Config() { ServiceURL = "https://eu-west-1.ec2.amazonaws.com/", UseSecureStringForAwsSecretKey = false } );
You’ll notice I’ve passed in an instance of AmazonEC2Config, with a ServiceURL. This makes future calls using this client easier if you’re working on one “zone” in Amazon – also note for Europe it’s just eu-west-1, no a, b or c at the end – this applies to all zones. As for the UseSecureStringForAwsSecretKey, this is due to .NET restrictions in trust levels, ideally this should be true but for a non distributed app (i.e. one you run on a private server no one can access) this is fine.
The client variable will now have an instance of the AmazonEC2 object which has a whole host of helper methods for various things you can do with the EC2 platform. (The complete list of methods in this class can be seen at the API reference.)
Retrieving a List of Running Instances
The method you’ll need here is DescribeInstances which requires an instance of DescribeInstancesRequest (the AWSSDK is extremely OO heavy as you’ll see below!). There are lots of ways to use this method, but I’ll go for a simple one – get a list of instances running with the specified AMI ID (also knows as Image ID).
DescribeInstancesResponse response = client.DescribeInstances( new DescribeInstancesRequest() { Filter = new List<Filter>() { new Filter() { Name = "image-id", Value = new List<String>() { "ami-223c1a1b" } } } } );
See what I mean by extreme OO? Not only does DescribeInstances take a DescribeInstancesRequest, but in turn that takes a List of type Filter who’s values are a List of type String! The good side to this is you can easily build up filters and each filter can have multiple values (so instead of just one AMI-ID as in the above example, you could specify several and they’ll all get returned). Conversley you can pass in a DescribeInstanceRequest with no parameters and you’ll get every instance available back. There are a lot of filters you can use, the complete list can be seen here.
So now you’ve got a list of instances matching the AMI ID ami-223c1a1b right? Well, kind of. What you actually have is an instance of DescribeInstancesResponse. This class has a few functions such as showing the XML response etc. what you want though is the public property DescribeInstancesResult which then has a public property Reservation which is of type List<Reservation>, more OO! You’d be forgiven for thinking this is a list of instances as a result of your query: what it actually represents is a list of groups of instances. Why is this? Well from what I can gather, this is because you can request servers to run in bulk with various parameters, each request to run servers is a reservation [happy to be corrected here].
What next then? Well each Reservation object has a property called RunningInstance which is actually not a single instance but of type List<RunningInstance>. If you’re like me, you probably don’t care about this huge level of abstraction as you simply wanted an actual list of running instances that match your request; so you’ll probably want code something like this:
List<RunningInstance>() instances = new List<RunningInstance>(); foreach(var instList in response.DescribeInstancesResult.Reservation) instances.AddRange(instList.RunningInstance);
Et voila! A nice simple list of RunningInstance objects you can do whatever you want with (RunningInstance again is part of the AWS SDK, documentation can be seen here.)
Running New Instances
Running new instances, like getting a list of instances uses the same OO approach and returns the same type of OO response (in this case a RunInstancesResult). An example of this can be seen below:
RunInstancesResponse response = client.RunInstances( new RunInstancesRequest() { ImageId = "ami-223c1a1b", InstanceType = "t1.micro", SecurityGroup = new List<string>() { "security-group-name" }, MinCount = 1, MaxCount = 10, KeyName = "quick-start-1" } );
These aren’t all the options available, complete list is here. But it does show you the power you have to control EC2. Majority of the variables are self-explanatory; it is worth nothin the SecurityGroup list should be populated by the name of the security group, not the ID (the name is what you see in the EC2 web interface) – you can however use SecurityGroupId instead. The MinCount/MaxCount properties are very useful, MinCount means “run at least this many servers, if you can’t, run none”; MaxCount means “run no more than this many servers, but you can run less provided you run at least MinCount”.
What I do with the response is use response.RunInstancesResult.Reservation.RunningInstance.Count which lets me know how many instances EC2 actually spawned (note how as this is a request, Reservation here is not a list, it’s a single object.)
What’s Next?
There is so much more you can do, this really does barely scratch the surface. What I hope it does do though is give you a quick start guide for using the SDK without having to delve too much into the API docs or working out how they like you to call their code.
For those of you who know the AWSSDK and are wondering why I chose the “inline” approach rather than using the .With…() methods – it’s because I prefer this way of doing it and I find it easier to maintain than to daisy-chain lots of .With…() ‘s together.
I’m really impressed along with your writing talents and also with the structure in your weblog. Is this a paid subject or did you customize it yourself? Either way keep up the excellent high quality writing, it is rare to peer a great blog like this one nowadays..
Hey, thanks for that, much appreciated 🙂
It’s all free and I write it as I’m interested and want to help people out as much as I can.
Hey,Wade,very nice post. I am a c# beginner,and I want to find a software to manage my EC2 service. I found a tool called AWSTOOLSET (www dot awstoolset dot com/),but it’s very expensive.
The tool what I needed it is just like AWS Explorer.but I want run it without Visual Studio.
Could you tell me other tools just like that?
Thanks for your help.
Hey jack, sorry for the late reply, I really need to sort notifications out!
Unfortunately I’m all about their UI and writing my own stuff and don’t know of anything that would fulfil your requirements!
Hey Wade,
Thank’s a lot for such a structured and neat explanation.
It was a cake walk for me to access AWS api’s. Thanks buddy..
Regards,
Pawan
Glad I could help!