Google Cloud Functions en C#

1. Introduction

Google Cloud Run Functions est une plate-forme de calcul sans serveur basée sur des événements. Cloud Run Functions vous permet d'écrire votre code sans vous soucier du provisionnement des ressources ni du scaling pour répondre aux exigences changeantes.

Il existe deux types de fonctions Cloud Run :

  • Les fonctions HTTP répondent aux requêtes HTTP.
  • Les fonctions d'événement sont déclenchées par des événements, comme la publication d'un message dans Cloud Pub/Sub ou l'importation d'un fichier dans Cloud Storage.

efb3268e3b74ed4f.png

Cet atelier de programmation vous expliquera comment créer vos propres fonctions Cloud Run en C#. Plus précisément, vous allez déployer des fonctions C# répondant à des événements HTTP et CloudEvents provenant de diverses sources Google Cloud.

Points abordés

  • Framework des fonctions pour .NET.
  • Comment écrire une fonction HTTP
  • Écrire une fonction déclenchée par un événement en réponse à des événements Cloud Storage
  • Comment écrire une fonction déclenchée par un événement qui répond aux événements Cloud Pub/Sub.
  • Écrire une fonction déclenchée par un événement qui répond à n'importe quel type d'événement.

2. Préparation

Configuration de l'environnement au rythme de chacun

  1. Connectez-vous à la console Google Cloud, puis créez un projet ou réutilisez un projet existant. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Le nom du projet est le nom à afficher pour les participants au projet. Il s'agit d'une chaîne de caractères non utilisée par les API Google. Vous pouvez le modifier à tout moment.
  • L'ID du projet doit être unique sur l'ensemble des projets Google Cloud et doit être immuable (vous ne pouvez pas le modifier une fois que vous l'avez défini). La console Cloud génère automatiquement une chaîne unique (en général, vous n'y accordez d'importance particulière). Dans la plupart des ateliers de programmation, vous devrez indiquer l'ID du projet (généralement identifié par PROJECT_ID). Si l'ID généré ne vous convient pas, vous pouvez en générer un autre de manière aléatoire. Vous pouvez également en spécifier un et voir s'il est disponible. Après cette étape, l'ID n'est plus modifiable et restera donc le même pour toute la durée du projet.
  • Pour information, il existe une troisième valeur (le numéro de projet) que certaines API utilisent. Pour en savoir plus sur ces trois valeurs, consultez la documentation.
  1. Vous devez ensuite activer la facturation dans la console Cloud pour utiliser les ressources/API Cloud. L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Pour désactiver les ressources et éviter ainsi que des frais ne vous soient facturés après ce tutoriel, vous pouvez supprimer le projet ou les ressources que vous avez créées. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai sans frais pour bénéficier d'un crédit de 300$.

Démarrer Cloud Shell

Bien que Google Cloud puisse être utilisé à distance depuis votre ordinateur portable, nous allons nous servir de Google Cloud Shell pour cet atelier de programmation, un environnement de ligne de commande exécuté dans le cloud.

Dans la console Google Cloud, cliquez sur l'icône Cloud Shell dans la barre d'outils supérieure :

55efc1aaa7a4d3ad.png

Le provisionnement et la connexion à l'environnement prennent quelques instants seulement. Une fois l'opération terminée, le résultat devrait ressembler à ceci :

7ffe5cbb04455448.png

Cette machine virtuelle contient tous les outils de développement nécessaires. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute sur Google Cloud, ce qui améliore nettement les performances du réseau et l'authentification. Vous pouvez effectuer toutes les tâches de cet atelier de programmation dans un navigateur. Vous n'avez rien à installer.

3. Avant de commencer

Dans Cloud Shell, exécutez la commande suivante pour activer les services requis :

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  cloudfunctions.googleapis.com \
  eventarc.googleapis.com \
  run.googleapis.com

Ensuite, définissez votre région.

REGION=<YOUR_REGION>

Pour cet atelier de programmation, vous allez créer un compte de service avec les autorisations Eventarc requises et le rôle Demandeur Cloud Run pour recevoir un événement de Cloud Storage et appeler la fonction Cloud Run.

Commencez par créer le compte de service.

PROJECT_ID=$(gcloud config get-value core/project)
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"

Ensuite, attribuez le rôle Récepteur d'événements Eventarc (roles/eventarc.eventReceiver) sur le projet au compte de service associé à votre déclencheur Eventarc afin que le déclencheur puisse recevoir des événements de fournisseurs d'événements.

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

Ensuite, attribuez au compte de service le rôle d'appelant Cloud Run afin qu'il puisse appeler la fonction.

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

4. Framework des fonctions pour .NET

Le framework des fonctions pour .NET est un framework FaaS (Function as a Service) Open Source permettant d'écrire des fonctions .NET portables. Il est proposé par l'équipe Google Cloud Functions.

Le framework des fonctions vous permet d'écrire des fonctions légères qui s'exécutent dans de nombreux environnements, dont les suivants :

  • Fonctions Google Cloud Run
  • Votre ordinateur de développement local
  • Cloud Run et Cloud Run sur GKE
  • Environnements basés sur Knative

Dans cet atelier de programmation, vous allez utiliser le framework Functions pour .NET et ses modèles afin de créer et de déployer des fonctions Cloud en C#.

Dans Cloud Shell, exécutez la commande suivante pour installer les modèles Cloud Functions pour dotnet :

dotnet new install Google.Cloud.Functions.Templates

Cela installe trois modèles pour dotnet. Chaque modèle est disponible en C#, F# et VB (mais vous n'utiliserez que C# dans cet atelier). Vous pouvez vérifier que les modèles sont installés en exécutant la commande suivante :

dotnet new list

Templates                                                 Short Name            
-----------------------------------------------------------------------
Google Cloud Functions CloudEvent Function                gcf-event
Google Cloud Functions CloudEvent Function (Untyped)      gcf-untyped-event
Google Cloud Functions HttpFunction                       gcf-http

5. Fonction HTTP

Vous allez créer et déployer une fonction HTTP qui répond aux requêtes HTTP.

Créez une fonction HTTP à l'aide du modèle gcf-http :

mkdir HelloHttp
cd HelloHttp
dotnet new gcf-http

Cette action crée un projet et un fichier Function.cs qui répond aux requêtes HTTP.

Dans le fichier .csproj, remplacez le framework cible par net8.0 :

<TargetFramework>net8.0</TargetFramework>

Pour déployer une fonction Cloud Run directement sur Cloud Run, exécutez la commande suivante :

gcloud beta run deploy hello-http-function \
    --source . \
    --function HelloHttp.Function \
    --base-image dotnet8 \
    --region $REGION \
    --allow-unauthenticated

Si vous préférez déployer la fonction en tant que Cloud Functions 2e génération, utilisez la commande suivante :

gcloud functions deploy hello-http-function \
    --allow-unauthenticated \
    --entry-point HelloHttp.Function \
    --gen2 \
    --region $REGION \
    --runtime dotnet8 \
    --trigger-http

Une fois votre fonction déployée, vous pouvez l'appeler à l'aide de la commande curl suivante :

SERVICE_URL=$(gcloud run services describe hello-http-function --platform managed --region $REGION --format 'value(status.url)')

curl $SERVICE_URL

6. Fonction CloudEvent : GCS

Vous allez créer et déployer une fonction CloudEvent qui répond aux événements Google Cloud Storage (GCS).

Commencez par créer un bucket Cloud Storage. Il s'agit du bucket à partir duquel vous écouterez les événements ultérieurement :

BUCKET_NAME="cloud-functions-bucket-${PROJECT_ID}"
gsutil mb -l us-central1 gs://${BUCKET_NAME}

Créez une fonction CloudEvent à l'aide du modèle gcf-event :

cd ..
mkdir HelloGcs
cd HelloGcs
dotnet new gcf-event

Cette action crée un projet et un fichier Function.cs répondant aux requêtes CloudEvent. Il analyse également les données de CloudEvent dans StorageObjectData.

Dans le fichier .csproj, remplacez le framework cible par net8.0 :

<TargetFramework>net8.0</TargetFramework>

Pour déployer une fonction Cloud Run directement sur Cloud Run, vous devez d'abord déployer la fonction, puis créer un déclencheur pour celle-ci.

gcloud beta run deploy hello-gcs-function \
      --source . \
      --function HelloGcs.Function \
      --region $REGION \
      --base-image dotnet8 \
      --no-allow-unauthenticated

Créez maintenant le déclencheur pour la fonction Cloud Run.

BUCKET_REGION=$REGION

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

Si vous préférez déployer la fonction en tant que fonction Cloud Functions de deuxième génération, vous pouvez utiliser la commande suivante pour la déployer à l'aide des indicateurs trigger-event et trigger-resource :

gcloud functions deploy hello-gcs-function \
    --allow-unauthenticated \
    --entry-point HelloGcs.Function \
    --gen2 \
    --region $REGION \
    --runtime dotnet8 \
    --trigger-event google.storage.object.finalize \
    --trigger-resource ${BUCKET_NAME} \
    --service-account=$SERVICE_ACCOUNT_ADDRESS

Après quelques minutes, la fonction devrait être visible dans la console Cloud :

c28654d74bb31420.png

Déclenchez la fonction en important un fichier dans le bucket de stockage :

echo "Hello from Storage" > random.txt
gsutil cp random.txt gs://${BUCKET_NAME}

Vérifiez que la fonction a été déclenchée en lisant les journaux :

Pour une fonction Cloud Run, vous pouvez exécuter cette commande :

gcloud logging read "resource.labels.service_name=hello-gcs-function AND textPayload: Name" --format=json

Pour une fonction de deuxième génération, vous pouvez exécuter la commande suivante :

gcloud functions logs read hello-gcs-function \
    --gen2 \
    --region us-central1

7. Fonction CloudEvent – Pub/Sub

Vous allez créer et déployer une fonction CloudEvent qui répond aux événements Cloud Pub/Sub.

Commencez par créer un sujet Cloud Pub/Sub qui émettra des événements :

TOPIC_NAME=cloud-functions-topic
gcloud pubsub topics create ${TOPIC_NAME}

Créez une fonction CloudEvent à l'aide du modèle gcf-event :

cd ..
mkdir HelloPubSub
cd HelloPubSub
dotnet new gcf-event

Cette action crée un projet et un fichier Function.cs répondant aux requêtes CloudEvent. Il analyse également les données de CloudEvent dans StorageObjectData par défaut.

Dans le fichier .csproj, remplacez le framework cible par net8.0 :

<TargetFramework>net8.0</TargetFramework>

Remplacez StorageObjectData par MessagePublishedData pour analyser les messages Pub/Sub. Remplacez Google.Events.Protobuf.Cloud.Storage.V1 par Google.Events.Protobuf.Cloud.PubSub.V1.

Au final, votre fonction devrait se présenter comme suit :

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using Google.Events.Protobuf.Cloud.PubSub.V1;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace HelloPubSub;

public class Function : ICloudEventFunction<MessagePublishedData>
{
    public Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data, CancellationToken cancellationToken)
    {
        var nameFromMessage = data.Message?.TextData;
        var name = string.IsNullOrEmpty(nameFromMessage) ? "world" : nameFromMessage;
        Console.WriteLine($"Hello {name}");
        return Task.CompletedTask;
    }
}

