概述
全链路灰度是基于流量标签功能,在微服务整个调用链中进行统一的流量打标和治理,从而实现全链路灰度能力。本文介绍如何实现全链路灰度发布能力。
微服务调用关系
微服务架构中有三个服务,app1、app2、app3,调用关系如下图,入口由Ingress网关做流量分发,要实现全链路灰度,预期是可以实现微服务之间只在在base版本内和test版本内调用,实现虚拟泳道。
前提条件
- 开通云容器引擎。
- 开通服务网格实例。
操作步骤
安装ingress gateway
登录控制台,选择对应的服务网格,进入网格页面后,通过左边栏的“网关”一栏选择“入口网关”。
进入网关页面后,选择集群和命名空间后可以创建网关。
填入详细的参数后,点确认即可。如图:
部署应用
在云容器引擎集群内创建demo命名空间,部署base版本和test版本应用。
apiVersion: apps/v1
kind: Deployment
metadata:
name: app1-base
namespace: demo
labels:
app: app1
csm-traffic-tag: base
spec:
replicas: 1
selector:
matchLabels:
app: app1
name: app1
csm-traffic-tag: base
template:
metadata:
labels:
sidecar.istio.io/inject: "true"
app: app1
name: app1
source: CCSE
csm-traffic-tag: base
spec:
containers:
- name: default
image: registry-vpc-crs-huadong1.cnsp-internal.ctyun.cn/library/trace-demo:v1.0.0
imagePullPolicy: IfNotPresent
env:
- name: version
value: base
- name: app
value: app1
- name: upstream_url
value: "http://app2:8000/"
ports:
- containerPort: 8000
--
apiVersion: apps/v1
kind: Deployment
metadata:
name: app2-base
namespace: demo
labels:
app: app2
csm-traffic-tag: base
spec:
replicas: 1
selector:
matchLabels:
app: app2
name: app2
csm-traffic-tag: base
template:
metadata:
labels:
sidecar.istio.io/inject: "true"
app: app2
name: app2
source: CCSE
csm-traffic-tag: base
spec:
containers:
- name: default
image: registry-vpc-crs-huadong1.cnsp-internal.ctyun.cn/library/trace-demo:v1.0.0
imagePullPolicy: IfNotPresent
env:
- name: version
value: base
- name: app
value: app2
- name: upstream_url
value: "http://app3:8000/"
ports:
- containerPort: 8000
--
apiVersion: apps/v1
kind: Deployment
metadata:
name: app3-base
namespace: demo
labels:
app: app3
csm-traffic-tag: base
spec:
replicas: 1
selector:
matchLabels:
app: app3
name: app3
csm-traffic-tag: base
template:
metadata:
labels:
sidecar.istio.io/inject: "true"
app: app3
name: app3
source: CCSE
csm-traffic-tag: base
spec:
containers:
- name: default
image: registry-vpc-crs-huadong1.cnsp-internal.ctyun.cn/library/trace-demo:v1.0.0
imagePullPolicy: IfNotPresent
env:
- name: version
value: base
- name: app
value: app3
ports:
- containerPort: 8000
test版本:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app1-test
namespace: demo
labels:
app: app1
csm-traffic-tag: test
spec:
replicas: 1
selector:
matchLabels:
app: app1
name: app1
csm-traffic-tag: test
template:
metadata:
labels:
sidecar.istio.io/inject: "true"
app: app1
name: app1
source: CCSE
csm-traffic-tag: test
spec:
containers:
- name: default
image: registry-vpc-crs-huadong1.cnsp-internal.ctyun.cn/library/trace-demo:v1.0.0
imagePullPolicy: IfNotPresent
env:
- name: version
value: test
- name: app
value: app1
- name: upstream_url
value: "http://app2:8000/"
ports:
- containerPort: 8000
--
apiVersion: apps/v1
kind: Deployment
metadata:
name: app2-test
namespace: demo
labels:
app: app2
csm-traffic-tag: test
spec:
replicas: 1
selector:
matchLabels:
app: app2
name: app2
csm-traffic-tag: test
template:
metadata:
labels:
sidecar.istio.io/inject: "true"
app: app2
name: app2
source: CCSE
csm-traffic-tag: test
spec:
containers:
- name: default
image: registry-vpc-crs-huadong1.cnsp-internal.ctyun.cn/library/trace-demo:v1.0.0
imagePullPolicy: IfNotPresent
env:
- name: version
value: test
- name: app
value: app2
- name: upstream_url
value: "http://app3:8000/"
ports:
- containerPort: 8000
apiVersion: apps/v1
kind: Deployment
metadata:
name: app3-test
namespace: demo
labels:
app: app3
csm-traffic-tag: test
spec:
replicas: 1
selector:
matchLabels:
app: app3
name: app3
csm-traffic-tag: test
template:
metadata:
labels:
sidecar.istio.io/inject: "true"
app: app3
name: app3
source: CCSE
csm-traffic-tag: test
spec:
containers:
- name: default
image: registry-vpc-crs-huadong1.cnsp-internal.ctyun.cn/library/trace-demo:v1.0.0
imagePullPolicy: IfNotPresent
env:
- name: version
value: test
- name: app
value: app3
ports:
- containerPort: 8000
关联的Service资源:
apiVersion: v1
kind: Service
metadata:
name: app1
labels:
app: app1
service: app1
withServiceMesh: true
spec:
ports:
- port: 8000
name: http
selector:
app: app1
---
apiVersion: v1
kind: Service
metadata:
name: app2
labels:
app: app2
service: app2
withServiceMesh: true
spec:
ports:
- port: 8000
name: http
selector:
app: app2
---
apiVersion: v1
kind: Service
metadata:
name: app3
labels:
app: app3
service: app3
withServiceMesh: true
spec:
ports:
- port: 8000
name: http
selector:
app: app3
创建泳道组
我们的demo应用使用trace-ctx-id作为链路追踪的key,app1作为微服务的入口应用。
添加base和test泳道
确定网关的访问入口地址,设置为GATEWAY_HOST环境变量,执行如下语句访问:
for i in {1..100}; do curl http://${GATEWAY_HOST}/; echo; sleep 1; done;
可以看到访问在两个版本之间跳变,微服务之间的调用也是在版本间穿插进行,此时的全链路没有统一的路由策略。
请求带上x-csm-traffic-tag: base,同时指定请求级别的trace-ctx-id:
for i in {1..200}; do curl -H "x-csm-traffic-tag: base" -H "trace-ctx-id: trace-$i" [http://${GATEWAY_HOST}](); echo; sleep 1; done;
可以看到请求只在base版本之间调用:
修改头部x-csm-traffic-tag: test,可以看到请求只在test版本之间调用: