Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案

这篇具有很好参考价值的文章主要介绍了Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:潘梦源

前言

Kruise Rollout [ 1] 是 OpenKruise 社区开源的渐进式交付框架。Kruise Rollout 支持配合流量和实例灰度的金丝雀发布、蓝绿发布、A/B Testing 发布,以及发布过程能够基于 Prometheus Metrics 指标自动化分批与暂停,并提供旁路的无感对接、兼容已有的多种工作负载(Deployment、CloneSet、DaemonSet)。

目前 Kruise Rollout 新增了流量调度支持自定义资源的能力 ,从而更好的支持渐进式发布中的流量调度。 本文将对 Kruise Rollout 所提出的方案进行介绍。

什么是渐进式发布?

**渐进式发布(Progressive Delivery)是一种软件部署和发布策略,旨在逐步将新版本或功能引入生产环境,以降低风险并确保系统的稳定性。一些常见的渐进式发布形式如下:

  • 金丝雀发布: 在发布时会创建一个金丝雀版本的 Deployment 进行验证,当验证通过后,再进行全量的工作负载升级,并删除金丝雀版本的 Deployment。

Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案,lua,junit,开发语言

  • A/B 测试: 按照一定的规则将用户流量切分成 A、B 两个不相交通路,并将导入不同版本的 Pod 实例进行处理,以此来更好地观察、对比或者灰度新版本能力。

Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案,lua,junit,开发语言

金丝雀发布、A/B 测试和蓝绿发布都是逐步测试和评估新功能或变更的策略,它们可以根据具体的需求和场景选择适合的部署和测试策略,并结合流量灰度等技术实现逐步发布和测试新版本或功能。

为什么需要对网关资源提供支持?

Kruise Rollout 目前已经对 Gateway API 提供了支持,那么为什么还需要对不同供应商的网关资源提供支持呢?在解释这个问题之前,我们先来简单介绍一下 Gateway API。

当前社区中不同的供应商都有自己的网关资源,并提出了自己的标准,而 Kubernetes 为了提供一个统一的网关资源标准,构建标准化的,独立于供应商的 API,提出了 Gateway API。目前,尽管 Gateway API 还处于开发阶段,但已经有很多项目表示支持或计划支持 Gateway API。包括:

  • Istio 是最流行的服务网格项目之一,Istio 1.9 版本计划引入实验性的 Gateway API 支持。用户可以通过 Gateway 和 HTTPRoute 资源来配置 Istio 的 Envoy 代理。
  • Apache APISIX 是一个动态、实时、高性能的 API 网关,APISIX 目前支持Gateway API 规范的 v1beta1 版本,用于其 Apache APISIX Ingress Controller。
  • Kong 是一个为混合云和多云环境构建的开源 API 网关,Kong 在 Kong Kubernetes Ingress Controller (KIC) 以及 Kong Gateway Operator 中支持 Gateway API。

然而由于目前 Gateway API 并不能覆盖供应商所提出网关资源的所有功能,并且仍然有大量用户使用供应商提供的网关资源,虽然用户可以通过开发 Gateway API 对网关资源进行适配,但这样的工作量较大,所以仅仅为 Gateway API 提供支持是远远不够的,尽管随着 Gateway API 特性的不断丰富,在未来,使用 Gateway API 将成为一种更加推荐的方式。因此,虽然 Kruise Rollout 目前已经提供了对 Gateway API 的支持,如何对现有供应商多种多样的网关资源提供支持仍然是一个重要的问题。

如何兼容社区多样的网关方案?

当前社区中已经存在许多广泛使用的供应商提供的网关资源,比如:Istio、Kong、Apisix 等,然而正如前文所述,这些资源的配置并没有形成统一的标准,因此无法设计出一套通用的代码对资源进行处理, 这种情况给开发人员带来了一些不便和挑战。

Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案,lua,junit,开发语言
argo-rollouts 与 flagger 兼容方案

