יצירת פייפליין של קובץ אימג' מותאם אישית של מערכת ההפעלה באופן פרוגרמטי

אתם יכולים להגדיר ולשלוח פייפליין של Image Builder באופן פרוגרמטי באמצעות ה-CLI של gcloud,‏ Terraform או ספריות לקוח כמו Go. הגדרת הפייפליין באופן פרוגרמטי מאפשרת לכם להגדיר את הגדרות התשתית, קובצי אימג' של מערכת ההפעלה הבסיסיים, פעולות ההתאמה האישית ובדיקות האימות בקובצי תצורה הצהרתיים.

לפני שמתחילים

התפקידים הנדרשים

כדי לקבל את ההרשאות שדרושות ליצירה ולשליחה של צינורות עיבוד נתונים להתאמה אישית של תמונות באופן פרוגרמטי, בקשו מהאדמין להקצות לכם את התפקידים הבאים ב-IAM בפרויקט:

להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.

יצירת קובצי תצורה

כדי להגדיר את צינור עיבוד הנתונים באמצעות ה-CLI של gcloud או Terraform, צריך ליצור שני קובצי תצורה:

  • ‫imagebuilder.yaml: מגדיר את מתכון ההתאמה האישית של קובץ האימג', כולל קובץ האימג' של מערכת ההפעלה הבסיסית, הגדרות התשתית של ה-worker VM, פרטי הפלט של קובץ האימג' המטורגט ושלבי ההתאמה האישית העוקבים, כמו הפעלת סקריפטים של מעטפת, העברת קבצים או הפעלה מחדש.
  • ‫cloudbuild.yaml: מתזמר את השלבים של תהליך ה-build ב-Cloud Build, כולל ניתוח, אימות, יצירה, בדיקה ופרסום של קובץ האימג' של מערכת ההפעלה בהתאמה אישית.

אם אתם שולחים את ה-build באמצעות Go, אתם צריכים רק ליצור את הקובץ imagebuilder.yaml ולהעלות אותו לקטגוריה של Cloud Storage, כי הדוגמה של Go מגדירה את שלבי התזמור של Cloud Build בקוד.

יצירת קובץ התצורה של התמונה

כדי לציין את הגדרות האימג', יוצרים קובץ בשם imagebuilder.yaml בספרייה המקומית. רשימה מלאה של כל שדות הסכימה הנתמכים ופעולות ההתאמה האישית מופיעה במאמרים סכימת מתכון להתאמה אישית ופעולות נתמכות להתאמה אישית.

קובץ ה-imagebuilder.yaml לדוגמה הבא מגדיר פייפליין שיוצר קובץ אימג' מותאם אישית של Ubuntu 22.04 LTS באמצעות worker VM e2-standard-4 באזור ובתחום (zone) שציינתם, ומבצע עדכון של חבילת המערכת.

apiVersion: imagebuilder.gcp.com/v1
kind: OSImageCustomization
metadata:
  name: customized-ubuntu-baseline
  description: "Ubuntu 22.04 LTS custom OS baseline image"
infrastructureConfig:
  machineType: e2-standard-4
  zone: ZONE
  debug: false
source:
  imageFamily: projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts
destinations:
  - diskImage:
      name: custom-ubuntu-v1
      family: custom-ubuntu-family
      project: PROJECT_ID
      storageLocations:
        - REGION
spec:
  config:
    skipSystemTests: false
  steps:
    -   name: "System Package Update"
      action: Shell
      inputs:
        command: "apt-get update -y && apt-get upgrade -y"

מחליפים את הערכים הזמניים הבאים לשמירת מקום:

  • PROJECT_ID: מזהה הפרויקט.
  • ‫REGION: מיקום האחסון של קובץ האימג' של היעד, לדוגמה us-east1 או europe-west1. חשוב לוודא שאתם עומדים בדרישות הבאות לגבי אזורים וזמינות:
    • אפשר להשתמש ב-Image Builder רק באזורים שבהם Cloud Build זמין.
    • ה-worker VM‏ ZONE חייב להיות בתוך ה-REGION שציינתם.
    • כדי לצמצם את זמן האחזור ברשת ולמנוע חיובים על תעבורת נתונים יוצאת לכמה אזורים, ודאו שהאזור של ה-worker VM, קטגוריית ה-staging ב-Cloud Storage, המאגר ב-Artifact Registry ומיקום האחסון של קובץ האימג' נמצאים באותו אזור.
  • ‫ZONE: אזור שנמצא בתוך REGION שציינתם, לדוגמה us-east1-b או europe-west1-b.

יצירת קובץ ה-build של התזמור

יוצרים קובץ בשם cloudbuild.yaml באותה ספרייה. הקובץ הזה קורא לשלבים של קונטיינר Image Builder כדי ליצור, לאמת ולפרסם את קובץ האימג' של מערכת ההפעלה בהתאמה אישית.

substitutions:
  _GCS_WORKDIR: 'gs://STAGING_BUCKET_NAME/workdir/'
  _IMAGE_BUILDER_CONFIG_PATH: 'imagebuilder.yaml'
  _SERVICE_ACCOUNT: 'projects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_EMAIL'
  _IMAGE_OUTPUT_PATH: 'image-builder/binaryOut'
  _ARTIFACT_REGISTRY_RESOURCE_URI: 'projects/PROJECT_ID/locations/REGION/repositories/REPOSITORY_NAME/packages/PACKAGE_NAME/versions/v${BUILD_ID}'

steps:
  #  Step 1: Parse configs and run OS customization on worker VM
  - name: 'REGION-docker.pkg.dev/image-builder-official/release/builder:stable'
    script: |
      #!/usr/bin/env bash
      /build
    id: 'imagebuilder-customize'
    results:
      - name: image_builder_telemetry_metrics
      - name: base_image
        attestationType: "https://cloudbuild.googleapis.com/attestations/build_content_restrictions"
        attestationContent: base_image

  # Step 2: Validate by running system boot checks on a test VM
  - name: 'REGION-docker.pkg.dev/image-builder-official/release/validator:stable'
    script: |
      #!/usr/bin/env bash
      /validate
    id: 'imagebuilder-validate'
    results:
      - name: image_builder_telemetry_metrics

  # Step 3: Register image in Compute Engine and upload tar files to Artifact Registry
  - name: 'REGION-docker.pkg.dev/image-builder-official/release/builder:stable'
    script: |
      #!/usr/bin/env bash
      /publish
    id: 'imagebuilder-publish'
    results:
      - name: image_builder_telemetry_metrics

options:
  automapSubstitutions: true
  requestedVerifyOption: VERIFIED
  substitutionOption: ALLOW_LOOSE
  dynamicSubstitutions: true
  logging: CLOUD_LOGGING_ONLY

artifacts:
  generic_artifacts:
    - folder: '${_IMAGE_OUTPUT_PATH}'
      registry_path: '${_ARTIFACT_REGISTRY_RESOURCE_URI}'

timeout: '3600s'

מחליפים את הערכים הזמניים הבאים לשמירת מקום:

  • ‫STAGING_BUCKET_NAME: קטגוריה קיימת של Cloud Storage בפרויקט, שתשמש כסביבת עבודה זמנית להכנת הנתונים. אם אין לכם קטגוריה, אתם יכולים ליצור אחת באמצעות הפעלת gcloud storage buckets create gs://STAGING_BUCKET_NAME. אם אתם פורסים את צינור עיבוד הנתונים באמצעות Terraform, ‏ Terraform יוצר את הקטגוריה הזו באופן אוטומטי.
  • ‫PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
  • ‫REGION: Google Cloud האזור של מאגר Artifact Registry, לדוגמה us-east1 או europe-west1.
  • ‫SERVICE_ACCOUNT_EMAIL: כתובת האימייל של חשבון השירות שהגדרתם עם הרשאות ה-IAM הנדרשות.
  • ‫REPOSITORY ו-PACKAGE: מאגר היעד ושם החבילה שנוצרו ב-Artifact Registry. כדי להגדיר את המרשם של Artifact Registry, קראו את המאמר הגדרת Artifact Registry.

