istio 0.5.0 新特性:流量镜像
在类似 Dark launch 的测试、发布过程中,流量复制是个非常有用的功能,istio 0.5.0 的更新,带来了一个新的路由相关特性:流量镜像。
这一场景中,我们会将正常的流量进行复制,将复制出来的流量分发给待上线的应用(V2),使用实际流量对新版本应用进行测试;而现有客户端则仅会感知到单一版本(V1)的存在。
下面做个小实验来进行验证。
条件
基于 Kubernetes 运行的 Istio 0.5.0 版本部署。
部署
源码见后。
用nginx:stabel-alpine
镜像,生成v1
和v2
两个版本的 Deployment,以及一个target
服务:
istioctl kube-inject -f v1.deploy.yaml| kubectl apply -f -
istioctl kube-inject -f v2.deploy.yaml| kubectl apply -f -
kubectl apply -f service.yaml
用dustise/sleep
镜像作为客户端服务,来制造请求访问目标服务。
istioctl kube-inject -f sleep.yaml | kubectl apply -f -
使用kubectl get po
验证 Pod 生成情况,就绪之后开始进行验证。
NAME READY STATUS RESTARTS AGE
sleep-6f569f4c9-hs6wx 2/2 Running 0 10m
target-v1-7f78d974c-mfhzz 2/2 Running 0 1h
target-v2-5886cd585d-tr22d 2/2 Running 0 1h
验证
初始化
首先我们生成一个缺省路由,将全部流量引入 v1:
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: rule-all-http
spec:
destination:
name: target
precedence: 1
route:
- labels:
app: target
version: v1
weight: 100
使用kubectl apply -f rules.yaml
应用这一规则。
接下来监控 nginx 的访问日志:
kubectl logs -f [v1-pod] -c nginx
kubectl logs -f [v2-pod] -c nginx
或者可以使用
kubetail
工具:kubetail target -c nginx
,对部署内容的日志进行监控。
kubectl exec -it [sleep-pod] -c sleep bash
进入客户端服务 Pod,执行curl http://target
,会看到在 v1
Pod 中出现了访问迹象:
[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:28:30 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.38.0" "-"
[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:28:31 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.38.0" "-"
[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:28:32 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.38.0" "-"
开始镜像
修改路由规则:
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: rule-all-http
spec:
destination:
name: target
precedence: 1
route:
- labels:
app: target
version: v1
weight: 100
- labels:
app: target
version: v2
weight: 0
mirror:
name: target
labels:
app: target
version: v2
注意这里为 v2
建立了一个权重为 0
的路由项,这是一个硬性规定,启用 mirror
的路由必须要在上面的 route
中具备一致的入口,以此通知 Envoy 进行相应的数据面操作。
使用 kubectl apply -f rules.yaml
来更新路由规则。
再次在客户端 Pod 中访问 target
服务,会发现两个版本的 Pod 中都出现了访问日志,并且数量上是一一对应的:
[target-v2-5886cd585d-tr22d] 127.0.0.1 - - [12/Feb/2018:15:20:16 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.38.0" "10.240
.0.29"
[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:20:16 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.38.0" "-"
[target-v2-5886cd585d-tr22d] 127.0.0.1 - - [12/Feb/2018:15:20:17 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.38.0" "10.240
.0.29"
[target-v1-7f78d974c-mfhzz] 127.0.0.1 - - [12/Feb/2018:15:20:17 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.38.0" "-"
从语法来看,仅支持一个复制
源码
v1.deploy.yaml
将 v1
替换成 v2
生成另外一个部署。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: target-v1
spec:
replicas: 1
template:
metadata:
labels:
app: target
version: v1
spec:
containers:
- image: nginx:stable-alpine
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
sleep.yaml
apiVersion: v1
kind: Service
metadata:
name: target
labels:
app: target
spec:
ports:
- name: http
port: 80
selector:
app: target
sleep.yaml
apiVersion: v1
kind: Service
metadata:
name: sleep
labels:
app: sleep
version: v1
spec:
selector:
app: sleep
version: v1
ports:
- name: ssh
port: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: sleep
spec:
replicas: 1
template:
metadata:
labels:
app: sleep
version: v1
spec:
containers:
- name: sleep
image: dustise/sleep
imagePullPolicy: IfNotPresent
---