为了能够兼容更多的社区网关资源,一些方案被提出,例如 flagger、argo-rollouts 为每一种网关资源都提供了代码实现。这些方案的实现相对简单,但也存在一些问题:

  • 面对大量的社区网关资源时,需要消耗大量精力进行实现
  • 每次实现都需要重新进行发布,自定义能力较差
  • 在某些环境下用户可能使用定制的网关资源,在这种情况下难以适配
  • 每一种资源都有不同的配置规则,配置较为复杂
  • 每添加一个新的网关资源都需要为其实现新的接口,维护难度较大

Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案,lua,junit,开发语言
argo-rollouts 不同资源配置

因此,需要一种支持用户定制,可以灵活插拔的实现方案,以适配社区以及用户定制的多种多样的网关资源,来满足社区不同的用户的需求,增强 Kruise Rollout 的兼容性和扩展性。

为此,我们提出了一种基于 Lua 脚本的网关资源可扩展流量调度方案

Kruise Rollout:基于 Lua 脚本的可扩展流量调度

Kruise Rollout 使用基于 Lua 脚本的网关资源定制方案,本方案通过调用 Lua 脚本根据发布策略和网关资源原始状态来获取并更新资源的期待工作状态(状态包含 spec、labels 以及 annotations),可以使用户能够轻松地适配和集成不同类型的网关资源,而无需修改现有的代码和配置。

Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案,lua,junit,开发语言

本方案对于网关资源的处理可以表示为上图,整个过程可以描述为:

  1. 用户定义了 Rollout 流量灰度规则、需要修改的资源等信息,开始金丝雀发布
  2. 根据 Rollout 配置获取指定资源
  3. 根据资源调用对应的 Lua 脚本
  4. 将资源当前状态转为字符串存入资源 annotation 中,并与发布策略一同输入 Lua 脚本
  5. 利用 Lua 脚本根据当前状态和发布策略处理得到新状态并更新资源
  6. 发布结束后,从 annotation 中获取资源的原始状态对资源进行恢复

通过使用 Kruise Rollout,用户可以:

  • 定制处理网关资源的 Lua 脚本,可以自由的实现对资源的处理逻辑,为更多资源提供支持
  • 利用一套通用的 Rollout 配置模版对不同资源进行配置,降低配置的复杂性,方便用户配置

同时,Kruise Rollout 采用的方案仅需要添加 5 个新接口即可实现对多种多样网关资源的支持。相比之下,其他方案例如 argo-rollouts 则为不同供应商的网关资源提供了不同的接口,对于 Istio 和 Apisix 来说,argo-rollouts 分别提供了 14 个和 4 个新的接口, 而且,该方案随着对更多网关资源的支持,接口数量还会持续增长。相比之下,Kruise Rollout 并不需要为新的网关资源提供新的接口,这使得 Kruise Rollout 成为一种更简洁、更易于维护的选择,而不会增加过多的接口负担。同时,编写 Lua 脚本相对于开发 Gateway API 对网关资源进行适配,可以大大减小开发人员的工作量。

以下展示了一个利用 Lua 脚本对 Istio DestinationRule 进行处理的的示例。

  1. 首先定义 rollout 配置文件:
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
...
spec:
  ...
      trafficRoutings:
      - service: mocka
        createCanaryService: false # 使用原有service,不创建新的canary service
        networkRefs: # 需要控制的网关资源
        - apiVersion: networking.istio.io/v1alpha3
          kind: DestinationRule
          name: ds-demo
      patchPodTemplateMetadata: 
        labels:
          version: canary # 为新版本pod打上label
  1. 对 Istio DestinationRule 进行处理的 Lua 脚本为:
local spec = obj.data.spec -- 获取资源的spec,obj.data为资源的状态信息
local canary = {} -- 初始化一条指向新版本的canary路由规则
canary.labels = {} -- 初始化canary路由规则的labels
canary.name = "canary" -- 定义canary路由规则名称
-- 循环处理rollout配置的新版本pod label
for k, v in pairs(obj.patchPodMetadata.labels) do 
  canary.labels[k] = v -- 向canary规则中加入pod label
end
table.insert(spec.subsets, canary) -- 向资源的spec.subsets中插入canary规则
return obj.data -- 返回资源状态
  1. 处理完的 DestinationRule 为:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
spec:
  ...
  subsets:
    - labels:           # -+
        version: canary #  |- Lua脚本处理后新插入的规则
      name: canary      # -+
    - labels:
        version: base
      name: version-base

Kruise Rollout 进行 Istio 资源流量调度实践

接下来介绍一个利用我们所提出方案对 Istio 进行支持的具体案例。

  1. 首先部署如下图所示的服务。该服务由以下几部分构成:
    • 由 Ingress Gateway 作为外部流量网关
    • 通过 VirtualService 和 DestinationRule 将流量调度至 nginx pod 中
    • 利用 ConfigMap 作为主页 nginx pod 的主页

Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案,lua,junit,开发语言

nginx 服务的 deployment 如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
        version: base
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: html-volume
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html-volume
        configMap:
          name: nginx-configmap-base # 挂载ConfigMap作为index
  1. 创建 rollout 资源,配置发布规则,该 rollout 分为两批发布:
    • 第一批将 20% 的流量转发至新发布的 pod 中
    • 第二批将带有 header version=canary 的流量转发至新版本 pod 中
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-demo
  annotations:
    rollouts.kruise.io/rolling-style: canary
spec:
  disabled: false
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: nginx-deployment
  strategy:
    canary:
      steps:
      - weight: 20 # 第一批转发20%的流量进入新版本pod
      - replicas: 1 # 第二批将包含version=canary header的流量转发入新版本pod
        matches:
        - headers:
          - type: Exact
            name: version
            value: canary
      trafficRoutings:
      - service: nginx-service # 旧版本pod使用的service
        createCanaryService: false # 不创建新的canary service,新旧pod共用一个service
        networkRefs: # 需要修改的网关资源
        - apiVersion: networking.istio.io/v1alpha3
          kind: VirtualService
          name: nginx-vs
        - apiVersion: networking.istio.io/v1beta1
          kind: DestinationRule
          name: nginx-dr
      patchPodTemplateMetadata: # 为新版本pod打上version=canary的label
        labels:
          version: canary
  1. 修改 nginx 服务 deployment 中挂载的 ConfigMap 开始金丝雀发布。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
      ...
      volumes:
      - name: html-volume
        configMap:
          name: nginx-configmap-canary # 挂载新的ConfigMap作为index
  1. 开始发布第一批,Kruise Rollout 自动调用定义的 Lua 脚本对 VirtualService 和 DestinationRule 资源进行修改,进行流量调度,将 20% 的流量转发至新版本 pod 中,此时整个服务的流量表示为下图所示:

Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案,lua,junit,开发语言

  1. 执行命令 kubectl-kruise rollout approve rollout/rollouts-demo,开始发布第二批,Kruise Rollout 自动调用定义的 Lua 脚本对 VirtualService 和 DestinationRule 资源进行修改,进行流量调度,将包含 version=canary header 的流量转发至新版本 pod 中,此时整个服务的流量表示为下图所示:

Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案,lua,junit,开发语言

  1. 执行命令 kubectl-kruise rollout approve rollout/rollouts-demo,发布结束,VirtualService 和 DestinationRule 资源恢复至发布前状态,所有流量路由至新版本 pod。

如何利用 Lua 脚本快速配置网关资源的流量调度

在调用 Lua 脚本获取资源状态新状态时,Kruise Rollout 支持两种 Lua 脚本调用方式,分别为:

  • 自定义的 Lua 脚本:用户自定义的,以 ConfigMap 的形式定义并在 Rollout 中调用
  • 已发布的 Lua 脚本:社区通用的、已经稳定的 Lua 脚本,随 Kruise Rollout 打包发布

