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

DIY:使用 Kubernetes 建立自己的雲(第 2 部分)

繼續我們關於如何僅使用 Kubernetes 生態系統構建自己的雲的系列文章。在上一篇文章中,我們解釋瞭如何基於 Talos Linux 和 Flux CD 準備一個基本的 Kubernetes 發行版。在本文中,我們將向您展示 Kubernetes 中的幾種不同虛擬化技術,並準備在 Kubernetes 中執行虛擬機器所需的一切,主要是儲存和網路。

我們將討論 KubeVirt、LINSTOR 和 Kube-OVN 等技術。

但首先,讓我們解釋一下為什麼需要虛擬機器,以及為什麼不能只使用 Docker 容器來構建雲?原因在於容器沒有提供足夠的隔離級別。儘管情況逐年改善,但我們經常遇到允許逃離容器沙箱並在系統中提升許可權的漏洞。

另一方面,Kubernetes 最初並非設計為多租戶系統,這意味著基本的使用模式是為每個獨立的專案和開發團隊建立一個單獨的 Kubernetes 叢集。

虛擬機器是在雲環境中隔離租戶的主要手段。在虛擬機器中,使用者可以使用管理員許可權執行程式碼和程式,但這不會影響其他租戶或環境本身。換句話說,虛擬機器可以實現硬性多租戶隔離,並在租戶互不信任的環境中執行。

Kubernetes 中的虛擬化技術

有幾種不同的技術將虛擬化引入 Kubernetes 世界:KubeVirtKata Containers 是最受歡迎的。但你應該知道它們的工作方式不同。

Kata Containers 實現了 CRI(容器執行時介面),透過在虛擬機器中執行標準容器來為其提供額外的隔離層。但它們在同一個 Kubernetes 叢集中工作。

A diagram showing how container isolation is ensured by running containers in virtual machines with Kata Containers

一張圖表,顯示瞭如何透過在帶有 Kata Containers 的虛擬機器中執行容器來確保容器隔離

KubeVirt 允許使用 Kubernetes API 執行傳統的虛擬機器。KubeVirt 虛擬機器作為容器中的常規 linux 程序執行。換句話說,在 KubeVirt 中,容器被用作執行虛擬機器(QEMU)程序的沙箱。這可以從下圖中清楚地看到,透過觀察 KubeVirt 中虛擬機器的即時遷移是如何實現的。當需要遷移時,虛擬機器會從一個容器移動到另一個容器。

A diagram showing live migration of a virtual machine from one container to another in KubeVirt

一張圖表,顯示了在 KubeVirt 中虛擬機器從一個容器即時遷移到另一個容器的過程

還有一個替代專案 - Virtink,它使用 Cloud-Hypervisor 實現輕量級虛擬化,並且最初專注於使用 Cluster API 執行虛擬 Kubernetes 叢集。

考慮到我們的目標,我們決定使用 KubeVirt,因為它是該領域最受歡迎的專案。此外,我們擁有廣泛的專業知識,並且已經對 KubeVirt 做出了很多貢獻。

KubeVirt 易於安裝,並允許您使用 containerDisk 功能開箱即用地執行虛擬機器 - 這允許您直接從容器映象倉庫中以 OCI 映象的形式儲存和分發虛擬機器映象。帶有 containerDisk 的虛擬機器非常適合建立 Kubernetes工作節點和其他不需要狀態持久化的虛擬機器。

為了管理持久化資料,KubeVirt 提供了一個獨立的工具,即 Containerized Data Importer (CDI)。它允許克隆 PVC 並用基礎映象中的資料填充它們。如果您想為虛擬機器自動配置持久卷,CDI 是必需的,並且 KubeVirt CSI 驅動程式也需要它,該驅動程式用於處理來自租戶 Kubernetes 叢集的持久卷宣告。

但首先,你必須決定在哪裡以及如何儲存這些資料。

Kubernetes 虛擬機器的儲存

隨著 CSI(容器儲存介面)的引入,與 Kubernetes 整合的各種技術變得可用。實際上,KubeVirt 充分利用了 CSI 介面,使得虛擬化儲存的選擇與 Kubernetes 本身的儲存選擇緊密相關。但是,有一些細微差別需要考慮。與通常使用標準檔案系統的容器不同,塊裝置對於虛擬機器更有效率。

