Envoy 配置及策略
Envoy 的配置使用
# 启动一个 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
# 加入了对应的信息