本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
介紹 kube-iptables-tailer:Kubernetes 叢集中更好的網路可見性
在 Box,我們使用 Kubernetes 賦能工程師,使他們能夠掌控微服務的整個生命週期。在網路方面,我們的工程師使用 Tigera 的 Project Calico 以宣告式方式管理執行在 Kubernetes 叢集中的應用程式的網路策略。應用所有者定義 Calico 策略,以使其 Pod 能夠傳送/接收網路流量,這些策略被例項化為 iptables 規則。
然而,有時應用所有者可能會缺少或錯誤地宣告此類網路策略。在這種情況下,iptables 規則將導致受影響的 Pod 之間發生網路資料包丟棄,這些丟棄事件會記錄在一個應用所有者無法訪問的檔案中。我們需要一種機制,能夠根據其網路策略無縫地提供有關這些 iptables 資料包丟棄的警報,以幫助應用所有者快速診斷相應的問題。為了解決這個問題,我們開發了一項名為 kube-iptables-tailer 的服務,用於從 iptables 日誌中檢測資料包丟棄,並將其報告為 Kubernetes 事件。我們很自豪地將 kube-iptables-tailer 開源,供您在自己的叢集中使用,無論您是否使用 Calico 或其他網路策略工具。
改進應用所有者的體驗
應用所有者無需進行任何額外更改即可使用 kube-iptables-tailer。他們只需執行 kubectl describe pods
即可檢查其任何 Pod 的流量是否因 iptables 規則而被丟棄。所有從 kube-iptables-tailer 傳送的結果都將顯示在“事件”部分,這比閱讀原始 iptables 日誌對開發者來說是一種更好的體驗。
$ kubectl describe pods --namespace=YOUR_NAMESPACE
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning PacketDrop 5s kube-iptables-tailer Packet dropped when receiving traffic from example-service-2 (IP: 22.222.22.222).
Warning PacketDrop 10m kube-iptables-tailer Packet dropped when sending traffic to example-service-1 (IP: 11.111.11.111).
* 從 kube-iptables-tailer 傳送給具有網路問題的 Kubernetes Pod 的事件輸出
kube-iptables-tailer 的執行過程
在擁有 kube-iptables-tailer 之前,Box 的工程師獲取與其網路策略相關的資料包丟棄資訊的唯一方法是解析原始 iptables 日誌並匹配其服務 IP。這是一種次優的體驗,因為 iptables 日誌僅包含基本的 IP 地址資訊。將這些 IP 對映到特定的 Pod 可能很痛苦,尤其是在 Pod 和容器是短暫的、IP 頻繁變化的 Kubernetes 世界中。這個過程涉及我們工程師大量的手動命令。此外,由於大量丟棄,iptables 日誌可能會很嘈雜,如果 IP 地址被重複使用,應用所有者甚至可能擁有過時的資料。有了 kube-iptables-tailer 的幫助,我們開發人員的生活現在變得輕鬆多了。如下圖所示,這項服務的原理可以分為三個步驟:
* kube-iptables-tailer 的序列圖
1. 監控 iptables 日誌檔案變化
我們現在使用 kube-iptables-tailer 幫助識別 iptables 日誌檔案中的變化,而不是要求人工工程師手動解讀原始 iptables 日誌。我們將該服務作為 DaemonSet 執行在叢集中的每個主機節點上,並定期跟蹤 iptables 日誌檔案。服務本身是用 Go 編寫的,它有多個 goroutine 用於同時執行的不同服務元件。我們使用通道在這些不同的元件之間共享資訊。例如,在此步驟中,服務將把在 iptables 日誌檔案中檢測到的任何更改傳送到 Go 通道,以便稍後進行解析。
2. 根據日誌字首解析 iptables 日誌
一旦解析器透過特定的 Go 通道接收到新的日誌訊息,它將首先透過解析日誌字首來檢查日誌訊息是否包含任何與網路策略相關的資料包丟棄資訊。基於我們的 Calico 策略的資料包丟棄將記錄為在 iptables 日誌檔案中包含“calico-drop:”作為日誌字首。在這種情況下,解析器將建立一個物件,其中日誌訊息中的資料作為物件的欄位儲存。這些方便的物件稍後將用於定位 Kubernetes 中執行的相關 Pod 並直接向它們釋出通知。解析器還能夠識別重複日誌並對其進行過濾,以避免造成混淆和消耗額外的資源。在解析過程之後,kube-iptables-tailer 將進入傳送結果的最後一步。
3. 定位 Pod 併發送事件
利用 Kubernetes API,kube-iptables-tailer 將透過匹配上一步解析出的物件中儲存的 IP,嘗試定位叢集中的傳送方和接收方。如果成功定位,一個事件將被髮布到這些受影響的 Pod。Kubernetes 事件是旨在提供有關 Kubernetes 元件內部發生情況資訊的物件。在 Box,Kubernetes 事件的一個用例是直接向相應的應用程式報告錯誤(更多詳情,請參閱這篇部落格文章)。由 kube-iptables-tailer 生成的事件包含有用的資訊,例如流量方向、IP 地址以及另一側 Pod 的名稱空間。我們還添加了 DNS 查詢,因為我們的 Pod 也會從執行在裸金屬主機和虛擬機器上的服務傳送和接收流量。此外,還實現了指數退避機制,以避免使 Kubernetes API 伺服器過載。
總結
在 Box,kube-iptables-tailer 節省了時間,也讓許多跨團隊的開發者工作更愉快。該服務不再讓網路策略相關的資料包丟棄問題變得盲目,而是能夠幫助檢測 iptables 日誌檔案中的變化,並將相應的資訊直接傳遞到 Kubernetes 叢集內部的 Pod。如果您不使用 Calico,您仍然可以應用任何其他日誌字首(在服務中配置為環境變數),以匹配您 iptables 規則中定義的任何內容,並收到網路策略相關資料包丟棄的通知。您可能還會發現其他情況,將主機系統中的資訊透過 Kubernetes API 提供給 Pod 是很有用的。作為一個開源專案,歡迎任何貢獻,幫助我們共同改進該專案。您可以在 Github 上找到該專案:https://github.com/box/kube-iptables-tailer
特別感謝 Kunal Parmar、Greg Lyons 和 Shrenik Dedhia 對該專案的貢獻。