Cloud Service Mesh 예시: 카나리아 배포


이 튜토리얼에서는 Cloud Service Mesh로 카나리아 배포를 출시하는 일반 사용 사례를 살펴봅니다.

카나리아 배포란 무엇인가요?

카나리아 배포는 트래픽 중 작은 일부만 새 버전의 마이크로서비스에 라우팅하고 전체 사용자 기반으로 출시를 점진적으로 진행하면서 이전 버전을 단계별로 줄이고 폐기하는 방법입니다. 이 프로세스 중 문제가 발생하면 트래픽을 이전 버전으로 다시 전환할 수 있습니다. Cloud Service Mesh에서는 트래픽을 라우팅하여 새 서비스가 안전하게 도입되는지 확인할 수 있습니다.

비용

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

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

이 튜토리얼을 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않도록 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

Online Boutique 배포

  1. kubectl의 현재 컨텍스트를, Online Boutique를 배포한 클러스터로 설정합니다.

    gcloud container clusters get-credentials CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  2. 샘플 애플리케이션과 인그레스 게이트웨이에 대해 네임스페이스를 만듭니다.

    kubectl create namespace onlineboutique
    
  3. Envoy 프록시를 자동으로 주입하도록 onlineboutique 네임스페이스에 라벨을 지정합니다. 자동 사이드카 주입 사용 설정 방법의 단계를 따릅니다.

  4. 샘플 앱을 배포합니다. 이 튜토리얼에서는 마이크로서비스 데모 앱인 Online Boutique를 배포합니다.

    kubectl apply \
    -n onlineboutique \
    -f https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/shared/online-boutique/kubernetes-manifests.yaml
    
  5. 다음 명령어를 실행하여 productcatalog 배포에 version=v1 라벨을 추가합니다.

    kubectl patch deployments/productcatalogservice -p '{"spec":{"template":{"metadata":{"labels":{"version":"v1"}}}}}' \
    -n onlineboutique
    

    배포한 서비스를 확인합니다.

    kubectl get pods -n onlineboutique
    

    예상 출력:

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-m84m6               2/2     Running   0          2m7s
    cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
    checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
    currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
    emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
    frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
    loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
    paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
    productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
    recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
    redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
    shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
    

    애플리케이션의 모든 포드가 작동되고 READY 열의 2/2를 사용해서 실행됩니다. 이것은 포드에 Envoy 사이드카 프록시가 성공적으로 주입된 것을 나타냅니다.

  6. productcatalog의 v1에 대해 VirtualServiceDestinationRule을 배포합니다.

    kubectl apply -f destination-vs-v1.yaml -n onlineboutique
    
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: productcatalogservice
    spec:
      host: productcatalogservice
      subsets:
      - labels:
          version: v1
        name: v1
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: productcatalogservice
    spec:
      hosts:
      - productcatalogservice
      http:
      - route:
        - destination:
            host: productcatalogservice
            subset: v1

    리소스에는 v1만 있습니다.

  7. 인그레스의 외부 IP 주소를 사용하여 브라우저에서 애플리케이션을 방문합니다.

    kubectl get services -n GATEWAY_NAMESPACE
    

다음 섹션에서는 Cloud Service Mesh UI를 둘러보고 측정항목을 확인하는 방법을 보여줍니다.

Google Cloud 콘솔에서 서비스 배포 및 보기

  1. Google Cloud 콘솔에서 GKE Enterprise 서비스 페이지로 이동합니다.

    GKE Enterprise 서비스로 이동

  2. 기본적으로 테이블 보기에 서비스가 표시됩니다.

    테이블 개요를 사용해서 중요한 측정항목은 물론 모든 서비스를 한 눈에 관찰할 수 있습니다.

    모든 서비스 워크로드

  3. 오른쪽 상단에서 토폴로지를 클릭합니다. 여기에서 서비스 및 서로 간의 상호작용을 볼 수 있습니다.

    커서를 위로 가져가서 서비스를 확장하고 각 서비스에 대한 초당 요청을 볼 수 있습니다.

    모든 서비스 워크로드 토폴로지

  4. 테이블 보기로 다시 돌아갑니다.

  5. 서비스 테이블에서 productcatalogservice를 선택합니다. 그러면 서비스 개요가 표시됩니다.

  6. 화면 왼쪽에서 트래픽을 클릭합니다.

  7. productcatalogservice의 수신 트래픽이 100% 워크로드 서비스로 이동하는지 확인합니다.

    productcatalog svc 트래픽

