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


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

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

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

비용

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

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

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

시작하기 전에

Online Boutique 배포

  1. Online Boutique를 배포하려는 클러스터로 kubectl의 현재 컨텍스트를 설정합니다. 명령어는 GKE 클러스터의 Cloud Service Mesh에 프로비저닝했는지 또는 GKE 외부의 Kubernetes 클러스터에 프로비저닝했는지에 따라 다릅니다.

    Google Cloud 기반 GKE

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    

    Google Cloud 외부의 GKE

    kubectl config use-context CLUSTER_NAME 
    
  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 콘솔에서 Google Kubernetes Engine(GKE) Enterprise 버전 서비스 페이지로 이동합니다.

    Google Kubernetes Engine(GKE) Enterprise 버전 서비스로 이동

  2. 기본적으로 목록 보기에 서비스가 표시됩니다.

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

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

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

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

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

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

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

다음 섹션에서는 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를 방문하면 프런트엔드가 주기적으로 로드보다 낮은 것이 확인됩니다.

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

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

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

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

    productcatalogservice 워크로드를 펼치고 productcatalogserviceproductcatalogservice-v2 배포를 확인합니다.

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

  4. 서비스 테이블에서 productcatalogservice를 클릭합니다.

  5. 왼쪽 탐색 메뉴에서 트래픽으로 돌아갑니다.

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

    페이지 오른쪽에 요청, 오류율, 지연 시간 측정항목이 표시됩니다. Cloud Service Mesh에서는 관측 가능성 측정항목을 제공하기 위해 각 서비스에 측정항목이 요약되어 있습니다.

버전으로 출시 또는 롤백

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

출시

v2 서비스 동작이 만족스러우면 v2 서비스로 전달되는 트래픽의 비율을 점진적으로 늘리면 됩니다. 결국 위에서 만든 VirtualService 리소스에서 트래픽 분할을 삭제하여 이 리소스의 새 서비스로 트래픽을 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 계정에 청구되지 않도록 하려면 프로젝트를 삭제하거나 개별 리소스를 삭제하면 됩니다.

프로젝트 삭제

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

gcloud projects delete PROJECT_ID

리소스 삭제

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

gcloud container clusters delete  CLUSTER_NAME  \
  --project=PROJECT_ID \
  --zone=CLUSTER_LOCATION 

클러스터 생성 중에 --enable-fleet 또는 --fleet-project 대신 gcloud container fleet memberships를 사용하여 Fleet에 클러스터를 등록한 경우 비활성 멤버십을 삭제합니다.

gcloud container fleet memberships delete  MEMBERSHIP  \
  --project=PROJECT_ID

클러스터를 Cloud Service Mesh에 대해 구성된 상태로 유지하되 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 정책 구성에 대한 일반적인 가이드는 전송 보안 구성을 참조하기