流量镜像
这一任务演示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:
cat <<EOF | kubectl create -f -
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
EOF
httpbin-v2:
cat <<EOF | kubectl create -f -
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
EOF
httpbin的Kubernetes Service:
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
spec:
ports:
- name: http
port: 8080
selector:
app: httpbin
EOF
- 启动
sleep
服务,然后我们就可以使用curl
产生负载了。
sleep
服务
cat <<EOF | 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
镜像
接下来设置一个场景来演示istio的流量镜像能力。我们现在有两个版本的httpbin
服务。缺省情况下,Kubernetes会在这两个版本的服务之间进行负载均衡。我们使用Istio的路由能力,强制所有流量到httpbin
服务的v1
版本中去。
创建缺省路由策略
创建缺省的路由规则,把所有流量导向v1
版本的httpbin
服务。
cat <<EOF | istioctl create -f -
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: httpbin-default-v1
spec:
destination:
name: httpbin
precedence: 5
route:
- labels:
version: v1
EOF
现在所有流量都进入httpbin v1
服务,我们尝试发送一些请求:
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:8080/headers'
{
"headers": {
"Accept": "*/*",
"Content-Length": "0",
"Host": "httpbin:8080",
"User-Agent": "curl/7.35.0",
"X-B3-Sampled": "1",
"X-B3-Spanid": "eca3d7ed8f2e6a0a",
"X-B3-Traceid": "eca3d7ed8f2e6a0a",
"X-Ot-Span-Context": "eca3d7ed8f2e6a0a;eca3d7ed8f2e6a0a;0000000000000000"
}
}
如果我们检查一下v1
和v2
两个版本的httpbin
服务的所属Pod的日志,会发现只有v1
版本的Pod中出现了访问记录:
$ kubectl logs -f httpbin-v1-2113278084-98whj -c httpbin
127.0.0.1 - - [07/Feb/2018:00:07:39 +0000] "GET /headers HTTP/1.1" 200 349 "-" "curl/7.35.0"
创建到v2
的镜像
cat <<EOF | istioctl create -f -
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: mirror-traffic-to-httbin-v2
spec:
destination:
name: httpbin
precedence: 11
route:
- labels:
version: v1
weight: 100
- labels:
version: v2
weight: 0
mirror:
name: httpbin
labels:
version: v2
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'
我们会在v1
和v2
两个版本的Pod中都看到访问记录。v2
中看到的访问日志实际上是访问v1
的流量的镜像引发的。
清理
删除规则
istioctl delete routerule mirror-traffic-to-httbin-v2
istioctl delete routerule httpbin-default-v1
关闭httpbin服务和客户端。
kubectl delete deploy httpbin-v1 httpbin-v2 sleep
kubectl delete svc httpbin
下一步
阅读镜像配置参考,可以获得更多流量复制配置方面的信息。