Istio流量管理实践之(3): 基于Istio实现流量对比分析

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 流量镜像提供一种尽可能低的风险为生产带来变化的强大功能。镜像会将实时流量的副本发送到镜像服务,镜像流量发生在主服务的关键请求路径之外。一旦我们能够可靠地镜像流量,就可以开始做一些有价值的事情,例如通过请求流量对比工具Diffy,可以将引入测试集群的流量与生产集群中的预期行为进行比较。

流量镜像

流量镜像,也称为影子流量,流量镜像提供一种尽可能低的风险为生产带来变化的强大功能。镜像会将实时流量的副本发送到镜像服务。镜像流量发生在主服务的关键请求路径之外。

在非生产或者测试环境中,尝试访问一个服务所有可能的测试用例组合是个非常不现实的任务。 在某些情况下,编写这些用例的所有工作也可能与实际生产所需的用例不匹配。在理想情况下,可以使用实时的生产用例和流量来帮助完善在测试环境中错过的功能区域。

一旦我们能够可靠地镜像流量,就可以开始做一些有价值的事情,例如通过请求流量对比工具Diffy,可以将引入测试集群的流量与生产集群中的预期行为进行比较。例如,我们可能想比较请求结果与预期结果间的偏差,或是API协议中的数据损坏情况,以便更好地兼容。
除此之外,需要注意:

  • 当流量镜像到不同的服务时,会发生在请求的关键路径之外;
  • 忽略对任何镜像流量的响应; 流量被视为“即发即忘”;

流量对比

此处,插入一个代理就可以负责此类流量的协调,并对其进行有趣的比较。Diffy就是一款这样的代理工具。Diffy启动一个代理服务(例如监听端口8880),再根据用户设置的primary、secondary两个旧服务地址(primary和secondary代码完全相同,目的是为了减少噪音干扰)、candidate新服务地址。

它还能够检测结果中的噪音,并通过先调用两个实时服务的实例来忽略它们(例如时间戳,单调递增计数器等提示),总结来说就是检测,然后在测试服务中忽略掉这部分。

图片.png

Diffy还提供了一个不错的页面可以用来查看调用结果、对比情况、和基于某些特征的过滤。它还有一个很好的管理控制台,可以查看有关调用比较结果的功能指标(metrics)和统计数据(statistics)。

创建用于Istio流量镜像的服务

在此任务中,将首先强制所有流量到 v1 版本的服务。然后,将使用规则将一部分流量镜像到 v2版本。

首先部署两个版本的示例服务。

版本1的部署使用了Docker镜像httpbin,提供常见的http请求访问:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mirrorservice-sample-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mirrorservice-sample
        version: v1
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: mirrorservice-sample
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:44134", "httpbin:app"]
        ports:
        - containerPort: 44134      

版本2的部署使用了自定义的Docker镜像,对应的Dockerfile如下:

FROM nginx:latest
COPY default.conf /etc/nginx/conf.d/
EXPOSE 80

所需的nginx 配置文件:

server {
    listen       44134;
    server_name  localhost;

    location / {
        proxy_pass http://httpbin-diffy.diffy:8880/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";   
    }
}

版本2的部署作为Istio的流量镜像目标,在接收到流量之后会转发到Diffy的代理中。当前没有直接将Diffy代理作为Isito流量镜像目标,原因是Diffy代理与Envoy代理目前本身有冲突,无法正常流量转发,因此需要此部署中转一下。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mirrorservice-sample-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mirrorservice-sample
        version: v2
    spec:
      containers:
      - name: mirrorservice-sample
        image: registry.cn-beijing.aliyuncs.com/wangxining/mirrorservice:0.1
        imagePullPolicy: Always
        ports:
        - containerPort: 44134

对应的Kubernetes service:

apiVersion: v1
kind: Service
metadata:
  name: mirrorservice-sample
spec:
  type: ClusterIP
  ports:
  - name: http
    port: 44134
  selector:
    app: mirrorservice-sample

创建流量镜像的Istio策略

默认情况下,Kubernetes 在服务的两个版本之间进行负载均衡。创建如下流量镜像规则将 100% 的流量发送到 v1, 同时指定流量镜像到v2。当流量被镜像时,请求将通过其主机/授权报头发送到镜像服务附上 -shadow 。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: mirrorservice-sample
spec:
  host: mirrorservice-sample
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
---      
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: mirrorservice-sample
spec:
  hosts:
    - mirrorservice-sample
  http:
  - route:
    - destination:
        host: mirrorservice-sample
        subset: v1
      weight: 100
    #- destination:
    #    host: mirrorservice-sample
    #    subset: v2
    #  weight: 0
    mirror:
      host: mirrorservice-sample
      subset: v2

搭建Diffy用于请求流量对比

Diffy可以作为代理,截取请求并发送至所有运行的服务实例,通过对比响应结果来发现每次迭代代码中可能存在的问题。其中,Diffy上运行了三类代码实例:

  • 线上稳定版本:一个运行线上稳定版本代码的节点
  • 线上稳定版本备份:同样运行了线上的稳定版本,用于消除噪音
  • 测试版本:待上线的测试版本,用于和线上环境代码进行对比
    图片.png

在实际Diffy测试中,会发现大部分的接口都会有一定差异,原因是这些响应中存在了噪音,噪音可能包括:

  • server响应中生成的时间戳
  • 随机生成的数字
  • 系统服务间的有条件竞争

Diffy能够通过一定的方式,清除这类噪音,保证分析结果不被影响。

创建Diffy及示例服务

通过以下YAML创建Diffy服务:

apiVersion: v1
kind: Service
metadata:
  name: httpbin-diffy
  labels:
    app: httpbin-diffy
spec:
  ports:
  - name: http-proxy
    port: 8880
  - name: http-admin
    port: 8881
  - name: http-console
    port: 8888    
  selector:
    app: httpbin-diffy
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: httpbin-diffy
    version: v2
  name: httpbin-diffy-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin-diffy
      version: v2
  template:
    metadata:
      labels:
        app: httpbin-diffy
        version: v2
    spec:
      containers:
      - image: lordofthejars/diffy:1.0
        imagePullPolicy: IfNotPresent
        livenessProbe:
          exec:
            command:
            - curl
            - localhost:8888
          initialDelaySeconds: 10
          periodSeconds: 60
          timeoutSeconds: 1
        name: httpbin-diffy
        args: ["-candidate=httpbin-candidate:8080", "-master.primary=httpbin-master:8080", "-master.secondary=httpbin-master:8080", "-service.protocol=http", "-serviceName=httpbin", "-proxy.port=:8880", "-admin.port=:8881", "-http.port=:8888", "-rootUrl='localhost:8888'"]
        ports:
        - containerPort: 8888
          name: http-console
          protocol: TCP
        - containerPort: 8880
          name: http-proxy
          protocol: TCP
        - containerPort: 8881
          name: http-admin
          protocol: TCP
        readinessProbe:
          exec:
            command:
            - curl
            - localhost:8888
          initialDelaySeconds: 10
          periodSeconds: 60
          timeoutSeconds: 1
        securityContext:
          privileged: false

通过以下YAML创建示例所用的primary、secondary(当前示例中与primary相同)与candidate服务:

apiVersion: v1
kind: Service
metadata:
  name: httpbin-master
  labels:
    app: httpbin-master
spec:
  ports:
  - name: http
    port: 8080
  selector:
    app: httpbin
    version: v1
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin-candidate
  labels:
    app: httpbin-candidate
spec:
  ports:
  - name: http
    port: 8080
  selector:
    app: httpbin
    version: v2
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: httpbin-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:8080", "httpbin:app"]
        ports:
        - containerPort: 8080
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: httpbin-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: httpbin
        version: v2
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:8080", "httpbin:app"]
        ports:
        - containerPort: 8080

发送流量进行镜像验证

启动 sleep 服务,这样就可以使用 curl 来提供负载:

cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sleep
    spec:
      containers:
      - name: sleep
        image: tutum/curl
        command: ["/bin/sleep","infinity"]
        imagePullPolicy: IfNotPresent
EOF

进入到SLEEP_POD, 具体POD名称根据实际赋值。

kubectl exec -it $SLEEP_POD -c sleep sh

