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

news2024/10/5 18:29:21

作者:潘梦源

前言

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

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

什么是渐进式发布?

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

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

图片

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

图片

金丝雀发布、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 等,然而正如前文所述,这些资源的配置并没有形成统一的标准,因此无法设计出一套通用的代码对资源进行处理, 这种情况给开发人员带来了一些不便和挑战。

图片
argo-rollouts 与 flagger 兼容方案

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

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

图片
argo-rollouts 不同资源配置

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

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

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

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

图片

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

  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 的主页

图片

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 中,此时整个服务的流量表示为下图所示:

图片

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

图片

  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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/973132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【B树 B+树】B树、B+树理论

目录 引入B树B树定义和性质m阶B树核心特性 B树B树的查找 引入B树 满足上面两个策略就是B树: m 叉查找树中,规定除了根节点外,任何结点至少有 ⌈ m / 2 ⌉ \lceil m/2 \rceil ⌈m/2⌉ 个分叉,即至少含有 ⌈ m / 2 ⌉ \lceil m/2 \…

【Linux网络编程】环境配置篇

由于博主本学期所使用的Linux系统为Ubuntu,所以这篇博客会先以安装虚拟机和Ubuntu开始。 虚拟机的话,可以选择VMware,也可以选择VirtualBox。直接选择安装就行,这个应该是没有什么问题的。但是,如果之前电脑安装过Vmwa…

器件介绍TPS25821DSSR、TPS65994ADRSLR USB Type-C接口IC,TPS65982DMCZBHR坞站管理控制器

一、TPS25821 USB Type-C™ 电源控制器和 1.5A 电源开关 概述:TPS25820/21 是一款 USB Type-C 电源控制器,集成了一个额定电流为 1.5A 的 USB 电源开关。TPS25820/21 通过监测 Type-C 配置通道 (CC) 线路来确定 USB 接收装置是否连接。如果连接了接收装…

python基础运用例子

python基础运用例子 1、⼀⾏代码交换 a , b :a, b b, a2、⼀⾏代码反转列表 l[::-1]3、合并两个字典 res {**dict1, **dict2}**操作符合并两个字典for循环合并dict(a, **b) 的方式dict(a.items() b.items()) 的方式dict.update(other_dict) 的方式 4、⼀⾏代码列…

使用Pyspider进行API接口抓取和数据采集

API接口是一种常见的数据获取方式,它可以提供文本格式的数据,并且具有高度的实时性和可靠性。而Pyspider是一个基于Python的强大的网络爬虫框架,它提供了丰富的功能和灵活的扩展性,使我们可以轻松地进行数据的抓取和处理。在我们的…

深度学习环境搭建笔记(二):mmdetection-CPU安装和训练

文章目录 第一步:安装anaconda第二步:安装虚拟环境第三步:安装torch和torchvision第四步: 安装mmcv-full第五步: 安装mmdetection第六步:测试环境第七步:训练-目标检测7.1 准备数据集7.2 检查数据集7.3 训练网络 第一步…

数据库-多表查询

概述: 介绍:多表查询:指从多张表中查询数据 笛卡儿积:笛卡儿积是指在数学中,两个集合(A集合和B集合)的所有组合情况(在多表查询时,需要消除无效的笛卡儿积) 分…

7. read_excel()函数读取Excel文件

【目录】 文章目录 1. pandas库读取数据2. read_excel()函数读取Excel文件3. 准备工作4. 路径前的r是什么5. io参数 绝对路径6. io 相对路径7. sheet_name:要读取的sheet的名称或索引7.1 sheet_name参数 名字7.2 sheet_name参数 顺序 8. index_col参数指定行索引…

[译]这8个CSS小技巧,你知道吗?

前言 在网页设计和前端开发中,CSS属性是非常重要的一部分。掌握常用的CSS属性不仅可以使你的网页看起来更美观,还能提升用户体验,今天小编为大家介绍8个常见的CSS小技巧: 1.修改滚动条样式 下图是我们常见的滚动条,…

开发前期准备工作

