Istio DestinationRule dr
来源:原创
时间:2022-03-01
作者:脚本小站
分类:云原生
灰度发布
流量示例:
根据权重将流量划分到v1和v2上:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: forecast-route namespace: weather spec: hosts: - forecast http: - route: - destination: host: forecast subset: v1 weight: 0 # 根据权重分配流量 - destination: host: forecast subset: v2 weight: 100 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: forecast-dr spec: host: forecast subsets: - name: v1 labels: version: v1 # 根据不同的标签来选着服务 - name: v2 labels: version: v2 --- # 对应v1、v2的服务 apiVersion: apps/v1 kind: Deployment metadata: name: forecast-v2 labels: app: forecast version: v2 spec: replicas: 1 selector: matchLabels: app: forecast version: v2 template: metadata: labels: app: forecast version: v2 spec: containers: - name: forecast image: istioweather/forecast:v2 imagePullPolicy: IfNotPresent ports: - containerPort: 3002 --- apiVersion: apps/v1 kind: Deployment metadata: name: forecast-v1 labels: app: forecast version: v1 spec: replicas: 1 selector: matchLabels: app: forecast version: v1 template: metadata: labels: app: forecast version: v1 spec: containers: - name: forecast image: istioweather/forecast:v2 imagePullPolicy: IfNotPresent ports: - containerPort: 3002
根据浏览器路由到不同服务
vs文件:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: forecast-route namespace: weather spec: hosts: - forecast http: - match: - headers: User-Agent: # 区分不同的浏览器 regex: .*(Chrome/([\d.]+)).* # Chrome浏览器到v2 route: - destination: host: forecast subset: v2 - route: # 其余浏览器流量都到v1 - destination: host: forecast subset: v1
dr文件:
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: forecast-dr spec: host: forecast subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 --- apiVersion: apps/v1 kind: Deployment metadata: name: forecast-v2 labels: app: forecast version: v2 spec: replicas: 1 selector: matchLabels: app: forecast version: v2 template: metadata: labels: app: forecast version: v2 spec: containers: - name: forecast image: istioweather/forecast:v2 imagePullPolicy: IfNotPresent ports: - containerPort: 3002
根据不同客户端分配流量
安卓端 v1、v2 流量各 50% ,其余客户端流量均给到 v1 版本。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: frontend-route namespace: weather spec: hosts: - "*" gateways: - istio-system/weather-gateway http: - match: # 安卓端的流量v1、v2各50% - headers: User-Agent: regex: .*((Android)).* route: - destination: host: frontend subset: v1 weight: 50 - destination: host: frontend subset: v2 weight: 50 - route: # 其余客户端流量都给到 v1 - destination: host: frontend subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: frontend-dr spec: host: frontend subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 --- apiVersion: apps/v1 kind: Deployment metadata: name: frontend-v2 labels: app: frontend version: v2 spec: replicas: 1 selector: matchLabels: app: frontend version: v2 template: metadata: labels: app: frontend version: v2 spec: containers: - name: frontend image: istioweather/frontend:v2 imagePullPolicy: IfNotPresent ports: - containerPort: 3000
根据用户名路由流量
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: frontend-route spec: hosts: - "*" gateways: - istio-system/weather-gateway http: - match: # 如果用户名匹配则路由到v2 - headers: cookie: regex: ^(.*?;)?(user=tester)(;.*)?$ route: - destination: host: frontend subset: v2 - route: # 其余流量路由到 v1 - destination: host: frontend subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: frontend-dr spec: host: frontend subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2
集群流量策略
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: demoapp spec: host: demoapp trafficPolicy: # 全局流量策略 loadBalancer: simple: LEAST_CONN # 调度算法 subsets: - name: v10 labels: version: v1.0 trafficPolicy: # 子集流量策略 loadBalancer: consistentHash: httpHeaderName: X-User # 根据标头值调度给同一个Pod - name: v11 labels: version: v1.1 --- # 用到的vs apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: demoapp spec: hosts: - demoapp http: - name: canary match: - uri: prefix: /canary rewrite: uri: / route: - destination: host: demoapp subset: v11 - name: default route: - destination: host: demoapp subset: v10
测试:相同的x-user的值会调度给相同的Pod,是Pod不是dm。
root@client # curl -H "X-User: user19" demoapp:8080 iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-5c497c6f7c-k6vpw, ServerIP: 10.244.5.206! root@client # curl -H "X-User: user19" demoapp:8080 iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-5c497c6f7c-k6vpw, ServerIP: 10.244.5.206! root@client # root@client # root@client # curl -H "X-User: user20" demoapp:8080 iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-5c497c6f7c-76gs7, ServerIP: 10.244.3.207! root@client # curl -H "X-User: user20" demoapp:8080 iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-5c497c6f7c-76gs7, ServerIP: 10.244.3.207!
断路器:将不健康的服务弹出去
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: demoapp spec: host: demoapp trafficPolicy: # 这里定义在了全局 loadBalancer: simple: RANDOM connectionPool: # 连接池 tcp: maxConnections: 100 connectTimeout: 30ms tcpKeepalive: time: 7200s interval: 75s http: http2MaxRequests: 1000 maxRequestsPerConnection: 10 outlierDetection: maxEjectionPercent: 50 # 最大弹出比例 consecutive5xxErrors: 5 # 连续5次出现5xx错误就弹出主机 interval: 10s # 每多长时间检测一次 baseEjectionTime: 1m # 服务被弹出的时长 minHealthPercent: 40 # 健康主机小于40%禁用弹出 subsets: - name: v10 labels: version: v1.0 - name: v11 labels: version: v1.1
服务故障测试:通过下面方法将服务的返回码改成5xx,模拟某个Pod或服务出现了故障。
curl -XPOST -d 'livez=FAIT' PodIP:port/livez
外部请求测试:连续请求5次失败之后就会将该Pod提出,一分钟后再加进来,在检测出5次错误再提出,两分钟后再加进来,再检测到5次错误再提出,三分钟后再加进来......。
~]# while true; do curl demoapp.ops.net/livez; sleep 0.$RANDOM; done Proxying value: FAIT - Took 27 milliseconds. Proxying value: OK - Took 22 milliseconds. Proxying value: OK - Took 12 milliseconds. Proxying value: OK - Took 30 milliseconds. Proxying value: FAIT - Took 13 milliseconds. Proxying value: FAIT - Took 25 milliseconds.
服务恢复正常测试:服务正常后就会加入到正常服务列表中。
curl -XPOST -d 'livez=OK' PodIP:port/livez
灰度发布示例
基础灰度发布示例:
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: grayscale namespace: default spec: selector: istio: ingressgateway servers: - hosts: - grayscale.ops.net port: name: http number: 80 protocol: HTTP --- apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: grayscale namespace: default spec: gateways: - grayscale hosts: - grayscale.ops.net http: - match: - uri: prefix: / route: - destination: host: grayscale subset: v1 port: number: 80 weight: 100 # 根据权重分配流量 - destination: host: grayscale subset: v2 port: number: 80 weight: 0 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: grayscale spec: host: grayscale subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: grayscale name: grayscale-v1 namespace: default spec: selector: matchLabels: app: grayscale version: v1 strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: app: grayscale version: v1 spec: containers: - image: m.daocloud.io/docker.io/kong/httpbin imagePullPolicy: IfNotPresent name: httpbin --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: grayscale name: grayscale-v2 namespace: default spec: selector: matchLabels: app: grayscale version: v2 strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: app: grayscale version: v2 spec: containers: - image: temperature-app:latest imagePullPolicy: IfNotPresent name: temperature --- apiVersion: v1 kind: Service metadata: labels: app: grayscale name: grayscale namespace: default spec: ports: port: 80 protocol: TCP targetPort: 80 selector: # 这里不要选着版本 app: grayscale type: ClusterIP