<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 深入理解Istio Service Mesh中的Envoy Sidecar代理的路由轉發 **注意:本書中的 Service Mesh 章節已不再維護,請轉到 [istio-handbook](https://jimmysong.io/istio-handbook) 中瀏覽。** 本文以 Istio 官方的 [bookinfo 示例](https://preliminary.istio.io/zh/docs/examples/bookinfo)來講解在進入 Pod 的流量被 iptables 轉交給 Envoy sidecar 后,Envoy 是如何做路由轉發的,詳述了 Inbound 和 Outbound 處理過程。關于流量攔截的詳細分析請參考[理解 Istio Service Mesh 中 Envoy 代理 Sidecar 注入及流量劫持](https://jimmysong.io/posts/envoy-sidecar-injection-in-istio-service-mesh-deep-dive/)。 下面是 Istio 官方提供的 bookinfo 的請求流程圖,假設 bookinfo 應用的所有服務中沒有配置 DestinationRule。 ![Bookinfo 示例](https://ws1.sinaimg.cn/large/006tNbRwgy1fvlwjd3302j31bo0ro0x5.jpg) 下面是 Istio 自身組件與 Bookinfo 示例的連接關系圖,我們可以看到所有的 HTTP 連接都在 9080 端口監聽。 ![Bookinfo 示例與 Istio 組件連接關系圖](https://ws4.sinaimg.cn/large/006tNbRwly1fyitp0jsghj31o70u0x6p.jpg) 可以在 [Google Drive](https://drive.google.com/open?id=19ed3_tkjf6RgGboxllMdt_Ytd5_cocib) 上下載原圖。 ## Sidecar 注入及流量劫持步驟概述 下面是從 Sidecar 注入、Pod 啟動到 Sidecar proxy 攔截流量及 Envoy 處理路由的步驟概覽。 **1.** Kubernetes 通過 Admission Controller 自動注入,或者用戶使用 `istioctl` 命令手動注入 sidecar 容器。 **2.** 應用 YAML 配置部署應用,此時 Kubernetes API server 接收到的服務創建配置文件中已經包含了 Init 容器及 sidecar proxy。 **3.** 在 sidecar proxy 容器和應用容器啟動之前,首先運行 Init 容器,Init 容器用于設置 iptables(Istio 中默認的流量攔截方式,還可以使用 BPF、IPVS 等方式) 將進入 pod 的流量劫持到 Envoy sidecar proxy。所有 TCP 流量(Envoy 目前只支持 TCP 流量)將被 sidecar 劫持,其他協議的流量將按原來的目的地請求。 **4.** 啟動 Pod 中的 Envoy sidecar proxy 和應用程序容器。這一步的過程請參考[通過管理接口獲取完整配置](https://zhaohuabing.com/post/2018-09-25-istio-traffic-management-impl-intro/#%E9%80%9A%E8%BF%87%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3%E8%8E%B7%E5%8F%96%E5%AE%8C%E6%95%B4%E9%85%8D%E7%BD%AE)。 > **Sidecar proxy 與應用容器的啟動順序問題** > > 啟動 sidecar proxy 和應用容器,究竟哪個容器先啟動呢?正常情況是 Envoy Sidecar 和應用程序容器全部啟動完成后再開始接收流量請求。但是我們無法預料哪個容器會先啟動,那么容器啟動順序是否會對 Envoy 劫持流量有影響呢?答案是肯定的,不過分為以下兩種情況。 > > **情況1:應用容器先啟動,而 sidecar proxy 仍未就緒** > > 這種情況下,流量被 iptables 轉移到 15001 端口,而 Pod 中沒有監聽該端口,TCP 鏈接就無法建立,請求失敗。 > > **情況2:Sidecar 先啟動,請求到達而應用程序仍未就緒** > > 這種情況下請求也肯定會失敗,至于是在哪一步開始失敗的,留給讀者來思考。 **問題**:如果為 sidecar proxy 和應用程序容器添加[就緒和存活探針](https://jimmysong.io/kubernetes-handbook/guide/configure-liveness-readiness-probes.html)是否可以解決該問題呢? **5.** 不論是進入還是從 Pod 發出的 TCP 請求都會被 iptables 劫持,inbound 流量被劫持后經 Inbound Handler 處理后轉交給應用程序容器處理,outbound 流量被 iptables 劫持后轉交給 Outbound Handler 處理,并確定轉發的 upstream 和 Endpoint。 **6.** Sidecar proxy 請求 Pilot 使用 xDS 協議同步 Envoy 配置,其中包括 LDS、EDS、CDS 等,不過為了保證更新的順序,Envoy 會直接使用 ADS 向 Pilot 請求配置更新。 ## Envoy 如何處理路由轉發 下圖展示的是 `productpage` 服務請求訪問 `http://reviews.default.svc.cluster.local:9080/`,當流量進入 `reviews` 服務內部時,`reviews` 服務內部的 Envoy Sidecar 是如何做流量攔截和路由轉發的。可以在 [Google Drive](https://drive.google.com/file/d/1n-h235tm8DnL_RqxTTA95rgGtrLkBsyr/view?usp=sharing) 上下載原圖。 ![Envoy sidecar 流量劫持與路由轉發示意圖](https://ws2.sinaimg.cn/large/006tNbRwly1fyl39icd27j31c70u04gc.jpg) 第一步開始時,`productpage` Pod 中的 Envoy sidecar 已經通過 EDS 選擇出了要請求的 `reviews` 服務的一個 Pod,知曉了其 IP 地址,發送 TCP 連接請求。 Istio 官網中的 [Envoy 配置深度解析](https://preliminary.istio.io/zh/help/ops/traffic-management/proxy-cmd/#envoy-%E9%85%8D%E7%BD%AE%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90)中是以發起 HTTP 請求的一方來詳述 Envoy 做流量轉發的過程,而本文中考慮的是接受 downstream 的流量的一方,它既要接收 downstream 發來的請求,自己還需要請求其他服務,例如 `reviews` 服務中的 Pod 還需要請求 `ratings` 服務。 `reviews` 服務有三個版本,每個版本有一個實例,三個版本中的 sidecar 工作步驟類似,下文只以 `reviews-v1-cb8655c75-b97zc` 這一個 Pod 中的 Sidecar 流量轉發步驟來說明。 ## 理解 Inbound Handler Inbound handler 的作用是將 iptables 攔截到的 downstream 的流量轉交給 localhost,與 Pod 內的應用程序容器建立連接。 查看下 `reviews-v1-cb8655c75-b97zc` pod 中的 Listener。 運行 `istioctl pc listener reviews-v1-cb8655c75-b97zc` 查看該 Pod 中的具有哪些 Listener。 ```ini ADDRESS PORT TYPE 172.33.3.3 9080 HTTP <--- 接收所有 Inbound HTTP 流量,該地址即為當前 Pod 的 IP 地址 10.254.0.1 443 TCP <--+ 10.254.4.253 80 TCP | 10.254.4.253 8080 TCP | 10.254.109.182 443 TCP | 10.254.22.50 15011 TCP | 10.254.22.50 853 TCP | 10.254.79.114 443 TCP | 10.254.143.179 15011 TCP | 10.254.0.2 53 TCP | 接收與 0.0.0.0_15001 監聽器配對的 Outbound 非 HTTP 流量 10.254.22.50 443 TCP | 10.254.16.64 42422 TCP | 10.254.127.202 16686 TCP | 10.254.22.50 31400 TCP | 10.254.22.50 8060 TCP | 10.254.169.13 14267 TCP | 10.254.169.13 14268 TCP | 10.254.32.134 8443 TCP | 10.254.118.196 443 TCP <--+ 0.0.0.0 15004 HTTP <--+ 0.0.0.0 8080 HTTP | 0.0.0.0 15010 HTTP | 0.0.0.0 8088 HTTP | 0.0.0.0 15031 HTTP | 0.0.0.0 9090 HTTP | 0.0.0.0 9411 HTTP | 接收與 0.0.0.0_15001 配對的 Outbound HTTP 流量 0.0.0.0 80 HTTP | 0.0.0.0 15030 HTTP | 0.0.0.0 9080 HTTP | 0.0.0.0 9093 HTTP | 0.0.0.0 3000 HTTP | 0.0.0.0 8060 HTTP | 0.0.0.0 9091 HTTP <--+ 0.0.0.0 15001 TCP <--- 接收所有經 iptables 攔截的 Inbound 和 Outbound 流量并轉交給虛擬監聽器處理 ``` 當來自 `productpage` 的流量抵達 `reviews` Pod 的時候已經,downstream 必須明確知道 Pod 的 IP 地址為 `172.33.3.3` 所以才會訪問該 Pod,所以該請求是 `172.33.3.3:9080`。 **`virtual` Listener** 從該 Pod 的 Listener 列表中可以看到,0.0.0.0:15001/TCP 的 Listener(其實際名字是 `virtual`)監聽所有的 Inbound 流量,下面是該 Listener 的詳細配置。 ```json { "name": "virtual", "address": { "socketAddress": { "address": "0.0.0.0", "portValue": 15001 } }, "filterChains": [ { "filters": [ { "name": "envoy.tcp_proxy", "config": { "cluster": "BlackHoleCluster", "stat_prefix": "BlackHoleCluster" } } ] } ], "useOriginalDst": true } ``` **UseOriginalDst**:從配置中可以看出 `useOriginalDst` 配置指定為 `true`,這是一個布爾值,缺省為 false,使用 iptables 重定向連接時,proxy 接收的端口可能與[原始目的地址](http://www.servicemesher.com/envoy/configuration/listener_filters/original_dst_filter.html)的端口不一樣,如此處 proxy 接收的端口為 15001,而原始目的地端口為 9080。當此標志設置為 true 時,Listener 將連接重定向到與原始目的地址關聯的 Listener,此處為 `172.33.3.3:9080`。如果沒有與原始目的地址關聯的 Listener,則連接由接收它的 Listener 處理,即該 `virtual` Listener,經過 `envoy.tcp_proxy` 過濾器處理轉發給 `BlackHoleCluster`,這個 Cluster 的作用正如它的名字,當 Envoy 找不到匹配的虛擬監聽器時,就會將請求發送給它,并返回 404。這個將于下文提到的 Listener 中設置 `bindToPort` 相呼應。 **注意**:該參數將被廢棄,請使用[原始目的地址](http://www.servicemesher.com/envoy/configuration/listener_filters/original_dst_filter.html)的 Listener filter 替代。該參數的主要用途是:Envoy 通過監聽 15001 端口將 iptables 攔截的流量經由其他 Listener 處理而不是直接轉發出去,詳情見 [Virtual Listener](https://zhaohuabing.com/post/2018-09-25-istio-traffic-management-impl-intro/#virtual-listener)。 **Listener 172.33.3.3_9080** 上文說到進入 Inbound handler 的流量被 `virtual` Listener 轉移到 `172.33.3.3_9080` Listener,我們在查看下該 Listener 配置。 運行 `istioctl pc listener reviews-v1-cb8655c75-b97zc --address 172.33.3.3 --port 9080 -o json` 查看。 ```json [{ "name": "172.33.3.3_9080", "address": { "socketAddress": { "address": "172.33.3.3", "portValue": 9080 } }, "filterChains": [ { "filterChainMatch": { "transportProtocol": "raw_buffer" }, "filters": [ { "name": "envoy.http_connection_manager", "config": { ... "route_config": { "name": "inbound|9080||reviews.default.svc.cluster.local", "validate_clusters": false, "virtual_hosts": [ { "domains": [ "*" ], "name": "inbound|http|9080", "routes": [ { ... "route": { "cluster": "inbound|9080||reviews.default.svc.cluster.local", "max_grpc_timeout": "0.000s", "timeout": "0.000s" } } ] } ] }, "use_remote_address": false, ... } } ], "deprecatedV1": { "bindToPort": false } ... }, { "filterChainMatch": { "transportProtocol": "tls" }, "tlsContext": {... }, "filters": [... ] } ], ... }] ``` **bindToPort**:注意其中有一個 [`bindToPort`](https://www.envoyproxy.io/docs/envoy/v1.6.0/api-v1/listeners/listeners) 的配置,其值為 `false`,該配置的缺省值為 `true`,表示將 Listener 綁定到端口上,此處設置為 `false` 則該 Listener 只能處理其他 Listener 轉移過來的流量,即上文所說的 `virtual` Listener,我們看其中的 filterChains.filters 中的 `envoy.http_connection_manager` 配置部分: ```json "route_config": { "name": "inbound|9080||reviews.default.svc.cluster.local", "validate_clusters": false, "virtual_hosts": [ { "domains": [ "*" ], "name": "inbound|http|9080", "routes": [ { ... "route": { "cluster": "inbound|9080||reviews.default.svc.cluster.local", "max_grpc_timeout": "0.000s", "timeout": "0.000s" } } ] } ] } ``` 該配置表示流量將轉交給 Cluster `inbound|9080||reviews.default.svc.cluster.local` 處理。 **Cluster `inbound|9080||reviews.default.svc.cluster.local`** 運行 `istioctl pc cluster reviews-v1-cb8655c75-b97zc --fqdn reviews.default.svc.cluster.local --direction inbound -o json` 查看該 Cluster 的配置如下。 ```json [ { "name": "inbound|9080||reviews.default.svc.cluster.local", "connectTimeout": "1.000s", "hosts": [ { "socketAddress": { "address": "127.0.0.1", "portValue": 9080 } } ], "circuitBreakers": { "thresholds": [ {} ] } } ] ``` 可以看到該 Cluster 的 Endpoint 直接對應的就是 localhost,再經過 iptables 轉發流量就被應用程序容器消費了。 ## 理解 Outbound Handler 因為 `reviews` 會向 `ratings` 服務發送 HTTP 請求,請求的地址是:`http://ratings.default.svc.cluster.local:9080/`,Outbound handler 的作用是將 iptables 攔截到的本地應用程序發出的流量,經由 Envoy 判斷如何路由到 upstream。 應用程序容器發出的請求為 Outbound 流量,被 iptables 劫持后轉移給 Envoy Outbound handler 處理,然后經過 `virtual` Listener、`0.0.0.0_9080` Listener,然后通過 Route 9080 找到 upstream 的 cluster,進而通過 EDS 找到 Endpoint 執行路由動作。這一部分可以參考 Istio 官網中的 [Envoy 深度配置解析](https://preliminary.istio.io/zh/help/ops/traffic-management/proxy-cmd/#envoy-%E9%85%8D%E7%BD%AE%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90)。 **Route 9080** `reviews` 會請求 `ratings` 服務,運行 `istioctl proxy-config routes reviews-v1-cb8655c75-b97zc --name 9080 -o json` 查看 route 配置,因為 Envoy 會根據 HTTP header 中的 domains 來匹配 VirtualHost,所以下面只列舉了 `ratings.default.svc.cluster.local:9080` 這一個 VirtualHost。 ```json [{ "name": "ratings.default.svc.cluster.local:9080", "domains": [ "ratings.default.svc.cluster.local", "ratings.default.svc.cluster.local:9080", "ratings", "ratings:9080", "ratings.default.svc.cluster", "ratings.default.svc.cluster:9080", "ratings.default.svc", "ratings.default.svc:9080", "ratings.default", "ratings.default:9080", "10.254.234.130", "10.254.234.130:9080" ], "routes": [ { "match": { "prefix": "/" }, "route": { "cluster": "outbound|9080||ratings.default.svc.cluster.local", "timeout": "0.000s", "maxGrpcTimeout": "0.000s" }, "decorator": { "operation": "ratings.default.svc.cluster.local:9080/*" }, "perFilterConfig": {... } } ] }, ..] ``` 從該 Virtual Host 配置中可以看到將流量路由到 Cluster `outbound|9080||ratings.default.svc.cluster.local`。 **Endpoint `outbound|9080||ratings.default.svc.cluster.local`** Istio 1.1 以前版本不支持使用 `istioctl` 命令直接查詢 Cluster 的 Endpoint,可以使用查詢 Pilot 的 debug 端點的方式折中。 ```bash kubectl exec reviews-v1-cb8655c75-b97zc -c istio-proxy curl http://istio-pilot.istio-system.svc.cluster.local:9093/debug/edsz > endpoints.json ``` `endpoints.json` 文件中包含了所有 Cluster 的 Endpoint 信息,我們只選取其中的 `outbound|9080||ratings.default.svc.cluster.local` Cluster 的結果如下。 ```json { "clusterName": "outbound|9080||ratings.default.svc.cluster.local", "endpoints": [ { "locality": { }, "lbEndpoints": [ { "endpoint": { "address": { "socketAddress": { "address": "172.33.100.2", "portValue": 9080 } } }, "metadata": { "filterMetadata": { "istio": { "uid": "kubernetes://ratings-v1-8558d4458d-ns6lk.default" } } } } ] } ] } ``` Endpoint 可以是一個或多個,Envoy 將根據一定規則選擇適當的 Endpoint 來路由。 **注**:Istio 1.1 將支持 `istioctl pc endpoint` 命令來查詢 Endpoint。 ## 參考 - [調試 Envoy 和 Pilot - istio.io](https://preliminary.istio.io/zh/help/ops/traffic-management/proxy-cmd/) - [理解 Istio Service Mesh 中 Envoy 代理 Sidecar 注入及流量劫持 - jimmysong.io](https://jimmysong.io/posts/envoy-sidecar-injection-in-istio-service-mesh-deep-dive/) - [Istio流量管理實現機制深度解析 - zhaohuabing.com](https://zhaohuabing.com/post/2018-09-25-istio-traffic-management-impl-intro/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看