API 网关深度集成火山引擎容器服务 VKE,可实时动态获取 VKE 集群中部署的 K8S Service 信息,作为 K8S Service 对外提供服务的流量入口。同时,API 网关提供 Upstream 和流量权重能力,方便用户进行服务的灰度发布,实现敏捷迭代、平滑升级。本文为您介绍如何通过 API 网关实现容器服务中应用的蓝绿部署和灰度发布。
为了保证服务稳定地对外提供服务,各企业都十分重视发布策略的选择。目前被业界广泛采用的服务发布策略有蓝绿部署和灰度发布,请根据实际情况选择适合的发布策略。
本文通过配置 2 个服务,为您演示容器服务集群中应用的蓝绿部署和灰度发布。该服务已提供一个查询当前版本的接口,请求路径为/version
。用户发送请求后,API 网关可将请求按照 Header 或权重转发至不同的服务,实现应用的多版本流量管理。
容器服务 VKE
API 网关
使用如下 YAML 配置,在容器服务集群中部署 v1 版本应用和服务。
apiVersion: v1 kind: Service metadata: name: service-old namespace: default spec: ports: - name: port port: 80 targetPort: 80 protocol: TCP selector: app: old type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: app-old namespace: default spec: replicas: 2 selector: matchLabels: app: old template: metadata: labels: app: old spec: containers: - image: cr-apig-cn-beijing.cr.volces.com/apig-demo/http-server:v1 name: demo ports: - containerPort: 80
使用如下 YAML 配置,在集群中创建 Ingress。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-old namespace: default spec: ingressClassName: apig rules: - host: apig-example.com http: paths: - backend: service: name: service-old port: number: 80 path: /version pathType: Exact
执行以下命令,进行 10 次访问测试。
for i in {1..10}; do curl apig-example.com/version;echo;done
预期结果如下,所有请求均成功转发至 v1 版本应用。
{"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"}
使用如下 YAML 配置,在容器服务集群中部署 v2 版本应用和服务。
注意
使用 API 网关实例发布容器服务集群中的应用,支持同集群部署和跨集群部署。
apiVersion: v1 kind: Service metadata: name: service-new namespace: default spec: ports: - name: port port: 80 targetPort: 80 protocol: TCP selector: app: new type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: app-new spec: replicas: 1 selector: matchLabels: app: new template: metadata: labels: app: new spec: containers: - image: cr-apig-cn-beijing.cr.volces.com/apig-demo/http-server:v2 name: demo ports: - containerPort: 80
使用如下 YAML 配置,在集群中为新版本服务创建 Ingress。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/canary: 'true' # 开启灰度发布 nginx.ingress.kubernetes.io/canary-by-header: 'foo' nginx.ingress.kubernetes.io/canary-by-header-value: 'bar' # headers 中包含 foo=bar 时,转发至 v2 版本的服务。不带此 header 时,转发至 v1 版本的服务 name: ingress-new namespace: default spec: ingressClassName: apig rules: - host: apig-example.com http: paths: - backend: service: name: service-new port: number: 80 path: /version pathType: Exact
执行以下命令,不带 Header 进行 10 次访问测试。
for i in {1..10}; do curl apig-example.com/version;echo;done
预期结果如下,所有请求均成功转发至 v1 版本应用。
{"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"}
执行以下命令,带 Header 进行 10 次访问测试。
for i in {1..10}; do curl -H "foo:bar" ${网关服务域名}/version;echo;done
预期结果如下,所有请求均成功转发至 v2 版本应用。
{"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v2"}
综上结果可以发现,两条路由都通过 apig-example.com/version
访问,如果带 Header(foo=bar),则转发至 v2 版本服务;否则转发至 v1 版本服务。实现了基于 Header 的灰度发布。
注意
在真实业务场景中,新版本验证完毕后,便可继续调大访问新版本的流量权重。期间注意对新版本扩容,按需对旧版本缩容。
使用如下 YAML 配置,在容器服务集群中部署 v1 版本应用和服务。
apiVersion: v1 kind: Service metadata: name: service-old namespace: default spec: ports: - name: port port: 80 targetPort: 80 protocol: TCP selector: app: old type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: app-old namespace: default spec: replicas: 2 selector: matchLabels: app: old template: metadata: labels: app: old spec: containers: - image: cr-apig-cn-beijing.cr.volces.com/apig-demo/http-server:v1 name: demo ports: - containerPort: 80
使用如下 YAML 配置,在集群中创建 Ingress。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-old namespace: default spec: ingressClassName: apig rules: - host: apig-example.com http: paths: - backend: service: name: service-old port: number: 80 path: /version pathType: Exact
执行以下命令,进行 10 次访问测试。
for i in {1..10}; do curl apig-example.com/version;echo;done
预期结果如下,所有请求均成功转发至 v1 版本应用。
{"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"}
使用如下 YAML 配置,在容器服务集群中部署 v2 版本应用和服务。
注意
使用 API 网关实例发布容器服务集群中的应用,支持同集群部署和跨集群部署。
apiVersion: v1 kind: Service metadata: name: service-new namespace: default spec: ports: - name: port port: 80 targetPort: 80 protocol: TCP selector: app: new type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: app-new spec: replicas: 1 selector: matchLabels: app: new template: metadata: labels: app: new spec: containers: - image: cr-apig-cn-beijing.cr.volces.com/apig-demo/http-server:v2 name: demo ports: - containerPort: 80
使用如下 YAML 配置,在集群中为新版本服务创建 Ingress。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/canary: 'true' # 开启灰度发布 nginx.ingress.kubernetes.io/canary-weight: '30' # 配置流量权重,将 30% 的流量转发至 v2 服务,70% 的流量转发至 v1 服务 name: ingress-new namespace: default spec: ingressClassName: apig rules: - host: apig-example.com http: paths: - backend: service: name: service-new port: number: 80 path: /version pathType: Exact
执行以下命令,进行 10 次访问测试。
for i in {1..10}; do curl apig-example.com/version;echo;done
预期结果如下,10 个请求中有 3 个请求转发至新版本 v2,流量比符合预期。
{"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v1"} {"code": 200, "message": "version: v2"} {"code": 200, "message": "version: v1"}
注意
在真实业务场景中,新版本验证完毕后,便可继续调大访问新版本的流量权重。期间注意对新版本扩容,按需对旧版本缩容。