Your submission was sent successfully! Close

Thank you for signing up for our newsletter!
In these regular emails you will find the latest updates from Canonical and upcoming events where you can meet our team.Close

Thank you for contacting our team. We will be in touch shortly.Close

  1. Blog
  2. Article

Maximilian Ehlers
on 21 December 2018

Our Kubernetes deployment pipeline

A few weeks ago I joined the web and design team here at Canonical, in the Base Squad, which is our backend team.

One of the things that we are responsible for is deploying the code to our different staging and production environments.

With multiple features being developed simultaneously, bugs being fixed, and some parts refactored on 27 websites and many projects it quickly becomes a complex problem to solve manually.

In this post I want to lay out the way we use Charmed Kubernetes to automate much of our deployment process, using as an example.

The cluster configuration

Before we delve into the flow of deploying changes to our Kubernetes cluster, we first need an idea of how the cluster is configured. Our cluster is a standard installation of our own Charmed Kubernetes, managed for us by our infrastructure team.

We use Git to manage all the Kubernetes configuration files for our infrastructure and all its changes.
This repository includes the config for almost all the public services that we manage. Feel free to take a look.

So for example the config has a deployment configuration with name: snapcraft-io attached to its metadata.

Besides all the other configuration that is going on in this file, this is the most important detail to understand how the next steps work.

From code to staging

Now let’s uncover our workflow for deploying code changes onto a Staging environment.

We have a policy in our team, that the master branch of our repositories is kept in a releasable state. This means that any of our developers are free to deploy any of our sites at any time.

Let’s say that we are through our Code Review and now want to bring the project to life in the staging environment.

The first thing to do is to head over to our Jenkins Server and start our pipeline.

First click in deployment journey
The second click, starting the Build

As a developer these are only two clicks, while what is actually happening on the server is the following:

  1. Pull the code from the GitHub master branch
  2. Build the files for the website
  3. Build a fresh docker container that contains the application and its dependencies
  4. Push the container into our container registry
  5. Remove the locally built container as cleanup
  6.  Deploy to cluster
    1. Trigger the deployment into the Kubernetes cluster (here we use the metadata mentioned above!)
    2. Kubernetes pulls the correct image from the registry
  7. Wait for the Pods to be updated with the new version

All changes are now deployed at

Once these steps are complete the application can be accessed by all our stakeholders to get some of that important feedback as quickly as we can.

If changes need to be made, we go back to work on the codebase.

An additional thing we add to our pipeline is a link to the production deploy task. This way we can just open that in a new browser tab when we are happy and continue with the next step.

From staging into production

The task to get our application into Staging has already done most of the heavy lifting for us, building the container and pushing it into our registry.

The encapsulation inside the image makes sure that the application will run the same way in the production environment as is does in the staging one, so Kubernetes can simply pull the same image from our registry.

With these prerequisites, the Jenkins pipeline for a production deploy is rather simple.

All we need to provide to it is the ID of the image that we previously deployed to staging.

Again a top down outline of what is happening:

  1. Trigger the deployment of the previously built image into our Production cluster (this comes from the registry)
  2. Wait for the deployment to be rolled out on all Pods
  3. Tag the deployed image as “latest” in the registry

The first two steps would be enough for a rollout to production already, which is then live at
Step 3 is only included to help us find the current live image that is running the site.


Depending on your experience this might have been quite a lot of new information, or you might say, too easy!

What I hope you can take away from this, is the relative straightforwardness of our Kubernetes workflow.

Ignoring the tag updating, we can deploy into our production environment in 8 steps, that translate to 2 Jenkins Tasks, which we can complete with ~3 clicks.

Of course we are always striving to keep on improving things. At the moment we are investigating tools such as Helm and ksonnet to see if they can help us simplify our workflow further.
If you would like to find out even more about how we work here in the Canonical Webteam head over to our practices website.

Related posts

Goulin Khoge
14 October 2022

Introducing a VSCode extension for Vanilla CSS Framework

Ubuntu Article

The Vanilla CSS Framework is a utility class-based and customizable SASS library that is the go-to when it comes to styling websites and dashboards across the majority of projects at Canonical. Knowing all the class utilities could be tricky. That’s why we make sure that our documentation is up-to-date and accessible as much as possible. ...

26 February 2024

Crafting new Linux schedulers with sched-ext, Rust and Ubuntu

Ubuntu Article

In our ongoing exploration of Rust and Ubuntu, we delve into an experimental kernel project that leverages these technologies to create new schedulers for Linux. Playing around with CPU scheduling policies has always been a dream for many kernel hackers and OS enthusiasts. However, such material typically remains within the domain of a fe ...

Igor Ljubuncic
24 January 2024

Canonical’s recipe for High Performance Computing


In essence, High Performance Computing (HPC) is quite simple. Speed and scale. In practice, the concept is quite complex and hard to achieve. It is not dissimilar to what happens when you go from a regular car to a supercar or a hypercar – the challenges and problems you encounter at 100 km/h are vastly ...