Lasso はコントローラー フレームワークです。
Lasso にはコントローラー ランタイム プロジェクトと機能的に同等の機能があり、コントローラー ランタイムの代わりに使用できます。
なげなわは低レベルです。独自のコントローラーを管理したい場合は、それを使用できます。独自のリソース タイプを作成するためのさらなる利便性と機能をお探しの場合は、Wrangler をチェックすることをお勧めします。
Wrangler と Norman によって使用されるコア コントローラー フレームワーク。
このドキュメントは、Kubernetes コントローラーの初心者と、Kubernetes コントローラーの初心者ではないが投げ縄の初心者という 2 人の読者を念頭に置いて書かれています。
「Kubernetes コントローラーを初めて使用する人」のカテゴリーに該当する場合は、Lasso の価値提案までスキップしてください。
Kubernetes コントローラーを初めて使用する場合は、どのセクションもスキップしないことをお勧めします。
Kubernetes の基本的な知識が不足している場合は、まず Kubernetes の概要などの基本に関する他のドキュメントを参照することをお勧めします。
注:これは非常に短い短期集中コースになります。このトピックに関する他のリソースもたくさんあるので、ぜひ調べてみることをお勧めします。 2 つの推奨リソースは、サンプル コントローラー プロジェクトと Kubernetes コントローラー フレームワークの紹介です。
Kubernetes ドキュメントより
Kubernetes では、コントローラーは、API サーバーを通じてクラスターの共有状態を監視し、現在の状態を望ましい状態に向けて変更しようとする制御ループです。
「コントローラー」という言葉は、上記の定義よりも大雑把に使用されています。私たち自身の言葉で言えば、コントローラーは Kubernetes リソース イベントに応答して動作するループ ハンドラーです。 Lasso では、このループ ハンドラーを登録し、必要なリソースを提供する役割を担う構造全体を指すために「コントローラー」という単語も使用します。つまり、コントローラーは、Kubernetes タイプと対話し、操作するために必要なものすべてをバンドルした構造です。
上記の目標を達成するには、いくつかの下位目標を達成する必要があります。
上記の目標を達成するために役立つフレームワークは数多くあります。ラッソーもその1つです。 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 は、プロジェクト内のキャッシュ、コントローラー、クライアントを管理するためのファクトリーを導入します。これは、さまざまなタイプの多数のインスタンスを管理する牧場主にとって不可欠です。
ラッソ コントローラーは client-go ワーク キューを使用します。 Lasso は、ワーク キューを処理するイベント ハンドラーを登録します。ワークキュー指向のハンドラーにより、Kubernetes タイプごとに追加する必要があるイベント ハンドラーは 1 つだけになります。ハンドラーを登録すると、それが型のコントローラーのハンドラーのリストに追加されるだけになります。オブジェクトをキューに入れると、オブジェクトが作業キューに追加されます。ワークキュー内の各オブジェクトは、ゴルーチンで実行されるワーカーによって処理されます。コントローラーのイベント ハンドラーは、1 つ以上のコントローラーのハンドラーがErrIgnore
タイプではないエラーを返す原因となったオブジェクトを再エンキューします。この作業キューには、他のソースからオブジェクトをキューに入れることもできます。この機能は、コントローラーの Enqueue 関数を通じて公開されます。これにより、コントローラーは Kubernetes リソースとキャッシュの再同期に対してのみ反応するものから、コードからも呼び出せるようになります。
sharedController タイプは、コントローラー インターフェイスを埋め込んでコントローラーの機能を公開します。また、sharedController は、Client 関数とともに RegisterHandler 関数も公開します。 RegisterHandler は、渡されたハンドラーをコントローラーのハンドラー リストに追加し、Client は、sharedController に対応するリソース タイプのクライアントを返します。 sharedController には、どのタイプに対応するかを示す GVK フィールド (Group Version Kind) があります。
「共有」の側面は、より原始的ななげなわコントローラーから始まります。ワーク キューを使用すると、たとえば 1 セットのイベント ハンドラーを共有できます。次に、Lasso 共有コントローラーは、GVK の再利用可能なクライアントを保持し、RegisterHandler を使用してその下のコントローラーにハンドラーを簡単に登録する方法を追加することで、これに追加します。
sharedController は、その基礎となるコントローラーを作成できます。これは、ハンドラーがsharedControllerに登録された場合にのみ行われます。
Kubernetes クライアントをラップします。 sharedClientFactory などの親構造体でクライアントを管理するための GVK フィールドが含まれます。基盤となる REST クライアントの User-Agent ヘッダーの構成など、いくつかの追加機能を公開します。
lasso Cache は、client-go の SharedIndexInformer の軽量ラッパーです。
Lasso キャッシュの主な利点は、GVK によってメモリ内の SharedIndexInformer を管理するキャッシュ ファクトリを割り当てて再利用できることです。 Lasso Cache 関数を使用する場合、Lasso Cache 関数は、作成するために渡された CacheFactory 内で自身を管理します。
共有キャッシュ ファクトリはキャッシュを保存し、GVK 構造体を介してキャッシュを管理できるようにします。キャッシュが作成されると、再利用できます。
共有クライアント ファクトリは、GVK のクライアントを作成後に再利用できるようにするために存在します。
SharedControllerFactory は、上記のすべてを結び付けます。これにより、単一のエントリ ポイントでクライアント、キャッシュ、ハンドラーにアクセスできるようになり、これらすべてが管理されます。主に共有コントローラーファクトリーと対話することが可能です。これにより、必要なすべての基盤となるコントローラー、クライアント、キャッシュが作成されます。これらのオブジェクトが重複していないことが保証されます。競合状態を防ぐことができます。
ForObject、ForKind、ForResource、または ForResourceKind を使用すると、SharedControllerFactory は次のことを実行します。
deferredController は、実行されるとコントローラーを作成して返す関数です。 SharedCacheFactory のキャッシュを使用してコントローラーを作成します。 deferredController 関数の目的は、絶対に必要になるまでキャッシュの設定を保留することです。これにより、ハンドラーが登録されている、キューに入れられている、またはコントローラーのキャッシュが要求されている Kubernetes リソースのみがメモリに保存されるようになります。
SharedControllerFactory からsharedControllerを取得したとき、基礎となるコントローラーはまだインスタンス化されていません。前述の操作のいずれかが実行されると、代わりに deferredController メソッドが呼び出され、メソッドが作成されます。
以下は、ハンドラーを登録してなげなわで実行する簡単な方法の手順です。
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 )
これらのドキュメントを作成する際には、次のリソースが役に立ちました。ここで紹介されている内容以上のことを学ぶには、これらを強くお勧めします。