Migrating from Kubernetes to Google Cloud Run with terraform
Contents
Kubernetes has its advantages when you’re big enough and require the flexibility it offers. But when all you’re after is running services and you don’t need stateful sets, Google Cloud Run can be a good alternative (provided you’re using Google Cloud Platform). This article provides a few pointers to migrate Kubernetes deployments to Google Cloud Run.
Migrating YAML deployment descriptors
There’s a guide for migrating deployment descriptors which outlines the major syntax differences between a Kubernetes deployment and a Cloud Run service.
What the guide doesn’t say however is that the feature set of Cloud Run YAML descriptors is fairly limited. For example:
- you can’t have more than one deployment per YAML file. So if your service spins is comprised of multiple deployments, you’ll need to create one file for each deployment
- there’s no way to use environment variables in the descriptors. I think this is the biggest caveat here because it means hardcoding everything. It is possible to inject values from the Secret Manager but they’ll have to be named explicitly.
If you happen to be using terraform to manage your infrastructure, there’s a nice way around this by:
- initially deploying a service using terraform
- subsequently deploying new images to it in the CI/CD using the
gcloud
CLI.
This approach assumes that you already have a build pipleine in place and only would like to move the deployments of the services. If you want to go one step further and also port the building of the projects, there’s Google Cloud Build for this.
Defining services in terraform
In what follows we’re defining a terraform module to deploy services to Cloud Run. The module assumes:
- that the service image is available in a Google Artifact registry repository
- that we want to inject a number of environment variables which we’ll read from the Secret Manager
Let’s start by creating a repository to hold the images:
|
|
This will create the docker image repository which we’ll use later on to publish our images.
Next, we can create the service itself by using the google_cloud_run_v2_service resource.
|
|
And this is pretty much it! If the services you’re deploying are homogenous (similar startup / liveness probe paths and similar ways to run a service), it’s a good idea to provide those as defaults in the variables.tf
of the module. A possible module usage then looks like this:
|
|
Deploying services in the CI/CD pipeline
In order to deploy new versions of the service in the CI/CD pipeline, we can use a gcloud
command to do so. Note how in the lifecycle settings of the terraform service resource, we are ignoring lifecycle changes for the image value - this allows to deploy different image tags without terraform complaining about the image having changed.
After having pushed the new version of the service image, we can simply deploy it like so:
|
|
And that’s about it. Happy deployment!