다음 섹션에서는 productcatalog 서비스의 v2 만들기를 살펴봅니다.

서비스의 v2 배포

  1. 이 튜토리얼에서 productcatalogservice-v2EXTRA_LATENCY 필드를 사용하여 3초 지연 시간을 도입합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: productcatalogservice-v2
    spec:
      selector:
        matchLabels:
          app: productcatalogservice
      template:
        metadata:
          labels:
            app: productcatalogservice
            version: v2
        spec:
          containers:
          - env:
            - name: PORT
              value: '3550'
            - name: EXTRA_LATENCY
              value: 3s
            name: server
            image: gcr.io/google-samples/microservices-demo/productcatalogservice:v0.3.6
            livenessProbe:
              exec:
                command: ["/bin/grpc_health_probe", "-addr=:3550"]
            ports:
            - containerPort: 3550
            readinessProbe:
              exec:
                command: ["/bin/grpc_health_probe", "-addr=:3550"]
            resources:
              limits:
                cpu: 200m
                memory: 128Mi
              requests:
                cpu: 100m
                memory: 64Mi
          terminationGracePeriodSeconds: 5

    이 리소스를 onlineboutique 네임스페이스에 적용합니다.

    kubectl apply -f productcatalog-v2.yaml -n onlineboutique
    
  2. 애플리케이션 포드를 확인합니다.

    kubectl get pods -n onlineboutique
    

    예상 출력:

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-8wqfd                  2/2     Running   0          25h
    cartservice-c77f6b866-7jwcr                 2/2     Running   0          25h
    checkoutservice-654c47f4b6-n8c6x            2/2     Running   0          25h
    currencyservice-59bc889674-l5xw2            2/2     Running   0          25h
    emailservice-5b9fff7cb8-jjr89               2/2     Running   0          25h
    frontend-77b88cc7cb-bwtk4                   2/2     Running   0          25h
    loadgenerator-6958f5bc8b-lqmnw              2/2     Running   0          25h
    paymentservice-68dd9755bb-dckrj             2/2     Running   0          25h
    productcatalogservice-84f95c95ff-ddhjv      2/2     Running   0          25h
    productcatalogservice-v2-6df4cf5475-9lwjb   2/2     Running   0          8s
    recommendationservice-64dc9dfbc8-7s7cx      2/2     Running   0          25h
    redis-cart-5b569cd47-vw7lw                  2/2     Running   0          25h
    shippingservice-5488d5b6cb-dj5gd            2/2     Running   0          25h
    

    이제 2개의 productcatalogservices가 나열됩니다.

  3. DestinationRule은 서비스 하위 세트를 지정하는 방법입니다. 이 시나리오에서는 productcatalogservice의 v1 및 v2를 위한 하위 집합이 있습니다.

    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: productcatalogservice
    spec:
      host: productcatalogservice
      subsets:
      - labels:
          version: v1
        name: v1
      - labels:
          version: v2
        name: v2

    labels 필드를 확인합니다. productcatalogservice 버전은 트래픽이 VirtualService로 라우팅된 후 구분됩니다.

    DestinationRule을 적용합니다.

    kubectl apply -f destination-v1-v2.yaml -n onlineboutique
    

v1과 v2 간 트래픽 분할

  1. VirtualService는 트래픽의 작은 부분은 productcatalogservice의 v2로 전달하는 방법입니다.

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: productcatalogservice
    spec:
      hosts:
      - productcatalogservice
      http:
      - route:
        - destination:
            host: productcatalogservice
            subset: v1
          weight: 75
        - destination:
            host: productcatalogservice
            subset: v2
          weight: 25

    하위 집합 필드는 버전을 나타내고 가중치 필드는 트래픽의 분할 비율을 나타냅니다. 트래픽의 75%가 productcatalog의 v1로 이동하고 25%가 v2로 이동합니다.

    VirtualService를 적용합니다.

    kubectl apply -f vs-split-traffic.yaml -n onlineboutique
    

