服務(wù)網(wǎng)格數(shù)據(jù)平面的關(guān)鍵:層層剖析Envoy配置

Envoy是一種高性能C++分布式代理,專為單個(gè)服務(wù)和應(yīng)用程序設(shè)計(jì)。作為Service Mesh中的重要組件,充分理解其配置就顯得尤為重要。本文列出了使用Envoy而不用其他代理的原因。并給出了Envoy及其服務(wù)的配置,然后對(duì)其進(jìn)行詳細(xì)解讀,幫助讀者理解其配置,從而掌握Envoy。
 
服務(wù)網(wǎng)格數(shù)據(jù)平面的關(guān)鍵:層層剖析Envoy配置

奉賢網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站開發(fā)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)公司成立于2013年到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)公司

 

 
服務(wù)網(wǎng)格是微服務(wù)設(shè)置中的通信層,也就是說往返于每個(gè)服務(wù)的所有請(qǐng)求都通過網(wǎng)格。服務(wù)網(wǎng)格在微服務(wù)設(shè)置中也成為基礎(chǔ)架構(gòu)層,它能夠讓服務(wù)之間的通信變得安全可靠。關(guān)于Service Mesh的基礎(chǔ)內(nèi)容,我們已經(jīng)在這篇文章中詳細(xì)介紹過。
 

每一個(gè)服務(wù)都有自己的代理服務(wù)(sidecars),然后所有代理服務(wù)一起形成服務(wù)網(wǎng)格。Sidecars處理服務(wù)之間的通信,也就是說所有的流量都會(huì)通過網(wǎng)格并且該透明層可以控制服務(wù)之間如何交互。
 

服務(wù)網(wǎng)格通過由API控制的組件提供可觀察性、服務(wù)發(fā)現(xiàn)以及負(fù)載均衡等。

 

實(shí)際上,如果一個(gè)服務(wù)要調(diào)用另一個(gè)服務(wù),它不會(huì)直接調(diào)用目標(biāo)服務(wù)。而是先將請(qǐng)求路由到本地代理,然后代理再將該請(qǐng)求路由到目標(biāo)服務(wù)。這一過程意味著服務(wù)實(shí)例不會(huì)和其他服務(wù)直接接觸,僅與本地代理進(jìn)行通信。
 
服務(wù)網(wǎng)格數(shù)據(jù)平面的關(guān)鍵:層層剖析Envoy配置
 
根據(jù)ThoughtWorks Technology Radar(這是一份半年度的文檔,用于評(píng)估現(xiàn)有技術(shù)和新生技術(shù)的風(fēng)險(xiǎn)和收益)指出,“服務(wù)網(wǎng)格提供一致的發(fā)現(xiàn)、安全性、跟蹤(tracing)、監(jiān)控以及故障處理,而無(wú)需共享資源(如API網(wǎng)關(guān)或ESB)。一個(gè)十分典型的用例是輕量的反向代理進(jìn)程會(huì)與每個(gè)服務(wù)進(jìn)程或單獨(dú)的容器一起部署?!?/p>

 
當(dāng)談到服務(wù)網(wǎng)格時(shí),不可避免談到的是“sidecar”——可用于每個(gè)服務(wù)實(shí)例的代理。每個(gè)sidecar負(fù)責(zé)管理一個(gè)服務(wù)的一個(gè)實(shí)例。我們將在本文中進(jìn)一步詳細(xì)討論sidecar。
 

服務(wù)網(wǎng)格可以交付什么?

 
服務(wù)網(wǎng)格數(shù)據(jù)平面的關(guān)鍵:層層剖析Envoy配置
 
當(dāng)前,越來越多的企業(yè)和組織開始轉(zhuǎn)向微服務(wù)架構(gòu)。這樣的企業(yè)需要服務(wù)網(wǎng)格所提供的上述功能。解耦庫(kù)的使用或自定義代碼的方法無(wú)疑是贏家。
 

為什么使用Envoy?

 
Envoy不是構(gòu)建一個(gè)服務(wù)網(wǎng)格的唯一選擇,市面上還有其他的代理如Nginx、Traefik等。我之所以選擇Envoy,這個(gè)用C++編寫的高性能代理,是因?yàn)槲腋矚gEnvoy的輕量、強(qiáng)大的路由,及其提供的可觀察性和可擴(kuò)展性。

 