יצירה ושליחה של צינור עיבוד הנתונים של ה-build

כדי להריץ את צינור עיבוד הנתונים להתאמה אישית של תמונות, שולחים גרסת build באמצעות ה-CLI של gcloud, פורסים את צינור עיבוד הנתונים באמצעות Terraform או שולחים גרסת build באמצעות ספריית הלקוח של Go. בוחרים אחת מהכרטיסיות הבאות:

gcloud

כדי לפרוס ולהריץ את צינור עיבוד הנתונים להתאמה אישית של קובץ האימג', מריצים את הפקודה gcloud builds submit מהספרייה המקומית של הטרמינל שמכילה את שני קובצי התצורה:

gcloud builds submit . \
    --config=cloudbuild.yaml \
    --project=PROJECT_ID \
    --service-account="projects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_EMAIL" \
    --region=REGION

מחליפים את מה שכתוב בשדות הבאים:

  • ‫PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
  • ‫REGION: האזור ב- Google Cloud שבו רוצים להריץ את משימת הצינור להתאמה אישית של תמונות.
  • ‫SERVICE_ACCOUNT_EMAIL: כתובת האימייל של חשבון השירות שמוגדר עם הרשאות ה-IAM הנדרשות.

הפקודה הזו מעלה את סביבת העבודה להתאמה אישית, רושמת את ההפעלה של Cloud Build ומפעילה את הקונטיינרים של התזמור.

Terraform

כדי להקצות את התשתית שנדרשת לבנייה ולאימות אוטומטיים של קובצי אימג' מותאמים אישית של מערכת ההפעלה, אתם יכולים להשתמש ב-Terraform. ההגדרה הזו של Terraform מבצעת את המשימות הבאות:

  • מפעילים את ממשקי ה-API הנדרשים של Google Cloud .
  • יוצרת קטגוריה ייעודית של Cloud Storage (workdir_bucket) לאחסון יומנים זמניים ופריטי מידע שנוצרו בתהליך פיתוח התוכנה.
  • מגדיר טריגר לפיתוח גרסת Build של Cloud (image_builder_trigger) שמקושר לחיבור של מאגר GitHub ב-Developer Connect.

יצירת קובצי התצורה של Terraform

