여러 리전의 트래픽 제공

여러 리전에 서비스를 배포하고 사용자를 가장 가까운 리전으로 라우팅하면 전 세계 사용자에게 더 빠르게 응답을 반환할 수 있습니다. 여러 리전에 배포하면 리전 서비스 중단 시 지연 시간이 짧아지고 가용성이 높아집니다.

Cloud Run 서비스는 개별 리전에 배포되므로 여러 리전에 서비스를 배포한 후 서비스에 글로벌 부하 분산을 구성해야 합니다.

여러 리전에 서비스 배포

다음 방법 중 하나를 사용하여 동일한 서비스를 여러 리전에 배포할 수 있습니다.

멀티 리전 서비스 배포

이 섹션에서는 단일 gcloud CLI 명령어로 멀티 리전 서비스를 배포하고 구성하는 방법을 보여줍니다.

  • 멀티 리전 서비스를 만들고 배포하려면 --regions 플래그를 사용하여 gcloud beta run deploy 명령어를 실행합니다.

    gcloud beta run deploy SERVICE_NAME \
      --image=IMAGE_URL \
      --regions=REGIONS

    다음을 바꿉니다.

    • SERVICE_NAME: 배포하려는 멀티 리전 서비스의 이름입니다.
    • IMAGE_URL: 컨테이너 이미지에 대한 참조(예: us-docker.pkg.dev/cloudrun/container/hello:latest)입니다.
    • REGIONS: 배포할 여러 리전의 목록입니다. 예를 들면 us-central1,asia-east1입니다.

멀티 리전 서비스 업데이트

Cloud Run 서비스를 업데이트하는 데 사용하는 것과 동일한 설정을 사용하여 gcloud beta run multi-region services 명령어를 실행하면 멀티 리전 Cloud Run 서비스를 업데이트할 수 있습니다. 멀티 리전 서비스에서 리전을 추가하거나 삭제하려면 gcloud beta run multi-region-services update 명령어를 실행합니다.

  • 멀티 리전 서비스를 하나 이상의 리전에 더 추가하려면 --add-regions 플래그를 사용합니다.

    gcloud beta run multi-region-services update SERVICE_NAME \
      --add-regions=REGIONS
  • 하나 이상의 리전에서 멀티 리전 서비스를 삭제하려면 --remove-regions 플래그를 사용합니다.

    gcloud beta run multi-region-services update SERVICE_NAME \
      --remove-regions=REGIONS

    다음을 바꿉니다.

  • SERVICE_NAME: 업데이트하려는 멀티 리전 서비스의 이름입니다.

  • REGIONS: 서비스를 추가하거나 삭제할 하나 이상의 리전입니다. 예를 들면 us-central1,asia-east1입니다.

멀티 리전 서비스 삭제

  • 멀티 리전 서비스를 삭제하려면 gcloud beta run multi-region-services delete 명령어를 실행합니다.

    gcloud beta run multi-region-services delete SERVICE_NAME

    SERVICE_NAME을 삭제하려는 멀티 리전 서비스의 이름으로 바꿉니다.

전역 부하 분산 구성

이 섹션에서는 외부 애플리케이션 부하 분산기를 전역 Anycast IP 주소(서비스를 배포하는 가장 가까운 Google 데이터 센터로 사용자를 라우팅함)를 가리키면서 관리형 TLS 인증서를 사용하여 보호되는 도메인과 함께 구성하는 방법을 보여줍니다.

이 섹션에서 설명하는 아키텍처는 리전 Cloud Run 서비스가 응답하지 않거나 오류를 반환하기 시작할 때 요청을 다른 리전으로 자동 라우팅하지 않습니다. 멀티 리전 서비스의 가용성을 높이려면 이상점 감지를 구성하여 HTTP 오류율을 기준으로 비정상 Cloud Run 서비스를 식별하고 일부 요청을 다른 리전으로 우회할 수 있습니다.

부하 분산기 만들기

외부 부하 분산기를 만들려면 여러 네트워킹 리소스를 만들고 이를 함께 연결해야 합니다.

gcloud CLI

  1. 부하 분산기를 다시 만들 때 DNS 레코드를 업데이트할 필요가 없도록 고정 IP 주소를 예약합니다.
    gcloud compute addresses create --global SERVICE_IP
    위 명령어에서 SERVICE_IP를 IP 주소 리소스의 이름으로 바꿉니다(예: myservice-ip).

    이 IP 주소는 Google 데이터 센터 또는 방문자와 가장 가까운 접속 지점으로 라우팅하는 전역 Anycast IPv4 주소입니다.

  2. 백엔드 서비스를 만듭니다.
    gcloud compute backend-services create --global BACKEND_NAME

    위 명령어에서 BACKEND_NAME를 백엔드 서비스에 지정할 이름으로 바꿉니다(예: myservice-backend).

  3. URL 맵을 만듭니다.
    gcloud compute url-maps create URLMAP_NAME --default-service=BACKEND_NAME

    URLMAP_NAME을 URL 맵에 지정할 이름으로 바꿉니다(예: myservice-urlmap).

  4. 도메인에서 HTTPS 트래픽을 제공하도록 관리형 TLS 인증서를 만듭니다. example.com을 도메인 이름으로 바꿉니다.
    gcloud compute ssl-certificates create CERT_NAME \
      --domains=example.com

    CERT_NAME을 관리형 SSL 인증서에 사용할 이름으로 바꿉니다(예: myservice-cert).

  5. 대상 HTTPS 프록시를 만듭니다.
    gcloud compute target-https-proxies create HTTPS_PROXY_NAME \
      --ssl-certificates=CERT_NAME \
      --url-map=URLMAP_NAME

    HTTPS_PROXY_NAME을 대상 HTTPS 프록시에 지정할 이름으로 바꿉니다(예: myservice-https).

  6. 생성한 네트워킹 리소스를 IP 주소에 연결하는 전달 규칙을 만듭니다.
    gcloud compute forwarding-rules create --global FORWARDING_RULE_NAME \
      --target-https-proxy=HTTPS_PROXY_NAME \
      --address=SERVICE_IP \
      --ports=443

    FORWARDING_RULE_NAME을 만들려는 전달 규칙 리소스의 이름으로 바꿉니다(예: myservice-lb).

Terraform

이 섹션에 설명된 단계 대신 전역 HTTP 부하 분산기 Terraform 모듈을 사용할 수 있습니다.