开发前期准备工作 文章目录 开发前期准备工作0 代码规范0.1 强制0.2 推荐0.3 参考dao:跟数据库打交道service:业务层,人类思维解决controller:抽象化 0.4 注释规范0.5 日志规范0.6 专有名词0.7 控制层统一异常统一结构体控制层提示…

2023年8月CSDN客服月报|解决个3重大问题和8个次要问题,处理个用户需求及建议

听用户心声,解用户之需。hello,大家好,这里是《CSDN客诉报告》第23期,接下来就请大家一同回顾我们8月份解决的bug~ 一、重大问题 1、【主站】博客访问异常 反馈量:102 持续时间:7月31日15:4…

Xcode,swift:Error Domain=kCLErrorDomain Code=1 (null)问题解决

问题描述: iOS开发时,当使用用户的位置权限时,获取用户经纬度报错:Error DomainkCLErrorDomain Code1 "(null)",错误域kCLError域代码1“(null)” 解决方法: 打开模拟机的设置-通用-语言与地区 将地区设置为中国(如果你的开发位置在中国的话) 点击左上方Features,选择…

leetCode动态规划“不同路径II”

迷宫问题是比较经典的算法问题,一般可以用动态规划、回溯等方法进行解题,这道题目是我昨晚不同路径这道题趁热打铁继续做的,思路与原题差不多,只是有需要注意细节的地方,那么话不多说,直接上coding和解析&a…

[Linux]编写一个极简版的shell(版本1)

[Linux]编写一个极简版的shell-version1 文章目录 [Linux]编写一个极简版的shell-version1命令行提示符打印接收命令行参数将命令行参数进行解释执行用户命令完整代码 本文能够帮助Linux系统学习者通过代码的角度更好地理解命令行解释器的实现原理。 命令行提示符打印 Linux操…

将两个文件夹中重复的图象删除

将两个文件夹中重复的图象删除 需求分析解决方案 需求分析 文件夹one和two存在图象的重复,将two文件中中重复的文件夹删除 解决方案 # coding: utf-8 from PIL import Image, ImageDraw, ImageFont import os import shutil import cv2 as cv import numpy as np …

二分搜索树节点的插入(Java 实例代码)

目录 二分搜索树节点的插入 Java 实例代码 src/runoob/binary/BinarySearchTreeInsert.java 文件代码&#xff1a; 二分搜索树节点的插入 首先定义一个二分搜索树&#xff0c;Java 代码表示如下: public class BST<Key extends Comparable<Key>, Value> { …

第 3 章 栈和队列(链栈)

1. 背景说明 链栈是指用单链表实现的栈&#xff0c;其存储结构为链式存储&#xff0c;实现类似于队列的链式实现&#xff0c;不过在插入元素时链栈在头部插入&#xff0c;而 链式队列在尾部插入&#xff0c;本示例中实现为带头结点的链栈&#xff0c;即栈顶元素为栈指针的下一…

Qcon2023: 大模型时代的技术人成长(简)

我目前致力于操作系统相关的研发&#xff0c; 公司的目标是打造物联网时代的智能原生操作系统。如何实现操作系统的AI Native 呢&#xff1f;带着这样的疑问我参加了Qcon2023 北京站的大会。 与Qcon 2022 北京站不同的是&#xff0c; 身份变了&#xff0c; 上次是分享者&#x…

【校招VIP】前端JavaScript语言之跨域

考点介绍&#xff1a; 什么是跨域&#xff1f;浏览器从一个域名的网页去请求另一个域名的资源时&#xff0c;域名、端口、协议任一不同&#xff0c;都是跨域。跨域是前端校招的一个重要考点&#xff0c;在面试过程中经常遇到&#xff0c;需要着重掌握。本期分享的前端算法考点之…

电商API对接流程,简单讲解!

电商API接口对接流程一般包括以下几个步骤&#xff1a; 1. 确定需求&#xff1a;首先确定您的电商平台需要与哪些其他系统或服务进行对接&#xff0c;以及需要传递哪些数据。 2. 寻找合适的API&#xff1a;根据您的需求&#xff0c;在开放平台或者第三方API市场中选择适合的API…