Puedes programar ejecuciones recurrentes de Image Builder con Cloud Scheduler y activadores de Cloud Build. Cuando programas compilaciones de imágenes de SO personalizadas, Cloud Build actualiza automáticamente tus imágenes de referencia con parches del sistema operativo y políticas de seguridad de la organización sin requerir intervención manual.
Antes de comenzar
- Completa los pasos de configuración del entorno en Prepara el entorno.
-
Si aún no lo hiciste, configura la autenticación.
La autenticación verifica tu identidad para acceder a los Google Cloud servicios y las APIs. Para ejecutar
código o muestras desde un entorno de desarrollo local, puedes autenticarte en
Compute Engine seleccionando una de las siguientes opciones:
Selecciona la pestaña según cómo planeas usar las muestras de esta página:
gcloud
-
Instala la Google Cloud CLI. Después de la instalación, inicializa Google Cloud CLI con el siguiente comando:
gcloud initSi usas un proveedor de identidad (IdP) externo, primero debes acceder a la gcloud CLI con tu identidad federada.
-
- Configura una región y una zona predeterminadas.
-
Instala la Google Cloud CLI.
-
Si usas un proveedor de identidad (IdP) externo, primero debes acceder a la gcloud CLI con tu identidad federada.
-
Si usas un shell local, crea credenciales de autenticación locales para tu cuenta de usuario:
gcloud auth application-default login
No es necesario que lo hagas si usas Cloud Shell.
Si se muestra un error de autenticación y usas un proveedor de identidad (IdP) externo, confirma que accediste a gcloud CLI con tu identidad federada.
Go
Para usar las muestras de Go incluidas en esta página en un entorno de desarrollo local, instala e inicializa la gcloud CLI y, luego, configura las credenciales predeterminadas de la aplicación con tus credenciales de usuario.
Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.
Roles obligatorios
Para obtener los permisos que necesitas para crear activadores y programar compilaciones, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:
- Editor de Cloud Build (
roles/cloudbuild.builds.editor) - Ejecutor de trabajos de Cloud Scheduler (
roles/cloudscheduler.jobRunner) o Administrador de Cloud Scheduler (roles/cloudscheduler.admin) - Usuario de la cuenta de servicio (
roles/iam.serviceAccountUser)
Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.
También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.
Crea una canalización de compilación programada
Puedes configurar compilaciones de imágenes recurrentes con gcloud CLI o los SDKs de cliente de Go:
gcloud
Para programar compilaciones de imagen de SO recurrentes con gcloud CLI, completa los siguientes pasos:
Ejecuta el
gcloud builds triggers create manualcomando para crear un activador de compilación manual de Cloud Build que especifique tu archivocloudbuild.yamlde destino. Como Cloud Scheduler invoca este activador de forma manual en lugar de en eventos del repositorio, no especifiques filtros de envío ni de solicitud de extracción:gcloud builds triggers create manual \ --name="TRIGGER_NAME" \ --region=REGION \ --build-config=CLOUDBUILD_YAML_PATH \ --project=PROJECT_IDEjecuta el comando
gcloud builds triggers describepara recuperar el ID único (trigger_id) generado para tu activador nuevo:gcloud builds triggers describe TRIGGER_NAME \ --region=REGION \ --format="value(id)" \ --project=PROJECT_IDPara crear un trabajo de Cloud Scheduler que envíe una solicitud
HTTP POSTa la API de Cloud Build (projects.locations.triggers.run) según tu programación cron de Unix requerida, por ejemplo, semanalmente los lunes a las 6:00 a.m. con'0 6 * * 1', ejecuta elgcloud scheduler jobs create httpcomando: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
Reemplaza lo siguiente:
TRIGGER_NAME: El nombre de tu activador de compilación de Cloud Build, por ejemplo,weekly-ubuntu-builder.REGION: La región para crear el activador, por ejemplo,us-central1.CLOUDBUILD_YAML_PATH: La ruta de acceso a tucloudbuild.yamlarchivo en tu directorio local, por ejemplo,cloudbuild.yaml.PROJECT_ID: ID del proyectoJOB_NAME: El nombre de tu trabajo cron de Cloud Scheduler, por ejemplo,weekly-custom-os-patching.CRON_SCHEDULE: La expresión de programación cron de Unix, por ejemplo,'0 6 * * 1'.TRIGGER_ID: El ID único (trigger_id) generado para tu activador.SERVICE_ACCOUNT_EMAIL: El correo electrónico de la cuenta de servicio que autoriza a Cloud Scheduler a invocar el activador. Esta cuenta de servicio requiere permisosroles/cloudbuild.builds.editor.
Go
Puedes programar canalizaciones de forma programática dentro de tus aplicaciones empresariales con las Google Cloud bibliotecas cliente de la API de Go (cloudbuild/v1 y cloudscheduler/v1).
En el siguiente ejemplo completo de Go, se muestra cómo analizar marcas de línea de comandos y construir la solicitud Build a partir de tu definición imagebuilder.yaml. Luego, el programa registra un activador manual de Cloud Build y aprovisiona un trabajo de Cloud Scheduler cuando proporcionas la marca --cron_schedule.
// 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
}
Ejecuta la aplicación programada de Go
Para ejecutar el objeto binario de Go compilado y programar la ejecución recurrente todos los lunes a las 6:00 a.m., ejecuta el siguiente comando:
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'
¿Qué sigue?
- Obtén información para automatizar compilaciones en eventos del repositorio en eventos de envío, etiqueta o combinación de Git con Terraform.
- Revisa el esquema de la receta de personalización para definir paquetes de software y procedimientos de validación.