Terraform 파일에 다음을 추가합니다(예: main.tf).

  1. IP 주소를 구성:

    resource "google_compute_global_address" "lb_default" {
      provider = google-beta
      name     = "myservice-service-ip"
    
      # Use an explicit depends_on clause to wait until API is enabled
      depends_on = [
        google_project_service.compute_api
      ]
    }
    output "load_balancer_ip_addr" {
      value = google_compute_global_address.lb_default.address
    }

    IP 주소 리소스 이름을 myservice-service-ip로 구성합니다. 이 값을 자신에게 해당하는 값으로 변경할 수 있습니다. 이 IP 주소는 Google 데이터 센터 또는 방문자와 가장 가까운 접속 지점으로 라우팅하는 전역 Anycast IPv4 주소입니다.

  2. 백엔드 서비스를 만들고 구성합니다.

    resource "google_compute_backend_service" "lb_default" {
      provider              = google-beta
      name                  = "myservice-backend"
      load_balancing_scheme = "EXTERNAL_MANAGED"
    
      backend {
        group = google_compute_region_network_endpoint_group.lb_default[0].id
      }
    
      backend {
        group = google_compute_region_network_endpoint_group.lb_default[1].id
      }
    
      # Use an explicit depends_on clause to wait until API is enabled
      depends_on = [
        google_project_service.compute_api,
      ]
    }

    이 리소스는 백엔드 서비스의 이름을 myservice-backend로 구성합니다. 이 값을 자신에게 해당하는 값으로 변경할 수 있습니다.

  3. URL 맵 구성:

    resource "google_compute_url_map" "lb_default" {
      provider        = google-beta
      name            = "myservice-lb-urlmap"
      default_service = google_compute_backend_service.lb_default.id
    
      path_matcher {
        name            = "allpaths"
        default_service = google_compute_backend_service.lb_default.id
        route_rules {
          priority = 1
          url_redirect {
            https_redirect         = true
            redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
          }
        }
      }
    }

    백엔드 서비스 리소스(myservice-backend)를 새 URL 맵 리소스(myservice-lb-urlmap)에 연결합니다. 이 값을 자신에게 해당하는 값으로 변경할 수 있습니다.

  4. 도메인에서 HTTPS 트래픽을 제공할 수 있도록 관리형 TLS 인증서를 만듭니다. example.comgoogle_compute_managed_ssl_certificate 리소스의 도메인 이름으로 바꿉니다.

    resource "google_compute_managed_ssl_certificate" "lb_default" {
      provider = google-beta
      name     = "myservice-ssl-cert"
    
      managed {
        domains = ["example.com"]
      }
    }
  5. HTTPS 프록시를 구성합니다.

    resource "google_compute_target_https_proxy" "lb_default" {
      provider = google-beta
      name     = "myservice-https-proxy"
      url_map  = google_compute_url_map.lb_default.id
      ssl_certificates = [
        google_compute_managed_ssl_certificate.lb_default.name
      ]
      depends_on = [
        google_compute_managed_ssl_certificate.lb_default
      ]
    }

    대상 이름이 myservice-https-proxygoogle_compute_target_https_proxy 리소스를 만들고 이전에 만든 TLS 인증서(myservice-ssl-cert) 및 URL 매핑 리소스(myservice-lb-urlmap)를 연결합니다. 이 값을 자신에게 해당하는 값으로 변경할 수 있습니다.

  6. 전달 규칙을 구성합니다.

    resource "google_compute_global_forwarding_rule" "lb_default" {
      provider              = google-beta
      name                  = "myservice-lb-fr"
      load_balancing_scheme = "EXTERNAL_MANAGED"
      target                = google_compute_target_https_proxy.lb_default.id
      ip_address            = google_compute_global_address.lb_default.id
      port_range            = "443"
      depends_on            = [google_compute_target_https_proxy.lb_default]
    }

    대상 이름이 myservice-https-proxygoogle_compute_global_forwarding_rule 리소스를 만들고 이전에 만든 HTTPS 프록시 대상(myservice-https-proxy) 및 IP 주소 리소스(myservice-service-ip)를 연결합니다. 이 값을 자신에게 해당하는 값으로 변경할 수 있습니다.

  7. 다음 구성을 적용합니다.

    Google Cloud 프로젝트에 Terraform 구성을 적용하려면 다음 섹션의 단계를 완료하세요.

    Cloud Shell 준비

    1. Cloud Shell을 실행합니다.
    2. Terraform 구성을 적용할 기본 Google Cloud 프로젝트를 설정합니다.

      이 명령어는 프로젝트당 한 번만 실행하면 되며 어떤 디렉터리에서도 실행할 수 있습니다.

      export GOOGLE_CLOUD_PROJECT=PROJECT_ID

      Terraform 구성 파일에서 명시적 값을 설정하면 환경 변수가 재정의됩니다.

    디렉터리 준비

    각 Terraform 구성 파일에는 자체 디렉터리(루트 모듈이라고도 함)가 있어야 합니다.

    1. Cloud Shell에서 디렉터리를 만들고 해당 디렉터리 내에 새 파일을 만드세요. 파일 이름에는 .tf 확장자가 있어야 합니다(예: main.tf). 이 튜토리얼에서는 파일을 main.tf라고 합니다.
      mkdir DIRECTORY && cd DIRECTORY && touch main.tf
    2. 튜토리얼을 따라 하는 경우 각 섹션이나 단계에서 샘플 코드를 복사할 수 있습니다.

      샘플 코드를 새로 만든 main.tf에 복사합니다.

      필요한 경우 GitHub에서 코드를 복사합니다. 이는 Terraform 스니펫이 엔드 투 엔드 솔루션의 일부인 경우에 권장됩니다.

    3. 환경에 적용할 샘플 매개변수를 검토하고 수정합니다.
    4. 변경사항을 저장합니다.
    5. Terraform을 초기화합니다. 이 작업은 디렉터리당 한 번만 수행하면 됩니다.
      terraform init

      원하는 경우 최신 Google 공급업체 버전을 사용하려면 -upgrade 옵션을 포함합니다.

      terraform init -upgrade

    변경사항 적용

    1. 구성을 검토하고 Terraform에서 만들거나 업데이트할 리소스가 예상과 일치하는지 확인합니다.
      terraform plan

      필요에 따라 구성을 수정합니다.

    2. 다음 명령어를 실행하고 프롬프트에 yes를 입력하여 Terraform 구성을 적용합니다.
      terraform apply

      Terraform에 '적용 완료' 메시지가 표시될 때까지 기다립니다.

    3. 결과를 보려면 Google Cloud 프로젝트를 엽니다. Google Cloud 콘솔에서 UI의 리소스로 이동하여 Terraform이 리소스를 만들었거나 업데이트했는지 확인합니다.

