本文转载自:Istio 的数据平面 Envoy Proxy 配置详解 - jimmysong.io
Envoy 是 Istio Service Mesh 中默认的 Sidecar,Istio 在 Enovy 的基础上按照 Envoy 的 xDS 协议扩展了其控制平面,在讲到 Envoy xDS 协议之前还需要我们先熟悉下 Envoy 的基本术语。下面列举了 Envoy 里的基本术语及其数据结构解析,关于 Envoy 的详细介绍请参考 Envoy 官方文档,至于 Envoy 在 Service Mesh(不仅限于 Istio) 中是如何作为转发代理工作的请参考网易云刘超的这篇深入解读 Service Mesh 背后的技术细节 以及理解 Istio Service Mesh 中 Envoy 代理 Sidecar 注入及流量劫持,本文引用其中的一些观点,详细内容不再赘述。
下面是您应该了解的 Enovy 里的基本术语:
我将在本文的后半部分解释以上术语与 Kubernetes、Istio 中概念之间的联系。
有一点需要大家注意,就是 Envoy 的 API 有 v1 和 v2 两个版本,从 Envoy 1.5.0 起 v2 API 就已经生产就绪了,为了能够让用户顺利的向 v2 版本的额 API 过度,Envoy 启动的时候设置了一个 --v2-config-only 的标志,Enovy 不同版本对 v1/v2 API 的支持详情请参考 Envoy v1 配置废弃时间表。
--v2-config-only
Envoy 的作者 Matt Klein 在 Service Mesh 中的通用数据平面 API 设计这篇文章中说明了 Envoy API v1 的历史及其缺点,还有 v2 的引入。v2 API 是 v1 的演进,而不是革命,它是 v1 功能的超集。
在 Istio 1.0 及以上版本中使用的是 Envoy 1.8.0-dev 版本,其支持 v2 的 API,同时在 Envoy 作为 Sidecar proxy 启动的使用使用了例如下面的命令:
$ /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev0.json --restart-epoch 0 --drain-time-s 45 --parent-shutdown-time-s 60 --service-cluster ratings --service-node sidecar~172.33.14.2~ratings-v1-8558d4458d-ld8x9.default~default.svc.cluster.local --max-obj-name-len 189 --allow-unknown-fields -l warn --v2-config-only
上面是都 Bookinfo 示例中的 rating pod 中的 sidecar 启动的分析,可以看到其中指定了 --v2-config-only,表明 Istio 1.0+ 只支持 xDS v2 的 API。
假如您使用 kubernetes-vagrant-centos-cluster 部署了 Kubernetes 集群并开启了 Istio Service Mesh,再部署 bookinfo 示例,那么在 default 命名空间下有一个名字类似于 ratings-v1-7c9949d479-dwkr4 的 Pod,使用下面的命令查看该 Pod 的 Envoy sidecar 的全量配置:
default
ratings-v1-7c9949d479-dwkr4
kubectl -n default exec ratings-v1-7c9949d479-dwkr4 -c istio-proxy curl http://localhost:15000/config_dump > dump-rating.json
将 Envoy 的运行时配置 dump 出来之后你将看到一个长 6000 余行的配置文件。关于该配置文件的介绍请参考 Envoy v2 API 概览。
Istio 会在为 Service Mesh 中的每个 Pod 注入 Sidecar 的时候同时为 Envoy 注入 Bootstrap 配置,其余的配置是通过 Pilot 下发的,注意整个数据平面即 Service Mesh 中的 Envoy 的动态配置应该是相同的。您也可以使用上面的命令检查其他 sidecar 的 Envoy 配置是否跟最上面的那个相同。
使用下面的命令检查 Service Mesh 中的所有有 Sidecar 注入的 Pod 中的 proxy 配置是否同步。
$ istioctl proxy-status PROXY CDS LDS EDS RDS PILOT VERSION details-v1-876bf485f-sx7df.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-5bf6d97f79-6lz4x 1.0.0 ...
istioctl 这个命令行工具就像 kubectl 一样有很多神器的魔法,通过它可以高效的管理 Istio 和 debug。
Istio envoy sidecar proxy 配置中包含以下四个部分。
每个部分中都包含静态配置与动态配置,其中 bootstrap 配置又是在集群启动的时候通过 sidecar 启动参数注入的,配置文件在 /etc/istio/proxy/envoy-rev0.json。
/etc/istio/proxy/envoy-rev0.json
Enovy 的配置 dump 出来后的结构如下图所示。
由于 bootstrap 中的配置是来自 Envoy 启动时载入的静态文件,主要配置了节点信息、tracing、admin 和统计信息收集等信息,这不是本文的重点,大家可以自行研究。
上图是 bootstrap 的配置信息。
Bootstrap 是 Envoy 中配置的根本来源,Bootstrap 消息中有一个关键的概念,就是静态和动态资源的之间的区别。例如 Listener 或 Cluster 这些资源既可以从 static_resources 静态的获得也可以从 dynamic_resources 中配置的 LDS 或 CDS 之类的 xDS 服务获取。
Listener 顾名思义,就是监听器,监听 IP 地址和埠,然后根据策略转发。
Listener 的特点
Listener 的数据结构
Listener 的数据结构如下,除了 name、address 和 filter_chains 为必须配置之外,其他都为可选的。
name
address
filter_chains
{ "name": "...", "address": "{...}", "filter_chains": [], "use_original_dst": "{...}", "per_connection_buffer_limit_bytes": "{...}", "metadata": "{...}", "drain_type": "...", "listener_filters": [], "transparent": "{...}", "freebind": "{...}", "socket_options": [], "tcp_fast_open_queue_length": "{...}", "bugfix_reverse_write_filter_order": "{...}" }
下面是关于上述数据结构中的常用配置解析。
10.254.74.159_15011
关于 Listener 的详细介绍请参考 Envoy v2 API reference - listener。
我们在这里所说的路由指的是 HTTP 路由,这也使得 Envoy 可以用来处理网格边缘的流量。HTTP 路由转发是通过路由过滤器实现的。该过滤器的主要职能就是执行路由表中的指令。除了可以做重定向和转发,路由过滤器还需要处理重试、统计之类的任务。
HTTP 路由的特点
Route 的数据结构
{ "name": "...", "virtual_hosts": [], "internal_only_headers": [], "response_headers_to_add": [], "response_headers_to_remove": [], "request_headers_to_add": [], "request_headers_to_remove": [], "validate_clusters": "{...}" }
envoy.http_connection_manager
http_filters.rds.route_config_name
virtual_hosts
关于 Route 的详细介绍请参考 Envoy v2 API reference - HTTP route configuration。
VirtualHost 即上文中 Route 配置中的 virtual_hosts,VirtualHost 是路由配置中的顶级元素。每个虚拟主机都有一个逻辑名称以及一组根据传入请求的 host header 路由到它的域。这允许单个 Listener 为多个顶级域路径树提供服务。基于域选择了虚拟主机后 Envoy 就会处理路由以查看要路由到哪个上游集群或是否执行重定向。
VirtualHost 的数据结构
下面是 VirtualHost 的数据结构,除了 name 和 domains 是必须配置项外,其他皆为可选项。
domains
{ "name": "...", "domains": [], "routes": [], "require_tls": "...", "virtual_clusters": [], "rate_limits": [], "request_headers_to_add": [], "request_headers_to_remove": [], "response_headers_to_add": [], "response_headers_to_remove": [], "cors": "{...}", "per_filter_config": "{...}", "include_request_attempt_count": "..." }
details.default.svc.cluster.local:9080
*
下面是一个实际的 VirtualHost 的例子,该配置来自 Bookinfo 应用的 details 应用的 Sidecar 服务。
{ "name": "details.default.svc.cluster.local:9080", "domains": [ "details.default.svc.cluster.local", "details.default.svc.cluster.local:9080", "details", "details:9080", "details.default.svc.cluster", "details.default.svc.cluster:9080", "details.default.svc", "details.default.svc:9080", "details.default", "details.default:9080", "10.254.4.113", "10.254.4.113:9080" ], "routes": [ { "match": { "prefix": "/" }, "route": { "cluster": "outbound|9080||details.default.svc.cluster.local", "timeout": "0s", "max_grpc_timeout": "0s" }, "decorator": { "operation": "details.default.svc.cluster.local:9080/*" }, "per_filter_config": { "mixer": { "forward_attributes": { "attributes": { "destination.service.uid": { "string_value": "istio://default/services/details" }, "destination.service.host": { "string_value": "details.default.svc.cluster.local" }, "destination.service.namespace": { "string_value": "default" }, "destination.service.name": { "string_value": "details" }, "destination.service": { "string_value": "details.default.svc.cluster.local" } } }, "mixer_attributes": { "attributes": { "destination.service.host": { "string_value": "details.default.svc.cluster.local" }, "destination.service.uid": { "string_value": "istio://default/services/details" }, "destination.service.name": { "string_value": "details" }, "destination.service.namespace": { "string_value": "default" }, "destination.service": { "string_value": "details.default.svc.cluster.local" } } }, "disable_check_calls": true } } } ] }
关于 route.VirtualHost 的详细介绍请参考 Envoy v2 API reference - route.VirtualHost。
路由既是如何匹配请求的规范,也是对下一步做什么的指示(例如,redirect、forward、rewrite等)。
route.Route 的数据结构
下面是是 route.Route 的数据结构,除了 match 之外其余都是可选的。
match
{ "match": "{...}", "route": "{...}", "redirect": "{...}", "direct_response": "{...}", "metadata": "{...}", "decorator": "{...}", "per_filter_config": "{...}", "request_headers_to_add": [], "request_headers_to_remove": [], "response_headers_to_add": [], "response_headers_to_remove": [] }
cluster
operation
details.default.svc.cluster.local:9080/*
per_filter_config
envoy.buffer
关于 route.Route 的详细介绍请参考 Envoy v2 API reference - route.Route。
Cluster 是指 Envoy 连接的一组逻辑相同的上游主机。Envoy 通过服务发现来发现 cluster 的成员。可以选择通过主动健康检查来确定集群成员的健康状态。Envoy 通过负载均衡策略决定将请求路由到 cluster 的哪个成员。
Cluster 的特点
Cluster 的数据结构
Cluster 的数据结构如下,除了 name 栏位,其他都是可选的。
{ "name": "...", "alt_stat_name": "...", "type": "...", "eds_cluster_config": "{...}", "connect_timeout": "{...}", "per_connection_buffer_limit_bytes": "{...}", "lb_policy": "...", "hosts": [], "load_assignment": "{...}", "health_checks": [], "max_requests_per_connection": "{...}", "circuit_breakers": "{...}", "tls_context": "{...}", "common_http_protocol_options": "{...}", "http_protocol_options": "{...}", "http2_protocol_options": "{...}", "extension_protocol_options": "{...}", "dns_refresh_rate": "{...}", "dns_lookup_family": "...", "dns_resolvers": [], "outlier_detection": "{...}", "cleanup_interval": "{...}", "upstream_bind_config": "{...}", "lb_subset_config": "{...}", "ring_hash_lb_config": "{...}", "original_dst_lb_config": "{...}", "least_request_lb_config": "{...}", "common_lb_config": "{...}", "transport_socket": "{...}", "metadata": "{...}", "protocol_selection": "...", "upstream_connection_options": "{...}", "close_connections_on_host_health_failure": "...", "drain_connections_on_host_removal": "..." }
--max-obj-name-len 189
inbound|9080||ratings.default.svc.cluster.local
|
inbound
outbound
DestinationRule
subnet
STATIC
STRICT_DNS
LOGICAL_DNS
EDS
ORIGINAL_DST
service_name
ads
关于 Cluster 的详细介绍请参考 Envoy v2 API reference - cluster。
推荐阅读: