Puedes programar ejecuciones recurrentes de Image Builder con Cloud Scheduler y los activadores de Cloud Build. Cuando programas compilaciones de imágenes personalizadas del SO, 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 necesidad de intervención manual.
Antes de comenzar
- Completa los pasos de configuración del entorno en Prepara tu entorno.
-
Si aún no lo hiciste, configura la autenticación.
La autenticación verifica tu identidad para acceder a los servicios y las APIs de Cloud de Confiance by S3NS . 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 que corresponda a la forma en que planeas usar las muestras de esta página:
gcloud
-
Instala Google Cloud CLI y, luego, accede a gcloud CLI con tu identidad federada. Después de acceder, inicializa Google Cloud CLI con el siguiente comando:
gcloud init
-
- Configura una región y una zona predeterminadas.
-
Instala Google Cloud CLI.
-
Configura gcloud CLI para usar tu identidad federada.
Para obtener más información, consulta Accede a la gcloud CLI con tu identidad federada.
-
Crea credenciales de autenticación locales para tu cuenta de usuario:
gcloud auth application-default login
Si se devuelve un error de autenticación y usas un proveedor de identidad (IdP) externo, confirma que accediste a la gcloud CLI con tu identidad federada.
Go
Para usar las muestras de Go de 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 a través de 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 recurrentes de imagen de SO con gcloud CLI, completa los siguientes pasos:
Ejecuta el comando
gcloud builds triggers create manualpara crear un activador manual de Cloud Build que especifique tu archivocloudbuild.yamlde destino. Como Cloud Scheduler invoca este activador de forma manual en lugar de hacerlo en eventos del repositorio, no especifiques filtros de solicitudes de extracción o envío:gcloud builds triggers create manual \ --name="TRIGGER_NAME" \ --region=REGION \ --build-config=CLOUDBUILD_YAML_PATH \ --project=PROJECT_IDPara recuperar el ID único (
trigger_id) generado para tu nuevo activador, ejecuta el comandogcloud builds triggers describe: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 el programa cron de Unix que necesites, por ejemplo, semanalmente los lunes a las 6 a.m. con'0 6 * * 1', ejecuta el comandogcloud scheduler jobs create http: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: Es el nombre de tu activador de compilación manual de Cloud Build, por ejemplo,weekly-ubuntu-builder.REGION: Es la región en la que se creará el activador, por ejemplo,us-central1.CLOUDBUILD_YAML_PATH: Es la ruta de acceso a tu archivocloudbuild.yamlen tu directorio local, por ejemplo,cloudbuild.yaml.PROJECT_ID: el ID de tu proyectoJOB_NAME: Es el nombre de tu trabajo cron de Cloud Scheduler, por ejemplo,weekly-custom-os-patching.CRON_SCHEDULE: Es la expresión de programación cron de Unix, por ejemplo,'0 6 * * 1'.TRIGGER_ID: Es el ID único (trigger_id) generado para tu activador.SERVICE_ACCOUNT_EMAIL: Es la dirección de 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 Cloud de Confiance bibliotecas cliente de la API de Go (cloudbuild/v1 y cloudscheduler/v1).
En el siguiente ejemplo completo de Go, se muestra cómo analizar las marcas de línea de comandos y construir la solicitud Build a partir de la definición de 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 de Go programada
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?
- Aprende a automatizar compilaciones en eventos de repositorio en eventos de envío, etiquetado o combinación de Git con Terraform.
- Revisa el esquema de recetas de personalización para definir paquetes de software y procedimientos de validación.