Google Kubernetes Engine(GKE) Autopilot 및 Standard 클러스터를 사용하여 멀티 클러스터 네트워킹으로 마이그레이션

Last reviewed 2022-02-17 UTC

멀티 클러스터 네트워킹은 리전별 고가용성, 낮은 지연 시간을 위해 전 세계적으로 분산된 사용자 인접성, 팀 간 조직 격리와 같은 사용 사례를 지원하는 중요한 도구입니다. Google Kubernetes Engine(GKE)은 GKE 클러스터 Fleet 간에 대규모로 사용 설정하고 사용할 수 있는 멀티 클러스터 네트워킹을 위한 기본 제공 기능을 지원합니다. 또한 이 기능을 통해 GKE Standard와 Autopilot 간에 배포된 인프라를 조합하거나 마이그레이션하여 각 애플리케이션의 아키텍처 요구를 충족시킬 수 있습니다.

이 문서에서는 몇 가지 배포 토폴로지를 통해 이러한 기능을 보여줍니다. 단일 GKE 클러스터에 배포된 애플리케이션을 가져와서 GKE Standard와 Autopilot 클러스터 간 멀티 클러스터 배포로 마이그레이션하는 방법을 알아봅니다. East-West 트래픽에 GKE 멀티 클러스터 서비스를 사용하고 멀티 클러스터 게이트웨이를 사용하여 멀티 클러스터 North-South 네트워킹을 지원합니다.

이 문서는 여러 Kubernetes 클러스터 간 서비스 배포를 위해 GKE를 사용 중이거나 사용할 계획인 클라우드 설계자 및 운영팀을 대상으로 합니다. 이 문서에서는 사용자가 Kubernetes에 익숙하다고 가정합니다.

GKE Standard 및 GKE Autopilot

GKE는 고가용성 제어 영역을 포함하여 전체 특성 세트가 있는 관리형 Kubernetes 배포를 제공합니다. GKE 클러스터는 빠르게 시작하고 최대 15,000개 노드까지 확장할 수 있습니다. GKE Autopilot 클러스터를 사용하면 Google이 제어 영역 및 노드를 포함하여 인프라를 관리합니다. 대신 노드를 구성하고 관리하려는 경우 GKE가 표준 모드를 제공합니다.

모드 간 차이점에 대한 자세한 내용은 클러스터 작업 모드 선택을 참조하세요.

멀티 클러스터 서비스 및 멀티 클러스터 게이트웨이

Kubernetes는 서로 다른 클라우드 영역에서 단일 제어 영역을 사용하여 실행됨으로써 서비스에 복원력과 고가용성을 제공할 수 있습니다. GKE는 이를 한 단계 더 발전시켜서 클러스터 간 서비스 검색 및 호출 메커니즘을 제공하는 GKE 멀티 클러스터 서비스(MCS)를 제공합니다. 이 기능을 사용하는 서비스는 가상 IP를 사용하여 클러스터 간에 검색 및 액세스할 수 있습니다. 이는 클러스터에서 액세스할 수 있는 ClusterIP 서비스의 동작과 일치합니다. 이러한 접근 방법은 다음과 같은 이점을 제공합니다.

  • 서비스는 동일한 리전 또는 다른 리전(East-West 트래픽)의 여러 클러스터에 부하 분산될 수 있습니다.
  • 리전 간 서비스 고가용성 옵션을 지원합니다.
  • 스테이트풀(Stateful) 및 스테이트리스(Stateless) 워크로드를 개별 클러스터 간에 배포하고 관리할 수 있습니다.
  • 공유 서비스를 클러스터 간에 사용할 수 있습니다.

MCS 배포 방법을 자세히 알아보려면 멀티 클러스터 서비스 구성을 참조하세요.

GKE는 GKE 게이트웨이 컨트롤러를 사용하는 Kubernetes Gateway API 구현을 제공합니다. GKE는 게이트웨이를 통해 GKE에 배포된 서비스에 대해 인바운드(North-South) 트래픽 라우팅을 제공하도록 Google Cloud 부하 분산기를 배포할 수 있습니다. GKE는 또한 서로 다른 GKE 클러스터에 배포된 서비스로 트래픽을 라우팅하는 부하 분산기를 프로비저닝할 수 있도록 GKE Gateway Controller를 확장하는 멀티 클러스터 게이트웨이(MCG)를 제공합니다.

다음 다이어그램은 MCS와 MCG를 결합할 때 단일 제어 영역에서 서비스 배포와 트래픽 라우팅의 상호 보완적인 측면을 관리하는 방법을 보여줍니다.

멀티 클러스터 서비스는 클러스터의 서비스 간 통신을 활용하고 멀티 클러스터 게이트웨이는 클러스터 간에 트래픽을 라우팅하도록 부하 분산기를 배포합니다.

자세한 내용은 멀티 클러스터 게이트웨이 배포를 참조하세요.

이전 개요

GKE 멀티 클러스터 네트워킹 기능은 여러 프로필의 워크로드를 활용합니다. 예를 들어 스테이트리스(Stateless) 구성요소의 트래픽 급증을 보다 효율적인 비용 모델인 Autopilot로 이동하길 원할 수 있습니다.

또는 애플리케이션 프런트엔드를 사용자에게 더 가까이 배치해야 할 수 있습니다. 이 접근 방식은 짧은 지연 시간과 캐싱을 제공하며, 이는 애플리케이션 성능과 사용자 환경을 개선합니다. 동시에 애플리케이션에서 사용되고 한 위치에만 있을 수 있는 스테이트풀(Stateful) 구성요소가 있을 수 있습니다. 이 구성을 사용하려면 클라이언트 트래픽을 해당 위치의 올바른 클러스터로 전송하기 위해 North-South 멀티 클러스터 부하 분산이 필요합니다. 또한 스테이트풀(Stateful) 구성요소에 도달하기 위해 클러스터 간에 트래픽을 전송하려면 East-West 멀티 클러스터 부하 분산이 필요합니다.

