本篇目錄
說明
在梳理開源的 API 網關和 ServiceMesh 項目時,最常遇到的一個詞是 Envoy,Ambassador、Contour、Gloo、Istio 等項目的數據平面都選用了 Envoy。Envoy 何德何能受到衆多項目的青睞? 掌握 Envoy 的脈絡只需 2 分鐘。
響應了時代號召的 Envoy
Envoy 是一個具有反向代理和負載均衡功能的單機軟件,和 Nginx、Haproxy 屬於同一類軟件。與 Nginx 和 Haproxy 相比,Envoy 有一個的重要特色是:自帶配置 API。
以 Nginx、Haproxy 爲代表的負載均衡軟件,在過去很多年的實際應用中,很少會在軟件運行的時候更改配置,即使偶爾要修改配置文件,使用 reload 等命令重新加載就能滿足需要。
以 Kubernetes 爲代表的 PaaS 或者容器管理系統出現後,IT 系統沿着“分工專業化、更少的人做更多同質事情”的路線演進,在當前的演進過程中,反向代理與負載均衡的能力被集中管理、統一提供。
這一演進在 Kubernetes 中體現爲作爲集羣出口的 ingress 代理集羣內所有服務,在以 istio 爲代表的 ServiceMesh 中體現爲分散在各處的代理軟件在同一個中心的控制下流轉流量。 無論是作爲 Kubernetes 的出口,還是作爲 Mesh 中的一個節點,承擔流量轉發功能的組件都需要完成一個挑戰: 在運行過程中頻繁的更新配置。
新場景中的更新的頻率是每秒 N 次,遠遠超過以往的場景中以周、月乃至年爲週期的更新頻率。這種情形下,熱加載配置文件的方式明顯遲緩笨重,有一些項目通過開發一個帶有 API 功能的組件,實現生成配置文件、觸發熱加載的功能,以此賦予 Nginx、Haproxy 等傳統負載均衡軟件高頻更新配置的能力。
但是,如果有一個軟件原生帶有配置 API,且專注於數據平面,它作爲可靠的第三方存在,能夠讓控制平面專心於規則管理,那麼它是不是會很受歡迎呢?
Envoy 就是這樣一款軟件。注意,這裏只是在交代背景,不爲 envoy 吹票,nginx、haproxy 等都在更新演進以適應場景的變化。
Cluster、Listener 與 Filter
Envoy 的功能和使用細節繁雜,但只要搞清楚了 Cluster、Listener 和 Filter 的用途,就把握住了大方向。
Cluster 就是一組 IP,相當於 Nginx 中 upstream,負載均衡策略在 cluster 中設置,cluster 中可以是 IP 也可以是域名:
Listener 就是監聽地址和轉發規則:
難啃的配置文件
Envoy 的配置文件是從零開始瞭解 Envoy 時遇到的最大困難,它的配置比較繁雜,而且缺少系統的介紹。
配置文件在 envoy 啓動時,用 -c
指定,內容分爲以下幾個部分:
{
"node": {
"id": "...",
"cluster": "...",
"metadata": "{...}",
"locality": "{...}",
"build_version": "..."
},
"static_resources": {
"listeners": [],
"clusters": [],
"secrets": []
},
"dynamic_resources": {
"lds_config": "{...}",
"cds_config": "{...}",
"ads_config": "{...}"
},
"cluster_manager": {
"local_cluster_name": "...",
"outlier_detection": "{...}",
"upstream_bind_config": "{...}",
"load_stats_config": "{...}"
},
"hds_config": {
"api_type": "...",
"cluster_names": [],
"grpc_services": [],
"refresh_delay": "{...}",
"request_timeout": "{...}",
"rate_limit_settings": "{...}"
},
"flags_path": "...",
"stats_sinks": [
{
"name": "...",
"config": "{...}"
}
],
"stats_config": {
"stats_tags": [],
"use_all_default_tags": "{...}",
"stats_matcher": "{...}"
},
"stats_flush_interval": "{...}",
"watchdog": {
"miss_timeout": "{...}",
"megamiss_timeout": "{...}",
"kill_timeout": "{...}",
"multikill_timeout": "{...}"
},
"tracing": {
"http": "{...}"
},
"rate_limit_service": {
"grpc_service": "{...}"
},
"runtime": {
"symlink_root": "...",
"subdirectory": "...",
"override_subdirectory": "..."
},
"admin": {
"access_log_path": "...",
"profile_path": "...",
"address": "{...}"
},
"overload_manager": {
"refresh_interval": "{...}",
"resource_monitors": [],
"actions": []
}
}
查看 envoy 容器中的默認配置文件,有助於建立感性認識,內容如下:
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address:
protocol: TCP
address: 127.0.0.1
port_value: 9901
static_resources:
listeners:
- name: listener_0
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
host_rewrite: www.google.com
cluster: service_google
http_filters:
- name: envoy.router
clusters:
- name: service_google
connect_timeout: 0.25s
type: LOGICAL_DNS
# Comment out the following line to test on v6 networks
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_google
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: www.google.com
port_value: 443
tls_context:
sni: www.google.com
掌握 envoy 的配置文件,是把握住這款軟件的關鍵一步,如何才能掌握 envoy 的配置呢?把它所有的配置細節記住當然算是掌握了,但是大多數時候我們並不需要如此,只需要知道實時反應配置文件全部細節的文檔在哪裏就足夠了,剩下的交給時間和好奇心:
挑大樑的 filter
幾乎可以這樣說,在實際應用中最常提及的 envoy 功能都是 filter 提供的, filter 是流量在 envoy 內流轉時經歷的一個又一個處理環節,每個環節都會解讀一些信息、作出一些判斷,影響下一個環節的處理。
Cluster 和 Listener 中都有 filter 的位置,有的 filter 比較複雜還實現了 子 filter
,例如專門處理 http 協議的 HttpConnectionManager。 Filter 的數量實在太多,知道到哪裏找到所有 filter 的說明和配置方法比記住個別 filter 的用法更重要:
這些 filter 的名稱很好的展示了 envoy 能夠做的事情,http、thrift、dubbo、zookeeper、mysql、mongo、redis,看起來是不是挺誘人的?
動態配置到底怎麼回事?
envoy 的一大賣點就是自帶配置 API,但要把它自帶的 API 用起來還挺周折。envoy 率先提出使用統一的 data-plane-api ,定義了一套 API 標準,並期待能夠得到廣泛的認同和採納,從新起的 Api 網關和 ServiceMesh 開源項目的選擇來看,這一策略是有效的。
go-controller-plane 是 envoy 提出的 data-plane-api 的 go 語言實現,可以用它向 envoy 下發配置,這個庫的使用方法三言兩語說不清楚,先弄清楚下面三個項目的關係: envoy 就是單機軟件 envoy,data-plane-api 是 API 接口標準,go-control-plane 是 API 接口標準的實現。
動手實踐一下
自帶配置 API 支持動態更新,Cluster、Listener、Filter 構成了 Envoy 的功能骨架,如果看完上面的介紹,依舊感覺朦朦朧朧如霧裏看花,想要看的更清楚一些,沒有比照敲一遍 Envoy 使用手冊 中的操作更快捷的方法了:
點擊查看: Envoy 使用手冊