Cloud Run işlerini kullanmaya başlama

1. Giriş

1965fab24c502bd5.png

Genel Bakış

Cloud Run hizmetleri, HTTP isteklerini dinleyerek süresiz olarak çalışan container'lar için uygundur. Cloud Run işleri ise tamamlanana kadar (şu anda en fazla 24 saat) çalışan ve isteklere hizmet vermeyen container'lar için daha uygundur. Örneğin, bir veritabanındaki kayıtları işleme, Cloud Storage paketindeki dosya listesini işleme veya Pi sayısını hesaplama gibi uzun süren işlemler Cloud Run işi olarak uygulandığında iyi sonuç verir.

İşler, istekleri sunma veya bir bağlantı noktasını dinleme özelliğine sahip değildir. Bu nedenle, Cloud Run hizmetlerinin aksine, işler bir web sunucusu içermemelidir. Bunun yerine, iş kapsayıcıları tamamlandığında çıkmalıdır.

Cloud Run işlerinde, görev sayısını belirterek kapsayıcınızın birden fazla kopyasını paralel olarak çalıştırabilirsiniz. Her görev, kapsayıcının çalışan bir kopyasını temsil eder. Her görev, verilerinizin bir alt kümesini bağımsız olarak işleyebiliyorsa birden fazla görev kullanmak yararlıdır. Örneğin, Cloud SQL'den 10.000 kaydı veya Cloud Storage'dan 10.000 dosyayı işlemek için her biri 1.000 kayıt ya da dosya işleyen 10 görev kullanılarak daha hızlı sonuç alınabilir.

Cloud Run işlerini kullanmak iki adımlı bir süreçtir:

  1. İş oluşturma: Bu, işi çalıştırmak için gereken tüm yapılandırmayı (ör. kapsayıcı resmi, bölge, ortam değişkenleri) kapsar.
  2. İşi çalıştırma: Bu işlem, işin yeni bir yürütmesini oluşturur. İsteğe bağlı olarak, Cloud Scheduler kullanarak işinizi planlı olarak çalışacak şekilde ayarlayın.

Bu codelab'de öncelikle web sayfalarının ekran görüntülerini alıp Cloud Storage'da depolamak için bir Node.js uygulamasını keşfedeceksiniz. Ardından uygulama için bir kapsayıcı görüntüsü oluşturur, bunu Cloud Run işlerinde çalıştırır, işi daha fazla web sayfası işleyecek şekilde günceller ve işi Cloud Scheduler ile planlı olarak çalıştırırsınız.

Neler öğreneceksiniz?

  • Web sayfalarının ekran görüntülerini almak için uygulamaları kullanma
  • Uygulama için container görüntüsü oluşturma
  • Uygulama için Cloud Run işi oluşturma
  • Uygulamayı Cloud Run işi olarak çalıştırma
  • İşi güncelleme
  • Cloud Scheduler ile işi nasıl planlayacağınız açıklanmaktadır.

2. Kurulum ve Gereksinimler

Kendi hızınızda ortam kurulumu

  1. Google Cloud Console'da oturum açın ve yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanın. Gmail veya Google Workspace hesabınız yoksa oluşturmanız gerekir.

295004821bab6a87.png

37d264871000675d.png

96d86d3d5655cdbe.png

  • Proje adı, bu projenin katılımcıları için görünen addır. Google API'leri tarafından kullanılmayan bir karakter dizesidir. Dilediğiniz zaman güncelleyebilirsiniz.
  • Proje kimliği, tüm Google Cloud projelerinde benzersizdir ve sabittir (ayarlandıktan sonra değiştirilemez). Cloud Console, benzersiz bir dizeyi otomatik olarak oluşturur. Genellikle bu dizenin ne olduğuyla ilgilenmezsiniz. Çoğu codelab'de proje kimliğinize (genellikle PROJECT_ID olarak tanımlanır) başvurmanız gerekir. Oluşturulan kimliği beğenmezseniz başka bir rastgele kimlik oluşturabilirsiniz. Dilerseniz kendi adınızı deneyerek kullanılabilir olup olmadığını kontrol edebilirsiniz. Bu adım tamamlandıktan sonra değiştirilemez ve proje süresince geçerli kalır.
  • Bazı API'lerin kullandığı üçüncü bir değer olan Proje Numarası da vardır. Bu üç değer hakkında daha fazla bilgiyi belgelerde bulabilirsiniz.
  1. Ardından, Cloud kaynaklarını/API'lerini kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir. Bu codelab'i tamamlamak size çok fazla zaman kaybettirmez. Bu eğitimin ötesinde faturalandırılmayı önlemek için kaynakları kapatmak üzere oluşturduğunuz kaynakları veya projeyi silebilirsiniz. Yeni Google Cloud kullanıcıları 300 ABD doları değerinde ücretsiz deneme programından yararlanabilir.

Cloud Shell'i Başlatma

Google Cloud, dizüstü bilgisayarınızdan uzaktan çalıştırılabilir. Ancak bu codelab'de, Cloud'da çalışan bir komut satırı ortamı olan Google Cloud Shell'i kullanacaksınız.

Google Cloud Console'da sağ üstteki araç çubuğunda Cloud Shell simgesini tıklayın:

Cloud Shell'i etkinleştirme

Ortamın temel hazırlığı ve bağlanması yalnızca birkaç dakikanızı alır. İşlem tamamlandığında aşağıdakine benzer bir sonuç görürsünüz:

Ortamın bağlandığını gösteren Google Cloud Shell terminalinin ekran görüntüsü

Bu sanal makine, ihtiyaç duyacağınız tüm geliştirme araçlarını içerir. 5 GB boyutunda kalıcı bir ana dizin sunar ve Google Cloud üzerinde çalışır. Bu sayede ağ performansı ve kimlik doğrulama önemli ölçüde güçlenir. Bu codelab'deki tüm çalışmalarınızı tarayıcıda yapabilirsiniz. Herhangi bir şey yüklemeniz gerekmez.

gcloud'u ayarlama

Cloud Shell'de proje kimliğinizi ve Cloud Run işini dağıtmak istediğiniz bölgeyi ayarlayın. Bunları PROJECT_ID ve REGION değişkenleri olarak kaydedin. İleride Cloud Run konumlarından birini seçebileceksiniz.

PROJECT_ID=[YOUR-PROJECT-ID]
REGION=us-central1
gcloud config set core/project $PROJECT_ID

API'leri etkinleştir

Gerekli tüm hizmetleri etkinleştirin:

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

3. Kodu alın

Öncelikle web sayfalarının ekran görüntülerini almak ve bunları Cloud Storage'de depolamak için bir Node.js uygulamasını keşfedersiniz. Daha sonra, uygulama için bir container görüntüsü oluşturup Cloud Run'da iş olarak çalıştıracaksınız.

Cloud Shell'den bu depodaki uygulama kodunu klonlamak için aşağıdaki komutu çalıştırın:

git clone https://github.com/GoogleCloudPlatform/jobs-demos.git

Uygulamayı içeren dizine gidin:

cd jobs-demos/screenshot

Aşağıdaki dosya düzenini görmelisiniz:

screenshot
 |
 ├── Dockerfile
 ├── README.md
 ├── screenshot.js
 ├── package.json

Her dosyanın kısa açıklaması aşağıda verilmiştir:

  • screenshot.js, uygulama için Node.js kodunu içerir.
  • package.json, kitaplık bağımlılıklarını tanımlar.
  • Dockerfile, container görüntüsünü tanımlar.

4. Kodu keşfetme

Kodu keşfetmek için Cloud Shell penceresinin üst kısmındaki Open Editor düğmesini tıklayarak yerleşik metin düzenleyiciyi kullanın.

15a2cdc9b7f6dfc6.png

Her dosyanın kısa açıklaması aşağıda verilmiştir.

screenshot.js

screenshot.js önce Puppeteer ve Cloud Storage'ı bağımlılık olarak ekler. Puppeteer, web sayfalarının ekran görüntülerini almak için kullandığınız bir Node.js kitaplığıdır:

const puppeteer = require('puppeteer');
const {Storage} = require('@google-cloud/storage');

Puppeteer'ı başlatmak için initBrowser işlevi, belirli bir URL'nin ekran görüntülerini almak için ise takeScreenshot işlevi vardır:

async function initBrowser() {
  console.log('Initializing browser');
  return await puppeteer.launch();
}

async function takeScreenshot(browser, url) {
  const page = await browser.newPage();

  console.log(`Navigating to ${url}`);
  await page.goto(url);

  console.log(`Taking a screenshot of ${url}`);
  return await page.screenshot({
    fullPage: true
  });
}

Ardından, Cloud Storage paketi alma veya oluşturma işlevi ve web sayfasının ekran görüntüsünü pakete yükleme işlevi yer alır:

async function createStorageBucketIfMissing(storage, bucketName) {
  console.log(`Checking for Cloud Storage bucket '${bucketName}' and creating if not found`);
  const bucket = storage.bucket(bucketName);
  const [exists] = await bucket.exists();
  if (exists) {
    // Bucket exists, nothing to do here
    return bucket;
  }

  // Create bucket
  const [createdBucket] = await storage.createBucket(bucketName);
  console.log(`Created Cloud Storage bucket '${createdBucket.name}'`);
  return createdBucket;
}

async function uploadImage(bucket, taskIndex, imageBuffer) {
  // Create filename using the current time and task index
  const date = new Date();
  date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
  const filename = `${date.toISOString()}-task${taskIndex}.png`;

  console.log(`Uploading screenshot as '${filename}'`)
  await bucket.file(filename).save(imageBuffer);
}

Son olarak, main işlevi giriş noktasıdır:

async function main(urls) {
  console.log(`Passed in urls: ${urls}`);

  const taskIndex = process.env.CLOUD_RUN_TASK_INDEX || 0;
  const url = urls[taskIndex];
  if (!url) {
    throw new Error(`No url found for task ${taskIndex}. Ensure at least ${parseInt(taskIndex, 10) + 1} url(s) have been specified as command args.`);
  }
  const bucketName = process.env.BUCKET_NAME;
  if (!bucketName) {
    throw new Error('No bucket name specified. Set the BUCKET_NAME env var to specify which Cloud Storage bucket the screenshot will be uploaded to.');
  }

  const browser = await initBrowser();
  const imageBuffer = await takeScreenshot(browser, url).catch(async err => {
    // Make sure to close the browser if we hit an error.
    await browser.close();
    throw err;
  });
  await browser.close();

  console.log('Initializing Cloud Storage client')
  const storage = new Storage();
  const bucket = await createStorageBucketIfMissing(storage, bucketName);
  await uploadImage(bucket, taskIndex, imageBuffer);

  console.log('Upload complete!');
}

main(process.argv.slice(2)).catch(err => {
  console.error(JSON.stringify({severity: 'ERROR', message: err.message}));
  process.exit(1);
});

main yöntemiyle ilgili olarak aşağıdakilere dikkat edin:

  • URL'ler bağımsız değişken olarak iletilir.
  • Paket adı, kullanıcı tarafından tanımlanan BUCKET_NAME ortam değişkeni olarak iletilir. Paket adı, tüm Google Cloud'da global olarak benzersiz olmalıdır.
  • Cloud Run işleri tarafından CLOUD_RUN_TASK_INDEX ortam değişkeni iletilir. Cloud Run işleri, uygulamanın birden fazla kopyasını benzersiz görevler olarak çalıştırabilir. CLOUD_RUN_TASK_INDEX, çalışan görevin dizinini temsil eder. Kod, Cloud Run işlerinin dışında çalıştırıldığında varsayılan olarak sıfır olur. Uygulama birden fazla görev olarak çalıştırıldığında her görev/kapsayıcı, sorumlu olduğu URL'yi alır, ekran görüntüsü alır ve görüntüyü pakete kaydeder.

package.json

package.json dosyası uygulamayı tanımlar ve Cloud Storage ile Puppeteer'ın bağımlılıklarını belirtir:

{
  "name": "screenshot",
  "version": "1.0.0",
  "description": "Create a job to capture screenshots",
  "main": "screenshot.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Google LLC",
  "license": "Apache-2.0",
  "dependencies": {
    "@google-cloud/storage": "^5.18.2",
    "puppeteer": "^13.5.1"
  }
}

Dockerfile

Dockerfile, gerekli tüm kitaplıklar ve bağımlılıklarla birlikte uygulamanın kapsayıcı görüntüsünü tanımlar:

FROM ghcr.io/puppeteer/puppeteer:16.1.0
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
ENTRYPOINT ["node", "screenshot.js"]

5. İş dağıtma

İş oluşturmadan önce, işi çalıştırmak için kullanacağınız bir hizmet hesabı oluşturmanız gerekir.

gcloud iam service-accounts create screenshot-sa --display-name="Screenshot app service account"

Hizmet hesabına storage.admin rolünü verin. Böylece bu hesap, paket ve nesne oluşturmak için kullanılabilir.

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --role roles/storage.admin \
  --member serviceAccount:screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com

Artık işi çalıştırmak için gereken yapılandırmayı içeren bir Cloud Run işi dağıtmaya hazırsınız.

gcloud beta run jobs deploy screenshot \
  --source=. \
  --args="https://example.com" \
  --args="https://cloud.google.com" \
  --tasks=2 \
  --task-timeout=5m \
  --region=$REGION \
  --set-env-vars=BUCKET_NAME=screenshot-$PROJECT_ID-$RANDOM \
  --service-account=screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com