Pour déployer une fonction Cloud Run directement sur Cloud Run, vous devez d'abord déployer la fonction, puis créer un déclencheur pour celle-ci.

gcloud beta run deploy hello-pubsub-function \
      --source . \
      --function HelloPubSub.Function \
      --region $REGION \
      --base-image dotnet8 \
      --no-allow-unauthenticated \
      --service-account=$SERVICE_ACCOUNT_ADDRESS

Créez maintenant le déclencheur pour la fonction Cloud Run.

gcloud eventarc triggers create my-pubsub-trigger \
    --location=$REGION \
    --service-account=$SERVICE_ACCOUNT_ADDRESS \
    --destination-run-service=hello-pubsub-function \
    --destination-run-region=$REGION \
    --destination-run-path="/" \
    --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
    --transport-topic=projects/$PROJECT_ID/topics/$TOPIC_NAME

Si vous préférez déployer la fonction en tant que Cloud Functions 2nd gen, vous pouvez utiliser la commande suivante avec l'indicateur trigger-topic :

gcloud functions deploy hello-pubsub-function \
    --allow-unauthenticated \
    --entry-point HelloPubSub.Function \
    --gen2 \
    --region us-central1 \
    --runtime dotnet8 \
    --trigger-topic ${TOPIC_NAME}

