https://jvns.ca/blog/2017/10/10/operating-a-kubernetes-network/
作者 | Julia Evans
譯者 | qhwdw ?共計翻譯:145 篇 貢獻時間:309 天
最近我一直在研究 Kubernetes 網路。我註意到一件事情就是,雖然關於如何設定 Kubernetes 網路的文章很多,也寫得很不錯,但是卻沒有看到關於如何去運維 Kubernetes 網路的文章、以及如何完全確保它不會給你造成生產事故。
在本文中,我將儘力讓你相信三件事情(我覺得這些都很合理 :)):
我肯定不是 Kubernetes 網路方面的專家,但是我在配置 Kubernetes 網路時遇到了一些問題,並且比以前更加瞭解 Kubernetes 網路了。
運維聯網軟體是很難的
在這裡,我並不討論有關運維物理網路的話題(對於它我不懂),而是討論關於如何讓像 DNS 服務、負載均衡以及代理這樣的軟體正常工作方面的內容。
我在一個負責很多網路基礎設施的團隊工作過一年時間,並且因此學到了一些運維網路基礎設施的知識!(顯然我還有很多的知識需要繼續學習)在我們開始之前有三個整體看法:
sysctl
)配置正確,而一個錯誤配置的系統控制就很容易讓你處於“一切都很好”和“到處都出問題”的差別中。我距離成為一名網路運維專家還差得很遠,但是我認為以下幾點很重要:
切換到 Kubernetes 顯然是個非常大的更改!因此,我們來討論一下可能會導致錯誤的地方!
Kubernetes 網路元件
在本文中我們將要討論的 Kubernetes 網路元件有:
kube-dns
kube-proxy
kubelet
如果你打算配置 HTTP 服務,或許這些你都會用到。這些元件中的大部分我都不會用到,但是我盡可能去理解它們,因此,本文將涉及它們有關的內容。
最簡化的方式:為所有容器使用宿主機網路
讓我們從你能做到的最簡單的東西開始。這並不能讓你在 Kubernetes 中執行 HTTP 服務。我認為它是非常安全的,因為在這裡面可以讓你動的東西很少。
如果你為所有容器使用宿主機網路,我認為需要你去做的全部事情僅有:
如果你為每個 pod 直接使用宿主機網路,那就不需要 kube-dns 或者 kube-proxy 了。你都不需要一個作為基礎的改寫網路。
這種配置方式中,你的 pod 們都可以連線到外部網路(同樣的方式,你的宿主機上的任何行程都可以與外部網路對話),但外部網路不能連線到你的 pod 們。
這並不是最重要的(我認為大多數人想在 Kubernetes 中執行 HTTP 服務並與這些服務進行真實的通訊),但我認為有趣的是,從某種程度上來說,網路的複雜性並不是絕對需要的,並且有時候你不用這麼複雜的網路就可以實現你的需要。如果可以的話,盡可能地避免讓網路過於複雜。
運維一個改寫網路
我們將要討論的第一個網路元件是有關改寫網路的。Kubernetes 假設每個 pod 都有一個 IP 地址,這樣你就可以與那個 pod 中的服務進行通訊了。我在說到“改寫網路”這個詞時,指的就是這個意思(“讓你透過它的 IP 地址指向到 pod 的系統)。
所有其它的 Kubernetes 網路的東西都依賴正確工作的改寫網路。更多關於它的內容,你可以讀 這裡的 kubernetes 網路模型[2]。
Kelsey Hightower 在 kubernetes 艱難之路[3] 中描述的方式看起來似乎很好,但是,事實上它的作法在超過 50 個節點的 AWS 上是行不通的,因此,我不打算討論它了。
有許多改寫網路後端(calico、flannel、weaveworks、romana)並且規劃非常混亂。就我的觀點來看,我認為一個改寫網路有 2 個職責:
Okay! 因此!你的改寫網路可能會出現的問題是什麼呢?
iptables -A -t nat POSTROUTING -s $SUBNET -j MASQUERADE
),以確保那個容器能夠向 Kubernetes 之外發出網路請求。如果在這個規則上有錯誤,你的容器就不能連線到外部網路。這並不很難(它只是幾條 iptables 規則而已),但是它非常重要。我發起了一個 拉取請求[4],因為我想確保它有很好的彈性。flannel hostgw
後端,我們開始使用它的時候,節點刪除功能 尚未開始工作[5]。flannel etcd
叢集上丟失了資料,最後的結果將是在容器中網路連線會丟失。(現在這個問題已經被修複了)我在這裡主要討論的是過去發生在 Flannel 中的問題,但是我並不是要承諾不去使用 Flannel —— 事實上我很喜歡 Flannel,因為我覺得它很簡單(比如,類似 vxlan 在後端這一塊的部分[7] 只有 500 行程式碼),對我來說,透過程式碼來找出問題的根源成為了可能。並且很顯然,它在不斷地改進。他們在審查拉取請求方面做的很好。
到目前為止,我運維改寫網路的方法是:
sudo ip route list
命令去檢視它是否正確即可)我認為去遍歷所有已合併的拉取請求以及過去已修複的 bug 清單真的是非常有幫助的 —— 這需要花費一些時間,但這是得到一個其它人遇到的各種問題的清單的好方法。
對其他人來說,他們的改寫網路可能工作的很好,但是我並不能從中得到任何經驗,並且我也曾聽說過其他人報告類似的問題。如果你有一個類似配置的改寫網路:a) 在 AWS 上並且 b) 在多於 50-100 節點上執行,我想知道你運維這樣的一個網路有多大的把握。
運維 kube-proxy 和 kube-dns?
現在,我有一些關於運維改寫網路的想法,我們來討論一下。
這個標題的最後面有一個問號,那是因為我並沒有真的去運維過。在這裡我還有更多的問題要問答。
這裡的 Kubernetes 服務是如何工作的!一個服務是一群 pod 們,它們中的每個都有自己的 IP 地址(像 10.1.0.3、10.2.3.5、10.3.5.6 這樣)
kube-dns
去解析 Kubernetes 服務 DNS 名字為 IP 地址(因此,my-svc.my-namespace.svc.cluster.local 可能對映到 10.23.1.2 上)kube-proxy
配置 iptables
規則是為了在它們之間隨機進行均衡負載。Kube-proxy 也有一個使用者空間的輪詢負載均衡器,但是在我的印象中,他們並不推薦使用它。因此,當你發出一個請求到 my-svc.my-namespace.svc.cluster.local
時,它將解析為 10.23.1.2,然後,在你本地主機上的 iptables
規則(由 kube-proxy 生成)將隨機重定向到 10.1.0.3 或者 10.2.3.5 或者 10.3.5.6 中的一個上。
在這個過程中我能想像出的可能出問題的地方:
kube-dns
配置錯誤kube-proxy
掛了,以致於你的 iptables
規則沒有得以更新iptables
規則相關的一些問題我們來討論一下 iptables
規則,因為建立大量的 iptables
規則是我以前從沒有聽過的事情!
kube-proxy 像如下這樣為每個標的主機建立一個 iptables
規則:這些規則來自 這裡[8])
-A KUBE-SVC-LI77LBOOMGYET5US -m comment --comment "default/showreadiness:showreadiness" -m statistic --mode random --probability 0.20000000019 -j KUBE-SEP-E4QKA7SLJRFZZ2DD[b][c]
-A KUBE-SVC-LI77LBOOMGYET5US -m comment --comment "default/showreadiness:showreadiness" -m statistic --mode random --probability 0.25000000000 -j KUBE-SEP-LZ7EGMG4DRXMY26H
-A KUBE-SVC-LI77LBOOMGYET5US -m comment --comment "default/showreadiness:showreadiness" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-RKIFTWKKG3OHTTMI
-A KUBE-SVC-LI77LBOOMGYET5US -m comment --comment "default/showreadiness:showreadiness" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CGDKBCNM24SZWCMS
-A KUBE-SVC-LI77LBOOMGYET5US -m comment --comment "default/showreadiness:showreadiness" -j KUBE-SEP-RI4SRNQQXWSTGE2Y
因此,kube-proxy 建立了許多 iptables
規則。它們都是什麼意思?它對我的網路有什麼樣的影響?這裡有一個來自華為的非常好的演講,它叫做 支援 50,000 個服務的可伸縮 Kubernetes[9],它說如果在你的 Kubernetes 叢集中有 5,000 服務,增加一個新規則,將需要 11 分鐘。如果這種事情發生在真實的叢集中,我認為這將是一件非常糟糕的事情。
在我的叢集中肯定不會有 5,000 個服務,但是 5,000 並不是那麼大的一個數字。為解決這個問題,他們給出的解決方案是 kube-proxy 用 IPVS 來替換這個 iptables
後端,IPVS 是存在於 Linux 核心中的一個負載均衡器。
看起來,像 kube-proxy 正趨向於使用各種基於 Linux 內核的負載均衡器。我認為這隻是一定程度上是這樣,因為他們支援 UDP 負載均衡,而其它型別的負載均衡器(像 HAProxy)並不支援 UDP 負載均衡。
但是,我覺得使用 HAProxy 更舒服!它能夠用於去替換 kube-proxy!我用谷歌搜尋了一下,然後發現了這個 thread on kubernetes-sig-network[10],它說:
kube-proxy 是很難用的,我們在生產系統中使用它近一年了,它在大部分的時間都表現的很好,但是,隨著我們叢集中的服務越來越多,我們發現它的排錯和維護工作越來越難。在我們的團隊中沒有 iptables 方面的專家,我們只有 HAProxy & LVS 方面的專家,由於我們已經使用它們好幾年了,因此我們決定使用一個中心化的 HAProxy 去替換分散式的代理。我覺得這可能會對在 Kubernetes 中使用 HAProxy 的其他人有用,因此,我們更新了這個專案,並將它開源:https://github.com/AdoHe/kube2haproxy。如果你發現它有用,你可以去看一看、試一試。
因此,那是一個有趣的選擇!我在這裡確實沒有答案,但是,有一些想法:
正如你所看到的,我在關於如何運維 Kubernetes 中的內部代理方面的思路還是很混亂的,並且我也沒有使用它們的太多經驗。總體上來說,kube-proxy 和 kube-dns 還是很好的,也能夠很好地工作,但是我仍然認為應該去考慮使用它們可能產生的一些問題(例如,”你不能有超出 5000 的 Kubernetes 服務“)。
入口
如果你正在執行著一個 Kubernetes 叢集,那麼到目前為止,很有可能的是,你事實上需要 HTTP 請求去進入到你的叢集中。這篇部落格已經太長了,並且關於入口我知道的也不多,因此,我們將不討論關於入口的內容。
有用的連結
幾個有用的連結,總結如下:
kube-proxy
上效能的討論:https://www.youtube.com/watch?v=4-pawkiazEg我認為網路運維很重要
我對 Kubernetes 的所有這些聯網軟體的感覺是,它們都仍然是非常新的,並且我並不能確定我們(作為一個社群)真的知道如何去把它們運維好。這讓我作為一個操作者感到很焦慮,因為我真的想讓我的網路執行的很好!:) 而且我覺得作為一個組織,執行你自己的 Kubernetes 叢集需要相當大的投入,以確保你理解所有的程式碼片段,這樣當它們出現問題時你可以去修複它們。這不是一件壞事,它只是一個事而已。
我現在的計劃是,繼續不斷地學習關於它們都是如何工作的,以盡可能多地減少對我動過的那些部分的擔憂。
一如繼往,我希望這篇文章對你有幫助,並且如果我在這篇文章中有任何的錯誤,我非常喜歡你告訴我。
via: https://jvns.ca/blog/2017/10/10/operating-a-kubernetes-network/
作者:Julia Evans[14] 譯者:qhwdw 校對:wxy
本文由 LCTT 原創編譯,Linux中國 榮譽推出