Kruise Rollout 默认首先查找本地是否存在已发布的 Lua 脚本,这些脚本通常需要设计测试案例进行单元测试验证其可用性,具有更好的稳定性。 测试案例的格式如下所示,Kruise Rollout 利用 Lua 脚本根据 rollout 中定义的发布策略对资源原始状态进行处理,得到发布过程中每一步的资源新状态,并与测试案例中 expected 中定义的期待状态进行对比,以验证 Lua 脚本是否按照预期工作。

rollout:
  # rollout配置
original:
  # 资源的原始状态
expected:
  # 发布过程中资源的期待状态

在资源的 Lua 脚本未发布的情况下,用户还可以快速的通过在 ConfigMap 中配置 Lua 脚本的方式由 Kruise Rollout 调用从而对资源进行处理。

apiVersion: v1
kind: ConfigMap
metadata:
  name: kruise-rollout-configuration
  namespace: kruise-rollout
data:
  # 键以lua.traffic.routing.Kind.CRDGroup的形式命名
  "lua.traffic.routing.DestinationRule.networking.istio.io": |
    --- 定义Lua脚本
    local spec = obj.data.spec
    local canary = {}
    canary.labels = {}
    canary.name = "canary"
    for k, v in pairs(obj.patchPodMetadata.labels) do
        canary.labels[k] = v
    end
    table.insert(spec.subsets, canary)
    return obj.data

详细的 Lua 脚本配置说明参见 Kruise Rollout 官网 [ 2]

未来规划

  • 更多网关协议支持: Kruise Rollout 目前是以 Lua 脚本插件化的方式支持多类型的网关协议,我们后续会重点加大这方面的投入,但面对百花齐放的协议类型,单靠社区 Maintainer 的单薄力量还远远不够,希望更多的社区小伙伴加入我们,一起来不断完善这方面的内容。
  • 全链路灰度支持: 全链路灰度是具有更加细粒度和全面的灰度发布模式,它涵盖了应用程序的所有服务,而不止对单一的服务进行灰度,可以更好的对新服务进行模拟和测试。目前可以通过社区的网关资源如 Istio 进行配置来实现,但人工配置往往需要消耗较大的精力。我们将对这一部分进行探索,从而实现对全链路灰度的支持。

社区参与

非常欢迎你通过 Github/Slack/钉钉/微信 等方式加入我们来参与 OpenKruise 开源社区。

你是否已经有一些希望与我们社区交流的内容呢?可以在我们的社区双周会 [ 3] 上分享你的声音,或通过以下渠道参与讨论:

  • 加入社区 Slack channel  [ 4] (English)
  • 加入社区钉钉群:搜索群号 23330762 (Chinese)
  • 加入社区微信群(新):添加用户 openkruise 并让机器人拉你入群 (Chinese)

相关链接:

[1] Kruise Rollout

https://github.com/openkruise/rollouts

[2] Kruise Rollout 官网

https://openkruise.io/rollouts/introduction

[3] 社区双周会https://shimo.im/docs/gXqmeQOYBehZ4vqo

[4] Slack channel

https://kubernetes.slack.com/?redir=%2Farchives%2Fopenkruise文章来源地址https://www.toymoban.com/news/detail-696435.html

