Pepper Metrics是我與同事開發的一個開源工具(github.com/zrbcool/pep…),其經過收集jedis/mybatis/httpservlet/dubbo/motan的運行性能統計,並暴露成prometheus等主流時序數據庫兼容數據,經過grafana展現趨勢。其插件化的架構也很是方便使用者擴展並集成其餘開源組件。
請你們給個star,同時歡迎你們成爲開發者提交PR一塊兒完善項目。node
隨着Service Mesh的概念逐漸被你們所接受,以及K8S做爲一個容器管理平臺已經成爲事實標準,你們對於K8S下的服務治理及流量管理的需求也是日漸強烈,在Google,IBM,Lyft幾個大廠的推進下,Istio + Envoy的Service Mesh及流量管理的解決方案補齊了K8S在服務治理,精細化的流量管理,灰度發佈等高級特性上的不足,因爲其Go加C++語言棧的優點,相比Linked的scala更節省資源,目前已經基本能夠肯定是Service Mesh領域的事實標準。
本篇文章,我以在阿里雲建立的K8S加Istio的集羣環境爲例,來說一下一個請求到底在K8S以及Istio、Envoy和微服務的Pod之間網絡上是如何流轉的。linux
本文中忽略了大量網絡及Kubernates中的概念及網絡實現原理的說明,若是讀者在閱讀中遇到困難,請參考下面列出的幾篇文章git
新建立集羣名爲test,下面有兩個node節點,主機名分別爲work001,和work002,(經過阿里雲容器服務Kubernetes版的應用市場)部署istio-ingressgateway並建立type爲LoadBalancer的Service,以及部署replics爲2的istio-ingressgateway POD實例,完成後可見兩個POD實例分別在work001及work002上啓動。
建立成功後,會在阿里雲控制檯上發現,LoadBalancer類型的Service會自動爲咱們建立好一個阿里雲負載均衡(182.92.251.227)實例並將咱們的兩個node節點的31061端口做爲阿里雲負載均衡實例的後端服務,以下圖所示:
github
從work001(上圖中的192.168.0.17)這臺機器查看iptables規則能夠看到:docker
➜ ~ iptables -L -t nat
Chain PREROUTING (policy ACCEPT 244 packets, 14640 bytes)
pkts bytes target prot opt in out source destination
32M 2003M KUBE-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
複製代碼
上面是一段nat表的規則,它的意思是,接受全部到來的數據,並交給KUBE-SERVICES這個規則鏈處理,下面咱們看下KUBE-SERVICES這個規則鏈:數據庫
Chain KUBE-SERVICES (2 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-FW-HBO2MBMQRZFAHKF2 tcp -- * * 0.0.0.0/0 182.92.251.227 /* default/istio-ingressgateway:http2 loadbalancer IP */ tcp dpt:80
562 33720 KUBE-NODEPORTS all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL
複製代碼
能夠看到目標是182.92.251.227:80的請求表要被轉發給KUBE-FW-HBO2MBMQRZFAHKF2這個規則鏈,繼續看KUBE-FW-HBO2MBMQRZFAHKF2:後端
Chain KUBE-FW-HBO2MBMQRZFAHKF2 (1 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-XLB-HBO2MBMQRZFAHKF2 all -- * * 0.0.0.0/0 0.0.0.0/0 /* default/istio-ingressgateway:http2 loadbalancer IP */
0 0 KUBE-MARK-DROP all -- * * 0.0.0.0/0 0.0.0.0/0 /* default/istio-ingressgateway:http2 loadbalancer IP */
Chain KUBE-MARK-DROP (7 references)
pkts bytes target prot opt in out source destination
0 0 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK or 0x8000
複製代碼
上面規則表示請求包轉交給規則鏈KUBE-XLB-HBO2MBMQRZFAHKF2處理,若是不能匹配則丟棄(KUBE-MARK-DROP)tomcat
Chain KUBE-XLB-HBO2MBMQRZFAHKF2 (2 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-SVC-HBO2MBMQRZFAHKF2 all -- * * 172.20.0.0/16 0.0.0.0/0 /* Redirect pods trying to reach external loadbalancer VIP to clusterIP */
80 4800 KUBE-SEP-EW7YLHH65NRUVIFQ all -- * * 0.0.0.0/0 0.0.0.0/0 /* Balancing rule 0 for default/istio-ingressgateway:http2 */
複製代碼
能夠看到該規則鏈有兩條規則,因爲咱們的請求來自於集羣外,經過SLB(182.92.251.227:80)進入集羣,因此匹配第二條規則KUBE-SEP-EW7YLHH65NRUVIFQbash
Chain KUBE-SEP-EW7YLHH65NRUVIFQ (2 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-MARK-MASQ all -- * * 172.20.1.157 0.0.0.0/0 /* default/istio-ingressgateway:http2 */
80 4800 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 /* default/istio-ingressgateway:http2 */ tcp to:172.20.1.157:80
Chain KUBE-MARK-MASQ (102 references)
pkts bytes target prot opt in out source destination
241 14460 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000
複製代碼
咱們的請求包匹配DNAT這條,DNAT將咱們的請求目標地址轉換爲172.20.1.157:80,並交給上層協議棧處理,這樣請求會走到routing decision(下面截圖來自於維基百科中大牛整理的Iptables/Netfilter的流轉圖) 網絡
work001的路由信息如圖所示# work001
➜ ~ ip route
default via 192.168.0.253 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
169.254.123.0/24 dev docker0 proto kernel scope link src 169.254.123.1
172.20.1.128/25 dev cni0 proto kernel scope link src 172.20.1.129
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.17
複製代碼
因爲172.20.1.157:80知足第三條172.20.1.128/25 dev cni0 proto kernel scope link src 172.20.1.129,該請求將直接交給網橋設備cni0(ip是172.20.1.129)處理
這樣請求就來到了cni0網橋
➜ ~ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
caf-sample-mesh-tomcat-77ff76b78f-fhgcl 2/2 Running 0 7d 172.20.1.167 cn-beijing.i-2zef83gtte2gddxlpy3q <none>
istio-ingressgateway-84b4868f6b-9xnts 1/1 Running 0 15d 172.20.1.157 cn-beijing.i-2zef83gtte2gddxlpy3q <none>
istio-ingressgateway-84b4868f6b-qxz5t 1/1 Running 0 22h 172.20.2.7 cn-beijing.i-2zeg4wnagly6jvlcz5kr <none>
zookeeper-854f49888f-4zhhk 2/2 Running 0 8d 172.20.1.165 cn-beijing.i-2zef83gtte2gddxlpy3q <none>
複製代碼
可以看到172.20.1.157這個IP由這個istio-ingressgateway-84b4868f6b-9xnts POD持有,進入這個POD,
➜ ~ kubectl exec -it istio-ingressgateway-84b4868f6b-9xnts bash
root@istio-ingressgateway-84b4868f6b-9xnts:/# ip route
default via 172.20.1.129 dev eth0
172.20.0.0/16 via 172.20.1.129 dev eth0
172.20.1.128/25 dev eth0 proto kernel scope link src 172.20.1.157
複製代碼
咱們知道K8S內的eth0網卡實際上是veth設備對的一邊放在了POD的網絡namespace內,而且重命名成eth0,另外一端在宿主機上插在網橋cni0上,從宿主機上能夠查看
➜ ~ brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.0a58ac140181 no veth0982819b
veth21f3386e
veth295aca54
veth29c64f6d
veth2fc83624
veth5413f391
veth55b5c32f
veth5d630032
veth5f4b9957
veth67b85819
veth6e5e5662
veth6efeda57
veth7413a550
veth831d20f5
veth849fecd0
veth8dbe1d2c
vetha7ec9173
vetha83f9559
vethcc9d3b42
vethd967d407
vethec751a37
vethf69ed27b
複製代碼
這時網橋cni0其實充當了二層交換機設備,全部發往cni0的數據包會路由給相應的veth對的另外一邊,也就是在容器POD的網絡namespace內的eth0網卡,咱們的示例中是:POD istio-ingressgateway-84b4868f6b-9xnts(IP爲172.20.1.157)
歷經重重關卡,咱們的請求包終於到達istio-ingressgateway容器內部,下面來總結下:
本講咱們主要介紹了,外網(集羣外)請求包如何經過阿里雲的四層負載均衡設備SLB轉發到咱們集羣內的POD(實際上是istio-ingressgateway)中,也就是咱們Service Mesh理念中常說的南北向流量,其實這塊的網絡轉發所有是由阿里雲的LoadBalancer(K8s的一種Service類型,由各個雲提供商來實現)以及K8s的cni網絡插件來實現的,目前還沒Istio什麼事
下一講咱們就來介紹下這個請求包在istio-ingressgateway中是如何流轉,及istio如何控制這個南北向流量的,敬請期待吧