Setting up a CI-CD Pipeline Using Azure DevOps
Tags: azureapril, kubernetes, docker, devops
Published: 2021-04-11 18:52:04

Continuous Integration is the process of merging all code changes into a central repository. Continuous Deployment on the other hand is the practice of automatically deploying code changes that have passed predefined checks to a specified environment. It uses a set of automated tools to run tests that ensure the codebase is stable and deployable. This approach helps deliver faster and efficient deployments.

An azure pipeline is a fantastic tool for setting up CICD pipelines; in this article, I am going to be walking through how to set up a CI-CD pipeline using Azure DevOps Pipelines. This is a follow-up to my previous article on [Deploying An Asp.Net WebApi and MySql DataBase Container to Azure Kubernetes Service](https://dev.to/gbengelebs/deploying-an-asp-net-webapi-and-mysql-database-container-to-azure-kubernetes-service-3ca). I will be referring to some information discussed in that article. If you are already familiar with Azure Kubernetes deployments you can continue.

##Prerequisites
1. VSCODE. Download [here](https://azure.microsoft.com/en-us/services/devops/pipelines/)
2. Azure DevOps [Login](https://azure.microsoft.com/en-us/services/devops/pipelines/)
3. An Azure account. You can create it for free [here](https://portal.azure.com/free). 
_Ps you get 200dollars free Azure credits and 12month's pay as you go._
4. Docker [docker](https://docs.docker.com/get-docker/)
5. VSCODE [vscode](https://code.visualstudio.com/download)

In my previous article, I discussed how to deploy a.NetCore web API and MySQL DB to azure Kubernetes service. I will be going one step further by automating the deployment process using an azure pipeline. The tool checks for changes in the git repository and automates the build and deployment process. I could also add a series of checks within the pipelines like approvals and tests. But for this article,I will just be setting up a basic build and deploy CI-CD pipeline.
![Azure Pipeline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/or4tcgop7thnru2mz5e6.jpeg)

**1. Download the source code from GitHub** [here](https://github.com/GbengaElebsDev/AksTutorial.git)
**2. Create a repository for the project and push your code to GitHub**
**3. If you followed the previous article revert the manual steps we did in the previous article by deleting the services and pod deployments and the images we pushed to Azure container registry.**. 

- Deleting Container Images
To delete a container image login to Azure portal- > container registry -> repositories click on the three ellipses.
![Deleting Images](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4jfb23omg3daq7kb1ohk.png)
- Deleting Kubernetes Services and Pods
Run this command to get your current Kubernetes context
```
$ kubectl config get-contexts
```
Ensure you are in your azure Kubernetes context
Delete all the resources in that context
```
$ kubectl delete daemonsets,replicasets,services,deployments,pods,rc,pv,pvc --all
```
Check if it has been deleted
```
$ kubectl get pods
                                                               
No resources found in the default namespace.
```
**4. The deployment YAML files are in a folder called manifest**
- This is to ensure that the pipeline can refer to all the deployments in one folder.

**5. Login to Azure Pipelines**
[Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/)
- Go to pipelines -> Create Pipeline
![Azure Pipelines](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b5n4o5ofzli3ggudlpt8.png)
- Connect to your GitHub and Authenticate
- Select your GitHub Project
- Select Deploy to Azure Kubernetes Service
- Login to your azure portal from the app
- Fill in your details like container registry and image name
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aievc8253o2oza72zzp7.png)
- A YAML file will be automatically generated.
- Edit the contents of the YAML file with this gist
**Remember to replace the environment variables with your own details and credentials**
{% gist https://gist.github.com/GbengaElebs/3ff0b801e1ca88ac430c268d5253dd9d %}

### Reviewing the YAML file

**trigger**: This command tells the pipeline to listen to changes pushed to the main branch.

**variables**: To store reusable entries things like the **containerRegistry** and secrets that you want to reuse in multiple places in the pipeline.
I define a **mysqltag** to specify the MySQL version I want to be created.

###Build Stage
**Stages**: are the major divisions in a pipeline: "build this app", "run these tests", and "deploy to pre-production" are good examples of stages. In our case, we have only "build" and "deploy".

**Job**: A deployment job is a collection of steps that are run sequentially against the environment.

**pool**- is the server that your azure pipeline would be carrying out the operation. By default Azure assigns an agent for each pipeline. But you can create yours. In my case I created an agent called "ubuntu-latest".

**steps**- The build stage has a task of **Docker@2** which will perform 2 tasks (Build & Push).
This will build the service and then push it to my Azure container registry using the environment variables as defined. 

- We add two builds and deploy steps because we have two images we will like to build. The SQL and the API image

__stages have jobs-> each job has a step -> each step has a task assigned to it__.

**publish**. This command tells the pipeline to find the manifest folder, create an artifact in the pipeline called manifest using the resources in the folder.

### Deploy Stage
**depends on** -It depends on the build stage. This means the build stage has to be completed before this can run.
**strategy** - How you want to deploy. **Run once** means all the steps run sequentially. 

In the task section, there is a task: **KubernetesManifest@0**
Kubernetes manifest task command tells the pipeline:
- To download the files from the manifest artifact  
- Apply the manifest artifact to the Kubernetes cluster
- Deploy the artifact to the Kubernetes cluster

As with the build section, we define two deployment tasks because we have two images.

Hit save and run and commit directly to the master branch. This will store your YAML file in your GitHub repo and it can be modified as needed.

You should see this stage stating that the build has begun
![BuildStage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/os6hrnbw2vg305lfl7z3.png)
-------------------------ERROR---------------------------
**This agent request is not running because you have reached the maximum number of requests that can run for parallelism type 'Microsoft-hosted Private'. Current position in queue: 1**
-------------------------ERROR---------------------------
You will probably run into this error and the root cause of the issue is that the pipeline Microsoft-hosted agent for public and private projects in new organizations on Azure DevOps has been restricted in the latest update. The summary of this is that Microsoft has temporarily restricted agents from running your jobs.

###To resolve this for a private project
Private Project:

You could send an email to azpipelines-freetier@microsoft.com in order to get your free tier.

- Your name
- Name of the Azure DevOps organization
- Private Project:

###To resolve this for a public project
You could send an email to azpipelines-ossgrant@microsoft.com in order to get your free tier.

- Your name
- Azure DevOps organization for which you are requesting the free grant
- Links to the repositories that you plan to build
- Brief description of your project.

If you are impatient like moi. Watch this
{% youtube psa8xfJ0-zI %}

- Self Hosted private Agent on Linux (Ubuntu) for Azure Pipelines on how to create your own self-hosted agents and link them to run your pipelines.

- After you create the agent. 
- Add it to the project
![Create Agent](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4sp4b6vdkcth945ntdzr.png)
- Copy the name and edit this section with your pool name so that agent runs it.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e85rbnvqasofcazfmp4o.png)
- Install docker on your self hosted agent using this the first step in this [How To Install and Use Docker on Ubuntu 18.04
](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04)

- cd into your agent and restart the agent.

As you can see all our Build processes are running similar to what we did before. But right now everything is running automatically in the Pipeline. Once there is a push to the main branch the pipeline triggers a build and it is deployed.

![BuildStage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/os6hrnbw2vg305lfl7z3.png)

![Deploy Stage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3aukzi4ei2c6uu3bsxlm.png)

- The build and deploy stages have been completed.
![build and Deploy Completed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzfrfvavoyp6g91en28q.png)

- Go to pipelines -> Runs -> View Environment -> Resources ->Services

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvzrv33jg73nn8lljanp.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ashxx9m4dvkk20oxmgsq.png)
- Navigate through the deployment and explore the resources created.
- Select the Test-API service External IP
Copy the external IP and navigate to the URL**
(http://external-ip:8080/swagger/index.html)
Mine is (http://20.62.158.83:8080/swagger/index.html). Test the API deployment using the swagger page as shown. Our containerized API is now running inside the Azure Kubernetes service and exposed to the internet via the Load Balancer Service. 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujvq49qqnzfzvhtzo7cc.png)

- We have successfully set up an azure pipeline to build and deploy our containerized application to both Azure Container Registry and Azure Kubernetes Service.

## Add The Azure Pipeline built successfully badge to the git repo 

-In your Azure DevOps. Select the pipeline -> Runs -> Click on the 3 Elipses
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zlpltf373qbuud584q1w.png)
- Select Status Badge -> Copy the Sample markdown.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zb4w9qgpixupa0a9stwg.png)
- Create a README.md file in your GitHub repo and paste the markdown there.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nvw3g42jfolueopviav1.png)


Follow me here and across my social media for more content like this [Twitter](https://twitter.com/ElegberunDaniel?s=09) [Linkedin](https://www.linkedin.com/in/olugbenga-elegberun/)