实施灰度发布
灰度发布是一种部署策略:先将变更逐步发布给一小部分用户,确认无误后再向所有用户开放,从而降低在生产环境 中引入新版软件的风险。
在 API7 企业版中,可以使用 traffic-split插件,按照分配的权重将请求分发到不同上游。
前置条件
- API7 企业版实例正在运行。
- 已创建网关组且网关实例正在运行。
- 一个 Dashboard Token。
工作流概览
下图展示了一次灰度发布,其中 90% 的流量发送到版本 1,10% 发送到版本 2:
配置流量拆分
本示例创建一个服务,其默认上游代表版本 1;随后在路由上配置 traffic-split 插件,将较小比例的流量发送到内联的版本 2 上游。
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/services/canary-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "canary-service",
"upstream": {
"type": "roundrobin",
"scheme": "https",
"pass_host": "node",
"nodes": [
{
"host": "mock.api7.ai",
"port": 443,
"weight": 100
}
]
}
}'
curl -k "https://localhost:7443/apisix/admin/routes/canary-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "canary-route",
"methods": ["GET"],
"paths": ["/headers"],
"service_id": "canary-service",
"plugins": {
"traffic-split": {
"rules": [
{
"weighted_upstreams": [
{
"weight": 10,
"upstream": {
"type": "roundrobin",
"nodes": [
{
"host": "httpbin.org",
"port": 443,
"weight": 1
}
]
}
},
{
"weight": 90
}
]
}
]
}
},
"priority": 0
}'
adc.yaml
services:
- name: canary-service
upstream:
scheme: https
pass_host: node
nodes:
- host: mock.api7.ai
port: 443
weight: 100
routes:
- name: canary-route
uris:
- /headers
methods:
- GET
plugins:
traffic-split:
rules:
- weighted_upstreams:
- weight: 10
upstream:
type: roundrobin
scheme: https
pass_host: node
nodes:
- host: httpbin.org
port: 443
weight: 1
- weight: 90
adc sync -f adc.yaml
逐步增加流量
随着对版本 2 信心的提升,可更新权重以增加其流量占比。
- 50/50 拆分:将两个权重都设置为 50。
- 100% 上线:将版本 2 权重设为 100、版本 1 权重设为 0;也可以将服务的默认上游更新为新版本并移除插件。
验证配置
向路由发送多个请求并验证分布:
for i in $(seq 1 60); do curl -s "http://127.0.0.1:9080/headers" | grep -q 'X-Application-Owner' && echo v1 || echo v2; done | sort | uniq -c
输出分布应接近配置的权重。在本地验证环境中,采用 90/10 拆分时,60 个请求产生了 56 个 v1 响应和 4 个 v2 响应。
回滚
如果发现版本 2 存在问题,可将版本 1 权重设为 100、版本 2 权重设为 0,以快速回滚。
{
"weighted_upstreams": [
{
"upstream": {
"type": "roundrobin",
"scheme": "https",
"pass_host": "node",
"nodes": [
{
"host": "httpbin.org",
"port": 443,
"weight": 1
}
]
},
"weight": 0
},
{ "weight": 100 }
]
}