隨著越來越多的公司擁抱云原生,從原先的單體應用演變為微服務,應用的部署方式也從虛機變為容器化,容器編排組件k8s也成為大多數公司的標配。然而在容器化以后,我們發現應用的性能比原先在虛擬機上表現更差,這是為什么呢?
壓測結果
容器化之前的表現
應用部署在虛擬機下,我們使用wrk工具進行壓測,壓測結果如下:
壓測結果
從壓測結果看,平均RT為1.68ms,qps為716/s,我們再來看下機器的資源使用情況,cpu 基本已經被打滿。
cpu 基本已經被打滿
容器化后的表現
使用wrk工具進行壓測,結果如下:
壓測結果
從壓測結果看,平均RT為2.11ms,qps為554/s,我們再來看下機器的資源使用情況,cpu基本已經被打滿。
cpu基本已經被打滿
性能對比結果
性能對比 | 虛擬機 | 容器 |
---|---|---|
RT | 1.68ms | 2.11ms |
QPS | 716/s | 554/s |
「總體性能下降:RT(25%)、QPS(29%)」
原因分析
架構差異
由于應用在容器化后整體架構的不同、訪問路徑的不同,將可能導致應用容器化后性能的下降,于是我們先來分析下兩者架構的區別。我們使用k8s作為容器編排基礎設施,網絡插件使用calico的ipip模式,整體架構如下所示。
架構差異
這里需要說明,雖然使用calico的ipip模式,由于pod的訪問為service的nodePort模式,所以不會走tunl0網卡,而是從eth0經過iptables后,通過路由到calico的calixxx接口,最后到pod。
性能分析
在上面壓測結果的圖中,我們容器化后,cpu的軟中斷si使用率明顯高于原先虛擬機的si使用率,所以我們使用perf繼續分析下熱點函數。
性能分析
為了進一步驗證是否是軟中斷的影響,我們使用perf進一步統計軟中斷的次數。
軟中斷的次數
?
「我們發現容器化后比原先軟中斷多了14%,到這里,我們能基本得出結論,應用容器化以后,需要更多的軟中斷的網絡通信導致了性能的下降。」
?
軟中斷原因
由于容器化后,容器和宿主機在不同的網絡namespace,數據需要在容器的namespace和host namespace之間相互通信,使得不同namespace的兩個虛擬設備相互通信的一對設備為veth pair,可以使用ip link命令創建,對應上面架構圖中紅色框內的兩個設備,也就是calico創建的calixxx和容器內的eth0。我們再來看下veth設備發送數據的過程
static?netdev_tx_t?veth_xmit(struct?sk_buff?*skb,?struct?net_device?*dev) { ... ????if?(likely(veth_forward_skb(rcv,?skb,?rq,?rcv_xdp) ... } static?int?veth_forward_skb(struct?net_device?*dev,?struct?sk_buff?*skb, ???????struct?veth_rq?*rq,?bool?xdp) { ?return?__dev_forward_skb(dev,?skb)??:?xdp?? ??veth_xdp_rx(rq,?skb)?: ??netif_rx(skb);//中斷處理 } /*?Called?with?irq?disabled?*/ static?inline?void?____napi_schedule(struct?softnet_data?*sd, ?????????struct?napi_struct?*napi) { ?list_add_tail(&napi->poll_list,?&sd->poll_list); ??//發起軟中斷 ?__raise_softirq_irqoff(NET_RX_SOFTIRQ); }
通過虛擬的 veth 發送數據和真實的物理接口沒有區別,都需要完整的走一遍內核協議棧,從代碼分析調用鏈路為 veth_xmit -> veth_forward_skb -> netif_rx -> __raise_softirq_irqoff,「veth的數據發送接收最后會使用軟中斷的方式,這也剛好解釋了容器化以后為什么會有更多的軟中斷,也找到了性能下降的原因。」
優化策略
原來我們使用calico的ipip模式,它是一種overlay的網絡方案,容器和宿主機之間通過veth pair進行通信存在性能損耗,雖然calico可以通過BGP,在三層通過路由的方式實現underlay的網絡通信,但還是不能避免veth pari帶來的性能損耗,針對性能敏感的應用,那么有沒有其他underly的網絡方案來保障網絡性能呢?那就是macvlan/ipvlan模式,我們以ipvlan為例稍微展開講講。
ipvlan L2 模式
IPvlan和傳統Linux網橋隔離的技術方案有些區別,它直接使用linux以太網的接口或子接口相關聯,這樣使得整個發送路徑變短,并且沒有軟中斷的影響,從而性能更優。如下圖所示:
ipvlan L2 模式
上圖是ipvlan L2模式的通信模型,可以看出container直接使用host eth0發送數據,可以有效減小發送路徑,提升發送性能。
ipvlan L3 模式
ipvlan L3模式,宿主機充當路由器的角色,實現容器跨網段的訪問,如下圖所示:
ipvlan L3 模式
Cilium
除了使用macvlan/ipvlan提升網絡性能外,我們還可以使用Cilium來提升性能,Cilium為云原生提供了網絡、可觀測性、網絡安全等解決方案,同時它是一個高性能的網絡CNI插件,高性能的原因是優化了數據發送的路徑,減少了iptables開銷,如下圖所示:
Cilium
雖然calico也支持ebpf,但是通過benchmark的對比,Cilium性能更好,高性能名副其實,接下來我們來看看官網公布的一些benchmark的數據,我們只取其中一部分來分析,如下圖:
benchmark數據
benchmark
無論從 QPS 和 CPU 使用率上 Cilium 都擁有更強的性能。
總結
容器化帶來了敏捷、效率、資源利用率的提升、環境的一致性等等優點的同時,也使得整體的系統復雜度提升一個等級,特別是網絡問題,容器化使得整個數據發送路徑變長,排查難度增大。不過現在很多網絡插件也提供了很多可觀測性的能力,幫助我們定位問題。
我們還是需要從實際業務場景出發,針對容器化后性能、安全、問題排查難度增大等問題,通過優化架構,增強基礎設施建設才能讓我們在云原生的路上越走越遠。
最后,感謝大家觀看,也希望和我討論云原生過程中遇到的問題。
編輯:黃飛
評論
查看更多