כדי לארגן ולפרוס את תשתית הצינור באמצעות Terraform, מבצעים את השלבים הבאים:

  1. יוצרים ספרייה ייעודית בתחנת העבודה המקומית או בסביבת ה-CI/CD, בנפרד ממאגר האפליקציות, ועוברים אליה:

    mkdir terraform-image-builder && cd terraform-image-builder
    
  2. בספרייה הזו, יוצרים את חמשת קובצי התצורה הבאים של Terraform:

    • ‫terraform.tfvars: מגדיר ערכים למשתנים ספציפיים לפרויקט.
    • ‫main.tf: מקצה משאבים בפרויקט ב- Google Cloud , כולל הפעלת ממשקי ה-API הנדרשים, יצירת קטגוריית ה-Staging ב-Cloud Storage‏ (workdir_bucket) ופריסת טריגר לפיתוח גרסת Build של Cloud Build‏ (image_builder_trigger).
    • ‫outputs.tf: מגדיר את ערכי הפלט שמוצגים במסוף אחרי הפריסה, כמו מזהה הטריגר ושם הקטגוריה של ה-Staging.
    • ‫providers.tf: מציין את הגרסה הנדרשת של Terraform‏ (>= 1.3) ומגדיר את הספק של Google Cloud ‏ (hashicorp/google).
    • ‫variables.tf: הגדרה של משתני הקלט, ערכי ברירת המחדל וכללי האימות לפריסה.

    בוחרים אחת מהכרטיסיות הבאות כדי להציג ולהעתיק את ההגדרות של כל קובץ לספרייה המקומית:

    terraform.tfvars

    בקובץ הזה מצוינים ערכי הפרמטרים של הסביבה שלכם למשתנים שהוצהרו:

    project_id                = "PROJECT_ID"
    builder_service_account   = "SERVICE_ACCOUNT_EMAIL"
    github_repo_name          = "projects/PROJECT_ID/locations/LOCATION/connections/CONNECTION/repositories/REPO_NAME"
    region                    = "REGION"
    trigger_name              = "TRIGGER_NAME"
    cloudbuild_yaml_path      = "CLOUDBUILD_YAML_PATH"
    image_builder_config_path = "RECIPE_PATH"
    gcs_lifecycle_age_days    = LIFECYCLE_DAYS
    ar_repository_id          = "REPOSITORY_NAME"
    ar_package_name           = "PACKAGE_NAME"
    

    מחליפים את ה-placeholders הבאים במשאבים הקיימים:

    • ‫PROJECT_ID: מזהה הפרויקט הקיים ב-Google Cloud .
    • ‫SERVICE_ACCOUNT_EMAIL: כתובת האימייל של חשבון השירות של ה-build שהגדרתם בקטע הגדרת חשבון שירות ל-Image Builder.
    • ‫LOCATION,‏ CONNECTION ו-REPO_NAME: האזור המארח של Developer Connect, שם החיבור והקישור למאגר שהגדרתם בקטע קישור למאגר.
    • ‫CLOUDBUILD_YAML_PATH: הנתיב היחסי לקובץ cloudbuild.yaml בספרייה המקומית. אין צורך להוסיף את cloudbuild.yaml למאגר Git.
    • ‫RECIPE_PATH: הנתיב היחסי לקובץ המתכון להתאמה אישית של imagebuilder.yaml, שנמצא במאגר Git.
    • REPOSITORY_NAME: מאגר Artifact Registry הגנרי הקיים שנוצר בהגדרת Artifact Registry.

    מחליפים את הפלייסהולדרים הבאים של המשאבים שנוצרו ב-Terraform:

    • ‫REGION: האזור ב- Google Cloudשבו Terraform מקצה את קטגוריית ה-Staging של Cloud Storage ואת הטריגר לפיתוח גרסת Build של Cloud Build, לדוגמה us-central1.
    • ‫TRIGGER_NAME: השם של הטריגר החדש של מאגר Cloud Build שנוצר על ידי Terraform, לדוגמה git-push-os-builder.
    • ‫LIFECYCLE_DAYS: תקופת השמירה בימים לפני שפריטי המידע שנוצרו על ידי Terraform בקטגוריית ה-staging של Cloud Storage נמחקים באופן אוטומטי, לדוגמה 30.
    • ‫PACKAGE_NAME: השם שאתם רוצים ש-Terraform ישתמש בו לחבילה שנוצרה במאגר Artifact Registry. החבילה הזו מאחסנת גרסאות של קובצי אימג' של מערכת ההפעלה שפורסמו, לדוגמה ubuntu-custom.

    main.tf

    בקובץ הזה מצהירים על משאבי התשתית העיקריים ועל מקורות הנתונים לפריסה:

    # Main resource configurations for Image Builder.
    # 1. Enable Required APIs
    resource "google_project_service" "apis" {
      for_each = toset([
        "compute.googleapis.com",
        "cloudbuild.googleapis.com",
        "artifactregistry.googleapis.com",
        "serviceusage.googleapis.com",
        "cloudresourcemanager.googleapis.com",
        "iam.googleapis.com",
        "storage.googleapis.com"
      ])
      project = var.project_id
      service = each.key
      disable_on_destroy = false
    }
    
    # 2. Project data source to retrieve Project Number
    data "google_project" "project" {
      project_id = var.project_id
      depends_on = [google_project_service.apis]
    }
    
    locals {
      builder_sa = var.builder_service_account
    }
    
    # 3. Storage Bucket for Image Builder Workdir
    resource "google_storage_bucket" "workdir_bucket" {
      name                        = var.gcs_bucket_name != "" ? var.gcs_bucket_name : "${var.project_id}-vm-builder-workdir"
      project                     = var.project_id
      location                    = var.region
      force_destroy               = true
      uniform_bucket_level_access = true
      lifecycle_rule {
        action {
          type = "Delete"
        }
        condition {
          age = var.gcs_lifecycle_age_days
        }
      }
      depends_on = [google_project_service.apis]
    }
    
    # 4. Cloud Build Trigger
    resource "google_cloudbuild_trigger" "image_builder_trigger" {
      name        = var.trigger_name
      location    = var.region
      project     = var.project_id
      description = "Trigger that runs Image Builder customization"
    
      service_account = var.builder_service_account != "" ? "projects/${var.project_id}/serviceAccounts/${var.builder_service_account}" : null
    
      repository_event_config {
        repository = replace(var.github_repo_name, "gitRepositoryLinks", "repositories")
        push {
          branch = "^main$"
        }
      }
      filename = var.cloudbuild_yaml_path
    
      substitutions = {
        _GCS_WORKDIR                    = "gs://${google_storage_bucket.workdir_bucket.name}/workdir/"
        _SERVICE_ACCOUNT                = "projects/${var.project_id}/serviceAccounts/${local.builder_sa}"
        _IMAGE_OUTPUT_PATH              = "image-builder/binaryOut"
        _PROJECT_ID                     = var.project_id
        _LOCATION                       = var.region
        _REPOSITORY_NAME                = var.ar_repository_id
        _PACKAGE_NAME                   = var.ar_package_name
        _IMAGE_BUILDER_CONFIG_PATH      = var.image_builder_config_path
        _ARTIFACT_REGISTRY_RESOURCE_URI = "projects/${var.project_id}/locations/${var.region}/repositories/${var.ar_repository_id}/packages/${var.ar_package_name}/versions/v$${BUILD_ID}"
      }
      depends_on = [
        google_project_service.apis
      ]
    }
    

    outputs.tf

    הקובץ הזה מגדיר את מאפייני הפלט שמוחזרים למסוף אחרי הפריסה:

    output "builder_service_account" {
      value       = local.builder_sa
      description = "The email representation of the resolved Image Builder service account."
    }
    
    output "workdir_bucket" {
      value       = google_storage_bucket.workdir_bucket.name
      description = "The name of the storage workdir bucket."
    }
    
    output "artifact_registry_repository" {
      value       = "projects/${var.project_id}/locations/${var.region}/repositories/${var.ar_repository_id}"
      description = "The fully qualified resource path of the Artifact Registry repository."
    }
    
    output "cloud_build_trigger_id" {
      value       = google_cloudbuild_trigger.image_builder_trigger.trigger_id
      description = "The unique ID for the created Cloud Build Trigger."
    }
    

    providers.tf

    בקובץ הזה מגדירים את הגרסה הנדרשת של Terraform ואת הגדרות האזור:

    terraform {
      required_version = ">= 1.3"
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = ">= 5.0, < 7.0"
        }
      }
    }
    
    provider "google" {
      project = var.project_id
      region  = var.region
    }
    

    variables.tf

    בקובץ הזה מצהירים על כל משתני הקלט וכללי האימות הנדרשים והאופציונליים:

    variable "project_id" {
      type        = string
      description = "The target Project ID where resources will be created."
      validation {
        condition     = can(regex("^[a-z0-9-]{6,30}$", var.project_id))
        error_message = "The project_id must consist of lowercase letters, numbers, and hyphens, and be between 6 and 30 characters."
      }
    }
    
    variable "region" {
      type        = string
      default     = "us-central1"
      description = "Location used for cloud build triggers, storage buckets, and artifact registry."
    }
    
    variable "github_repo_name" {
      type        = string
      default     = ""
      description = "Developer Connect github repository details, format: projects/PROJECT_ID/locations/LOCATION/connections/CONNECTION/repositories/REPO_LINK"
      validation {
        condition     = can(regex("^projects/[^/]+/locations/[^/]+/connections/[^/]+/(gitRepositoryLinks|repositories)/[^/]+$", var.github_repo_name))
        error_message = "The github_repo_name must follow either the Cloud Build v2 repository link format (using '/repositories/') or the Developer Connect resource format (using '/gitRepositoryLinks/')."
      }
    }
    
    variable "builder_service_account" {
      type        = string
      default     = ""
      description = "The email representation of the pre-existing Image Builder service account. If omitted, the default Cloud Build service account will be used."
    }
    
    variable "gcs_bucket_name" {
      type        = string
      default     = ""
      description = "Custom name for the workdir storage bucket. If left empty, a default name using the project ID will be constructed."
    }
    
    variable "gcs_lifecycle_age_days" {
      type        = number
      default     = 30
      description = "The number of days after which temporary logs and artifacts in the storage workdir bucket are deleted."
    }
    
    variable "ar_repository_id" {
      type        = string
      default     = "vm-images"
      description = "The repository ID for the generic Artifact Registry hosting the final OS image tarballs."
    }
    
    variable "ar_package_name" {
      type        = string
      default     = "image-builder"
      description = "The package name under which the generic OS image artifact will be registered in Artifact Registry."
    }
    
    variable "trigger_name" {
      type        = string
      default     = "custom-os-image-builder"
      description = "The name of the Cloud Build trigger."
    }
    
    variable "cloudbuild_yaml_path" {
      type        = string
      default     = "cloudbuild.yaml"
      description = "The path to the cloudbuild.yaml configuration file relative to the repository root."
    }
    
    variable "image_builder_config_path" {
      type        = string
      default     = "imagebuilder.yaml"
      description = "The path to the imagebuilder.yaml configuration file relative to the repository root."
    }
    
  3. כדי לפרוס את ההגדרות, מריצים את הפקודות הבאות בספרייה שמכילה את קובצי Terraform:

    1. מפעילים את הספרייה:
      terraform init
    2. מאמתים את התחביר:
      terraform validate
    3. צפייה בתצוגה מקדימה של הפריסה:
      terraform plan
    4. מחילים את ההגדרה:
      terraform apply

