istio 1.10学习笔记10: Istio流量管理之流量镜像
2021-07-27
流量镜像,也叫称为影子流量,是指将实时流量的副本发送到镜像服务。镜像流量发生在主服务的关键请求路径之外。
本节将测试使用istio流量管理中的流量镜像功能。会在k8s的default命名空间内部署httpbin
服务的v1和v2两个版本,首先把流量全部路由到httpbin:v1
,然后执行规则将一部分流量镜像到v2版本。
部署服务并配置默认路由到v1版本 #
因为default命名空间在前面部署bookinfo应用时已经开启了istio sidecar的自动注入功能,所以这里直接部署httpbin
应用v1和v2的两个版本。
httpbin v1的deployment:
1cat <<EOF | kubectl create -f -
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5 name: httpbin-v1
6spec:
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
25EOF
httpbin v2的deployment:
1cat <<EOF | kubectl create -f -
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5 name: httpbin-v2
6spec:
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
25EOF
httpbin的k8s service:
1kubectl create -f - <<EOF
2apiVersion: v1
3kind: Service
4metadata:
5 name: httpbin
6 labels:
7 app: httpbin
8spec:
9 ports:
10 - name: http
11 port: 8000
12 targetPort: 80
13 selector:
14 app: httpbin
15EOF
创建httpbin的目标规则,并配置好v1和v2两个服务子集:
1kubectl apply -f - <<EOF
2apiVersion: networking.istio.io/v1alpha3
3kind: DestinationRule
4metadata:
5 name: httpbin
6spec:
7 host: httpbin
8 subsets:
9 - name: v1
10 labels:
11 version: v1
12 - name: v2
13 labels:
14 version: v2
15EOF
为了能从集群外部访问httpbin,给它创建一个Ingress Gateway:
1kubectl apply -f - <<EOF
2apiVersion: networking.istio.io/v1alpha3
3kind: Gateway
4metadata:
5 name: httpbin-gateway
6spec:
7 selector:
8 istio: ingressgateway # use istio default controller
9 servers:
10 - port:
11 number: 80
12 name: http
13 protocol: HTTP
14 hosts:
15 - httpbin.example.com
16 tls:
17 httpsRedirect: true
18 - port:
19 number: 443
20 name: https
21 protocol: HTTPS
22 tls:
23 mode: SIMPLE
24 credentialName: bookinfo-credential # must be the same as secret
25 hosts:
26 - httpbin.example.com
27EOF
这里将使用二级域名httpbin.example.com
作为入口,因为前面为bookinfo应用创建Gateway时创建好的证书bookinfo-credential里是*.example.com
的通配证书,这里直接使用这个证书bookinfo-credential。
接下来为httpbin服务创建虚拟服务,并与上面创建的gateway关联,创建好入口路由规则:
1kubectl apply -f - <<EOF
2apiVersion: networking.istio.io/v1alpha3
3kind: VirtualService
4metadata:
5 name: httpbin
6spec:
7 gateways:
8 - httpbin-gateway
9 hosts:
10 - httpbin.example.com
11 http:
12 - route:
13 - destination:
14 host: httpbin
15 port:
16 number: 8000
17 subset: v1
18 weight: 100
19EOF
此时从入口域名httpbin.example.com
访问httpbin服务时,所有的流量都将被路由到httpbin:v1
。
在集群外部访问https://httpbin.example.com/headers
,正常返回信息:
1curl https://httpbin.example.com/headers
2{
3 "headers": {
4 "Accept": "*/*",
5 "Host": "httpbin.example.com",
6 "User-Agent": "curl/7.64.1",
7 "X-B3-Parentspanid": "f11310681322428c",
8 "X-B3-Sampled": "1",
9 "X-B3-Spanid": "d7d9533be9694d50",
10 "X-B3-Traceid": "7fad3179541ed266f11310681322428c",
11 "X-Envoy-Attempt-Count": "1",
12 "X-Envoy-Internal": "true",
13 "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/default;Hash=6bbc6b64389016a1ed1dcf2219cfb8e626021e6e1d54205e586441ac15b2b7f5;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"
14 }
15}
此时在k8s中分别查看httbin服务v1和v2两个版本pod的日志,发现v1有访问日志,v2没有访问日志,说明上面配置生效,目前是所有的流量都被配置路由到了httpbin v1上。
1export V1_POD=$(kubectl get pod -l app=httpbin,version=v1 -o jsonpath={.items..metadata.name})
2kubectl logs "$V1_POD" -c httpbin
3
4127.0.0.6 - - [27/Jul/2021:14:05:19 +0000] "GET /headers HTTP/1.1" 200 599 "-" "curl/7.64.1"
5
6export V2_POD=$(kubectl get pod -l app=httpbin,version=v2 -o jsonpath={.items..metadata.name})
7kubectl logs "$V2_POD" -c httpbin
8
9无访问日志打印
镜像流量到v2版本 #
接下来改变httpbin虚拟服务中的路由规则,配置镜像100%的流量到v2版本:
1kubectl apply -f - <<EOF
2apiVersion: networking.istio.io/v1alpha3
3kind: VirtualService
4metadata:
5 name: httpbin
6spec:
7 gateways:
8 - httpbin-gateway
9 hosts:
10 - httpbin.example.com
11 http:
12 - route:
13 - destination:
14 host: httpbin
15 port:
16 number: 8000
17 subset: v1
18 weight: 100
19 mirror:
20 host: httpbin
21 subset: v2
22 mirrorPercentage:
23 value: 100.0
24EOF
现在这个是虚拟服务的路由规则是将100%的流量路由到httpbin:v1
,同时将100%的相同流量镜像到httpbin:v2
。
需要注意,当流量被镜像时,请求将发送到镜像服务,并在headers中的Host/Authority
属性值上追加-shadow
。例如cluster-1
变为cluster-1-shadow
,
另外注意镜像的流量是即发即弃的,就是说镜像请求的响应会被丢弃。
此时在集群外部访问https://httpbin.example.com/headers
,在k8s中分别查看httbin服务v1和v2两个版本pod的日志,发现两个版本的pod都有访问日志。
总结 #
流量镜像(Traffic Mirroring),也称为影子流量(Traffic Shadowing), 是一种强大的、无风险的测试应用版本的方法,它将实时流量的副本发送给被镜像的服务。 使用流量镜像,可以搭建一个与原环境类似的环境以进行验收测试,从而提前发现问题。 由于镜像流量存在于主服务关键请求路径带外,终端用户在测试全过程不会受到影响。另外在使用流量镜像之前,必须确认镜像服务连接的数据状态存储(例如数据库等)是独立的,避免污染关键请求路径上的状态存储。