到了这里,关于Kruise Rollout:基于 Lua 脚本的可扩展流量调度方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于 Redis + Lua 脚本实现分布式锁,确保操作的原子性

    1.加锁的Lua脚本: lock.lua 2.解锁的Lua脚本: unLock.lua 3.将资源文件放在资源文件夹下 4.Java中调用lua脚本 1)获取文件方式 2)lua字符串方式 5.jedis调用Lua脚本实现分布式重试锁 1)引入jedis依赖 2)jedis调用lua

    2024年02月07日
    浏览(43)
  • Gallia:一款针对汽车安全的可扩展渗透测试框架

    Gallia是一款专注于汽车安全的可扩展渗透测试框架,该工具可以对整辆汽车执行渗透测试,而且甚至可以还可以单独对车辆ECU进行测试。目前,Gallia主要针对的是UDS接口,并利用了模块化的设计分别实现了日志记录和归档功能。作为一个通用接口,日志记录功能实现了可重复

    2024年02月02日
    浏览(47)
  • NodeFormer:一种用于节点分类的可扩展图结构学习Transformer

    图神经网络已经被广泛研究用于利用互连数据进行学习。尽管如此,最近的证据表明,GNN的缺陷与过度挤压、异质性、处理长程依赖性、边缘不完全性有关,尤其是完全没有图。虽然一个合理的解决方案是学习用于消息传递的新的自适应拓扑,但有关二次复杂性的问题阻碍了

    2024年02月11日
    浏览(46)
  • lua脚本获取table类型-Java使用lua脚本操作redis获取zset元素的集合

    lua脚本获取table类型-Java使用lua脚本操作redis获取zset元素的集合 7.0点赞功能-定时持久化到数据库-lua脚本的编写_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1bu411j75u 这个脚本主要是放到Springboot工程里的, 这里如果是向放到字段控制台执行,那就要加入 eval 以及其他参数:

    2024年02月13日
    浏览(34)
  • 网络流量调度的艺术:权重公平排队算法(WFQ)揭秘,全面解析!

    在计算机网络中,流量调度是一个重要的问题。为了有效地利用网络资源,保证各个应用程序获得公平的带宽分配,一种常用的流量调度算法——权重公平排队(Weighted Fair Queuing,简称WFQ)应运而生。本文将从基本概念、工作原理、优点和缺点等方面对WFQ进行详细解析。 2.

    2024年02月03日
    浏览(29)
  • 【实战】使用Lua脚本怎么清理redis中的数据【实战】使用Lua脚本怎么清理redis中的数据

    首先我们通过hiredis 向redis 中写入了数据,这里我们主要以测试为目的,所以,Key 值设定为毫秒级时间戳。 但是当我们测试完成之后,需要验证实际情况,这里我们直接使用redis-cli 登录数据库看看。 本次测试完成,接下来要结合业务开始测试,需要清理数据库,但是一条一

    2024年02月13日
    浏览(77)
  • Lua脚本编程基础

    一. 数据类型 ①基本类型 1. nil类型 2. boolean类型 3. numbers类型 4. string类型 ②高级类型 1. table类型 2. function类型 3. userdata类型 4. thread类型  二 . 脚本示例 三. lua与c/c++的互操作

    2024年02月12日
    浏览(27)
  • Lua脚本本地调试

    这里主要使用日志的方式进行debug 项目对openresty包的依赖比较高,所以环境基础都在openresty下进行 openresty下载地址 下载完成后解压,具体使用方式和nginx没有什么区别,主要依赖文件是一下几个 这里拿lua链接mysql为例 双击 nginx.exe即可,浏览器输入 http://localhost:8765 进入启动

    2024年02月16日
    浏览(31)
  • Lua脚本语言

    Lua(发音为\\\"loo-ah\\\",葡萄牙语中的\\\"lua\\\"意为月亮)是一种轻量级的、高效的、可嵌入的脚本编程语言。官网Lua最初由巴西计算机科学家Roberto Ierusalimschy、Waldemar Celes和Luiz Henrique de Figueiredo于1993年开发,它的设计目标是提供一种简单的、易扩展的脚本语言,特别适用于嵌入到其他

    2024年02月07日
    浏览(28)
  • Redis之Lua脚本

    目录 Lua脚本 编写Lua脚本  springboot整合redis使用lua Lua脚本        Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。使用脚本的好处如下: 1. 减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成。使

    2024年01月23日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包