Istio 的數據平面 Envoy Proxy 配置詳解——你該瞭解的那些 Envoy 配置

本文轉載自:宋淨超的博客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

Envoy proxy 架構圖

基本術語

下面是您應該瞭解的 Enovy 裏的基本術語:git

  • Downstream(下游):下游主機鏈接到 Envoy,發送請求並接收響應,即發送請求的主機。
  • Upstream(上游):上游主機接收來自 Envoy 的鏈接和請求,並返回響應,即接受請求的主機。github

  • Listener(監聽器):監聽器是命名網地址(例如,端口、unix domain socket 等),下游客戶端能夠鏈接這些監聽器。Envoy 暴露一個或者多個監聽器給下游主機鏈接。redis

  • Cluster(集羣):集羣是指 Envoy 鏈接的一組邏輯相同的上游主機。Envoy 經過服務發現來發現集羣的成員。能夠選擇經過主動健康檢查來肯定集羣成員的健康狀態。Envoy 經過負載均衡策略決定將請求路由到集羣的哪一個成員。json

我將在本文的後半部分解釋以上術語與 Kubernetes、Istio 中概念之間的聯繫。bootstrap

關於 xDS 的版本

有一點須要你們注意,就是 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。

Istio sidecar proxy 配置

假如您使用 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 概覽

Envoy 配置

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。

Envoy proxy 配置解析

Istio envoy sidecar proxy 配置中包含如下四個部分。

  • bootstrap:Envoy proxy 啓動時候加載的靜態配置。
  • listeners:監聽器配置,使用 LDS 下發。
  • clusters:集羣配置,靜態配置中包括 xds-grpc 和 zipkin 地址,動態配置使用 CDS 下發。
  • routes:路由配置,靜態配置中包括了本地監聽的服務的集羣信息,其中引用了 cluster,動態配置使用 RDS 下發。

每一個部分中都包含靜態配置與動態配置,其中 bootstrap 配置又是在集羣啓動的時候經過 sidecar 啓動參數注入的,配置文件在 /etc/istio/proxy/envoy-rev0.json

Enovy 的配置 dump 出來後的結構以下圖所示。

Envoy 配置

因爲 bootstrap 中的配置是來自 Envoy 啓動時加載的靜態文件,主要配置了節點信息、tracing、admin 和統計信息收集等信息,這不是本文的重點,你們能夠自行研究。

bootstrap 配置

上圖是 bootstrap 的配置信息。

Bootstrap 是 Envoy 中配置的根原本源,Bootstrap 消息中有一個關鍵的概念,就是靜態和動態資源的之間的區別。例如 ListenerCluster 這些資源既能夠從 static_resources 靜態的得到也能夠從 dynamic_resources 中配置的 LDSCDS 之類的 xDS 服務獲取。

Listener

Listener 顧名思義,就是監聽器,監聽 IP 地址和端口,而後根據策略轉發。

Listener 的特色

  • 每一個 Envoy 進程中能夠有多個 Listener,Envoy 與 Listener 之間是一對多的關係。
  • 每一個 Listener 中能夠配置一條 filter 鏈表(filter_chains),Envoy 會根據 filter 順序執行過濾。
  • Listener 能夠監聽下游的端口,也能夠接收來自其餘 listener 的數據,造成鏈式處理。
  • filter 是可擴展的。
  • 能夠靜態配置,也可使用 LDS 動態配置。
  • 目前只能監聽 TCP,UDP 還未支持。

Listener 的數據結構

Listener 的數據結構以下,除了 nameaddressfilter_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_authenvoy.echoenovy.http_connection_managerenvoy.mongo_proxyenvoy.rate_limitenovy.redis_proxyenvoy.tcp_proxyhttp_filtersthrift_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

Route

咱們在這裏所說的路由指的是 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": "{...}"
}
複製代碼

下面是關於上述數據結構中的經常使用配置解析。

  • name:該名字跟 envoy.http_connection_manager filter 中的 http_filters.rds.route_config_name 一致,在 Istio Service Mesh 中爲 Envoy 下發的配置中的 Route 是以監聽的端口號做爲名字,而同一個名字下面的 virtual_hosts 能夠有多個值(數組形式)。
  • virtual_hosts:由於 VirtualHosts 是 Envoy 中引入的一個重要概念,咱們在下文將詳細說明 virtual_hosts 的數據結構。
  • validate_clusters:這是一個布爾值,用來設置開啓使用 cluster manager 來檢測路由表引用的 cluster 是否有效。若是是路由表是經過 route_config 靜態配置的則該值默認設置爲 true,若是是使用 rds 動態配置的話,則該值默認設置爲 false。

關於 Route 的詳細介紹請參考 Envoy v2 API reference - HTTP route configuration