이 문서에서는 Online Boutique 클라우드 마이크로서비스 데모 애플리케이션을 사용해서 단일 영역 데모의 배포를 향상시키기 위해 사용할 수 있는 멀티 클러스터 패턴을 보여줍니다. 애플리케이션의 단일 영역 버전으로 시작합니다. 그런 후 멀티 클러스터 서비스 및 멀티 클러스터 게이트웨이를 사용하여 고가용성 및 복원력 요소를 추가하고 Autopilot을 활용해서 운영 부담을 줄입니다.

초기 단일 클러스터 배포

다음 다이어그램에서 Online Boutique 애플리케이션은 처음에 std-west라는 단일 GKE Standard 모드 클러스터에 배포되며 LoadBalancer 서비스를 사용하여 노출됩니다.

일반 HTTP 외부 LoadBalancer 서비스를 사용하여 노출된 모든 서비스를 실행하는 단일 Standard 모드 GKE 클러스터입니다.

멀티 클러스터 서비스로 마이그레이션

다음 중간 단계에서는 2개의 추가 클러스터를 만들고 스테이트리스(Stateless) 서비스가 추가 리전에 배포됩니다. 단일 std-west GKE Standard 클러스터와 구분되는 2개의 개별 리전에 auto-eastauto-central이라는 2개의 GKE Autopilot 클러스터를 만들고 클러스터를 Google Cloud Fleet에 등록합니다.

Fleet은 클러스터 및 기타 리소스를 논리적으로 구성하기 위한 Google Cloud 개념으로, 멀티 클러스터 기능을 사용 및 관리하고 시스템 전체에 일관된 정책을 적용할 수 있습니다.

onlineboutique 네임스페이스의 std-west 클러스터에서 ServiceExport를 사용하여 cartservice를 새로운 Fleet 클러스터로 내보냅니다. 세 개의 클러스터 모두에 Online Boutique의 프런트엔드 서비스를 배포하고 ClusterIP 서비스를 통해 노출합니다. 그런 다음 ServiceExports를 사용하여 서비스를 Fleet으로 내보냅니다. Online Boutique의 미들웨어 레이어와 같은 서비스(예: productcatalog, shipping, adservice)도 세 클러스터 모두에 배포됩니다.

Fleet의 모든 클러스터에서 실행되는 Pod는 해당 서비스의 ClusterSet URI에 요청을 전송하여 내보낸 Service에 액세스할 수 있습니다. 요청이 서비스를 지원하는 엔드포인트로 라우팅됩니다.

frontend 서비스는 미들웨어 서비스(예: productcatalogservice 또는 currencyservice)를 같은 클러스터에서 로컬로 소비할 수 있습니다. 이 아키텍처는 프런트엔드가 요청에 응답하는 리전에 대해 수신 요청을 로컬로 유지하고 불필요한 리전 간 네트워크 트래픽 요금이 청구되지 않도록 합니다.

다음 다이어그램은 2개의 멀티 클러스터 서비스를 보여줍니다. 스테이트리스(Stateless) 프런트엔드 서비스는 클러스터 3개에 배포되며 스테이트풀(Stateful) 백엔드 cartservice는 클러스터 1개에 배포됩니다. 이 다이어그램은 또한 중간 단계에서 frontend-external LoadBalancer 서비스에서 생성한 외부 패스 스루 네트워크 부하 분산기를 사용하여 프런트엔드 서비스의 인바운드 트래픽이 us-west1에서 원래의 GKE Standard 클러스터로 계속 라우팅되도록 하는 것을 보여줍니다.

멀티 클러스터 서비스는 3개의 GKE 클러스터에서 실행되지만 트래픽은 일반 HTTP 외부 LoadBalancer 서비스를 사용하여 단일 클러스터로 계속 전달됩니다.

멀티 클러스터 게이트웨이로 마이그레이션

마지막 단계에서는 멀티 클러스터 게이트웨이를 사용하여 frontend 서비스의 인바운드 트래픽을 외부 클라이언트 요청에서 Fleet의 멀티 클러스터 서비스로 라우팅합니다.

이 구성 중에 생성되는 GatewayHTTPRoute 리소스에 대한 구성을 호스팅하고 관리하기 위해 config-central이라는 네 번째 클러스터가 Fleet에 추가됩니다. HTTPRoute 리소스는 / 프리픽스를 프런트엔드 ServiceImport에 매핑합니다. Online Boutique의 프런트엔드 트래픽은 사용 가능한 리전 중 하나의 정상 엔드포인트로 전송됩니다. 이 접근 방법은 Online Boutique 애플리케이션 아키텍처에 고가용성 요소를 추가합니다.

다음 다이어그램에서 멀티 클러스터 게이트웨이는 Fleet의 세 가지 애플리케이션 클러스터 각각에 배포된 스테이트리스(Stateless) 프런트엔드 서비스로 외부 트래픽을 라우팅하는 전역 Cloud 부하 분산기를 배포합니다.

멀티 클러스터 서비스는 세 개의 GKE 클러스터에서 실행되며 이제 멀티 클러스터 외부 게이트웨이를 사용하여 모든 클러스터의 프런트엔드 서비스에 트래픽이 분산됩니다.

