淺析Istio元件Envoy的流量管理

2022.12.24

淺析Istio元件Envoy的流量管理


Envoy的核心工作內容在於對業務透明的請求攔截,將所有進出流量進行管理。 對攔截的請求進行一定的規則進行安全訪問控制、接入控制、流量控制等諸多方面處理后,發送給應用程式。

背景介紹

微服務架構帶來的開發便捷性使業務功能的開發週期明顯縮短,通過對於雲計算平台架構的原生優化,讓業務功能的持續集成與交付更為敏捷。 但同時微服務架構也引入了服務治理的諸多問題:一個應用由多個服務組成,每個服務有數個實例,每個實例的運行狀態又在實時變化,這些催生了服務間通訊層的出現。 通訊層既不與應用程式代碼耦合,又能捕獲到底層環境的動態變化並作出適當的調整,避免業務出現單點故障。

1.ServiceMesh簡介

1.1服務網格(Service Mesh)簡介

服務網路是一個基礎設施層,用於處理服務間通信。 雲原生應用有著複雜的服務拓撲,服務網格負責在這些拓撲中實現請求的可靠傳遞。 在實踐中,服務網格通常實現為一組輕量級網路代理,它們與應用程式一起部署,但對應用程式透明。

從局部看,服務網格技術就是在應用節點上部署代理,應用將請求發給代理,由代理完成點對點的路由轉發。

在上面的圖中,如果把左邊圖中的應用程式去掉,只呈現出來代理和它們之間的調用關係(即右圖)。 這時Service Mesh的概念就會清晰:代理和調用關係形成完整的網路,代表服務間複雜的調用關係,承載著系統內的所有應用。

1.2服務網路架構特點及優勢

1)點對點通訊:沒有中心瓶頸。

2對應用無入侵:可以支援異構技術產品的集成。 同時對應用透明,應用開發不再需要關心複雜的網路通訊實現,可以專注業務邏輯的實現。

2.Istio及Envoy簡介

Istio是一個由Google,IBM和Lyft團隊合作開發的開源Service Mesh框架。 目前已成為ServiceMesh的事實技術標準,被廣泛應用於各個行業的IT架構。

Envoy 是用 C++語言開發的高性能代理,其內置服務發現、負載均衡、TLS終止、HTTP/2、GRPC代理、熔斷器、健康檢查,基於百分比流量拆分的灰度發佈、故障注入等功能,用於協調服務網格中所有服務的入站和出站流量。

3.Envoy流量管理的原理

3.1Iptables介紹

Istio調用Linux中的iptables進行流量管理。 iptables是一個運行在用戶空間的應用軟體,它通過控制Linux內核netfilter模組,來管理網路數據包的流動與轉送,實際上netfilter才是防火牆真正的安全框架。 netfilter是Linux網路安全大廈的基石,它提供了一整套鉤子(Hook)函數機制,IP層的5個鉤子點對應了iptables的5個內置鏈條:

  • PREROUTING:在此DNAT。
  • POSTROUTING:在此SNAT。
  • INPUT:處理輸入給本地進程的封包。
  • OUTPUT:處理本地進程輸出的封包。
  • FORWARD:處理轉發給其他機器、其他網路命名空間的封包。

3.2關於網路入站的IP封包

從網路入站的IP封包,先入TREOUTING鏈,而後進行路由判斷:

1)如果封包路由目的地是本機:則進入INPUT鏈,然後發給本地進程。

2如果封包路由目的地不是本機,並且啟用了IP轉發,則進入FORWARD鏈,然後通過POSTROUTING鏈,最後經過網路介面發走。

3對於本地進程發往協定棧的封包,則首先通過OUTPUT鏈,然後通過POSTROUTING鏈,最後經過網路介面發走。

3.3關於自定義鏈

除此以外,我們還可以自定義鏈,但自定義鏈只能被某個預設的鏈當做動作去調用才能起作用。

在Kubernetes中Istio通過Admission webhook的機制將Envoy Sidecar自動注入,與應用容器運行於同一個Pod中,這種情況下它們將共用網路名稱空間,因此也使用同一個網路協議棧。

Istio 給應用 Pod 注入的配置主要包括:

1)Init 容器 istio-init:用於Pod中設置iptables埠轉發。

2) Sidecar 容器 istio-proxy:運行Envoy Sidecar代理。

3.4Iptables配置規則

在容器初始化后,我們進入Sidecar容器切換為root使用者,查看配置的iptables規則。

iptables -t nat -S
  • 1.

ISTIO_INBOUND 鏈:對所有進入Pod但非指定埠(如22)的流量全部重定向至15006埠(Envoy入口流量埠)進行攔截處理。

ISTIO_OUTPUT 鏈:將由 istio-proxy 用戶空間發出且目的地不為localhost的Pod流出流量全部重定向至15001埠(envoy出口流量埠)。 其他流量全部直接放行至下一個POSTROUTING鏈,不用被Envoy攔截處理。

整體流量流向示意圖如下圖所示:

1)进入Pod的Inbound流量首先被PREROUTING链拦截并处理。

2)当TCP请求进入PREROUTING链时全部交给ISTIO_INBOUND处理。

-A PREROUTING -p tcp -j ISTIO_INBOUND
  • 1.

3)请求目标端口非15008/22/15090/15021/15020的TCP请求全部交给ISTIO_IN_REDIRECT处理。

-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
  • 1.

4)将发送到此的TCP请求全部重定向至15006端口(Envoy入口流量端口)

-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
  • 1.

5)在Envoy内部处理后,决定将数据包转发到应用,这一步对Envoy来说属于出口流量,会被netfilter拦截转发至出口流量OUTPUT链。

6)出站请求,当TCP请求进入OUTPUT链时全部交给ISTIO_OUTPUT处理。

-A OUTPUT -p tcp -j ISTIO_OUTPUT
  • 1.

7)匹配出站请求对应规则,请求本地服务,出口为lo网卡同时来自istio-proxy用户空间,流量返回到它的调用点中的下一条链执行,即POSTROUTING链 。

-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN -A ISTIO_OUTPUT -m owner 
--gid-owner 1337 -j RETURN
  • 1.
  • 2.

8)Sidecar发出的请求到达目标应用。

9)目标应用处理完业务逻辑后响应Sidecar,这一步对应用来说属于出口流量,再次被netfilter拦截转发至出口流量OUTPUT链。

10) 出站请求,当TCP请求进入OUTPUT链时全部交给ISTIO_OUTPUT处理。

-A OUTPUT -p tcp -j ISTIO_OUTPUT
  • 1.

11)请求下一个服务/响应请求,即请求非本地服务同时不来自istio-proxy用户空间,流量被转发至ISTIO_REDIRECT链。

-A ISTIO_OUTPUT -j ISTIO_REDIRECT
  • 1.

12)将重定向于此的TCP协议请求流量全部重定向至15001端口(Envoy出口流量端口)。

-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
  • 1.

13)在Envoy内部处理后,决定将数据包对外转发,这一步对Envoy来说属于出口流量,会被netfilter拦截转发至出口流量OUTPUT链。

14)出站请求,当TCP请求进入OUTPUT链时全部交给ISTIO_OUTPUT处理。

-A OUTPUT -p tcp -j ISTIO_OUTPUT
  • 1.

15請求非本地的服務,出口不為lo網卡同時來自istio-proxy用戶空間則跳過了ISTIO_REDIREC處理,直接RETURN到下一個鏈,即POSTROUTING鏈

-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN -A ISTIO_OUTPUT -m owner 
--gid-owner 1337 -j RETURN
  • 1.
  • 2.

16POSTROUTING鏈處理完成後,根據路由表選擇合適的網路發送Outbound流量。

4.總結

Envoy的核心工作內容在於對業務透明的請求攔截,將所有進出流量進行管理。 對攔截的請求進行一定的規則進行安全訪問控制、接入控制、流量控制等諸多方面處理后,發送給應用程式。 通過使用Envoy,可以使開發者專注於應用功能的開發,不用考慮複雜的網路通訊。