使用 Google Cloud CLI 或 Terraform 以编程方式配置和提交 Image Builder 流水线。以程序化方式配置流水线,可让您在声明性配置文件中定义基础设施设置、基本操作系统映像、自定义操作和验证测试。
准备工作
- 完成准备环境中的环境设置步骤。
- 如果您打算使用 Terraform 部署流水线或自动执行代码库中的构建,请使用 Cloud Build 代码库 (
2nd gen) 或 Developer Connect 连接链接连接您的 GitHub、GitLab 或 Bitbucket 代码库。 - 如果您计划使用 Terraform,请安装 1.3 版或更高版本的 Terraform CLI。
-
如果您尚未设置身份验证,请进行设置。身份验证用于验证您的身份,以便访问 Google Cloud 服务和 API。如需从本地开发环境运行代码或示例,您可以通过选择以下选项之一向 Compute Engine 进行身份验证:
选择标签页以了解您打算如何使用本页面上的示例:
gcloud
-
安装 Google Cloud CLI。 安装完成后,运行以下命令来初始化 Google Cloud CLI:
gcloud init如果您使用的是外部身份提供方 (IdP),则必须先使用联合身份登录 gcloud CLI。
-
- 设置默认区域和可用区。
-
安装 Google Cloud CLI。
-
如果您使用的是外部身份提供方 (IdP),则必须先使用联合身份登录 gcloud CLI。
-
如果您使用的是本地 shell,请为您的用户账号创建本地身份验证凭证:
gcloud auth application-default login
如果您使用的是 Cloud Shell,则无需执行此操作。
如果系统返回身份验证错误,并且您使用的是外部身份提供方 (IdP),请确认您已 使用联合身份登录 gcloud CLI。
Terraform
如需在本地开发环境中使用本页面上的 Terraform 示例,请安装并初始化 gcloud CLI,然后使用您的用户凭证设置应用默认凭据。
如需了解详情,请参阅 为本地开发环境设置身份验证。
所需的角色
如需获得使用 Google Cloud CLI 或 Terraform 创建和提交映像自定义流水线所需的权限,请让管理员向您授予项目的以下 IAM 角色:
- Cloud Build Editor (
roles/cloudbuild.builds.editor) - Service Account User (
roles/iam.serviceAccountUser)
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
创建配置文件
如需使用 gcloud CLI 或 Terraform 配置流水线,请创建两个配置文件:
imagebuilder.yaml:定义映像的自定义配方,包括基础操作系统映像、工作器虚拟机基础设施设置、目标映像输出详细信息,以及顺序自定义步骤,例如运行 shell 脚本、传输文件或执行重新启动。cloudbuild.yaml:编排 Cloud Build 中的构建流程步骤,包括解析、验证、构建、测试和发布自定义操作系统映像。
创建映像配置文件
如需指定映像配置,请在本地目录中创建一个名为 imagebuilder.yaml 的文件。如需查看所有受支持的架构字段和自定义操作的完整列表,请参阅自定义配方架构和支持的自定义操作。
以下示例 imagebuilder.yaml 文件配置了一个流水线,该流水线使用指定区域和可用区中的 e2-standard-4 工作器虚拟机机构建自定义 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 可用的区域受支持。
- 工作器虚拟机
ZONE必须位于您指定的REGION内。 - 为最大限度地减少网络延迟并避免产生跨区域出站流量费用,请确保您的工作器虚拟机可用区、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 项目 ID。REGION:您的 Artifact Registry 代码库的 Google Cloud 区域,例如us-east1或europe-west1。SERVICE_ACCOUNT_EMAIL:您配置了所需 IAM 权限的服务账号的电子邮件地址。REPOSITORY和PACKAGE:在 Artifact Registry 中创建的目标代码库和软件包名称。如需设置 Artifact Registry 注册表,请参阅配置 Artifact Registry。
创建并提交构建流水线
如需运行映像自定义流水线,请使用 gcloud CLI 提交 build,或使用 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
如需预配自动构建和验证自定义操作系统映像所需的基础设施,您可以使用 Terraform。此 Terraform 配置可完成以下任务:
- 启用必需的 Google Cloud API。
- 创建专用 Cloud Storage 存储桶 (
workdir_bucket) 以存储临时日志和 build 工件。 - 配置与 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 服务账号中配置的 build 服务账号的电子邮件地址。LOCATION、CONNECTION和REPO_NAME:在关联代码库中配置的 Developer Connect 主机区域、连接名称和代码库链接。CLOUDBUILD_YAML_PATH:本地目录中cloudbuild.yaml文件的相对路径。您无需将cloudbuild.yaml签入 Git 代码库。RECIPE_PATH:签入到 Git 代码库中的imagebuilder.yaml自定义配方文件的相对路径。REPOSITORY_NAME:在配置 Artifact Registry 中创建的现有通用 Artifact Registry 代码库。
替换以下占位符,以用于 Terraform 创建的资源:
REGION:Terraform 用于预配 Cloud Storage 临时存储桶和 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 代码库中创建的软件包的名称。此软件包存储已发布的操作系统映像版本,例如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
- 初始化目录:
验证和监控 build
如需跟踪 build 流水线的进度,请完成以下步骤:
在 Google Cloud 控制台中,前往 Cloud Build 页面。
在导航菜单中,点击历史记录以查看有效或已完成的作业。
在构建列表中,点击相应构建的构建 ID 以检查容器运行日志。日志会显示工作器虚拟机中执行的步骤(例如系统软件包更新或自定义 shell 命令)、测试虚拟机的验证测试结果以及最终输出注册。
后续步骤
- 如需通过命令行配置和启动周期性或自动化构建,请执行以下操作:
- 验证图片来源