최종 상태에서는 이 독자적인 패턴은 애플리케이션의 스테이트풀(Stateful) 부분(cartserviceredis-cart)과 스테이트리스(Stateless) 부분(frontend, emailservice, checkoutservice, recommendationservice, paymentservice, productcatalogservice, currencyservice, shippingservice, and adservice)간의 느슨한 결합을 보여줍니다. 이 문서에서는 다루지 않지만 향후 스테이트풀(Stateful) 서비스 레이어에 복원력과 고가용성을 추가할 수 있습니다.

목표

  • GKE Standard 및 Autopilot 클러스터를 만들고 구성합니다.
  • Online Boutique를 영역 GKE Standard 클러스터에 배포합니다.
  • 멀티 클러스터 Services를 내보냅니다.
  • Standard 및 Autopilot 클러스터에 매니페스트를 배포합니다.
  • 멀티 클러스터 게이트웨이를 사용 설정하고 구성합니다.
  • 멀티 리전 애플리케이션 동작을 테스트합니다.

비용

이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

시작하기 전에

조직에서 정의한 보안 제약조건으로 인해 다음 단계를 완료하지 못할 수 있습니다. 문제 해결 정보는 제한된 Google Cloud 환경에서 애플리케이션 개발을 참조하세요.

시작하기 전에 다음 요구사항이 충족되었는지 확인합니다.

  • 완료 후 프로젝트를 삭제하는 것이 가장 쉬운 방법이므로 이 가이드에서는 새 프로젝트를 사용하는 것이 좋습니다.
  • 이 가이드에서는 Google Cloud 프로젝트에 대해 소유자 IAM 역할이 있다고 가정합니다. 프로덕션 또는 실제 설정의 경우에는 권한 범위를 최소 권한으로 지정하는 것이 가장 좋습니다. 자세한 내용은 IAM을 안전하게 사용ID 및 액세스 관리를 참조하세요.
  • Online Boutique 마이크로서비스 데모 애플리케이션 아키텍처를 숙지합니다.

환경 준비

이 가이드에서는 Cloud Shell을 사용하여 명령어를 입력합니다. Cloud Shell은 Google Cloud 콘솔의 명령줄에 대한 액세스를 제공하고 Google Cloud SDK 및 Google Cloud CLI와 같은 기타 도구를 포함합니다. Cloud Shell은 Google Cloud 콘솔 하단에 창으로 표시됩니다. 초기화되는 데 몇 분 정도 걸릴 수 있지만 창은 즉시 표시됩니다.

  1. Google Cloud 콘솔에서 Cloud Shell을 활성화합니다.

    Cloud Shell 활성화

  2. Cloud Shell에서 이 가이드에 사용된 환경 변수를 정의합니다. PROJECT_ID를 내 프로젝트 ID로 바꿉니다.

    export PROJECT=PROJECT_ID
    gcloud config set project ${PROJECT}
    
  3. 이 문서에 필요한 서비스를 사용 설정합니다.

    gcloud services enable \
        gkehub.googleapis.com \
        multiclusteringress.googleapis.com \
        dns.googleapis.com \
        trafficdirector.googleapis.com \
        cloudresourcemanager.googleapis.com \
        multiclusterservicediscovery.googleapis.com \
        container.googleapis.com
    
    gcloud container fleet multi-cluster-services enable
    

    멀티 클러스터 서비스는 Cloud DNS, 방화벽 규칙, Cloud Service Mesh와 같은 Google Cloud 구성요소를 관리하므로 이러한 API도 사용 설정해야 합니다. 자세한 내용은 Cloud Service Mesh 개요를 참조하세요.

    출력은 다음 예시와 비슷합니다.

    Operation "operations/acf.p2-822685001869-ee4ebe78-6dd8-465e-b0fd-3b0e5f964bad"
    finished successfully.
    
    Waiting for Feature Multi-cluster Services to be created...done.
    
  4. 멀티 클러스터 서비스가 활성 상태인지 확인합니다.

    gcloud container fleet multi-cluster-services describe
    

    출력은 다음 예시와 비슷합니다.

    createTime: '2021-11-30T21:59:25.245190894Z'
    name: projects/PROJECT_ID/locations/global/features/multiclusterservicediscovery
    resourceState:
      state: ACTIVE
    spec: {}
    updateTime: '2021-11-30T21:59:27.459063070Z'
    

    상태 값이 활성이 아닌 경우 MCS 문서의 문제 해결 섹션을 참조하세요.

GKE 클러스터 만들기 및 구성

