使用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內核團隊』原創,作者:曾福振。

未經允許不得私自轉載,比心~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內容