Cloud Run işlerini kullanmaya başlama

1. Giriş

1965fab24c502bd5.png

Genel Bakış

Cloud Run hizmetleri, HTTP isteklerini süresiz olarak dinleyen container'lar için uygundur. Cloud Run işleri ise sonuna kadar çalışan (şu anda 24 saate kadar) ve istek sunmayan container'lar için daha uygundur. Örneğin, bir veritabanından kayıtları işlemek, Cloud Storage paketindeki dosya listesini işlemek veya Pi'yi hesaplama gibi uzun süreli bir işlem, Cloud Run işi olarak uygulandığında iyi sonuç verir.

İşler, istek sunma veya bir bağlantı noktasında dinleme yetkisine sahip değildir. Yani, Cloud Run hizmetlerinin aksine işlerin bir web sunucusu paket halinde sunulmaması gerekir. Bunun yerine, iş kapsayıcıları tamamlandığında çıkış yapmalıdır.

Cloud Run işlerinde, bir dizi görev belirterek container'ı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, her biri paralel olarak 1.000 kayıt veya dosya işleyen 10 görevle, Cloud SQL'den 10.000 kayıt veya Cloud Storage'dan 10.000 dosya işleme süreci daha hızlı tamamlanabilir.

Cloud Run işlerini kullanmak iki adımlı bir işlemdir:

  1. İş oluşturma: Bu, işi çalıştırmak için gereken tüm yapılandırmayı (ör. container görüntüsü, bölge, ortam değişkenleri) içerir.
  2. İşi çalıştırma: İşin yeni bir yürütülmesini sağlar. İsteğe bağlı olarak, Cloud Scheduler kullanarak işinizi bir plana göre çalışacak şekilde ayarlayın.

Bu codelab'de, web sayfalarının ekran görüntülerini almak ve Cloud Storage'da depolamak için önce bir Node.js uygulamasını keşfedeceksiniz. Ardından, uygulama için bir container görüntüsü derler, Cloud Run işlerinde çalıştırır, daha fazla web sayfası işlemek için işi güncellersiniz ve Cloud Scheduler ile işi plana göre çalıştırırsınız.

Neler öğreneceksiniz?

  • Web sayfalarının ekran görüntülerini almak için bir uygulama nasıl kullanılır?
  • Uygulama için container görüntüsü derleme.
  • Uygulama için Cloud Run işi oluşturma.
  • Uygulamanın Cloud Run işi olarak nasıl çalıştırılacağını öğreneceksiniz.
  • İşin güncellenmesi
  • Cloud Scheduler ile işin nasıl planlanacağı.

2. Kurulum ve Gereksinimler

Kendi hızınızda ortam kurulumu

  1. Google Cloud Console'da oturum açıp yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanın. Gmail veya Google Workspace hesabınız yoksa hesap 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. İstediğiniz zaman güncelleyebilirsiniz.
  • Proje Kimliği, tüm Google Cloud projelerinde benzersizdir ve değiştirilemez (belirlendikten sonra değiştirilemez). Cloud Console, otomatik olarak benzersiz bir dize oluşturur. bunun ne olduğunu umursamıyorsunuz. Çoğu codelab'de proje kimliğinizi (genellikle PROJECT_ID olarak tanımlanır) belirtmeniz gerekir. Oluşturulan kimliği beğenmezseniz rastgele bir kimlik daha oluşturabilirsiniz. Alternatif olarak, kendi ölçümünüzü deneyip mevcut olup olmadığına bakabilirsiniz. Bu adımdan sonra değiştirilemez ve proje süresince kalır.
  • Bilginiz olması açısından, bazı API'lerin kullandığı üçüncü bir değer, yani Proje Numarası daha vardır. Bu değerlerin üçü hakkında daha fazla bilgiyi belgelerde bulabilirsiniz.
  1. Sonraki adımda, Cloud kaynaklarını/API'lerini kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir. Bu codelab'i çalıştırmanın maliyeti, yüksek değildir. Bu eğitim dışında faturalandırmanın tekrarlanmasını önlemek amacıyla kaynakları kapatmak için oluşturduğunuz kaynakları silebilir veya projeyi silebilirsiniz. Yeni Google Cloud kullanıcıları 300 ABD doları değerindeki ücretsiz denemeden yararlanabilir.

Cloud Shell'i Başlatma

Google Cloud dizüstü bilgisayarınızdan uzaktan çalıştırılabilse de 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 bulunan Cloud Shell simgesini tıklayın:

84688aa223b1c3a2.png

Ortamı sağlamak ve bağlamak yalnızca birkaç dakika sürer. Tamamlandığında şuna benzer bir sonuç görmeniz gerekir:

320e18fedb7fbe0.png

İhtiyacınız olan tüm geliştirme araçlarını bu sanal makinede bulabilirsiniz. 5 GB boyutunda kalıcı bir ana dizin sunar ve Google Cloud üzerinde çalışarak ağ performansını ve kimlik doğrulamasını büyük ölçüde iyileştirir. Bu codelab'deki tüm çalışmalarınız tarayıcıda yapılabilir. Herhangi bir şey yüklemeniz gerekmez.

gcloud'u kurun

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. Gelecekte Cloud Run konumlarından birinden bölge 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 Cloud Storage'da depolamak için bir Node.js uygulamasını keşfedeceksiniz. Daha sonra uygulama için bir container görüntüsü derleyecek ve Cloud Run'da iş olarak çalıştıracaksınız.

Bu depodaki uygulama kodunu klonlamak için Cloud Shell'den 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

Şu dosya düzenini görürsünüz:

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

Aşağıda her dosyanın kısa bir açıklaması verilmiştir:

  • screenshot.js, uygulamanın 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 inceleyin

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

