首页 > 其他分享 >原生Ingress灰度发布能力不够?我们是这么干的

原生Ingress灰度发布能力不够?我们是这么干的

时间:2022-11-30 20:02:54浏览次数:54  
标签:原生 Ingress 服务 demo echo 灰度 版本


灰度发布是一种常见的服务滚动升级或 A/B 测试策略。在新版本服务正式发布前,可以部署少量的新版本服务和上个版本共存,用部分生产流量测试新版本的功能和特性。如果新版本反馈良好,则可以渐进地提高新版本的比例或者全部替换成新版本,如果有问题也能够及时撤回,不至于造成太大范围的影响。

 

目前,原生容器发布基本都是使用 deployment,通过给 deployment 和 service 灵活配置 labels ,可以实现一种基于服务版本的灰度发布。

 

 

由于原生 Ingress 对象描述能力的限制,一些常见 Ingress controller 的灰度发布功能也大打折扣,很难满足用户灰度发布的实际需求。

 

博云基于原生Ingress,做了大量增强,基于请求特征的灰度发布是其中一个重要特性。

 

 

 

 

使用 deployment 实施灰度发布

 

 

 

 

通过配置 pod labels 和 service label selector,Kubernetes 原生支持灰度发布。假设我们部署了 echo-demo 服务的两个版本的 deployment:

 

> echo-demo-v1.yaml

 

     name: echo-demo-v1

     replicas: 3

     ...

     labels:

        app: echo-demo

        track: stable

     ...

     image: deploy.bocloud/ingress/echo-demo:1.0.0

 

> echo-demo-v2.yaml

 

     name: echo-demo-v2

     replicas: 2

     ...

     labels:

        app: echo-demo

        track: canary

     ...

     image: deploy.bocloud/ingress/echo-demo:2.0.0

 

以及一个 echo-demo service:

 

 apiVersion: v1

kind: Service

metadata:

  name: echo-demo

spec:

  ports:

    - port: 80

      protocol: TCP

      targetPort: 8080

  selector:

    app: echo-demo

 

上述配置中,echo-demo service 聚合了 echo-demo-v1 和 echo-demo-v2 两个版本的服务,两个版本分别有 3 个和 2 个实例。此时我们访问 echo-demo service,请求将根据实例数量的占比按 3:2 的比例分布到 v1 和 v2 两个服务中。这样就实现了基于权重的灰度发布。

 

然而这种灰度发布却自有其限制和问题。首先,如果我们给服务加上自动水平伸缩(HPA),那么两个版本的服务将完全根据各自的负载情况独立调整 pod 实例数量,这样一来两个版本的实例数量和比例就会发生变化,打破我们一开始设置的灰度比例。其次,如果我们只想配置很小比例的请求到灰度版本,比如 100:1,那么在最少提供一个灰度版本 pod 的前提下,需要配置最少 100 个旧版本实例,很不灵活。第三,除了按比例的灰度策略,有时可能还需要根据请求特征来辨别用户并分配灰度服务到其中的一小部分。由于deployment有着上述的缺陷,导致其很少被当做灰度使用的原因。所以在实际应用当中,灰度发布基本上 由ingress来做。而这几个问题,都可以通过使用 Ingress 灰度发布方案来解决。

 

 

 

Ingress 能描述灰度发布吗?

 

 

 

 

Ingress 是 Kubernetes 平台的一个原生 API,定义了 HTTP 路由到 Kubernetes service 的映射。Ingress Controller 依据 Ingress 对象的声明,动态生成负载均衡器的配置文件,由负载均衡器将 k8s 内部服务暴露出去,Nginx Ingress Controller 是使用最广泛的一个 Ingress 控制器。一个典型的 Ingress 描述文件如下:

 

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: echo-demo

  labels:

    app: echo-demo

  annotations:

    kubernetes.io/ingress.class: nginx

  namespace: default

spec:

  rules:

    - host: test.domain.com

      http:

        paths:

          - backend:

              serviceName: echo-demo-v1

              servicePort: 80

            path: /echo

  - backend:

       serviceName: hello-world

       servicePort: 8080

     path: /hello

 

