• EnvoyFilter实践: 通过解析子域名注入环境标识


    背景

    在基于istio的多环境治理场景, 需要用户访问服务时带上环境标识来进行流量染色, 如

    curl -H 'x-demo-env: feature-1' http://demo.com/x/y/z
    
    • 1

    上述的feature-1即为环境标识(可能是环境uuid或者可读的id等).

    那么在istio vs中就可以通过识别http header来路由到特定环境, 这样就能做到最基本的路由策略:
    同环境内优先路由, 否则回落到基线环境.
    istio相应的VS大致如下:

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    spec:
      gateways:
      - demo-internal/demo-default-gw
      hosts:
      - app1-service
      http:
      - match:
        - headers:
            x-demo-env:
              exact: feature-1
        route:
        - destination:
            host: app1 
            port:
              number: 8000
            subset: feature-1 
      - match: []  # fallback to base env
        route:
        - destination:
            host: app1
            port:
              number: 8000
            subset: base
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    istio相应的DR如下:

    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    spec:
      host: app1-service
      subsets:
      - name: feature-1 
        labels:
          x-demo-env: feature-1 
      - name: base
        labels:
          x-demo-env: base
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    问题

    上述实现中规中矩, 但是在web场景下有个体验问题:
    用户需要通过浏览器插件或者其他手段来注入header: x-demo-env: feature-1.
    如果用户用的是ie或者其他不支持特定插件的浏览器的话, 通过浏览器就没法用了.

    通过EnvoyFilter自动注入环境标识

    由于是在内网环境, 我们可以通过DNS平台提供的接口创建子域名:
    feature-1.demo.com, feature-2.demo.com, …
    即将环境标识直接作为域名的一部分, 然后在istio gateway处通过EnvoyFilter将环境标识提取出来, 自动注入header, 这样体验会更好一些.

    此时用户访问流程如下:
    通过EnvoyFilter注入header

    相应的EnvoyFilter代码简化如下:

    apiVersion: networking.istio.io/v2alpha3
    kind: EnvoyFilter
    metadata:
      name: demo-inject-header
      namespace: istio-system
      labels:
        project: envoy-filter
        app: demo-inject-header
    spec:
      workloadSelector:
        # select by label in the same namespace
        labels:
          istio: ingressgateway
          app: istio-ingressgateway-demo-mesh
      configPatches:
        # The Envoy config you want to modify
      - applyTo: HTTP_FILTER
        match:
          context: GATEWAY
          proxy:
            proxyVersion: '^1\.1\d.*' # 这里根据实际情况可以写死
          listener:
            filterChain:
              filter:
                name: "envoy.filters.network.http_connection_manager"
                subFilter:
                  name: "envoy.filters.http.router"
        patch:
          operation: INSERT_BEFORE
          value: # lua filter specification
            name: demo-mesh.tof.checklogin.envoy.lua
            typed_config:
              "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
              inlineCode: |-
                function envoy_on_request(request_handle)
                  local host = request_handle:headers():get(":authority")
                  
                  -- host 应该匹配 [^.]+.demo.com 
                  local domainRe = prefix.."([^.]+)%.demo%.com"
                  local dyeingKey = host:match(domainRe) or ""
    
                  if  (not dyeingKey) or (string.len(dyeingKey) <= 0) then
                    request_handle:logWarn("not demo mesh host:"..host))
                    return
                  end
    
                  -- 将子域名转为染色key header
                  request_handle:logInfo("host:"..host.."|dyeingKey:"..tostring(dyeingKey))
                  -- 注意这里要用replace()而不是add(), 否则用户如果手动传了x-demo-env会有问题.
                  request_handle:headers():replace('x-demo-env', dyeingKey)
                end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    上述的inlineCode部分是lua代码, 相关文档参考:
    https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/lua_filter#configuration

    参考

    1. EnvoyFilter lua语法: https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/lua_filter#configuration

    (完)

  • 相关阅读:
    js内置对象Date
    Linux locate命令报错:-bash: locate: command not found
    水库大坝安全管理主要问题和维护措施
    指针进阶(续)
    【无标题】
    浅谈语义分割、图像分类与目标检测中的TP、TN、FP、FN
    wrk HTTP打流测试工具
    在智能家居领域产品中常用芯片
    天马行空的超级炫酷旋转图片-前端
    Dynamsoft Barcode Reader 9.4.0
  • 原文地址:https://blog.csdn.net/butterfly5211314/article/details/126569281