使用 Google Cloud CLI 或 Terraform,以程式輔助方式設定及提交 Image Builder 管道。以程式輔助方式設定管道,可在宣告式設定檔中定義基礎架構設定、基礎 OS 映像檔、自訂動作和驗證測試。
事前準備
- 請按照「準備環境」一文中的步驟完成環境設定。
- 如要使用 Terraform 部署管道,或從存放區自動建構,請使用 Cloud Build 存放區 (
2nd gen) 或 Developer Connect 連線連結,連結 GitHub、GitLab 或 Bitbucket 存放區。 - 如果您打算使用 Terraform,請安裝 Terraform CLI 1.3 以上版本。
-
如果尚未設定驗證,請先完成設定。
驗證可確認您的身分,以便存取 Google Cloud 服務和 API。如要從本機開發環境執行程式碼或範例,請選取下列其中一個選項,向 Compute Engine 進行驗證:
選取這個頁面上您打算如何使用範例的分頁:
gcloud
-
安裝 Google Cloud CLI。 完成後,執行下列指令來初始化 Google Cloud CLI:
gcloud init若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI。
-
- 設定預設地區和區域。
-
安裝 Google Cloud CLI。
-
若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI。
-
如果您使用本機殼層,請為使用者帳戶建立本機驗證憑證:
gcloud auth application-default login
如果您使用 Cloud Shell,則不需要執行這項操作。
如果系統傳回驗證錯誤,且您使用外部識別資訊提供者 (IdP),請確認您已 使用聯合身分登入 gcloud CLI。
Terraform
如要在本機開發環境中使用本頁的 Terraform 範例,請安裝並初始化 gcloud CLI,然後使用使用者憑證設定應用程式預設憑證。
詳情請參閱 這篇文章,瞭解如何設定本機開發環境的驗證機制。
必要的角色
如要取得使用 Google Cloud CLI 或 Terraform 建立及提交映像檔自訂管道所需的權限,請要求管理員在專案中授予您下列 IAM 角色:
- Cloud Build 編輯者 (
roles/cloudbuild.builds.editor) - 服務帳戶使用者 (
roles/iam.serviceAccountUser)
如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。
建立設定檔
如要使用 gcloud CLI 或 Terraform 設定管道,請建立兩個設定檔:
imagebuilder.yaml:定義映像檔的自訂方式,包括基礎 OS 映像檔、工作站 VM 基礎架構設定、目標映像檔輸出詳細資料,以及依序執行的自訂步驟,例如執行 Shell 指令碼、傳輸檔案或重新啟動。cloudbuild.yaml: 協調 Cloud Build 中的建構程序步驟,包括剖析、驗證、建構、測試及發布自訂 OS 映像檔。
建立映像檔設定檔
如要指定映像檔設定,請在本地目錄中建立名為 imagebuilder.yaml 的檔案。如需所有支援的架構欄位和自訂動作完整清單,請參閱自訂食譜架構和支援的自訂動作。
下列範例 imagebuilder.yaml 檔案會設定管道,在您指定的區域和可用區中,使用 e2-standard-4 worker VM 建構自訂的 Ubuntu 22.04 LTS 映像檔,並執行系統套件更新。
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:您的專案 ID。REGION:目標圖片儲存位置,例如us-east1或europe-west1。請確認符合下列區域和可用區規定:- Image Builder 僅支援Cloud Build 支援的區域。
- 工作站 VM
ZONE必須位於您指定的REGION內。 - 為盡量縮短網路延遲時間並避免產生跨區域輸出費用,請確保工作站 VM 區域、Cloud Storage 暫存值區、Artifact Registry 存放區和目標映像檔儲存位置位於相同區域。
ZONE:位於指定REGION內的區域,例如us-east1-b或europe-west1-b。
建立自動化調度管理工具建構檔案
在同一個目錄中建立名為 cloudbuild.yaml 的檔案。這個檔案會呼叫 Image Builder 容器步驟,以建構、驗證及發布自訂 OS 映像檔。
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 bucket,用做暫時的暫存工作區。如果沒有 bucket,可以執行gcloud storage buckets create gs://STAGING_BUCKET_NAME建立 bucket。如果您使用 Terraform 部署管道,Terraform 會自動建立這個值區。PROJECT_ID:您的 Google Cloud 專案 ID。REGION:Artifact Registry 存放區的 Google Cloud 區域,例如us-east1或europe-west1。SERVICE_ACCOUNT_EMAIL:您設定了必要 IAM 權限的服務帳戶電子郵件地址。REPOSITORY和PACKAGE:在 Artifact Registry 中建立的目標存放區和套件名稱。如要設定 Artifact Registry 登錄檔,請參閱「設定 Artifact Registry」。
建立並提交建構管道
如要執行映像檔自訂管道,請使用 gcloud CLI 提交建構作業,或使用 Terraform 部署管道。選取下列其中一個分頁:
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 專案 ID。REGION:執行映像檔自訂管道作業的 Google Cloud 區域。SERVICE_ACCOUNT_EMAIL:已設定必要 IAM 權限的服務帳戶電子郵件地址。
這個指令會上傳自訂工作區、註冊 Cloud Build 執行作業,並啟動協調容器。
Terraform
如要佈建基礎架構,以便自動建構及驗證自訂 OS 映像檔,可以使用 Terraform。這項 Terraform 設定會完成下列工作:
- 啟用必要的 Google Cloud API。
- 建立專屬的 Cloud Storage bucket (
workdir_bucket),用於儲存臨時記錄和建構構件。 - 設定連結至 Developer Connect GitHub 存放區連線的 Cloud Build 自動建構觸發條件 (
image_builder_trigger)。
建立 Terraform 設定檔
如要使用 Terraform 整理及部署管道基礎架構,請完成下列步驟:
在本機工作站或 CI/CD 環境中,建立與應用程式存放區分開的專屬目錄,然後變更為該目錄:
mkdir terraform-image-builder && cd terraform-image-builder
在這個目錄中,建立下列五個 Terraform 設定檔:
terraform.tfvars:設定專案專屬變數的值。main.tf:在 Google Cloud 專案中佈建資源,包括啟用必要 API、建立 Cloud Storage 暫存值區 (workdir_bucket),以及部署 Cloud Build 自動建構觸發條件 (image_builder_trigger)。outputs.tf:定義部署後顯示在終端機中的輸出值,例如觸發程序 ID 和暫存值區名稱。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"
將下列預留位置替換為現有資源:
PROJECT_ID:現有 Google Cloud 專案 ID。SERVICE_ACCOUNT_EMAIL:在「設定 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:Terraform 佈建 Cloud Storage 暫存 bucket 和 Cloud Build 自動建構觸發條件的目標 Google Cloud區域,例如us-central1。TRIGGER_NAME:Terraform 建立的新 Cloud Build 存放區觸發條件名稱,例如git-push-os-builder。LIFECYCLE_DAYS:以天為單位的保留期限,超過期限後,Terraform 建立的 Cloud Storage 暫存值區中的中繼構件會自動刪除,例如30。PACKAGE_NAME:您希望 Terraform 用於在 Artifact Registry 存放區內建立的套件名稱。這個套件會儲存已發布的 OS 映像檔版本,例如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." }如要部署設定,請在包含 Terraform 檔案的目錄中執行下列指令:
- 初始化目錄:
terraform init
- 驗證語法:
terraform validate
- 預覽部署作業:
terraform plan
- 套用設定:
terraform apply
- 初始化目錄:
驗證及監控建構作業
如要追蹤建構管道的進度,請完成下列步驟:
前往 Google Cloud 控制台的「Cloud Build」頁面。
在導覽選單中,按一下「記錄」即可查看進行中或已完成的工作。
在「建構」清單中,按一下建構項目的「建構 ID」,即可檢查容器執行記錄。記錄檔會顯示工作站 VM 中執行的步驟,例如系統套件更新或自訂殼層指令,接著是測試 VM 的驗證測試結果,以及最終輸出註冊。
後續步驟
- 如要透過指令列設定及啟動週期性或自動化建構作業,請按照下列步驟操作:
- 驗證圖片來源