Cloud Service Mesh 示例:Canary 部署


在本教程中,您将逐步完成一个常见的使用场景:使用 Istio API 来通过 Cloud Service Mesh 发布 Canary 部署。

什么是 Canary 部署?

Canary 部署会将一小部分流量路由到新版微服务,然后逐步提高该百分比,同时逐步淘汰和弃用旧版本。如果在此过程中出现问题,流量可以切换回早期版本。借助 Cloud Service Mesh,您可以路由流量,以确保安全引入新服务。

如需详细了解 Canary 测试,请参阅应用部署和测试策略

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本教程后,您可以删除所创建的资源以避免持续产生费用。如需了解详情,请参阅清理

准备工作

部署 Online Boutique

  1. kubectl 的当前上下文设置为您计划在其中部署 Online Boutique 的集群。该命令取决于您是在 GKE 集群上预配 Cloud Service Mesh,还是在 GKE 外部的 Kubernetes 集群上预配 Cloud Service Mesh:

    GKE on Google Cloud

    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. onlineboutique 命名空间添加标签以自动注入 Envoy 代理。请按照如何启用自动边车代理注入中的步骤操作。

  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 表示 Pod 已启动并运行,且 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 界面,并介绍如何查看指标。

在 Google Cloud 控制台中查看您的服务

  1. 在 Google Cloud 控制台中,前往 Google Kubernetes Engine (GKE) Enterprise 版本服务页面。

    转到 Google Kubernetes Engine (GKE) Enterprise 版本服务

  2. 默认情况下,您在列表视图中查看您的服务。

    通过“表概览”,您可以一目了然地查看所有服务以及重要指标。

  3. 点击右上角的拓扑。 在这里,您可以查看服务及其彼此的交互情况。

    您可以展开服务,然后将光标悬停在每项服务上,查看其每秒请求数

  4. 返回到表格视图

  5. 服务表中,选择 productcatalogservice。您将大致了解您的服务。

  6. 在屏幕左侧,点击流量

  7. 确保 productcatalogservice 的所有传入流量都去往工作负载服务。

下一部分介绍如何创建 productcatalog 服务的 v2 版本。

部署服务的 v2 版

  1. 在本教程中,productcatalogservice-v2 为包含 EXTRA_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. 查看应用 Pod。

    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
    

    请注意,现在列出了两个 productcatalogservices

  3. 使用 DestinationRule 指定服务的子集。在此场景中,v1 有一个子集,v2 又有一个单独的 productcatalogservice 子集。

    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 字段。在 VirtualService 路由流量后,可以区分 productcatalogservice 的不同版本。

    应用 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
    

如果您访问集群 Ingress 的 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 服务工作负载。

    在页面的右侧,您会看到请求错误率延迟时间指标。 借助 Cloud Service Mesh,每项服务都会概括这些指标,为您提供可观测性指标。

发布或回滚到某个版本

在 Canary 部署期间观察指标后,您可以完成新服务版本的发布,或利用 VirtualService 资源回滚到原始服务版本。

发布

在对 v2 服务的行为感到满意后,您可以逐步增加指向 v2 服务的流量的百分比。最终,通过从该资源中移除流量拆分,可以将流量全部定向到您在上面创建的 VirtualService 资源中的新服务。

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 

如果您使用 gcloud container fleet memberships 向舰队注册集群(而不是在集群创建期间使用 --enable-fleet--fleet-project),请移除过时的成员资格:

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 政策的一般指南,请参阅配置传输安全性