使用自定义 fieldSelector 列出来自缓存客户端的自定义资源
List custom resources from caching client with custom fieldSelector
我正在使用 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":"..."}
最重要的部分是
Index with name field:spec.someField does not exist
我已经在默认 API 客户端上搜索了 the Operator SDK's documentation 并了解了客户端的内部工作原理,但没有详细解释此错误或如何修复它。
此错误消息是什么意思,我如何创建此缺失索引以有效地按此字段值列出对象?
控制器提供的默认 API 客户端是一个 拆分客户端 -- 它服务来自 Get
和 List
的请求locally-held 缓存并将其他方法(如 Create
和 Update
直接转发到 Kubernetes API 服务器。这也在 the respective documentation:
中解释
The SDK will generate code to create a Manager, which holds a Cache and a Client to be used in CRUD operations and communicate with the API server. By default a Controller's Reconciler will be populated with the Manager's Client which is a split-client. [...] A split client reads (Get and List) from the Cache and writes (Create, Update, Delete) to the API server. Reading from the Cache significantly reduces request load on the API server; as long as the Cache is updated by the API server, read operations are eventually consistent.
要使用自定义字段选择器从缓存中查询值,缓存需要有该字段的搜索索引。该索引器可以在设置缓存后立即定义。
要注册自定义索引器,请将以下代码添加到运算符的引导逻辑中(在 auto-generated 代码中,这是直接在 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
上的字段选择器将按预期从本地缓存中工作。
我正在使用 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":"..."}
最重要的部分是
Index with name field:spec.someField does not exist
我已经在默认 API 客户端上搜索了 the Operator SDK's documentation 并了解了客户端的内部工作原理,但没有详细解释此错误或如何修复它。
此错误消息是什么意思,我如何创建此缺失索引以有效地按此字段值列出对象?
控制器提供的默认 API 客户端是一个 拆分客户端 -- 它服务来自 Get
和 List
的请求locally-held 缓存并将其他方法(如 Create
和 Update
直接转发到 Kubernetes API 服务器。这也在 the respective documentation:
The SDK will generate code to create a Manager, which holds a Cache and a Client to be used in CRUD operations and communicate with the API server. By default a Controller's Reconciler will be populated with the Manager's Client which is a split-client. [...] A split client reads (Get and List) from the Cache and writes (Create, Update, Delete) to the API server. Reading from the Cache significantly reduces request load on the API server; as long as the Cache is updated by the API server, read operations are eventually consistent.
要使用自定义字段选择器从缓存中查询值,缓存需要有该字段的搜索索引。该索引器可以在设置缓存后立即定义。
要注册自定义索引器,请将以下代码添加到运算符的引导逻辑中(在 auto-generated 代码中,这是直接在 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
上的字段选择器将按预期从本地缓存中工作。