이 가이드에서는 멀티 클러스터 패턴을 보여주기 위해 3개의 개별 클라우드 리전에서 3개의 애플리케이션 클러스터를 사용하고 1개의 클러스터로 게이트웨이 리소스의 구성을 호스팅합니다. 입니다. 모든 클러스터를 프로젝트와 연결된 Fleet에 등록합니다. Google Cloud 프로젝트에는 연결된 Fleet이 하나만 있을 수 있습니다. 이 프로젝트를 Fleet 호스트 프로젝트라고 합니다.

  1. Standard 및 Autopilot GKE 클러스터를 만듭니다.

    gcloud container clusters create std-west \
        --zone us-west1-a \
        --num-nodes=6 \
        --enable-ip-alias \
        --release-channel regular \
        --workload-pool=${PROJECT}.svc.id.goog \
        --async
    
    gcloud container clusters create-auto auto-east \
        --region us-east1 \
        --release-channel regular \
        --async
    
    gcloud container clusters create-auto auto-central \
        --region us-central1 \
        --release-channel regular \
        --async
    
    gcloud container clusters create config-central \
        --region us-central1 \
        --num-nodes=1 \
        --enable-ip-alias \
        --release-channel regular \
        --workload-pool=${PROJECT}.svc.id.goog \
        --async
    

    GKE용 워크로드 아이덴티티 제휴는 GKE Autopilot 클러스터에서 기본적으로 사용 설정되므로 GKE Standard 클러스터와 마찬가지로 클러스터를 만들 때 --workload-pool 플래그를 사용할 필요가 없습니다.

  2. 클러스터의 상태프로비저닝에서 실행 중으로 변경될 때까지 기다립니다. 이 과정은 최대 10분 정도 걸릴 수 있습니다. 감시 루프를 사용하여 문서의 다음 부분으로 진행하기 전에 커피를 한 잔 마시거나 가벼운 스트레칭을 하면서 진행 상황을 모니터링해도 됩니다.

    watch -n 20 --difference=permanent "gcloud container clusters list"
    

    출력은 다음 예시와 비슷합니다.

    NAME: auto-central
    LOCATION: us-central1
    MASTER_VERSION: 1.21.5-gke.1802
    MASTER_IP: 107.178.213.138
    MACHINE_TYPE: e2-medium
    NODE_VERSION: 1.21.5-gke.1802
    NUM_NODES: 3
    STATUS: PROVISIONING
    
    NAME: config-central
    LOCATION: us-central1
    MASTER_VERSION: 1.21.5-gke.1802
    MASTER_IP:
    MACHINE_TYPE: e2-medium
    NODE_VERSION: 1.21.5-gke.1802
    NUM_NODES: 9
    STATUS: PROVISIONING
    
    NAME: auto-east
    LOCATION: us-east1
    MASTER_VERSION: 1.21.5-gke.1802
    MASTER_IP: 35.229.88.209
    MACHINE_TYPE: e2-medium
    NODE_VERSION: 1.21.5-gke.1802
    NUM_NODES: 3
    STATUS: PROVISIONING
    
    NAME: std-west
    LOCATION: us-west1-a
    MASTER_VERSION: 1.21.5-gke.1802
    MASTER_IP: 35.197.93.113
    MACHINE_TYPE: e2-medium
    NODE_VERSION: 1.21.5-gke.1802
    NUM_NODES: 6
    STATUS: PROVISIONING
    
  3. 모든 클러스터가 실행 상태가 되면 CTRL-C를 눌러 명령어를 중단합니다.

  4. Fleet 호스트 프로젝트 MCS 서비스 계정에 자체 프로젝트의 네트워크 사용자 역할을 부여하는 Identity and Access Management(IAM) 정책 바인딩을 추가합니다.

    gcloud projects add-iam-policy-binding ${PROJECT} \
        --member "serviceAccount:${PROJECT}.svc.id.goog[gke-mcs/gke-mcs-importer]" \
        --role "roles/compute.networkViewer"
    

    GKE용 워크로드 아이덴티티 제휴를 사용하여 MCS 서비스에 프로젝트 VPC 네트워크 구성에 대한 읽기 액세스 권한을 부여합니다. 따라서 Fleet 호스트 프로젝트의 MCS Importer GKE 서비스 계정에 이 역할이 필요합니다.

    출력은 다음 예시와 비슷합니다.

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]
      role: roles/compute.networkViewer
    [...]
    
  5. GKE Standard 및 Autopilot 클러스터를 프로젝트 Fleet에 등록합니다. 자세한 내용은 클러스터 등록을 참조하세요. 이 단계는 최대 5분이 걸릴 수 있습니다.

    gcloud container fleet memberships register std-west \
        --gke-cluster us-west1-a/std-west \
        --enable-workload-identity \
        --project=${PROJECT}
    
    gcloud container fleet memberships register auto-east \
        --gke-cluster us-east1/auto-east \
        --enable-workload-identity \
        --project=${PROJECT}
    
    gcloud container fleet memberships register auto-central \
        --gke-cluster us-central1/auto-central \
        --enable-workload-identity \
        --project=${PROJECT}
    
    gcloud container fleet memberships register config-central \
        --gke-cluster us-central1/config-central \
        --enable-workload-identity \
        --project=${PROJECT}
    

    각 명령어에서 출력은 다음 예시와 비슷합니다.

    Waiting for membership to be created...done.
    Created a new membership [projects/PROJECT_ID/locations/global/memberships/std-west] for the cluster [std-west]
    Generating the Connect Agent manifest...
    Deploying the Connect Agent on cluster [std-west] in namespace [gke-connect]...
    Deployed the Connect Agent on cluster [std-west] in namespace [gke-connect].
    Finished registering the cluster [std-west] with the Hub.
    
  6. 클러스터에 연결하고 kubeconfig 항목을 생성합니다.

    gcloud container clusters get-credentials std-west \
        --zone us-west1-a --project $PROJECT
    
    gcloud container clusters get-credentials auto-east \
        --region us-east1 --project $PROJECT
    
    gcloud container clusters get-credentials auto-central \
        --region us-central1 --project $PROJECT
    
    gcloud container clusters get-credentials config-central \
        --region us-central1 --project $PROJECT
    

    각 명령어에서 출력은 다음 예시와 비슷합니다.

    Fetching cluster endpoint and auth data.
    kubeconfig entry generated for std-west.
    
  7. 이 문서의 나머지 부분에서 쉽게 작업할 수 있도록 클러스터 컨텍스트 이름을 바꿉니다.

    kubectl config rename-context \
        gke_${PROJECT}_us-west1-a_std-west \
        std-west
    
    kubectl config rename-context \
        gke_${PROJECT}_us-east1_auto-east \
        auto-east
    
    kubectl config rename-context \
        gke_${PROJECT}_us-central1_auto-central \
        auto-central
    
    kubectl config rename-context \
        gke_${PROJECT}_us-central1_config-central \
        config-central
    

    이 가이드에서는 해당 위치에 따라 컨텍스트 이름을 지정합니다. 다른 이름을 제공할 수도 있지만 이 가이드의 남은 단계에서 이 단계에 사용된 이름이 사용됩니다.

