Video Thumbnail for Lesson
12.1: Multi-Environment Overview

Deploying to Multiple Environments (Overview)

Transcript:

Up until this point, we've had a single configuration that we've been deploying into a single Kubernetes cluster. This is valuable, but in any real-world scenario, you're going to have multiple environments that you're going to want to deploy your applications to. This can be long-lived environments like a production environment or a staging environment. There also could be short-lived, ephemeral environments that you want to spin up and spin down quickly. In order to do this, we need to have some approach that allows us to take a common configuration and reuse it across multiple different places. There's a few popular tools that I'm going to cover here in this section, describing the trade-offs between them, and eventually building out a fully working example of our demo app that we'll deploy to multiple clusters. The first tool that I'll cover is Customize. It is a command-line tool that is built into kubectl. It also can be installed as a standalone binary, and it uses what is called a base and overlay model. You start out by defining some base configuration. This is going to have all of the common fields that all of your environments use, and maybe some default values as well. Then for each environment you want to deploy into, you'll specify an overlay. So only fields that are different for your particular environment need to be specified in an overlay, so it can ideally be a much smaller configuration. Customize then takes those two and merges them together to get your end-resulting configuration. It's very easy to get started with conceptually, as well as the fact that you already have the tooling built in to kubectl. However, there are some major limitations that you'll run into eventually related to how it handles arrays within YAML, and if you need to replace a specific value within a YAML array, or if you need to do patching for multiline strings within YAML, there's no support for that, so you'll have to replace the entire multiline string block. That is particularly relevant if you use file-like config maps, where you're defining a config for a particular file as a multiline string within your config map YAML. Another very popular tool that is used to handle deploying into multiple environments is Helm. We looked at Helm earlier in this course, and so this is just taking that tool and applying it to your first-party applications. Helm uses a templating model, so you'll have your chart, which includes a number of templates for all the resources you plan to deploy. Within those template files, you can specify variables that you want to be able to substitute in values for, and then for each environment, you'll have a custom values.yaml file containing the specific values for that environment. When you do a Helm install or a Helm upgrade, it will take those values, substitute them into the template files, and pass the resulting hydrated templates into the cluster. One nice thing about Helm is it has this concept of hooks. Hooks allow you to specify the ordering of deployment of resources, and so if there are dependencies between certain things, let's say you need to run a migration job before you upgrade your application, you can use hooks to encode that logic. Helm charts do represent sort of another deployment artifact that you're going to need to build, publish, and manage, so it's just another process that you have to deal with and potentially automate. I think some challenges with Helm are that the templating style, those Go templates quickly become hard to read as you add more and more templating to your chart. Helm also adds a significant amount of boilerplate even for the most simple of use cases, and so if you only need to substitute in an image tag and maybe a few other values like resource requests and limits, Helm can feel quite heavy for that. And then another challenge can be CRD management, so we talked about custom resources earlier in the course and how tools use them. While you can install CRDs via Helm, there's not a lot of control over how you would upgrade those CRDs with Helm, and or if you had conflicting Helm charts that were trying to install different versions of a CRD, that could become an issue as well. Now a third tool that I want to highlight and one that I'm particularly excited about, so much so that I sponsor the creator of this tool on GitHub, is ClueControl or ClueCuddle. It also uses a templating model similar to Helm and also has hooks for configuring the order of deployments. It requires much less boilerplate than Helm. When implementing it for a project, you will have a number of template files kind of like Helm. You'll have a ClueControl.yaml file that you define your environment in, and then within that file, you'll specify the different environments you want to deploy to and you can have variables at that top level that get templated in or you can use those top level environments as sort of an entry point. You store a configuration for each of those environments within the templates themselves. It integrates nicely with Helm and Customize, so if you're already using those tools, it's not too difficult to migrate over piece by piece as you see fit. And there's a built-in GitOps engine, which you can use as an alternative to something like FluxCD or ArgoCD that allows you to leverage all of the features that ClueControl has. There's also just a ton of nice developer experience features within this tool that I think will become apparent as we start to interact with it. I do want to call out a few other options that I've seen in the wild. Some people will implement their own sort of templating solution with Bash and envstubs or using YQ to substitute values within the YAML. This generally works and is fairly simple to get started with, but over time you end up with this very complex, convoluted setup that's hard to maintain. There's a tool called Timony, which is a quite powerful application packaging system that allows you to package up both your application container images as well as all the configuration for the different environments as OCI artifacts. It uses a language called Q, which can have a bit of a steep learning curve, but it's worth looking into if you have nuanced application packaging needs. There's also providers for infrastructure as code tools like Terraform and Pulumi that allow you to provision Kubernetes resources via Terraform or via Pulumi. And then CDK8s is a tool which enables you to write and deploy Kubernetes configurations using general purpose programming languages like TypeScript, Python, or Go. And by doing so, which allow you to use the control flow within those languages to produce configurations unique to any particular environment. Let's go ahead and jump over to the code editor and take a look at what some configurations with Customize, Helm, and Kluctl will look like for our demo application.