Prerequisites And Need To Knows
Amazon Elastic Compute Cloud (EC2) can be considered as a computer where we can host our data. It’s available in different types on the basis of computing, memory, storage, and graphics. An AWS EC2 instance is like we are renting a server from AWS on an hourly basis. You will be required to have an EC2 instance configured and an active account setup.
GitLab is a web-based DevOps lifecycle tool that provides a Git-repository manager providing wiki, issue-tracking and continuous integration and deployment pipeline features, using an open-source license.
GitLab uses Docker containerization for its CI/CD pipelines. Docker provides the ability to package and run an application in a loosely isolated environment called a container.
Docker Hub is a cloud-based repository in which Docker users and partners create, test, store and distribute container images. Through Docker Hub, a user can access public, open source image repositories, as well as use a space to create their own private repositories, automated build functions, webhooks and work groups.
We will also be leveraging the GitFlow Branching model for reference: https://nvie.com/posts/a-successful-git-branching-model/
Introduction
The goal of this tutorial is to teach new GitLab users how to create your first CI/CD pipeline for a “Hello World” app which will be tested, and then deployed to a development environment. If the deployment is successful, it will then be merged to the Master Branch, and deployed to a Production server. We will be using SSH keys to log into an EC2 instance. This can be a little tricky in GitLab since we will be using containers.
Create A New Project & Repository
First let’s start by creating our new project. Under the “Projects” tab click “New Project”
Choose “Create blank project”
Then fill in your project details and click “Create project”
Next, we will be adding a couple of files to your new project’s repository. Navigate to the “Hello World” project. Click the “Clone” tab. And clone your new repo to your local environment.
Or use the built-in file editor. Then copy & paste the code below and commit. This is a simple Hello world application that will be displayed once the sight is working.
Index.html <!DOCTYPE html> <html> <head> <title>Hello World!</title> </head> <body> <h1>Hello World!</h1> </body> </html>
We’re now going to build our “.gitlab-ci.yml” file. The “.gitlab-ci.yml” file is a YAML file that you create on your project’s root. This file automatically runs whenever you push a commit to the server. This triggers a notification to the runner, and then it processes the series of tasks you specified.
Note:
Since we’re using containers, the tasks will always start with a clean image state. This means that all the modifications that you do inside the “.gitlab-ci.yml” will be reverted each time you push a commit to the server.
Now open up your new “gitlab-ci.yml” file. We will be using the “monachus/hugo” from Docker Hub. I like using this image because it’s intended uses are specifically for GitLab CI/CD pipelines.
image: monachus/hugo:latest
This section of code will be used to setup our separate deployment stages. Stages are a series of steps that your code will follow order. GitLab also allows you to define any number of stages with any name that you’d like. You do so by specifying under the Stage function in order of which you’d like the build process to run.
stages: - test - deploy_develop
My first stage is called “test”. But it doesn’t really matter what you name these stages. Just make sure they make sense in the context. The goal of this first stage is to simply curl the IP address of my environment.
test: stage: test script: - echo "Running tests" - curl $TEST_IP #Use this to prove fail test
You may have noticed I am using an environment variable $TEST_IP. For security, and usability purposes. It is always recommended to leverage them. You can do so by navigating to your “Settings” drop down tab and choosing “CI/CD” and scrolling down to the “Variables” section and choosing “Expand”.
When I first sought out to deploy code using the standard SysAdmin tools such as leveraging ssh keys and Rsync (utility used for efficiently transferring and synchronizing files between a computer and an external device or across networked computers). I found it quite difficult due to the nature of containers. I mentioned this earlier but whenever you deploy using GitLab you’re using a fresh container. The trick is to add your private key to your Environment variables and have the agent configure them at the beginning of each build.
deploy_develop: stage: deploy_develop script: - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y && apt-get --yes install git ssh )' - mkdir -p ~/.ssh # Run ssh-agent (inside the build environment) - eval $(ssh-agent -s) - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' # Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store #- ssh-add <(echo "$SSH_PRIVATE_KEY2" | base64 -d) - ssh-add <(echo "$SSH_PRIVATE_KEY2")
After that I am simply removing any previous code, cloning the latest version of the develop branch and then restarting the Apache server.
- ssh -o StrictHostKeyChecking=no ubuntu@$DEVELOP "rm -rf hello-world && git clone --single-branch --branch develop $GIT_ACCESS2 && sudo rsync -avz --delete hello-world/index.html /var/www/html/index.html && sudo systemctl reload apache2" environment: name: staging only: - develop
At this point we have now successfully deployed our “Hello World” app to the web server. Which can be seen in the CI/CD Pipelines section of Gitlab.
If you click on the “passed” button you will then see that both the test and deployment sections of the pipelines ran.
Now open up your “.gitlab-ci.yml” and lets update the stages section to include the master branch stage.
stages: - test - deploy_develop - deploy_master
With this section of the code we will be deploying to the Production environment leveraging the master branch stage. This is configured the same as Develop branch so we simply need to add in the new environment variables “SSH_PRIVATE_KEY” and “PRODUCTION” url.
deploy_master: stage: deploy_master script: - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y && apt-get --yes install git ssh )' - mkdir -p ~/.ssh # Run ssh-agent (inside the build environment) - eval $(ssh-agent -s) - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' # Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store - ssh-add <(echo "$SSH_PRIVATE_KEY") - ssh -o StrictHostKeyChecking=no ubuntu@$PRODUCTION "rm -rf hello-world && git clone --single-branch --branch master $GIT_ACCESS && sudo rsync -avz --delete hello-world/index.html /var/www/html/index.html && sudo systemctl reload apache2" environment: name: production only: - master
After we’re done committing the code above to the develop branch we’re now going to merge the code from the develop branch into the master branch. This will trigger the new deployment stage “deploy_master”. Click on “Merge Requests” then “New merge requests”. Then Select “develop” as Source and “master” as destination.
After successfully merging our latest code into the “master” branch you can see the out-come in the CI/CD pipelines section of Gitlab.
Conclusion
The items covered here will have given you the necessary skills to deploy a basic web server to an EC2 instance, setup SSH keys, create tests, merge between the develop and master branches for a basic Gitflow CI/CD pipeline. GitLab is capable of having great control over automating your codebases by building and publishing Docker images and leveraging third-party tools. Thank you for reading this tutorial and I hope you found it useful!
Who am I?
My name is Keith. Over the years I have become a very experienced, passionate DevOps Engineer who has grown enormously in recent years, partly because DevOps has become increasingly important, but mainly because of my personal drive to further develop within this field.
I am a native English speaker from Canada (with an Irish passport) who has recently immigrated to the Netherlands.
See all Techspire blogs?
See all Techspire news?
Follow our LinkedIn page: Techspire LinkedIn