【问题标题】:List custom resources from caching client with custom fieldSelector使用自定义 fieldSelector 列出来自缓存客户端的自定义资源
【发布时间】:2019-07-17 19:52:56
【问题描述】:

我正在使用Operator SDK 构建自定义 Kubernetes 操作符。我使用相应的 Operator SDK 命令创建了自定义资源定义和控制器:

operator-sdk add api --api-version example.com/v1alpha1 --kind=Example
operator-sdk add controller --api-version example.com/v1alpha1 --kind=Example

在主协调循环中(对于上面的示例,自动生成的 ReconcileExample.Reconcile 方法)我有一些自定义业务逻辑,需要我查询 Kubernetes API 以查找具有特定字段值的其他同类对象.我突然想到,我也许可以将默认 API 客户端(由控制器提供)与自定义字段选择器一起使用:

func (r *ReconcileExample) Reconcile(request reconcile.Request) (reconcile.Result, error) {
    ctx := context.TODO()
    listOptions := client.ListOptions{
        FieldSelector: fields.SelectorFromSet(fields.Set{"spec.someField": "someValue"}),
        Namespace:     request.Namespace,
    }
    otherExamples := v1alpha1.ExampleList{}

    if err := r.client.List(ctx, &listOptions, &otherExamples); err != nil {
        return reconcile.Result{}, err
    }

    // do stuff...

    return reconcile.Result{}, nil
}

当我运行运算符并创建新的Example 资源时,运算符失败并显示以下错误消息:

{"level":"info","ts":1563388786.825384,"logger":"controller_example","msg":"Reconciling Example","Request.Namespace":"default","Request.Name":"example-test"}
{"level":"error","ts":1563388786.8255732,"logger":"kubebuilder.controller","msg":"Reconciler error","controller":"example-controller","request":"default/example-test","error":"Index with name field:spec.someField does not exist","stacktrace":"..."}

最重要的部分是

名称为字段的索引:spec.someField 不存在

我已经在默认 API 客户端上搜索了the Operator SDK's documentation 并了解了一些有关客户端的内部工作原理,但没有对此错误或如何修复它的详细说明。

此错误消息是什么意思,如何创建此缺失索引以按此字段值有效列出对象?

【问题讨论】:

    标签: go kubernetes operator-sdk


    【解决方案1】:

    控制器提供的默认 API 客户端是 拆分客户端 -- 它服务于来自本地缓存的 GetList 请求,并转发其他方法,例如 CreateUpdate 直接发送到 Kubernetes API 服务器。这在the respective documentation中也有解释:

    SDK 将生成代码来创建一个管理器,其中包含一个缓存和一个客户端,用于 CRUD 操作并与 API 服务器通信。默认情况下,Controller 的 Reconciler 将填充 Manager 的客户端,它是一个拆分客户端。 [...] 拆分客户端从缓存中读取(获取和列出)并将(创建、更新、删除)写入 API 服务器。从缓存中读取显着减少了 API 服务器上的请求负载;只要 Cache 被 API server 更新,读操作最终是一致的。

    要使用自定义字段选择器从缓存中查询值,缓存需要有一个针对该字段的搜索索引。可以在设置缓存后立即定义此索引器。

    要注册自定义索引器,请将以下代码添加到运算符的引导逻辑中(在自动生成的代码中,这是直接在 main 中完成的)。这需要控制器管理器被实例化 (manager.New) 并且也在自定义 API 类型被添加到 runtime.Scheme 之后完成:

    package main
    
    import (
        k8sruntime "k8s.io/apimachinery/pkg/runtime"
        "example.com/example-operator/pkg/apis/example/v1alpha1"
        // ...
    )
    
    function main() {
        // ...
    
        cache := mgr.GetCache()
    
        indexFunc := func(obj k8sruntime.Object) []string {
            return []string{obj.(*v1alpha1.Example).Spec.SomeField}
        }
    
        if err := cache.IndexField(&v1alpha1.Example{}, "spec.someField", indexFunc); err != nil {
            panic(err)
        }
    
        // ...
    }
    

    定义相应的索引器函数后,spec.someField 上的字段选择器将按预期从本地缓存中工作。

    【讨论】:

    猜你喜欢
    • 2021-09-12
    • 2022-09-27
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    相关资源
    最近更新 更多