GKE Standard에 Online Boutique 배포

데모 배포의 첫 번째 단계에서는 전체 Online Boutique 애플리케이션 서비스를 us-west1의 단일 GKE Standard 클러스터 std-west에 배포합니다.

  1. std-west에 네임스페이스 onlineboutique를 만듭니다.

    kubectl create namespace onlineboutique --context std-west
    

    출력은 다음 예시와 비슷합니다.

    namespace/onlineboutique created
    
  2. Online Boutique GitHub 저장소를 클론하고 WORKDIR 변수를 설정합니다.

    cd ~
    
    git clone --branch release/v0.4.1 \
        https://github.com/GoogleCloudPlatform/microservices-demo.git
    
    cd microservices-demo/release && export WORKDIR=`pwd`
    
  3. std-west에 Online Boutique를 배포합니다. 이 프로세스는 모든 Online Boutique의 마이크로서비스에 대해 DeploymentsServices를 만들고 Online Boutique의 프런트엔드 서비스를 외부에 노출하는 LoadBalancer 유형 서비스를 포함합니다.

    cd $WORKDIR
    
    kubectl apply -f kubernetes-manifests.yaml \
        -n onlineboutique --context=std-west
    
  4. LoadBalancer 서비스에 외부 IP가 제공될 때까지 기다립니다.

    watch -n 20 --difference=permanent \
         "kubectl get svc frontend-external -n onlineboutique --context=std-west"
    

    출력은 처음에는 다음 예시와 비슷합니다.

    NAME                TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    frontend-external   LoadBalancer   10.60.5.62   <pending>     80:30359/TCP   43s
    

    Service가 준비되면 EXTERNAL-IP 열에 부하 분산기의 공개 IP 주소가 표시됩니다.

  5. Service가 준비되면 부하 분산기의 외부 IP 주소를 가져와서 curl을 사용하여 프런트엔드가 준비되었는지 확인합니다. 이 curl 명령어가 오류를 반환하면 잠시 기다린 후 다시 시도합니다.

      curl $(kubectl get svc frontend-external \
          -n onlineboutique --context=std-west \
          -o=jsonpath="{.status.loadBalancer.ingress[0].ip}") | \
            grep -e Cluster -e Zone -e Pod
    

    curl 명령어가 성공하면 다음 예시와 비슷한 출력이 표시됩니다.

    <b>Cluster: </b>std-west<br/>
    <b>Zone: </b>us-west1-a<br/>
    <b>Pod: </b>frontend-b7bddcc97-wdjsk
    

이제 us-west1-a에서 Online Boutique의 단일 영역 버전이 실행됩니다. 또한 웹브라우저를 사용해서 frontend-external LoadBalancer 서비스에 할당된 외부 IP로 이동하여 애플리케이션에 액세스하고 동작을 관찰할 수 있습니다. 다음 다이어그램은 이러한 초기 단일 배포를 보여줍니다.

일반 HTTP 외부 LoadBalancer 서비스를 통해 노출된 모든 서비스를 실행하는 단일 Standard 모드 GKE 클러스터입니다.

cartservice를 멀티 클러스터 서비스로 내보내기

이 섹션에서는 애플리케이션에 고가용성 요소를 추가합니다. 백엔드 cartservice를 GKE Autopilot 클러스터에 멀티 클러스터 서비스로 내보냅니다.

  1. 나머지 클러스터에서 네임스페이스 onlineboutique를 만듭니다.

    kubectl create namespace onlineboutique --context auto-east
    
    kubectl create namespace onlineboutique --context auto-central
    
    kubectl create namespace onlineboutique --context config-central
    

    각 명령어에서 출력은 다음 예시와 비슷합니다.

    namespace/onlineboutique created
    
  2. std-west 클러스터에서 ClusterSet의 다른 모든 클러스터로 cartservice를 내보냅니다. ServiceExport 객체는 Fleet에서 onlineboutique 네임스페이스가 제공된 모든 클러스터로 내보내기를 수행하기 위해 cartservice 서비스를 GKE 멀티 클러스터 서비스에 등록합니다. 자세한 내용은 내보내기를 위한 서비스 등록을 참조하세요.

    cat <<EOF>> $WORKDIR/cartservice-export.yaml
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
     namespace: onlineboutique
     name: cartservice
    
    EOF
    
    kubectl apply -f $WORKDIR/cartservice-export.yaml \
        -n onlineboutique --context=std-west
    

멀티 클러스터 패턴에 애플리케이션 매니페스트 적용

이 섹션에서는 멀티 클러스터 패턴 배포를 위해 2개의 선별된 매니페스트를 적용합니다. 이러한 매니페스트에는 std-west 클러스터에 이전에 적용한 kubernetes-manifests.yaml 중 선택한 부분이 포함됩니다.

  • 첫 번째 매니페스트는 프런트엔드 Deployment, Service, ServiceExport에 사용됩니다.
  • 두 번째 매니페스트는 미들웨어 Services(emailservice, checkoutservice, recommendationservice, paymentservice, productcatalogservice, currencyservice, shippingservice, adservice)를 프런트엔드가 실행되는 모든 리전에 배포하기 위해 사용됩니다. 요청을 가능한 한 리전에 로컬로 유지하기 위해 불필요한 리전 간 네트워크 트래픽 부과를 방지합니다.

