Getting Started with Event-driven Cloud Run functions

1. Introduction

Overview

Cloud Run functions is a new way to deploy workloads using the familiar GCF eventing paradigms and function signature. Instead of using our opinionated build process and deployment configurations, Cloud Run functions gives you direct control over the underlying Service created on Cloud Run.

With Cloud Run functions, we provide the simple UX of Cloud Run source deploy, giving developers complete control over their workloads using Cloud Run configurations.

In this section, you'll learn how to deploy an event-driven function in Node. You'll deploy a function that is triggered whenever an object is finalized in a Google Cloud Storage bucket.

This codelab uses nodejs samples in the examples below. However, you can use the Cloud Functions 2nd gen code samples in the language of your choice:

What you'll learn

  • How to deploy an event-driven Cloud Run function that is triggered whenever an object is uploaded to a GCS bucket
  • How to create a service account with proper roles to receive an event from Cloud Storage and invoke the Cloud Run function

2. Setup environment variables and enable APIs

Update gcloud CLI

This codelab requires a recent version of the gcloud CLI installed. You can update the CLI by running

gcloud components update

Enable APIs

Before you can start using this codelab, there are several APIs you will need to enable. This codelab requires using the following APIs. You can enable those APIs by running the following command:

gcloud services enable run.googleapis.com \
    cloudbuild.googleapis.com \
    storage.googleapis.com \
    artifactregistry.googleapis.com

Setup environment variables

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

PROJECT_ID=<YOUR_PROJECT_ID>
REGION=<YOUR_REGION, e.g. us-central1>

gcloud config set project $PROJECT_ID
SERVICE_NAME=crf-event-codelab
BUCKET_NAME=$PROJECT_ID-$SERVICE_NAME
TRIGGER_NAME=$SERVICE_NAME-trigger

3. Create a Storage Bucket and a Service Account

Create a storage bucket

You can create a Cloud Storage bucket by running the following command:

gsutil mb -l us-central1 gs://$BUCKET_NAME

Create a service account

For this example, you'll create a service account with required EventArc permissions and Cloud Run invoker role to receive an event from Cloud Storage and invoke the Cloud Run function.

First, create the service account.

PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')

SERVICE_ACCOUNT="cloud-run-functions"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com

gcloud iam service-accounts create $SERVICE_ACCOUNT \
  --display-name="Cloud Run functions Eventarc service account"

Next, grant the Eventarc Event Receiver role (roles/eventarc.eventReceiver) on the project to the service account associated with your Eventarc trigger so that the trigger can receive events from event providers.

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role=roles/eventarc.eventReceiver

Then, grant the service account the Cloud Run invoker role so that it can invoke the function.

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role=roles/run.invoker

4. Create and deploy the function

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

mkdir ../$SERVICE_NAME && cd $_

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

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

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

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

// Register a CloudEvent callback with the Functions Framework that will
// be triggered by Cloud Storage.
functions.cloudEvent("helloGCS", (cloudEvent) => {
    console.log(`Event ID: ${cloudEvent.id}`);
    console.log(`Event Type: ${cloudEvent.type}`);

    const file = cloudEvent.data;
    console.log(`Bucket: ${file.bucket}`);
    console.log(`File: ${file.name}`);
    console.log(`Metageneration: ${file.metageneration}`);
    console.log(`Created: ${file.timeCreated}`);
    console.log(`Updated: ${file.updated}`);
});

Now you can deploy the Cloud Run function by running the following command:

gcloud beta run deploy $SERVICE_NAME \
 --source . \
      --function helloGCS \
      --region $REGION \
      --no-allow-unauthenticated

Please note the following:

  • the –source flag is used to tell Cloud Run to build the function into a runnable container based service
  • the –function flag (new) is used to set the entrypoint of the new service to be the function signature you want to be invoked
  • (optional) the –no-allow-unauthenticated to prevent your function from being publicly invokable

You can view your new service crf-nodejs-event by running the following command:

gcloud beta run services describe $SERVICE_NAME

5. Create the event

We can create an Eventarc trigger to send messages to our function every time an object is finalized in Google Cloud Storage:

BUCKET_REGION=$REGION

gcloud eventarc triggers create $TRIGGER_NAME \
     --location=$REGION \
     --destination-run-service=crf-nodejs-event \
  --destination-run-region=$BUCKET_REGION \
     --event-filters="type=google.cloud.storage.object.v1.finalized" \
     --event-filters="bucket=$BUCKET_NAME" \
     --service-account=$SERVICE_ACCOUNT_ADDRESS

Please note the following:

  • gcs-function-trigger is the name of the trigger
  • crf-nodejs-event is the name of the Cloud Run service where our function is deployed
  • for the –event-filters flag, do not use the gs:// prefix in your bucket name.

A detailed tutorial of setting up Trigger service from Cloud Storage using Eventarc can be found in the Cloud Run documentation here: https://cloud.google.com/run/docs/tutorials/eventarc

6. Test the Function

When the deployment is complete, you will see the service URL. To invoke the function, you need to send an authenticated request with your identity token or the identity token of a principle that has the Cloud Run Invoker role, as shown below:

# get the Service URL
SERVICE_URL="$(gcloud run services describe crf-nodejs-event --region us-central1 --format 'value(status.url)')"

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

With our function deployed and a trigger created, we are now ready to invoke the function.

Create a file and upload it to your Cloud Storage bucket. You can do this through the Cloud Console web interface, or using the gsutil CLI tool, e.g.

echo "hello world" > test.txt
gsutil cp test gs://$BUCKET_NAME

When the file is successfully uploaded, an event will be generated and your function will print some basic information about the object e.g. the filename. You can find this output in the log entries for the function in the Cloud Console. Alternatively, you can query for this output using the gcloud CLI:

gcloud logging read "resource.labels.service_name=crf-nodejs-event AND textPayload: File" --format=json 

and you should see the following output

"textPayload": "File: test.txt"

7. Congratulations!

Congratulations for completing the codelab!

We recommend reviewing the documentation for Cloud Run functions

What we've covered

  • How to deploy an event-driven Cloud Run function that is triggered whenever an object is uploaded to a GCS bucket
  • How to create a service account with proper roles to receive an event from Cloud Storage and invoke the Cloud Run function

8. Clean up

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

To delete the Cloud Run services, go to the Cloud Run Cloud Console at https://console.cloud.google.com/run/ and delete the crf-event-codelab service 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.