클러스터 인그레스의 EXTERNAL_IP를 방문하면 프런트엔드가 주기적으로 로드보다 낮은 것이 확인됩니다.

다음 섹션에서는 GKE Enterprise Google Cloud 콘솔에서 트래픽 분할을 살펴봅니다.

Google Cloud 콘솔에서 트래픽 분할 관찰

  1. Google Cloud 콘솔로 돌아가서 GKE Enterprise 서비스 페이지로 이동합니다. GKE Enterprise 서비스로 이동

  2. 오른쪽 상단에서 토폴로지를 클릭합니다.

    productcatalogservice 워크로드를 확장합니다. productcatalogserviceproductcatalogservice-v2 배포가 표시됩니다.

    productcatalog svc v1 v2 트래픽 토폴로지

  3. 테이블 보기로 돌아갑니다. 서비스 테이블에서 productcatalogservice를 클릭합니다. 왼쪽 탐색 메뉴에서 트래픽으로 돌아갑니다.

  4. VirtualService 파일에 지정된 비율에 따라 v1과 v2 사이에 수신 트래픽이 분할되었는지 확인하고 productcatalog 서비스의 워크로드가 2개 있는지 확인합니다.

    화면 오른쪽에 요청, 오류 비율, 지연 시간 측정항목이 표시됩니다. Cloud Service Mesh에서는 각 서비스에 이러한 측정항목을 볼 수 있도록 요약되어 있습니다.

    productcatalog svc v1 v2 트래픽

버전으로 출시 또는 롤백

카나리아 배포 중 측정항목을 관찰한 후 VirtualService 리소스를 활용해서 새 버전으로 출시하거나 이전 버전으로 롤백할 수 있습니다.

출시

v2 서비스 동작이 만족스러우면 트래픽 동작을 v2 서비스로 점진적으로 늘립니다. 결국 트래픽을 새 서비스로 100% 전달할 수 있습니다.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: productcatalogservice
spec:
  hosts:
  - productcatalogservice
  http:
  - route:
    - destination:
        host: productcatalogservice
        subset: v2

모든 트래픽을 productcatalogservice의 v2로 전달하려면 다음 안내를 따르세요.

kubectl apply -f vs-v2.yaml -n onlineboutique

롤백

v1 서비스로 롤백해야 할 경우에는 단순히 앞에 나온 destination-vs-v1.yaml을 적용합니다. 이렇게 하면 트래픽이 productcatalogservice의 v1로만 전달됩니다.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: productcatalogservice
spec:
  hosts:
  - productcatalogservice
  http:
  - route:
    - destination:
        host: productcatalogservice
        subset: v1

모든 트래픽을 productcatalogservice의 v1로 전달하려면 다음 안내를 따르세요.

kubectl apply -f vs-v1.yaml -n onlineboutique

삭제

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

이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 프로젝트를 삭제하거나 개별 리소스를 삭제하면 됩니다.

프로젝트 삭제

  1. Cloud Shell에서 프로젝트를 삭제합니다.

    gcloud projects delete PROJECT_ID
    

리소스 삭제

  • 추가 요금이 청구되지 않도록 하려면 클러스터를 삭제하세요.

    gcloud container clusters delete  CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  • 클러스터를 유지하고 Online Boutique를 삭제하려면 다음 안내를 따르세요.

    1. 애플리케이션 네임스페이스를 삭제합니다.

      kubectl delete -f namespace onlineboutique
      

      예상 출력:

      namespace "onlineboutique" deleted
      
    2. 서비스 항목을 삭제합니다.

      kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/istio-manifests/frontend.yaml -n onlineboutique
      kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/istio-manifests/frontend-gateway.yaml -n onlineboutique
      

      예상 출력:

      serviceentry.networking.istio.io "allow-egress-googleapis" deleted
      serviceentry.networking.istio.io "allow-egress-google-metadata" deleted
      

다음 단계

  • PeerAuthentication 정책 구성에 대한 일반적인 가이드는 전송 보안 구성을 참조하기