流量镜像详解
1)什么是流量镜像(
流量镜像(Mirroring / traffic-shadow),也叫作影子流量,是指通过一定的配置将线上的真实流量复制一份到镜像服务中去,我们通过流量镜像转发以达到在不影响线上服务的情况下对流量或请求内容做具体分析的目的,它的设计思想是只做转发而不接收响应(fire and forget)。
(2)流量镜像工作原理
在 Istio 的服务网格架构中,数据平面的代理(通常是 Envoy)拦截服务间的请求。当流量镜像功能被启用时,代理会根据配置规则把原始流量的一份副本发送到指定的镜像目标。
假设有一个在线购物系统,包括订单服务、库存服务和支付服务。如果想对新升级的库存服务进行测试,就可以配置流量镜像,将发往原始库存服务的部分或全部流量复制一份发送到新升级的库存服务版本。原始订单服务和支付服务仍然按照正常流程处理业务,不受流量镜像的影响。
(3)应用场景
功能测试:在微服务架构中,当开发新功能或对现有功能进行升级时,可以使用流量镜像将生产流量复制到测试环境中的新服务版本。这样可以在真实的流量负载下观察新功能的行为,检查是否存在潜在的问题,如性能下降、逻辑错误等。
故障排查:当出现问题时,如服务性能异常或者出现错误,流量镜像可以帮助将流量复制到一个带有调试工具的服务副本。例如,可以将流量镜像到一个启用了详细日志记录或者性能分析工具的服务,从而更好地分析问题产生的原因。
数据收集与分析:通过将流量镜像到一个专门用于数据收集的服务,可以获取生产环境中真实的流量数据。这些数据可以用于各种分析目的,如用户行为分析、流量模式分析等,有助于优化服务和架构设计。
2.流量镜像测试
流量镜像功能可以将生产的流量镜像复制到测试集群或者新的测试版本中,在不影响实际生产环境的情况下,测试具有实际生产流量的服务,帮助减低版本变更的风险。也可以用在不同集群间的同步,实验开始:
(1)部署httpbin服务
V1版本的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: containers: - image: docker.io/kennethreitz/httpbin imagePullPolicy: IfNotPresent name: httpbin command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"] ports: - containerPort: 80 |
V2版本的httpbin
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| apiVersion: apps/v1 kind: Deployment metadata: name: httpbin-v2 spec: replicas: 1 selector: matchLabels: app: httpbin version: v2 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:80", "httpbin:app"] ports: - containerPort: 80 |
部署service,service 通过标签 app: httpbin 关联 httpbin-v1 和 httpbin-v2
|------------------------------------------------------------------------------------------------------------------------------------------------------|
| apiVersion: v1 kind: Service metadata: name: httpbin labels: app: httpbin spec: ports: - name: http port: 8000 targetPort: 80 selector: app: httpbin |
测试容器sleep
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| apiVersion: apps/v1 kind: Deployment metadata: name: sleep spec: replicas: 1 selector: matchLabels: app: sleep template: metadata: labels: app: sleep spec: containers: - name: sleep image: curlimages/curl command: ["/bin/sleep","3650d"] imagePullPolicy: IfNotPresent |
全部部署:
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| kubectl apply -f Traffic-Mirroring/mirrors-httpbin-v1.yaml kubectl apply -f Traffic-Mirroring/mirrors-httpbin-v2.yaml kubectl apply -f Traffic-Mirroring/mirrors-httpbin-service.yaml kubectl apply -f Traffic-Mirroring/mirrors-sleep.yaml [root@master mirroring]# kubectl apply -f ./ |
检查所有pod是否正常启动:
(2)配置路由
部署dr和VS
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - httpbin http: - route: - destination: host: httpbin subset: v1 weight: 100 ##所有流量都给V1了 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: httpbin spec: host: httpbin subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 |
部署
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@master mirroring]# kubectl apply -f mirrors-httpbin-vs-dr.yaml virtualservice.networking.istio.io/httpbin created destinationrule.networking.istio.io/httpbin created [root@master mirroring]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE httpbin ClusterIP 10.96.11.60 <none> 8000/TCP 17m kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 79m |
(3)测试访问
通过sleep容器向httpbin发起访问
|---------------------------------------------------------------------------------------------------|
| [root@master mirroring]# kubectl exec deployments/sleep -- curl -sS http://httpbin:8000/headers |
分别查看httpbinv1和v2的日志:
由于所有流量都被发给v1,所以v1有一条访问记录,而v2没有
(4)镜像流量
将v1所有的流量镜像给v2版本
重新部署一个VS
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - httpbin http: - route: - destination: host: httpbin subset: v1 weight: 100 mirror: host: httpbin subset: v2 mirrorPercentage: value: 100.0 |
部署VS
|--------------------------------------------------------------------------------------------------------------------------------|
| [root@master mirroring]# kubectl apply -f mirrors-httpbin-v1-2-v2.yaml virtualservice.networking.istio.io/httpbin configured |
再次做测试:
|---------------------------------------------------------------------------------------------------|
| [root@master mirroring]# kubectl exec deployments/sleep -- curl -sS http://httpbin:8000/headers |
查看httpbinV1和V2的日志
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@master mirroring]# kubectl logs deployments/httpbin-v1 [2024-11-06 07:14:59 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2024-11-06 07:14:59 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1) [2024-11-06 07:14:59 +0000] [1] [INFO] Using worker: sync [2024-11-06 07:14:59 +0000] [9] [INFO] Booting worker with pid: 9 127.0.0.6 - - [06/Nov/2024:07:15:42 +0000] "GET /headers HTTP/1.1" 200 525 "-" "curl/8.10.1" 127.0.0.6 - - [06/Nov/2024:07:16:56 +0000] "GET /headers HTTP/1.1" 200 525 "-" "curl/8.10.1" [root@master mirroring]# kubectl logs deployments/httpbin-v2 [2024-11-06 07:14:52 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2024-11-06 07:14:52 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1) [2024-11-06 07:14:52 +0000] [1] [INFO] Using worker: sync [2024-11-06 07:14:52 +0000] [9] [INFO] Booting worker with pid: 9 127.0.0.6 - - [06/Nov/2024:07:16:56 +0000] "GET /headers HTTP/1.1" 200 565 "-" "curl/8.10.1" |
由于所有流量都被发给v1并且镜像给了v2,所以v1有一条访问记录,v2在同一时间也有一条相同的访问记录。