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 )
以下资源对编写这些文档很有帮助。强烈建议您学习比此处介绍的更多内容: