クイックスタート: Cloud Run で Go ジョブをビルドして作成する

Cloud Run で Go ジョブをビルドして作成する

シンプルな Cloud Run ジョブを作成してコンテナ イメージにパッケージ化し、コンテナ イメージを Container Registry にアップロードして Cloud Run にデプロイする方法を学習します。ここで説明していない言語を使用することもできます。

始める前に

  1. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトの課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

  4. Google Cloud CLI をインストールします。
  5. gcloud CLI を初期化するには:

    gcloud init
  6. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  7. Google Cloud プロジェクトの課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

  8. Google Cloud CLI をインストールします。
  9. gcloud CLI を初期化するには:

    gcloud init

サンプルジョブの作成

Go でジョブを作成するには:

  1. jobs という名前の新しいディレクトリを作成し、そのディレクトリに移動します。

    mkdir jobs
    cd jobs
    
  2. 同じディレクトリに、実際のジョブコードを記述する main.go ファイルを作成します。ここに次のサンプル行をコピーします。

    package main
    
    import (
    	"fmt"
    	"log"
    	"math/rand"
    	"os"
    	"strconv"
    	"time"
    )
    
    type Config struct {
    	// Job-defined
    	taskNum    string
    	attemptNum string
    
    	// User-defined
    	sleepMs  int64
    	failRate float64
    }
    
    func configFromEnv() (Config, error) {
    	// Job-defined
    	taskNum := os.Getenv("CLOUD_RUN_TASK_INDEX")
    	attemptNum := os.Getenv("CLOUD_RUN_TASK_ATTEMPT")
    	// User-defined
    	sleepMs, err := sleepMsToInt(os.Getenv("SLEEP_MS"))
    	failRate, err := failRateToFloat(os.Getenv("FAIL_RATE"))
    
    	if err != nil {
    		return Config{}, err
    	}
    
    	config := Config{
    		taskNum:    taskNum,
    		attemptNum: attemptNum,
    		sleepMs:    sleepMs,
    		failRate:   failRate,
    	}
    	return config, nil
    }
    
    func sleepMsToInt(s string) (int64, error) {
    	sleepMs, err := strconv.ParseInt(s, 10, 64)
    	return sleepMs, err
    }
    
    func failRateToFloat(s string) (float64, error) {
    	// Default empty variable to 0
    	if s == "" {
    		return 0, nil
    	}
    
    	// Convert string to float
    	failRate, err := strconv.ParseFloat(s, 64)
    
    	// Check that rate is valid
    	if failRate < 0 || failRate > 1 {
    		return failRate, fmt.Errorf("Invalid FAIL_RATE value: %f. Must be a float between 0 and 1 inclusive.", failRate)
    	}
    
    	return failRate, err
    }
    
    func main() {
    	config, err := configFromEnv()
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	log.Printf("Starting Task #%s, Attempt #%s ...", config.taskNum, config.attemptNum)
    
    	// Simulate work
    	if config.sleepMs > 0 {
    		time.Sleep(time.Duration(config.sleepMs) * time.Millisecond)
    	}
    
    	// Simulate errors
    	if config.failRate > 0 {
    		if failure := randomFailure(config); failure != nil {
    			log.Fatalf("%v", failure)
    		}
    	}
    
    	log.Printf("Completed Task #%s, Attempt #%s", config.taskNum, config.attemptNum)
    }
    
    // Throw an error based on fail rate
    func randomFailure(config Config) error {
    	rand.Seed(time.Now().UnixNano())
    	randomFailure := rand.Float64()
    
    	if randomFailure < config.failRate {
    		return fmt.Errorf("Task #%s, Attempt #%s failed.", config.taskNum, config.attemptNum)
    	}
    	return nil
    }
    

    Cloud Run ジョブを使用すると、実行するタスクの数を指定できます。次のサンプルコードは、組み込みの CLOUD_RUN_TASK_INDEX 環境変数を使用する方法を示しています。各タスクが、コンテナの 1 つの実行中のコピーを表します。タスクは通常、並行して実行されます。各タスクが独立してデータのサブセットを処理できる場合は、複数のタスクを使用すると便利です。

    各タスクはインデックスを認識し、CLOUD_RUN_TASK_INDEX 環境変数に格納されます。組み込みの CLOUD_RUN_TASK_COUNT 環境変数には、ジョブの実行時に --tasks パラメータを介して指定されたタスクの数が含まれています。

    このコードは、組み込みの CLOUD_RUN_TASK_ATTEMPT 環境変数を使用してタスクを再試行する方法を示しています。この変数はタスクの再試行回数を表します。最初の再試行が行われると、この変数に 0 が設定され、--max-retries になるまで再試行のたびに値が 1 ずつ増加します。

    このコードでは、再試行のテストやエラーログの生成も行うことができるため、問題の発生箇所を確認できます。

  3. go.mod ファイルを作成し、次の内容を追加します。

    module github.com/GoogleCloudPlatform/golang-samples/run/jobs
    
    go 1.19
    

コードが完成し、コンテナにパッケージ化できるようになりました。

ジョブコンテナをビルドしてリポジトリに送信する

重要: 以下の説明では、このクイックスタートで使用するプロジェクトのオーナーロールまたは編集者ロールが付与されていることを前提としています。このロールが付与されていない場合は、Cloud Run のデプロイ権限Cloud Build の権限Artifact Registry の権限で必要な権限を確認してください。

buildpack を使用してコンテナをビルドします。

gcloud builds submit --pack image=gcr.io/PROJECT_ID/logger-job

Cloud Run でジョブを作成する

作成したコンテナを使用してジョブを作成するには:

gcloud run jobs create job-quickstart \
    --image gcr.io/PROJECT_ID/logger-job \
    --tasks 50 \
    --set-env-vars SLEEP_MS=10000 \
    --set-env-vars FAIL_RATE=0.5 \
    --max-retries 5 \
    --region REGION
    --project=PROJECT_ID

ここで、PROJECT_ID はプロジェクト ID、REGION はリージョンです(例: us-central1)。パラメータの値は、テスト目的で使用する任意の値に変更できます。SLEEP_MS は作業をシミュレートし、FAIL_RATE でタスクの X% を失敗させます。これにより、並列処理をテストし、失敗したタスクを再試行できます。

Cloud Run でジョブを実行する

作成したジョブを実行するには:

gcloud run jobs execute job-quickstart

リージョンの入力を求められたら、任意のリージョン(us-central1 など)を選択します。

ローカルでテストする

ジョブはローカルで実行できます。

docker run --rm -e FAIL_RATE=0.9 -e SLEEP_MS=1000 gcr.io/PROJECT_ID/logger-job
ここで、PROJECT_ID はプロジェクト ID です。

次のステップ

コードソースからコンテナをビルドし、リポジトリに push する方法については、以下をご覧ください。