Using revisions in Cloud Functions 2nd gen for Traffic Splitting, Gradual Rollouts, and Rollbacks

1. Introduction

Overview

Cloud Run allows you to specify which revisions should receive traffic and to specify traffic percentages that are received by a revision. Revisions allows you to rollback to a previous revision, gradually roll out a revision, and split traffic between multiple revisions.

This codelabs show you how to use revisions to manage traffic to your 2nd gen Cloud Functions. You can learn more about revisions in the Cloud Run documentation.

What you'll learn

  • How to to split traffic between two or more revisions for a 2nd gen function
  • How to roll out a new revision gradually
  • How to rollback to a previous revision

2. Setup and Requirements

Prerequisites

  • You are logged into the Cloud Console.
  • You have previously deployed a 2nd gen function. For example, you can follow the deploy a Cloud Function 2nd gen quickstart to get started.

Activate Cloud Shell

  1. From the Cloud Console, click Activate Cloud Shell d1264ca30785e435.png.

cb81e7c8e34bc8d.png

If this is your first time starting Cloud Shell, you're presented with an intermediate screen describing what it is. If you were presented with an intermediate screen, click Continue.

d95252b003979716.png

It should only take a few moments to provision and connect to Cloud Shell.

7833d5e1c5d18f54.png

This virtual machine is loaded with all the development tools needed. It offers a persistent 5 GB home directory and runs in Google Cloud, greatly enhancing network performance and authentication. Much, if not all, of your work in this codelab can be done with a browser.

Once connected to Cloud Shell, you should see that you are authenticated and that the project is set to your project ID.

  1. Run the following command in Cloud Shell to confirm that you are authenticated:
gcloud auth list

Command output

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Run the following command in Cloud Shell to confirm that the gcloud command knows about your project:
gcloud config list project

Command output

[core]
project = <PROJECT_ID>

If it is not, you can set it with this command:

gcloud config set project <PROJECT_ID>

Command output

Updated property [core/project].

3. Traffic Splitting

This sample shows you how to create a function that reads a color environment variable and responds back with the revision name using that background color.

Although this codelab uses node.js, you can use any runtime.

Set Environment Variables

You can set environment variables that will be used throughout this codelab.

REGION=<YOUR_REGION>
PROJECT_ID=<YOUR-PROJECT-ID>
BG_COLOR=darkseagreen

Create the function

First, create a directory for the source code and cd into that directory.

mkdir revisions-gcf-codelab && cd $_

Then, create a package.json file with the following content:

{
    "dependencies": {
        "@google-cloud/functions-framework": "^3.0.0"
    }
}

Next, create a index.js source file with the following content:

const functions = require('@google-cloud/functions-framework');


const BG_COLOR = process.env.BG_COLOR;
const K_REVISION = process.env.K_REVISION;


functions.http('helloHttp', (req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<html><body style="background-color:' + BG_COLOR + ';"' + '><div><p>' + 'Hello from ' + K_REVISION + ' using color ' + BG_COLOR + '</p></div></body>' + '</html>');
});

and now deploy the function

gcloud functions deploy traffic-splitting-gcf \
  --gen2 \
  --runtime nodejs20 \
  --entry-point helloHttp \
  --source . \
  --region $REGION \
  --trigger-http \
  --no-allow-unauthenticated \
  --update-env-vars BG_COLOR=$BG_COLOR

To test the function, you can either curl the existing endpoint to see the darkseagreen color in the html, or use your browser to hit the endpoint directly to see the background color.

SERVICE_URL=$(gcloud run services describe traffic-splitting-gcf --platform managed --region $REGION --format 'value(status.url)')

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

Now deploy a second revision with a tan background color:

# update the env var
BG_COLOR=tan

# deploy the function
gcloud functions deploy traffic-splitting-gcf \
  --gen2 \
  --runtime nodejs20 \
  --entry-point helloHttp \
  --source . \
  --region $REGION \
  --trigger-http \
  --no-allow-unauthenticated \
  --update-env-vars BG_COLOR=$BG_COLOR

Now when you curl the endpoint, you'll see the tan background color.

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

Split the traffic 50-50

To split the traffic between the deep sea green and tan revisions, you need to find the revision IDs of the underlying Cloud Run services. You can see the revision IDs by running this command:

gcloud run revisions list --service traffic-splitting-gcf \
  --region $REGION --format 'value(REVISION)'

You should see results similar to those below

traffic-splitting-gcf-00003-qoq
traffic-splitting-gcf-00002-zag

You can split the traffic 50/50 between the two revisions by running the following command:

gcloud run services update-traffic traffic-splitting-gcf \
  --region $REGION \
  --to-revisions <REVISION1>=50,<REVISION2>=50

Test the traffic splitting

You can test the function by visiting its public URL (either by curl or directly in the browser).

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" $SERVICE_URL

Half of the time, you should see the dark sea green revision and, the other half, the tan revision. You will also see the revision name listed in the output, e.g.

<html><body style="background-color:tan;"><div><p>Hello traffic-splitting-gcf-00006-qoq</p></div></body></html>

4. Gradual Rollouts

In this section, you'll learn how to gradually rollout changes to a new Cloud Function revision. You can learn more about gradual rollouts in the documentation.

You will use the same code as the previous section, but you will deploy it as a new Cloud Function.

First, set the background color to beige and deploy the function with the name gradual-rollouts-gcf.

# update the env var
BG_COLOR=beige

