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

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

概述

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

// VerticalScalerSpec defines the desired state of VerticalScaler.
type VerticalScalerSpec struct {
    // Name of the Deployment object which will be auto-scaled.
    DeploymentName string `json:"deploymentName"`
}

问题

当该资源不为控制器所有,并且该资源不持有对其资源由控制器管理的对象的引用时,是否有一种观察任意资源的好方法?

我发现了什么

我认为这应该在控制器的 Kubebuilder 标准 SetupWithManager 函数中进行配置,尽管可以在其他地方设置手表。

// SetupWithManager sets up the controller with the Manager.
func (r *VerticalScalerReconciler) SetupWithManager(mgr ctrl.Manager) error {
    return ctrl.NewControllerManagedBy(mgr).
        For(&v1beta1.VerticalScaler{}).
        Complete(r)
}

我一直在 controller-runtime/pkg/builder 和 Kubebuilder 文档中寻找好的方法。我找到的最接近的例子是 kubebuilder-v1 docs on watches 中的“观看任意资源”部分:

控制器可以监视任意资源并将它们映射到控制器管理的资源的键。控制器甚至可以将一个事件映射到多个键,为每个键触发 Reconciles。

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

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

我使用这种不完美的方法使这段代码工作:

const deploymentNameIndexField = ".metadata.deploymentName"

// SetupWithManager sets up the controller with the Manager.
func (r *VerticalScalerReconciler) SetupWithManager(mgr ctrl.Manager) error {
    if err := r.createIndices(mgr); err != nil {
        return err
    }

    return ctrl.NewControllerManagedBy(mgr).
        For(&v1beta1.VerticalScaler{}).
        Watches(
            &source.Kind{Type: &appsv1.Deployment{}},handler.EnqueueRequestsFromMapFunc(r.mapDeploymentToRequests)).
        Complete(r)
}

func (r *VerticalScalerReconciler) createIndices(mgr ctrl.Manager) error {
    return mgr.GetFieldIndexer().IndexField(
        context.Background(),&v1beta1.VerticalScaler{},deploymentNameIndexField,func(object client.Object) []string {
            vs := object.(*v1beta1.VerticalScaler)

            if vs.Spec.DeploymentName == "" {
                return nil
            }

            return []string{vs.Spec.DeploymentName}
        })
}

func (r *VerticalScalerReconciler) mapDeploymentToRequests(object client.Object) []reconcile.Request {
    deployment := object.(*appsv1.Deployment)

    ctx,cancel := context.WithTimeout(context.Background(),time.Minute)
    defer cancel()

    var vsList v1beta1.VerticalScalerList

    if err := r.List(ctx,&vsList,client.InNamespace(deployment.Namespace),client.MatchingFields{deploymentNameIndexField: deployment.Name},); err != nil {
        r.Log.Error(err,"could not list VerticalScalers. " +
            "change to Deployment %s.%s will not be reconciled.",deployment.Name,deployment.Namespace)
        return nil
    }

    requests := make([]reconcile.Request,len(vsList.Items))

    for i,vs := range vsList.Items {
        requests[i] = reconcile.Request{
            NamespacedName: client.ObjectKeyFromObject(&vs),}
    }

    return requests
}

其他考虑过的方法

只是为了涵盖我的基础,我应该提到我不想将 VerticalScaler 设置为 Deployment 的所有者,因为如果 VerticalScaler 被删除,我不想对 Deployment 进行垃圾收集。即使是非控制器 ownerReference 也会导致垃圾回收。

我也考虑过使用 Channel 观察器,但文档说这是针对源自集群外部的事件,而事实并非如此。

我也可以为 Deployment 创建一个单独的控制器,并从该控制器的 Reconcile 函数更新依赖 VerticalScaler(s) 的一些字段,但是我还需要一个终结器来处理在 Deployment 被删除时触发 VerticalScaler 协调,这似乎有点矫枉过正。

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

解决方法

您确实使用了地图功能和普通手表。 https://github.com/coderanger/migrations-operator/blob/088a3b832f0acab4bfe02c03a4404628c5ddfd97/components/migrations.go#L64-L91 显示了一个示例。您最终确实经常不得不在 map 函数中执行 I/O 以计算出这件事对应于哪个根对象,但我同意这有点糟糕,如果这些调用,除了 log 或 panic 之外别无他法失败。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res