淺析Istio組件Envoy的流量管理
淺析Istio組件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.
16)POSTROUTING链处理完成后,根据路由表选择合适的网卡发送Outbound流量。
4.总结
Envoy的核心工作内容在于对业务透明的请求拦截,将所有进出流量进行管理。对拦截的请求进行一定的规则进行安全访问控制、接入控制、流量控制等诸多方面处理后,发送给应用程序。通过使用Envoy,可以使开发者专注于应用功能的开发,不用考虑复杂的网络通讯。