Cloud Build and CI/CD
Cloud Build Configuration
# cloudbuild.tf
resource "google_cloudbuild_trigger" "build_trigger" {
name = "${var.environment}-build-trigger"
project = var.project_id
description = "Build and deploy to ${var.environment}"
github {
owner = var.github_owner
name = var.github_repo
push {
branch = "^${var.branch_name}$"
}
}
included_files = ["src/**", "terraform/**"]
service_account = google_service_account.cloudbuild_sa.id
build {
step {
name = "gcr.io/cloud-builders/docker"
args = [
"build",
"-t", "gcr.io/$PROJECT_ID/${var.app_name}:$COMMIT_SHA",
"."
]
}
step {
name = "gcr.io/cloud-builders/docker"
args = [
"push",
"gcr.io/$PROJECT_ID/${var.app_name}:$COMMIT_SHA"
]
}
step {
name = "hashicorp/terraform"
args = [
"init",
"-backend-config=bucket=${var.tf_state_bucket}",
"-backend-config=prefix=${var.environment}"
]
dir = "terraform"
}
step {
name = "hashicorp/terraform"
args = [
"apply",
"-var=image_tag=$COMMIT_SHA",
"-auto-approve"
]
dir = "terraform"
}
artifacts {
images = ["gcr.io/$PROJECT_ID/${var.app_name}:$COMMIT_SHA"]
}
}
}
# Cloud Build Service Account
resource "google_service_account" "cloudbuild_sa" {
account_id = "cloudbuild-sa"
display_name = "Cloud Build Service Account"
project = var.project_id
}
resource "google_project_iam_member" "cloudbuild_roles" {
for_each = toset([
"roles/cloudbuild.builds.builder",
"roles/container.developer",
"roles/storage.admin",
"roles/cloudkms.cryptoKeyEncrypterDecrypter"
])
project = var.project_id
role = each.value
member = "serviceAccount:${google_service_account.cloudbuild_sa.email}"
}
Artifact Registry
# artifacts.tf
resource "google_artifact_registry_repository" "repository" {
provider = google-beta
project = var.project_id
location = var.region
repository_id = "${var.environment}-repo"
description = "Docker repository for ${var.environment}"
format = "DOCKER"
docker_config {
immutable_tags = true
}
cleanup_policy_dry_run = false
cleanup_policies {
id = "keep-minimum-versions"
action = "KEEP"
most_recent_versions {
keep_count = 5
}
}
cleanup_policies {
id = "delete-old-versions"
action = "DELETE"
condition {
older_than = "2592000s" # 30 days
tag_state = "TAGGED"
}
}
}
# IAM for Artifact Registry
resource "google_artifact_registry_repository_iam_member" "repository_iam" {
for_each = var.repository_iam_members
project = google_artifact_registry_repository.repository.project
location = google_artifact_registry_repository.repository.location
repository = google_artifact_registry_repository.repository.name
role = each.value.role
member = each.value.member
}
Cloud Scheduler and Tasks
Cloud Scheduler
# scheduler.tf
resource "google_cloud_scheduler_job" "jobs" {
for_each = var.scheduler_jobs
name = each.key
project = var.project_id
region = var.region
description = each.value.description
schedule = each.value.schedule
time_zone = each.value.time_zone
attempt_deadline = each.value.deadline
retry_config {
retry_count = each.value.retry_count
max_retry_duration = each.value.max_retry_duration
min_backoff_duration = each.value.min_backoff_duration
max_backoff_duration = each.value.max_backoff_duration
max_doublings = each.value.max_doublings
}
http_target {
uri = each.value.target_uri
http_method = each.value.http_method
headers = each.value.headers
body = base64encode(jsonencode(each.value.body))
oauth_token {
service_account_email = google_service_account.scheduler_sa[each.key].email
}
}
}
# Service Account for Scheduler
resource "google_service_account" "scheduler_sa" {
for_each = var.scheduler_jobs
account_id = "scheduler-${each.key}"
display_name = "Service Account for ${each.key} scheduler"
project = var.project_id
}
Cloud Tasks
# cloudtasks.tf
resource "google_cloud_tasks_queue" "queue" {
for_each = var.task_queues
name = each.key
project = var.project_id
location = var.region
rate_limits {
max_concurrent_dispatches = each.value.max_concurrent
max_dispatches_per_second = each.value.max_rate
}
retry_config {
max_attempts = each.value.max_attempts
max_retry_duration = each.value.max_retry_duration
min_backoff = each.value.min_backoff
max_backoff = each.value.max_backoff
max_doublings = each.value.max_doublings
}
stackdriver_logging_config {
sampling_ratio = 1.0
}
}
# IAM for Cloud Tasks
resource "google_cloud_tasks_queue_iam_member" "queue_invoker" {
for_each = var.task_queues
name = google_cloud_tasks_queue.queue[each.key].name
project = var.project_id
location = var.region
role = "roles/cloudtasks.enqueuer"
member = "serviceAccount:${google_service_account.task_sa[each.key].email}"
}
Advanced Compute Configuration
Instance Groups and Autoscaling
# compute_advanced.tf
resource "google_compute_instance_template" "template" {
name_prefix = "${var.environment}-template-"
project = var.project_id
machine_type = var.machine_type
region = var.region
disk {
source_image = var.boot_image
auto_delete = true
boot = true
disk_type = "pd-ssd"
disk_size_gb = var.boot_disk_size
dynamic "disk_encryption_key" {
for_each = var.kms_key_id != null ? [1] : []
content {
kms_key_self_link = var.kms_key_id
}
}
}
network_interface {
network = var.network_id
subnetwork = var.subnet_id
dynamic "alias_ip_range" {
for_each = var.alias_ip_ranges
content {
ip_cidr_range = alias_ip_range.value.cidr
subnetwork_range_name = alias_ip_range.value.range_name
}
}
}
metadata = {
startup-script = templatefile("${path.module}/scripts/startup.sh", {
environment = var.environment
config = var.app_config
})
shutdown-script = file("${path.module}/scripts/shutdown.sh")
}
service_account {
email = google_service_account.instance_sa.email
scopes = ["cloud-platform"]
}
lifecycle {
create_before_destroy = true
}
labels = var.labels
tags = var.network_tags
}
resource "google_compute_region_instance_group_manager" "mig" {
name = "${var.environment}-mig"
project = var.project_id
base_instance_name = "${var.environment}-instance"
region = var.region
version {
instance_template = google_compute_instance_template.template.id
name = "primary"
}
target_pools = [google_compute_target_pool.pool.id]
named_port {
name = "http"
port = 8080
}
auto_healing_policies {
health_check = google_compute_health_check.autohealing.id
initial_delay_sec = 300
}
update_policy {
type = "PROACTIVE"
minimal_action = "REPLACE"
most_disruptive_allowed_action = "REPLACE"
max_surge_fixed = 3
max_unavailable_fixed = 0
min_ready_sec = 60
}
}
resource "google_compute_region_autoscaler" "autoscaler" {
name = "${var.environment}-autoscaler"
project = var.project_id
region = var.region
target = google_compute_region_instance_group_manager.mig.id
autoscaling_policy {
max_replicas = var.max_replicas
min_replicas = var.min_replicas
cooldown_period = 60
cpu_utilization {
target = 0.7
}
metric {
name = "custom.googleapis.com/metric"
target = 100
type = "GAUGE"
}
scale_in_control {
max_scaled_in_replicas {
fixed = 2
}
time_window_sec = 300
}
}
}
[Continue to Part 5 with Serverless, App Engine, and more advanced configurations?]
Would you like me to continue with the next part covering Serverless, App Engine, and more advanced GCP configurations?