😸

Maintenance Routing

2025/02/25に公開

네, 심야 유지보수를 위한 sorry 페이지 설정 방법을 설명드리겠습니다.

  1. 먼저 sorry 페이지용 Cloud Storage 버킷을 생성합니다:
modules/maintenance/storage.tf
resource "google_storage_bucket" "maintenance_page" {
  name          = "maintenance-page-bucket"
  location      = "ASIA-NORTHEAST1"
  force_destroy = true

  uniform_bucket_level_access = true

  website {
    main_page_suffix = "index.html"
    not_found_page   = "404.html"
  }
}

# sorry 페이지용 IAM 설정
resource "google_storage_bucket_iam_member" "public_read" {
  bucket = google_storage_bucket.maintenance_page.name
  role   = "roles/storage.objectViewer"
  member = "allUsers"
}
  1. Cloud Scheduler를 사용하여 유지보수 모드 전환을 자동화합니다:
modules/maintenance/scheduler.tf
resource "google_cloud_scheduler_job" "maintenance_start" {
  name     = "maintenance-mode-start"
  schedule = "0 4 * * *"  # 매일 04:00
  time_zone = "Asia/Tokyo"

  http_target {
    http_method = "POST"
    uri         = "https://cloudfunctions.googleapis.com/v1/projects/${var.project_id}/locations/${var.region}/functions/switchMaintenanceMode"
    
    oidc_token {
      service_account_email = google_service_account.maintenance_sa.email
    }

    body = base64encode(jsonencode({
      "maintenance_mode": "on"
    }))
  }
}

resource "google_cloud_scheduler_job" "maintenance_end" {
  name     = "maintenance-mode-end"
  schedule = "0 6 * * *"  # 매일 06:00
  time_zone = "Asia/Tokyo"

  http_target {
    http_method = "POST"
    uri         = "https://cloudfunctions.googleapis.com/v1/projects/${var.project_id}/locations/${var.region}/functions/switchMaintenanceMode"
    
    oidc_token {
      service_account_email = google_service_account.maintenance_sa.email
    }

    body = base64encode(jsonencode({
      "maintenance_mode": "off"
    }))
  }
}
  1. Cloud Load Balancer 설정을 수정하여 유지보수 모드를 지원합니다:
modules/loadbalancer/main.tf
resource "google_compute_url_map" "main" {
  name = "main-url-map"

  default_service = google_compute_backend_bucket.main_backend.id

  host_rule {
    hosts        = ["${var.domain}"]
    path_matcher = "main-paths"
  }

  path_matcher {
    name            = "main-paths"
    default_service = google_compute_backend_bucket.main_backend.id

    path_rule {
      paths   = ["/api/*"]
      service = google_compute_backend_service.cloudrun_backend.id
    }
  }

  # 유지보수 모드용 조건부 라우팅
  header_action {
    request_headers_to_remove = ["maintenance-mode"]
    response_headers_to_add {
      header_name  = "X-Maintenance-Mode"
      header_value = "{maintenance_mode}"
      replace      = true
    }
  }
}

# Cloud Armor 보안 정책 수정
resource "google_compute_security_policy" "policy" {
  name = "maintenance-security-policy"

  # 기존 IP 제한 규칙
  rule {
    action   = "allow"
    priority = "1000"
    match {
      versioned_expr = "SRC_IPS_V1"
      config {
        src_ip_ranges = var.allowed_ip_ranges
      }
    }
  }

  # 유지보수 모드 시 모든 트래픽을 sorry 페이지로 리다이렉트
  rule {
    action   = "redirect"
    priority = "900"
    match {
      expr {
        expression = "has(headers.maintenance-mode) && headers.maintenance-mode.contains('on')"
      }
    }
    redirect_options {
      type   = "EXTERNAL_302"
      target = "https://${var.domain}/maintenance.html"
    }
  }
}
  1. 유지보수 모드 전환을 위한 Cloud Function:
modules/maintenance/function/main.py
from google.cloud import storage
import functions_framework

@functions_framework.http
def switch_maintenance_mode(request):
    mode = request.get_json().get('maintenance_mode')
    
    # Load Balancer의 헤더 규칙 업데이트
    # (여기서는 예시로 Cloud Storage의 메타데이터를 사용)
    storage_client = storage.Client()
    bucket = storage_client.bucket('maintenance-page-bucket')
    blob = bucket.blob('maintenance.txt')
    
    if mode == 'on':
        blob.upload_from_string('maintenance')
    else:
        blob.delete()
    
    return {'status': 'success', 'mode': mode}
  1. IAP 설정 유지:
modules/iap/main.tf
resource "google_iap_web_backend_service_iam_binding" "binding" {
  project = var.project_id
  web_backend_service = google_compute_backend_service.cloudrun_backend.name
  role = "roles/iap.httpsResourceAccessor"
  members = var.allowed_members
}

주요 특징:

  1. 유지보수 시간에 자동으로 sorry 페이지로 전환
  2. Cloud Armor를 통한 IP 제한 유지
  3. IAP 인증 유지
  4. Cloud Scheduler를 통한 자동 전환
  5. 기존 인프라 구성 유지

설정 순서:

  1. sorry 페이지를 Cloud Storage에 업로드
  2. Cloud Scheduler로 유지보수 시간 설정
  3. Load Balancer와 Cloud Armor 규칙 수정
  4. Cloud Function 배포

이렇게 설정하면:

  • 평상시: 일반 서비스 제공
  • 유지보수 시간(04:00-06:00): 모든 요청이 sorry 페이지로 리다이렉트
  • IP 제한과 IAP 인증은 계속 유지됨

Discussion