5.3.7 流量镜像

流量镜像,也称为影子流量,是一个以尽可能低的风险为生产带来变化的强大的功能。服务新版本上线时,对服务的性能和bug并没有太大把握,流量镜像会将实时流量的副本发送到镜像服务。镜像流量发生在主服务的关键请求路径之外。

任务:把流量全部路由到v1版本的测试服务。然后,执行规则将一部分流量镜像到v2版本。

1.前置条件

1.安装好Istio 2.部署两个版本的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
deployment.apps/httpbin-v1 created

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
deployment.apps/httpbin-v2 created

httpbin service

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
service/httpbin created

3.启动sleep服务,这样就可以使用curl来提供负载

sleep service

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: curlimages/curl
        command: ["/bin/sleep","3650d"]
        imagePullPolicy: IfNotPresent
EOF
deployment.apps/sleep created

2.创建一个默认路由策略

默认情况下,Kubernetes在httpbin服务的两个版本之间进行负载均衡。在此步骤中会更改该行为,把所有流量都路由到v1版本。

1.创建一个默认路由规则,将所有流量路由到服务的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
virtualservice.networking.istio.io/httpbin created
destinationrule.networking.istio.io/httpbin created

现在所有流量都转到httpbin:v1服务。

2.向服务发送一部分流量

export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
kubectl exec -it "$SLEEP_POD" -c sleep -- curl -sS http://httpbin:8000/headers
{
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin:8000",
    "User-Agent": "curl/7.35.0",
    "X-B3-Parentspanid": "91ffa12314782a09",
    "X-B3-Sampled": "1",
    "X-B3-Spanid": "012952154e90d7cb",
    "X-B3-Traceid": "70956ad857e4bfd191ffa12314782a09",
    "X-Envoy-Attempt-Count": "1",
    "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/default;Hash=bc31ed168cab2d9b5e0bd47ddf3f0b3cbbc995c9323357dca0de153b4293dfe3;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default"
  }
}

3.分别查看httpbin pod的v1v2两个版本的日志,可以看到只有v1版本的访问日志条目。

export V1_POD=$(kubectl get pod -l app=httpbin,version=v1 -o jsonpath={.items..metadata.name})
kubectl logs "$V1_POD" -c httpbin

export V2_POD=$(kubectl get pod -l app=httpbin,version=v2 -o jsonpath={.items..metadata.name})
kubectl logs "$V2_POD" -c httpbin

3.流量镜像到v2

1.改变流量规则将流量镜像到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
    mirrorPercentage:
      value: 100.0
EOF
virtualservice.networking.istio.io/httpbin configured

这个路由规则发送100%流量到v1版本。最后一节表示您将100%的相同流量镜像(即发送)到httpbin:v2服务。当流量被镜像时,请求将发送到镜像服务中,并在headers中的Host/Authority属性值上追加-shadow。例如cluster-1变为cluster-1-shadow

此外,重点注意这些被镜像的流量是『 即发即弃』的,就是说镜像请求的响应会被丢弃。

您可以使用mirrorPercentage下的value属性来设置镜像流量的百分比,而不是镜像全部请求。为了兼容老版本,如果这个属性不存在,将镜像所有流量。

2.发送流量测试

kubectl exec -it "${SLEEP_POD}" -c sleep -- curl -sS http://httpbin:8000/headers
{
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin:8000",
    "User-Agent": "curl/7.35.0",
    "X-B3-Parentspanid": "a60a327f14ed15f3",
    "X-B3-Sampled": "1",
    "X-B3-Spanid": "ee6beda1c7ba4061",
    "X-B3-Traceid": "1212719a8fbb98e1a60a327f14ed15f3",
    "X-Envoy-Attempt-Count": "1",
    "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/default;Hash=bc31ed168cab2d9b5e0bd47ddf3f0b3cbbc995c9323357dca0de153b4293dfe3;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default"
  }
}

现在就可以看到v1v2版本中都有了访问日志。v2版本中的访问日志就是由镜像流量产生的,这些请求的实际目标是v1版本。

kubectl logs "$V1_POD" -c httpbin

kubectl logs "$V2_POD" -c httpbin

4.清理

1.清楚规则

kubectl delete virtualservice httpbin
kubectl delete destinationrule httpbin

2.关闭Httpbin服务和客户端

kubectl delete deploy httpbin-v1 httpbin-v2 sleep
kubectl delete svc httpbin
Copyright © huangzhongde.cn 2021 all right reserved,powered by Gitbook该文件修订时间: 2022-01-28 00:02:24

results matching ""

    No results matching ""