发送流量:

curl -v http://mirrorservice-sample:44134/headers

可以查看 v1的访问日志记录,如下所示创建的请求100%指向了v1。
图片.png

与此同时,查看Diffy的Web界面,可以看到创建的请求也被镜像到Diffy Proxy:
图片.png

图片.png

Diffy能够通过一定的方式,清除这类噪音,保证分析结果不被影响。
图片.png

结论

流量镜像提供一种尽可能低的风险为生产带来变化的强大功能。镜像会将实时流量的副本发送到镜像服务,镜像流量发生在主服务的关键请求路径之外。一旦我们能够可靠地镜像流量,就可以开始做一些有价值的事情,例如通过请求流量对比工具Diffy,可以将引入测试集群的流量与生产集群中的预期行为进行比较。

支持流量镜像只是 Istio 的众多功能之一,它将使基于大型微服务的应用程序的生产部署与管理变得更加简单。欢迎大家使用阿里云上的容器服务,快速搭建微服务的开放治理平台Istio,比较简单地集成到自己项目的微服务开发中。

相关文章
|
3月前
|
Shell Python Perl
深入理解Istio流量管理的熔断配置
创建目标规则,访问 httpbin 服务时应用熔断配置 在 fortio 服务中向 httpbin 服务的发出并发请求
93 3
深入理解Istio流量管理的熔断配置
|
9月前
|
Kubernetes JavaScript API
如何理解 Istio Ingress, 它与 API Gateway 有什么区别?东西流量?南北流量?
这三者都和流量治理密切相关,那么流量治理在过去和现在有什么区别呢?都是如何做的呢? 在学习istio的时候对流量管理加深了理解。什么是东西流量?什么是南北流量?
182 0
|
6月前
|
安全 前端开发 Cloud Native
Istio 探索:微服务的流量管理、安全性和策略加固
Istio 探索:微服务的流量管理、安全性和策略加固
41 0
|
7月前
|
Kubernetes 负载均衡 网络协议
全网最细,深度解析 Istio Ambient Mesh 流量路径
本文旨在对 Istio Ambient Mesh 的流量路径进行详细解读,力求尽可能清晰地呈现细节,以帮助读者完全理解 Istio Ambient Mesh 中最为关键的部分。
|
9月前
|
Prometheus Kubernetes Cloud Native
一文带你了解 Istio 流量路由
当我们尝试在 Kubernetes 中使用 NodePort 或 LoadBalancer 类型的服务设施配置进行通信时,Istio 或许是一个非常流行、新兴的开源服务网格产品,其能够用于通信管理、可观察性、错误处理及安全性等。作为微服务架构体系的一部分,为了无需过多地使用重复的逻辑填充每个微服务代码,我们可以利用 Istio 服务网格在一个地方完成所有这些事情。
109 0
|
9月前
|
Kubernetes Shell iOS开发
Istio 网络:深入了解流量和架构
像 Istio 这样的服务网格项目为我们的架构引入了许多功能和优势,包括更安全地管理集群微服务之间的流量、服务发现、请求路由以及服务之间的可靠通信。
155 0
|
9月前
|
缓存 运维 NoSQL
在Istio中实现Redis集群的数据分片读写分离和流量镜像
Redis 是一个高性能的 key-value 存储系统,被广泛用于微服务架构中。如果我们想要使用 Redis 集群模式提供的高级特性,则需要对客户端代码进行改动,这带来了应用升级和维护的一些困难。利用 Istio 和 Envoy ,我们可以在不修改客户端代码的前提下实现客户端无感知的 Redis Cluster 数据分片,并提供读写分离、流量镜像等高级流量管理功能。
|
测试技术 开发者
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(二)
快速学习 KubeVela 对接 Istio 实现应用灰度发布实践
362 0
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(二)
|
开发者 微服务
Istio 流量管理| 学习笔记
快速学习 Istio 流量管理
100 0
|
Prometheus 监控 Kubernetes
进阶:对接 Istio 实现应用灰度发布实践| 学习笔记
快速学习进阶:对接 Istio 实现应用灰度发布实践。
149 0
进阶:对接  Istio 实现应用灰度发布实践| 学习笔记