# deploy the function
gcloud functions deploy gradual-rollouts-gcf \
  --gen2 \
  --runtime nodejs20 \
  --entry-point helloHttp \
  --source . \
  --region $REGION \
  --trigger-http \
  --no-allow-unauthenticated \
  --update-env-vars BG_COLOR=$BG_COLOR

Now let's say we want to gradually roll out a new revision with the background color lavender.

First, let's set the current revision beige to receive 100% traffic. This will ensure that your future Cloud Function deployments do not receive any traffic. By default, Cloud Functions sets 100% traffic to the revision with the latest flag. By manually specifying that this current revision beige should receive all the traffic, the revision with the latest flag will no longer receive 100% traffic. See documentation.

# get the revision name

BEIGE_REVISION=$(gcloud run revisions list --service gradual-rollouts-gcf \
  --region $REGION --format 'value(REVISION)')

# now set 100% traffic to that revision

gcloud run services update-traffic gradual-rollouts-gcf --to-revisions=$BEIGE_REVISION=100 --region $REGION

You'll see output similar to Traffic: 100% gradual-rollouts-gcf2-00001-yox

Now you can deploy a new revision that will not receive any traffic. Instead of making any code changes, you can update the BG_COLOR environment variable for this revision.

# update color

BG_COLOR=lavender

# deploy the function that will not receive any traffic
gcloud functions deploy gradual-rollouts-gcf \
  --gen2 \
  --runtime nodejs20 \
  --entry-point helloHttp \
  --source . \
  --region $REGION \
  --trigger-http \
  --no-allow-unauthenticated \
  --update-env-vars BG_COLOR=$BG_COLOR \
  --tag $BG_COLOR

and now when you curl the service

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

you will see the beige color, even though lavender was the most recently deployed revision.

<html><body style="background-color:beige;"><div><p>Hello from gradual-rollouts-gcf-24jan16-staging-2-00001-kop using color beige</p></div></body></html>

Test a Revision serving 0% traffic

Suppose you have verified that your revision deployed successfully and that it is serving 0% traffic. Even though it has passed health checks, you still want to verify that this revision is using the lavender background color.

To test the lavender revision, you can apply a tag to that revision. Tagging allows you to directly test the new revision at a specific URL, without serving traffic.

First, get the image URL for that revision.

IMAGE_URL=$(gcloud_staging run services describe gradual-rollouts-gcf--region $REGION --format 'value(IMAGE)')

And now tag that image with its associated color.

gcloud run deploy gradual-rollouts-gcf --image $IMAGE_URL --no-traffic --tag $BG_COLOR --region $REGION --no-allow-unauthenticated

You will see output similar to the following:

The revision can be reached directly at https://lavender---gradual-rollouts-gcf-k6msmyp47q-lz.a.run.app

Now you can curl this revision directly

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET <DIRECT_REVISION_URL>

and see the lavender color in the results:

<html><body style="background-color:lavender;"><div><p>Hello from gradual-rollouts-gcf-24jan16-00003-xik using color lavender</p></div></body></html>

Gradually increasing traffic

Now, you can start sending traffic to the lavender revision. The example below shows how to send 1% of traffic to lavender.

gcloud run services update-traffic gradual-rollouts-gcf --to-tags lavender=1

To send 50% of traffic to lavender, you can use the same command, but specify 50% instead.

gcloud run services update-traffic gradual-rollouts-gcf --to-tags lavender=50

You should see a list of how much traffic each revision is receiving.

Traffic:
  50% gradual-rollouts-gcf-00001-hos
  50% gradual-rollouts-gcf-00004-mum
        lavender: https://lavender---gradual-rollouts-gcf-k6msmyp47q-uc.a.run.app

When you're ready to fully roll out lavender, you can set lavender to 100% to replace beige.

gcloud run services update-traffic gradual-rollouts-gcf --to-tags lavender=100

and now when you visit or curl the gradual-rollouts-gcf function service URL,

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

you will only see lavender.

<html><body style="background-color:lavender;"><div><p>Hello gradual-rollouts-gcf-00004-mum</p></div></body></html>

5. Rollbacks

Suppose early UX feedback has come in, indicating the customers prefer beige to lavender, and you need to rollback to beige.

You can roll back to the previous revision (beige) by running this command.

gcloud run services update-traffic gradual-rollouts-gcf --to-revisions $BEIGE_REVISION=100

and now when your curl or visit the function URL endpoint,

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

you'll see beige returned.

<html><body style="background-color:beige;"><div><p>Hello gradual-rollouts-gcf-00001-hos</p></div></body></html>

You can learn more about rollbacks in the docs.

6. Congratulations!

Congratulations for completing the codelab!

We recommend reviewing the documentation on rollouts, rollbacks, and traffic migration

What we've covered

  • How to to split traffic between two or more revisions for a 2nd gen function
  • How to roll out a new revision gradually
  • How to rollback to a previous revision

7. Clean up

To avoid inadvertent charges, (for example, if this Cloud Function is inadvertently invoked more times than your monthly Cloud Function invokement allocation in the free tier), you can either delete the Cloud Function or delete the project you created in Step 2.

To delete the Cloud Function, go to the Cloud Function Cloud Console at https://console.cloud.google.com/functions/ and delete the functions you created in this codelab.

If you choose to delete the entire project, you can go to https://console.cloud.google.com/cloud-resource-manager, select the project you created in Step 2, and choose Delete. If you delete the project, you'll need to change projects in your Cloud SDK. You can view the list of all available projects by running gcloud projects list.