bfenetworks / ingress-bfe

BFE Ingress Controller for Kubernetes
Apache License 2.0
91 stars 25 forks source link

Header重写 #55

Open zhugelianglongming opened 2 years ago

zhugelianglongming commented 2 years ago

背景

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

配置方式

Ingress 资源内

参考格式:

metadata:
    annotations:
        bfe.ingress.kubernetes.io/rewrite-header.actions: '[{}]'
spec:
  rules:
  - ...

重写请求 Header

通过设置 bfe.ingress.kubernetes.io/rewrite-header.actions ,配置请求 Header 修改规则。 支持:

添加

bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_ADD", "params": ["key", "value"]}]'

修改

bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_SET", "params": ["key", "value"]}]'

删除

bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_DEL", "params": ["key"]}]'

重写响应 Header

通过设置 bfe.ingress.kubernetes.io/rewrite-header.actions ,配置响应 Header 修改规则。 支持:

添加

bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_ADD", "params": ["key", "value"]}]'

修改

bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_SET", "params": ["key", "value"]}]'

删除

bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_DEL", "params": ["key"]}]'

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

QingyanMu commented 1 year ago

Header重写需求

需求简介

BFE 支持对流量的Header重写,通过添加、删除制定header定义修改覆盖的流量范围,通过修改指定header定位修改header的行为。

将租户的配置文件通过annotations解析后转换为BFE引擎的相关配置文件,再经BFE引擎热加载实现流量的Header重写。

同类汇总

功能 NGINX Ingress Kong Traefik haproxy voyager Contour
重写请求header 支持添加、重定义header 支持修改header 支持添加、修改、删除header 支持添加、修改、删除header 支持修改header 支持修改header
重写响应header 支持添加、修改header,支持将header值设置为 void删除header 支持修改header 支持修改header 支持添加、修改、删除header 不支持 支持修改header

需求分析

在mod_header中,提供对请求和响应增加其他信息的能力,对流量的Header重写只需关注定位修改Header的行为。

可以对每个租户提供包含cond、Actions、Last的配置表来让租户自定义需要透传的信息。

Annotation设计

需求描述 BFE 引擎实现 BFE Ingress实现 示例
为请求添加指定 Header REQ_HEADER_ADD bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_ADD", "params": ["key", "value"]}]' bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_ADD", "params": ["example", "_1"]}]'
Headerexample的值的末尾拼接_1
修改请求的Header REQ_HEADER_SET bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_SET", "params": ["key", "value"]}]' bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_SET", "params": ["example", "example"]}]'
Headerexample的值为example
删除请求的 Header REQ_HEADER_DEL bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_DEL", "params": ["key"]}] bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_DEL", "params": ["example"]}]
删除Header中example的值
为响应添加指定 Header RSP_HEADER_ADD bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_ADD", "params": ["key", "value"]}]' bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_ADD", "params": ["X-Proxied-By", "system"]}]'
HeaderX-Proxied-By的值的末尾拼接system
修改响应的Header RSP_HEADER_SET bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_SET", "params": ["key", "value"]}]' bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_SET", "params": ["X-Proxied-By", "bfe"]}]'
设置HeaderX-Proxied-By的值为bfe
删除响应的 Header RSP_HEADER_DEL bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_DEL", "params": ["key"]}]' bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_DEL", "params": ["X-Proxied-By"]}]'
删除Header中X-Proxied-By的值

设计方案

主要任务

Ingress配置文件翻译成BFE Engine的配置文件中的mod_header/header_rule.data

Ingress配置

根据Ingress涉及的两个方面展开:

  1. spec.rules 对路由规则的定义
    • 设置路由的Host和Path
    • Annotation方式设置对Header的高级匹配条件:bfe.ingress.kubernetes.io/router.header
  2. 修改header行为的相关设置
    • 修改请求Header
      • bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_ADD", "params": ["key", "value"]}]'
      • bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_SET", "params": ["key", "value"]}]'
      • bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_DEL", "params": ["key"]}]'
    • 修改响应Header
      • bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_ADD", "params": ["key", "value"]}]'
      • bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_SET", "params": ["key", "value"]}]'
      • bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_DEL", "params": ["key"]}]'

实现方案

租户给出的Ingress配置:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-ingress
  namespace: ingress-bfe
  annotations:
    kubernetes.io/ingress.class: bfe  
    bfe.ingress.kubernetes.io/router.cookie: "Session: 123"
    bfe.ingress.kubernetes.io/router.header: "Content-Language: zh-cn"
    bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_SET", "params": ["X-Bfe-Log-Id", "%bfe_log_id"]}]'
    bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "REQ_HEADER_SET", "params": ["X-Bfe-Vip", "%bfe_vip"]}]'
    bfe.ingress.kubernetes.io/rewrite-header.actions: '[{"cmd": "RSP_HEADER_SET", "params": ["X-Proxied-By", "bfe"]}]'

spec:
  rules:
  - host: whoami.com
    http:
      paths:
      - path: /testpath
        pathType: Prefix
        backend:
          service:
            name: whoami
            port:
              number: 80

Ingress配置文件中,共有四个字段。kindapiVersionmetadataspec

Header重写配置

{
    "Version": "20230201000000",
    "Config": {
        "example_product": [
            {
                "cond": "req_path_prefix_in(\"/header\", false)",
                "actions": [
                    {
                        "cmd": "REQ_HEADER_SET",
                        "params": [
                            "X-Bfe-Log-Id",
                            "%bfe_log_id"
                        ]
                    },
                    {
                        "cmd": "REQ_HEADER_SET",
                        "params": [
                            "X-Bfe-Vip",
                            "%bfe_vip"
                        ]
                    },
                    {
                        "cmd": "RSP_HEADER_SET",
                        "params": [
                            "X-Proxied-By",
                            "bfe"
                        ]
                    }
                ],
                "last": true
            }
        ]
    }
}
ps1976 commented 1 year ago

请确认Ingress的rewrite-header.actions有多个时,annotation是一行还是多行 rewrite-header.actions的参数是json数组,因此多个action时一行annotation更加合理,如下所示 bfe.ingress.kubernetes.io/rewrite-header.actions: |- [ {"cmd": "REQ_HEADER_ADD", "params": ["key", "value"]}, {"cmd": "REQ_HEADER_SET", "params": ["key", "value"]}, {"cmd": "REQ_HEADER_DEL", "params": ["key"]} ]

zhugelianglongming commented 1 year ago

Annotation设计

@QingyanMu Rewrite 的 hook 点 是一个很可能需要扩展的配置点,设计的时候建议考虑兼容