리전별 네트워크 엔드포인트 그룹 구성

이전 단계에서 배포한 각 리전에 대해 다음 안내에 따라 서버리스 네트워크 엔드포인트 그룹(NEG)을 만들고 백엔드 서비스에 추가해야 합니다.

gcloud CLI

  1. REGION에서 Cloud Run 서비스의 네트워크 엔드포인트 그룹을 만듭니다.

    gcloud compute network-endpoint-groups create NEG_NAME \
      --region=REGION \
      --network-endpoint-type=SERVERLESS \
      --cloud-run-service=SERVICE_NAME

    다음을 바꿉니다.

    • NEG_NAME을 네트워크 엔드포인트 그룹 리소스의 이름으로 바꿉니다 (예: `myservice-neg-uscentral1`)
    • REGION을 서비스가 배포된 [region][loc]로 바꿉니다.
    • SERVICE_NAME를 서비스 이름으로 바꿉니다.
  2. 백엔드 서비스에 네트워크 엔드포인트 그룹을 추가합니다.

    gcloud compute backend-services add-backend --global BACKEND_NAME \
      --network-endpoint-group-region=REGION \
      --network-endpoint-group=NEG_NAME

    이전 단계에서 만든 리전의 NEG_NAME을 지정합니다.

  3. 각 리전에 대해 위 단계를 반복합니다.

Terraform

  1. run_regions 변수에 지정된 각 리전마다 Cloud Run 서비스에 대한 이름이 myservice-neg인 네트워크 엔드포인트 그룹을 구성합니다.

    resource "google_compute_region_network_endpoint_group" "lb_default" {
      provider              = google-beta
      count                 = length(local.run_regions)
      name                  = "myservice-neg"
      network_endpoint_type = "SERVERLESS"
      region                = local.run_regions[count.index]
      cloud_run {
        service = google_cloud_run_v2_service.run_default[count.index].name
      }
    }
  2. 네트워크 엔드포인트 그룹(myservice-neg)을 연결하도록 백엔드 서비스를 구성합니다.

    resource "google_compute_backend_service" "lb_default" {
      provider              = google-beta
      name                  = "myservice-backend"
      load_balancing_scheme = "EXTERNAL_MANAGED"
    
      backend {
        group = google_compute_region_network_endpoint_group.lb_default[0].id
      }
    
      backend {
        group = google_compute_region_network_endpoint_group.lb_default[1].id
      }
    
      # Use an explicit depends_on clause to wait until API is enabled
      depends_on = [
        google_project_service.compute_api,
      ]
    }

도메인에 DNS 레코드 구성

도메인 이름이 앞에서 만든 전달 규칙을 가리키도록 하려면 앞에서 만든 IP 주소를 사용하여 DNS 레코드를 업데이트해야 합니다.

  1. 다음 명령어를 실행하여 부하 분산기의 예약된 IP 주소를 찾습니다.

    gcloud compute addresses describe \
      --global SERVICE_IP \
      --format='value(address)'

    SERVICE_IP를 이전에 만든 IP 주소의 이름으로 바꿉니다. 이 명령어는 IP 주소를 출력에 인쇄합니다.

  2. 이 IP 주소로 A 레코드를 추가하여 도메인의 DNS 레코드를 업데이트합니다.

인증된 서비스를 사용하는 경우 커스텀 대상 구성

인증된 서비스는 IAM으로 보호됩니다. 이러한 Cloud Run 서비스에는 사용자 인증 정보 생성 시 요청의 의도된 수신자(대상)를 선언하는 클라이언트 인증이 필요합니다.

대상은 일반적으로 타겟 서비스의 전체 URL이며, 기본적으로 Cloud Run 서비스의 경우 run.app으로 끝나는 생성 URL입니다. 하지만 멀티 리전 배포에서는 클라이언트가 요청이 라우팅될 리전 서비스를 미리 알 수 없습니다. 따라서 멀티 리전 배포의 경우 커스텀 대상을 사용하도록 서비스를 구성합니다.

부하 분산기 프로비저닝 대기

부하 분산기 IP 주소로 도메인을 구성한 후 DNS 레코드가 적용될 때까지 기다려야 합니다. 마찬가지로 도메인에서 관리형 TLS 인증서가 발급될 때까지 기다린 후 HTTPS 트래픽을 전역적으로 제공할 준비를 해야 합니다.

