基于集群内服务层使用流量镜像

流量镜像功能可以将生产的流量镜像拷贝到测试集群或者新的测试版本中,在不影响实际生产环境的情况下,测试具有实际生产流量的服务,帮助您减低版本变更的风险。本文介绍什么是流量镜像,以及如何基于集群内服务层使用流量镜像。

什么是流量镜像?

微服务能够帮助用户快速地开发和部署应用,但版本变更中也存在一定风险。服务网格ASM提供流量镜像(Traffic Mirroring)的功能,也称影子流量(Traffic Shadowing)。该功能将实时流量的副本发送到镜像服务,而镜像流量发生在主服务的关键请求路径之外。当流量被镜像时,请求将通过其主机或授权报头发送到镜像服务添加“–shadow”标记,用以区分流量从何处被镜像到何处。流量镜像功能可以将生产的流量镜像拷贝到测试集群或者新的测试版本中,在引导实时流量之前进行测试,有效地降低版本变更的风险。

功能优势

优势

说明

测试环境更加真实,版本部署风险更低。

流量镜像功能可以将生产的流量镜像拷贝到测试集群或者新的测试版本中,利用实时生产用例和流量进行测试,使得测试服务环境更加真实,测试结果更加准确,帮助您降低生产环境部署的风险。

不影响实际生产环境。

  • 当流量镜像到不同的服务时,会发生在请求的关键路径之外。流量镜像产生的任何问题都不会影响生产环境。

  • 忽略对任何镜像流量的响应,流量被视为“即发即忘”。镜像实例发回的任何响应都将被忽略,不会干扰到正常的生产流量的响应。

适用场景

流量镜像可以在不影响最终客户端的情况下,测试具有实际生产流量的服务。您可以使用流量镜像功能,验证新版本是否能够以相同的方式处理真正的各种传入请求、在同一服务的两个版本之间进行比较基准测试等。

下面介绍几种典型的应用场景,帮助您发挥流量镜像的优势。

应用场景

说明

线上流量模拟和测试

测试集群的测试可以使用生产实例真实流量,不会影响正常生产的关键路径。例如,用新系统替换老旧系统或者系统经历大规模改造时,您可以将线上流量导入新系统,进行试运行;对于一些实验性的架构调整,您也可以通过线上流量进行模拟测试。

新版本校验

您可以实时对比生产流量和镜像流量的输出结果。由于是全样本的模拟,影子流量可以应用于新服务的预上线演练。传统的手工测试本身是一种样本化的行为,通过导入真实流量形态,可以完整地模拟线上的所有情况,例如异常的特殊字符、带恶意攻击的Token等,帮助您探测预发布服务最真实的处理能力和对异常的处理能力。

隔离测试数据库

与数据处理相关的业务,可以使用空的数据存储并加载测试数据。针对该数据进行镜像流量操作,实现测试数据的隔离。

线上问题排查和临时的数据采集

对于一些线上突发性问题,在线下流量总是无法复现,此时您可以临时开启一个分支服务,导入影子流量进行调试和排查。采用此方式,不影响线上服务。

日志行为采集

对于推荐系统和算法来说,样本和数据非常核心。传统的自动化测试在算法类的应用面临的最大挑战是无法构建真实环境的用户行为数据。通过影子流量可以将用户行为以日志的形式保存起来,既可以为推荐系统和算法模型构建模拟测试样本数据,也可以作为后续大数据分析用户画像的数据来源再应用到推荐服务中。

启用流量镜像示例代码

使用Istio启用流量镜像的YAML示例如下。YAML示例中,VirtualService将100%的流量路由到v1子集,同时将相同的流量镜像到v1-mirroring子集。发送给v1子集的相同请求将被复制并触发v1-mirroring子集。

当v1-mirroring将一些请求发送到应用程序的v1版本时,您可以查看应用程序的日志。调用应用程序时,获得的响应来自v1子集。您还可以看到请求镜像到v1-mirroring子集。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp-traffic-mirroring
spec:
  hosts:
    - myapp
  http:
    - route:
        - destination:
            host: myapp.default.svc.cluster.local
            port:
              number: 8000
            subset: v1
          weight: 100
      mirror:
        host: myapp.default.svc.cluster.local
        port:
          number: 8000
        subset: v1-mirroring

集群内使用流量镜像流程介绍

本文示例将所有流量分配到v1版本,然后使用规则将流量镜像到v1-mirroring版本。基于集群内服务层使用流量镜像

步骤一:配置并启动示例应用服务

  1. 使用以下内容,创建httpbin.yaml文件。

    展开查看httpbin.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
        service: httpbin
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 80
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin-v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          serviceAccountName: httpbin
          containers:
          - image: docker.io/kennethreitz/httpbin
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 80
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin-v1-mirroring
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1-mirroring
      template:
        metadata:
          labels:
            app: httpbin
            version: v1-mirroring
        spec:
          serviceAccountName: httpbin
          containers:
          - image: docker.io/kennethreitz/httpbin
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 80
  2. 执行以下命令,部署v1和v1-mirroring两个版本的httpbin服务。

    kubectl apply -f httpbin.yaml
  3. 使用以下内容,创建sleep.yaml文件。

    展开查看sleep.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: curlimages/curl
            command: ["/bin/sleep", "infinity"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
    ---
  4. 执行以下命令,部署一个客户端应用sleep服务。

    kubectl apply -f httpbin.yaml

步骤二:创建路由策略

  1. 创建目标规则,定义v1和v1-mirroring两个版本。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

    2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择流量管理中心 > 目标规则,然后单击创建

    3. 创建页面,进行如下配置,然后单击创建创建路由策略

  2. 创建新的虚拟服务路由策略。将100%流量导入到v1版,同时将流量镜像到v1-mirroring服务。

    1. 在网格详情页面左侧导航栏,选择流量管理中心 > 虚拟服务

    2. 虚拟服务页面,单击创建,进行如下配置,然后单击创建

      创建路由策略-1创建路由策略2

步骤三:发送流量请求

  1. 等待应用服务运行正常之后,执行以下命令,通过sleep应用向httpbin服务发送一些流量。

    export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
    kubectl exec -it $SLEEP_POD -c sleep -- curl http://httpbin:8000/headers
  2. 查看v1和v1-mirroring版本的Pod日志。具体操作,请参见检查Pod的日志

    日志显示,v1和v1-mirroring版本的Pod中有上述请求流量访问的记录,表明100%的流量被发送到v1版本的同时,也有50%的流量被镜像到v1-mirroring的Pod中,符合上述定义的镜像策略。

    如下图所示,对比v1和v1-mirroring版本的日志,可以看到在v1的流量被镜像到了v1-mirroring。日志中的v1-mirroring报文比v1大,是因为流量被标记为影子流量,且在authority结果中影子流量自动补加了-shadow对比日志