Cloud Scheduler 및 Cloud Build 트리거를 사용하여 반복되는 Image Builder 실행을 예약할 수 있습니다. 커스텀 OS 이미지 빌드를 예약하면 Cloud Build가 수동 개입 없이 운영체제 패치 및 조직 보안 정책으로 기준 이미지를 자동으로 업데이트합니다.
시작하기 전에
- 환경 준비의 환경 설정 단계를 완료합니다.
-
아직 인증을 설정하지 않았다면 설정합니다.
인증은 Google Cloud 서비스 및 API에 액세스하기 위해 ID를 확인합니다. 로컬 개발 환경에서 코드 또는 샘플을 실행하려면 다음 옵션 중 하나를 선택하여 Compute Engine에 인증하면 됩니다.
이 페이지의 샘플 사용 방법에 대한 탭을 선택하세요.
gcloud
-
Google Cloud CLI를 설치합니다. 설치 후 Google Cloud CLI를 초기화하려면 다음 명령어를 실행합니다.
gcloud init외부 ID 공급업체 (IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.
-
- 기본 리전 및 영역을 설정합니다.
-
Google Cloud CLI를 설치합니다.
-
외부 ID 공급업체 (IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.
-
로컬 셸을 사용하는 경우 사용자 계정에 대한 로컬 인증 사용자 인증 정보를 만듭니다. 사용자 계정에 대한 로컬 인증 사용자 인증 정보 만들기:
gcloud auth application-default login
Cloud Shell을 사용하는 경우 이 작업을 수행할 필요는 없습니다.
인증 오류가 반환되고 외부 ID 공급업체 (IdP)를 사용하는 경우 제휴 ID로 gcloud CLI에 로그인했는지 확인합니다.
Go
로컬 개발 환경에서 이 페이지의 Go 샘플을 사용하려면 gcloud CLI를 설치하고 초기화한 후 사용자 인증 정보로 애플리케이션 기본 사용자 인증 정보를 설정합니다.
자세한 내용은 로컬 개발 환경의 인증 설정을 참고하세요.
필요한 역할
트리거를 만들고 빌드를 예약하는 데 필요한 권한을 얻으려면 관리자에게 프로젝트에 대한 다음 IAM 역할을 부여해 달라고 요청하세요.
- Cloud Build 편집자 (
roles/cloudbuild.builds.editor) - Cloud Scheduler 작업 실행자 (
roles/cloudscheduler.jobRunner) 또는 Cloud Scheduler 관리자 (roles/cloudscheduler.admin) - 서비스 계정 사용자 (
roles/iam.serviceAccountUser)
역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.
커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.
예약된 빌드 파이프라인 만들기
gcloud CLI 또는 Go 클라이언트 SDK를 사용하여 반복되는 이미지 빌드를 구성할 수 있습니다.
gcloud
gcloud CLI를 사용하여 반복되는 OS 이미지 빌드를 예약하려면 다음 단계를 완료하세요.
대상
cloudbuild.yaml파일을 지정하는 수동 Cloud Build 빌드 트리거를gcloud builds triggers create manual명령어를 실행하여 만듭니다. Cloud Scheduler는 저장소 이벤트가 아닌 수동으로 이 트리거를 호출하므로 푸시 또는 pull 요청 필터를 지정하지 마세요.gcloud builds triggers create manual \ --name="TRIGGER_NAME" \ --region=REGION \ --build-config=CLOUDBUILD_YAML_PATH \ --project=PROJECT_ID새 트리거에 대해 생성된 고유 ID (
trigger_id)를gcloud builds triggers describe명령어를 실행하여 가져옵니다.gcloud builds triggers describe TRIGGER_NAME \ --region=REGION \ --format="value(id)" \ --project=PROJECT_ID필요한 Unix cron 일정에 따라 Cloud Build API(
projects.locations.triggers.run)에HTTP POST요청을 전송하는 Cloud Scheduler 작업을 만들려면(예: 월요일 오전 6시에'0 6 * * 1'사용)gcloud 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
다음을 바꿉니다.
TRIGGER_NAME: 수동 Cloud Build 빌드 트리거의 이름(예:weekly-ubuntu-builder)REGION: 트리거를 만들 리전(예:us-central1)CLOUDBUILD_YAML_PATH: 로컬 디렉터리에 있는cloudbuild.yaml파일의 경로(예:cloudbuild.yaml)PROJECT_ID: 프로젝트 IDJOB_NAME: Cloud Scheduler 크론 작업의 이름(예:weekly-custom-os-patching)CRON_SCHEDULE: Unix cron 일정 표현식 (예:'0 6 * * 1')TRIGGER_ID: 트리거에 대해 생성된 고유 ID (trigger_id)SERVICE_ACCOUNT_EMAIL: Cloud Scheduler가 트리거를 호출하도록 승인하는 서비스 계정 이메일 이 서비스 계정에는roles/cloudbuild.builds.editor권한이 필요합니다.
Go
Google Cloud Go API 클라이언트 라이브러리
(cloudbuild/v1 및 cloudscheduler/v1)를 사용하여 엔터프라이즈
애플리케이션 내에서 프로그래매틱 방식으로 파이프라인을 예약할 수 있습니다.
다음 전체 Go 예시는 명령줄 플래그를 파싱하고 imagebuilder.yaml 정의에서 Build 요청을 구성하는 방법을 보여줍니다. 그런 다음 프로그램은 --cron_schedule 플래그를 제공할 때 수동 Cloud Build 트리거를 등록하고 Cloud Scheduler 작업을 프로비저닝합니다.
// 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
}
예약된 Go 애플리케이션 실행
컴파일된 Go 바이너리를 실행하고 매주 월요일 오전 6시에 반복 실행을 예약하려면 다음 명령어를 실행합니다.
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'
다음 단계
- Terraform을 사용하여 Git 푸시, 태그 또는 병합 이벤트의 저장소 이벤트에서 빌드를 자동화하는 방법을 알아봅니다.
- 소프트웨어 패키지 및 유효성 검사 절차를 정의하려면 맞춤설정 레시피 스키마 를 검토하세요.