儘管 Kubernetes 中的 CSI 介面允許請求兩種型別的卷:檔案系統和塊裝置,但驗證您的儲存後端是否支援這一點很重要。

為虛擬機器使用塊裝置消除了對額外抽象層(如檔案系統)的需求,這使其效能更高,並且在大多數情況下能夠使用 ReadWriteMany 模式。此模式允許多個節點併發訪問卷,這是在 KubeVirt 中啟用虛擬機器即時遷移的關鍵功能。

儲存系統可以是外部的或內部的(在超融合基礎設施的情況下)。在許多情況下,使用外部儲存可以使整個系統更穩定,因為您的資料與計算節點分開儲存。

A diagram showing external data storage communication with the compute nodes

一張圖表,顯示外部資料儲存與計算節點的通訊

外部儲存解決方案在企業系統中通常很受歡迎,因為這種儲存通常由外部供應商提供,由其負責運營。與 Kubernetes 的整合僅涉及安裝在叢集中的一個小元件 - CSI 驅動程式。該驅動程式負責在此儲存中配置卷並將其附加到 Kubernetes 執行的 Pod。然而,此類儲存解決方案也可以使用純開源技術實現。其中一個流行的解決方案是使用 democratic-csi 驅動程式的 TrueNAS

A diagram showing local data storage running on the compute nodes

一張圖表,顯示在計算節點上執行的本地資料儲存

另一方面,超融合系統通常使用本地儲存(當您不需要複製時)和軟體定義儲存實現,這些儲存通常直接安裝在 Kubernetes 中,例如 Rook/CephOpenEBSLonghornLINSTOR 等。

A diagram showing clustered data storage running on the compute nodes

一張圖表,顯示在計算節點上執行的叢集資料儲存

超融合系統有其優勢。例如,資料本地性:當您的資料儲存在本地時,訪問這些資料的速度更快。但也有缺點,因為這樣的系統通常更難管理和維護。

在 Ænix,我們希望提供一個即用型解決方案,無需購買和設定額外的外部儲存,並且在速度和資源利用方面都是最優的。LINSTOR 成為了這個解決方案。經過時間考驗和行業流行的技術,如 LVM 和 ZFS 作為後端,讓人相信資料被安全地儲存。基於 DRBD 的複製速度非常快,並且消耗少量計算資源。

要在 Kubernetes 中安裝 LINSTOR,有 Piraeus 專案,它已經為 KubeVirt 提供了即用型塊儲存。

Kubernetes 虛擬機器的網路

儘管有相似的介面 - CNI,Kubernetes 中的網路架構實際上更復雜,通常由許多不直接相互連線的獨立元件組成。實際上,您可以將 Kubernetes 網路分為四個層次,如下所述。

節點網路(資料中心網路)

節點之間相互連線的網路。這個網路通常不受 Kubernetes 管理,但它很重要,因為沒有它,任何東西都無法工作。在實踐中,裸機基礎設施通常有不止一個這樣的網路,例如,一個用於節點間通訊,第二個用於儲存複製,第三個用於外部訪問等。

A diagram showing the role of the node network (data center network) on the Kubernetes networking scheme

一張圖表,顯示節點網路(資料中心網路)在 Kubernetes 網路方案中的作用

配置節點之間的物理網路互動超出了本文的範圍,因為在大多數情況下,Kubernetes 利用已經存在的網路基礎設施。

Pod 網路

這是您的 CNI 外掛提供的網路。CNI 外掛的任務是確保叢集中所有容器和節點之間的透明連線。大多數 CNI 外掛實現了一個扁平網路,從中為每個節點上的使用分配單獨的 IP 地址塊。

A diagram showing the role of the pod network (CNI-plugin) on the Kubernetes network scheme

一張圖表,顯示 Pod 網路(CNI 外掛)在 Kubernetes 網路方案中的作用

在實踐中,您的叢集可以有多個由 Multus 管理的 CNI 外掛。這種方法常用於基於 KubeVirt 的虛擬化解決方案 - RancherOpenShift。主 CNI 外掛用於與 Kubernetes 服務整合,而額外的 CNI 外掛用於實現私有網路(VPC)和與資料中心物理網路的整合。

