全网最全干货-APISIX蓝绿发布

博客原文地址:

雨云优惠码:wp-admin

在实际环境中,升级往往是充斥着风险的,但某些情况下可能会出现更新后整个服务直接崩盘的情况,如果使用了docker之类的东西还好,可以通过tags回滚版本,但总会有一定的中断时间,这时候我们就可以尝试蓝绿发布

官方文档对蓝绿发布的描述/使用

蓝绿发布
在蓝绿发布场景中,你需要维护两个环境,一旦新的变化在蓝色环境(staging)中被测试和接受,用户流量就会从绿色环境(production)转移到蓝色环境。

以下示例展示了如何基于请求头来配置 match 规则:

curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: $admin_key" -X PUT -d '
{
    "uri": "/index.html",
    "plugins": {
        "traffic-split": {
            "rules": [
                {
                    "match": [
                        {
                            "vars": [
                                ["http_release","==","new_release"]
                            ]
                        }
                    ],
                    "weighted_upstreams": [
                        {
                            "upstream": {
                                "name": "upstream_A",
                                "type": "roundrobin",
                                "nodes": {
                                    "127.0.0.1:1981":10
                                }
                            }
                        }
                    ]
                }
            ]
        }
    },
    "upstream": {
            "type": "roundrobin",
            "nodes": {
                "127.0.0.1:1980": 1
            }
    }
}'

测试

通过 curl 命令发出请求,如果请求带有一个值为 new_release 的 release header,它就会被引导至在插件上配置的新的上游服务:

curl http://127.0.0.1:9080/index.html -H 'release: new_release' -i
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
world 1981

否则请求会被引导至在路由上配置的另一个上游服务:

curl http://127.0.0.1:9080/index.html -H 'release: old_release' -i
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
hello 1980

蓝绿发布的流程

image

首先,正常情况下会有一个负载均衡器(LB),并且后端由蓝组和绿组同时提供服务,若要执行蓝绿发布,首先需要在负载均衡器上将绿组移除,也就是没有任何流量会被转发到绿组,此时对绿组执行升级

升级完毕后再将绿组加回负载均衡器,再将蓝组从负载均衡器中移除,对蓝组进行升级,这就是蓝绿发布

实战运用

在配置路由时,在插件配置的地方往下滑,找到traffic-split插件

开启插件后在下方编写配置文件

{
  "rules": [
    {
      "match": [
        {
          "vars": [
            [
              "http头、变量",
              "判断方式",
              "参数值"
            ]
          ]
        }
      ],
      "weighted_upstreams": [
        {
          "upstream": {
            "name": "服务的名字,随便起,和Web上显示的那个上游不是一个东西",
            "nodes": {
              "上游IP:端口": 权重
            },
            "type": "算法"
          }
        }
      ]
    }
  ]
}

“type”: “roundrobin”是流量引导机制的类型;roundrobin 表示支持权重的负载,chash 表示使用一致性哈希。

vars中的http头、变量与 NGINX 内部自身变量命名是保持一致的,所以也可以使用 request_uri、host 等,但是如果要使用一些http头或者自定义头部,那么应该加上http_的前缀,例如“http_x_real_ip”,“http_x_web_version”

参数值就是一个字符串,可以是版本号,IP地址等

判断方式有很多,比如这个官方示例中的vars

"vars": [
    ["arg_name2","==","rose"],
    ["http_user-id2","!",">","33"],
    ["http_apisix-key2","~~","[a-z]+"]
]

“==”就是完全匹配,”!”是不匹配,”>”是大于某个数值,”~~”则是使用正则表达式匹配

匹配方式则是“内与外或”,每个vars内的所有条件都要匹配到才会视为这个vars被命中,同理,也可以配置多个vars,多个vars任意一个被匹配到就会被视为规则命中,从而引导流量,否则将不会进行流量引导,继续发送流量至原本服务而不是新服务

这是一个多vars的示例

{
            "rules": [
                {
                    "match": [
                        {
                            "vars": [
                                ["http_x-api-id","==","1"]
                            ]
                        }
                    ],
                    "weighted_upstreams": [
                        {
                            "upstream": {
                                "name": "upstream-A",
                                "type": "roundrobin",
                                "nodes": {
                                    "127.0.0.1:1981":1
                                }
                            },
                            "weight": 3
                        }
                    ]
                },
                {
                    "match": [
                        {
                            "vars": [
                                ["http_x-api-id","==","2"]
                            ]
                        }
                    ],
                    "weighted_upstreams": [
                        {
                            "upstream": {
                                "name": "upstream-B",
                                "type": "roundrobin",
                                "nodes": {
                                    "127.0.0.1:1982":1
                                }
                            },
                            "weight": 3
                        }
                    ]
                }
            ]
        }

禁用插件但保留配置

官方给出了删除插件的方法,但是某些情况下我们只希望禁用插件,不希望删除配置,例如这次蓝绿部署后测试出现了问题,需要回滚到之前的版本继续提供服务,但是在bug修复后还要进行蓝绿部署,这时我们就可以只禁用插件不删除配置(WebUI和API请求同理可用)

首先我们在保存了插件配置之后,再打开会发现多出一个_meta

一般情况下我们不要手动更改这里,不然会出问题,我们要更改的是上面“启用”开关的状态,APISIX会自动更改这个值从而达成禁用插件但保留配置,对于不部署WebUI的用户,直接请求API可以使用PUT方法来更新