Envoy是一種高性能C++分布式代理,專為單個服務和應用程序設計。作為Service Mesh中的重要組件,充分理解其配置就顯得尤為重要。本文列出了使用Envoy而不用其他代理的原因。并給出了Envoy及其服務的配置,然后對其進行詳細解讀,幫助讀者理解其配置,從而掌握Envoy。
奉賢網站制作公司哪家好,找成都創新互聯公司!從網頁設計、網站建設、微信開發、APP開發、響應式網站開發等網站項目制作,到程序開發,運營維護。成都創新互聯公司成立于2013年到現在10年的時間,我們擁有了豐富的建站經驗和運維經驗,來保證我們的工作的順利進行。專注于網站建設就選成都創新互聯公司。
服務網格是微服務設置中的通信層,也就是說往返于每個服務的所有請求都通過網格。服務網格在微服務設置中也成為基礎架構層,它能夠讓服務之間的通信變得安全可靠。關于Service Mesh的基礎內容,我們已經在這篇文章中詳細介紹過。
每一個服務都有自己的代理服務(sidecars),然后所有代理服務一起形成服務網格。Sidecars處理服務之間的通信,也就是說所有的流量都會通過網格并且該透明層可以控制服務之間如何交互。
服務網格通過由API控制的組件提供可觀察性、服務發現以及負載均衡等。
實際上,如果一個服務要調用另一個服務,它不會直接調用目標服務。而是先將請求路由到本地代理,然后代理再將該請求路由到目標服務。這一過程意味著服務實例不會和其他服務直接接觸,僅與本地代理進行通信。
根據ThoughtWorks Technology Radar(這是一份半年度的文檔,用于評估現有技術和新生技術的風險和收益)指出,“服務網格提供一致的發現、安全性、跟蹤(tracing)、監控以及故障處理,而無需共享資源(如API網關或ESB)。一個十分典型的用例是輕量的反向代理進程會與每個服務進程或單獨的容器一起部署。”
當談到服務網格時,不可避免談到的是“sidecar”——可用于每個服務實例的代理。每個sidecar負責管理一個服務的一個實例。我們將在本文中進一步詳細討論sidecar。
當前,越來越多的企業和組織開始轉向微服務架構。這樣的企業需要服務網格所提供的上述功能。解耦庫的使用或自定義代碼的方法無疑是贏家。
Envoy不是構建一個服務網格的唯一選擇,市面上還有其他的代理如Nginx、Traefik等。我之所以選擇Envoy,這個用C++編寫的高性能代理,是因為我更喜歡Envoy的輕量、強大的路由,及其提供的可觀察性和可擴展性。
讓我們首先構建1個包含3個服務的服務網格設置,這是我們正在嘗試構建的架構:
在我們的設置中Front Envoy是一個邊緣代理,我們通常在其中執行TLS終止、身份驗證、生成請求頭等操作。
我們來看看Front Envoy配置:
---
admin:
access_log_path: "/tmp/admin_access.log"
address:
socket_address:
address: "127.0.0.1"
port_value: 9901
static_resources:
listeners:
-
name: "http_listener"
address:
socket_address:
address: "0.0.0.0"
port_value: 80
filter_chains:
filters:
-
name: "envoy.http_connection_manager"
config:
stat_prefix: "ingress"
route_config:
name: "local_route"
virtual_hosts:
-
name: "http-route"
domains:
- "*"
routes:
-
match:
prefix: "/"
route:
cluster: "service_a"
http_filters:
-
name: "envoy.router"
clusters:
-
name: "service_a"
connect_timeout: "0.25s"
type: "strict_DNS"
lb_policy: "ROUND_ROBIN"
hosts:
-
socket_address:
address: "service_a_envoy"
port_value: 8786
Envoy配置主要由以下部分組成:
1、 監聽器(Listener)
2、 路由
3、 集群
4、 端點
一個或多個監聽器可以在單個Envoy實例中運行。在以上9到36行的代碼提到了當前監聽器的地址和端口。每個監聽器也可以有一個或多個網絡過濾器。這些過濾器可以啟用路由、tls終止、流量轉移等活動。除了envoy.http_connection_manager
使用的是內置過濾器之外,Envoy還有其他幾個過濾器。
22行到34行代碼為過濾器配置了路由規范,同時它也指定了我們所接受請求的域以及路由匹配器。路由匹配器可以根據配置的規則匹配每個請求,并將請求轉發到適當的集群。
集群是Envoy將流量路由到的上游服務規范。41行到48行代碼定義了“Service A”,這是Front Envoy要通信的唯一上游。“connect_timeout”是在返回503之前建立與上游服務的連接的時間限制。
通常情況下,有多個“Serivce A”實例,并且Envoy支持多種負載均衡算法來路由流量。在本例中,我們使用了一個簡單的循環算法。
“host”指定我們要將流量路由到的Service A的實例。在本例中,我們只有1個實例。
第47行代碼沒有直接與Service A進行通信,而是與Service A的Envoy代理實例進行通信,該代理將路由到本地Service A實例。
我們還可以利用返回Service A的所有實例的服務名稱(如Kubernetes中的headless服務),來執行客戶端負載均衡。Envoy緩存Service A的所有host,并每5秒刷新一次host列表。
此外,Envoy還支持主動和被動的健康檢查。因此,如果我們要進行主動健康檢查,我們需要在集群配置部分對其進行配置。
第2行到第7行配置了管理服務器,它能夠幫助查看配置、更改日志級別、查看統計信息等。
第8行的“static_resources”可以手動加載所有配置。我們將在下文討論如何動態地執行此操作。
雖然這里描述了許多其他配置,但是我們的目標不是全面介紹所有配置,而是以最少的配置開始。
這是Service A的Envoy配置:
admin:
access_log_path: "/tmp/admin_access.log"
address:
socket_address:
address: "127.0.0.1"
port_value: 9901
static_resources:
listeners:
-
name: "service-a-svc-http-listener"
address:
socket_address:
address: "0.0.0.0"
port_value: 8786
filter_chains:
-
filters:
-
name: "envoy.http_connection_manager"
config:
stat_prefix: "ingress"
codec_type: "AUTO"
route_config:
name: "service-a-svc-http-route"
virtual_hosts:
-
name: "service-a-svc-http-route"
domains:
- "*"
routes:
-
match:
prefix: "/"
route:
cluster: "service_a"
http_filters:
-
name: "envoy.router"
-
name: "service-b-svc-http-listener"
address:
socket_address:
address: "0.0.0.0"
port_value: 8788
filter_chains:
-
filters:
-
name: "envoy.http_connection_manager"
config:
stat_prefix: "egress"
codec_type: "AUTO"
route_config:
name: "service-b-svc-http-route"
virtual_hosts:
-
name: "service-b-svc-http-route"
domains:
- "*"
routes:
-
match:
prefix: "/"
route:
cluster: "service_b"
http_filters:
-
name: "envoy.router"
-
name: "service-c-svc-http-listener"
address:
socket_address:
address: "0.0.0.0"
port_value: 8791
filter_chains:
-
filters:
-
name: "envoy.http_connection_manager"
config:
stat_prefix: "egress"
codec_type: "AUTO"
route_config:
name: "service-b-svc-http-route"
virtual_hosts:
-
name: "service-b-svc-http-route"
domains:
- "*"
routes:
-
match:
prefix: "/"
route:
cluster: "service_c"
http_filters:
-
name: "envoy.router"
clusters:
-
name: "service_a"
connect_timeout: "0.25s"
type: "strict_dns"
lb_policy: "ROUND_ROBIN"
hosts:
-
socket_address:
address: "service_a"
port_value: 8081
-
name: "service_b"
connect_timeout: "0.25s"
type: "strict_dns"
lb_policy: "ROUND_ROBIN"
hosts:
-
socket_address:
address: "service_b_envoy"
port_value: 8789
-
name: "service_c"
connect_timeout: "0.25s"
type: "strict_dns"
lb_policy: "ROUND_ROBIN"
hosts:
-
socket_address:
address: "service_c_envoy"
port_value: 8790
11行到39行定義了一個監聽器來路由流量到實際的Service A實例。在103行到111行中找到service_a
實例的相應集群定義。
Service A與Service B和Service C進行通信,它指向了兩個以上的監聽器以及集群。在本例中,我們為每個上游(localhost、Service B和Service C)分離了監聽器。另一種方法是使用單個監聽器,并根據URL或請求頭路由到任意上游。
Service B和Service C處于葉級,除了本地主機服務實例外,不與任何其他上游通信。因此其配置十分簡單。
而讓事情變得復雜的是上述配置中的單個監聽器和單個集群。
配置完成后,我們將此設置部署到Kubernetes或使用docker-compose對其進行測試。你可以運行docker-compose build
和docker-compose up
并點擊localhost:8080,以查看請求是否成功通過所有服務和Envoy代理。我們可以使用日志對其進行驗證。
我們為每個sidecar提供了配置,并且根據不同的服務,服務之間的配置也有所不同。雖然我們可以手動制作和管理sidecar配置,但最初至少要提供2或3個服務,并且隨著服務數量的增加,配置會變得十分復雜。此外,每次sidecar配置更改時,你都必須重新啟動Envoy實例,以使更改生效。
正如上文所討論的,我們可以通過使用API server來避免手動配置并加載所有組件:集群(CDS)、端點(EDS)、監聽器(LDS)以及路由(RDS)。所以每個sidecar將與API server通信并接收配置。當新配置更新到API server時,它將自動反映在Envoy實例中,從而避免了重新啟動。
你可以在以下鏈接中了解關于動態配置的信息:
https://www.envoyproxy.io/docs/envoy/latest/configuration/overview/v2_overview#dynamic
這有一個簡單的xDS server:
https://github.com/tak2siva/Envoy-Pilot
本部分將討論如果我們要在Kubernetes中實現所討論的設置該怎么辦。以下是架構圖:
因此,將需要更改:
Pod
盡管Pod規范中僅定義了一個容器——按照定義,一個Pod可以容納一個或多個容器。為了對每個服務實例運行sidecar代理,我們將Envoy容器添加到每個Pod中。為了與外界通信,服務容器將通過localhost與Envoy容器進行對話。
部署文件如下所示:
admin:
access_log_path: "/tmp/admin_access.log"
address:
socket_address:
address: "127.0.0.1"
port_value: 9901
static_resources:
listeners:
-
name: "service-b-svc-http-listener"
address:
socket_address:
address: "0.0.0.0"
port_value: 8789
filter_chains:
-
filters:
-
name: "envoy.http_connection_manager"
config:
stat_prefix: "ingress"
codec_type: "AUTO"
route_config:
name: "service-b-svc-http-route"
virtual_hosts:
-
name: "service-b-svc-http-route"
domains:
- "*"
routes:
-
match:
prefix: "/"
route:
cluster: "service_b"
http_filters:
-
name: "envoy.router"
clusters:
-
name: "service_b"
connect_timeout: "0.25s"
type: "strict_dns"
lb_policy: "ROUND_ROBIN"
hosts:
-
socket_address:
address: "service_b"
port_value: 8082
在容器部分添加了Envoy sidecar,并且在33到39行的configmap中我們掛載了我們的Envoy配置文件。
Kubernetes服務負責維護Pod端點列表,該列表可以路由流量。盡管kube-proxy通常處理Pod端點之間的負載均衡,但在本例中,我們將執行客戶端負載均衡,并且我們不希望kube-proxy進行負載均衡。此外,我們想要提取Pod端點列表并對其進行負載均衡。為此,我們需要使用“headless服務“來返回端點列表。
如下所示:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: servicea
spec:
replicas: 2
template:
metadata:
labels:
app: servicea
spec:
containers:
- name: servicea
image: dnivra26/servicea:0.6
ports:
- containerPort: 8081
name: svc-port
protocol: TCP
- name: envoy
image: envoyproxy/envoy:latest
ports:
- containerPort: 9901
protocol: TCP
name: envoy-admin
- containerPort: 8786
protocol: TCP
name: envoy-web
volumeMounts:
- name: envoy-config-volume
mountPath: /etc/envoy-config/
command: ["/usr/local/bin/envoy"]
args: ["-c", "/etc/envoy-config/config.yaml", "--v2-config-only", "-l", "info","--service-cluster","servicea","--service-node","servicea", "--log-format", "[METADATA][%Y-%m-%d %T.%e][%t][%l][%n] %v"]
volumes:
- name: envoy-config-volume
configMap:
name: sidecar-config
items:
- key: envoy-config
path: config.yaml
有兩件事需要注意。一是第6行使服務變成headless,二是我們不是將Kubernetes服務端口映射到應用程序的服務端口,而是映射到Envoy監聽器端口。這意味著,流量首先通向Envoy。即便如此,Kubernetes也可以完美運行。
在本文中,我們看到了如何使用Envoy代理構建服務網格。其中,我們設置了所有通信都將通過網格。因此,現在網格不僅有大量有關流量的數據,而且還具有控制權。
以下鏈接中你可以獲取我們所討論的配置和代碼:
https://github.com/dnivra26/envoy_servicemesh
原文鏈接:
https://www.thoughtworks.com/insights/blog/building-service-mesh-envoy-0
當前標題:服務網格數據平面的關鍵:層層剖析Envoy配置
網站鏈接:http://vcdvsql.cn/article26/pphejg.html
成都網站建設公司_創新互聯,為您提供網站建設、App開發、做網站、標簽優化、搜索引擎優化、小程序開發
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