המשך

לפני שמריצים את הדוגמה הזו, צריך להעלות את קובץ התצורה imagebuilder.yaml לקטגוריית ה-staging ב-Cloud Storage, למשל gs://STAGING_BUCKET_NAME/imagebuilder.yaml.

כדי לשלוח build של Cloud Build שמריץ את צינור עיבוד הנתונים של Image Builder באמצעות ספריית הלקוח של Cloud Build ב-Go, משתמשים בדוגמה הבאה:

import (
	"context"
	"encoding/json"
	"fmt"
	"io"

	"google.golang.org/api/cloudbuild/v1"
)

// submitBuild submits a Cloud Build build that uses Image Builder to
// customize, validate, and publish a VM image to Compute Engine and Artifact
// Registry.
//
// Before you run this sample, upload your imagebuilder.yaml configuration file
// to Cloud Storage, create a generic Artifact Registry repository, and create a
// service account to run the build.
func submitBuild(w io.Writer, projectID, gcsWorkdir, configPath, serviceAccount string) error {
	// projectID := "my-project-id"
	region := "us-central1"
	// gcsWorkdir := "gs://my-bucket/workdir/"
	// configPath := "gs://my-bucket/imagebuilder.yaml"
	repository := "vm-images"
	packageName := "custom-os-images"
	// serviceAccount := "image-builder@my-project-id.iam.gserviceaccount.com"

	ctx := context.Background()
	cbService, err := cloudbuild.NewService(ctx)
	if err != nil {
		return fmt.Errorf("cloudbuild.NewService: %w", err)
	}

	sa := fmt.Sprintf("projects/%s/serviceAccounts/%s", projectID, serviceAccount)
	req := &cloudbuild.Build{
		ServiceAccount: sa,
		// AutomapSubstitutions exposes these substitutions to every step as
		// environment variables. See
		// https://cloud.google.com/build/docs/configuring-builds/substitute-variable-values#mapping_substitutions_to_environment_variables
		Substitutions: map[string]string{
			"_GCS_WORKDIR":               gcsWorkdir,
			"_SERVICE_ACCOUNT":           sa,
			"_IMAGE_OUTPUT_PATH":         "image-builder/binaryOut",
			"_IMAGE_BUILDER_CONFIG_PATH": configPath,
			"_ARTIFACT_REGISTRY_RESOURCE_URI": fmt.Sprintf(
				"projects/%s/locations/%s/repositories/%s/packages/%s/versions/v${BUILD_ID}",
				projectID, region, repository, packageName,
			),
		},
		Steps: []*cloudbuild.BuildStep{
			{
				Id:     "imagebuilder-customize",
				Name:   "us-docker.pkg.dev/image-builder-official/release/builder:stable",
				Script: "#!/usr/bin/env bash\n/build",
				Results: []*cloudbuild.StepResult{
					{
						Name:            "base_image",
						AttestationType: "https://cloudbuild.googleapis.com/attestations/build_content_restrictions",
					},
					{Name: "image_builder_telemetry_metrics"},
				},
			},
			{
				Id:      "imagebuilder-validate",
				Name:    "us-docker.pkg.dev/image-builder-official/release/validator:stable",
				Script:  "#!/usr/bin/env bash\n/validate",
				Results: []*cloudbuild.StepResult{{Name: "image_builder_telemetry_metrics"}},
			},
			{
				Id:      "imagebuilder-publish",
				Name:    "us-docker.pkg.dev/image-builder-official/release/builder:stable",
				Script:  "#!/usr/bin/env bash\n/publish",
				Results: []*cloudbuild.StepResult{{Name: "image_builder_telemetry_metrics"}},
			},
		},
		Options: &cloudbuild.BuildOptions{
			AutomapSubstitutions:  true,
			DynamicSubstitutions:  true,
			RequestedVerifyOption: "VERIFIED",
			SubstitutionOption:    "ALLOW_LOOSE",
			// Builds that run as a user-specified service account must set a
			// logging option.
			Logging: "CLOUD_LOGGING_ONLY",
		},
		Artifacts: &cloudbuild.Artifacts{
			GenericArtifacts: []*cloudbuild.GenericArtifact{
				{
					Folder:       "${_IMAGE_OUTPUT_PATH}",
					RegistryPath: "${_ARTIFACT_REGISTRY_RESOURCE_URI}",
				},
			},
		},
		Timeout: "3600s",
	}

	parent := fmt.Sprintf("projects/%s/locations/%s", projectID, region)
	op, err := cbService.Projects.Locations.Builds.Create(parent, req).Context(ctx).Do()
	if err != nil {
		return fmt.Errorf("Builds.Create: %w", err)
	}

	// The operation metadata contains the build that was created.
	var metadata cloudbuild.BuildOperationMetadata
	if err := json.Unmarshal(op.Metadata, &metadata); err != nil {
		return fmt.Errorf("json.Unmarshal: %w", err)
	}
	fmt.Fprintf(w, "Build submitted. ID: %s\n", metadata.Build.Id)
	fmt.Fprintf(w, "Logs: %s\n", metadata.Build.LogUrl)
	return nil
}

אימות ומעקב אחרי ה-build

כדי לעקוב אחרי ההתקדמות של צינור עיבוד הנתונים של ה-build, מבצעים את השלבים הבאים:

  1. נכנסים לדף Cloud Build במסוף Google Cloud .

    כניסה ל-Cloud Build

  2. בתפריט הניווט, לוחצים על History כדי לראות את המשימות הפעילות או שהושלמו.

  3. ברשימה Builds, לוחצים על Build ID של ה-build כדי לבדוק את יומני ההרצה של הקונטיינר. ביומנים מוצגים השלבים שמתבצעים ב-worker VM, כמו עדכונים של חבילות מערכת או פקודות מעטפת בהתאמה אישית, ואחריהם תוצאות של בדיקות אימות מה-test VM ורישום הפלט הסופי.

המאמרים הבאים