post-image

EC2 Instance Deployments with CodeDeploy from GitHub

Using AWS CodeDeploy helps me to seamlessly deploy updates and revisions to my applications on the servers that I run. While I mainly do deployments for React/NodeJS applications, I also use EC2 instances to host WordPress sites, using CodeDeploy makes the process of deploying my code wherever I like simple.

In this post I am going to walk you through how to install and configure AWS CodeDeploy on an EC2 instance running Ubuntu 16.04. I’m also going to cover all of the headaches I have encountered when deployments fail, and how to figure out what went wrong.

Also to note that we will be deploying code from a repository within GitHub. Here is a short bullet pointed list of the steps we will walk through to create the deployment:

  1. Create two IAM roles for both the instance and the CodeDeploy application we will create.
  2. Assign the CodeDeployInstanceRole to the instance when it is created.
  3. Install CodeDeploy on the instance.
  4. Deploy a new revision within the AWS CodeDeploy interface.
  5. Run through any reasons why the deployment may fail and how to resolve them.

Create the required IAM roles

We are going to create two roles named CodeDeployInstanceRole and CodeDeployServiceRole. Head into IAM within AWS and create a new role.

For the first step when it asks to choose the service that will use this role, select EC2.

Next we will add the required permissions to this role, search for the following 2 policies and select them:

  • AmazonEC2RoleforAWSCodeDeploy
  • AutoScalingNotificationAccessRole

Now it’s time to review the role, you can name the role whatever you like, I like to use CodeDeployInstanceRole. Here is what the role will look like:

codedeploy-instance-role

Now create a second role named CodeDeployServiceRole and attach the following policy to it:

  • AWSCodeDeployRole

Your second role should look like this:

codedeploy-service-role

Once this role has been created view the role and edit the “Trust Relationship”, update it to the following:

{
   "Version": "2012-10-17",
   "Statement": [
    {
       "Effect": "Allow",
       "Principal": {
         "Service": "codedeploy.amazonaws.com"
      },
       "Action": "sts:AssumeRole"
    }
  ]
}

Now that we have created both IAM roles that are required we can move on to installing the CodeDeploy agent onto the instance.

Install CodeDeploy on the Instance

We are going to install CodeDeploy on the instance. However before we install CodeDeploy on the instance it is very important that you create a new instance and attach the role you have created “CodeDeployInstanceRole” when creating the new instance!

I have wasted hours before wondering why my deployments kept failing only to find out that the instance role must be attached to the instance when creating it, not after. Again, you cannot assign the IAM role to the instance after creating it, for some strange reason CodeDeploy will fail. If you need to do a deployment for a server that has already been launched, create an image and launch it on a new server attaching the IAM role to the instance as you create it.

Ok so with that out of the way, SSH into your Ubuntu server and run the following commands to install CodeDeploy.

This will install ruby

sudo apt-get install ruby

This will install wget (it should already be installed)

sudo apt-get install wget

This will download the codedeploy agent

wget https://aws-codedeploy-ap-southeast-2.s3.amazonaws.com/latest/install

This will make the install file executable

chmod +x ./install

This will run the installer

sudo ./install auto

This will start CodeDeploy

sudo service codedeploy-agent start

This will check the status of CodeDeploy

sudo service codedeploy-agent status


You can now see in my terminal window that the codedeploy agent is active:

codedeploy-agent-status

Deploy a revision from Github through CodeDeploy

The Github repository which you are looking to deploy must contain a file named appspec.yml, this is what CodeDeploy uses to manage the deployment and optionally run several lifecycle event hooks. We will be using three of these hooks including BeforeInstall, ApplicationStart and ApplicationStop.

The appspec.yml file must be placed within the root directory structure of an applications source code. This file must also use the correct file spacing otherwise CodeDeploy may raise an error that could be difficult to debug. For reference you can view the sample GitHub repository I have created for this guide here: https://github.com/Krucial92/codedeploy-example 

Ok so with that out of the way head over to CodeDeploy in AWS and hit Create Application. Set the application name and deployment group name to whatever you choose, and leave the deployment type set to In-place deployment.

codedeploy-create-application

For the environment configuration select the Amazon EC2 instances panel and choose your EC2 instance that you assigned the CodeDeployInstanceRole to.

codedeploy-enviroment-config

Continue scrolling down to the bottom where you need to select the Service role, this service role is the CodeDeployServiceRole that we created earlier within IAM:

codedeploy-deployment-config

Now that the application has been created select it and choose the “Actions” dropdown where you can deploy a new revision:

codedeploy-deploy-revision

For the repository type select “My application is stored in Github” and scroll down to connect to Github if you are not already authenticated:

codedeploy-create-deployment

Add your Github repository name and the commit ID that you want to deploy.

The first time that we deploy the application, we will set Content options to Fail the deployment, after the first deployment when we want to make updates we will set this to Overwrite the content.

codedeploy-content-options

Once you deploy you will come to a screen where the deployment shows it’s progress, be patient until the bar is green. In my experience if you wait longer than 5 minutes, something has gone wrong. If all is good you will get the green progress bar with a nice green tick letting you know that the deployment was successful.

codedeploy-successful-deployment

Now when you look within your server you will see that your source code has been deployed:

codedeploy-success-terminal

After Deploying

If you are running a NodeJS app obviously make sure to restart the application, and also install any added dependencies that were included in your app from the last deployment.

A better way to do this, than manually doing these tasks yourself is to utilize the CodeDeploy lifecycle scripts that are executed such as BeforeInstall, ApplicationStart and ApplicationStop to do these tasks for you.

If the Deployment Fails

There are many reasons why a deployment may fail, unfortunately I have spent a lot of time figuring out why they have failed in the past. Here are a list of things that you can check/do:

  • Double check that the correct IAM roles are assigned to both the instance and the CodeDeploy application you have created.
  • Double check that the instance allows traffic on ports 80 & 443.
  • Double check that the spacing inside of your appspec.yml file is correct.
  • Make sure there are no empty spaces within any of the bash scripts.
  • Make sure that the first time you deploy a revision you select to “Fail the deployment” under content options. If this is not the first time you are deploying, make sure to choose “Overwrite the content”.
  • Restart the EC2 instance & nginx/apache.
  • Make sure that the IAM role has been added to the instance when it was created! The IAM role cannot be added to the instance after it was created for some strange reason.

If you still have no luck you can check the CodeDeploy agent log by going to /var/log/aws/codedeploy-agent/codedeploy-agent.log on your server and finding the errors associated with your deployment.

author
Jeremy Stocker
Passionate about web development and working with the latest technologies including React, Node, AWS & WordPress.
Address

45 St Georges Terrace
Perth, AU 6000

View on Google Map
Contact

Give me a call on

0498 127 791

Or reach me by email

jeremy@krucial.com.au

© 2018 Krucial Australia.