Pipeline Doc
Pipeline Doc
CI/CD tools are important to help a team to automate their testing and deployment. Some
tools specifically handle Continuous Integration (CI) which focusing on build, test and merge
the project while some manage the development and deployment (CD) side.
The diagram below shows the CI/CD stack that will be used in this article.
All the project codes are committed in the GitHub repository. GitHub Actions will take place
once the user triggers a push event to the respective repository. It will perform the code build
process and run the automated tests. Once it is done, GitHub Actions will run the CD job
which will trigger the AWS CodeDeploy to do the deployment part. CodeDeploy will help to
automate the deployment by fetching the latest committed code in GitHub and update the
project code in the EC2 server.
The CI/CD process flow
2. The Requirements
To create the CI/CD pipeline, make sure to create these accounts first:
There are two types of IAM roles that need to be created: Instance Role and Service.
Instance Role
In the first step, we need to create the instance role using AWS IAM. This role is important as
it gives the proper permission to EC2 to access and read files from S3 buckets.
To create it, go to AWS Management Console and log in using our AWS Account. Then,
proceed to IAM in the console and click on Roles. Once we have entered the Roles page,
click on Create Role.
We will create roles for EC2 instance, therefore select EC2 as our use case.
• AmazonEC2RoleForAWSCodeDeploy
Then, give the EC2 role a name and Click on Create Role
Service Role
Next, we need to create the IAM service role which will give the AWS CodeDeploy access
and read the EC2 instance tags. Go to the Roles page and then Click on Create Role.
Select EC2 and proceed to add the following policy:
• AWSCodeDeployRole
Then, give the service role a name and Click on Create Role. After that, we need to edit the
trust relationship of the service role.
In order to do this, we need to go to the Roles page and click on the service role name that we
have created.
You will see the trust relationships tab on the next page and click on Edit trust
relationships.
Edit the policy document as below:
{
“Version”: “2012–10–17”,
“Statement”: [
{
“Effect”: “Allow”,
“Principal”: {
“Service”: [
“codedeploy.amazonaws.com”
]
},
“Action”: “sts:AssumeRole”
}
]
}
Now, we need to set up our EC2 instance. Go to AWS Management Console and log in using
our AWS Account. Then, proceed to EC2 in the console and click on Launch Instances.
Then, choose an Amazon Machine Image (AMI) for the instance. In this article, we will be
selecting the Amazon Linux 2 AMI (HVM), SSD Volume Type.
Choose the Instance Type for EC2 and Click on Next: Configure Instance Details
In the configure instance details section, click on the IAM role drop-down and select the role
name that you have created earlier.
Under the Tag page, click on Add Tag add new key and value name.
Go to Configure Security Group and we can add any firewall rules that control traffic for of
our instance.
Once done, click on Review and Launch. We will be in the Review page and if everything is
satisfied according to our needs, we can click Launch.
A modal box will appear asking us whether to select an existing private key pair or creating a
new one. In this tutorial, we will be creating new key pair and make sure to download the key
pair and save it. Then, click on Launch Instance.
You should see you newly created instance in the list of running instances in the EC2 page.
Alright now our EC2 is setup, let’s dive into the AWS CodeDeploy configurations.
In order to make sure our application is able to run properly on the EC2 server, we need to
install the required packages. Since we are using Flask Application as an example, we are
required to install python related packages and also a git module to enable the server
environment to use the git services.
Go to the EC2 page and click on the Instance ID. Then click on the Connect button on the
top right of the screen.
Open Command Prompt and locate our .pem file that we created earlier when setting up the
EC2 instance. Then, paste the ssh connection command.
Now, we are in the EC2 server.
4. Install authbind and modify port 80 (for enabling production server to run app at port
80 without superuser privileges)
wget https://s3.amazonaws.com/aaronsilber/public/authbind-2.1.1-0.1.x86_64.rpm
sudo rpm -Uvh https://s3.amazonaws.com/aaronsilber/public/authbind-2.1.1-0.1.x86_64.rpm
sudo touch /etc/authbind/byport/80
sudo chmod 500 /etc/authbind/byport/80
sudo chown ec2-user /etc/authbind/byport/80
5. Clone GitHub Repository. (You may change to your own working GitHub repository)
git clone https://github.com/azzan-amin-97/FlaskAppCodeDeploy.git
Alright all done! We can now focus on configuring AWS CodeDeploy Service.
To use the AWS CodeDeploy service we need to define the application and deployment
group. All of these can be set up in the AWS CodeDeploy page.
Create an Application
Go to AWS Management Console and log in using our AWS Account. Proceed to
CodeDeploy in the console and click on Applications. Then, Click on Create application.
We will need to put the our application name and select EC2/On-premises as our compute
platform.
Next, choose Amazon EC2 instances in the environment configuration and put our EC2
instance tag.
For Agent configuration, we can leave it as it is (as the default settings). In the deployment
settings, select CodeDeployDefault.OneAtATime. You can enable the load balancing if it is
suit your use case otherwise just unselect it.
We can now click on Create deployment group. In our CodeDeploy application, we can
now see the newly created deployment group.
We use EC2/On-Premises compute platform for our application. Therefore, in order to make
the deployment automation successful, the AppSpec file must be a YAML-formatted file
named appspec.yml and it must be placed in the root of our application project’s source code
directory. If you want to understand more about the CodeDeploy AppSpec file, please check
this out: CodeDeploy AppSpec File reference — AWS CodeDeploy (amazon.com)
In your root project directory, add appspec.yml . This is what our AppSpec file looks like.
version: 0.0
os: linux
files:
- source: .
destination: /home/ec2-user/app
hooks:
AfterInstall:
- location: scripts/install_app_dependencies
timeout: 300
runas: root
ApplicationStart:
- location: scripts/start_server
timeout: 300
runas: root
We will be using supervisor to run the application production server. Therefore, we will need
to add supervisord.conf file in the root directory. Please check out this link to see what does
the supervisord.conf looks like.
Add scripts folder in root directory and add these files below
To create the CI/CD workflow in GitHub Actions, create a folder named .github/workflows in
our application root that will contain the GitHub action workflows. You can use the code
below in the terminal as the guide to achieving this process.
cd path/to/root_repo
mkdir .github/workflows
touch .github/workflows/workflow.yml
jobs:
continuous-integration:
runs-on: ubuntu-latest
steps: # Step 1
- uses: actions/checkout@v2
# Step 2
- name: Set up Python 3.7
uses: actions/setup-python@v2
with:
python-version: 3.7
# Step 3
- name: Install dependencies
run: pip install -r requirements.txt
# Step 4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id:${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key:${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-southeast-1
# Step 5
- name: Build Application and Run unit Test
run: python app.py & pytest
continuous-deployment:
runs-on: ubuntu-latest
needs: [continuous-integration]
if: github.ref == 'refs/heads/main'
steps: # Step 1
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id:${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key:${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-southeast-1
# Step 2
- name: Create CodeDeploy Deployment
id: deploy
run: |
aws deploy create-deployment \
--application-name application-name \
--deployment-group-name AppDeploymentGroupName \
--deployment-config-name CodeDeployDefault.OneAtATime \
--github-location repository=${{ github.repository }},commitId=${{ github.sha }}
Let us break it down and have a look at each part of the workflow:
• The workflow will be triggered when commit codes pushed to the main branch
in the repository.
Continuous Integration
• This job will only run when the continuous-integration build is succeeded. This
process can be achieved by using the command needs:[continuous-
integration] after the runner has been defined.
Now, let’s push some changes to our main branch to see the result of our CI/CD workflow in
GitHub Actions. We should see something like this in our GitHub Actions for the latest build
workflow result.
Now, you can try to see the app running on the server using the EC2 public IP.