Fleet의 모든 클러스터에서 실행되는 Pod는 해당 서비스의 ClusterSet URI에 SERVICE_NAME.NAMESPACE.svc.clusterset.local 형식으로 요청을 전송하여 내보낸 Service에 액세스할 수 있습니다. 예를 들어 예시 클러스터 3개 모두에서 프런트엔드 Deploymentscartservice.onlineboutique.svc.clusterset.local에 요청을 실행하여 onlineboutique 네임스페이스의 cartservice를 사용할 수 있습니다

이러한 이유로 각 매니페스트에서 cartservice의 호스트 이름은 ClusterSet URI로 업데이트되었습니다. 매우 중요한 단계입니다. 이 서비스 호스트 이름이 업데이트되지 않으면 프런트엔드 서비스는 kube-dns에 cartservice.onlineboutique.svc.clusterset.local 대신 cartservice를 요청합니다. 이 동작으로 인해 cartservice의 로컬 버전을 사용할 수 없는 클러스터에서 HTTP Status 500 오류가 발생하고 프런트엔드 포드가 비정상 상태가 됩니다.

  1. 매니페스트를 포함하는 GitHub 저장소에 대해 환경 변수를 설정합니다.

    export MANIFEST_REPO_PATH=https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/cluster-migration
    
  2. 매니페스트를 적용하여 3개의 워크로드 클러스터 모두에 프런트엔드 레이어를 배포합니다.

    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-frontend-manifests.yaml \
        -n onlineboutique --context=std-west
    
    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-frontend-manifests.yaml \
        -n onlineboutique --context=auto-east
    
    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-frontend-manifests.yaml \
        -n onlineboutique --context=auto-central
    
  3. 매니페스트를 적용하여 3개의 워크로드 클러스터 모두에 미들웨어 레이어를 배포합니다.

    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-middleware-manifests.yaml \
        -n onlineboutique --context=std-west
    
    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-middleware-manifests.yaml \
        -n onlineboutique --context=auto-east
    
    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-middleware-manifests.yaml \
        -n onlineboutique --context=auto-central
    

이제 std-west, auto-east, auto-central 클러스터에서 활성인 프런트엔드 Deployment, Service, ServiceExport가 있습니다. 또한 각 클러스터에는 로컬에서 실행되는 Online Boutique 미들웨어 서비스가 있습니다. 그러나 다음 다이어그램과 같이 외부 트래픽은 us-west1의 초기 클러스터에서 실행되는 Service로만 라우팅됩니다.

멀티 클러스터 서비스는 3개의 GKE 클러스터에서 실행되지만 트래픽은 일반 HTTP 외부 LoadBalancer 서비스를 사용하여 단일 클러스터로 계속 전달됩니다.

멀티 클러스터 게이트웨이 사용 설정 및 구성

이 섹션에서는 3개 클러스터 모두 프런트엔드 간에 트래픽을 라우팅하고 외부 트래픽을 부하 분산합니다. 이 구성을 얻기 위해 멀티 클러스터 게이트웨이(MCG)를 사용합니다. 이 문서에서는 멀티 클러스터 게이트웨이 사용 설정에 설명된 대로 안내에 따라 MCG를 설정합니다.

