That’d be better than implementing a plugin to support it. Chao Zhang [email protected]
> On Sep 28, 2020, at 1:34 PM, wei jin <[email protected]> wrote: > > I like this proposal very much and think it will be the final form. > This function can be divided into two parts: > 1.label && selector; > 2. A grayscale upgrade configuration; > These two things can be done simultaneously. > > 1. Implement label && selector to replace the current upstream_id binding > relationship; > 2. The configuration method of grayscale upgrade can be realized by a > plug-in version first. > After waiting for the label function to be implemented, the gray scale > capability is migrated to the native implementation in the apisix object. > > The plug-in configuration is similar to this > > ```json > "plugins":{ > "routex": { > "rules": [ > { > "match": [ > { > "vars": [ > ["arg_user_id",">=",13], > ["arg_user_id","<=",133] > ] > }, > { > "vars": [ > ["arg_user_id","==",222] > ] > } > ], > "upstreams": [ > { > "upstream_id": 3, > "weight": 20 > }, > { > "upstream_id": 5, > "weight": 80 > } > ] > } > ] > } > } > ``` > > YuanSheng Wang <[email protected]> 于2020年9月26日周六 下午5:25写道: > >> wow, this is an interesting feature. >> >> It is very different from the current way. I need time to understand it. >> ^_^ >> >> >> On Fri, Sep 25, 2020 at 10:08 AM Zhang Chao <[email protected]> wrote: >> >>> >>> ### Background >>> >>> I observed the Pull Request https://github.com/apache/apisix/pull/2279 >>> adds labels for `upstream` object, which inspires me that if we attach >>> labels for each node in `upstream`, then we can implement fancy traffic >>> split feature. >>> >>> ### Design >>> >>> Traffic split, which means to setup several route rules and schedule >>> requests by respecting these rules to specified upstream (or a subset >> nodes >>> in a single upstream). With this feature, we can support the Canary >>> Release ( >>> >> https://martinfowler.com/bliki/CanaryRelease.html#:~:text=Canary%20release%20is%20a%20technique,making%20it%20available%20to%20everybody. >> ), >>> Blue Green Release ( >>> >> https://docs.cloudfoundry.org/devguide/deploy-apps/blue-green.html#:~:text=Blue%2Dgreen%20deployment%20is%20a,live%20and%20Green%20is%20idle >> .) >>> for backend applications when they are releasing, it's useful to reduce >> the >>> downtime when something fault happens. >>> >>> But it's not a good idea to introduce these concepts into APISIX >> directly, >>> since features like Blue Green Release is closer to business, not the >>> infrastructure, so what we can do is introducing the concept traffic >> split >>> , to abstract all the business logics into the traffic split rules (route >>> rules), and it can be implemented as a plugin. >>> >>> Both the Istio and SMI (https://github.com/servicemeshinterface/smi-spec >> ) >>> support traffic split by `VirtualService` and `TrafficSplit` CRD >>> respectively, although the latter is not perfect (at lease for now), we >>> still can be aware of the similarity between them. >>> >>> In general, we need two parts to define a traffic split rule, match and >>> route, the `match` defines the conditions that needed to judge wether a >>> request is eligible to apply the `route`, for instance, a `match` might >> be >>> "the method of HTTP request must be `GET`, and the parameter `id` must be >>> equal to `1006`. From APISIX's point of view, match conditions can be >>> scoped to HTTP, TLS, so conditions can vary, like URI, method, headers, >> SNI >>> and even other APISIX instance-scoped variables (hostname, env and etc). >>> >>> The APISIX Route already defines a fantastic match mechanism which is >>> similar with the traffic split. But that not means we don't need to embed >>> the match part in traffic split plugin, instead, we can reuse the match >>> mechanism in Route as it's own match mechanism to further split requests >>> that hit the same Route. See >>> https://github.com/api7/lua-resty-radixtree#new for more details about >>> Route match. >>> >>> The route, decides the ultimate upstream that a request will go, either >>> specifying the upstream name or with a label selector to filter an >> eligible >>> subset from that upstream. What's more, multiple upstreams can be >>> specified, each with a non-negative weight to support probabilistic >>> selection. For now, node in APISIX Upstream doesn't contain labels >>> attribute, so we can implement it by the metadata map in node >> indirectly. >>> >>> ```json >>> # route requests to the nodes that has label release=canary in >>> fake_upstream, >>> { >>> "route": [ >>> { >>> "upstream_id": "1", >>> "labels": { >>> "release": "canary" >>> } >>> } >>> ] >>> } >>> >>> # route 75% requests to upstream 2 and other 25% to upstream 3. >>> { >>> "route": [ >>> { >>> "upstream_id": "2", >>> "weight": 75 >>> }, >>> { >>> "upstream_id": "3", >>> "weight": 25 >>> } >>> ] >>> } >>> ``` >>> >>> The Route already contains an upstream, after introducing the traffic >>> split plugin, this upstream will be treated as the default upstream and >>> will be used when requests can not hit the route rules. >>> >>> ### Examples >>> >>> #### Weighted Blue Green Release >>> >>> Say we have two upstreams `app-blue` (id: 1) and `app-green` (id: 2), >>> which represent the old and new releases for `app` respectively. Now we >>> want to route 10% requests which UA is Android to `app-green`. >>> >>> ```json >>> [ >>> { >>> "match": [ >>> { >>> "vars": [ >>> [ "http_user_agent", "~~", "Android"] >>> ] >>> } >>> ], >>> "route": [ >>> { >>> "upstream_id": 2, >>> "weight": 10 >>> } >>> ] >>> }, >>> { >>> "route": [ >>> { >>> "upstream_id": 1, >>> "weight": 90 >>> } >>> ] >>> } >>> ] >>> ``` >>> >>> #### Canary Release in a single upstream >>> >>> Say we updated a node in upstream `app` (id: 3), and this node have a >>> unique label `release=canary`, other nodes in `app` has label >>> `release=stable`, now we want to route requests which parameter `user_id` >>> is between [13, 133] to this node. >>> >>> ```json >>> [ >>> { >>> "match": [ >>> { >>> "vars": [ >>> [ "arg_user_id", ">=", 13], >>> [ "arg_user_id", "<=", 133] >>> ] >>> } >>> ], >>> "route": [ >>> { >>> "upstream_id": 3, >>> "labels": "release=canary" >>> } >>> ] >>> }, >>> { >>> "route": [ >>> { >>> "upstream_id": 3, >>> "labels": "release=stable" >>> } >>> ] >>> } >>> ] >>> ``` >>> >>> ### References >>> >>> * VirtualService: >>> https://istio.io/latest/docs/reference/config/networking/virtual-service >>> * TrafficSplit: >>> >> https://github.com/servicemeshinterface/smi-spec/blob/master/apis/traffic-split/v1alpha3/traffic-split.md >>> >>> >>> Chao Zhang >>> [email protected] >>> >>> >>> >>> >> >> -- >> >> *MembPhis* >> My GitHub: https://github.com/membphis >> Apache APISIX: https://github.com/apache/incubator-apisix >>
