Cloud Run işlevlerini kullanmaya başlama

1. Giriş

Genel Bakış

Cloud Run işlevleri, Google Cloud'un Cloud Run ve Eventarc tarafından desteklenen Hizmet Olarak İşlev (FaaS) teklifidir. Bu teklif, performans ve ölçeklenebilirlik üzerinde daha gelişmiş kontrolün yanı sıra 90'dan fazla etkinlik kaynağındaki işlevlerin çalışma zamanı ve tetikleyicileri üzerinde daha fazla kontrol sağlar.

Bu codelab'de, HTTP çağrılarına yanıt veren, Pub/Sub mesajları ve Cloud Denetleme Günlükleri tarafından tetiklenen Cloud Run işlevleri oluşturma adımları açıklanmaktadır.

Bu codelab'de, --base-image işaretini kullanarak temel bir resim belirtilerek işlev dağıtımları için otomatik temel resim güncellemeleri de kullanılır. Cloud Run için otomatik temel görüntü güncellemeleri, Google'ın temel görüntünün işletim sistemi ve dil çalışma zamanı bileşenlerine otomatik olarak güvenlik yamaları uygulamasına olanak tanır. Temel görüntünün güncellenmesi için hizmetinizi yeniden oluşturmanız veya yeniden dağıtmanız gerekmez. Daha fazla bilgi için otomatik temel resim güncellemeleri başlıklı makaleyi inceleyin.

Otomatik temel resim güncellemelerini kullanmamayı tercih ederseniz bu codelab'de gösterilen örneklerden --base-image işaretini kaldırabilirsiniz.

Neler öğreneceksiniz?

  • Cloud Run işlevlerine genel bakış ve otomatik temel görüntü güncellemelerini kullanma
  • HTTP çağrılarına yanıt veren bir işlev yazma
  • Pub/Sub mesajlarına yanıt veren bir işlev yazma
  • Cloud Storage etkinliklerine yanıt veren bir işlev yazma
  • Trafiği iki düzeltme arasında bölme
  • Minimum örneklerle soğuk başlatma sorununu nasıl ortadan kaldırabilirsiniz?

2. Kurulum ve Gereksinimler

Kök klasör oluşturma

Tüm örnekler için bir kök klasör oluşturun.

mkdir crf-codelab
cd crf-codelab

Ortam değişkenlerini ayarlama

Bu codelab boyunca kullanılacak ortam değişkenlerini ayarlayın.

gcloud config set project <YOUR-PROJECT-ID>
REGION=<YOUR_REGION>

PROJECT_ID=$(gcloud config get-value project)

API'leri etkinleştir

Gerekli tüm hizmetleri etkinleştirin:

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  eventarc.googleapis.com \
  run.googleapis.com \
  logging.googleapis.com \
  pubsub.googleapis.com

3. HTTP İşlevi

İlk işlev için HTTP isteklerine yanıt veren bir kimliği doğrulanmış Node.js işlevi oluşturalım. Ayrıca, bir işlevin HTTP isteklerine yanıt vermek için nasıl daha fazla zamanı olabileceğini göstermek amacıyla 10 dakikalık bir zaman aşımı kullanalım.

Oluştur

Uygulama için bir klasör oluşturun ve bu klasöre gidin:

mkdir hello-http
cd hello-http

HTTP isteklerine yanıt veren bir index.js dosyası oluşturun:

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

functions.http('helloWorld', (req, res) => {
  res.status(200).send('HTTP with Node.js in Cloud Run functions!');
});

Bağımlılıkları belirtmek için bir package.json dosyası oluşturun:

{
  "name": "nodejs-run-functions-codelab",
  "version": "0.0.1",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^2.0.0"
  }
}

Dağıt

İşlevi dağıtın:

gcloud run deploy nodejs-run-function \
      --source . \
      --function helloWorld \
      --base-image nodejs22 \
      --region $REGION \
      --timeout 600 \
      --no-allow-unauthenticated

Bu komut, işlev kaynak kodunuzu üretime hazır bir kapsayıcı görüntüsüne dönüştürmek için buildpack'leri kullanır.

