应用服务网格

全链路灰度功能体验

2025-08-14 02:03:24

全链路灰度是基于流量标签功能,在微服务整个调用链中进行统一的流量打标和治理,从而实现全链路灰度能力。本文介绍如何实现全链路灰度发布能力。

微服务调用关系

微服务架构中有三个服务,app1app2app3,调用关系如下图,入口由Ingress网关做流量分发,要实现全链路灰度,预期是可以实现微服务之间只在在base版本内和test版本内调用,实现虚拟泳道。


前提条件:

1. 开通云容器引擎

2. 开通服务网格实例

操作步骤:

1)安装ingress gateway

登录控制台,选择对应的服务网格,进入网格页面后,通过左边栏的“网关”一栏选择“入口网关”

进入网关页面后,选择集群和命名空间后可以创建网关

填入详细的参数后,点确认即可。如图:


2)部署应用

在云容器引擎集群内创建demo命名空间,部署base版本和test版本应用

base版本:

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

 

3)创建泳道组


我们的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版本之间调用: