Set Up and Deploy to Kubernetes Using Azure DevOps (CI/CD)
This article demonstrates how to build docker images, push to a container registry, and deploy that registry into Kubernetes.
Prerequisites
Azure Subscription credentials, Create an Azure container registry (ACR).
AKS Managed cluster.
Create an Azure Container Registry (ACR) Using CLI
The Azure container registry is a private Docker registry in Azure that stores Docker container images and uses Docker commands to push a container image into a registry. In the end, it pulls and runs the image from the registry. In order to use this tool, you need to:
Install Azure command-line interface.
Check the version of azure-CLI version with the following command.
az --version
- Use the following command to set the subscription id or name of the subscription.
az account set --subscription "$(id or name)"
Create a resource group.
az group create --name $(resource group) --location westus
- Create a container registry by using the following command:
az acr create --resource-group (myResourceGroup) --name myContainerRegistry007 --sku Basic
This command gives output in a JSON format and takes note of the login server name, which is a container registry name.
Before pulling and pushing images into the ACR, you need to log in to ACR by using the following command.
az acr login --name <acrName>
Continuous Integration (CI)
Use the azure-pipelines.yml, shown in full at the end of this post at the root of your repository and adjust variables to work for your needs. This .yaml file will create a build pipeline for your project. Modify this file and commit it back to your repository so that your build/deploy processes are also treated as code.
Follow all instructions in "Introduction to Azure Pipelines" to create a build pipeline to build docker images for .NET or NodeJS applications.
Steps
- Azure pipelines have an option to build and deploy using Microsoft-hosted agents. Each time you build or release a pipeline, you get a fresh virtual machine (VM) for the build.
- If Microsoft-hosted agents don't work, use a self-hosted agent that will act as a system host.
pool:
name: Hosted Ubuntu 1604
Build, push, or run a container Docker application. The task can be used with Docker or Azure Container registry.
Build Container Image Using docker-compose.yaml
This task will build the Docker image from the docker-compose file mentioned the ACR and subscription details.
steps:
- task: DockerCompose@0
displayName: 'Build services'
inputs:
azureSubscription: '(xxxx-xxxx-xxx-xxx)'
azureContainerRegistry: '{"loginServer":"iotci.azurecr.io", "id" : "/subscriptions/a476/resourceGroups/xxxaa/providers/Microsoft.ContainerRegistry/registries/XXXX"}'
dockerComposeFile: 'docker-compose.yml'
action: 'Build services'
additionalImageTags: '$(Build.BuildId)'
includeLatestTag: true
- Push a container image to Azure container registry(ACR)
steps:
- task: DockerCompose@0
displayName: 'Push services'
inputs:
azureSubscription: 'SIOT-CI-01 (XXXX-XXXX-XXX-XXX-XXX)'
azureContainerRegistry: '{"loginServer":"iotci.azurecr.io", "id" : "/subscriptions/XXXX-XXX-XXX-XXX/resourceGroups/iotcicd/providers/Microsoft.ContainerRegistry/registries/iotcicd9fa3"}'
dockerComposeFile: 'docker-compose.yml'
action: 'Push services'
additionalImageTags: '$(Build.BuildId)'
Use of this task in the build pipeline to publish the build artifacts to the Azure pipelines file share. Artifacts of the build store it in the Azure DevOps server.
steps:
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: drop'
Release Pipeline (CD)
Before creating a release pipeline, you need to create an AKS (Azure Kubernetes Cluster) manually by using Azure CLI or Azure Portal. AKS is a managed Kubernetes cluster used to quickly deploy and manage the cluster.
Create a Kubernetes Cluster
Use the following command to create an AKS cluster with one node.
az aks create \
--resource-group myResourceGroup \
--name myAKSCluster \
--node-count 1 \
--enable-addons monitoring \
--generate-ssh-keys
- Manage kubernetes cluster with the kubectl command line; this will communicate with the kubernetes API cluster.
- Use the following command to download credentials and configure the Kubernetes CLI.
az aks get-credentials --resource-group myResourceGroup --name myAKSCluster
- Verify the connection to the cluster; use the kubectl get command to list the nodes
kubectl get nodes
- Make sure that status is Ready
Run the Application
Kubernetes describes a desired state of the cluster and what container images to run. A manifest is used to create all objects needed; it can create a deployment, service, ingress, config map. Create a namespace with the following command.
kubectl create ns <namespace-name>
Create a file name with azure-svc.yaml, azure-dep.yaml and load balancer for service to expose the outside world. The Yaml definition will use these manifest files to deploy objects into a cluster.
apiVersion: apps/v1
kind: Deployment
metadata:
name: azure-vote-back
spec:
replicas: 1
selector:
matchLabels:
app: azure-vote-back
template:
metadata:
labels:
app: azure-vote-back
spec:
nodeSelector:
"beta.kubernetes.io/os": linux
containers:
- name: azure-vote-back
image: redis
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
ports:
- containerPort: 6379
name: redis
---
apiVersion: v1
kind: Service
metadata:
name: azure-vote-back
spec:
ports:
- port: 6379
selector:
app: azure-vote-back
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: azure-vote-front
spec:
replicas: 1
selector:
matchLabels:
app: azure-vote-front
template:
metadata:
labels:
app: azure-vote-front
spec:
nodeSelector:
"beta.kubernetes.io/os": linux
containers:
- name: azure-vote-front
image: microsoft/azure-vote-front:v1
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
ports:
- containerPort: 80
env:
- name: REDIS
value: "azure-vote-back"
---
apiVersion: v1
kind: Service
metadata:
name: azure-vote-front
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: azure-vote-front
Deploy the application in AKS by using Kubectl to apply the following task.
variables:
cluster_rg: 'DefaultResourceGroup-EUS'
kube_cluster: 'test'
steps:
- task: Kubernetes@1
displayName: 'kubectl apply'
inputs:
connectionType: 'Azure Resource Manager'
azureSubscriptionEndpoint:
azureResourceGroup: '$(cluster_rg)'
kubernetesCluster: '$(kube_cluster)'
command: apply
useConfigurationFile: true
configuration: 'c:/azure.yaml'
secretType: generic
secretName: 'acr-authentication'
versionSpec: 1.8.1
Verify each task logs for Build (CI) and Release pipeline(CD) .
An azure-pipelines.yml is shown here.
# Build(CI) pipeline to build docker image and push into a Container,nodejs application code.
pool:
vmImage: 'Ubuntu 16.04'
steps:
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install Node.js'
- script: |
cd result
npm install
npm run build
displayName: 'npm install and build'
steps:
- task: DockerCompose@0
displayName: 'Build services'
inputs:
azureSubscription: '(xxxx-xxxx-xxx-xxx)'
azureContainerRegistry: '{"loginServer":"iotci.azurecr.io", "id" : "/subscriptions/a476/resourceGroups/xxxaa/providers/Microsoft.ContainerRegistry/registries/XXXX"}'
dockerComposeFile: 'docker-compose.yml'
action: 'Build services'
additionalImageTags: '$(Build.BuildId)'
includeLatestTag: true
steps:
- task: DockerCompose@0
displayName: 'Push services'
inputs:
azureSubscription: 'IoT (XXXX-XXXX-XXX-XXX-XXX)'
azureContainerRegistry: '{"loginServer":"iotci.azurecr.io", "id" : "/subscriptions/XXXX-XXX-XXX-XXX/resourceGroups/iotcicd/providers/Microsoft.ContainerRegistry/registries/iotcicd9fa3"}'
dockerComposeFile: 'docker-compose.yml'
action: 'Push services'
steps:
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: drop'
#Release(CD) pipeline to deploy into a nodejs application.
az aks get-credentials --resource-group $(cluster_rg) --name $(kube_cluster)
variables:
cluster_rg: 'DefaultResourceGroup-EUS'
kube_cluster: 'test'
steps:
- task: Kubernetes@1
displayName: 'kubectl apply'
inputs:
connectionType: 'Azure Resource Manager'
azureSubscriptionEndpoint: 'Subscription name (XXXX-XXXX-XXXX-XXXX)'
azureResourceGroup: '$(cluster_rg)'
kubernetesCluster: '$(kube_cluster)'
command: apply
useConfigurationFile: true
configuration: 'c:/test.yaml'
secretType: generic
secretName: 'authenticate'
versionSpec: 1.8.1