本小节主要讲解istio的流量镜像能力。

流量镜像(Traffic mirroring),也称为“影子”(shadowing),是一个功能强大的概念,允许功能团队以尽可能小的风险将更改带到生产环境中。镜像将实时通信的副本发送到镜像服务。镜像通信发生在主服务的关键请求路径的带外。

在此任务中,您将首先强制所有流量到测试服务的v1。然后,您将应用一个规则来将一部分流量映射到v2。

1. 准备工作

首先部署两个启用了访问日志记录的httpbin服务版本:

  • httpbin-v1:
  1. $ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: httpbin-v1
  6. spec:
  7. replicas: 1
  8. selector:
  9. matchLabels:
  10. app: httpbin
  11. version: v1
  12. template:
  13. metadata:
  14. labels:
  15. app: httpbin
  16. version: v1
  17. spec:
  18. containers:
  19. - image: docker.io/kennethreitz/httpbin
  20. imagePullPolicy: IfNotPresent
  21. name: httpbin
  22. command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]
  23. ports:
  24. - containerPort: 80
  25. EOF
  • httpbin-v2:
  1. $ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: httpbin-v2
  6. spec:
  7. replicas: 1
  8. selector:
  9. matchLabels:
  10. app: httpbin
  11. version: v2
  12. template:
  13. metadata:
  14. labels:
  15. app: httpbin
  16. version: v2
  17. spec:
  18. containers:
  19. - image: docker.io/kennethreitz/httpbin
  20. imagePullPolicy: IfNotPresent
  21. name: httpbin
  22. command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]
  23. ports:
  24. - containerPort: 80
  25. EOF
  • httpbin kubernetes服务:
  1. $ kubectl create -f - <<EOF
  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: 8000
  12. targetPort: 80
  13. selector:
  14. app: httpbin
  15. EOF
  • 启动sleep的服务,才能使用curl
  1. $ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: sleep
  6. spec:
  7. replicas: 1
  8. selector:
  9. matchLabels:
  10. app: sleep
  11. template:
  12. metadata:
  13. labels:
  14. app: sleep
  15. spec:
  16. containers:
  17. - name: sleep
  18. image: tutum/curl
  19. command: ["/bin/sleep","infinity"]
  20. imagePullPolicy: IfNotPresent
  21. EOF

2. 创建默认的路由策略

默认情况下,Kubernetes在两个版本的httpbin服务之间进行负载平衡。在此步骤中,您将更改该行为,以便所有流量都转到v1。

  1. 创建默认的路由规则去路由所有流量到v1
  1. kubectl apply -f - <<EOF
  2. apiVersion: networking.istio.io/v1alpha3
  3. kind: VirtualService
  4. metadata:
  5. name: httpbin
  6. spec:
  7. hosts:
  8. - httpbin
  9. http:
  10. - route:
  11. - destination:
  12. host: httpbin
  13. subset: v1
  14. weight: 100
  15. ---
  16. apiVersion: networking.istio.io/v1alpha3
  17. kind: DestinationRule
  18. metadata:
  19. name: httpbin
  20. spec:
  21. host: httpbin
  22. subsets:
  23. - name: v1
  24. labels:
  25. version: v1
  26. - name: v2
  27. labels:
  28. version: v2
  29. EOF
  1. 发送一些流量到服务进行测试
  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:8000/headers' | python -m json.tool
  1. 检查httpbin的v1和v2日志,应该看到v1版本有日志,而v2版本没有。
  1. $ export V1_POD=$(kubectl get pod -l app=httpbin,version=v1 -o jsonpath={.items..metadata.name})
  2. $ kubectl logs -f $V1_POD -c httpbin
  1. $ export V2_POD=$(kubectl get pod -l app=httpbin,version=v2 -o jsonpath={.items..metadata.name})
  2. $ kubectl logs -f $V2_POD -c httpbin

3. 镜像流量到v2

  1. 改变路由规则去镜像流量到v2
  1. $ kubectl apply -f - <<EOF
  2. apiVersion: networking.istio.io/v1alpha3
  3. kind: VirtualService
  4. metadata:
  5. name: httpbin
  6. spec:
  7. hosts:
  8. - httpbin
  9. http:
  10. - route:
  11. - destination:
  12. host: httpbin
  13. subset: v1
  14. weight: 100
  15. mirror:
  16. host: httpbin
  17. subset: v2
  18. mirror_percent: 100
  19. EOF

此路由规则将100%的流量发送到v1。最后一节指定您希望镜像到httpbin:v2 服务。当流量被镜像时,请求被发送到镜像服务,其Host/Authority报头被附加上-shadow。例如,cluster-1变成cluster-1-shadow

另外,需要注意的是,这些请求被镜像为“fire and forget”,这意味着响应被丢弃。

您可以使用mirror_percent字段来镜像一部分流量,而不是镜像所有请求。如果该字段不存在,为了与旧版本兼容,所有流量都将被镜像。

  1. 发送流量
  1. $ kubectl exec -it $SLEEP_POD -c sleep -- sh -c 'curl http://httpbin:8000/headers' | python -m json.tool

现在,您应该看到v1和v2的访问日志记录。在v2中创建的访问日志实际上是指向v1的镜像请求。

  1. $ kubectl logs -f $V1_POD -c httpbin
  2. $ kubectl logs -f $V2_POD -c httpbin

3. 清除本实验

  1. $ kubectl delete virtualservice httpbin
  2. $ kubectl delete destinationrule httpbin
  3. $ kubectl delete deploy httpbin-v1 httpbin-v2 sleep
  4. $ kubectl delete svc httpbin