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

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: 

az --version


az account set --subscription "$(id or name)"


az group create --name $(resource group) --location westus


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.

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

pool:
   name: Hosted Ubuntu 1604


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


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)'


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


az aks get-credentials --resource-group myResourceGroup --name myAKSCluster


kubectl get nodes



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) . Verifying 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

 

 

 

 

Top