本小节主要讲解istio的流量镜像能力。
流量镜像(Traffic mirroring),也称为“影子”(shadowing),是一个功能强大的概念,允许功能团队以尽可能小的风险将更改带到生产环境中。镜像将实时通信的副本发送到镜像服务。镜像通信发生在主服务的关键请求路径的带外。
在此任务中,您将首先强制所有流量到测试服务的v1。然后,您将应用一个规则来将一部分流量映射到v2。
1. 准备工作
首先部署两个启用了访问日志记录的httpbin服务版本:
- httpbin-v1:
$ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -apiVersion: apps/v1kind: Deploymentmetadata:name: httpbin-v1spec:replicas: 1selector:matchLabels:app: httpbinversion: v1template:metadata:labels:app: httpbinversion: v1spec:containers:- image: docker.io/kennethreitz/httpbinimagePullPolicy: IfNotPresentname: httpbincommand: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]ports:- containerPort: 80EOF
- httpbin-v2:
$ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -apiVersion: apps/v1kind: Deploymentmetadata:name: httpbin-v2spec:replicas: 1selector:matchLabels:app: httpbinversion: v2template:metadata:labels:app: httpbinversion: v2spec:containers:- image: docker.io/kennethreitz/httpbinimagePullPolicy: IfNotPresentname: httpbincommand: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]ports:- containerPort: 80EOF
- httpbin kubernetes服务:
$ kubectl create -f - <<EOFapiVersion: v1kind: Servicemetadata:name: httpbinlabels:app: httpbinspec:ports:- name: httpport: 8000targetPort: 80selector:app: httpbinEOF
- 启动sleep的服务,才能使用curl
$ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -apiVersion: apps/v1kind: Deploymentmetadata:name: sleepspec:replicas: 1selector:matchLabels:app: sleeptemplate:metadata:labels:app: sleepspec:containers:- name: sleepimage: tutum/curlcommand: ["/bin/sleep","infinity"]imagePullPolicy: IfNotPresentEOF
2. 创建默认的路由策略
默认情况下,Kubernetes在两个版本的httpbin服务之间进行负载平衡。在此步骤中,您将更改该行为,以便所有流量都转到v1。
- 创建默认的路由规则去路由所有流量到v1
kubectl apply -f - <<EOFapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: httpbinspec:hosts:- httpbinhttp:- route:- destination:host: httpbinsubset: v1weight: 100---apiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata:name: httpbinspec:host: httpbinsubsets:- name: v1labels:version: v1- name: v2labels:version: v2EOF
- 发送一些流量到服务进行测试
$ export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})$ kubectl exec -it $SLEEP_POD -c sleep -- sh -c 'curl http://httpbin:8000/headers' | python -m json.tool
- 检查httpbin的v1和v2日志,应该看到v1版本有日志,而v2版本没有。
$ export V1_POD=$(kubectl get pod -l app=httpbin,version=v1 -o jsonpath={.items..metadata.name})$ kubectl logs -f $V1_POD -c httpbin
$ export V2_POD=$(kubectl get pod -l app=httpbin,version=v2 -o jsonpath={.items..metadata.name})$ kubectl logs -f $V2_POD -c httpbin
3. 镜像流量到v2
- 改变路由规则去镜像流量到v2
$ kubectl apply -f - <<EOFapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: httpbinspec:hosts:- httpbinhttp:- route:- destination:host: httpbinsubset: v1weight: 100mirror:host: httpbinsubset: v2mirror_percent: 100EOF
此路由规则将100%的流量发送到v1。最后一节指定您希望镜像到httpbin:v2 服务。当流量被镜像时,请求被发送到镜像服务,其Host/Authority报头被附加上-shadow。例如,cluster-1变成cluster-1-shadow。
另外,需要注意的是,这些请求被镜像为“fire and forget”,这意味着响应被丢弃。
您可以使用mirror_percent字段来镜像一部分流量,而不是镜像所有请求。如果该字段不存在,为了与旧版本兼容,所有流量都将被镜像。
- 发送流量
$ kubectl exec -it $SLEEP_POD -c sleep -- sh -c 'curl http://httpbin:8000/headers' | python -m json.tool
现在,您应该看到v1和v2的访问日志记录。在v2中创建的访问日志实际上是指向v1的镜像请求。
$ kubectl logs -f $V1_POD -c httpbin$ kubectl logs -f $V2_POD -c httpbin
3. 清除本实验
$ kubectl delete virtualservice httpbin$ kubectl delete destinationrule httpbin$ kubectl delete deploy httpbin-v1 httpbin-v2 sleep$ kubectl delete svc httpbin
