Envoy 配置及策略

853 阅读5分钟

Envoy 配置及策略

Envoy 的配置使用

www.envoyproxy.io/docs

# 启动一个 nginx 环境
docker pull nginx
docker run -dit --name=web nginx
docker exec -it web bash
/# echo 111 > /usr/share/nginx/html/index.html
/# exit
docker inspect web | grep -i ipaddress
# 172.17.0.2
​
​
# 启动 envoy
docker pull envoyproxy/envoy:latest
​
# 先将下面的 envoy 配置文件写了再启动
docker run -d -p 10000:10000 -v /root/envoy.yaml:/etc/envoy/envoy.yaml --name myenvoy envoyproxy/envoy:latest
# 关键是在于写 envoy 的配置文件 envoy.yaml
docker logs myenvoy
​
#修改hosts
vim /etc/hosts
192.168.26.23<本级IP> bb.yuan.cc bb
​
# 客户端测试, envoy设置了: domains: [bb.yuan.cc]  #只转发此条
curl bb.yuan.cc bb:10000
#没有返回
curl -H "Host: bb.yuan.cc" bb.yuan.cc bb:10000
#返回111

Envoy配置文件结构

listen -- 监听器
    1.我监听的地址
    2.过滤链
        filter1
            路由: 转发到哪里
                virtual_hosts
                    只转发什么
                    转发到哪里 --> 由后面的 cluster 来定义
        filter2
        filter3
        #envoyproxy.io/docs/envoy/v1.19.1/api-v3/config/filter/filter
cluster
    转发规则
    endpoints
        --指定了我的后端地址

vim envoy.yaml 比较老旧的写法了

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 127.0.0.1, port_value: 9901 }  #定义管理

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 10000 }  #要监听的地址
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager #指明使用哪个过滤器,这个是做普通的转发
        #typed_config:
        #  "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
        # extensions.filters.network.http_connection_manager.v3.HttpConnectionManager 为具体值,type.googleapis.com/envoy为固定前缀
        config:
          stat_prefix: ingress_http
          codec_type: AUTO  #都允许
          #codec_type: HTTP2  #只允许HTTP2协议访问,(如果是访问nginx容器,要先开启nginx的http2)
          #access_log:  #添加访问日志
          #- name: envoy.file_access_log
          #  config:
          #    path: "/tmp/aa.log"
          route_config:
            name: myroute1
            virtual_hosts:
            - name: local_service
              domains: ["*"]  #都允许
              #domains: [bb.yuan.cc]  #只转发此条
              routes:
              - match: { prefix: "/" }
              #- match: { prefix: "/demo1" } #只匹配 相对目录 的 demo1 目录
                route: { cluster: some_service }  #可以自定义名字
            #- name: local_service2
            #  domains: ["cc.yuan.cc"] 
            #  routes:
            #  - match: { prefix: "/" }
            #    route: { cluster: some_service2 }              
          http_filters:
          #- name: envoy.router  #旧的写法,快被废弃了
          - name: envoy.filters.http.router 
  clusters: 
  - name: some_service  #与上面route对应
    connect_timeout: 0.25s
    type: STATIC
    #type: LOGICAL_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [  #指定后端地址
      #{ socket_address: { address: 192.168.26.23, port_value: 808 }},
      { socket_address: { address: 172.17.0.2, port_value: 80 }}

    ]
  #- name: some_service2  #与上面route对应
  #  connect_timeout: 0.25s
  #  type: STATIC
  #  dns_lookup_family: V4_ONLY
  #  lb_policy: ROUND_ROBIN
  #  hosts: [
  #    { socket_address: { address: 172.17.0.4, port_value: 80 }}
  #  ]

Filter的写法语法1

name: 指定使用哪个过滤器

config:

参数1:值1

参数2:值2

。。。

这里选择什么参数,要看name里选择的什么参数要根据所选择的过滤器来判定

和http相关的,一般选择 HTTP connection manager。

www.envoyproxy.io/docs/envoy/…里找参数

name的位置应该写envoy.filters.network.http_connection_manager

http_connection_manager 常见的参数包括:

codec_type -- 可选值为AUTO(默认)、HTTP1、

HTTP2

stat_prefix

route_config

http_filters

access_log

Filter的写法语法2

name: 指定使用哪个过滤器

typed_config:

"@type": type.googleapis.com/envoy.过滤器的具体值

参数1:值1

参数2:值2

。。。

这里选择什么参数,要看name里选择的什么参数要根据所选择的过滤器来判定

和http相关的,一般选择 HTTP connection manager。

www.envoyproxy.io/docs/envoy/… 里找参数

name的位置应该写envoy.filters.network.http_connection_manager

@type的值到文档里找具体的值

vim envoy.yaml 现在的写法有所改动

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 127.0.0.1, port_value: 9901 }  #定义管理

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 10000 }  #要监听的地址
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager #指明使用哪个过滤器,这个是做普通的转发
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
        # extensions.filters.network.http_connection_manager.v3.HttpConnectionManager 为具体值,type.googleapis.com/envoy为固定前缀
        #config:
          stat_prefix: ingress_http
          codec_type: AUTO  #都允许
          route_config:
            name: myroute1
            virtual_hosts:
            - name: local_service
              domains: ["*"]  #都允许
              #domains: [bb.yuan.cc]  #只转发此条
              routes:
              - match: { prefix: "/" }
                route: { cluster: some_service } 
          http_filters:
          - name: envoy.filters.http.router 
  clusters: 
  - name: some_service  #与上面route对应
    connect_timeout: 0.25s
    type: STATIC
    #type: LOGICAL_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    #hosts: [ 
    #  { socket_address: { address: 172.17.0.2, port_value: 80 }}
    #]
    load_assignment:
      cluster_name: some_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 172.17.0.2
                port_value: 80
        #- endpoint:
        #    address:
        #      socket_address:
        #        address: 172.17.0.4
        #        port_value: 80

使用 lua

vim envoy.yaml

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 127.0.0.1, port_value: 9901 }  #定义管理
static_resources:
  listeners:
  - name: main
    address:
      socket_address: 
        address: 0.0.0.0  #要监听的地址
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager #指明使用哪个过滤器,这个是做普通的转发
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
        # extensions.filters.network.http_connection_manager.v3.HttpConnectionManager 为具体值,type.googleapis.com/envoy为固定前缀
        #config:
          stat_prefix: ingress_http
          codec_type: AUTO  #都允许
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: 
              - "*"
              routes:
              - match: 
                  prefix: "/"
                route: 
                  cluster: some_service
          http_filters:
          - name: envoy.filters.http.lua #修改为 lua
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
              #inline_code:
              inlineCode: |
                function envoy_on_response(response_handle)
                  response_handle:headers():add("X-User-Header","===X====")
                end
          - name: envoy.filters.http.router
            typed_config: {}
  clusters: 
  - name: some_service  #与上面route对应
    connect_timeout: 0.25s
    type: STATIC_DNS  #static
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: some_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 172.17.0.2
                port_value: 80

EnvoyFilter

EnvoyFilter用来自定义 Istio Pilot 生成的 Envoy 配置。使用 EnvoyFilter 可以修改某些

envoy的字段,添加特定的过滤器,甚至添加全新的监听器、集群等。必须谨慎使用此功能

docker ps | grep pod1
#k8s_istio_proxy_pod1_ns1  #sidecar
#k8s_pod1_pod1_ns1  #业务容器,nginx
​
docker top 713f7358dbf8  #sidecar 的 conternerId
#运行了两个主要的进程
# /usr/local/bin/pilot-agent proxy sidecar ...
# /usr/local/bin/envoy -c etc/istio/proxy/envpy-rev0.json #envoy 的配置文件有两种,静态|动态#查看 envoyFilter 
kubectl get envoyFilter
#No resources found in ns1 namespace

workloadSelector: 用于指定作用在谁

configPatches:用于配置补丁,下面的属性包括3个大类

  • apply_To: 应用到谁

match:指定匹配规则

patch:新的规则

applyTo: 给哪个位置打补丁,可用的值包括

INVALID

LISTENER #将补丁应用到监听器

FILTER_CHAIN #将补丁应用到过滤器链

NETWORK_FILTER #将补丁应用到网络过滤器链

HTTP_FILTER #将补丁应用到HTTP过滤器链

ROUTE_CONFIGURATION

VIRTUAL_HOST

HTTP_ROUTE

CLUSTER

match:

context: SIDECAT_OUTBOUNT/SIDECAR_INBOUNT/GATEWAY(弃用)

