Cloud Scheduler と Cloud Build トリガーを使用して、Image Builder の実行を定期的にスケジュールできます。カスタム OS イメージのビルドをスケジュールすると、Cloud Build は、手動操作を必要とせずに、オペレーティング システムのパッチと組織のセキュリティ ポリシーでベースライン イメージを自動的に更新します。
始める前に
- 環境を準備する の手順に沿って環境を設定します。
-
まだ設定していない場合は、認証を設定します。
認証では、 Google Cloud サービスと API にアクセスするための ID が確認されます。ローカル開発環境からコードまたはサンプルを実行するには、次のいずれかのオプションを選択して Compute Engine に対する認証を行います。
このページのサンプルをどのように使うかに応じて、タブを選択してください。
gcloud
-
Google Cloud CLI をインストールします。 インストール後、 初期化するには、次のコマンドを実行して Google Cloud CLI を初期化します。
gcloud init外部 ID プロバイダ(IdP)を使用している場合は、まず フェデレーション ID を使用して gcloud CLI にログインする必要があります。
-
- デフォルトのリージョンとゾーンを設定します。
-
Google Cloud CLI をインストールします。
-
外部 ID プロバイダ(IdP)を使用している場合は、まず フェデレーション ID を使用して gcloud CLI にログインする必要があります。
-
ローカルシェルを使用している場合は、ユーザー アカウントのローカル認証情報を作成します。
gcloud auth application-default login
Cloud Shell を使用している場合は、この操作を行う必要はありません。
認証エラーが返され、外部 ID プロバイダ (IdP)を使用している場合は、 連携 ID を使用して gcloud CLI にログインしていることを確認します。
Go
ローカル開発環境でこのページの Go サンプルを使用するには、gcloud CLI をインストールして 初期化し、ユーザー認証情報を使用してアプリケーションのデフォルト認証情報を設定します。
詳細については、 ローカル開発環境の認証を設定するをご覧ください。
必要なロール
トリガーを作成してビルドをスケジュールするために必要な権限を取得するには、プロジェクトに対する次の IAM ロールの付与を管理者に依頼してください。
- Cloud Build 編集者 (
roles/cloudbuild.builds.editor) - Cloud Scheduler ジョブ実行者(
roles/cloudscheduler.jobRunner)または Cloud Scheduler 管理者(roles/cloudscheduler.admin) - サービス アカウント ユーザー (
roles/iam.serviceAccountUser)
ロールの付与については、プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。
必要な権限は、カスタム ロールや他の事前定義 ロールから取得することもできます。
スケジュールされたビルド パイプラインを作成する
gcloud CLI または Go クライアント SDK を使用して、定期的なイメージ ビルドを構成できます。
gcloud
gcloud CLI を使用して OS イメージのビルドを定期的にスケジュールするには、次の操作を行います。
ターゲットの
cloudbuild.yamlファイルを指定する手動の Cloud Build ビルドトリガーを作成するには、gcloud builds triggers create manualコマンド を実行します。Cloud Scheduler は、リポジトリ イベントではなく、このトリガーを手動で呼び出すため、push または pull リクエスト フィルタを指定しないでください。gcloud builds triggers create manual \ --name="TRIGGER_NAME" \ --region=REGION \ --build-config=CLOUDBUILD_YAML_PATH \ --project=PROJECT_ID新しいトリガー用に生成された一意の ID(
trigger_id)をgcloud builds triggers describeコマンドを実行して取得します。gcloud builds triggers describe TRIGGER_NAME \ --region=REGION \ --format="value(id)" \ --project=PROJECT_ID必要な unix cron スケジュールに従って、Cloud Build API(
projects.locations.triggers.run)にHTTP POSTリクエストを送信する Cloud Scheduler ジョブを作成するには、gcloud scheduler jobs create httpコマンドを実行します。たとえば、毎週月曜日の午前 6 時('0 6 * * 1')に実行します。gcloud scheduler jobs create http JOB_NAME \ --schedule="CRON_SCHEDULE" \ --uri="https://cloudbuild.googleapis.com/v1/projects/PROJECT_ID/locations/REGION/triggers/TRIGGER_ID:run" \ --message-body="{}" \ --oauth-service-account-email="SERVICE_ACCOUNT_EMAIL" \ --location=REGION \ --project=PROJECT_ID
次のように置き換えます。
TRIGGER_NAME: 手動の Cloud Build ビルドトリガーの名前(例:weekly-ubuntu-builder)。REGION: トリガーを作成するリージョン(例:us-central1)。CLOUDBUILD_YAML_PATH: ローカル ディレクトリ内のcloudbuild.yamlファイルのパス(例:cloudbuild.yaml)。PROJECT_ID: プロジェクト ID。JOB_NAME: Cloud Scheduler cron ジョブの名前(例:weekly-custom-os-patching)。CRON_SCHEDULE: unix cron スケジュール式 (例:'0 6 * * 1')。TRIGGER_ID: トリガー用に生成された一意の ID(trigger_id)。SERVICE_ACCOUNT_EMAIL: Cloud Scheduler がトリガーを呼び出すことを承認するサービス アカウントのメールアドレス。このサービス アカウントには、roles/cloudbuild.builds.editor権限が必要です。
Go
Google Cloud Go API クライアント ライブラリ
(cloudbuild/v1 と cloudscheduler/v1)を使用して、エンタープライズ
アプリケーション内でパイプラインをプログラムでスケジュールできます。
次の完全な Go の例では、コマンドライン フラグを解析し、imagebuilder.yaml 定義から Build リクエストを作成する方法を示します。次に、--cron_schedule フラグを指定すると、プログラムは手動の Cloud Build トリガーを登録し、Cloud Scheduler ジョブをプロビジョニングします。
// Program main demonstrates how to submit or schedule a Image Builder pipeline using Go SDKs.
package main
import (
"context"
"flag"
"fmt"
"os"
"google.golang.org/api/cloudbuild/v1"
"google.golang.org/api/cloudscheduler/v1"
)
var (
projectID = flag.String("project_id", "", "The target Project ID")
region = flag.String("region", "us-central1", "Region of resources")
gcsWorkdir = flag.String("gcs_workdir", "", "The storage workspace directory URI, e.g. gs://my-bucket/workdir/")
serviceAccount = flag.String("service_account", "", "Service account email to run the worker VM")
imageBuilderYAML = flag.String("config_path", "imagebuilder.yaml", "Path to the imagebuilder.yaml configuration file")
arRepositoryID = flag.String("ar_repo_id", "os-images", "Name of the target generic Artifact Registry repository")
arPackageName = flag.String("ar_package_name", "custom-os", "Package identifier for OS images")
cronSchedule = flag.String("cron_schedule", "", "Optional cron schedule to run this build periodically (e.g. '0 6 * * 1')")
)
func main() {
flag.Parse()
if *projectID == "" || *serviceAccount == "" || *gcsWorkdir == "" {
fmt.Fprintln(os.Stderr, "Error: --project_id, --gcs_workdir, and --service_account are required flags")
flag.Usage()
os.Exit(1)
}
ctx := context.Background()
if *cronSchedule != "" {
fmt.Printf("Scheduling build with cron schedule: %s\n", *cronSchedule)
if err := scheduleBuild(ctx); err != nil {
fmt.Fprintf(os.Stderr, "Failed to schedule Cloud Build: %v\n", err)
os.Exit(1)
}
} else {
fmt.Println("Submitting build request immediately to Cloud Build API...")
if err := triggerBuild(ctx); err != nil {
fmt.Fprintf(os.Stderr, "Failed to trigger Cloud Build: %v\n", err)
os.Exit(1)
}
}
}
func createBuildRequest() *cloudbuild.Build {
subs := map[string]string{
"_GCS_WORKDIR": *gcsWorkdir,
"_SERVICE_ACCOUNT": fmt.Sprintf("projects/%s/serviceAccounts/%s", *projectID, *serviceAccount),
"_IMAGE_OUTPUT_PATH": "image-builder/binaryOut",
"_IMAGE_BUILDER_CONFIG_PATH": *imageBuilderYAML,
"_ARTIFACT_REGISTRY_RESOURCE_URI": fmt.Sprintf("projects/%s/locations/%s/repositories/%s/packages/%s/versions/v${BUILD_ID}", *projectID, *region, *arRepositoryID, *arPackageName),
}
return &cloudbuild.Build{
Steps: []*cloudbuild.BuildStep{
{
Name: "us-central1-docker.pkg.dev/image-builder-official/release/builder:stable",
Script: "#!/usr/bin/env bash\n/build",
Id: "imagebuilder-customize",
},
{
Name: "us-central1-docker.pkg.dev/image-builder-official/release/validator:stable",
Script: "#!/usr/bin/env bash\n/validate",
Id: "imagebuilder-validate",
},
{
Name: "us-central1-docker.pkg.dev/image-builder-official/release/builder:stable",
Script: "#!/usr/bin/env bash\n/publish",
Id: "imagebuilder-publish",
},
},
Substitutions: subs,
Options: &cloudbuild.BuildOptions{
AutomapSubstitutions: true,
RequestedVerifyOption: "VERIFIED",
SubstitutionOption: "ALLOW_LOOSE",
DynamicSubstitutions: true,
},
Timeout: "3600s",
}
}
func triggerBuild(ctx context.Context) error {
cbService, err := cloudbuild.NewService(ctx)
if err != nil {
return err
}
build := createBuildRequest()
op, err := cbService.Projects.Locations.Builds.Create(fmt.Sprintf("projects/%s/locations/%s", *projectID, *region), build).Do()
if err != nil {
return err
}
fmt.Printf("Build submitted: %s\n", op.Name)
return nil
}
func scheduleBuild(ctx context.Context) error {
cbService, err := cloudbuild.NewService(ctx)
if err != nil {
return err
}
csService, err := cloudscheduler.NewService(ctx)
if err != nil {
return err
}
// 1. Create a manual Cloud Build trigger
trigger := &cloudbuild.BuildTrigger{
Build: createBuildRequest(),
Name: "scheduled-image-builder-trigger",
Description: "Manual trigger invoked periodically via Cloud Scheduler for Image Builder",
}
createdTrigger, err := cbService.Projects.Locations.Triggers.Create(fmt.Sprintf("projects/%s/locations/%s", *projectID, *region), trigger).Do()
if err != nil {
return fmt.Errorf("failed creating trigger: %w", err)
}
fmt.Printf("Created Cloud Build trigger with ID: %s\n", createdTrigger.Id)
// 2. Create the Cloud Scheduler job
targetURI := fmt.Sprintf("https://cloudbuild.googleapis.com/v1/projects/%s/locations/%s/triggers/%s:run", *projectID, *region, createdTrigger.Id)
job := &cloudscheduler.Job{
Name: fmt.Sprintf("projects/%s/locations/%s/jobs/weekly-image-builder-job", *projectID, *region),
Schedule: *cronSchedule,
Description: "Scheduled job to run custom OS Image Builder pipeline",
HttpTarget: &cloudscheduler.HttpTarget{
Uri: targetURI,
HttpMethod: "POST",
OauthToken: &cloudscheduler.OAuthToken{
ServiceAccountEmail: *serviceAccount,
},
},
}
createdJob, err := csService.Projects.Locations.Jobs.Create(fmt.Sprintf("projects/%s/locations/%s", *projectID, *region), job).Do()
if err != nil {
return fmt.Errorf("failed creating scheduler job: %w", err)
}
fmt.Printf("Successfully scheduled job: %s\n", createdJob.Name)
return nil
}
スケジュールされた Go アプリケーションを実行する
コンパイルされた Go バイナリを実行し、毎週月曜日の午前 6 時に定期的に実行するようにスケジュールするには、次のコマンドを実行します。
go run main.go \ --project_id PROJECT_ID \ --region us-central1 \ --gcs_workdir gs://STAGING_BUCKET/workdir/ \ --service_account SERVICE_ACCOUNT_EMAIL \ --config_path gs://STAGING_BUCKET/imagebuilder.yaml \ --cron_schedule '0 6 * * 1'
次のステップ
- Terraform を使用して、Git push、タグ、マージ イベントのリポジトリ イベントでビルドを自動化する方法を学習する 。
- カスタマイズ レシピ スキーマ を確認して、ソフトウェア パッケージと検証手順を定義する。