Envoy 配置及策略
Envoy 的配置使用
https://www.envoyproxy.io/docs
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
| # 启动一个 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配置文件结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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
比较老旧的写法了
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 52 53 54 55 56 57 58 59 60 61 62
| 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 config: stat_prefix: ingress_http codec_type: AUTO route_config: name: myroute1 virtual_hosts: - name: local_service domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: some_service } http_filters: - name: envoy.filters.http.router clusters: - name: some_service connect_timeout: 0.25s type: STATIC dns_lookup_family: V4_ONLY lb_policy: ROUND_ROBIN hosts: [ { socket_address: { address: 172.17.0.2, port_value: 80 }}
]
|
Filter的写法语法1
name: 指定使用哪个过滤器
config:
参数1:值1
参数2:值2
。。。
这里选择什么参数,要看name里选择的什么参数要根据所选择的过滤器来判定
和http相关的,一般选择 HTTP connection manager。
在https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/filter/filter里找参数
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。
在 https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/filter/filter 里找参数
name的位置应该写envoy.filters.network.http_connection_manager
@type的值到文档里找具体的值
vim envoy.yaml
现在的写法有所改动
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 52 53 54
| 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 stat_prefix: ingress_http codec_type: AUTO route_config: name: myroute1 virtual_hosts: - name: local_service domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: some_service } http_filters: - name: envoy.filters.http.router clusters: - name: some_service connect_timeout: 0.25s type: STATIC dns_lookup_family: V4_ONLY 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
|
使用 lua
vim envoy.yaml
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 52 53 54 55 56
| 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 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 typed_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 - name: envoy.filters.http.router typed_config: {} clusters: - name: some_service connect_timeout: 0.25s type: STATIC_DNS 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的字段,添加特定的过滤器,甚至添加全新的监听器、集群等。必须谨慎使用此功能
1 2 3 4 5 6 7 8 9 10 11 12
| docker ps | grep pod1 #k8s_istio_proxy_pod1_ns1 #k8s_pod1_pod1_ns1
docker top 713f7358dbf8 #sidecar 的 conternerId #运行了两个主要的进程 # /usr/local/bin/pilot-agent proxy sidecar ... # /usr/local/bin/envoy -c etc/istio/proxy/envpy-rev0.json
#查看 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
举个例子:
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| mkdir chap6 && cd chap6 kubectl get pods -n istio-system -l istio=ingressgateway
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
kubectl apply -f ef1.yaml kubectl get envoyFilter -n istio-system
curl -I aa.yuan.cc
-----------------------------------------------------------
kubectl delete -f ef1.yaml vim ef2.yaml
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: addheader-into-ingressgateway namespace: istio-system spec: workloadSelector: labels: istio: ingressgateway configPatches: - applyTo: HTTP_FILTER match: context: GATEWAY proxy: proxyVersion: '^1\.10.*' 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) 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
kubectl apply -f ef2.yaml
curl -I aa.yuan.cc
|