Lasso 是一個控制器框架。
Lasso 與控制器運行時專案具有一定的功能相似性,可以用來取代控制器運行時。
套索是低等級的。如果您想管理自己的控制器,那麼您可以使用它。如果您正在尋找更多便利性和功能來創建自己的資源類型,我們建議您查看 Wrangler。
Wrangler 和 Norman 使用的核心控制器框架。
本文檔的編寫考慮了兩種受眾:Kubernetes 控制器的新手和 Kubernetes 控制器不陌生但 lasso 新手的人。
如果您屬於「不熟悉 Kubernetes 控制器的人」類別,您可以跳到 Lasso 的價值主張。
如果您不熟悉 Kubernetes 控制器,建議您不要跳過任何部分。
如果您缺乏基本的 Kubernetes 知識,那麼建議您先查閱其他基礎知識文檔,例如 Kubernetes 概述。
注意:這將是一個非常簡短的速成課程。我們鼓勵您尋找有關該主題的其他資源,有很多!兩個建議的資源是範例控制器專案和 Kubernetes 控制器框架簡介。
來自 Kubernetes 文檔
在 Kubernetes 中,控制器是一個控制循環,它透過 apiserver 監視叢集的共用狀態,並進行更改,嘗試將目前狀態移至所需狀態。
「控制器」這個詞的使用比上述定義可能讓您相信的更為寬鬆。用我們自己的話來說:控制器是回應 Kubernetes 資源事件的循環處理程序。在 Lasso 中,我們還使用「控制器」一詞來指稱負責註冊此循環處理程序並為其提供所需資源的整個結構。簡而言之,控制器是捆綁與 Kubernetes 類型互動和操作所需的一切的結構。
為了實現上述目標,需要滿足幾個子目標:
有許多框架可以幫助實現上述目標。套索就是其中之一。大多數這些框架(包括 lasso)的共同點是它們使用 client-go 的功能來實現這些目標。您只需使用 client-go 即可實現這些目標。在本節的其餘部分中,我們將僅使用 client-go 概念來介紹如何將控制器組合在一起。
通知者用於實現 Kubernetes 控制器所需的上述目標。告密者擁有一個事件處理程序和一個索引器。索引器擁有儲存和映射函數,用於對儲存中的物件進行索引,稱為索引器。底層結構不同,但下面顯示了一個偽結構來說明這一點:
Informer
EventHandler
Indexer
Store
Indexers
EventHandler 可以有不同的邏輯來建立、更新和刪除事件。事件處理程序是控制器的用武之地。
索引器用作快取。
儲存是索引器保存物件的地方。
索引器是索引器可用於索引持久性物件的函數。一旦使用索引器建立索引,就可以使用描述索引器關心的特徵的字串來檢索物件。
索引器通常用於透過簡單的元資料(例如命名空間和名稱)檢索物件。
通知者首先透過列出從客戶端傳回的所有資源來填入索引器。然後,通知者會監視其指派的 Kubernetes 資源。當事件發生時,它使用該事件來更新其索引器並執行其事件處理程序。
通常一個應用程式需要多個控制器。然而,對於每個控制器來說,擁有自己的通知器並因此擁有自己的索引器可能效率不高。 client-go 中的 SharedIndexerInformer 可用來新增全部使用相同索引器的多個控制器。
在 kubernetes/sample-controller 儲存庫中可以很好地了解 Kubernetes 控制器的工作原理。
註:為了簡潔起見,舉報人已被簡化。如果您對它們的工作原理感興趣,建議您仔細閱讀 client-go 程式碼。
Lasso 透過其控制器包標準化了控制器的含義。 Lasso 引入了用於管理專案中的快取、控制器和客戶端的工廠。這對於管理多種類型實例的牧場主來說是必要的。
lasso 控制器使用 client-go 工作佇列。 Lasso 註冊一個處理工作佇列的事件處理程序。以工作佇列的處理程序使得只需為每種 Kubernetes 類型新增一個事件處理程序。現在註冊一個處理程序只需將其新增至該類型的控制器的處理程序清單中。將物件加入佇列會將其新增至工作佇列。然後,工作隊列中的每個物件將由在 goroutine 中運行的工作線程進行處理。控制器的事件處理程序將重新排隊導致一個或多個控制器的處理程序傳回非ErrIgnore
類型的錯誤的任何物件。此工作佇列還可以具有從其他來源排隊的物件。此功能透過控制器的 Enqueue 函數公開。這將控制器從僅對 Kubernetes 資源和快取重新同步做出反應,轉變為可以透過程式碼呼叫。
SharedController 類型嵌入了 Controller 介面以公開其控制器的功能。 SharedController 也公開了 RegisterHandler 函數以及 Client 函數。 RegisterHandler將傳入的handler加入controller的handler清單中,Client傳回sharedController對應資源類型的客戶端; SharedController 有一個 GVK 欄位(Group Version Kind),它指示它的類型。
「共享」方面始於更原始的套索控制器。例如,使用工作佇列允許共用一組事件處理程序。然後,Lasso 共享控制器透過為 GVK 保留可重複使用客戶端並添加一種使用 RegisterHandler 輕鬆將處理程序註冊到下面的控制器的方法來補充。
SharedController 可以建立其底層控制器。只有當處理程序註冊到共用控制器後,它才會執行此操作。
包裝 Kubernetes 客戶端。包含用於管理父結構(例如sharedClientFactory)中的客戶端的GVK欄位。公開一些附加功能,例如為底層 REST 用戶端設定 User-Agent 標頭。
lasso Cache 是來自 client-go 的 SharedIndexInformer 的輕量級包裝。
Lasso Cache 的主要好處是可以為其分配一個 Cache Factory,該工廠透過 GVK 管理記憶體中的 SharedIndexInformer,以便可以重複使用它們。當使用 Lasso Cache 函數時,它將在創建它時傳遞的 CacheFactory 中自我管理。
共享快取工廠儲存快取並允許透過 GVK 結構來管理它們。一旦快取被創建,它們就可以被重複使用。
存在共用客戶端工廠,以便 GVK 的客戶端在創建後可以重複使用。
SharedControllerFactory 將上面的所有內容連結在一起。它允許使用單一入口點來存取客戶端、快取和處理程序 - 所有這些都由它為您管理。主要可以與共享控制器工廠互動。它將創建您需要的所有底層控制器、客戶端和快取。它將確保這些物件不存在重複項。它將防止競爭條件。
一旦您使用 ForObject、ForKind、ForResource 或 ForResourceKind,SharedControllerFactory 將執行下列操作:
deferredController 是一個函數,一旦執行,就會建立並傳回一個控制器。它將使用 SharedCacheFactory 中的快取建立控制器。 deferredController 函數的目的是推遲填充緩存,直到絕對必要為止。這可確保只有已註冊處理程序、已排隊或已要求控制器快取的 Kubernetes 資源才會儲存在記憶體中。
當您從 SharedControllerFactory 取得共用控制器時,它還沒有實例化底層控制器。一旦執行上述操作之一,它就會呼叫 deferredController 方法來建立一個。
以下是註冊處理程序並在 lasso 中運行它們的簡單方法的步驟:
package main
import (
"context"
"github.com/rancher/lasso/pkg/controller"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
)
func main () {
config , err := clientcmd . BuildConfigFromFlags ( "" , os . Getenv ( "KUBECONFIG" ))
if err != nil {
panic ( err )
}
// Setup types you want to work with
scheme := runtime . NewScheme ()
appsv1 . AddToScheme ( scheme )
controllerFactory , err := controller . NewSharedControllerFactoryFromConfig ( config , scheme )
if err != nil {
panic ( err )
}
// ForObject, ForKind, ForResource, and ForResourceKind can all be used to retrieve the controller.
// They all accept different parameters but the first three all eventually call ForResourceKind.
// Refer to [How to use Lasso](#how-to-use-lasso) for more information on how ForResourceKind works.
sharedController , err := controllerFactory . ForObject ( & appsv1. Deployment {})
if err != nil {
panic ( err )
}
// Register a handler on a shared controller. If you need a dedicated queue then use controller.New()
sharedController . RegisterHandler ( context . TODO (), "my-handler" , controller . SharedControllerHandlerFunc ( func ( key string , obj runtime. Object ) (runtime. Object , error ) {
// obj is the latest version of this obj in the cache and MAY BE NIL when an object is finally deleted
dep , ok := obj .( * appsv1. Deployment )
if ! ok {
return obj , nil
}
// Do some stuff ...
// Get stuff from the cache
sharedController . Informer (). GetStore (). Get ( key )
result := & appsv1. Deployment {}
err := sharedController . Client (). Update ( ctx , dep . Namespace , dep , result , metav1. UpdateOptions {})
// return the latest version of the object
return result , err
}))
// the second, int parameter is the number of workers to be used for EACH controller.
err = controllerFactory . Start ( context . TODO (), 5 )
if err != nil {
panic ( err )
}
}
lasso 的一些測試使用 envtest 來運行。 Envtest 允許測試在「假」kubernetes 伺服器上運行,幾乎沒有/沒有開銷。
若要安裝所需的setup-envtest
二進位文件,請使用下列命令:
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
在執行測試之前,您必須執行以下命令來設定假伺服器:
# note that this will use a new/latest version of k8s. Our CI will run against the version of k8s that corresponds to lasso's
# current client-go version, as seen in scripts/test.sh
export KUBEBUILDER_ASSETS= $( setup-envtest use -p path )
以下資源對撰寫這些文件很有幫助。強烈建議您學習比此處介紹的更多內容: