AWS Partner Network (APN) Blog
Deploy to Production using AWS CodeBuild and the AWS Developer Tools Suite
This is a guest post from Paul Duvall, Stelligent, with contributions from Brian Jakovich and Jonny Sywulak, Stelligent. Paul Duvall is CTO at Stelligent, and an AWS Community Hero.
Stelligent is an AWS DevOps Competency Partner.
At re:Invent 2016, AWS announced a new fully managed service called AWS CodeBuild that allows you to build your software. Using CodeBuild, you can build code using pre-built images for Java, Ruby, Python, Golang, Docker, Node, and Android or use your own customize images for other environments without provisioning additional compute resources and configuration. This way you can focus more time on developing your application or service features for your customers.
In our previous post, An Introduction to CodeBuild, we described the purpose of AWS CodeBuild, its target users, and how to setup an initial CodeBuild project. In this post, you will learn how to integrate and automate the orchestration of CodeBuild with the rest of the AWS Developer Tools suite – including AWS CodeDeploy, AWS CodeCommit, and AWS CodePipeline using AWS’ provisioning tool, AWS CloudFormation. By automating all of the actions and stages into a deployment pipeline, you can release changes to users in production whenever you choose to do so. You’ll see an example that walks you through the process along with a detailed screencast that shows you every step in launching the solution and testing the deployment.
Figure 1 shows this deployment pipeline in action.
Figure 1 – CodePipeline building with CodeBuild and deploying with CodeDeploy using source assets in CodeCommit
Keep in mind that CodeBuild is a building block service you can use for executing build, static analysis, and test actions that you can integrate into your deployment pipelines. You use an orchestration tool like CodePipeline to model the workflow of these actions along with others such as polling a version-control repository, provisioning environments, and deploying software.
Prerequisites
Here are the prerequisites for this solution:
- AWS Account – Follow these instructions to create an AWS Account: Creating an AWS Account
- EC2 Key Pair – Follow these instructions to create an EC2 Key Pair: Creating Your Key Pair Using Amazon EC2
These prerequisites will be explained in greater detail in the Deployment Steps section.
Architecture and Implementation
In Figure 2, you see the architecture for launching a deployment pipeline that gets source assets from CodeCommit, builds with CodeBuild, and deploys software to an EC2 instance using CodeDeploy. You can click on the image to launch the template in CloudFormation Designer.
Figure 2 – Architecture of CodeBuild, CodePipeline, CodeDeploy, and CodeCommit solution
The components of this solution are described in more detail below:
- AWS CloudFormation – All of the resource generation of this solution is described in CloudFormation which is a declarative code language that can be written in JSON or YAML
- AWS CodeBuild – Creates a CodeBuild project using the AWS::CodeBuild::Project
- AWS CodeCommit – Creates a CodeCommit Git repository using the AWS::CodeCommit::Repository
- AWS CodeDeploy – CodeDeploy automates the deployment to the EC2 instance that was provisioned by the nested stack using the AWS::CodeDeploy::Application and AWS::CodeDeploy::DeploymentGroup
- AWS CodePipeline – I’m defining CodePipeline’s stages and actions in CloudFormation code which includes using CodeCommit as a source action, CodeBuild as a build action, and CodeDeploy for a deploy action (For more information, see Action Structure Requirements in AWS CodePipeline)
- Amazon EC2 – A nested CloudFormation stack is launched to provision multiple EC2 instances on which the CodeDeploy agent is installed. The CloudFormation template called through the nested stack is provided by AWS.
- AWS IAM – An Identity and Access Management (IAM) Role is provisioned using the AWS::IAM::Role resource which defines the resources that the pipeline can access.
- AWS SNS – Provisions a Simple Notification Service (SNS) Topic using the AWS::SNS::Topic The SNS topic is used by the CodeCommit repository for notifications.
CloudFormation Template
In this section, I’ll highlight a few code snippets from the CloudFormation template that automates the provisioning of the AWS Developer Tools stack along with other resources including EC2, IAM, and SNS. You can find a link to the CloudFormation template at the bottom of this post.
CodeBuild
AWS CloudFormation has provided CodeBuild support from day one. Using the AWS::CodeBuild::Project resource, you can provision your CodeBuild project in code as shown in the sample below.
"CodeBuildJavaProject":{
"Type":"AWS::CodeBuild::Project",
"DependsOn":"CodeBuildRole",
"Properties":{
"Name":{
"Ref":"AWS::StackName"
},
"Description":"Build Java application",
"ServiceRole":{
"Fn::GetAtt":[
"CodeBuildRole",
"Arn"
]
},
"Artifacts":{
"Type":"no_artifacts"
},
"Environment":{
"Type":"LINUX_CONTAINER",
"ComputeType":"BUILD_GENERAL1_SMALL",
"Image":"aws/codebuild/java:openjdk-8"
},
"Source":{
"Location":{
"Fn::Join":[
"",
[
"https://git-codecommit.",
{
"Ref":"AWS::Region"
},
".amazonaws.com/v1/repos/",
{
"Ref":"AWS::StackName"
}
]
]
},
"Type":"CODECOMMIT"
},
"TimeoutInMinutes":10,
"Tags":[
{
"Key":"Owner",
"Value":"JavaTomcatProject"
}
]
}
},
The key attributes, blocks, and values of the CodeBuild CloudFormation resource are defined here:
- Name – Define the unique name for the project. In my CloudFormation template, I’m using the stack name as a way of uniquely defining the CodeBuild project without requiring user input.
- ServiceRole – Refer to the previously-created IAM role resource that provides the proper permissions to CodeBuild.
- Environment Type – The type attribute defines the type of container that CodeBuild uses to build the code.
- Environment ComputeType – The compute type defines the CPU cores and memory the build environment uses
- Environment Image – The image is the programming platform on which the environment runs.
- Source Location and Type – In Source, I’m defining the CodeCommit URL as the location along with the type. Along with the CODECOMMIT type, CodeBuild also supports S3 and GITHUB. In defining CodeCommit as the type, CodeBuild automatically searches for a yml file in the root directory of the source repository. See the Build Specification Reference for AWS CodeBuild for more detail.
- TimeoutInMinutes – This is the amount of time before the CodeBuild project will cease running. This modifies from the default of 60 minutes to 10 minutes.
- Tags – I can define multiple tag types for the CodeBuild project. In this example, I’m defining the team owner.
For more information, see the AWS::CodeBuild::Project resource documentation.
CodeCommit
With CodeCommit, you can provision a fully managed private Git repository that integrates with other AWS services such as CodePipeline and IAM. To automate the provisioning of a new CodeCommit repository, you can use the AWS::CodeCommit::Repository CloudFormation resource. You can create a trigger to receive notifications when the master branch gets updated using an SNS Topic as a dependent resource that is created in the same CloudFormation template. For a more detailed example and description, see Provision a hosted Git repo with AWS CodeCommit using CloudFormation.
CodeDeploy
AWS CodeDeploy provides a managed service to help you automate and orchestrate software deployments to Amazon EC2 instances or those that run on-premises.
To configure CodeDeploy in CloudFormation, you use the AWS::CodeDeploy::Application and AWS::CodeDeploy::DeploymentGroup resources.
CodePipeline
While you can create a deployment pipeline for CodePipeline in CloudFormation by directly writing the configuration code, we often recommend that customers manually create the initial pipeline using the CodePipeline console and then once it’s established run the get-pipeline command (as shown below) to get the proper CodePipeline configuration to use in defining the CloudFormation template. To create a pipeline using the console, follow the steps in the Simple Pipeline Walkthrough. Choose CodeCommit as a source provider, CodeBuild as a build provider and CodeDeploy as a deploy provider.
In the following snippet, you see how you can use the AWS::CodePipeline::Pipeline resource to define the deployment pipeline in CodePipeline. A snippet of this configuration is shown below.
"CodePipelineStack":{ "Type":"AWS::CodePipeline::Pipeline", "Properties":{ ... "Stages":[ ...
Once the CodePipeline has been manually created using the AWS console, you can run the following command to get the necessary resource configuration that can be copied and modified in CloudFormation. Replace PIPELINE-NAME with the name of the pipeline that you manually created.
aws codepipeline get-pipeline --name PIPELINE-NAME
You will get the configuration output using this command. You can add this configuration to the CodePipeline resource configuration in CloudFormation. You’ll need to modify the attribute names from lowercase to title case.
In configuring the CodeBuild action for the CodePipeline resource, the most relevant section is in defining the ProjectName as shown in the snippet below.
"ProjectName":{ "Ref":"CodeBuildJavaProject" } }, …
CodeBuildJavaProject references the CodeBuild project resource defined previously in the template.
Costs
Since costs can vary as you use certain AWS services and other tools, you can see a cost breakdown and some sample scenarios to give you an idea of what your monthly spend might look like. Note this will be dependent on your unique environment and deployment, and the AWS Cost Calculator can assist in establishing cost projections.
- CloudFormation – No additional cost.
- CodeBuild – CodeBuild charges per minute used. It comes with 100 minutes per month at no charge. For a simple execution of this demo, you can stay within the limits of the AWS Free Tier – please read about the Free Tier here. For more information, see AWS CodeBuild pricing.
- CodeCommit – If used on a small project of less than six users, there’s no additional cost. See AWS CodeCommit Pricing for more information.
- CodeDeploy – No additional cost.
- CodePipeline – $1 a month per pipeline unless you’re using it as part of the free tier. For more information, see AWS CodePipeline pricing.
- EC2 – There are a number of Instance types and pricing options. See Amazon EC2 Pricing for more information.
- IAM – No additional cost.
- SNS – Considering you likely won’t have over 1 million Amazon SNS requests for this particular solution, there’s no cost. For more information, see AWS SNS Pricing.
So, for this particular sample solution, as long as you don’t run it past the 30 days free period after the pipeline was created, you will not be charged. Read more about CodePipeline’s pricing here.
Deployment Steps
There are three main steps in launching this solution: preparing an AWS account, launching the stack, and testing the deployment. Each is described in more detail in this section. Please note that you are responsible for any charges incurred while creating and launching your solution.
Step 1. Prepare an AWS Account
- If you don’t already have an AWS account, create one at http://aws.amazon.com by following the on-screen instructions. Part of the sign-up process involves receiving a phone call and entering a PIN using the phone keypad. Be sure you’ve signed up for the CloudFormation service.
- Use the region selector in the navigation bar of the console to choose the Northern Virginia (us-east-1) region
- Create a key pair. To do this, in the navigation pane of the Amazon EC2 console, choose Key Pairs, Create Key Pair, type a name, and then choose Create.
Step 2. Launch the Stack
Click on the Launch Stack button below to launch the CloudFormation stack. Before you launch the stack, review the architecture, configuration, and other considerations discussed in this post. To download the template, click here.
Time to deploy: Approximately 7 minutes
The template includes default settings that you can customize by following the instructions in this post.
Step 3. Test the Deployment
Click on the CodePipelineURL
Output in your CloudFormation stack. You’ll see that the pipeline has failed on the Source action. This is because the Source action expects a populated repository and it’s empty. The way to resolve this is to commit the application files to the newly-created CodeCommit repository. First, you’ll need to clone the repository locally. To do this, get the CloneUrlSsh
Output from the CloudFormation stack you launched in Step 2. A sample command is shown below. You’ll replace {CloneUrlSsh}
with the value from the CloudFormation stack output. For more information on using SSH to interact with CodeCommit, see the Connect to the CodeCommit Repository section at: Create and Connect to an AWS CodeCommit Repository.
{CloneUrlSsh} cd {localdirectory}
Once you’ve cloned the repository locally, download the sample application files from the aws-codedeploy-sample-tomcat Git repository and place the files directly into your local repository. Do not include the aws-codedeploy-sample-tomcat folder. Go to the local directory and type the following to commit and push the new files to the CodeCommit repository:
git add . git commit -am "add all files from the AWS Java Tomcat CodeDeploy application" git push
Once these files have been committed, the pipeline will discover the changes in CodeCommit and run a new pipeline instance and all stages and actions should succeed as a result of this change. It takes approximately 3-4 minutes to complete all stages and actions in the pipeline.
Access the Application and Pipeline Resources
Once the CloudFormation stack has successfully completed, select the stack and go to the Outputs tab and click on the CodePipelineURL output value. This will launch the deployment pipeline in CodePipeline console. Go to the Deploy action and click on the Details link. Next, click on the link for the Deployment Id of the CodeDeploy deployment. Then, click on the link for the Instance Id. From the EC2 instance, copy the Public IP value and paste into your browser and hit enter to launch the Java sample application – as displayed in Figure 3.
Figure 3 – Deployed Java Application
You can access the Source and Build using the CodePipeline Action Details. For example, go to the pipeline and click on commit id for the Source action and click on the Details to the Build action. See Figure 4 for a detailed illustration of this pipeline.
Figure 4 – CodePipeline with Action Details
There are also direct links for the CodeCommit, CodeBuild, and CodeDeploy resources in the CloudFormation Outputs as well.
Commit Changes to CodeCommit
Make some visual modifications to the src/main/webapp/WEB-INF/pages/index.jsp
page and commit these changes to your CodeCommit repository to see these changes get deployed through your pipeline. You perform these actions from the directory where you cloned the local version of your CodeCommit repo (in the directory created by your git clone command). To push these changes to the remote repository, see the commands below.
git add . git commit -am "modify front page for AWS sample Java Tomcat CodeDeploy application" git push
Once these changes have been committed, CodePipeline will discover the changes made to your CodeCommit repo and initiate a new pipeline. After the pipeline is successfully completed, follow the same instructions for launching the application from your browser. Once deployed, you should see the modifications you made in the application upon entering the URL – as shown in Figure 5.
Figure 5 – Deployed Java Application with Changes Committed to CodeCommit, Built with CodeBuild, and Deployed with CodeDeploy
How-to Video
In this video, I walk through the deployment steps described above.
Additional Resources
- Here are some additional resources you might find useful:
- AWS CodeBuild – Product Page
- AWS CodeBuild – Fully Managed Build Service – Blog post from Jeff Barr
- An Introduction to AWS CodeBuild – First part of the two-part series on CodeBuild from Stelligent
Summary
In this post, you learned how to define and launch a CloudFormation stack capable of provisioning a fully-codified continuous delivery solution using CodeBuild. Additionally, the example included the automation of a CodePipeline deployment pipeline – which included the CodeCommit, CodeBuild, and CodeDeploy integration.
Furthermore, I described the prerequisites, architecture, implementation, costs, and deployment steps of the solution.
Sample Code
The code for the examples demonstrated in this post are located at https://github.com/stelligent/aws-codedeploy-sample-tomcat. Let us know if you have any comments or questions @stelligent.
The content and opinions in this blog are those of the third party author and AWS is not responsible for the content or accuracy of this post.