이 가이드에서는 config-central 클러스터를 사용하여 게이트웨이 리소스의 구성을 호스팅합니다.

  1. 모든 클러스터가 Fleet에 성공적으로 등록되었는지 확인합니다.

    gcloud container fleet memberships list --project=$PROJECT
    

    다음 출력 예시는 모든 클러스터가 성공적으로 등록된 것을 보여줍니다.

    NAME: auto-central
    EXTERNAL_ID: 21537493-32ea-4a41-990d-02be2c1b319f
    
    NAME: config-central
    EXTERNAL_ID: 4369423e-ea7b-482d-a0eb-93b560e67b98
    
    NAME: std-west
    EXTERNAL_ID: 7fcb048b-c796-476b-9698-001a00f91ab3
    
    NAME: auto-east
    EXTERNAL_ID: aae2d2ff-b861-4a38-bcaf-612f14810012
    
  2. config-central 클러스터에 Gateway API 커스텀 리소스 정의를 설치합니다.

    kubectl --context=config-central kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.5.0" \
        | kubectl apply -f -
    

    이 단계에서는 GatewayClass, Gateway, HTTPRoute 리소스를 포함하여 Gateway API 커스텀 리소스 정의를 설치합니다. 커스텀 리소스 정의는 Kubernetes Network Special Interest Group에서 관리됩니다. 설치된 다음 GKE Gateway Controller를 사용할 수 있습니다.

  3. Fleet에 아직 멀티 클러스터 인그레스를 사용 설정하지 않았으면 지금 사용 설정합니다. 이 기능을 사용 설정하면 멀티 클러스터 게이트웨이 컨트롤러도 사용 설정됩니다.

    gcloud container fleet ingress enable \
        --config-membership=config-central \
        --project=$PROJECT
    
    gcloud container fleet ingress describe --project=$PROJECT
    

    출력은 다음 예시와 비슷합니다.

    createTime: '2021-12-08T23:10:52.505888854Z'
    name: projects/PROJECT_ID/locations/global/features/multiclusteringress
    resourceState:
      state: ACTIVE
    spec:
      multiclusteringress:
        configMembership: projects/zl-mcs-expf61cbd13/locations/global/memberships/config-central
    state:
      state:
        code: OK
        description: Ready to use
        updateTime: '2021-12-08T23:11:37.994971649Z'
    updateTime: '2021-12-08T23:11:38.098244178Z'
    

    상태 값이 활성이 아닌 경우 멀티 클러스터 인그레스 문제 해결 및 작업을 참조하세요.

  4. config-central 클러스터에서 GatewayClasses를 사용할 수 있는지 확인합니다.

    kubectl get gatewayclasses --context=config-central
    

    출력은 다음 예시와 비슷합니다.

    NAME                                  CONTROLLER                  AGE
    gke-l7-global-external-managed        networking.gke.io/gateway   18s
    gke-l7-global-external-managed-mc     networking.gke.io/gateway   19s
    gke-l7-regional-external-managed      networking.gke.io/gateway   18s
    gke-l7-regional-external-managed-mc   networking.gke.io/gateway   19s
    gke-l7-gxlb                           networking.gke.io/gateway   74s
    gke-l7-gxlb-mc                        networking.gke.io/gateway   16s
    gke-l7-rilb                           networking.gke.io/gateway   74s
    gke-l7-rilb-mc                        networking.gke.io/gateway   16s
    

    GatewayClass 리소스는 기능이 서로 다릅니다. 언제 어떤 유형을 사용할지에 대해서는 GatewayClass 기능을 참조하세요.

  5. external-http 게이트웨이 리소스를 config-central에 배포합니다.

    cat <<EOF>> $WORKDIR/external-http-gateway.yaml
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: external-http
      namespace: onlineboutique
    spec:
      gatewayClassName: gke-l7-global-external-managed-mc
      listeners:
      - protocol: HTTP
        port: 80
        name: http
    EOF
    
    kubectl apply -f external-http-gateway.yaml \
        -n onlineboutique --context=config-central
    

    gatewayClassName 필드에 표시된 것처럼 이 리소스는 레이어 7 외부 Cloud Load Balancing을 관리하고 멀티 클러스터 애플리케이션을 노출하는 GatewayClass gke-l7-global-external-managed-mc의 리소스입니다.

  6. config-centralpublic-frontend-route라는 HTTPRoute를 배포합니다.

    cat <<EOF>> $WORKDIR/public-frontend-route.yaml
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: public-frontend-route
      namespace: onlineboutique
    spec:
      parentRefs:
      - name: "external-http"
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /
        backendRefs:
        - name: frontend
          group: net.gke.io
          kind: ServiceImport
          port: 80
    EOF
    
    kubectl apply -f public-frontend-route.yaml \
        -n onlineboutique --context=config-central
    

    HTTPRoute 리소스 배포 시 외부 레이어 7 Cloud Load Balancing 리소스를 만들고 std-west, auto-east, auto-central 클러스터에서 실행되는 프런트엔드 서비스에서 지원되는 프런트엔드 ServiceImport를 노출합니다.

    다음 다이어그램은 멀티 클러스터 게이트웨이가 배포된 후 3개의 애플리케이션 클러스터 중 하나의 프런트엔드 멀티 클러스터 서비스로 트래픽을 라우팅하는 방법을 보여줍니다.

    멀티 클러스터 서비스는 세 개의 GKE 클러스터에서 실행되며 이제 멀티 클러스터 외부 게이트웨이를 사용하여 모든 클러스터의 프런트엔드 서비스에 트래픽이 분산됩니다.

  7. 다음 단계로 진행하기 전 부하 분산기에 프로비저닝된 외부 IP 주소가 준비될 때까지 기다립니다. IP 주소가 할당되려면 최대 10분까지 걸릴 수 있습니다. 감시 루프를 사용하여 진행 상태를 모니터링할 수 있습니다. 부하 분산기 이름은 gkemcg-onlineboutique-external-http-k09mfhk74gop와 같은 패턴으로 지정됩니다.

    watch -n 20 --difference=permanent \
        "gcloud compute forwarding-rules list \
            | grep -A 5 NAME..*external-http"
    

    출력은 다음 예시와 비슷합니다.

    NAME: gkemcg-onlineboutique-external-http-k09mfhk74gop
    REGION:
    IP_ADDRESS: 34.149.29.176
    IP_PROTOCOL: TCP
    TARGET: gkemcg-onlineboutique-external-http-k09mfhk74gop
    
  8. 부하 분산기가 준비되면 Cloud Shell에서 다음 명령어를 실행하여 external-http-gateway.yamlpublic-frontend-route.yaml 메니페스트의 애플리케이션을 통해 생성된 부하 분산기의 외부 IP 주소를 내보냅니다.

    export EXTERNAL_LB_IP=$(kubectl --context=config-central \
                                -n onlineboutique get gateway external-http \
                                -o=jsonpath='{.status.addresses[0].value}')
    
  9. 적절한 헤더를 사용해서 부하 분산기로 요청을 전송하면 프런트엔드 서비스로 처리된 HTML 콘텐츠가 반환됩니다. 예를 들어 store.example.com 호스트 이름을 프런트엔드 ServiceImport로 매핑하도록 HTTPRoute 리소스를 구성했으므로, HTTP 요청을 수행할 때 HOST 헤더를 지정해야 합니다. 다음 curl 예시가 오류를 반환하면 몇 분 정도 기다린 후 다시 시도합니다.

    curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
        grep -e Cluster -e Zone -e Pod
    

    curl 명령어가 성공하면 다음 예시와 비슷한 출력이 표시됩니다.

    <b>Cluster: </b>auto-central<br/>
    <b>Zone: </b>us-central1-f<br/>
    <b>Pod: </b>frontend-7c7d596ddc-jdh8f
    

애플리케이션 멀티 리전 라우팅 동작 테스트

멀티 클러스터 서비스와 멀티 클러스터 게이트웨이를 사용하여 얻을 수 있는 강력한 특성 중 하나는 외부 요청이 지리적으로 가장 가까운 클러스터로 라우팅된다는 것입니다.