Après quelques minutes, la fonction devrait être visible dans la console Cloud :

3443808da7caf3bc.png

Déclenchez la fonction en publiant un message dans le sujet :

gcloud pubsub topics publish ${TOPIC_NAME} --message="World"

Vérifiez que la fonction a été déclenchée en lisant les journaux.

Pour une fonction Cloud Run, vous pouvez exécuter cette commande :

gcloud logging read "resource.labels.service_name=hello-pubsub-function AND textPayload: World" --format=json

Pour une fonction de deuxième génération, vous pouvez exécuter la commande suivante :

gcloud functions logs read hello-pubsub-function \
    --gen2 \
    --region us-central1

8. Fonction CloudEvent : non typée

Si vous testez les CloudEvents et que vous n'avez pas encore de modèle de données de charge utile auquel vous souhaitez vous engager, ou si vous souhaitez que votre fonction puisse gérer n'importe quel Cloud Event, vous pouvez utiliser une fonction CloudEvent non typée.

Créez une fonction Cloud Events à l'aide du modèle gcf-untyped-event :

cd ..
mkdir HelloUntyped
cd HelloUntyped
dotnet new gcf-untyped-event

Cela crée un projet et un fichier Function.cs répondant aux requêtes CloudEvent sans aucune tentative d'analyse des données du CloudEvent.