讓我們首先構(gòu)建1個(gè)包含3個(gè)服務(wù)的服務(wù)網(wǎng)格設(shè)置,這是我們正在嘗試構(gòu)建的架構(gòu):
 
服務(wù)網(wǎng)格數(shù)據(jù)平面的關(guān)鍵:層層剖析Envoy配置
 

Front Envoy

 
在我們的設(shè)置中Front Envoy是一個(gè)邊緣代理,我們通常在其中執(zhí)行TLS終止、身份驗(yàn)證、生成請(qǐng)求頭等操作。

 

我們來看看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、 監(jiān)聽器(Listener)

2、 路由

3、 集群

4、 端點(diǎn)
 

監(jiān)聽器

 

一個(gè)或多個(gè)監(jiān)聽器可以在單個(gè)Envoy實(shí)例中運(yùn)行。在以上9到36行的代碼提到了當(dāng)前監(jiān)聽器的地址和端口。每個(gè)監(jiān)聽器也可以有一個(gè)或多個(gè)網(wǎng)絡(luò)過濾器。這些過濾器可以啟用路由、tls終止、流量轉(zhuǎn)移等活動(dòng)。除了envoy.http_connection_manager使用的是內(nèi)置過濾器之外,Envoy還有其他幾個(gè)過濾器。
 

路 由

 

22行到34行代碼為過濾器配置了路由規(guī)范,同時(shí)它也指定了我們所接受請(qǐng)求的域以及路由匹配器。路由匹配器可以根據(jù)配置的規(guī)則匹配每個(gè)請(qǐng)求,并將請(qǐng)求轉(zhuǎn)發(fā)到適當(dāng)?shù)募骸?br/> 

集 群

 

集群是Envoy將流量路由到的上游服務(wù)規(guī)范。41行到48行代碼定義了“Service A”,這是Front Envoy要通信的唯一上游?!癱onnect_timeout”是在返回503之前建立與上游服務(wù)的連接的時(shí)間限制。

 

通常情況下,有多個(gè)“Serivce A”實(shí)例,并且Envoy支持多種負(fù)載均衡算法來路由流量。在本例中,我們使用了一個(gè)簡(jiǎn)單的循環(huán)算法。
 

端 點(diǎn)

 

“host”指定我們要將流量路由到的Service A的實(shí)例。在本例中,我們只有1個(gè)實(shí)例。

 

第47行代碼沒有直接與Service A進(jìn)行通信,而是與Service A的Envoy代理實(shí)例進(jìn)行通信,該代理將路由到本地Service A實(shí)例。
 

我們還可以利用返回Service A的所有實(shí)例的服務(wù)名稱(如Kubernetes中的headless服務(wù)),來執(zhí)行客戶端負(fù)載均衡。Envoy緩存Service A的所有host,并每5秒刷新一次host列表。

 

此外,Envoy還支持主動(dòng)和被動(dòng)的健康檢查。因此,如果我們要進(jìn)行主動(dòng)健康檢查,我們需要在集群配置部分對(duì)其進(jìn)行配置。
 

其 他

 

第2行到第7行配置了管理服務(wù)器,它能夠幫助查看配置、更改日志級(jí)別、查看統(tǒng)計(jì)信息等。

 

第8行的“static_resources”可以手動(dòng)加載所有配置。我們將在下文討論如何動(dòng)態(tài)地執(zhí)行此操作。

 

雖然這里描述了許多其他配置,但是我們的目標(biāo)不是全面介紹所有配置,而是以最少的配置開始。
 

Service A

 

這是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行定義了一個(gè)監(jiān)聽器來路由流量到實(shí)際的Service A實(shí)例。在103行到111行中找到service_a實(shí)例的相應(yīng)集群定義。

 

Service A與Service B和Service C進(jìn)行通信,它指向了兩個(gè)以上的監(jiān)聽器以及集群。在本例中,我們?yōu)槊總€(gè)上游(localhost、Service B和Service C)分離了監(jiān)聽器。另一種方法是使用單個(gè)監(jiān)聽器,并根據(jù)URL或請(qǐng)求頭路由到任意上游。
 

Service B 和 Service C

 

Service B和Service C處于葉級(jí),除了本地主機(jī)服務(wù)實(shí)例外,不與任何其他上游通信。因此其配置十分簡(jiǎn)單。
 

而讓事情變得復(fù)雜的是上述配置中的單個(gè)監(jiān)聽器和單個(gè)集群。
 

