Building a Kubernetes deployment pipeline for Microsoft Bot Framework — Part 1

In my previous post, I discussed the development of a chat bot for theme park information. All the code for which can be found over on my GitHub:
Up until now the bot had been running locally on my machine. The next step was to host it in order that people can actually start chatting with it.
There are different ways I could have hosted the bot but I decided to go with Kubernetes. The reason being is that I have wanted to learn Kubernetes for some time now, but just didn’t have a suitable project to take the plunge.
This and a follow up post will detail how I went about setting up an end to end build and deployment pipeline for the theme park bot.
Part 1 details setting up the Kubernetes cluster and supporting infrastructure in Azure. All the code presented is available on my GitHub at: themeparks-infrastructure.
Tools
There are a number of different tools I used in setting up the deployment pipeline, each described below.
Azure
Azure is Microsoft’s cloud platform which I am using to host all the infrastructure for the bot.
I decided to use Azure because I already have a lot of pre-existing knowledge of building and deploying applications on Azure. This meant that I could then focus more on learning Kubernetes, rather than cloud platform’s specifics.
Azure CLI
Azure CLI is the command-line tool for managing Azure resources. This is used by the build and deployment scripts to authenticate with Azure and deploy resources.
I chose Azure CLI since it is cross platform allowing me to develop on my Windows machine and yet also work on Travis CI’s Linux machines.
Azure Resource Manager templates
Azure Resource Manager (ARM) templates allow you to define Azure resources using JSON.
Using this means I could define all my infrastructure as code and store in source control, plus Azure CLI integrates nicely with it.
Travis CI
Travis CI is a Continuous Integration tool for GitHub, which I use to build and deploy my GitHub projects.
I chose Travis CI after I read this GitHub blog post. This post showed that the majority of projects on GitHub that use CI, utilise Travis CI. I couldn’t argue with that.
Helm
Helm is a package manager for Kubernetes which I am using to:
- Provide a templating language for Kubernetes resources. This allows me to easily change the tag of a container image during deployment and similarly, pass in secret values.
- Define dependencies of the bot such NGINX and Redis. These are available as Helm charts that have already been configured with best practices in mind; which means I don’t have to have in depth knowledge about them. These dependencies get automatically deployed along side my bot.
kubectl
kubectl is the command-line tool for deploying and managing applications on Kubernetes. This is a dependency for Helm.
Defining the Azure resources
The following ARM template defines the individual Azure resources which are used to host and by the bot; these are:
- Azure Container Service (AKS) — A managed Kubernetes cluster.
- Application Insights — Logging and analytics for the bot.
- Bot Channels Registration – a registration to allow communication with the bot through channels such as Facebook messenger.
- LUIS — Language understanding service which is used by the bot to understand the intent of a user’s message.
- Storage Account — A state store for the bot.
Whilst creating the ARM template I wanted to know as soon as possible if I had defined it incorrectly. Azure CLI provides a mechanism to validate whether an ARM template together with its parameters is valid, without actually deploying it.
So I created this script which I could use as part of the build:
Now that I had a way to validate the template, I needed to be able to deploy it. Similarly using the Azure CLI, I created the following:
Setting up helm
The next step after creating the Azure resources would be to setup Helm in the newly created Kubernetes cluster.
This entails installing Tiller (Helm’s server component) on the Kubernetes cluster. This can be done using the following command, per the documentation:
helm init
Prior to running the previous, I needed to setup the context to communicate with the Kubernetes cluster. This is encompassed in the following script:
One thing to note is the override which is a recommendation in the Helm documentation. As by default, due to legacy reasons, Tiller uses ConfigMaps to store sensitive release information and should really use Secrets.
I love it when a build comes together
After creating all the required scripts and templates, I could put everything together using Travis CI. Then any time I make a change the updated infrastructure would be automatically built and deployed.
My .travis.yml file looks like the following:
This Travis CI definition utilizes Build Stages (currently in Beta) which allow you to cleanly separate the various phases of a build/deploy pipeline. You will also notice that I am using a number of environment variables which are set using the Repository settings.
This definition performs the following actions:
- Before any stage, it installs dependencies that the scripts require to work i.e. Azure CLI, kubectl and helm.
- Runs the test stage which validates the ARM template and the parameters specified.
- If the test phase passes and the build is working off the master branch, then it runs the deploy stage. This stage uses the experimental Script deployment to run a wrapper script deploying the ARM template and sets up Tiller.
The wrapper script looks as follows and just calls the scripts I defined earlier.
That’s the infrastructure setup! Part 2 details building and deploying the theme park bot using Helm.