Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redirect #53

Closed
zhugelianglongming opened this issue Feb 10, 2022 · 5 comments · Fixed by #72
Closed

Redirect #53

zhugelianglongming opened this issue Feb 10, 2022 · 5 comments · Fixed by #72
Assignees
Labels
enhancement New feature or request

Comments

@zhugelianglongming
Copy link
Member

背景

BFE 支持对流量进行重定向,希望 bfe-ingress-controller 实现该功能。

配置方式

Ingress 资源内

  • spec.rules 定义路由规则
  • metadata.annotations 定义对符合路由规则的流量,重定向响应的行为

参考格式:

metadata:
    annotations:
        bfe.ingress.kubernetes.io/redirect.target: "https://www.baidu.com"
        bfe.ingress.kubernetes.io/redirect.status: 302
spec:
  rules:
  - ...
metadata:
    annotations:
        bfe.ingress.kubernetes.io/redirect.cmd: SCHEME_SET
        bfe.ingress.kubernetes.io/redirect.params: '["http"]'
        bfe.ingress.kubernetes.io/redirect.status: 302
spec:
  rules:
  - ...

重定向类型

通过设置重定向返回状态码 bfe.ingress.kubernetes.io/redirect.status ,配置重定向类型

  • 默认为 302 临时重定向

永久重定向

bfe.ingress.kubernetes.io/redirect.status: 301
bfe.ingress.kubernetes.io/redirect.status: 308

临时重定向

bfe.ingress.kubernetes.io/redirect.status: 302

重定向目标

通过特定 annotation 配置重定向目标,可设置为以下模式其中之一:

  • 静态 URL
  • 动态 URL

静态 URL

通过设置 bfe.ingress.kubernetes.io/redirect.target ,配置静态重定向目标URL

bfe.ingress.kubernetes.io/redirect.target: "https://www.baidu.com"

对应示例

动态 URL

通过设置 bfe.ingress.kubernetes.io/redirect.cmd 、 bfe.ingress.kubernetes.io/redirect.params ,配置静态重定向目标URL

设置 Scheme

bfe.ingress.kubernetes.io/redirect.cmd: SCHEME_SET
bfe.ingress.kubernetes.io/redirect.params: '["http"]'

对应示例

从Query中获得URL

bfe.ingress.kubernetes.io/redirect.cmd: URL_FROM_QUERY
bfe.ingress.kubernetes.io/redirect.params: '["url"]'

对应示例

添加前缀

bfe.ingress.kubernetes.io/redirect.cmd: URL_PREFIX_ADD
bfe.ingress.kubernetes.io/redirect.params: '["http://www.baidu.com/redirect"]'

对应示例

https://www.bfe-networks.net/en_us/modules/mod_redirect/mod_redirect/

@loheagn
Copy link
Contributor

loheagn commented Jun 28, 2022

需求细化

同类产品调查

本部分主要调研了当前比较流行的两款是Ingress Controller的重定向功能的实现:Nginx IngressTraefik Ingress

Nginx Ingress Traefik Ingress
静态重定向 可以将当前Ingress中定义的所有Rule重定向到一个固定的地址 可以使用正则表达式指定哪些路径需要被重定向
HTTPS重定向 支持 通过重定向到不同的entry-point来实现
www重定向 支持 通过重定向到不同的entry-point来实现
动态重定向,即从Request中取值作为重定向的location 不支持 不支持

需求场景分析

下面将结合租户使用BFE Ingress重定向的几种具体场景和BFE Ingress实现的可行性进行具体的需求分析。由于BFE Ingress的各种能力本质上是由BFE Engine提供的,所以,在进行需求分析时,必须BFE Engine当前具备的重定向能力

  1. 租户希望将当前Ingress中的所有定义的路由全部重定向到某个固定的地址。BFE Engine中可以使用URL_SET Action实现。

  2. 租户希望根据客户端发起请求的内容,动态给出不同的重定向地址,即租户希望重定向的地址动态地从Request中获取。此时,可能有以下几种情况:

    • 重定向地址来自URL中的Query参数
    • 重定向地址来自Request的Header,比如租户可以使用一些自定义的Header(如X-Redirct-Location
    • 重定向地址来自Request的body中的特定字段
    • 重定向地址可能不会直接来自Request中的字段,而是使用更灵活的拼接方式。举例来说,租户可能希望根据客户端的不同(例如,使用DeviceID作为区分)来指定不同的重定向地址

    对于重定向地址来自于URL中的Query参数的情况,BFE Engine提供了URL_FROM_QUERY Action的实现

    对于从Header中取值和“更灵活的拼接方式”,从必要性角度,目前没有已知的特定的场景应用;从可行性角度,当前BFE Engine并没有提供相应的实现,所以这两个需求场景当前不予支持。对于从Request中的Body中取值,这要求BFE Engine不仅要解析Request的头部信息,还要解析Request的body内容,而且大部分情况下,body中的内容是经过加密的,而且其内容格式并不统一(可能是纯文本,也可能是二进制),该场景从必要性和可行性的角度,当前都没有支持的必要。

  3. 租户对业务整体的域名或API格式做替换,例如,旧的业务API格式是https://example.old.org/api/yyy/xxx,而现在希望将所有API格式迁移为https://example.new.org/api/v2/yyy/xxx

    当前BFE Engine仅支持将就的URL的协议、域名、端口号替换为新的协议、域名、端口号,并添加Path前缀。即,当前BFE Engine不支持将https://example.old.org/api/yyy/xxx重定向到https://example.new.org/api/v2/yyy/xxx,而仅支持将https://example.old.org/api/yyy/xxx重定向到https://example.new.org/newPath/api/yyy/xxx。而这一功能是通过URL_PREFIX_ADD Action实现的。

  4. 租户希望将用户的HTTP请求重定向到HTTPS,或者将HTTPS的请求重定向到HTTP。BFE Engine中可以使用SET_SCHEME Action实现。

除了重定向的Location取值,租户也会有自定义重定向返回的状态码。可以考虑将状态码的设置作为可选项。默认设置返回的状态码为302,并允许租户使用注解的方式自定义之。具体地,对于永久重定向需求,租户可以设置状态码为301或308,对于暂时重定向需求,租户可以选择设置状态码为302、303、307。对于各个状态码的具体使用规范,请参考RFC相关文档

总结

租户使用场景 BFE Engine的实现 BFE Ingress的实现 示例 默认状态码
将当前Ingress中的所有Rule都重定向到某个地址 Redirect模块中的URL_SET action bfe.ingress.kubernetes.io/redirect.url-set bfe.ingress.kubernetes.io/redirect.url-set: "https://www.baidu.com"
所有符合当前Ingress中Rule的请求都会被重定向到 https://www.baidu.com
302
使用query参数指定重定向地址 Redirect模块中的URL_FROM_QUERY action bfe.ingress.kubernetes.io/redirect.url-from-query
bfe.ingress.kubernetes.io/redirect.url-from-query: "redirectURL"
https://example.org?redirectURL=https://www.baidu.com 重定向到 https://www.baidu.com
302
对业务整体的域名或API格式做替换,例如,旧的业务API格式是https://example.old.org/api/yyy/xxx,而现在希望将所有API格式迁移为https://example.new.org/newPath/api/yyy/xxx Redirect模块中的URL_PREFIX_ADD action bfe.ingress.kubernetes.io/redirect.url-prefix-add bfe.ingress.kubernetes.io/redirect.url-prefix-add: "https://www.baidu.com/prefix"
https://example.org/yyy/xxx 重定向到 https://www.baidu.com/prefix/yyy/xxx
302
将用户的HTTP请求重定向到HTTPS,或将HTTPS重定向到HTTP Redirect模块中的SCHEME_SET action bfe.ingress.kubernetes.io/redirect.set-scheme bfe.ingress.kubernetes.io/redirect.set-scheme: https 302

状态码

上述状态码是各个场景的默认值,租户可以手动使用注解bfe.ingress.kubernetes.io/redirect.response-status指定Response的状态码,可选值有 301、302、303、307、308。

@loheagn
Copy link
Contributor

loheagn commented Jun 28, 2022

设计方案

主要任务

将租户给出的Ingress定义,翻译成BFE Engine的配置文件中的mod_redirect/redirect.data

“源文件”:Ingress定义

在本次开发中,Ingress作为“翻译”的“源文件”,我们主要关注两点:

  1. 重定向流量的识别条件。这其中包括

    • Ingress对路由的Host和Path定义
    • 路由相关的Annotation,包括bfe.ingress.kubernetes.io/router.cookiebfe.ingress.kubernetes.io/router.header
  2. 重定向行为的配置参数,即Ingress中与重定向相关的BFE Ingress Annotation。

    • 指定如何获取重定向的Location的Annotation(注意,以下注解在同一个Ingress资源中最多使用一个):
      • bfe.ingress.kubernetes.io/redirect.url-set
      • bfe.ingress.kubernetes.io/redirect.url-from-query
      • bfe.ingress.kubernetes.io/redirect.url-prefix-add
      • bfe.ingress.kubernetes.io/redirect.scheme-set
    • 指定重定向返回的Response的状态码的Annotation
      • bfe.ingress.kubernetes.io/redirect.response-status

其中,关于Annotation的作用和解释,详见需求部分的讨论

目标文件:mod_redirect/redirect.data

详细目标文件的定义可以参考BFE Engine文档

下面是一个例子:

{
    "Version": "20190101000000",
    "Config": {
        "example_product": [
            {
                "Cond": "req_path_prefix_in(\"/redirect\", false)",
                "Actions": [
                    {
                        "Cmd": "URL_SET",
                        "Params": ["https://example.org"]
                    }
                ],
                "Status": 301
            }
        ]
    }
}

可以看到,每个产品线会对应一条重定向规则。每个重定向规则包括:

  • CondBFE条件原语表达式,用来指定哪些Request需要被重定向
  • Actions:指定“应该怎样进行重定向”,即如何获取重定向的Location。该参数是一个列表,由一个Action组成。其中,每个Action又包括:
    • Cmd:指出获取重定向Location的方式,可选URL_SETURL_FROM_QUERYURL_PREFIX_ADDSET_SCHEME
    • Params:上述Cmd的参数,其为一个字符串数组,在目前BFE Engine的重定向实现中,仅支持填充一个字符串
  • Status:重定向返回的Response的状态码

实现方案

由于当前BFE Ingress生成配置文件仅包含DEFAULT_PRODUCT产品线。因此,最终生成的mod_redirect/redirect.data应该类似于:

{
    "Version": "version",
    "Config": {
        "DEFAULT_PRODUCT": [
            {
                "Cond": "req_path_prefix_in(\"/redirect\", false)",
                "Actions": [
                    {
                        "Cmd": "URL_SET",
                        "Params": ["https://example.org"]
                    }
                ],
                "Status": 302
            },
            {
                "Cond": "req_path_prefix_in(\"/redirect\", false)",
                "Actions": [
                    {
                        "Cmd": "SCHEME_SET",
                        "Params": ["https"]
                    }
                ],
                "Status": 302
            },
            
            // ......
            
        ]
    }
}

由于BFE Engine对路由和重定向等的配置是基于“HTTP Rule”的。即,对不同的“HTTP Rule”有不同的路由规则和重定向规则。而一个Ingress对象中包含多个Host和Path,即会被BFE Ingress解析为多个“HTTP Rule”。因此,我们需要将一个Ingress对象解析为多条“HTTP Rule”后,再针对每条“HTTP Rule”生成对应的重定向规则。

Cond

将Ingress中的Host和Path描述的Rule转换成BFE的条件原语表达的表达式。

如上所述,一个重定向规则对应着一个“HTTP Rule”。因此,这里的Cond表达式可以复用在生成路由配置时从Ingress中解析出来的“HTTP Rule”的Cond表达式。

Action

ActionCmdParams组成。

AnnotationCmd的映射关系如下:

  • bfe.ingress.kubernetes.io/redirect.url-set -> URL_SET
  • bfe.ingress.kubernetes.io/redirect.url-from-query -> URL_FROM_QUERY
  • bfe.ingress.kubernetes.io/redirect.url-prefix-add -> URL_PREFIX_ADD
  • bfe.ingress.kubernetes.io/redirect.scheme-set -> SCHEME_SET

生成的Params则是包含一个字符串的字符串数组,其中的字符串即为上述Annotation的值。

Status

Status 将从 bfe.ingress.kubernetes.io/redirect.reponse-status 中读取。如果无法读到,默认为302。

@zhugelianglongming
Copy link
Member Author

zhugelianglongming commented Jul 4, 2022

我们主要关注两点

  • 重定向流量的识别条件
  • 重定向行为的配置参数

需求场景分析

建议补充&更正下场景的描述和分析

bfe.ingress.kubernetes.io/redirect.status

bfe.ingress.kubernetes.io/redirect.response-status 是不是表意更明确些?

同类产品调查

建议补充相关引用链接

@zhugelianglongming
Copy link
Member Author

zhugelianglongming commented Jul 4, 2022

2. Ingress中与重定向相关的BFE Ingress Annotation

建议分类描述,如配置重定向的地址和返回状态码

目标文件:mod_redirect/redirect.data

建议补充主要字段的简单介绍

            // ingress1 生成:
            {
                "Cond": "req_path_prefix_in(\"/redirect\", false)",
                "Actions": [
                    {
                        "Cmd": "URL_SET",
                        "Params": ["https://example.org"]
                    }
                ],
                "Status": 302
            },

1 个Ingress 资源文件生成一条 redirect 规则存在隐患,需考虑Ingress场景中路由匹配优先级的因素。

Cond

将Ingress中的Host和Path描述的Rule转换成BFE的条件原语表达的表达式。

需要结合考虑下 Header、Cookie 甚至未来添加的其他匹配条件

生成的Params则是包含一个字符串的字符串数组,其中的字符串即为上述Annotation的值。

建议补充具体的参数说明

@loheagn
Copy link
Contributor

loheagn commented Jul 14, 2022

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants