流量镜像

这一任务演示istio对流量进行镜像复制的能力。流量镜像是一个有力的工具,在业务团队对生产系统进行变更的过程中,这一能力能够有效的降低风险。流量镜像功能可以对实时流量进行复制,将这一副本发送给镜像服务,并把主服务的关键请求路径放到带外。

Mirroring brings a copy of live traffic to a mirrored service and happens out of band of the critical request path for the primary service.
上句翻译存疑,目前也找不到合适的测试方法进行验证。

开始之前

  • 遵循安装指南设置Istio。
  • 启动两个版本的httpbin服务,并确保对其日志的访问能力。

httpbin-v1:

  1. cat <<EOF | kubectl create -f -
  2. apiVersion: extensions/v1beta1
  3. kind: Deployment
  4. metadata:
  5. name: httpbin-v1
  6. spec:
  7. replicas: 1
  8. template:
  9. metadata:
  10. labels:
  11. app: httpbin
  12. version: v1
  13. spec:
  14. containers:
  15. - image: docker.io/kennethreitz/httpbin
  16. imagePullPolicy: IfNotPresent
  17. name: httpbin
  18. command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:8080", "httpbin:app"]
  19. ports:
  20. - containerPort: 8080
  21. EOF

httpbin-v2:

  1. cat <<EOF | kubectl create -f -
  2. apiVersion: extensions/v1beta1
  3. kind: Deployment
  4. metadata:
  5. name: httpbin-v2
  6. spec:
  7. replicas: 1
  8. template:
  9. metadata:
  10. labels:
  11. app: httpbin
  12. version: v2
  13. spec:
  14. containers:
  15. - image: docker.io/kennethreitz/httpbin
  16. imagePullPolicy: IfNotPresent
  17. name: httpbin
  18. command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:8080", "httpbin:app"]
  19. ports:
  20. - containerPort: 8080
  21. EOF

httpbin的Kubernetes Service:

  1. cat <<EOF | kubectl create -f -
  2. apiVersion: v1
  3. kind: Service
  4. metadata:
  5. name: httpbin
  6. labels:
  7. app: httpbin
  8. spec:
  9. ports:
  10. - name: http
  11. port: 8080
  12. selector:
  13. app: httpbin
  14. EOF
  • 启动sleep服务,然后我们就可以使用curl产生负载了。

sleep服务

  1. cat <<EOF | kubectl create -f -
  2. apiVersion: extensions/v1beta1
  3. kind: Deployment
  4. metadata:
  5. name: sleep
  6. spec:
  7. replicas: 1
  8. template:
  9. metadata:
  10. labels:
  11. app: sleep
  12. spec:
  13. containers:
  14. - name: sleep
  15. image: tutum/curl
  16. command: ["/bin/sleep","infinity"]
  17. imagePullPolicy: IfNotPresent
  18. EOF

镜像

接下来设置一个场景来演示istio的流量镜像能力。我们现在有两个版本的httpbin服务。缺省情况下,Kubernetes会在这两个版本的服务之间进行负载均衡。我们使用Istio的路由能力,强制所有流量到httpbin服务的v1版本中去。

创建缺省路由策略

创建缺省的路由规则,把所有流量导向v1版本的httpbin服务。

  1. cat <<EOF | istioctl create -f -
  2. apiVersion: config.istio.io/v1alpha2
  3. kind: RouteRule
  4. metadata:
  5. name: httpbin-default-v1
  6. spec:
  7. destination:
  8. name: httpbin
  9. precedence: 5
  10. route:
  11. - labels:
  12. version: v1
  13. EOF

现在所有流量都进入httpbin v1服务,我们尝试发送一些请求:

  1. export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
  2. kubectl exec -it $SLEEP_POD -c sleep -- sh -c 'curl http://httpbin:8080/headers'
  3. {
  4. "headers": {
  5. "Accept": "*/*",
  6. "Content-Length": "0",
  7. "Host": "httpbin:8080",
  8. "User-Agent": "curl/7.35.0",
  9. "X-B3-Sampled": "1",
  10. "X-B3-Spanid": "eca3d7ed8f2e6a0a",
  11. "X-B3-Traceid": "eca3d7ed8f2e6a0a",
  12. "X-Ot-Span-Context": "eca3d7ed8f2e6a0a;eca3d7ed8f2e6a0a;0000000000000000"
  13. }
  14. }

如果我们检查一下v1v2两个版本的httpbin服务的所属Pod的日志,会发现只有v1版本的Pod中出现了访问记录:

  1. $ kubectl logs -f httpbin-v1-2113278084-98whj -c httpbin
  2. 127.0.0.1 - - [07/Feb/2018:00:07:39 +0000] "GET /headers HTTP/1.1" 200 349 "-" "curl/7.35.0"

创建到v2的镜像

  1. cat <<EOF | istioctl create -f -
  2. apiVersion: config.istio.io/v1alpha2
  3. kind: RouteRule
  4. metadata:
  5. name: mirror-traffic-to-httbin-v2
  6. spec:
  7. destination:
  8. name: httpbin
  9. precedence: 11
  10. route:
  11. - labels:
  12. version: v1
  13. weight: 100
  14. - labels:
  15. version: v2
  16. weight: 0
  17. mirror:
  18. name: httpbin
  19. labels:
  20. version: v2
  21. EOF

这一规则指定100%的流量进入v1,进入v2的流量是0%。目前这样的古怪设置是必须的,我们需要这样的一条来通知后端,根据这一内容对Envoy集群进行配置,我们会在这方面进行改进,以便今后不再需要制定0%权重的路由。

最后一段要求对流量进行复制,发送给httpbin v2服务。当流量被镜像的同时,这些请求会在Host/Authority头部加入-shadow字样,发送给镜像服务。例如cluster-1变成了cluster-1-shadow。另外,镜像请求是发完即忘的,对于镜像流量的请求响应是会被丢弃的。

如果我们再一次发送请求:

kubectl exec -it $SLEEP_POD -c sleep -- sh -c 'curl http://httpbin:8080/headers'

我们会在v1v2两个版本的Pod中都看到访问记录。v2中看到的访问日志实际上是访问v1的流量的镜像引发的。

清理

  1. 删除规则

    1. istioctl delete routerule mirror-traffic-to-httbin-v2
    2. istioctl delete routerule httpbin-default-v1
  2. 关闭httpbin服务和客户端。

    1. kubectl delete deploy httpbin-v1 httpbin-v2 sleep
    2. kubectl delete svc httpbin

下一步

阅读镜像配置参考,可以获得更多流量复制配置方面的信息。