route.VirtualHost

VirtualHost 即上文中 Route 配置中的 virtual_hosts,VirtualHost 是路由配置中的頂級元素。每一個虛擬主機都有一個邏輯名稱以及一組根據傳入請求的 host header 路由到它的域。這容許單個 Listener 爲多個頂級域路徑樹提供服務。基於域選擇了虛擬主機後 Envoy 就會處理路由以查看要路由到哪一個上游集羣或是否執行重定向。

VirtualHost 的數據結構

下面是 VirtualHost 的數據結構,除了 namedomains 是必須配置項外,其餘皆爲可選項。

{
  "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": "..."
}
複製代碼

下面是關於上述數據結構中的經常使用配置解析。

  • name:該 VirtualHost 的名字,通常是 FQDN 加端口,如 details.default.svc.cluster.local:9080
  • domains:這是個用來匹配 VirtualHost 的域名(host/authority header)列表,也可使用通配符,可是通配符不能匹配空字符,除了僅使用 * 做爲 domains,注意列表中的值不能重複和存在交集,只要有一條 domain 被匹配上了,就會執行路由。Istio 會爲該值配置全部地址解析形式,包括 IP 地址、FQDN 和短域名等。
  • routes:針對入口流量的有序路由列表,第一個匹配上的路由將被執行。咱們在下文將詳細說明 route 的數據結構。

下面是一個實際的 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

route.Route

路由既是如何匹配請求的規範,也是對下一步作什麼的指示(例如,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": []
}
複製代碼

下面是關於上述數據結構中的經常使用配置解析。

  • match:路由匹配參數。例如 URL prefix(前綴)、path(URL 的完整路徑)、regex(規則表達式)等。
  • route:這裏面配置路由的行爲,能夠是 routeredirectdirect_response,不過這裏面沒有專門的一個配置項用來配置以上三種行爲,而是根據實際填充的配置項來肯定的。例如在此處添加 cluster 配置則暗示路由動做爲」route「,表示將流量路由到該 cluster。詳情請參考 route.RouteAction
  • decorator:被匹配的路由的修飾符,表示被匹配的虛擬主機和 URL。該配置裏有且只有一個必須配置的項 operation,例如 details.default.svc.cluster.local:9080/*
  • per_filter_config:這是一個 map 類型,per_filter_config 字段可用於爲 filter 提供特定路由的配置。Map 的 key 應與 filleter 名稱匹配,例如用於 HTTP buffer filter 的 envoy.buffer。該字段是特定於 filter 的,詳情請參考 HTTP filter

關於 route.Route 的詳細介紹請參考 Envoy v2 API reference - route.Route

Cluster

Cluster 是指 Envoy 鏈接的一組邏輯相同的上游主機。Envoy 經過服務發現來發現 cluster 的成員。能夠選擇經過主動健康檢查來肯定集羣成員的健康狀態。Envoy 經過負載均衡策略決定將請求路由到 cluster 的哪一個成員。

Cluster 的特色

  • 一組邏輯上相同的主機構成一個 cluster。
  • 能夠在 cluster 中定義各類負載均衡策略。
  • 新加入的 cluster 須要一個熱身的過程才能夠給路由引用,該過程是原子的,即在 cluster 熱身以前對於 Envoy 及 Service Mesh 的其他部分來講是不可見的。
  • 能夠經過多種方式來配置 cluster,例如靜態類型、嚴格限定 DNS、邏輯 DNS、EDS 等。

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": "..."
}
複製代碼

下面是關於上述數據結構中的經常使用配置解析。

  • name:若是你留意到做爲 Sidecar 啓動的 Envoy 的參數的會注意到 --max-obj-name-len 189,該選項用來用來指定 cluster 的名字,例如 inbound|9080||ratings.default.svc.cluster.local。該名字字符串由 | 分隔成四個部分,分別是 inboundoutbound 表明入向流量或出向流量、端口號、subcluster 名稱、FQDN,其中 subcluster 名稱將對應於 Istio DestinationRule 中配置的 subnet,若是是按照多版本按比例路由的話,該值能夠是版本號。
  • type:即服務發現類型,支持的參數有 STATIC(缺省值)、STRICT_DNSLOGICAL_DNSEDSORIGINAL_DST
  • hosts:這是個列表,配置負載均衡的 IP 地址和端口,只有使用了 STATICSTRICT_DNSLOGICAL_DNS 服務發現類型時才須要配置。
  • eds_cluster_config:若是使用 EDS 作服務發現,則須要配置該項目,其中包括的配置有 service_nameads

關於 Cluster 的詳細介紹請參考 Envoy v2 API reference - cluster

參考

相關文章
相關標籤/搜索