简而言之,金丝雀发布背后的想法是仅向一小部分用户提供新的软件版本,分析结果,并决定是否进一步进行。如果结果与预期不符,则回滚;如果是,请增加暴露的用户数量,直到所有用户都从新版本中受益。
在这篇文章中,我想简要详细介绍这一介绍,解释定义分数的不同方法,并展示如何使用Apache APISIX 执行它。
“金丝雀”一词起源于煤炭开采业。采矿时释放有毒气体并不罕见:在狭小的封闭空间中,这可能意味着快速死亡。更糟糕的是,这些气体可能是无味的,因此矿工们会呼吸它,直到为时已晚。一氧化碳在煤矿中很常见,人类的感官无法察觉。
因此,矿工们将金丝雀带到了地下。如果金丝雀突然死掉,那么气袋很可能已经破裂,是时候离开这个地方了。
几年前,我们采用这种方法发布了新的软件版本。类比是这样的:矿工是部署版本的运维团队,金丝雀由衡量发布影响的所有工具组成,而天然气是一个(关键)错误。
最关键的是你需要衡量发布的影响,包括失败率、HTTP状态码等,并与之前的版本进行比较。这超出了本文的范围,但同样,如果您想从金丝雀版本中受益,这一点至关重要。第二个最重要的部分是,如果新版本有问题,能够快速回滚。
请注意,金丝雀发布并不是管理发布新代码风险的唯一方法。例如,功能标志是另一种流行的方式:
功能标志代表了一种更敏捷的回滚方法(真正意义上的)。如果十分之一的功能有问题,您无需取消部署新版本;您只需停用越野车功能即可。然而,这种超能力是以额外的代码库复杂性为代价的,无论您是依赖第三方产品还是自己实现。
另一方面,金丝雀需要成熟的部署管道才能随意部署和取消部署。
金丝雀版本背后的想法是只允许一小部分用户访问新版本。大多数金丝雀定义仅将“分数”定义为用户的百分比。然而,还有更多的事情要做。
第一步可能是只允许经过审查的用户检查生产环境中的部署是否按预期工作。在这种情况下,您可以仅将一组特定的内部用户(例如测试人员)转发到新版本。如果事先认识人,并且系统对用户进行了认证,可以通过身份进行配置;如果没有,您需要回退到某种通用方式,例如HTTP 标头 - X-Canary: Let-Me-Go-To-v2
。
请记住,我们必须监控新旧系统以查看差异。如果没有显示任何内容,那么现在是增加转发到新版本的用户池的绝佳时机。我假设你吃自己的狗粮,即;团队成员使用他们正在开发的软件。例如,如果您没有豪华汽车电子商务网站,欢迎您跳过本节。
为了扩大用户比例,同时限制风险,我们现在可以无差别地向内部用户提供新版本。我们可以将系统配置为根据客户端 IP 转发到新版本来执行此操作。当人们在现场工作时,这很容易,因为他们的 IP 在特定范围内。远程没有太大变化,因为用户可能通过 VPN 访问公司网络。
此时再次进行监控和比较。
此时,对于部分或全部内部用户来说,一切都应该按预期工作。但正如没有任何计划能够在与敌人接触后幸存下来一样,任何用法都无法模仿生产工作负载的全部多样性。简而言之,我们需要让普通用户访问新版本,但要以受控的方式,就像我们到目前为止逐渐增加用户数量一样:从一小部分开始,对其进行监控,如果一切正常,则增加部分。
以下是如何使用 Apache APISIX 执行此操作。 Apache APISIX提供了基于插件的架构,并提供了一个满足我们需求的插件,即traffic-split
插件。
traffic-split
插件可用于动态地将部分流量定向到各种上游服务。这是通过配置
match
(用于分割流量的自定义规则)和weighted_upstreams
(将流量定向到的一组上游)来完成的。
--流量分割
让我们从一些基本的上游开始,每个版本一个:
upstreams: - id: v1 nodes: "v1:8080": 1 - id: v2 nodes: "v2:8080": 1
我们可以使用traffic-split
插件将大部分流量转发到 v1,将一小部分流量转发到 v2:
routes: - id: 1 uri: "*" #1 upstream_id: v1 plugins: traffic-split: rules: - weighted_upstreams: #2 - upstream_id: v2 #3 weight: 1 #3 - weight: 99 #3
我们再次监控一切并确保结果符合预期。然后,我们可以增加转发到 v2 的流量比例,例如:
routes: - id: 1 uri: "*" upstream_id: v1 plugins: traffic-split: rules: - weighted_upstreams: - upstream_id: v2 weight: 5 #1 - weight: 95 #1
请注意,Apache APISIX 每秒都会重新加载对上述文件的更改。因此,您可以近乎实时地分配流量。或者,您可以使用管理 API 来实现相同的目的。
在上面,我从内部用户转移到了一小部分外部用户。也许向每个内部用户发布对您的组织来说风险太大,您需要更多的控制。请注意,在这种情况下,您可以进一步配置traffic-split
插件。
routes: - id: 1 uri: /* upstream_id: v1 plugins: traffic-split: rules: - match: - vars: [["http_X-Canary","~=","Let-Me-Go-To-v2"]] #1 - weighted_upstreams: - upstream_id: v2 weight: 5 - weight: 95
X-Canary
HTTP 标头具有配置的值时才拆分流量。
以下命令始终转发到 v1:
curl http://localhost:9080
以下命令也始终转发到 v1:
curl -H 'X-Canary: Let-Me-Go-To-v1' http://localhost:9080
以下命令根据配置的权重(即95/5)拆分流量:
curl -H 'X-Canary: Let-Me-Go-To-v2' http://localhost:9080
这篇文章解释了 Canary 版本以及如何通过 Apache APISIX 配置它。您可以从具有不同优先级的多条路线开始,然后继续使用traffic-split
插件。后者甚至可以进一步配置以允许更复杂的用例。
这篇文章的完整源代码可以在GitHub上找到。
更进一步:
最初于 2023 年 12 月 3 日发表于A Java Geek