Azure DevOps: How to Build, Test And Deploy to Azure Kubernetes Service
I have been using Azure Devops for a while. Like most of the cloud products out there this is one which gets constant refresh. My plan is to document the steps for building, testing and deploying an app to Azure Kubernetes Service using Azure Devops. So let's start.
- Github or Bitbucket
- Azure Kubernetes Service
- Azure Container Registry
- Soap UI Pro (you need Pro edition for CICD).
- Azure Devops
- Azure Devops Agent hosted on your Windows VM. (needed for SoapUI Pro)
1) My code & Dockerfile
What I got is a simple .NET web api project. And below is my Dockerfile.
2) My Github link
3) Azure Container Registry
This is where we push our Docker image to. Below is a screenshot of Azure Container Registry from Azure Portal.
Azure Kubernetes Service.
This is the Azure managed Kubernetes Service. This is where we will deploy the containers into.
Now that we have talked about the prerequisite required we will get ritht to it. We will walk through how we configure Azure Devops to build and push Docker image to registry and then deploying that image to AKS and running integration tests against it using SoapUI Pro
So we will create 2 pipelines in Azure Devops. (Details below).
- The first one is build pipeline
- and the second pipeline is release pipeline.
At the end of build pipeline the expected output is to have a new Docker Image in Azure Contaoner registry. This will be the artifact we will deploying to AKS as part of release pipeline.
Below is my yaml file.
# Unit the dotnet project. xUnit and NSubtitute
# Build and push an image to Azure Container Registry
# Now we get the tag of the published id and update the k8 Deployment yaml image
- repo: self
# Container registry service connection established during pipeline creation
# Agent VM image name
- stage: UnitTestBuildAndPublish
displayName: Unit Test then Build and Push Docket to Register then Publish of release pipeline
- job: UnitTest
displayName: Running Unit tests for the Hospital Microservice
- task: DotNetCoreCLI@2
- job: Build
displayName: Build and push to container registry
- task: Docker@2
displayName: Build and push an image to container registry
- job: PreReleasePrepForhospitalMicroservice
displayName: Pre Release Preparation (Bash build id and Publish for Release pipeline)
- task: Bash@3
# Write your commands here
echo "$value" > '$(Build.SourcesDirectory)/hospital_build.yaml'
echo 'after creation of hospital'
- task: PublishPipelineArtifact@1
Before talking about what is happening in above pipeliene; it maybe better to look at Azure Pipeline hierachy first.
- stage: A
- job: A1
- bash: echo "Hello world"
- job: A2
- bash: echo "A"
- stage: B
- job: B1
- bash: echo "B"
- job: B2
- bash: echo "A"
So the hierarchy is like above. You can have a list of stages which is the top level. Underneath it you can have a list of jobs which can further be broken down into steps and then steps into tasks. Also you can assign the kind of Build agent you want at job level. So you can have one job using Windows 10 agent another using Ubuntu.
OK now that the pipeline hierarchy is clear; let's go back to the original build pipeline I have above.
In that we have only 1 Stage called UnitTestBuildAndPublish.
There are 3 jobs within it.
Variables in above build pipeline.
- Job1 called UnitTest
- Job2 called Build There is a task within this Job called Docker@2 which is for Build and pushing to Azure Container Registry.
- Job3 called PreReleasePrepForhospitalMicroservice. There are two tasks withing this. In the first task I use the bash command to get hold of the K8 yaml file and replace the placeholder with the imagetag. Then in the second task I use the PublishPipelineArtifact. This is kind of pushing the artifact so i can get hold of this in the release pipeline. There I need info on the Imagetag that was pushed to Azure Container Registry.(https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/publish-pipeline-artifact?view=azure-devops)
On whether the jobs runs in sequence or in parallel. By default they run parallel. But in above yaml file you may notice the "dependsOn" tag under each job. You will note that Build job "dependsOn" Unit test project to complete. And Prepublish job "dependsOn" Build Job. SO in essense they are executed in an sequential manner.
- Sequence: UnitTest > Build(&Push Docker Image to Registry > Prepublish
- dockerRegistryServiceConnection: This is the Azure Container Registry connection string. This is preconfigured.
- containerRegistry: 'dockerstore' is the ACR service name,
- imageRepository: This is image repositor (or microservice name.
- dockerfilePath: Relative path to the Dockerfile in Github
- tag: Docker Image tag. We are using the BuildId and the Github Commitid for traceablity from Docker Image to Github code.
Below is the screenshot of my release pipeline tasks page. As you can see I am using two Agents.
- Hosted Agent running Ubuntu 18.04
- Custom Agent on Windows 10 VM
SoapUI Pro requires a Windows 10 OS to run it's tests.
Download Pipeline Artifact (running on Ubuntu agent)
So first step is to Download the Pipeline Artifact. We need this for K8 yaml file. In the Build pipleine we have updated the ##BuildID## placeholder with the real tag of the image that was pushed to ACR.
Kubectl Apply (running on Ubuntu agent)
We will use this task to apply the above yaml file against the "NM" namespace of AKS. The namespace is a way to logically have multpile environments in Kubernetes. The above yaml shows that the pods and services will be deployed to "NM" namespace.
The above command confirms that the services and pods are deployed in that namespace.
Bash Script Task (running on Ubuntu agent)
This is more of a hack I put in there. This task just sleeps and holds the pipeline for few seconds. I wanted to ensure that the Pods are given enough time to be up and running. This is required because if the Pods are not Up SoapUI Pro will fail all the tests. Which is not the right thing.
Azure SQL Dacpac Task (running on Ubuntu agent)
This is for database deployment. I am not doing anything currently for this project. That is why it is in disabled state. But this is the task you would use to run the DDL and DML statements against your Azure SQL.
API Management - Create/Update API (running on Windows 10 agent)
This is task, I got from the market lace which helps me deploying API definitions to Azure API Management. It accepts OAS 3.0 defintion that I build using Swagger editor. Below is my API definition.
# Added by API Auto Mocking Plugin
- description: SwaggerHub API Auto Mocking
description: Demo API on Hospital.
name: Apache 2.0
- name: Hospital
description: Hospital related matters
summary: Finds hospital by id
By passing in the valid id, you can search for
the hospial details in the database
- in: path
description: pass the hospitalId for looking up the database
description: search result matching criteria
description: bad input parameter
summary: deletes a hospital from list
description: Deletes a hospital from list
- name: hospitalId
description: Hospital id to delete
description: "Invalid ID supplied"
description: "Hospital not found"
summary: adds a hospital to the list
description: Adds a hospital to the list
- name: Authorization
description: hospital added
description: invalid input, object invalid
description: hospital already exists
description: Add Hospital to list
summary: Updates a hospital in the list
description: Updates a hospital to the list
description: hospital updated
description: invalid input, object invalid
description: hospital does not exists
description: Updates Hospital in the list
example: Epidemic Diseases Hospial
SoapUI Pro for Azure DevOps (running on Win10 agent)
After all of the above steps are completed; it is time to do the integration tests. And make sure everything is complying. SLA will be met. We didn't break anything.
Once the tests are completed SoapUI exports some of the reports to Azure Devops. Below is one such report.
Once all the test passes; we can promote the deployments to higher environments. This too can be automated nicely in Azure Devops. Each environment is called stages and we can add Manual Approver too as part of environment promotion. Below is a screenshot of the stages graphic that Azure Devops provide.
So that's it. This is my github page: https://github.com/mohammednaseem/aksistio-hospital
if you run into trouble with Azure Devops let me know.
Subscribe to get your daily round-up of top tech stories!