Erstellung benutzerdefinierter Betriebssystem-Images planen

Sie können wiederkehrende Image Builder-Ausführungen mit Cloud Scheduler- und Cloud Build-Triggern planen. Wenn Sie benutzerdefinierte Betriebssystem-Image-Builds planen, aktualisiert Cloud Build Ihre Basis-Images automatisch mit Betriebssystem-Patches und Sicherheitsrichtlinien der Organisation, ohne dass ein manueller Eingriff erforderlich ist.

Hinweis

  • Führen Sie die Schritte zur Umgebungseinrichtung unter Umgebung vorbereiten aus.
  • Richten Sie die Authentifizierung ein, falls Sie dies noch nicht getan haben. Bei der Authentifizierung wird Ihre Identität für den Zugriff auf Google Cloud Dienste und APIs überprüft. Wenn Sie Code oder Beispiele aus einer lokalen Entwicklungsumgebung ausführen möchten, können Sie sich bei Compute Engine authentifizieren. Wählen Sie dazu eine der folgenden Optionen aus:

    Wählen Sie den Tab für die Verwendung der Beispiele auf dieser Seite aus:

    gcloud

    1. Installieren Sie die Google Cloud CLI. Initialisieren Sie die Google Cloud CLI nach der Installation mit dem folgenden Befehl:

      gcloud init

      Wenn Sie einen externen Identitätsanbieter (IdP) verwenden, müssen Sie sich zuerst mit Ihrer föderierten Identität in der gcloud CLI anmelden.

  • Legen Sie eine Standardregion und -zone fest.
  • Go

    Wenn Sie die Go-Beispiele auf dieser Seite in einer lokalen Entwicklungsumgebung verwenden möchten, installieren und initialisieren Sie die gcloud CLI und richten Sie dann die Standardanmeldedaten für Anwendungen mit Ihren Nutzeranmeldedaten ein.

    1. Installieren Sie die Google Cloud CLI.

    2. Wenn Sie einen externen Identitätsanbieter (IdP) verwenden, müssen Sie sich zuerst mit Ihrer föderierten Identität in der gcloud CLI anmelden.

    3. Wenn Sie eine lokale Shell verwenden, erstellen Sie lokale Anmeldedaten zur Authentifizierung für Ihr Nutzerkonto:

      gcloud auth application-default login

      Wenn Sie Cloud Shell verwenden, ist dies nicht erforderlich.

      Wenn ein Authentifizierungsfehler zurückgegeben wird und Sie einen externen Identitätsanbieter (IdP) verwenden, prüfen Sie, ob Sie sich mit Ihrer föderierten Identität in der gcloud CLI angemeldet haben.

    Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

Erforderliche Rollen

Bitten Sie Ihren Administrator, Ihnen die folgenden IAM-Rollen für Ihr Projekt zuzuweisen, um die Berechtigungen zu erhalten, die Sie zum Erstellen von Triggern und Planen von Builds benötigen:

  • Cloud Build-Bearbeiter (roles/cloudbuild.builds.editor)
  • Cloud Scheduler-Jobinitiator (roles/cloudscheduler.jobRunner) oder Cloud Scheduler-Administrator (roles/cloudscheduler.admin)
  • Service Account User (roles/iam.serviceAccountUser)

Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zugriff auf Projekte, Ordner und Organisationen verwalten.

Sie können die erforderlichen Berechtigungen auch über benutzerdefinierte Rollen oder andere vordefinierte Rollen erhalten.

Geplante Build-Pipeline erstellen

Sie können wiederkehrende Image-Builds mit der gcloud CLI oder den Go-Client-SDKs konfigurieren:

gcloud

So planen Sie wiederkehrende Betriebssystem-Image-Builds mit der gcloud CLI:

  1. Erstellen Sie einen manuellen Cloud Build-Trigger, der Ihre Ziel cloudbuild.yaml Datei angibt, indem Sie den gcloud builds triggers create manual Befehl ausführen. Da Cloud Scheduler diesen Trigger manuell und nicht bei Repository-Ereignissen aufruft, geben Sie keine Push- oder Pull-Anfrage Filter an:

    gcloud builds triggers create manual \
        --name="TRIGGER_NAME" \
        --region=REGION \
        --build-config=CLOUDBUILD_YAML_PATH \
        --project=PROJECT_ID
    
  2. Rufen Sie die eindeutige ID (trigger_id) ab, die für Ihren neuen Trigger generiert wurde, indem Sie den gcloud builds triggers describe Befehl ausführen:

    gcloud builds triggers describe TRIGGER_NAME \
        --region=REGION \
        --format="value(id)" \
        --project=PROJECT_ID
    
  3. Wenn Sie einen Cloud Scheduler-Job erstellen möchten, der gemäß Ihrem erforderlichen Unix-Cron Zeitplan eine HTTP POST Anfrage an die Cloud Build API (projects.locations.triggers.run) sendet, z. B. wöchentlich montags um 6:00 Uhr mit '0 6 * * 1', führen Sie den gcloud scheduler jobs create http Befehl aus:

    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
    

Ersetzen Sie Folgendes:

  • TRIGGER_NAME: der Name für Ihren manuellen Cloud Build-Trigger, z. B. weekly-ubuntu-builder.
  • REGION: die Region, in der der Trigger erstellt werden soll, z. B. us-central1.
  • CLOUDBUILD_YAML_PATH: der Pfad zu Ihrer cloudbuild.yaml -Datei in Ihrem lokalen Verzeichnis, z. B. cloudbuild.yaml.
  • PROJECT_ID: Ihre Projekt-ID.
  • JOB_NAME: der Name für Ihren Cloud Scheduler-Cron-Job, z. B. weekly-custom-os-patching.
  • CRON_SCHEDULE: der Unix-Cron-Zeitplanausdruck, z. B. '0 6 * * 1'.
  • TRIGGER_ID: die eindeutige ID (trigger_id), die für Ihren Trigger generiert wurde.
  • SERVICE_ACCOUNT_EMAIL: die E-Mail-Adresse des Dienstkontos, mit der Cloud Scheduler den Trigger aufrufen kann. Für dieses Dienstkonto sind die Berechtigungen roles/cloudbuild.builds.editor erforderlich.

Go

Sie können Pipelines programmatisch in Ihren Unternehmens anwendungen mit den Google Cloud Go API-Clientbibliotheken (cloudbuild/v1 und cloudscheduler/v1) planen.

Das folgende vollständige Go-Beispiel zeigt, wie Sie Befehlszeilen-Flags parsen und die Build-Anfrage aus Ihrer imagebuilder.yaml-Definition erstellen. Das Programm registriert dann einen manuellen Cloud Build-Trigger und stellt einen Cloud Scheduler-Job bereit, wenn Sie das Flag --cron_schedule angeben.

// 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
}

Geplante Go-Anwendung ausführen

Führen Sie den folgenden Befehl aus, um die kompilierte Go-Binärdatei auszuführen und die wiederkehrende Ausführung jeden Montag um 6:00 Uhr zu planen:

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'

Nächste Schritte