本篇文章要來探討 Kubernetes/Docker 一些關於 connection timeout 的事情,文章非常長,這邊幫大家重點整理
1. 跟我之前分享的 DNS timeout 問題類似,都會踩到 Kernel 的 race condition,都是 __ip_conntrack_confirm 這個人丟掉大家封包的
2. 本文著重於怎麼發現這個問題,如何減緩這個問題。對於喜歡研究細節的人值得一看。
3. 2017年底作者團隊開始將服務遷移到 Kubernetes (v1.8), Flannel(1.9.0),開始發現團隊中基於 Scala 的應用程式出現封包 timeout 的問題,這導致部分請求回應都延遲1-3秒
4. 決定認真調查網路問題,經由研究與錄製封包後發現 TCP 重送(SYN)的現象,該現象導致第一個封包會特別慢
5. 接下來要縮小範圍,使用環境中的一個VM作為基底,上面安裝 docker,開始觀察相關的網路流量與封包,發現可以重製這個行為,第一個封包從容器出去後,宿主機上面的真實網卡卻看不到,直到下次第二個封包就可以。藉由這個行為他們判斷,問題出在VM上,跟底層其餘硬體架構無關,藉此縮小問題範圍。
6. 介紹 iptalbes + SNAT + conntrack
7. 問題發生在 Kernel 裡面針對 SNAT 去選擇對外 source IP 時會出錯,因為(1)挑選一個適當的 source port, (2)將該紀錄寫到 conntrack 這兩個步驟中間會有落差,因此如果兩個封包同時進入(1),選到一樣的結果,後續要跑(2)就會有一個人寫不進去,導致封包被丟棄
8. 一種解決方法是告訴 kernel 請隨機幫我挑選對外的 source port, 這樣就算大家同時執行(1),有很大的機會會挑到不同的 source port,藉此減少衝突的機會。
9. iptables 執行 --masquerate 的時候可以下 --random-fully 這個參數
10. 團隊當時客製化 Flannel 來解決這個問題
註: 對 SNAT 有興趣瞭解的可以參考我之前撰寫的 SNAT Kernel 原始碼閱讀文章
https://www.hwchiu.com/iptables-masquerade.html
https://www.hwchiu.com/iptables-masquerade-handson.html
https://tech.xing.com/a-reason-for-unexplained-connection-timeouts-on-kubernetes-docker-abd041cf7e02
同時也有10000部Youtube影片,追蹤數超過2,910的網紅コバにゃんチャンネル,也在其Youtube影片中提到,...
race condition解決 在 矽谷牛的耕田筆記 Facebook 的精選貼文
今天跟大家分享一個 UDP 於 Linux Kernel 內的 Race Condition 問題。這問題我以前於 Linux Kernel 3.14 也有採過一樣的雷,但是到今日都還沒有一個很漂亮的解決方案,這邊就快速的跟大家介紹一下這個問題是什麼,以及跟 k8s 有什麼關係
# 發生前提
1. 使用 UDP 這種沒有重送機制的協定
2. Kernel 有開啟 conntrack 此功能
# 發生條件
相同的 Client 短時間內透過 UDP (也許是不同 thread) 送出兩個 UDP 封包到外面,對於 Linux Kernel 來說,會希望透過 conntrack 來追蹤每一條連線,但是底層建立的時候會有一些會有一些機制,因此當兩個封包同時進入的時候,有可能就會因為先後順序導致第二個封包被丟棄
# 可能發生問題
DNS 的請求封包預設情況下會同時透過 UDP 送出 A & AAAA 兩個封包,而這兩個封包如果很巧的採到這個情況,然後你的 A 封包就沒有辦法順利解出 DNS,最後就要等五秒的 timeout 來重新發送
下偏這篇文章就是 weave works 遇到 DNS 5秒 timeout 的問題,然後仔細的將我上面所寫的總結給解釋清楚,每一個步驟發生什麼事情,什麼是 conntrack 以及暫時的 workaround 是什麼
之後會在跟大家分享目前一些解決方法怎麼做
https://www.weave.works/blog/racy-conntrack-and-dns-lookup-timeouts
race condition解決 在 軟體開發學習資訊分享 Facebook 的最佳解答
課程介紹
在一家國際投資銀行12樓的會議中,氣氛令人沮喪。 在關鍵的核心應用程式失敗並導致系統範圍內的中斷之後,公司的開發人員開會討論了最佳的解決方案。
“夥計們,我們這裡有一個嚴重的問題。我發現中斷是由我們的程式碼中的競爭狀況( race condition )引起的,是在前一段時間引入的,並在昨晚觸發。” 高階開發人員Mark Adams說。
房間變得安靜了。 在繁華的城市交通中,落地窗外的汽車緩慢而無聲地蠕動。 高階開發人員立即瞭解了情況的嚴重性,意識到他們現在將全天候工作以解決問題並整理資料儲存中的混亂情況。 經驗不足的開發人員瞭解競爭狀況很嚴重,但不知道到底是什麼原因導致的,因此請閉嘴。
最終,交付經理 Brian Holmes 打破了沉默,“該應用程式已經運行了幾個月,沒有任何問題,我們最近還沒有釋出任何程式碼,該軟體怎麼可能崩潰了?!”
每個人都搖搖頭,回到辦公桌前,把Brian獨自留在房間裡,感到困惑。 他拿出手機,搜尋“race condition”。
聽起來有點熟? 你有多少次聽到另一位開發人員在談論使用執行緒和並發(Concurrency)程式設計來解決特定問題,卻出於恐懼而置身於討論之外?
這是高階開發人員永遠不會分享的小祕密…多執行緒程式設計並不比普通程式設計難得多。 開發人員害怕併發程式設計,因為他們認為這是隻有經驗豐富的開發人員才能使用的高階主題。
這遠非真相。 我們的思想非常習慣於處理並發(Concurrency)。 實際上,我們在日常生活中做到這一點沒有任何問題,但是以某種方式我們很難將其轉換為程式碼。 造成這種情況的原因之一是,我們不熟悉可用於管理併發的概念和工具。 本課程旨在幫助你瞭解如何使用多執行緒工具和概念來管理並行程式設計。 它被設計為儘可能實用。 我們從有關並行性的一些理論開始,然後解釋作業系統如何處理多個行程( process )和執行緒。 稍後,我們將繼續透過使用多執行緒解決範例問題來解釋可用的多種工具。
在本課程中,我們將 Google 的 Go 程式語言及其 goroutines 結合使用,但是,此處學習的概念可以應用於大多數程式語言。
https://softnshare.com/multithreading-in-go-lang/