預設的 CNI 外掛可用於連線網橋或物理介面。此外,還有一些專門的外掛,如 macvtap-cni,旨在提供更高的效能。

在 Kubernetes 中執行虛擬機器時需要記住的另一個方面是需要 IPAM(IP 地址管理),特別是對於由 Multus 提供的輔助介面。這通常由在您的基礎設施內執行的 DHCP 伺服器管理。此外,虛擬機器的 MAC 地址分配可以由 Kubemacpool 管理。

儘管在我們的平臺中,我們決定走另一條路,完全依賴 Kube-OVN。這個 CNI 外掛基於 OVN(開放虛擬網路),最初是為 OpenStack 開發的,它為 Kubernetes 中的虛擬機器提供了一個完整的網路解決方案,具有用於管理 IP 和 MAC 地址的自定義資源,支援在節點之間保留 IP 地址的即時遷移,並能夠建立 VPC 以實現租戶之間的物理網路分離。

在 Kube-OVN 中,您可以將單獨的子網分配給整個名稱空間,或使用 Multus 將它們作為額外的網路介面連線。

服務網路

除了 CNI 外掛,Kubernetes 還有一個服務網路,主要用於服務發現。與傳統的虛擬機器相反,Kubernetes 最初設計為執行具有隨機地址的 Pod。而服務網路提供了一個方便的抽象(穩定的 IP 地址和 DNS 名稱),它將始終將流量引導到正確的 Pod。儘管雲中虛擬機器的 IP 通常是靜態的,但這種方法也常用於虛擬機器。

A diagram showing the role of the services network (services network plugin) on the Kubernetes network scheme

一張圖表,顯示服務網路(服務網路外掛)在 Kubernetes 網路方案中的作用

Kubernetes 中服務網路的實現由服務網路外掛處理,標準實現稱為 kube-proxy,在大多數叢集中使用。但如今,此功能可能作為 CNI 外掛的一部分提供。最先進的實現由 Cilium 專案提供,它可以在 kube-proxy 替換模式下執行。

Cilium 基於 eBPF 技術,該技術允許有效解除安裝 Linux 網路堆疊,從而與基於 iptables 的傳統方法相比,提高了效能和安全性。

在實踐中,Cilium 和 Kube-OVN 可以輕鬆地整合,以提供一個統一的解決方案,為虛擬機器提供無縫、多租戶的網路,以及高階網路策略和組合的服務網路功能。

外部流量負載均衡器

到這個階段,您已經擁有在 Kubernetes 中執行虛擬機器所需的一切。但實際上還有一件事。您仍然需要從叢集外部訪問您的服務,而外部負載均衡器將幫助您組織這一點。

對於裸機 Kubernetes 叢集,有幾種負載均衡器可用:MetalLBkube-vipLoxiLB,此外 CiliumKube-OVN 也提供了內建實現。

外部負載均衡器的作用是提供一個可從外部訪問的穩定地址,並將外部流量引導到服務網路。服務網路外掛將像往常一樣將其引導到您的 Pod 和虛擬機器。

The role of the external load balancer on the Kubernetes network scheme

一張圖表,顯示外部負載均衡器在 Kubernetes 網路方案中的作用

在大多數情況下,在裸機上設定負載均衡器是透過在叢集內的節點上建立浮動 IP 地址,並使用 ARP/NDP 或 BGP 協議從外部通告它來實現的。

在探索了各種選項後,我們認為 MetalLB 是最簡單、最可靠的解決方案,儘管我們不嚴格強制只使用它。

另一個好處是,在 L2 模式下,MetalLB 的 speaker 會透過使用 memberlist 協議執行活性檢查,持續檢查其鄰居的狀態。這使得故障轉移能夠獨立於 Kubernetes 控制平面工作。

結論

至此,我們對 Kubernetes 中的虛擬化、儲存和網路的概述就結束了。這裡提到的技術在 Cozystack 平臺上已經可用並預先配置好,您可以在那裡無限制地試用它們。

下一篇文章中,我將詳細介紹如何在此基礎上,只需點選一個按鈕即可實現功能齊全的 Kubernetes 叢集的配置。