Currently there is a huge push to migrate from on premise environments to AWS. In these scenarios a "lift and shift" approach is ideal especially for legacy applications where no one knows how to configure or manage them in your organization or if you want to just verify if an application will work in the cloud.

Today I'll migrate a CentOS 7.6 virtual machine running on VirtualBox to AWS. Currently only CentOS 7.6 and older are supported on AWS. CentOS 7.7 and 8 are NOT supported as of February 2020.


Prerequistes

Before you begin, make sure you have the awscli installed on your machine. I will be using the new AWS CLI v2.

You will also need an export of a virtual machine. My hypervisor is VirtualBox, but any hypervisor will work (VMWare, Hyper-V, or KVM) as long as it can export to an ova or vmdk format.  

I will also create a user named test-user1 on the virtual machine before I export it. This will be the user I will use to log into the EC2 instance once it's provisioned in AWS.


Files You Will Need

Below, you will need the following files. The first file is the trust-policy.json, I will use this to create an IAM role.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": { "Service": "vmie.amazonaws.com" },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "sts:Externalid": "vmimport"
                }
            }
        }
    ]
}
trust-policy.json

The next file is role-policy.json, it contains the necessary rules granted to the role. I'll allow this policy to grab the objects and list bucket contents within a bucket named testvmimportsbucket001.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::vmimportsbucket001",
                "arn:aws:s3:::vmimportsbucket001/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:ModifySnapshotAttribute",
                "ec2:CopySnapshot",
                "ec2:RegisterImage",
                "ec2:Describe*"
            ],
            "Resource": "*"
        }
    ]
}
role-policy.json

The container.json will tell the import process in which S3 bucket to find the export and which format it's in.

[{
    "Description": "CentOS7.6",
    "Format": "OVA",
    "UserBucket": {
        "S3Bucket": "vmimportsbucket001",
        "S3Key": "test.ova"
    }
}]
container.json

Prep Work

First I'll create an IAM role and call it vmimport, I'll also supply the trust-policy.json file.

aws2 iam create-role --role-name vmimport --assume-role-policy-document "file://trust-policy.json"

Next create the role policy. To do this I'll attach the policy name vmimport to the role with the same name,vmimport. The role-policy.json will be supplied when attaching the policy to the role.

aws2 iam put-role-policy --role-name vmimport --policy-name vmimport --policy-document "file://role-policy.json"

Lastly for the prep work, I'll create an S3 bucket within the us-west-2 region. This will contain the exports from my hypervisor.

aws2 s3 mb s3://vmimportsbucket001 --region us-west-2

Exporting the VM from VirtualBox

Now hopefully your index finger is warmed up because it's time for some clicking action! Go and open up VirtualBox. Once VirtualBox is ready to go, click on 'file' and select "Export Appliance".

Make sure to export the file with the .ova extension. You may choose to include your network adapter MAC addresses, I went with the default option which was to include the NAT adapter.

When you're ready click on the "Export" button. Depending on your host machine and size of the virtual machine this may take awhile.

vmexport


Upload OVA to S3 bucket

Now you can head back into the AWS CLI! To upload the ova file, use the following s3 command.

aws2 s3 cp centos7.6.ova s3://vmimportsbucket001

You can start the import process as soon as the upload to the S3 bucket is complete.

aws2 ec2 import-image --description "CentOS7.6" --disk-containers "file://container.json"

You will get an output like below. Notice the "Progress" in the output below, wait for this to fully complete!

Note: Do not execute the import-image command again to check the status. It will create another task!

{
    "Description": "CentOS7.6",
    "ImportTaskId": "import-ami-0c9aafe073fefb449",
    "Progress": "2",
    "SnapshotDetails": [
        {
            "DiskImageSize": 0.0,
            "Format": "OVA",
            "UserBucket": {
                "S3Bucket": "vmimportsbucket001",
                "S3Key": "centos7.6.ova"
            }
        }
    ],
    "Status": "active",
    "StatusMessage": "pending"
}
output of import-image command

To check the status of the import, copy the ImportTaskId from the output above and plug it into the describe-import-image-tasks command below.

aws2 ec2 describe-import-image-tasks --import-task-ids "import-ami-0c9aafe073fefb449"

The import process may take some time so please be patient and periodically check the status of the import by issuing the aws2 ec2 describe-import-image-tasks command above every so often.


Create an EC2 Instance

Once the process above completes, you should see a new AMI based on the ova file in your S3  bucket.

export

You can now go ahead and create an EC2 instance based on this AMI!

When your shiny new EC2 instance based on your export is up and running, go ahead and SSH into it using the local user on the virtual machine. Even though you were prompted to associate a public key when you created the EC2 instance, that public key will not work here. I will instead SSH into the EC2 instance as test-user1 and supply the password when prompted.

Before I exported my virtual machine from VirtualBox, I created a file in test-user1's home directory. All this file had was the phrase "hello world!", but this is a good indication that the export originated from my very own virtual machine.

cat /home/test-user1/howdy.txt

hello world!

Conclusion

As you can see migrating virtual machines to AWS is simple and within half an hour you can be up and running in the cloud. Being able to lift and shift your virtual machines is an important skill to know since it allows you to test your system or application in the cloud quickly with minimal configuration changes.

The workflow went like this:

  1. Create an IAM role
  2. Attach a policy to the IAM role
  3. Create an S3 bucket for the export
  4. Export the on-prem virtual machine
  5. Upload the export file to S3
  6. Import the exported file
  7. Create a new EC2 instance from the newly created AMI