Configure CI/CD for dockerized apps using VSTS and deploy to ACS

n this blog post, we’ll discuss how to configure CI/CD for dockerized apps using Visual Studio Team Services (VSTS) and deploy to a Linux based kubernetes cluster in Azure Container Services (ACS). For building dockerized app, we’ll use .NET core and build a linux based docker image. Also we’ll be using Azure Container Services to deploy Linux based Kubernetes cluster and Azure Container Registry for providing docker registry.

Deploy Kubernetes cluster on ACS

For this, please refer to this blog post here.

Deploy Azure Container Registry

First, we need to login to the Azure Portal with our subscription details.  Once we have done that, go to More Services from left pane -> Search for container registries and then click container registries:

Search for 'container registries' from left pane
Search for ‘container registries’ from left pane

Once you click it, click +Add option and then this will ask for certain information like registry name, resource group name etc. to create registry. Below is a quick sample of details:

Provide details for the creating registry
Provide details for the creating registry

Provide details as per your environment and then click ok. Do note that you’ll need to provide a unique name for container registry and it should be in the same subscription as the Azure Container Services.

Upload source code to VSTS

We need to have source code ready so that we can upload it to VSTS. If you have the source code, you can use steps mentioned here to upload your code to VSTS. For this blog’s case, we’ll be using source code from Github repository: https://github.com/azooinmyluggage/k8s-docker-core which is available to fork or download.

You can also upload a Github repository directly into VSTS and there is no need to download it and then sync it.

Create Build Definition

  1. Go to your team project -> Build & Release -> Builds -> +New and then select empty process template.

2. Add Build process details: Provide a name for VSTS build definition and the agent details. For this, we’ll set a name as Kubernetes-ACS-CI and agent as Hosted Linux Preview:

Configure Build Process details
Configure Build Process details

3. Add Repository details: We’ll need to provide details of the VSTS repository. Here we can also choose to link Github directly. Below is a quick sample:

Configure Sources for the build
Configure Sources for the build

4. Restore .NET Core: Click add task, select .NET core task, add and set below details:

Command: restore
Project(s): **/*.csproj

Add .NET Core task and set for restore
Add .NET Core task and set for restore
  1. Build .NET Core: Click add task, select .NET core task, add and set below details:

Command: build
Project(s): **/*.csproj
Arguments: -c Release

Add .NET core task and set for build
Add .NET core task and set for build
  1. Publish .NET Core: Click add task, select .NET core task, add and set below details:

Command: publish
Check box for Publish Web Projects
Arguments: -o publish

Add .NET core task and set for publish
Add .NET core task and set for publish
  1. Build docker Image: Click add task, select docker task, add and set below details:

Action: Build an image
Docker File: **/Dockerfile
Check ‘Use Default Build Context’
Image Name: docker-dotnetcore
Check Qualify Image Name
Additional Image Tag: $(Build.BuildId)
Check ‘Include latest tag’

Add Docker task and set for build
Add Docker task and set for build
  1. Publish Docker Image: Click add task, select docker task, add and set below details:

Action: Push an image
Image Name: docker-dotnetcore
Check Qualify Image Name
Additional Image Tag: $(Build.BuildId)
Check ‘Include latest tag’

Add Docker task and set for publish
Add Docker task and set for publish
  1. Publish Artifacts: Click add task, select publish artifacts task and set below details:

Path to Publish: k8config
Artifact Name: yaml
Artifact Type: server

Add Publish Artifacts tasks
Add Publish Artifacts tasks

You can add dotnet test command to run your unit tests as a part of your build. Similarly, Team Services has support for Docker compose as well and instead of using Dockerfile, compose can be used. You can also choose to add latest tag to your images.

Create Service Endpoint for Kubernetes

Go to Settings -> Services -> new service endpoint -> kubernetes:

Create service endpoint for kubernetes
Create service endpoint for kubernetes

In the dialog box, fill the details as below:

Connection Name: can be any name of your choice
Server URL: provide details of the Azure Kubernetes cluster. You can also find this within kubectl config file
Kubeconfig: Copy-paste content of entire kubectl config file

Enable continuous integration (CI)

On the Triggers tab, enable Continuous integration (CI). This tells the system to queue a build whenever someone on your team commits or checks in new code.

Save, queue, and test the build

Save and queue the build. If everything is successful, you should see output like below:

Check build results
Check build results

Once the build is done, click the link to the completed build, click Artifacts, and then click Explore to see the files produced by the build.

Create Release definition

As a part of release we will be executing the following steps:

  1. Create a secret that cluster can use to connect to container registry
  2. Create a Kubernetes deployment and service
  3. Use the new images we built and pushed to container registry earlier to update the Kubernetes cluster

<

ol>

  • Go to your team project -> Build & Release -> Releases -> + and then select create release definition. Choose a empty one
  • Provide Release Definition name: Provide a name for release definition. For our purposes, we’ll choose name as Kubernetes-ACS-CD.
  • Configure Environment: Provide a name for the environment and environment owner name. We’ll choose name as dev-env. Leave everything else as it is.
     
    Provide details for the environment
    Provide details for the environment

  • Add Artifacts and enabled CD : Click on Add artifacts and select previously created build definition. Select default version as latest. Enable continuous deployment trigger.
  • Add Release tasks for Environment: Select environment and add 3 instances of Deploy to Kubernetes task. These will be used to run kubectl commands. For all of the 3 tasks, configure below common properties:

    Kubernetes service connection: Select name of service endpoint created earlier
    Container Services Registry: Azure Container Registry
    Azure Subscription: Select azure subscription
    Azure Container Registry: Select name of azure container registry created earlier
    Secret Name: azurecontainerreg
    Check Force Update Secret

    Secret is used by kubernetes cluster to connect to container registry. This may vary as per your source code. It is generally configured in the secret name in the Kubernetes YAML configuration file.

  • Configure Kubernetes deployment task: Configure below settings for this task:
    Command: apply
    Check Use Configuration Files
    Configuration File: $(System.DefaultWorkingDirectory)/Kubernetes-ACS-CI/yaml/deployment.yaml

    Run kubectl deployment in release definition
    Run kubectl deployment in release definition
  • Configure Kubernetes service task: Configure below settings for this task:
    Command: apply
    Check Use Configuration Files
    Configuration File: $(System.DefaultWorkingDirectory)/Kubernetes-ACS-CI/yaml/service.yaml

    Run kubectl service in release definition
    Run kubectl service in release definition
  • Configure Kubernetes update deployment task: Configure below settings for this task:
    Command: set
    Configuration File: image deployment/coreserverdeployment core-server={image:tag}

    Run update kubectl command in release definition
    Run update kubectl command in release definition
  • You can use latest tag as well or replace this command with the tag of your image. For example, in this case since we are using a private registry so the image name must be prefixed with the container registry name. And we used Build Id to tag our images too. So the image:tag value will be Your-acr-name.azurecr.io/docker-dotnetcore:$(Build.BuildId) where
    docker-dotnetcore is the image name we used in build.

    Now save and create a release. If everything goes right, you should see release results as below:

    See Release details
    See Release details

    We can now connect to kubernetes cluster and verify that images are deployed correctly.

    4 thoughts on “Configure CI/CD for dockerized apps using VSTS and deploy to ACS

    1. So on each new build you push both deployment and service yaml file in addition to updating image tag? What image tag is specified in your service.yaml and would not applying service yaml will first instruct kubernetes to run that image in service and then you update image again in `set image` instruction?

      Like

      1. Hi there!! Thanks for stopping by. Image tage in service.yaml is coming from source code. So to check that you need to check the source code. Also we would like to make sure that service is running also with same image as the cluster.

        Like

        1. I got your point now. You are correct. It runs two times. So for first time deployment, you would need only to create cluster and service. From next time onwards, you only need to update the configuration. So we need to adjust the release steps accordingly.

          Like

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s