由 Ingress API 可以看到,一个域名下可以定义多个访问路径,然而一个路径却只能定义一个 service。于是,在使用 Ingress 对象来描述灰度发布的情形下,要实现一个访问端点与多个服务版本的映射,仍然只能采用上述一个 kubernetes service 聚合多个版本的 deployment 的方式,这种方案的种种问题上文已经分析过了。社区版 Nginx Ingress Controller 受限于 Ingress API 的描述能力,对灰度发布的支持完全是不可用的状态。有没有一种办法,既兼容 Ingress API,又能做到一个访问端点映射到多个 service 呢?

 

博云基于 Nginx Ingress Controller 开发的 Ingress 控制器 BeyondELB,设计了一种 Ingress 组合模型,在兼容 Ingress API 的基础上,用 labels 给 Ingress 对象分类,并将多个不同类别的 Ingress 对象组合成一个逻辑 Ingress,从而实现了一个访问端点到多个 service 的映射。这种组合模型为实现另一种灰度发布方案提供了可能。

 

 

 

使用 BeyondELB

实施基于权重的灰度发布

 

 

 

 

上面可以看到,使用 deployment labels 实现的基于权重的灰度发布,其灰度比例完全依赖于服务的实例数量,而引入 HPA 之后服务实例数量可能会发生倾斜从而打破灰度比例。而由 Ingress 组合模型实现的灰度方案中,一个访问端点能够配置多个 service,每个 service 有自己的灰度权重和同一版本的服务实例,灰度权重不再和服务实例数量相绑定。通过将灰度权重和服务实例数量解耦,权重可以随时按需调整,服务的实例数量则可以根据负载情况自行伸缩,不会影响到设定好的灰度比例。

 

原生Ingress灰度发布能力不够?我们是这么干的_原生Ingress

 

采用了 Ingress 组合模型的 BeyondELB 支持上述权重灰度发布策略。可以为某个 Ingress 访问路径定义一个或多个服务版本,然后为不同服务版本设定灰度权重,请求将按照灰度权重分配到不同版本的服务中。

 

上图中,选择开启基于权重的灰度发布,定义了一个灰度服务并设定 20 的权重,如果主版本服务的权重设定为 80(图中未给出主服务版本定义),则请求将按照 4:1 的比例分配到主版本服务和灰度版本服务。下面对配置了 80/20 权重的服务连续请求 100 次,可见流量按设定的比例分配到 v1 和 v2 服务中。

 

$ for i in `seq 1 100`; do curl -s http://test.domain.com/weight; done | jq .version | sort | uniq -c

 

    78 "1.0.0"

    22 "2.0.0"

 

 

 

 

使用 BeyondELB 

实施基于请求特征的版本级灰度发布

 

 

 

 

在某些场景下,可能会需要对灰度选择有更好的控制,比如对于 HTTP 服务来说,可以通过请求特征甄别用户,允许将具有特定请求 Header 或 Cookie 的用户发送到灰度版本。

 

原生Ingress灰度发布能力不够?我们是这么干的_灰度发布_02

 

上图中,我们添加了一个灰度服务版本,并且设定灰度策略为“基于请求特征”。当请求附有名为 "canary" 值为 "true" 的请求 Header 时,将由该灰度服务版本响应;而其它未匹配该灰度条件的请求则由主服务版本响应(图中未给出主服务版本定义)。

 

我们通过以下两个脚本测试基于 Header 的灰度效果。

 

请求携带名为 canary 且其值为 "true" 的 Header:
 

$ for i in `seq 1 100`; do curl -s -H "canary: true" http://test.domain.com/header; done | jq .version | sort | uniq -c

 

100 "1.0.0"

 

请求不携带名为 "canary" 的 Header:

 

        $ for i in `seq 1 100`; do curl -s http://test.domain.com/header; done | jq .version | sort | uniq -c

 

100 "2.0.0"

 