Lütfen şunları unutmayın:

  • --source işareti, Cloud Run'a işlevi çalıştırılabilir bir kapsayıcı tabanlı hizmet olarak oluşturmasını söylemek için kullanılır.
  • --function işareti (yeni), yeni hizmetin giriş noktasını çağrılmasını istediğiniz işlev imzası olarak ayarlamak için kullanılır.
  • --base-image işareti (yeni), işleviniz için temel resim ortamını (ör. nodejs22, python312, go123, java21, dotnet8, ruby33 veya php83) belirtir. Temel resimler ve her resimde bulunan paketler hakkında daha fazla bilgi için Çalışma zamanı temel resimleri başlıklı makaleyi inceleyin.
  • (isteğe bağlı) --timeout işareti, işlevin HTTP isteklerine yanıt vermek için daha uzun bir zaman aşımına sahip olmasına olanak tanır. Bu örnekte, 10 dakikalık yanıt süresini göstermek için 600 saniye kullanılmıştır.
  • (isteğe bağlı) İşlevinizin herkese açık olarak çağrılmasını önlemek için --no-allow-unauthenticated

Test etme

Aşağıdaki komutlarla işlevi test edin:

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

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

Yanıt olarak HTTP with Node.js in Cloud Run functions! mesajını görmeniz gerekir.

4. Pub/Sub işlevi

İkinci işlev için belirli bir konuda yayınlanan Pub/Sub mesajıyla tetiklenen bir Python işlevi oluşturalım.

Pub/Sub yetkilendirme jetonlarını ayarlama

Pub/Sub hizmet hesabını 8 Nisan 2021'de veya daha önce etkinleştirdiyseniz Pub/Sub hizmet hesabına iam.serviceAccountTokenCreator rolünü verin:

PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member  serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role roles/iam.serviceAccountTokenCreator

Oluştur

Örnekte kullanılacak bir Pub/Sub konusu oluşturun:

TOPIC=cloud-run-functions-pubsub-topic
gcloud pubsub topics create $TOPIC

Uygulama için bir klasör oluşturun ve bu klasöre gidin:

mkdir ../hello-pubsub
cd ../hello-pubsub

CloudEvent kimliğini içeren bir mesajı kaydeden bir main.py dosyası oluşturun:

import functions_framework

@functions_framework.cloud_event
def hello_pubsub(cloud_event):
   print('Pub/Sub with Python in Cloud Run functions! Id: ' + cloud_event['id'])

Bağımlılıkları belirtmek için aşağıdaki içeriklere sahip bir requirements.txt dosyası oluşturun:

functions-framework==3.*

Dağıt

İşlevi dağıtın:

gcloud run deploy python-pubsub-function \
       --source . \
       --function hello_pubsub \
       --base-image python313 \
       --region $REGION \
       --no-allow-unauthenticated

Hizmet hesabı kimliği için kullanılacak proje numarasını alın.

PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')

Tetikleyiciyi oluşturma

gcloud eventarc triggers create python-pubsub-function-trigger  \
    --location=$REGION \
    --destination-run-service=python-pubsub-function  \
    --destination-run-region=$REGION \
    --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
    --transport-topic=projects/$PROJECT_ID/topics/$TOPIC \
    --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

Test etme

Konuya mesaj göndererek işlevi test edin:

gcloud pubsub topics publish $TOPIC --message="Hello World"

Alınan CloudEvent'i günlüklerde görmeniz gerekir:

gcloud run services logs read python-pubsub-function --region $REGION --limit=10

5. Cloud Storage işlevi

Bir sonraki işlev için Cloud Storage paketindeki etkinliklere yanıt veren bir Node.js işlevi oluşturalım.

Kur

Cloud Storage işlevlerini kullanmak için Cloud Storage hizmet hesabına pubsub.publisher IAM rolünü verin:

SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT \
  --role roles/pubsub.publisher

Oluştur

Uygulama için bir klasör oluşturun ve bu klasöre gidin:

mkdir ../hello-storage
cd ../hello-storage

Yalnızca Cloud Storage etkinliklerine yanıt veren bir index.js dosyası oluşturun:

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

functions.cloudEvent('helloStorage', (cloudevent) => {
  console.log('Cloud Storage event with Node.js in Cloud Run functions!');
  console.log(cloudevent);
});

Bağımlılıkları belirtmek için bir package.json dosyası oluşturun:

{
  "name": "nodejs-crf-cloud-storage",
  "version": "0.0.1",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^2.0.0"
  }
}

Dağıt

Öncelikle bir Cloud Storage paketi oluşturun (veya mevcut bir paketi kullanın):

export BUCKET_NAME="gcf-storage-$PROJECT_ID"
​​export BUCKET="gs://gcf-storage-$PROJECT_ID"
gsutil mb -l $REGION $BUCKET

İşlevi dağıtın:

gcloud run deploy nodejs-crf-cloud-storage \
 --source . \
 --base-image nodejs22 \
 --function helloStorage \
 --region $REGION \
 --no-allow-unauthenticated

İşlev dağıtıldıktan sonra Cloud Console'un Cloud Run bölümünde görebilirsiniz.

Şimdi Eventarc tetikleyicisini oluşturun.

BUCKET_REGION=$REGION

gcloud eventarc triggers create nodejs-crf-cloud-storage-trigger \
  --location=$BUCKET_REGION \
  --destination-run-service=nodejs-crf-cloud-storage \
  --destination-run-region=$REGION \
  --event-filters="type=google.cloud.storage.object.v1.finalized" \
  --event-filters="bucket=$BUCKET_NAME" \
  --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

Test etme

Pakete dosya yükleyerek işlevi test edin:

echo "Hello World" > random.txt
gsutil cp random.txt $BUCKET/random.txt

Alınan CloudEvent'i günlüklerde görmeniz gerekir:

gcloud run services logs read nodejs-crf-cloud-storage --region $REGION --limit=10

6. Cloud Denetleme Günlükleri

Bir sonraki işlev için, Compute Engine sanal makine örneği oluşturulduğunda Cloud Denetleme Günlüğü etkinliği alan bir Node.js işlevi oluşturalım. Buna karşılık olarak, yeni oluşturulan sanal makineye sanal makinenin oluşturucusunu belirten bir etiket ekler.

Yeni oluşturulan Compute Engine VM'lerini belirleme

Compute Engine, bir sanal makine oluşturulduğunda 2 denetim günlüğü yayınlar.

İlki, sanal makine oluşturma işleminin başında yayınlanır. İkincisi, sanal makine oluşturulduktan sonra yayınlanır.

Denetleme günlüklerinde işlem alanları farklıdır ve first: true ile last: true değerlerini içerir. İkinci denetleme günlüğü, bir örneği etiketlemek için ihtiyaç duyduğumuz tüm bilgileri içerir. Bu nedenle, Cloud Run işlevlerinde bunu algılamak için last: true işaretini kullanırız.

Kur

Cloud Audit Log işlevlerini kullanmak için Eventarc'ta denetleme günlüklerini etkinleştirmeniz gerekir. Ayrıca eventarc.eventReceiver rolüne sahip bir hizmet hesabı kullanmanız gerekir.

  1. Compute Engine API için Cloud Audit Logs Admin Read, Data Read ve Data Write günlük türlerini etkinleştirin.
  2. Varsayılan Compute Engine hizmet hesabına eventarc.eventReceiver IAM rolünü verin:
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
  --role roles/eventarc.eventReceiver

İşlevi oluşturma

Bu codelab'de node.js kullanılmaktadır ancak https://github.com/GoogleCloudPlatform/eventarc-samples adresinde başka örnekler de bulabilirsiniz.

package.json dosyası oluşturma

{
  "dependencies": {
    "googleapis": "^84.0.0"
  }
}

node.js dosyası oluşturma

// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const { google } = require("googleapis");
var compute = google.compute("v1");

exports.labelVmCreation = async (cloudevent) => {
  const data = cloudevent.body;

  // in case an event has >1 audit log
  // make sure we respond to the last event
  if (!data.operation || !data.operation.last) {
    console.log("Operation is not last, skipping event");
    return;
  }

  // projects/dogfood-gcf-saraford/zones/us-central1-a/instances/instance-1
  var resourceName = data.protoPayload.resourceName;
  var resourceParts = resourceName.split("/");
  var project = resourceParts[1];
  var zone = resourceParts[3];
  var instanceName = resourceParts[5];
  var username = data.protoPayload.authenticationInfo.principalEmail.split("@")[0];

  console.log(`Setting label username: ${username} to instance ${instanceName} for zone ${zone}`);

  var authClient = await google.auth.getClient({
    scopes: ["https://www.googleapis.com/auth/cloud-platform"]
  });

  // per docs: When updating or adding labels in the API,
  // you need to provide the latest labels fingerprint with your request,
  // to prevent any conflicts with other requests.
  var labelFingerprint = await getInstanceLabelFingerprint(authClient, project, zone, instanceName);

  var responseStatus = await setVmLabel(
    authClient,
    labelFingerprint,
    username,
    project,
    zone,
    instanceName
  );

  // log results of setting VM label
  console.log(JSON.stringify(responseStatus, null, 2));
};

async function getInstanceLabelFingerprint(authClient, project, zone, instanceName) {
  var request = {
    project: project,
    zone: zone,
    instance: instanceName,
    auth: authClient
  };

  var response = await compute.instances.get(request);
  var labelFingerprint = response.data.labelFingerprint;
  return labelFingerprint;
}

async function setVmLabel(authClient, labelFingerprint, username, project, zone, instanceName) {
  var request = {
    project: project,
    zone: zone,
    instance: instanceName,

    resource: {
      labels: { "creator": username },
      labelFingerprint: labelFingerprint
    },

    auth: authClient
  };

  var response = await compute.instances.setLabels(request);
  return response.statusText;
}

Dağıt

İşlevi dağıtın:

gcloud run deploy gce-vm-labeler \
  --source . \
  --function labelVmCreation \
  --region $REGION \
  --no-allow-unauthenticated

Şimdi tetikleyiciyi oluşturun. Fonksiyonun, --trigger-event-filters işaretiyle Compute Engine eklemeleri için denetleme günlüklerini nasıl filtrelediğine dikkat edin.

gcloud eventarc triggers create gce-vm-labeler-trigger \
  --location=$REGION \
  --destination-run-service=gce-vm-labeler \
  --destination-run-region=$REGION \
  --event-filters="type=google.cloud.audit.log.v1.written,serviceName=compute.googleapis.com,methodName=v1.compute.instances.insert" \
  --service-account=$ROJECT_NUMBER-compute@developer.gserviceaccount.com

Test etme

Ortam değişkenlerini ayarlayın:

# if you're using europe-west1 as your region
ZONE=europe-west1-d
VM_NAME=codelab-crf-auditlog

Sanal makine oluşturmak için aşağıdaki komutu çalıştırın:

gcloud compute instances create $VM_NAME --zone=$ZONE --machine-type=e2-medium --image-family=debian-11  --image-project=debian-cloud

Sanal makine oluşturma işlemi tamamlandıktan sonra, Cloud Console'daki sanal makinede Temel bilgiler bölümünde veya aşağıdaki komutu kullanarak eklenen creator etiketini görmeniz gerekir:

gcloud compute instances describe $VM_NAME --zone=$ZONE

Çıkışta etiketi aşağıdaki örnekteki gibi görmeniz gerekir:

...
labelFingerprint: ULU6pAy2C7s=
labels:
  creator: atameldev
...

Temizleme

Sanal makine örneğini sildiğinizden emin olun. Bu laboratuvarda tekrar kullanılmayacaktır.

gcloud compute instances delete $VM_NAME --zone=$ZONE

7. Trafiği bölme

Cloud Run işlevleri, işlevlerinizin birden fazla revizyonunu destekler, trafiği farklı revizyonlar arasında böler ve işlevinizi önceki bir sürüme geri alır.

Bu adımda, bir işlevin 2 düzeltmesini dağıtacak ve ardından trafiği aralarında %50-%50 böleceksiniz.

Oluştur

Uygulama için bir klasör oluşturun ve bu klasöre gidin:

mkdir ../traffic-splitting
cd ../traffic-splitting

Bir renk ortam değişkenini okuyan ve bu arka plan renginde Hello World ile yanıt veren bir Python işlevi içeren bir main.py dosyası oluşturun:

import os

color = os.environ.get('COLOR')

def hello_world(request):
    return f'<body style="background-color:{color}"><h1>Hello World!</h1></body>'

Bağımlılıkları belirtmek için aşağıdaki içeriklere sahip bir requirements.txt dosyası oluşturun:

functions-framework==3.*

Dağıt

Fonksiyonun ilk düzeltmesini turuncu arka planla dağıtın:

COLOR=orange
gcloud run deploy hello-world-colors \
 --source . \
 --base-image python313 \
 --function hello_world \
 --region $REGION \
 --allow-unauthenticated \
 --update-env-vars COLOR=$COLOR

Bu noktada, HTTP tetikleyiciyi (yukarıdaki dağıtım komutunun URI çıkışı) tarayıcınızda görüntüleyerek işlevi test ederseniz turuncu arka planlı Hello World görmeniz gerekir:

36ca0c5f39cc89cf.png

İkinci düzeltmeyi sarı arka planla dağıtın:

COLOR=yellow
gcloud run deploy hello-world-colors \
 --source . \
 --base-image python313 \
 --function hello_world \
 --region $REGION \
 --allow-unauthenticated \
 --update-env-vars COLOR=$COLOR

Bu en son düzeltme olduğundan işlevi test ederseniz sarı arka planlı Hello World görmeniz gerekir:

391286a08ad3cdde.png

Trafiği 50-50 bölme

Turuncu ve sarı revizyonlar arasında trafiği bölmek için Cloud Run hizmetlerinin revizyon kimliklerini bulmanız gerekir. Düzeltme kimliklerini görmek için kullanılan komut:

gcloud run revisions list --service hello-world-colors \
  --region $REGION --format 'value(REVISION)'

Çıkış şu şekilde görünmelidir:

hello-world-colors-00001-man
hello-world-colors-00002-wok

Şimdi trafiği bu iki düzeltme arasında aşağıdaki şekilde bölün (X-XXX değerini düzeltme adlarınıza göre güncelleyin):

gcloud run services update-traffic hello-world-colors \
  --region $REGION \
  --to-revisions hello-world-colors-0000X-XXX=50,hello-world-colors-0000X-XXX=50

Test etme

Herkese açık URL'sini ziyaret ederek işlevi test edin. Yarı yarıya olacak şekilde turuncu ve sarı düzeltmeyi görmelisiniz:

36ca0c5f39cc89cf.png 391286a08ad3cdde.png

Daha fazla bilgi için geri alma, kademeli kullanıma sunma ve trafik taşıma başlıklı makaleyi inceleyin.

8. Minimum örnek sayısı

Cloud Run işlevlerinde, sıcak tutulacak ve isteklere hizmet vermeye hazır olacak minimum işlev örneği sayısı belirtebilirsiniz. Bu, sıfırdan başlatma sayısını sınırlamak için kullanışlıdır.

Bu adımda, yavaş başlatılan bir işlevi dağıtacaksınız. Soğuk başlatma sorununu gözlemlersiniz. Ardından, sıfırdan başlatmayı ortadan kaldırmak için minimum örnek değerini 1 olarak ayarlayarak işlevi dağıtırsınız.

Oluştur

Uygulama için bir klasör oluşturun ve bu klasöre gidin:

mkdir ../min-instances
cd ../min-instances

main.go dosyası oluşturun. Bu Go hizmetinde, uzun bir başlatma işlemini simüle etmek için 10 saniye boyunca uyku modunda kalan bir init işlevi var. Ayrıca, HTTP çağrılarına yanıt veren bir HelloWorld işlevi de vardır:

package p

import (
        "fmt"
        "net/http"
        "time"
)

func init() {
        time.Sleep(10 * time.Second)
}

func HelloWorld(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "Slow HTTP Go in Cloud Run functions!")
}

Dağıt

İşlevin ilk düzeltmesini varsayılan minimum örnek değeri olan sıfırla dağıtın:

gcloud run deploy go-slow-function \
 --source . \
 --base-image go123 \
 --function HelloWorld \
 --region $REGION \
 --no-allow-unauthenticated

Aşağıdaki komutla işlevi test edin:

# get the Service URL
SERVICE_URL="$(gcloud run services describe go-slow-function --region $REGION --format 'value(status.url)')"

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

İlk aramada 10 saniyelik bir gecikme (soğuk başlatma) yaşarsınız ve ardından mesajı görürsünüz. Sonraki aramalar hemen döndürülmelidir.

Minimum örnek sayısını ayarlama

İlk istekte sıfırdan başlatma sorununu gidermek için işlevi aşağıdaki gibi --min-instances bayrağı 1 olarak ayarlanmış şekilde yeniden dağıtın:

gcloud run deploy go-slow-function \
 --source . \
 --base-image go123 \
 --function HelloWorld \
 --region $REGION \
 --no-allow-unauthenticated \
 --min-instances 1

Test etme

İşlevi tekrar test edin:

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

Artık ilk istekte 10 saniyelik gecikme görmemeniz gerekir. Minimum örnekler sayesinde, ilk çağırmada (uzun süre kullanılmadıktan sonra) karşılaşılan soğuk başlatma sorunu ortadan kalktı.

Daha fazla bilgi için minimum örnekleri kullanma başlıklı makaleyi inceleyin.

9. Tebrikler!

Codelab'i tamamladığınız için tebrikler.

İşlediğimiz konular

  • Cloud Run işlevlerine genel bakış ve otomatik temel görüntü güncellemelerini kullanma
  • HTTP çağrılarına yanıt veren bir işlev yazma
  • Pub/Sub mesajlarına yanıt veren bir işlev yazma
  • Cloud Storage etkinliklerine yanıt veren bir işlev yazma
  • Trafiği iki düzeltme arasında bölme
  • Minimum örneklerle soğuk başlatma sorununu nasıl ortadan kaldırabilirsiniz?