listener:

name: 格式为ip:端口

portNumber:

filterChain:

filter:

name: 这4行用于定义过滤器

格式为 envoy.filters.network.http_connection_manager

patch:

operation: 操作的意思,对应值有

MERG

ADD

REMOVE

INSERT_BEFOR

INSERT_AFTER

value

举个例子

mkdir chap6 && cd chap6
kubectl get pods -n istio-system -l istio=ingressgateway
#istio-ingressgateway-5h354d356-jdmc4
​
vim ef1.yaml
​
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: lua-filter
  namespace: istio-system  #指定命名空间
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: "envoy.filters.network.http_connection_manager"
            subFilter:
              name: "envoy.filters.http.router"
    patch:
      operation: INSERT_BEFORE  #插入过滤器
      value:
        name: envoy.filters.http.lua  #插入此过滤器
        type_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          inlineCode: |
             function envoy_on_response(response_handle)
                 response_handle:headers():add("X-User-Header","===X===")
             end
​
# 启动 envoyFilter
kubectl apply -f ef1.yaml
kubectl get envoyFilter -n istio-system
#lua-filter
curl -I aa.yuan.cc
# x-user-header: ===X===  #改变了标题的报文信息
​
​
-----------------------------------------------------------
​
​
kubectl delete -f ef1.yaml
vim ef2.yaml  #阿里云提供的一个demo,用此作些修改
​
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: addheader-into-ingressgateway
  namespace: istio-system  #指定命名空间
spec:
  workloadSelector:
    # select by label in the same namespace
    labels:
      istio: ingressgateway
  configPatches:
    # The Envoy config you want to modify
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      proxy:
        proxyVersion: '^1.10.*'  #改为自己 istio 的版本
      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: envoy.filters.http.lua  #插入此过滤器
        type_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          inlineCode: |-
             function envoy_on_response(response_handle)
                 function hasFrameAncestors(rh)
                 s = rh:headers():get("Content-Security-Policy");
                 delimiter = ";";
                 defined = false;
                 for match in (s..delimiter):gmatch("(.-)"..delimiter) do
                     match = match:gsub("%s+", "");
                     if match:sub(1,15)=="frame-ancestors" then
                     return true;
                     end
                 end
                 return false;
                 end
                 if not response_handle:headers():get("Content-Security-Policy") then
                 csp = "frame-ancestors none;";
                 response_handle:headers():add("Content-Security-Policy", csp);
                 elseif response_handle:headers():get("Content-Security-Policy") then
                 if not hasFrameAncestors(response_handle) then
                     csp = response_handle:headers():get("Content-Security-Policy");
                     csp = csp .. ";frame-ancestors none;";
                     response_handle:headers():replace("Content-Security-Policy", csp);
                 end
                 end
                 if not response_handle:headers():get("X-Frame-Options") then
                 response_handle:headers():add("X-Frame-Options", "deny");
                 end
                 if not response_handle:headers():get("X-XSS-Protection") then
                 response_handle:headers():add("X-XSS-Protection", "1; mode=block");
                 end
                 if not response_handle:headers():get("X-Content-Type-Options") then
                 response_handle:headers():add("X-Content-Type-Options", "nosniff");
                 end
                 if not response_handle:headers():get("Referrer-Policy") then
                 response_handle:headers():add("Referrer-Policy", "no-referrer");
                 end
                 if not response_handle:headers():get("X-Download-Options") then
                 response_handle:headers():add("X-Download-Options", "noopen");
                 end
                 if not response_handle:headers():get("X-DNS-Prefetch-Control") then
                 response_handle:headers():add("X-DNS-Prefetch-Control", "off");
                 end
                 if not response_handle:headers():get("Feature-Policy") then
                 response_handle:headers():add("Feature-Policy", 
                                                 "camera 'none';"..
                                                 "microphone 'none';"..
                                                 "geolocation 'none';"..
                                                 "encrypted-media 'none';"..
                                                 "payment 'none';"..
                                                 "speaker 'none';"..
                                                 "usb 'none';")..
                 end
                 if response_handle:headers():get("X-Powered-By") then
                 response_handle:headers():remove("X-Powered-By");
                 end
             end
                 
# 应用 ef2
kubectl apply -f ef2.yaml
# 测试
curl -I aa.yuan.cc
# 加入了对应的信息
​