使用Docker網路解決方案weave遇到的那些坑
前言
Weave 作為 Docker 跨主機叢集網路解決方案的一種,可以用於連線部署在多臺主機上的 Docker 容器,使用網路的應用程式不必去配置埠對映等資訊,Weave的通訊支援加密,所以使用者可以從一個不受信任的網路連線到主機。Weave 在控制層面和 Calico 類似,在資料層面通過UDP封裝實現 L2 overlay 。 Weave 在 1.2 版本之前都是使用 usersapce 實現,在 weave-1.2版本後, weave 結合了核心的 openvswitch 模組,實現了 open vSwitch datapath(odp)功能,結合 kernel 的 vxlan 特性,在網路效能上有較大的提升。 由於 odp 功能和核心相關模組結合較為緊密,在實際使用中可能遇到一些和核心相關的坑,本文描述的兩個問題都和核心有關係。
坑一:weave fastdp造成虛擬機器網路中斷
問題描述
在 weave 1.2 版本之後,考慮到原先 sleeve 模式的網路效能較差,增加了 fastdp 的模式,該模式成為了 weave 啟動時的預設模式,在 fastdp 模式中使用了 kernel 中的 openvswitch 模組,做報文封裝時使用了 vxlan 協議。在使用 qemu-kvm 建立的雲主機上, 如果安裝的是 centos7.0 ,核心版本為 kernel-3.10.123 ,在啟動 weave 並使用 fastdp 模式時,會造成 virtio_net 虛擬網路卡無法傳送資料,進而導致整個虛擬機器的網路中斷的問題。
問題分析
造成網路斷開的原因是因為觸發了核心的一個 bug ,該核心 bug 的 commit 連結地址:https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit/?id=8a0cafc9a8131cc545dc9924aed38f7176ee4ad7。
觸發該 bug 主要是由於 Weave 在初始化時會傳送一個 60000 位元組的 UDP 資料包進行 PMTU 的探測,並且 Weave 傳送使用的套接字為 raw socket ,導致了 virtio_net 使用的記憶體被汙染,表現的現象就是無法通知到宿主機上 vhost 取資料,在介面上看到傳送報文的計數始終不會增加。
該問題不是隻有 weave 才能觸發,使用普通的應用程式只要在建立 socket 時,使用是 raw socket ,並且在傳送資料時,傳送的資料大於介面的 MTU 值,介面的 UFO 功能是開啟的,都極有可能觸發該問題,造成網路的中斷。
圖1:fastdp 模式的資料流原理
解決方案
有兩種方式可以解決該問題:
1)升級核心,保證核心版本大於等於 3.13 ,
2)關閉虛擬機器網路卡的 ufo 特性,centos7.1 的 kernel-3.10.229 核心已經修復了該問題。
圖2:guest 通知 vhost 讀取資料流程
坑二:Weave無法使用fastdp模式
問題描述
在核心版本 CentOS Linux (3.10.0-327.10.1.el7.x86_64) 7 (Core) 上 ,weave 版本大約 1.2 ,如果雲主機的 MTU 值為 1450 或者小於 1474 , weave 啟動時無法正常的選擇 fast data path模式。在 weave 啟動後一直選擇 sleeve 模式,本應該預設模式為 fastdp ,該問題也和核心的版本相關。
問題分析
Weave的fast data path路徑使用到了 odp 技術,也就是核心中的OVS模組,在 Container 中直接傳送資料包到 ovs 模組。在啟動 Weave 時,會自動選擇使用 sleeve 模式還是 fastdp 模式,這裡通過傳送心跳包來決定的,出現該問題時,在雲主機通過 docker logs weave 的日誌可以看到這樣出錯的資訊:fastdp timed out waiting for vxlan heartbeat。
這個 heartbeat 的資料包,是一個 UDP 包,目的埠號為 6784 ,在某些雲主機上介面的MTU值為 1454 ,但是在傳送 UDP 的 heartbeat 資料包時,傳送的是 1474 位元組,這樣就會對報文在IP層進行分片,但在主機上發現心跳報文傳送不出,當 MTU 的值修改為 1500 後,就可以傳送出去,在 MTU 為 1454 的情況下,會出現下面的 ICMP 的錯誤報文。
圖3: 出現的錯誤icmp報文
出現上面錯誤的 icmp 報文,是核心中的 ip_fragment 函式呼叫 icmp_send 函式傳送的,
if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) ||
(IPCB(skb)->frag_max_size &&
IPCB(skb)->frag_max_size > mtu))) {
IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
htonl(mtu));
kfree_skb(skb);
return -EMSGSIZE;
}
通過上面的程式碼可以看出,如果出現上面出錯的 ICMP 報文,下面的判斷條件 iph->frag_off & htons(IP_DF)) && !skb->ignore_df 需要成立,通過對抓取的報文分析可知 iph->frag_off & htons(IP_DF)) 的值為真,那麼 skb->ignore_df 值需要為 0 ,這裡的關鍵在於 skb->ignore_df 的值是何時賦值為0的。
通過分析 weave 傳送心跳包的流程可知,在 vxlan_tnl_send 函式中,對 skb->ignore_df 賦值為 1 ; 在最後呼叫 tunnel 的傳送函式 iptunnel_xmit 時,呼叫了 skb_scrub_packet 函式,在該函式中又重新對 skb->ignore_df 賦值為0.( kernel 版本為:3.10.0-327.el7 ),造成後續傳送報文時,傳送了 ICMP 目的不可達,並且錯誤碼為 ICMP_FRAG_NEEDED 的報文。
void skb_scrub_packet(struct sk_buff *skb, bool xnet)
{
skb->tstamp.tv64 = 0;
skb->pkt_type = PACKET_HOST;
skb->skb_iif = 0;
skb->ignore_df = 0;
skb_dst_drop(skb);
secpath_reset(skb);
nf_reset(skb);
nf_reset_trace(skb);
if (!xnet)
return;
skb_orphan(skb);
skb->mark = 0;
}
上面程式碼是 centos 7 的 3.10.0 - 327.el7 ,而在老一些的核心版本 3.10.0 - 123.el7 上, iptunnel_xmit 呼叫的是 secpath_reset(skb) 函式,在該函式中並沒有對 skb->local_df (低版本的核心使用的是 local_df )進行重新的初始化,也就是 skb->local_df 值仍舊為1,因此在該版本上不會出現該問題。
static inline void
secpath_reset(struct sk_buff *skb)
{
#ifdef CONFIG_XFRM
secpath_put(skb->sp);
skb->sp = NULL;
#endif
}
圖4:核心版本不同造成設定不同
在新的核心版本中存在該問題,但是核心本身是沒問題的,還是 weave 使用者態的管理 datapath 的程式和核心的適配上有問題(它並不是使用 ovs-switchd ),在 ovs 中的對 tunnel 型別可以設定為 df_default = false 進行分片。
解決方案
保證介面 MTU 值為預設的1500.
總結
Weave 的 odp 功能使用了核心的特性,在使用 weave 的 fastdp 功能時遇到上面兩個問題,都是和核心有著緊密聯絡,通過對核心層面的分析,可以定位到問題的根因。在後續遇到類似問題時,可以多從核心的角度進行考慮。
本文由『UCloud核心團隊』原創,作者:曾福振。
未經允許不得私自轉載,比心~
相關文章
- docker 打包 selenium+chromedriver+chrome 遇到的坑和解決方案DockerChrome
- 容器中跨主機的網路方案-Weave
- 使用vue匯出excel遇到的那些坑VueExcel
- wepy+weappx開發小程式遇到的坑以及解決方案APP
- Python:那些年我們遇到的坑Python
- 解決input 中placeholder的那些神坑
- 063、如何使用weave網路(2019-04-03 週三)
- 那些前端工作中遇到的坑(01)前端
- 異常處理遇到過的那些坑
- 網路安全控制網管解決方案
- 網路運維網管解決方案運維
- 使用dataX遇到的坑
- 微信小程式開發遇到的那些坑微信小程式
- 玩Deno遇到問題的解決方案
- 安緹網路雲解決方案
- docker ubuntu 的vi,nano命令無法使用的解決方案DockerUbuntuNaN
- 區塊鏈私有鏈搭建中遇到的那些坑區塊鏈
- 現代網路的解決方案—SD-WAN
- 反網路爬蟲以及解決方案爬蟲
- 網路安全解決方案與智慧城市
- Windows下使用python庫 curses遇到錯誤訊息的解決方案WindowsPython
- 記錄內網Docker啟動Stable-Diffusion遇到的幾個坑內網Docker
- ffmpeg軟解碼遇到的坑
- Docker的網路模式詳解Docker模式
- KImysql timestamp比較查詢遇到的坑及解決ehsMySql
- 森林防火應急現場的網路解決方案
- 小程式使用Picker遇到的坑
- 使用constexpr時遇到的小坑
- 使用laravels可能遇到的小小坑Laravel
- 怎樣解決更新MacOS big sur時遇到的那些問題!Mac
- 網際網路公司無線覆蓋解決方案
- WiNet智慧網路解決方案解讀 讓網路運維更簡單運維
- Composer 使用過程中遇到的問題和解決方案
- Laravel 使用 swoole 協程遇到的坑Laravel
- 使用MySQL時遇到的各種坑MySql
- 網路會議室解決方案系統部署
- mpvue使用sass的解決方案Vue
- mpvue 使用sass的解決方案Vue
- 在靜態網路環境中快速修改網路配置資訊的解決方案