부하 분산기가 트래픽을 제공하기까지 데 최대 30분이 걸릴 수 있습니다.

준비가 되면 https:// 프리픽스가 있는 웹사이트의 URL을 방문하여 직접 사용해 보세요.

상태 확인

  1. DNS 레코드 전파의 상태를 확인하려면 dig 명령줄 유틸리티를 사용합니다.

    dig A +short example.com

    출력에 DNS 레코드에서 구성한 IP 주소가 표시됩니다.

  2. 다음 명령어를 실행하여 관리형 인증서 발급 상태를 확인합니다.

    gcloud compute ssl-certificates describe CERT_NAME

    CERT_NAME을 이전에 SSL 인증서 리소스에 대해 선택한 이름으로 바꿉니다.

    출력에 status: ACTIVE가 포함된 줄이 표시됩니다.

HTTP에서 HTTPS로 리디렉션 설정

기본적으로 전달 규칙은 단일 프로토콜만 처리하므로 http:// 엔드포인트에 대한 요청은 '404 Not Found'로 응답합니다. http:// URL에 대한 요청을 https:// 프로토콜로 리디렉션해야 하는 경우 다음 안내에 따라 추가 URL 맵 및 전달 규칙을 만들어야 합니다.

gcloud CLI

  1. 리디렉션 규칙을 사용하여 URL 맵을 만듭니다.

    gcloud compute url-maps import HTTP_URLMAP_NAME \
      --global \
      --source /dev/stdin <<EOF
            name: HTTP_URLMAP_NAME
            defaultUrlRedirect:
              redirectResponseCode: MOVED_PERMANENTLY_DEFAULT
              httpsRedirect: True
            EOF

    HTTP_URLMAP_NAME을 만들려는 URL 맵 리소스의 이름으로 바꿉니다(예: myservice-httpredirect).

  2. URL 맵을 사용하여 대상 HTTP 프록시를 만듭니다.

    gcloud compute target-http-proxies create HTTP_PROXY_NAME \
      --url-map=HTTP_URLMAP_NAME

    HTTP_PROXY_NAME을 만들려는 대상 HTTP 프록시의 이름으로 바꿉니다(예: myservice-http).

  3. 포트 80에 예약된 IP 주소가 동일한 전달 규칙을 만듭니다.

    gcloud compute forwarding-rules create --global HTTP_FORWARDING_RULE_NAME \
      --target-http-proxy=HTTP_PROXY_NAME \
      --address=SERVICE_IP \
      --ports=80
            

    HTTP_FORWARDING_RULE_NAME을 만들려는 새 전달 규칙의 이름으로 바꿉니다(예: myservice-httplb).

Terraform

  1. 리디렉션 규칙을 사용하여 URL 맵 리소스를 만듭니다.

    resource "google_compute_url_map" "https_default" {
      provider = google-beta
      name     = "myservice-https-urlmap"
    
      default_url_redirect {
        redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
        https_redirect         = true
        strip_query            = false
      }
    }
  2. 새로 만든 URL 맵 리소스(myservice-https-urlmap)로 대상 HTTP 프록시를 만듭니다.

    resource "google_compute_target_http_proxy" "https_default" {
      provider = google-beta
      name     = "myservice-http-proxy"
      url_map  = google_compute_url_map.https_default.id
    
      depends_on = [
        google_compute_url_map.https_default
      ]
    }
  3. 포트 80에 예약된 IP 주소 리소스(myservice-http-proxy)가 동일한 전달 규칙을 만듭니다.

    resource "google_compute_global_forwarding_rule" "https_default" {
      provider   = google-beta
      name       = "myservice-https-fr"
      target     = google_compute_target_http_proxy.https_default.id
      ip_address = google_compute_global_address.lb_default.id
      port_range = "80"
      depends_on = [google_compute_target_http_proxy.https_default]
    }

멀티 리전 배포에서 인증된 Pub/Sub 푸시 구독 사용

기본적으로 Pub/Sub 서비스는 Pub/Sub 서비스가 메시지를 저장하는 위치와 동일한 Google Cloud 리전의 푸시 엔드포인트에 메시지를 전달합니다. 이 동작에 대한 해결 방법은 멀티 리전 Cloud Run 배포에 인증된 Pub/Sub 푸시 구독 사용을 참조하세요.