如何为任意对象触发Kubernetes控制器协调器? 概述

如何为任意对象触发Kubernetes控制器协调器? 概述,kubernetes,kubernetes-operator,kubebuilder,Kubernetes,Kubernetes Operator,Kubebuilder,我正在为VerticalScaler CRD编写一个Kubernetes控制器,它可以垂直扩展集群中的部署。我的规范引用群集中的现有部署对象。如果引用的部署被修改或删除,我想将VerticalScaler的协调请求排队 //VerticalScalerSpec定义VerticalScaler的所需状态。 类型VerticalScalerSpec结构{ //将自动缩放的部署对象的名称。 DeploymentName字符串`json:“DeploymentName”` } 问题: 当任意资源不属于

我正在为VerticalScaler CRD编写一个Kubernetes控制器,它可以垂直扩展集群中的部署。我的规范引用群集中的现有部署对象。如果引用的部署被修改或删除,我想将VerticalScaler的协调请求排队

//VerticalScalerSpec定义VerticalScaler的所需状态。
类型VerticalScalerSpec结构{
//将自动缩放的部署对象的名称。
DeploymentName字符串`json:“DeploymentName”`
}
问题: 当任意资源不属于控制器,并且该资源不包含对其资源由控制器管理的对象的引用时,是否有一种监视该资源的好方法

我发现了什么 我认为这应该在控制器的Kubebuilder标准函数中进行配置,不过也可以在其他地方设置手表

//SetupWithManager使用管理器设置控制器。
func(r*VerticalScalerReconciler)SetupWithManager(管理控制管理器)错误{
返回ctrl.NewControllerManagedBy(mgr)。
对于(&v1beta1.VerticalScaler{})。
完成(r)
}
我一直在和Kubebuilder文档中寻找一种好方法。我发现的最接近的例子是“监视任意资源”一节:

控制器可以监视任意资源并将其映射到控制器管理的资源的密钥。控制器甚至可以将事件映射到多个键,从而触发每个键的协调

示例:为了响应集群缩放事件(例如,删除或添加节点),控制器将监视节点并将监视事件映射到控制器管理的对象的键

我的挑战是如何将部署映射到依赖的VerticalScaler,因为部署中不存在此信息。我可以在VerticalScaler上使用字段选择器从查找VerticalScaler,但似乎不应该在MapFunc中执行I/O。如果列表部署操作失败,我将无法重试或重新排队更改

我使用这种不完美的方法来编写代码:

const deploymentNameIndexField=“.metadata.deploymentName”
//SetupWithManager使用管理器设置控制器。
func(r*VerticalScalerReconciler)SetupWithManager(管理控制管理器)错误{
如果错误:=r.createIndexes(mgr);错误!=nil{
返回错误
}
返回ctrl.NewControllerManagedBy(mgr)。
对于(&v1beta1.VerticalScaler{})。
监视(
&source.Kind{Type:&appsv1.Deployment{},
handler.EnqueueRequestsFromMapFunc(r.mapDeploymentToRequests))。
完成(r)
}
func(r*VerticalScalerReconciler)创建索引(管理器控制管理器)错误{
返回mgr.GetFieldIndexer().IndexField(
context.Background(),
&v1beta1.VerticalScaler{},
deploymentNameIndexField,
func(object client.object)[]字符串{
vs:=对象。(*v1beta1.VerticalScaler)
如果vs.Spec.DeploymentName==“”{
归零
}
返回[]字符串{vs.Spec.DeploymentName}
})
}
func(r*VerticalScalerReconciler)mapDeploymentToRequests(对象client.object)[]协调.Request{
部署:=对象。(*appsv1.deployment)
ctx,cancel:=context.WithTimeout(context.Background(),time.Minute)
推迟取消
变量vsList v1beta1.VerticalScalerList
如果err:=r.List(ctx和vsList,
client.InNamespace(deployment.Namespace),
client.MatchingFields{deploymentNameIndexField:deployment.Name},
);呃!=零{
r、 Log.Error(错误,“无法列出垂直缩放器。”+
“将不协调对部署%s.%s的更改。”,
deployment.Name,deployment.Namespace)
归零
}
请求:=make([]协调.Request,len(vsList.Items))
对于i,vs:=范围vsList.Items{
请求[i]=协调。请求{
NamespacedName:client.ObjectKeyFromObject(&vs),
}
}
返回请求
}
其他经过考虑的办法 为了说明我的基本情况,我应该提到我不想将VerticalScaler设置为部署的所有者,因为如果删除了VerticalScaler,我不想对部署进行垃圾收集。即使是非控制器ownerReference也会导致垃圾收集

我也考虑过使用一个监视程序,但文档中说这是针对源自集群外部的事件,而事实并非如此

我还可以为部署创建一个单独的控制器,并从该控制器的协调功能中更新依赖VerticalScaler上的某些字段,但是我还需要一个终结器来处理在删除部署时触发VerticalScaler协调的问题,这似乎有些过分


我可以让我的VerticalScaler协调器向部署添加注释,但如果由例如Helm管理,部署注释可能会被覆盖。在部署之前创建VerticalScaler的情况下,这也不会导致协调请求。

您确实使用了映射函数和普通监视。显示了一个示例。你经常需要在map函数中做I/O来计算出这个东西对应的根对象,但是我同意,如果这些调用失败,除了日志或恐慌之外,没有其他方法可以做,这有点糟糕


您还可以使用非控制器所有者引用或注释作为存储给定部署的映射目标的一种方式,这使得映射功能更简单,但通常响应性也更低。总的来说,这取决于需要多大的动态性。请随时打开#kubebuilder Slack频道寻求帮助。

谢谢您的回答。我可以尝试使用map函数。但是,因为它没有任何重试或重新登录