配置完成后,我們將此設(shè)置部署到Kubernetes或使用docker-compose對(duì)其進(jìn)行測(cè)試。你可以運(yùn)行docker-compose builddocker-compose up并點(diǎn)擊localhost:8080,以查看請(qǐng)求是否成功通過所有服務(wù)和Envoy代理。我們可以使用日志對(duì)其進(jìn)行驗(yàn)證。
 

Envoy xDS

 

我們?yōu)槊總€(gè)sidecar提供了配置,并且根據(jù)不同的服務(wù),服務(wù)之間的配置也有所不同。雖然我們可以手動(dòng)制作和管理sidecar配置,但最初至少要提供2或3個(gè)服務(wù),并且隨著服務(wù)數(shù)量的增加,配置會(huì)變得十分復(fù)雜。此外,每次sidecar配置更改時(shí),你都必須重新啟動(dòng)Envoy實(shí)例,以使更改生效。

 

正如上文所討論的,我們可以通過使用API server來避免手動(dòng)配置并加載所有組件:集群(CDS)、端點(diǎn)(EDS)、監(jiān)聽器(LDS)以及路由(RDS)。所以每個(gè)sidecar將與API server通信并接收配置。當(dāng)新配置更新到API server時(shí),它將自動(dòng)反映在Envoy實(shí)例中,從而避免了重新啟動(dòng)。

 

你可以在以下鏈接中了解關(guān)于動(dòng)態(tài)配置的信息:
 
https://www.envoyproxy.io/docs/envoy/latest/configuration/overview/v2_overview#dynamic

 

這有一個(gè)簡(jiǎn)單的xDS server:
 
https://github.com/tak2siva/Envoy-Pilot
 

如何在Kubernetes中實(shí)現(xiàn)

 

本部分將討論如果我們要在Kubernetes中實(shí)現(xiàn)所討論的設(shè)置該怎么辦。以下是架構(gòu)圖:
 
因此,將需要更改:

  • Pod

  • 服務(wù)
     

    部署Pod

 

盡管Pod規(guī)范中僅定義了一個(gè)容器——按照定義,一個(gè)Pod可以容納一個(gè)或多個(gè)容器。為了對(duì)每個(gè)服務(wù)實(shí)例運(yùn)行sidecar代理,我們將Envoy容器添加到每個(gè)Pod中。為了與外界通信,服務(wù)容器將通過localhost與Envoy容器進(jìn)行對(duì)話。
 
部署文件如下所示:
 


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配置文件。
 

更改服務(wù)

 
Kubernetes服務(wù)負(fù)責(zé)維護(hù)Pod端點(diǎn)列表,該列表可以路由流量。盡管kube-proxy通常處理Pod端點(diǎn)之間的負(fù)載均衡,但在本例中,我們將執(zhí)行客戶端負(fù)載均衡,并且我們不希望kube-proxy進(jìn)行負(fù)載均衡。此外,我們想要提取Pod端點(diǎn)列表并對(duì)其進(jìn)行負(fù)載均衡。為此,我們需要使用“headless服務(wù)“來返回端點(diǎn)列表。

 

如下所示:

 


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行使服務(wù)變成headless,二是我們不是將Kubernetes服務(wù)端口映射到應(yīng)用程序的服務(wù)端口,而是映射到Envoy監(jiān)聽器端口。這意味著,流量首先通向Envoy。即便如此,Kubernetes也可以完美運(yùn)行。

 

在本文中,我們看到了如何使用Envoy代理構(gòu)建服務(wù)網(wǎng)格。其中,我們?cè)O(shè)置了所有通信都將通過網(wǎng)格。因此,現(xiàn)在網(wǎng)格不僅有大量有關(guān)流量的數(shù)據(jù),而且還具有控制權(quán)。

 

以下鏈接中你可以獲取我們所討論的配置和代碼:

https://github.com/dnivra26/envoy_servicemesh

 

原文鏈接:

https://www.thoughtworks.com/insights/blog/building-service-mesh-envoy-0

當(dāng)前標(biāo)題:服務(wù)網(wǎng)格數(shù)據(jù)平面的關(guān)鍵:層層剖析Envoy配置
網(wǎng)站鏈接:http://muchs.cn/article26/pphejg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、App開發(fā)、做網(wǎng)站、標(biāo)簽優(yōu)化搜索引擎優(yōu)化、小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)