Dans le fichier .csproj, remplacez le framework cible par net8.0 :

<TargetFramework>net8.0</TargetFramework>

Pour déployer une fonction Cloud Run directement sur Cloud Run, vous devez d'abord déployer la fonction, puis créer un déclencheur pour celle-ci.

gcloud beta run deploy hello-untyped-function \
      --source . \
      --function HelloUntyped.Function \
      --region $REGION \
      --base-image dotnet8 \
      --no-allow-unauthenticated

Créez maintenant le déclencheur pour la fonction Cloud Run.

BUCKET_REGION=$REGION

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

Si vous préférez déployer la fonction en tant que fonction Cloud Functions de deuxième génération, vous pouvez utiliser la commande suivante pour la déployer à l'aide des indicateurs trigger-event et trigger-resource :

gcloud functions deploy hello-untyped-function \
    --allow-unauthenticated \
    --entry-point HelloUntyped.Function \
    --gen2 \
    --region us-central1 \
    --runtime dotnet8 \
    --trigger-event google.storage.object.finalize \
    --trigger-resource ${BUCKET_NAME}

La fonction se déclenche lorsqu'un fichier est importé dans un bucket de stockage.

Après quelques minutes, la fonction devrait être visible dans la console Cloud :

afe56530826787c6.png

Déclenchez la fonction en important un fichier dans le bucket de stockage :

echo "Hello from Storage" > random.txt
gsutil cp random.txt gs://${BUCKET_NAME}

Vérifiez que la fonction a été déclenchée en lisant les journaux.

Pour une fonction Cloud Run, vous pouvez exécuter cette commande :

gcloud logging read "resource.labels.service_name=hello-gcs-function AND textPayload: Name" --format=json

Pour une fonction de deuxième génération, vous pouvez exécuter la commande suivante :

gcloud functions logs read hello-untyped-function \
    --gen2 \
    --region us-central1

9. Félicitations !

Bravo ! Vous avez terminé cet atelier de programmation.

Points abordés

  • Framework des fonctions pour .NET.
  • Comment écrire une fonction Cloud HTTP
  • Écrire une fonction CloudEvent qui répond aux événements Cloud Storage.
  • Découvrez comment écrire une fonction CloudEvent qui répond aux événements Cloud Pub/Sub.
  • Écrire une fonction CloudEvent qui répond à n'importe quel type d'événement