除了基于请求 Header 的灰度匹配策略,博云的 Ingress Controller 还支持基于请求 Cookie 的匹配策略,以及多个 Header 或 Cookie 灰度条件组合的匹配策略。我们还可以用正则表达式匹配 operator 来实现更具体化的灰度方案,比如如下匹配表达式可以将 User ID 以 3 结尾的用户发送到灰度服务版本。

 

(header("x-userid" regex "^[0-9]+3$")

 

 

 

总结

 

 

 

 

通过使用 Kubernetes pod labels 和 service,可以初步实现基于权重的灰度发布。但这种灰度发布依赖于服务版本的实例数量,不仅不灵活而且在引入 HPA 时会造成服务比例倾斜。博云自研的 Ingress Controller 将灰度权重和服务实例数量解耦,服务可依据负载和 HPA 规则自行伸缩实例,不影响灰度比例。而基于 Header 或 Cookie 的灰度匹配策略,为实现更可控的灰度方案提供了支持。除了增强的灰度发布能力,博云商用版本的 Ingress Controller 还支持租户级负载、热更新等特性,后续将会逐步介绍。

 

 

标签:原生,Ingress,服务,demo,echo,灰度,版本
From: https://blog.51cto.com/u_11976981/5900449

相关文章

  • 基于云原生技术的融合通信是如何实现的?
    孵化于云端,云通信成为时代的主流。01云通信的「前世今生」通信与每个人息息相关。 生态合作和渠道的规模上量,给传统通信模式带来巨大的挑战,由此衍生出云通信。 ......
  • 构建基于 Ingress 的全链路灰度能力
    作者:涂鸦背景随着云原生技术不断普及,越来越多的业务应用开始向云原生架构转变,借助容器管理平台Kubernetes的不可变基础设施、弹性扩缩容和高扩展性,助力业务迅速完成数......
  • 构建基于 Ingress 的全链路灰度能力
    作者:涂鸦背景随着云原生技术不断普及,越来越多的业务应用开始向云原生架构转变,借助容器管理平台Kubernetes的不可变基础设施、弹性扩缩容和高扩展性,助力业务迅速完成数字化......
  • 基于云原生技术的融合通信是如何实现的?
    孵化于云端,云通信成为时代的主流。01云通信的「前世今生」通信与每个人息息相关。生态合作和渠道的规模上量,给传统通信模式带来巨大的挑战,由此衍生出云通信。云通信,......
  • 云原生 • Kubernetes 认识 k8s、k8s 架构、核心概念点介绍
    云原生•Kubernetes认识k8s、k8s架构、核心概念点介绍 一、Kubernetes简介Kubernetes简称k8s,是支持云原生部署的一个平台,起源于谷歌。谷歌早在十几年之前就对其......
  • 云原生主题学习月|共同学习全球领先的亚马逊云科技云原生课程,组团共学拿奖励~
    CSDN已上线亚马逊云科技超过60门中文数字化培训课程,希望为学习者提供亚马逊云科技基础技能知识和最佳实践。每门课程时长从十分钟到几小时不等,由亚马逊云科技专家打造,......
  • nginx-ingress实现二级目录
    需求说明内网后端地址:http://10.10.246.29:9000如图:外网域名:https://devhtk.ntmaorong.com/要求:https://devhtk.ntmaorong.com/minio/--->访问http://10.10.246.2......
  • 浪潮存储:拥抱云原生,进入CNCF云原生存储全景图
    近日,浪潮存储正式加入云原生计算基金会(CloudNativeComputingFoundation,以下简称CNCF)的云原生存储(CloudNativeStorage)全景图。这意味着,浪潮存储被国际权威机构认可,成为......
  • JavaScript调用App原生代码(iOS、Android)通用解决方案
     实际场景场景:现在有一个H5活动页面,上面有一个登陆按钮,要求点击登陆按钮以后,唤出App内部的登录界面,当登录成功以后将用户的手机号返回给H5页面,显示出来。这个场景应......
  • istio --- 云原生时代到来
    ​​微服务​​对于每个功能的开发细化了,但是对与系统的管理复杂度增强了,尤其是网络流量的管理。试想一下:黑名单,导流,加密,访问控制,流量监控,熔断,限速,收费功能,数据流阶段延迟......