Aşağıda her dosyanın kısa bir açıklaması verilmiştir.

screenshot.js

screenshot.js, ilk olarak 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 ve belirli bir URL'nin ekran görüntüsünü almak için 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 almak veya oluşturmak için bir işlev ve web sayfasının ekran görüntüsünü pakete yüklemek için bir işlev daha vardı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 aşağıdaki noktalara dikkat edin:

  • URL'ler bağımsız değişken olarak aktarılır.
  • Paket adı, kullanıcı tanımlı 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, benzersiz görevler olarak uygulamanın birden fazla kopyasını ç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 çok görev olarak çalıştırıldığında, her görev/kapsayıcı sorumlu olduğu URL'yi alır, bir 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 için bağımlılıkları 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 uygulama için container 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

Bir iş 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"

Paket ve nesne oluşturmak için kullanılabilmesi için hizmet hesabına storage.admin rolü verin.

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 \
  --service-account=screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com

Bu yöntem, kaynak tabanlı dağıtım kullanır ve yürütmeden Cloud Run işi oluşturur.

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

--tasks işaretiyle çalıştırılacak bir dizi görev 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. Bunu kolaylaştırmak için her görev, CLOUD_RUN_TASK_INDEX ortam değişkeninde depolanan dizinini bilir. Hangi görevin hangi veri alt kümesini işleyeceğini belirlemekten kodunuz sorumludur. Bu örnekte --tasks=2 konusuna dikkat edin. Böylece, işlemek istediğimiz 2 URL için 2 kapsayıcının çalışmasını sağlar.

Her görev 24 saate kadar çalıştırılabilir. Bu örnekte yaptığımız gibi, --task-timeout işaretini kullanarak bu zaman aşımını azaltabilirsiniz. İşin başarıyla tamamlanabilmesi için tüm görevlerin başarılı olması gerekir. Varsayılan olarak, başarısız 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 paralel olarak mümkün olduğunca çok sayıda görevle yürütülür. Bu, işiniz için en fazla 100 görev sayısına eşit olacaktır. Sınırlı ölçeklenebilirliğe sahip bir arka uca erişen işler için paralelliği daha düşük bir değere ayarlamak isteyebilirsiniz. Örneğin, sınırlı sayıda etkin bağlantıyı destekleyen bir veritabanı. --parallelism işaretini kullanarak paralelliği azaltabilirsiniz.

6. İş çalıştırma

İşi çalıştırmadan önce, işin oluşturulup oluşturulmadığını listeleyin:

gcloud run jobs list

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

İşi aşağıdaki komutla ç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ütme işlemlerini 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ütme sürecini tanımlayın. Yeşil onay işareti ve tasks completed successfully mesajı gösterilir:

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

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örürsünüz:

7c4d355f6f65106.png

Bazen bir yürütme işlemi tamamlanmadan önce durdurmanız gerekebilir. Bunun nedeni, işi farklı parametrelerle çalıştırmanız gerektiğini fark etmeniz veya kodda bir hata olması ve gereksiz işlem süresini kullanmak istememeniz olabilir.

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

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

7. İş 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 container'ı yeniden oluşturmanız ve işinizi güncellemeniz gerekir. Etiketli resimler kullanmak, o anda resmin hangi sürümünün kullanılmakta olduğunu belirlemenize yardımcı olur.

Benzer şekilde, bazı yapılandırma değişkenlerini 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ü aldığı sayfaları --args işaretinde değiştirin. Ayrıca, sayfa sayısını yansıtmak için --tasks işaretini 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 yeniden çalıştırın. Yürütmelerin bitmesini beklemek için --wait işaretinde bu süre geçti:

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

Birkaç saniye sonra, pakete 3 ekran görüntüsü daha eklendiğini görürsünüz:

ed0cbe0b5a5f9144.png

8. İş planlayın

Şu ana kadar işleri manuel olarak çalıştırıyorsunuz. Gerçek dünyaya ait bir senaryoda işleri bir olaya göre veya bir plana göre yürütmek isteyebilirsiniz. Cloud Scheduler kullanarak ekran görüntüsü işinin planlı olarak nasıl çalıştırılacağını görelim.

İlk olarak, Cloud Scheduler API'nin etkinleştirildiğinden emin olun:

gcloud services enable cloudscheduler.googleapis.com

Cloud Run işlerinin 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 09:00'da çalışacak bir Scheduler işi oluşturun ve Continue öğesini seçin:

81fd098be0db216.png

Sonraki sayfada varsayılan Compute hizmet hesabını belirleyip Create değerini seçin:

fe479501dfb91f9f.png

Şimdi yeni bir Cloud Scheduler tetikleyicisinin oluşturulduğunu göreceksiniz:

5a7bc6d96b970b92.png

Cloud Scheduler sayfasına gitmek için View Details bağlantısını tıklayın.

Planlayıcının devreye girmesi için saat 09:00'a kadar bekleyebilir veya Force Run öğesini 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'ın çağrısıyla eklenen 3 ekran görüntüsü daha göreceksiniz:

56398a0e827de8b0.png

9. Tebrikler

Tebrikler, codelab'i tamamladınız.

Temizlik (İsteğe bağlı)

Ücretlerin tekrarlanmasını önlemek için kaynakları temizlemeniz önerilir.

Projeye ihtiyacınız yoksa projeyi silmeniz yeterlidir:

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 bir uygulama nasıl kullanılır?
  • Uygulama için container görüntüsü derleme.
  • Uygulama için Cloud Run işi oluşturma.
  • Uygulamanın Cloud Run işi olarak nasıl çalıştırılacağını öğreneceksiniz.
  • İşin güncellenmesi
  • Cloud Scheduler ile işin nasıl planlanacağı.