Automating AWS EC2 Management with Java

Introduction

One of the most popular services available on Amazon Web Services is EC2, which stands for Elastic Compute Cloud. EC2 makes it easy for developers and users to create and manage cloud-hosted virtual machines, also known as EC2 instances.

EC2 provides a web interface which makes it easy to spin up and work with VM instances, including configuration, authentication, connection, maintenance, storage, scaling, and more.

In addition to creating and working with the EC2 service through the web interface, AWS provides SDK's that allow VM operations to be performed directly from code.

In this article, we'll discuss using the Java SDK and API to create an EC2 instance, start and stop the instance, reboot it, back it up into an image, and restoring it from the backup.

Setup AWS Credentials for the Java SDK

Let's start by learning how to create a set of AWS credentials, which are required to access AWS and make API calls through the SDK. The easiest way to do this is to log into the AWS console and create a new IAM (Identity and Access Management) role.

Follow these steps to do this:

  1. Log into the AWS Console.

  2. Click on the Services menu in the top left of the screen, search for IAM, and click on the dropdown option that appears.

AWS IAM Services Menu

  1. Under the Security Status heading, expand the Create individual IAM users option and click the Manage Users button.

AWS IAM Manage Users

  1. Click the Add user button.

  2. Enter the user name for your new IAM user and check the box for Programmatic access.

AWS IAM User Details

  1. Click the Next: Permissions button and then select Attach existing policies directly.

  2. Type EC2 into the search box and in the results, check the box for AmazonEC2FullAccess.

AWS IAM EC2 Permissions

  1. Click the Next: Tags button, then click the Next: Review button.

  2. Review the IAM user configuration and click the Create user button.

  3. You'll be taken to a confirmation page, where you can copy out the Access key ID and Secret access key which are the credentials you'll use to access the AWS API through the Java SDK.

By default, the SDK will look up for the credentials in the Default credential profile file, which is a file typically located at ~/.aws/credentials on your local machine. You'll need to create this file yourself and add the IAM credentials into it.

To configure this yourself, create the new file ~/.aws/credentials and add the following contents, replacing the access key and secret key with the values from your newly created IAM user in the AWS console:

aws_access_key_id = YOUR_ACCESS_KEY_ID
aws_secret_access_key = YOUR_SECRET_ACCESS_KEY

Create a default region file for the AWS SDK to use by adding a new file called ~/.aws/config with the following contents (you can replace the region with one closer to where your users live for optimal performance):

region = US_WEST_2

The local environment should now be configured for the AWS Java SDK to authenticate successfully.

Installing the SDK with Maven

If you're using Maven, add the following dependency to include the AWS Java SDK:

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-ec2</artifactId>
    <version>${version}</version>
</dependency>

Or, if you're using Gradle:

compile group: 'com.amazonaws', name: 'aws-java-sdk', version: '${version}'

Now, instead of just the EC2 dependency, you could use aws-java-sdk, which is the entire SDK. There's a lot of dependencies in the entire SDK - 219, to be exact, so if you're only using EC2, there's no need to download them all.

Creating an EC2 Instance

The AWS Java SDK for EC2 provides several classes that can be used to create a new instance. These are located in the software.amazon.awssdk library. These classes are:

  • Region: Represents an AWS hosting region to perform the SDK operations in.
  • Ec2Client: Used to set up and configure a client to connect to AWS EC2 over web services.
  • InstanceType: Represents a VM instance type/size such as T2.MICRO.
  • RunInstancesRequest: Represents a web request for creating EC2 instances.
  • RunInstancesResponse: Represents a web response from the AWS EC2 service after instance creation.

Let's see how we can use these to create an EC2 instance:

Region region = Region.US_WEST_2;
String amiId = "ami-0e34e7b9ca0ace12d";

Ec2Client ec2 = Ec2Client.builder()
        .region(region)
        .build();

RunInstancesRequest runRequest = RunInstancesRequest.builder()
        .imageId(amiId)
        .instanceType(InstanceType.T1_MICRO)
        .maxCount(1)
        .minCount(1)
        .build();

RunInstancesResponse response = ec2.runInstances(runRequest);

Here, we set up a Region to a region close to the end-users for optimal performance. If a Region is not programmatically specified, the default region from the ~/.aws/config is used.

Then, we've specified our AMI in a String. This is a unique identifier for the machine image we're using and can be obtained in the AWS Console.

With those two in place, we've instantiated an Ec2Client object and set the region. After that, using the RunInstancesRequest class, we've populated the information for a request.

The request is sent via the runInstances() method and the response is packed in a RunInstancesResponse instance.

After this, the instance can be seen in the AWS Console:

AWS EC2 instance running in console

