System Architect

Product Manager

Software Engineer

Deploying containers on Cloud Run using YAML manifests

When you are working with an architecture that includes Kubernetes clusters you might still find useful to use Cloud Run for certain applications, like a web frontend, API gateway and more. At the same time, you may find confusing how to integrate it seamlessly in your CI/CD workflow.

gcloud CLI can deploy Cloud Run service, but it doesn’t have all possible deployment options, and in this case you can’t store configurations in a repository like a pre-configured manifest, or use the same Config Map with environment variables for both Kubernetes and Cloud Run applications. Luckily, it’s possible to deploy Cloud Run applications in a similar way as Kubernetes and I’m going to show how to do it.

Creating Cloud Run service

Cloud Run uses knative and you can find there a description for a base manifest structure. At the same time, I wasn’t be able to find a complete manifest reference for Cloud Run. But it isn’t a problem, because we can easily get a manifest preset from a Cloud Run service created with Console (a web interface):

  1. Go to Cloud Run Console
  2. Click “Create Service”.
  3. Set your preferable settings.
  4. Click “Create”.

Or from Cloud Run service created by gcloud CLI:

gcloud run deploy

Exporting Cloud Run YAML manifest

Our Cloud Run application is deployed, now we need to obtain YAML manifest. An easy way to do it by using gcloud CLI:

gcloud run services describe <cloudrun-service-name> --format=export > cloudrun-preset.yaml

This is how your exported Cloud Run YAML may look like:

kind: Service
  annotations: <region><project-name>/<container-name>@sha256:<hash> all all
  labels: <region>
  name: <app-name>
  namespace: '<namespace>'
      annotations: '3' cloud-console 'true' gen1 'true'
      name: <app-name>-<revision-code>
      containerConcurrency: 80
      - env:
        - name: LISTEN_ADDR
        - name: LISTEN_PORT
          value: '80'
        - name: DB_HOST
        - name: DB_PORT
          value: '5432'
        - name: DB_NAME
          value: db_default
        - name: DB_SECRET
          value: default-user
        image: <region><project-name>/<container-name>@sha256:<hash>
        - containerPort: 80
          name: http1
            cpu: 1000m
            memory: 512Mi
      timeoutSeconds: 300
  - latestRevision: true
    percent: 100

Now we can adjust the preset by changing or removing certain fields and values. Then, the manifest can be committed to a git repository or put to any other place where you store your Kubernetes YAML manifests.

Deploying Cloud Run using YAML manifest

One of the ways to deploy Cloud Run instance from a manifest preset is by using yq and gcloud. Let’s say we have configmap.yaml with environment variables:

apiVersion: v1
kind: ConfigMap
  name: app-config
  namespace: default
  DB_PORT: '5432'
  DB_NAME: db_default
  DB_SECRET: default-user

A new container that we want to deploy is ${_DOCKER_IMAGE_URL} with a digest ${_DOCKER_IMAGE_DIGEST}

The Bash deployment code may look like:

yq e ".spec.template.spec.containers[0].env = $(yq e -o=j -I=0 '.data | \
to_entries | (.[] |= with_entries( (select(.key=="key") | .key) = "name" \
) )' configmap.yaml)" cloudrun-preset.yaml > deployment.yaml;


artifact=$artifact yq e -i \
'.metadata.annotations.""=strenv(artifact)' \

artifact=$artifact yq e -i \
'.spec.template.spec.containers[0].image=strenv(artifact)' \

gcloud run services replace deployment.yaml;

Optionally, after running this script you can check if the deployment was successful, then you can commit deployment.yaml to the repository where successful deployments are stored.

Now you can deploy the same application to Kubernetes and Cloud Run seamlessly inside the single CI/CD workflow.