本小节主要讲解istio的流量镜像能力。
流量镜像(Traffic mirroring),也称为“影子”(shadowing),是一个功能强大的概念,允许功能团队以尽可能小的风险将更改带到生产环境中。镜像将实时通信的副本发送到镜像服务。镜像通信发生在主服务的关键请求路径的带外。
在此任务中,您将首先强制所有流量到测试服务的v1。然后,您将应用一个规则来将一部分流量映射到v2。
1. 准备工作
首先部署两个启用了访问日志记录的httpbin服务版本:
- httpbin-v1:
$ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v1
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
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:80", "httpbin:app"]
ports:
- containerPort: 80
EOF
- httpbin-v2:
$ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v2
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v2
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:80", "httpbin:app"]
ports:
- containerPort: 80
EOF
- httpbin kubernetes服务:
$ kubectl create -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 80
selector:
app: httpbin
EOF
- 启动sleep的服务,才能使用curl
$ cat <<EOF | istioctl kube-inject -f - | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: sleep
spec:
replicas: 1
selector:
matchLabels:
app: sleep
template:
metadata:
labels:
app: sleep
spec:
containers:
- name: sleep
image: tutum/curl
command: ["/bin/sleep","infinity"]
imagePullPolicy: IfNotPresent
EOF
2. 创建默认的路由策略
默认情况下,Kubernetes在两个版本的httpbin服务之间进行负载平衡。在此步骤中,您将更改该行为,以便所有流量都转到v1。
- 创建默认的路由规则去路由所有流量到v1
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin
http:
- route:
- destination:
host: httpbin
subset: v1
weight: 100
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
EOF
- 发送一些流量到服务进行测试
$ 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 - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin
http:
- route:
- destination:
host: httpbin
subset: v1
weight: 100
mirror:
host: httpbin
subset: v2
mirror_percent: 100
EOF
此路由规则将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