Bu işlem, kaynağa dayalı dağıtımı kullanır ve Cloud Run işini yürütmeden oluşturur.

Web sayfalarının nasıl bağımsız değişken olarak iletildiğine dikkat edin. Ekran görüntülerinin kaydedileceği paket adı, ortam değişkeni olarak iletilir.

--tasks işaretini kullanarak çalıştırılacak görev sayısını belirterek kapsayıcınızın birden fazla kopyasını aynı anda çalıştırabilirsiniz. Her görev, kapsayıcının çalışan bir kopyasını temsil eder. Her görev, verilerinizin bir alt kümesini bağımsız olarak işleyebiliyorsa birden fazla görev kullanmak yararlıdır. Bunu kolaylaştırmak için her görev, CLOUD_RUN_TASK_INDEX ortam değişkeninde depolanan kendi dizinini bilir. Hangi görevin verilerin hangi alt kümesini işleyeceğini belirlemek kodunuzun sorumluluğundadır. Bu örnekteki --tasks=2 işaretine dikkat edin. Bu sayede, işlemek istediğimiz 2 URL için 2 kapsayıcının çalışması sağlanır.

Her görev en fazla 24 saat çalışabilir. Bu örnekte yaptığımız gibi --task-timeout işaretini kullanarak bu zaman aşımını azaltabilirsiniz. İşin başarıyla tamamlanması için tüm görevlerin başarılı olması gerekir. Varsayılan olarak, başarısız olan görevler yeniden denenmez. Görevleri, başarısız olduklarında yeniden denenecek şekilde yapılandırabilirsiniz. Herhangi bir görev, yeniden deneme sayısını aşarsa tüm iş başarısız olur.

Varsayılan olarak işiniz mümkün olduğunca çok görevle paralel olarak çalışır. Bu değer, işinizdeki görev sayısına eşit olur (en fazla 100). Ölçeklenebilirliği sınırlı bir arka uca erişen işler için paralelliği daha düşük ayarlayabilirsiniz. Örneğin, sınırlı sayıda etkin bağlantıyı destekleyen bir veritabanı. --parallelism işaretiyle paralelliği azaltabilirsiniz.

6. İş çalıştırma

İşi çalıştırmadan önce, oluşturulduğunu görmek için işi listeleyin:

gcloud run jobs list

✔
JOB: screenshot
REGION: us-central
LAST RUN AT:
CREATED: 2022-02-22 12:20:50 UTC

Aşağıdaki komutla işi çalıştırın:

gcloud run jobs execute screenshot --region=$REGION

Bu işlem, işi yürütür. Mevcut ve geçmiş yürütmeleri listeleyebilirsiniz:

gcloud run jobs executions list --job screenshot --region=$REGION

...
JOB: screenshot
EXECUTION: screenshot-znkmm
REGION: $REGION
RUNNING: 1
COMPLETE: 1 / 2
CREATED: 2022-02-22 12:40:42 UTC

Yürütmeyi açıklayın. Yeşil onay işaretini ve tasks completed successfully mesajını görmeniz gerekir:

gcloud run jobs executions describe screenshot-znkmm --region=$REGION

✔ Execution screenshot-znkmm in region $REGION
2 tasks completed successfully


Image:           $REGION-docker.pkg.dev/$PROJECT_ID/containers/screenshot at 311b20d9...
Tasks:           2
Args:            https://example.com https://cloud.google.com
Memory:          1Gi
CPU:             1000m
Task Timeout:    3600s
Parallelism:     2
Service account: 11111111-compute@developer.gserviceaccount.com
Env vars:
  BUCKET_NAME    screenshot-$PROJECT_ID-$RANDOM

Durumu görmek için Cloud Console'un Cloud Run işleri sayfasını da kontrol edebilirsiniz:

1afde14d65f0d9ce.png

Cloud Storage paketini kontrol ederseniz oluşturulan iki ekran görüntüsü dosyasını görmeniz gerekir:

7c4d355f6f65106.png

Bazen, yürütmeyi tamamlanmadan önce durdurmanız gerekebilir. Örneğin, işi farklı parametrelerle çalıştırmanız gerektiğini fark etmiş olabilirsiniz veya kodda bir hata vardır ve gereksiz işlem süresi kullanmak istemiyorsunuzdur.

İşinizin yürütülmesini durdurmak için yürütmeyi silmeniz gerekir:

gcloud run jobs executions delete screenshot-znkmm --region=$REGION

7. İşi güncelleme

Container'ınızın yeni sürümleri, bir sonraki yürütmede Cloud Run işleri tarafından otomatik olarak alınmaz. İşinizin kodunu değiştirirseniz kapsayıcıyı yeniden oluşturmanız ve işinizi güncellemeniz gerekir. Etiketli resimler kullanmak, resmin hangi sürümünün kullanıldığını belirlemenize yardımcı olur.

Benzer şekilde, yapılandırma değişkenlerinden bazılarını güncellemek istiyorsanız işi de güncellemeniz gerekir. İşin sonraki yürütmelerinde yeni kapsayıcı ve yapılandırma ayarları kullanılır.

İşi güncelleyin ve uygulamanın ekran görüntüsünü aldığı sayfaları --args işaretinde değiştirin. Ayrıca, sayfa sayısını yansıtacak şekilde --tasks işaretini de güncelleyin.

gcloud run jobs update screenshot \
  --args="https://www.pinterest.com" \
  --args="https://www.apartmenttherapy.com" \
  --args="https://www.google.com" \
  --region=$REGION \
  --tasks=3

İşi tekrar çalıştırın. Yürütme işlemlerinin tamamlanmasını beklemek için --wait işaretini iletin:

gcloud run jobs execute screenshot --region=$REGION --wait

Birkaç saniye sonra, pakete 3 ekran görüntüsü daha eklenir:

ed0cbe0b5a5f9144.png

8. İş planlama

Şu ana kadar işleri manuel olarak çalıştırıyorsunuz. Gerçek hayattaki bir senaryoda, işleri bir etkinliğe yanıt olarak veya belirli bir programa göre çalıştırmak isteyebilirsiniz. Cloud Scheduler kullanarak ekran görüntüsü işini planlı olarak nasıl çalıştıracağımızı görelim.

Öncelikle Cloud Scheduler API'nin etkinleştirildiğinden emin olun:

gcloud services enable cloudscheduler.googleapis.com

Cloud Run işleri ayrıntılar sayfasına gidin ve Triggers bölümünü tıklayın:

3ae456368905472f.png

Add Scheduler Trigger düğmesini seçin:

48cbba777f75e1eb.png

Sağ tarafta bir panel açılır. Bu yapılandırmayla her gün saat 9:00'da çalışacak bir Scheduler işi oluşturun ve Continue seçeneğini belirleyin:

81fd098be0db216.png

Sonraki sayfada varsayılan işlem hizmeti hesabını ve Create simgesini seçin:

fe479501dfb91f9f.png

Şimdi yeni bir Cloud Scheduler tetikleyicisi oluşturulduğunu görmelisiniz:

5a7bc6d96b970b92.png

Cloud Scheduler sayfasına gitmek için View Details simgesini tıklayın.

Planlayıcının devreye girmesi için saat 09:00'a kadar bekleyebilir veya Force Run simgesini seçerek Cloud Scheduler'ı manuel olarak tetikleyebilirsiniz:

959525f2c8041a6a.png

Birkaç saniye sonra Cloud Scheduler işinin başarıyla yürütüldüğünü görürsünüz:

d64e03fc84d61145.png

Ayrıca Cloud Scheduler'dan gelen çağrı tarafından eklenen 3 ekran görüntüsü daha görmeniz gerekir:

56398a0e827de8b0.png

9. Tebrikler

Tebrikler, codelab'i tamamladınız.

Temizleme (isteğe bağlı)

Ücretlendirilmemek için kaynakları temizlemeniz önerilir.

Projeye ihtiyacınız yoksa projeyi silebilirsiniz:

gcloud projects delete $PROJECT_ID

Projeye ihtiyacınız varsa kaynakları tek tek silebilirsiniz.

Kaynak kodu silin:

rm -rf ~/jobs-demos/

Artifact Registry deposunu silin:

gcloud artifacts repositories delete containers --location=$REGION

Hizmet hesabını silin:

gcloud iam service-accounts delete screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com

Cloud Run işini silin:

gcloud run jobs delete screenshot --region=$REGION

Cloud Scheduler işini silin:

gcloud scheduler jobs delete screenshot-scheduler-trigger --location=$REGION

Cloud Storage paketini silin:

gcloud storage rm --recursive gs://screenshot-$PROJECT_ID

İşlediğimiz konular

  • Web sayfalarının ekran görüntülerini almak için uygulamaları kullanma
  • Uygulama için container görüntüsü oluşturma
  • Uygulama için Cloud Run işi oluşturma
  • Uygulamayı Cloud Run işi olarak çalıştırma
  • İşi güncelleme
  • Cloud Scheduler ile işi nasıl planlayacağınız açıklanmaktadır.