애플리케이션 멀티 리전 동작을 테스트하려면 클러스터가 배포된 여러 리전에서 시작되는 트래픽을 생성합니다. 각 제공 클러스터(std-west, auto-east, auto-central)에 하나씩 3개의 작은 포드를 만듭니다. 이를 사용해서 HTTP 요청을 부하 분산기 엔드포인트로 전송할 수 있습니다. 결과를 통해 응답하는 프런트엔드 Pod를 확인할 수 있습니다.

  1. 클라이언트 포드를 만듭니다.

    kubectl run --context=std-west \
                --image=radial/busyboxplus:curl client-west \
                -- sh -c 'while sleep 3600; do :; done'
    
    kubectl run --context=auto-east \
                --image=radial/busyboxplus:curl client-east \
                -- sh -c 'while sleep 3600; do :; done'
    
    kubectl run --context=auto-central \
                --image=radial/busyboxplus:curl client-central \
                -- sh -c 'while sleep 3600; do :; done'
    
  2. 포드가 실행되면 curl 명령어를 사용하여 std-west 클러스터의 Pod 클라이언트에서 부하 분산기 엔드포인트로 요청을 보내고 응답을 검토합니다.

    kubectl exec -it --context=std-west client-west \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
               grep -e Cluster -e Zone -e Pod
    

    curl 명령어가 성공하면 다음 예시와 비슷한 출력이 표시됩니다.

    <b>Cluster: </b>std-west<br/>
    <b>Zone: </b>us-west1-a<br/>
    <b>Pod: </b>frontend-7cf48b79cf-trzc4
    
  3. auto-east 클러스터의 클라이언트 Pod에서 동일한 curl 요청을 실행하고 응답을 확인합니다.

    kubectl exec -it --context=auto-east client-east \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
               grep -e Cluster -e Zone -e Pod
    

    curl 명령어가 성공하면 다음 예시와 비슷한 출력이 표시됩니다.

    <b>Cluster: </b>auto-east<br/>
    <b>Zone: </b>us-east1-d<br/>
    <b>Pod: </b>frontend-6784b6df98-scdws
    

    Autopilot 클러스터이므로, Pod 예약을 위해 클러스터가 추가 리소스를 프로비저닝해야 할 수 있습니다. 다음 예시와 비슷한 출력이 표시되면 잠시 기다린 후 다시 시도합니다.

     Error from server (BadRequest): pod client-east does not have a host assigned
    
  4. auto-central 클러스터의 클라이언트 Pod에서 curl을 실행하고 응답을 확인합니다.

    kubectl exec -it --context=auto-central client-central \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
            grep -e Cluster -e Zone -e Pod
    

    curl 명령어가 성공하면 다음 예시와 비슷한 출력이 표시됩니다.

    <b>Cluster: </b>auto-central<br/>
    <b>Zone: </b>us-central1-b<br/>
    <b>Pod: </b>frontend-6784b6df98-x2fv4
    

    이러한 결과는 트래픽이 요청 원본과 가장 가까운 위치의 해당 포드로 라우팅되는지 확인합니다.

애플리케이션 멀티 리전 복원력 테스트

효율적인 트래픽 라우팅 외에도 여러 리전에서 서비스를 실행하면 드물지만 발생할 수도 있는 인프라 오류시 복원력을 제공합니다.

특정 클러스터에서 프런트엔드 Deployments를 삭제하여 동작을 테스트한 후 해당 리전의 클라이언트 Pod에서 curl 명령어를 재시도합니다. 애플리케이션을 계속 사용할 수 있는지 확인하고, 요청에 응답하는 Pod 위치를 확인합니다.

  1. std-west 클러스터의 client-west Pod에서 curl 명령어를 실행하고 결과가 us-west1의 프런트엔드에서 제공되는지 확인합니다.

    kubectl exec -it --context=std-west client-west \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP  | \
               grep -e Cluster -e Zone -e Pod
    

    curl 명령어가 성공하면 다음 예시와 비슷한 출력이 표시됩니다.

    <b>Cluster: </b>std-west<br/>
    <b>Zone: </b>us-west1-a<br/>
    <b>Pod: </b>frontend-7cf48b79cf-trzc4
    
  2. std-west 클러스터에서 프런트엔드 Deployment를 삭제합니다.

    kubectl delete deploy frontend \
        -n onlineboutique --context=std-west
    

    출력은 다음 예시와 비슷합니다.

    deployment.apps "frontend" deleted
    
  3. std-west 클러스터의 client-west Pod에서 다른 요청을 전송합니다. auto-east 또는 auto-central 클러스터에 있는 남은 프런트엔드 Deployments 중 하나에서 응답이 표시됩니다.

    kubectl exec -it --context=std-west client-west \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
               grep -e Cluster -e Zone -e Pod
    

    다음 예시와 비슷한 출력에 이 요청에 응답하는 정상 Pod 위치가 표시됩니다.

    <b>Cluster: </b>auto-central<br/>
    <b>Zone: </b>us-central1-b<br/>
    <b>Pod: </b>frontend-6784b6df98-x2fv4
    

    또는

    <b>Cluster: </b>auto-east<br/>
    <b>Zone: </b>us-east1-d<br/>
    <b>Pod: </b>frontend-6784b6df98-scdws
    

    명령어를 여러 번 실행하여 교대 결과를 확인합니다.

이 데모 배포에서는 멀티 클러스터 서비스 및 멀티 클러스터 게이트웨이를 사용하여 Online Boutique 애플리케이션에 복원력 및 지리적 분포 요소를 추가했습니다. 요청이 가장 가까운 지리적 리전으로 라우팅되고, 리전의 프런트엔드 또는 미들웨어 서비스에 문제가 있더라도 최종 사용자가 애플리케이션을 계속 성공적으로 사용할 수 있습니다.

삭제

이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.

    리소스 관리로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.

다음 단계