本文已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

隆重介紹 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 可能很痛苦,尤其是在 Kubernetes 世界中,Pod 和容器是短暫的,並且 IP 經常變更。此過程涉及我們工程師的一堆手動命令。此外,iptables 日誌可能會因大量丟失而變得嘈雜,並且如果 IP 位址被重複使用,應用程式擁有者甚至可能有一些過時的資料。借助 kube-iptables-tailer 的幫助,我們開發人員的生活現在變得輕鬆多了。如下圖所示,此服務的原理可分為三個步驟:kube-iptables-tailer 的順序圖

* kube-iptables-tailer 的順序圖

1. 監看 iptables 日誌檔案的變更

我們現在使用 kube-iptables-tailer 來幫助識別該檔案中的變更,而不是要求人類工程師手動解讀原始 iptables 日誌。我們在叢集中每個主機節點上以 DaemonSet 運行該服務,並且它會定期追蹤 iptables 日誌檔案。該服務本身是用 Go 語言編寫的,它有多個 goroutine 用於並行運行的不同服務組件。我們使用通道在這些不同的組件之間共享資訊。例如,在此步驟中,服務會將其在 iptables 日誌檔案中偵測到的任何變更發送到 Go 通道,以便稍後解析。

2. 根據日誌前綴解析 iptables 日誌

一旦解析器透過特定的 Go 通道接收到新的日誌訊息,它將首先透過解析日誌前綴來檢查日誌訊息是否包含任何與網路策略相關的封包丟失資訊。基於我們的 Calico 策略的封包丟失將被記錄下來,其中在 iptables 日誌檔案中包含「calico-drop:」作為日誌前綴。在這種情況下,解析器將建立一個物件,其中來自日誌訊息的資料將儲存為物件的欄位。這些方便的物件稍後將用於定位在 Kubernetes 中運行的相關 Pod,並直接向它們發布通知。解析器還能夠識別重複的日誌並過濾它們,以避免造成混淆和消耗額外的資源。在解析過程之後,它將進入 kube-iptables-tailer 發送結果的最後一步。

3. 定位 Pod 並發送事件

kube-iptables-tailer 將使用 Kubernetes API,嘗試透過匹配從上一步解析的物件中儲存的 IP 來定位我們叢集中的發送者和接收者。因此,如果成功定位這些受影響的 Pod,則會向它們發布事件。Kubernetes 事件是旨在提供有關 Kubernetes 組件內部正在發生的事情的資訊的物件。在 Box,Kubernetes 事件的使用案例之一是直接向相應的應用程式報告錯誤(有關更多詳細資訊,請參閱此部落格文章)。kube-iptables-tailer 產生的事件包含有用的資訊,例如流量方向、IP 和來自另一側 Pod 的命名空間。我們也新增了 DNS 查找,因為我們的 Pod 也從裸機主機和 VM 上運行的服務發送和接收流量。此外,還實作了指數退避,以避免 Kubernetes API 伺服器不堪重負。

摘要

在 Box,kube-iptables-tailer 節省了時間,也讓許多不同團隊的開發人員的生活更加愉快。該服務能夠幫助偵測 iptables 日誌檔案中的變更,並將相應的資訊直接傳遞到 Kubernetes 叢集內的 Pod,而不是對基於網路策略的封包丟失一無所知。如果您未使用 Calico,您仍然可以應用任何其他日誌前綴(在服務中配置為環境變數)來匹配在您的 iptables 規則中定義的任何內容,並獲得有關與網路策略相關的封包丟失的通知。您也可能會發現其他情況,在這些情況下,透過 Kubernetes API 將來自主機系統的資訊提供給 Pod 非常有用。作為一個開源專案,非常歡迎每一份貢獻,以幫助共同改進該專案。您可以在 Github 上找到託管的專案:https://github.com/box/kube-iptables-tailer

特別感謝 Kunal ParmarGreg LyonsShrenik Dedhia 為這個專案做出貢獻。