开发者可以通过kuberneters annotation,很容易控制服务的流量,实现灰度发布

应用场景

  1. 微服务各组件独立更新,然后验证又必须在实际环境中进行
  2. 部署新功能有风险,然后可以通过导流一小部分用户实际使用,来减小风险
  3. 依赖的第三方组件,无法很好地进行测试,只能依靠实际的使用,来验证是否能成功的对接。

过程

  1. 部署v2版本,定义导量1%
  2. 测试(请求多少次,有木有失败之类的,由业务方决定),观测和监控
  3. 没有问题则v2 100%(没有迭代的过程,区别滚动部署),下线v1版本

架构图

架构图

工作流程
  • service annotation中定义配置,Kubernetes API 异步通知 Ambassador 的更改。
  • Ambassador 将配置转换为抽象的中间代码 (IR)。
  • 从 IR 中生成一个 Envoy 配置文件。
  • 使用 Ambassador 验证 Envoy 配置文件。
  • 如果配置文件有效,Ambassador 将使用 Envoy 的热重新启动机制来部署新的配置,并保持连接。
  • 流量将会在新启动的 Envoy 进程中传输。

功能描述

Self-Service via Kubernetes Annotations

developer可以通过kubernetes service 的annotations来定义ambassadorf服务,很容易集成到你的现有项目中。

Flexible Canary Deployments

developer可以通过kuberneters annotation很容易控制到服务的流量,实现金丝雀发布。

Kubernetes-Native Architecture

利用k8s原生能力实现可靠性、可用性和可伸缩性。使用envoy实现路由和代理

gRPC and HTTP/2 Support

由envoy提供的能力

Istio Integration

和istio配合实现服务网格。ambassador作为边缘代理,实现外部流量到内部istio的桥梁。

Authentication

ambassador支持请求认证。如果配置了,ambassador在路由之前会事先请求第三方认证服务

Rate Limiting

ambassador支持限流。ambassador在路由之前会事先请求第三方速度限流服务

Integrated Diagnostics

ambassador包含一个诊断服务,可以快速定位问题

部署

install deploy

测试

提前部署两个后台服务 sv1 和 sv2

sv1 请求返回"Hello World, this is test service num 1!"
sv2 请求返回"Hello World, this is test service num 2!"

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: svc1
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: svc1
    spec:
      containers:
      - name: svc1
        image: ambassador-sv1:1.0
        ports:
        - name: http-api
          containerPort: 5000
        resources:
          limits:
            cpu: "0.1"
            memory: 100Mi
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: svc2
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: svc2
    spec:
      containers:
      - name: svc2
        image: ambassador-sv2:1.0
        ports:
        - name: http-api
          containerPort: 5000
        resources:
          limits:
            cpu: "0.1"
            memory: 100Mi

根据weight进行灰度

以80%的概率路由到svc1, 20%的概率路由到svc2

svc1 (不配置权重,默认100%)

---
apiVersion: v1
kind: Service
metadata:
  name: svc1
  namespace: 295-a222222
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  svc1_mapping
      prefix: /svc/
      service: svc1.295-a222222:8080
spec:
  selector:
    app: svc1
  ports:
  - port: 8080
    name: http-svc
    targetPort: http-api

svc2

---
apiVersion: v1
kind: Service
metadata:
  name: svc2
  namespace: 295-a222222
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  svc2_mapping
      prefix: /svc/
      service: svc2.295-a222222:8080
      weight: 20
spec:
  selector:
    app: svc2
  ports:
  - port: 8080
    name: http-svc
    targetPort: http-api

结果:

[root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 2![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 2![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 2![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl 

根据请求头 header 进行灰度 (regex_headers 正则匹配)

请求头中包含Cookie: UM_distinctid=12345的请求全部路由到svc2中

---
apiVersion: v1
kind: Service
metadata:
  name: svc2
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  svc2_mapping
      prefix: /svc/
      service: svc2
      headers:
        Cookie: UM_distinctid=12345
spec:
  selector:
    app: svc2
  ports:
  - port: 80
    name: http-svc2
    targetPort: http-api
regex_headers
apiVersion: v1
kind: Service
metadata:
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  create
      prefix: /svc/create/
      service: create:8080
      regex_headers:
        Cookie: "ddddd.*"

结果:

[root@master01 ambassador]# curl  10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl  10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl  10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl  10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# curl  10.104.75.142:80/svc/
Hello World, this is test service num 1![root@master01 ambassador]# 
[root@master01 ambassador]# 
[root@master01 ambassador]# curl -H "Cookie: UM_distinctid=12345" 10.104.75.142:80/svc/
Hello World, this is test service num 2![root@master01 ambassador]# curl -H "Cookie: UM_distinctid=12345" 10.104.75.142:80/svc/
Hello World, this is test service num 2![root@master01 ambassador]# curl -H "Cookie: UM_distinctid=12345" 10.104.75.142:80/svc/
Hello World, this is test service num 2![root@master01 ambassador]# curl -H "Cookie: UM_distinctid=12345" 10.104.75.142:80/svc/
Hello World, this is test service num 2![root@master01 ambassador]# curl -H "Cookie: UM_distinctid=12345" 10.104.75.142:80/svc/
Hello World, this is test service num 2![root@master01 ambassador]# curl -H "Cookie: UM_distinctid=12345" 10.104.75.142:80/svc/
Hello World, this is test service num 2![root@master01 ambassador]# 

业务灰度流程

当前业务

即需要更新的业务,此时业务流向全走向svc1

kubectl apply -f svc1.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc1
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  svc1_mapping
      prefix: /svc/
      service: svc1
spec:
  ····

查看ambassador的流量代理

url service weight
http://172.31.133.26:31327/svc/ svc1 100.0%

灰度版本

部署svc2.yaml,此时带header: Cookie: UM_distinctid=12345 流量走向svc2,不带header流量依旧走svc1。

kubectl apply -f svc2.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: svc2
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  svc2_mapping
      prefix: /svc/
      service: svc2
      headers:
        Cookie: UM_distinctid=12345
spec:
  ···

查看ambassador的流量代理

url service weight
http://172.31.133.26:31327/svc/ svc1 100.0%
http://172.31.133.26:31327/svc/
Cookie: UM_distinctid=12345
svc2 100.0%

流量切换

第一步

更新header(去掉header),此时一半流量到svc1,一半到svc2

kubectl apply -f svc2.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: svc2
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  svc2_mapping
      prefix: /svc/
      service: svc2
#      headers:
#        Cookie: UM_distinctid=12345
spec:
  ···

查看ambassador的流量代理

url service weight
http://172.31.133.26:31327/svc/ svc1
svc2
50.0%
100.0%

第二步

下线老的服务svc1,流量全部走到svc2

kubectl delete -f svc1.yaml

查看ambassador的流量代理

url service weight
http://172.31.133.26:31327/svc/ svc2 100.0%

manshu
65 声望9 粉丝

clear is better than clever