本文轉載自:宋淨超的博客html
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 注入及流量劫持,本文引用其中的一些觀點,詳細內容再也不贅述。node
下面是您應該瞭解的 Enovy 裏的基本術語:git
Upstream(上游):上游主機接收來自 Envoy 的鏈接和請求,並返回響應,即接受請求的主機。github
Listener(監聽器):監聽器是命名網地址(例如,端口、unix domain socket 等),下游客戶端能夠鏈接這些監聽器。Envoy 暴露一個或者多個監聽器給下游主機鏈接。redis
Cluster(集羣):集羣是指 Envoy 鏈接的一組邏輯相同的上游主機。Envoy 經過服務發現來發現集羣的成員。能夠選擇經過主動健康檢查來肯定集羣成員的健康狀態。Envoy 經過負載均衡策略決定將請求路由到集羣的哪一個成員。json
我將在本文的後半部分解釋以上術語與 Kubernetes、Istio 中概念之間的聯繫。bootstrap
有一點須要你們注意,就是 Envoy 的 API 有 v1 和 v2 兩個版本,從 Envoy 1.5.0 起 v2 API 就已經生產就緒了,爲了可以讓用戶順利的向 v2 版本的額 API 過分,Envoy 啓動的時候設置了一個 --v2-config-only
的標誌,Enovy 不一樣版本對 v1/v2 API 的支持詳情請參考 Envoy v1 配置廢棄時間表。centos
Envoy 的做者 Matt Klein 在 Service Mesh 中的通用數據平面 API 設計這篇文章中說明了 Envoy API v1 的歷史及其缺點,還有 v2 的引入。v2 API 是 v1 的演進,而不是革命,它是 v1 功能的超集。api
在 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 的全量配置:
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
。
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": [],
"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": "{...}"
}
複製代碼
下面是關於上述數據結構中的經常使用配置解析。
name:該 listener 的 UUID,惟一限定名,默認60個字符,例如 10.254.74.159_15011
,可使用命令參數指定長度限制。
address:監聽的邏輯/物理地址和端口號,例如
"address": {
"socket_address": {
"address": "10.254.74.159",
"port_value": 15011
}
}
複製代碼
filter_chains:這是一個列表,Envoy 中內置了一些通用的 filter,每種 filter 都有特定的數據結構,Enovy 會根據該配置順序執行 filter。Envoy 中內置的 filter 有:envoy.client_ssl_auth、envoy.echo、enovy.http_connection_manager、envoy.mongo_proxy、envoy.rate_limit、enovy.redis_proxy、envoy.tcp_proxy、http_filters、thrift_filters等。這些 filter 能夠單獨使用也能夠組合使用,還能夠自定義擴展,例如使用 Istio 中的 EnvoyFilter 配置。
use_original_dst:這是一個布爾值,若是使用 iptables 重定向鏈接,則代理接收的端口可能與原始目的地址的端口不同。當此標誌設置爲 true 時,Listener 將重定向的鏈接切換到與原始目的地址關聯的 Listener。若是沒有與原始目的地址關聯的 Listener,則鏈接由接收它的 Listener 處理。默認爲 false。注意:該參數將被廢棄,請使用原始目的地址的 Listener filter 替代。該參數的主要用途是:Envoy 經過監聽 15001 端口將應用的流量截取後再由其餘 Listener 處理而不是直接轉發出去,詳情見 Virtual Listener。
關於 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
filter 中的 http_filters.rds.route_config_name
一致,在 Istio Service Mesh 中爲 Envoy 下發的配置中的 Route 是以監聽的端口號做爲名字,而同一個名字下面的 virtual_hosts
能夠有多個值(數組形式)。virtual_hosts
的數據結構。關於 Route 的詳細介紹請參考 Envoy v2 API reference - HTTP route configuration。
VirtualHost 即上文中 Route 配置中的 virtual_hosts
,VirtualHost 是路由配置中的頂級元素。每一個虛擬主機都有一個邏輯名稱以及一組根據傳入請求的 host header 路由到它的域。這容許單個 Listener 爲多個頂級域路徑樹提供服務。基於域選擇了虛擬主機後 Envoy 就會處理路由以查看要路由到哪一個上游集羣或是否執行重定向。
VirtualHost 的數據結構
下面是 VirtualHost 的數據結構,除了 name
和 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
。*
做爲 domains,注意列表中的值不能重複和存在交集,只要有一條 domain 被匹配上了,就會執行路由。Istio 會爲該值配置全部地址解析形式,包括 IP 地址、FQDN 和短域名等。下面是一個實際的 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": "{...}",
"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
配置則暗示路由動做爲」route「,表示將流量路由到該 cluster。詳情請參考 route.RouteAction。operation
,例如 details.default.svc.cluster.local:9080/*
。per_filter_config
字段可用於爲 filter 提供特定路由的配置。Map 的 key 應與 filleter 名稱匹配,例如用於 HTTP buffer filter 的 envoy.buffer
。該字段是特定於 filter 的,詳情請參考 HTTP filter。關於 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
,該選項用來用來指定 cluster 的名字,例如 inbound|9080||ratings.default.svc.cluster.local
。該名字字符串由 |
分隔成四個部分,分別是 inbound
或 outbound
表明入向流量或出向流量、端口號、subcluster 名稱、FQDN,其中 subcluster 名稱將對應於 Istio DestinationRule
中配置的 subnet
,若是是按照多版本按比例路由的話,該值能夠是版本號。STATIC
(缺省值)、STRICT_DNS
、LOGICAL_DNS
、EDS
、ORIGINAL_DST
。STATIC
、STRICT_DNS
、LOGICAL_DNS
服務發現類型時才須要配置。EDS
作服務發現,則須要配置該項目,其中包括的配置有 service_name
和 ads
。關於 Cluster 的詳細介紹請參考 Envoy v2 API reference - cluster。