DevOps On AWS: CodePipeline In Action
Tags: aws, devops, terraform, cloud
Published: 2023-06-02 17:26:43

This post was originally published at [Practical Cloud](https://practicalcloud.net).
View the original post [here](https://practicalcloud.net/implementing-devops-on-aws-codebuild-codedeploy-and-codepipeline-in-action/).

This is the second part of a three series project on designing and deploying a three-tier architecture on AWS. [Here](https://dev.to/kelvinskell/a-practical-guide-to-deploying-a-complex-production-level-three-tier-architecture-on-aws-2hf0) is the link to the first part of this project.

DevOps on AWS is the implementation of the DevOps philosophy on the AWS Cloud platform. This includes implementing an effective CI/CD solution that provides components such as Load Balancing, Content Delivery, Storage, Security, Database, Caching and Scaling.
AWS provides a set of tools for implementing DevOps which includes,but may not be limited to:

- **[AWS CodeCommit](https://aws.amazon.com/codecommit/)**: This is a cloud version control service that is quite secure and highly scalable.
- **[AWS CodeBuild](https://aws.amazon.com/codebuild/)**: This is a fully managed build and continuous integration service in the cloud. It provides similar capability to Jenkins. It is also highly scalable, offering continuous scaling and high availability.
- **[AWS CodeDeploy](https://docs.aws.amazon.com/codedeploy/latest/userguide/welcome.html)**: This is a deployment service that automatically deploys applications to EC2 instances, On-premises servers, Lambda functions and ECS.
- **[AWS CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/welcome.html)**: This is a managed continuous delivery service that can be used to automate a release pipeline. 
AWS also offers other supplementary services such as **[CodeStar](https://aws.amazon.com/codestar/)**, **Device Farm**, etc which can help improve the quality of your DevOps experience on AWS.

In this project, we'll be making use of **CodePipeline** as the continuous delivery service for automating the deployment of our three-tier application to AWS.
- We'll be using GitHub, instead of CodeCommit for source control.
- We'll use CodeBuild  for building and testing our application code. CodeBuild will also be used to execute our terraform scripts in order to provision environments for the application. At this stage we'll also add a manual step, which involves sending SNS notifications to the user after a "terraform plan". If we are happy with the plan, then we go ahead to approve, which takes it to the next step.
- CodeDeploy will then be used to deploy the Flask application to our EC2 instances.

**Lets Go!**

## Step 1: Fork The Application repository
This is a very important first step. CodePipeline will listen for changes to our application. To follow through with the rest of the project, you'll need to have the repository in your GitHub account. **[Here](https://github.com/Kelvinskell/terra-tier/tree/master)** is the link to the project on GitHub. Fork the repository.


## Step 2: Provision The Environment
Clone the repository to your local computer. 
Navigate into the _terraform_ directory. Edit the _backend.tf_ file and add your own backend.
Run `terraform plan`. if you like the plan, then run `terraform apply`. After the apply is successfully executed, you should see your bastion host's IP address and your application's DNS address on your screen.


## Step 3: Create A Build Project
This is where we integrate our source control.
CodeBuild enables us to perform testing and other necessary builds and integrations. It is our build server of choice for this project.
On the CodeBuild Console, create a project. Choose a suitable name and description. Enable build badge.
Build badges are images provided through a public URL which displays the status of our latest build.
![AWS CodeBuild](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oiihbcnu7oelowwzkotg.png)

Your source provider should be GitHub. Connect to your GitHub account. Source version is master (The master branch).
![Codebuild connect to GitHub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q7mv67kre4wqh6wnmdw9.png)

Choose Ubuntu as your operating system. Choose the standard runtime and select "**create a new service role**".
![CodeBuild](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kfiese8iza6ogcnc4kdq.png)

Because I want CodeBuild to have private access to my servers, I will click on "**Additional configuartion**".
Under VPC, Ill select the project-x-vpc that I provisioned using terraform.
Leave every other setting as is. Click on **create build project**.
**N.B:** The secret sauce for CodeBuild is the **`buildspec`** file at the root of the application's repository. This is where I define what happens during the build phase. CodeBuild cannot run without a buildspec file. By default, this file must be named `buildspec.yml` though you can change this behaviour.




## Step 4: Create An IAM Role For CodeDeploy
CodeDeploy will require IAM permissions in order to access the application servers.
Go to the IAM Console, click on "**Roles**", click on "**Create role**".
We will create a service roles which CodeDeploy will assume to gain access to our EC2 servers.

![IAM role for CodeDeploy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f4zmzafe8fgvayeiv715.png)
Click on **Next**.
![Iam for codedeploy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/imfjf8zpiatknl5u775q.png)

Since our AutoScaling group will be originally launched from a launch template, we will need to add extra permissions.
Click on **Add permissions**, **Attach policy**, **Create policy**
Our json policy willl look like this:
```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "VisualEditor0",
			"Effect": "Allow",
			"Action": [
				"ec2:CreateTags",
				"ec2:RunInstances",
				"iam:PassRole"
			],
			"Resource": "*"
		}
	]
}
```
Click on **Next**. Review and create your policy. It should look like this:
![Iam Policy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e9mfs417xwnmt87j5gql.png)

Now go back and attach this permission, it should look like this:
![CodeDeploy Role](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dfwp556cnzwx60sf7h8b.png)
Click **Next**, Review and create your role.


## Step 5: Configure CodeDeploy
AWS CodeDeploy is a deployment service that automates the continuous deployment of application updates/versions to your servers.
Click on CodeDeploy drop down on the Left hand side of your screen. Click on "**Applications**". Click on "Create Application".
Application in CodeDeploy is a mechanism by which it manages revisions, deployment configurations and deployment groups.
Choose a name for your application and select a platform. Click on "**Create application**".
![CodeDeploy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bsx80e7ylz5wi6vuyhlw.png)

Click on "**Create deployment group**".
Choose a name for your group. Select the CodeDeploy service role we created in step 4.
![Create A CodeDeployment Group](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/avkay5laz9ywtsvqzz2n.png)

Now because I want MINIMUM downtime, I'll be using a blue/green deployment type. You can visit [here](https://www.redhat.com/en/topics/devops/what-is-blue-green-deployment) to get more information about blue/green deployments.
![code deploy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t3d9izk65ryzm9xrynxg.png)

Select the **_project-x-asg_** auto scaling group and also choose terminate after 5 minutes. Under Application Load Balancer, select your provisoned **_project-x-lb-tg_** target group as the target group of choice.
![code deploy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0zcdka8hu4xnkn33b6j.png)

Click on "**advanced options**". Enable deployment rollbacks on failures. Create your deployment group.
![Code deploy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2nfvrh3ner9nwi0th3g2.png)

We don't need any triggers for this deployment group. you typically use triggers if you are simply automating your deployment. But since this is a CI/CD pipeline, we'll leave everything to CodePipeline to orchestrate.

**N.B:** The secret sauce for CodeDeploy is the **`appspec`** file at the root of the application's repository. This is where I define what happens during the deploy phase. CodeDeploy cannot run without an appspec file. By default, this file must be named `appspec.yml` though you can change this behaviour.
Also note that the only reason this would work is because I already included instructions for installing the CodeDeploy as part of the user data on the logic tier servers. Therefore they will be automatically provisoned by terraform. If you were to use a different environment, remeber to install the CodeDeploy agent on your servers. You can find instructions on how to do that [here](https://docs.aws.amazon.com/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html).


## Step 6: Create A Pipeline
AWS Codepipeline acts as our continuous delivery service. It is the glue that holds our entire together and also orchestrates it. CodePipeline will seamlessly handle the integration of source control, CodeBuild and Codedeploy.

Go to the Pipeline Console, click on "**Create Pipeline**".
![AWS pipeline console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7qcjzb20d5ogl2y3yn1o.png)

Choose a name for your pipeline. Click on **Next**.
![Creating an AWS CodePipeline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wo2pyeul6cutsh65c6k.png)

Under **source stage**, select GitHub from the drop down. Authorize access to GitHub.
![Creating a pipeline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzc7upcfet94c16wt3jn.png)

CodePipeline allows us to choose either Jenkins or CodeBuild as our build provider. We are going to choose CodeBuild.
Under **project name**, select the build project we created in step 3.
![Creating a pipleine](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5yk1f9hbs3unzuzvm0wy.png)

On the **Add Deploy stage**, we will use CodeDeploy as our deploy provider. Then we will select the application name and deployment group we created earlier on in step 5.
![CodePipeline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6hsg7mow9nfwzwxyv3y3.png)
Review and create your pipeline.

**Aaaaaaaaaaaaaaaaaaannnnnnndd............Done!!!**
We have successfully created a CI/CD pipeline on AWS using AWS CodePipeline.

_**Before You Go..**_
Let's take this a notch further by adding a manual approval feature through which manual approval must be given before the application is deployed.

## Step 7: Create An SNS Topic
 
For manual the manual approval stage, we want to be able to send an email notification to the team lead that the buid is successful and about to deploy. The team lead must then review the artifacts and/or log outputs from the build and  make a decision whether to continue to deploy or not.

Go to the AWS SNS console, create a topic. 
Choose a standard topic. Give a name and display name to your topic. create the topic.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cz4ioz80x2yisr7p46nt.png)

## Step 8: Modify The Pipeline
Now we have to include an action group after the build stage to enable a manual approval feature.

Go to the pipeline, click on **Edit**.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j85tzyy57efmhml21df7.png)

On the Build Stage, click on **Edit**.
Here, we will add an action group just after the build.
An Action Group is a set of one or more actions through which you can further refine your pipeline workflow. There are six types of actions - source, build, test, deploy, approval and invoke. Read more about them [here](https://docs.aws.amazon.com/codecatalyst/latest/userguide/workflows-group-actions.html).
Your pipelie should now look like this:
![Pipeline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8elgkwbp9nf3wl8pba4s.png)
Without the red lines of course!

That's it. I hope you enjoyed it. Happy Clouding!!!