Let's now manipulate the instance we created, beginning with starting and stopping it.

Starting and Stopping an Instance

Building upon the classes used in the previous example, and in the same fashion, to send requests for starting and stopping of an instance, we have:

  • StartInstancesRequest: Represents a web request for starting EC2 instances.
  • StopInstancesRequest: Represents a web request for stopping EC2 instances.

Let's see how we can use these two classes to start and stop an EC2 instance:

Region region = Region.US_WEST_2;
String instanceId = "i-025dea8c69e83bb61";

Ec2Client ec2 = Ec2Client.builder()
        .region(region)
        .build();

StartInstancesRequest request = StartInstancesRequest.builder()
        .instanceIds(instanceId)
        .build();

ec2.startInstances(request);

StopInstancesRequest request = StopInstancesRequest.builder()
        .instanceIds(instanceId)
        .build();

ec2.stopInstances(request);

We've set the Region and made note of our instance ID. Then, we've built an Ec2Client, like last time.

Finally, we've formulated a StartInstancesRequest with the instance ID and sent it via the startInstances() method.

The StopInstancesRequest is built the exact same way and is sent via the stopInstances() method.

After starting or stopping an EC2 instance in this way, the new state of the instance should be visible in the AWS EC2 console.

For convenience, both the stopping and starting actions can be performed in a single reboot request.

Rebooting an Instance

In the same fashion, we're introduced to the RebootInstancesRequest class:

  • RebootInstancesRequest: Represents a web request for starting EC2 instances.

Let's see how we can construct a request to reboot an instance:

Region region = Region.US_WEST_2;
String instanceId = "i-025dea8c69e83bb61";

Ec2Client ec2 = Ec2Client.builder()
        .region(region)
        .build();

RebootInstancesRequest request = RebootInstancesRequest.builder()
        .instanceIds(instanceId)
        .build();

ec2.rebootInstances(request);

We've set the Region and instanceId and constructed an Ec2Client.

Using the builder() method of the RebootInstancesRequest, we build a request with just the instanceId.

The request is sent via the rebootInstances() method, after which, the instance is rebooted.

Next, we'll look into automating the common task of backing up an existing EC2 instance to an AMI. We'll also discuss how to restore the image to a new EC2 instance.

Back up an Instance to an AMI (Amazon Machine Image)

As with the previous tasks, this one is taken care of with a request as well. To construct requests for backing up instances to images, we've got:

  • CreateImageRequest: Represents a web request for creating a new AMI.

Let's see how we can use the CreateImageRequest class to back up an image based on an existing instance:

Region region = Region.US_WEST_2;
String instanceId = "i-025dea8c69e83bb61";

Ec2Client ec2 = Ec2Client.builder()
        .region(region)
        .build();

CreateImageRequest request = CreateImageRequest.builder()
        .instanceId(instanceId)
        .name("newimage")
        .build();

ec2.createImage(request);

After creating a new AMI from an existing EC2 instance in this way, the new AMI will be visible in the IMAGES > AMIs link on the right sidebar of the EC2 console.

Restore an Instance from an AMI

Luckily, restoring this AMI to create a new instance is very easy since we already learned how to create a new EC2 instance in the first example of this article.

All we need to do is replace the string amiId (which we originally found from the desired AMI in the AWS console) with the AMI ID from the new custom AMI that we created:

Region region = Region.US_WEST_2;
String amiId = "created_ami";

Ec2Client ec2 = Ec2Client.builder()
        .region(region)
        .build();

RunInstancesRequest runRequest = RunInstancesRequest.builder()
        .imageId(amiId)
        .instanceType(InstanceType.T1_MICRO)
        .maxCount(1)
        .minCount(1)
        .build();

RunInstancesResponse response = ec2.runInstances(runRequest);

This will allow us to use our custom AMI as a template for creating the new EC2 instance instead of the out-of-the-box AWS AMI from their marketplace.

Conclusion

In this article, we discussed how to set up and configure the AWS SDK for Java, specifically for the EC2 service.

We covered the setup of credentials for AWS SDK authentication and adding required dependencies using Maven. We also detailed the Java code for some common EC2 operations such as creating a new instance, stopping/starting the instance, rebooting the instance, and backing up/restoring the instance from an AMI.

About the Author

This article was written by Jacob Stopak, a software developer and consultant with a passion for helping others improve their lives through code. Jacob is the author of the Baby Bitcoin Guidebook for Developers, a book that dives into Bitcoin's code to help curious developers understand how Bitcoin works under the hood.

Author image
About Jacob Stopak
San Diego, CA Twitter Website
Jacob Stopak is a software developer and creator of InitialCommit.io - a site dedicated to teaching people how popular programs are coded. Its main project helps people learn Git at the code level.