In this article I will describe how to use Azure DevOps to:
- build a docker image of your application
- push this image to Azure Container Register
- release your kubernetes deployment to Azure Kubernetes Service
If you don't have a basic knowledge about docker, kubernetes and Azure CLI please check my previous article Deploying .NET Core Application to Azure Kubernetes Cluster for Less Than 5$.
- you save a lot oh time
- you eliminate bugs that happens when you do the same job again and again
- you deliver your product more often and much faster
Azure DevOps can help you with that.
Azure DevOps can automate your Continuous Integration and Delivery process. It can get access to you git repository (Azure Repos Git, GitHub and other git repositories). It can automatically react on what you are doing with your repository:
- run tests when you create a pull request
- build a docker image when you merge your pull request to selected branch and push it to Azure Container Register (ACR)
- when everything is ok it can apply changes to your Azure Kubernetes Service (AKS)
You can use docker images from your ACR to create as many release configuration as you need. For example one for dev, test, stage and production environment and decide when you want to release them.
If you don't have your Azure Container Register and Azure Kubernetes Service yet you can use necessary Azure CLI commands from my previous article:
#Create temp variables:
$projectName="shkube"
$argName=$projectName+"RG"
$acrName=$projectName+"ACR"
$aksName=$projectName+"AKS"
$region="northeurope"
We are going to use them to create ACR and AKS in Azure Resource Group (ARG).
Login to azure:
az login
And lets create everyting you will need later:
# Create resource group
az group create -n $argName -l $region
# Create azure container register
az acr create -n $acrName -g $argName --sku standard
# Create azure kubernetes service
az aks create -n $aksName -g $argName --generate-ssh-keys --node-count 1 --node-vm-size Standard_B2s --enable-addons monitoring
# Get AKS Client Id and AKS Id
$CLIENT_ID=$(az aks show -g $argName -n $aksName --query "servicePrincipalProfile.clientId" --output tsv)
$ACR_ID=az acr show --name $acrName --resource-group $argName --query "id" --output tsv
# Give AKS access to ACR
az role assignment create --assignee $CLIENT_ID --role acrpull --scope $ACR_ID
# Get credential to your AKS
az aks get-credentials -g $argName -n $aksName
Now we can begin to work with your CI/CD
If you are reading this article then you probably already have your application up and running inside Docker Container or even Kubernetes but if not then you need three additional files to do that:
- Dockerfile
- docker-compose.yml
- deployment.yml
If you don't have them you can use mine from this project.
Go to your azure devops website and create new project
Create a new pipeline
I'm going to use classic editor and select github repository so pick your repository and a branch which you are going to use to build a container from
If you see Docker Compose on a list you can use it but I will pick Empty job
Use +
button to add first step of your pipeline! In this step we will build a new docker image with your application.
We will use Docker Compose
step that will use your docker-compose.yml
file.
Now there are few things to do:
- select your Azure Subscription
- select Azure Container Register
- put a path to your
docker-compose.yml
file - change Action to
Build service image
- and put
$(Build.BuildId)
as Additional Image Tags (without this, we won't be able to determinate which image version to deploy later)
Great! Now we have to push this image to our ACR. Let's add second Docker Compose
step.
The only difference is the Action field: now pick Push service image
The third step is optional but recommended. Locking an image version or a repository so that it can't be deleted or updated.
As before add Docker Compose
step. The only difference is the Action field. Now pick Lock image service
.
Output Docker Compose File
will fill automatically.
There are two more steps to add.
Add Copy Files
step.
- In
Contents
put a name or path to yourdeployment.yml
file (we will use this file during Release) - In
Target folder
put$(Build.ArtifactStagingDirectory)
And Publish build artifacts
step. Leave it as is.
We will use Artifact name
during Release
If you want your pipeline to trigger automatically after each merge go to Triggers
tab and select Enable continuous integration
Click on Build pipeline
and change Agent Specification
to use Ubuntu (if you prefer Windows then you will have to change all paths to match Windows)
Now we can test our pipeline! Hit Save & queue
.
Go to Pipelines, select the pipeline you have created and pick the newest Run. If it shines green then everything is ok.
If not then you have to check which step want wrong and fix it.
Congratulations! Half of our plan is ready. We have an image, the image is available on your ACR. Let's check it out. Please login to your Azure Portal and check if your image is there (please notify that our image is also tagged by build number).
Now we can configure new Release
Go to Release
tab and create a new one
Similarly to pipeline configuration I have selected Empty job
Now click on Add an artifact
, select your project and source.
Go to Tasks
tab
Add Kubectl
task
- change
Service connection type
- select
Azure subscription
- select
resource group
- select
Kubernetes cluster
- pick
Apply
Command - check
Use configuration
And pick your deployment.yml
file in File path
Expand Advance
and check Version spec
that match to the version of Kubernetes on Azure.
You can use this command to check the current one:
az aks show -g $argName -n $aksName --output table
Add new Kubectl
step (we will have to replace the name of your docker image to match the one on ACR).
Set everything as before but chance Command
to set
and Arguments
input to
image deployments/shkube-deployment shkube=shkubeacr.azurecr.io/shkube:$(Build.BuildId)
This command is tricky, we have to navigate by name
to deployment and then to container image.
We are specifying the image version here, this is better practise then just use :latest
because
latest image is always pointing to the newest one (that is created after each merge).
It could be ok for your dev environment but not for sure for production one.
Click Save
and Create release
(top right) and go to Release to check if everything shines green.
Ok let's go to console and check your services and pods
And navigate to IP of your service to check if it is up and running.
It is working! Congratulation! Your Continuous Integration and Delivery setup is ready. You can now use your pipeline to create another Release
configuration for your test, stage or production environment.