登录
首页 >  Golang >  Go问答

"error": "在方案 \"pkg/runtime/scheme.go:100\"" 中没有为类型 v1.ServiceMonitor 注册任何种类}

来源:stackoverflow

时间:2024-04-09 15:18:32 252浏览 收藏

“纵有疾风来,人生不言弃”,这句话送给正在学习Golang的朋友们,也希望在阅读本文《"error": "在方案 \"pkg/runtime/scheme.go:100\"" 中没有为类型 v1.ServiceMonitor 注册任何种类}》后,能够真的帮助到大家。我也会在后续的文章中,陆续更新Golang相关的技术文章,有好的建议欢迎大家在评论留言,非常感谢!

问题内容

我为我的应用程序创建了一个运算符,并希望为其创建一个服务监视器。 prometheus 运算符已创建。 导入了监控prometheus库,并在我的k8s集群中创建了服务监控crd。 以下是该对象的 go 代码:

package controllers

import (
    "context"
    "fmt"

    appsv1alpha1 "k8s-operator/api/v1alpha1"

    monitoring "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
    "gopkg.in/yaml.v2"
    "k8s.io/apimachinery/pkg/api/errors"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/types"
    "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    "sigs.k8s.io/controller-runtime/pkg/reconcile"
)

// ensuresvcmonitor ensures svcmonitor is running in a namespace.
func (r *myappreconciler) ensuresvcmonitor(request reconcile.request,
    instance *appsv1alpha1.myapp,
    svcmonitor *monitoring.servicemonitor,
) (*reconcile.result, error) {

    // see if svcmonitor already exists and create if it doesn't
    found := &monitoring.servicemonitor{}
    err := r.get(context.todo(), types.namespacedname{
        name:      svcmonitor.name,
        namespace: instance.namespace,
    }, found)
    if err != nil && errors.isnotfound(err) {

        // create the svcmonitor
        err = r.create(context.todo(), svcmonitor)

        if err != nil {
            // svcmonitor creation failed
            return &reconcile.result{}, err
        } else {
            // svcmonitor creation was successful
            return nil, nil
        }
    } else if err != nil {
        // error that isn't due to the svcmonitor not existing
        return &reconcile.result{}, err
    }

    return nil, nil
}

// backendsvcmonitor is a code for creating a svcmonitor
func (r *myappreconciler) backendsvcmonitor(v *appsv1alpha1.myapp) *monitoring.servicemonitor {

    svcmonitor := &monitoring.servicemonitor{
        typemeta: metav1.typemeta{
            kind:       "servicemonitor",
            apiversion: "monitoring.coreos.com/v1",
        },
        objectmeta: metav1.objectmeta{
            name:      v.spec.name + "-svcmonitor",
            namespace: v.namespace},
        spec: monitoring.servicemonitorspec{
            endpoints: []monitoring.endpoint{{
                port: v.spec.name,
            }},
            selector: metav1.labelselector{
                matchlabels: labels(v),
            },
        },
    }

    controllerutil.setcontrollerreference(v, svcmonitor, r.scheme)
    yamldata, _ := yaml.marshal(&svcmonitor)
    fmt.println(string(yamldata))
    return svcmonitor
}

这是我调用这些函数以在控制器中创建此对象的部分:

if instance.spec.servicemonitorenable {
        result, err = r.ensuresvcmonitor(req, instance, r.backendsvcmonitor(instance))
        if result != nil {
            log.error(err, "servicemonitor not ready")
            return *result, err
        }
    }

但是当我创建自定义资源实例时,我收到此错误:

"error": "no kind is registered for the type v1.ServiceMonitor in scheme \"pkg/runtime/scheme.go:100\""}

正确答案


在您的main.go中,您需要将monitoring/v1添加到注入controller-runtimescheme,即:

// main.go
package main

import (
    "os"
    ctrl "sigs.k8s.io/controller-runtime"
    monitoring "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
    "k8s.io/apimachinery/pkg/runtime"
)

var (
    scheme = runtime.newscheme()
)

func init() {
    monitoring.addtoscheme(scheme)
}

func main() {
    mgr, err := ctrl.newmanager(ctrl.getconfigordie(), ctrl.options{
        scheme: scheme,
        // ... other options here
    })

    // start manager
    if err := mgr.start(ctrl.setupsignalhandler()); err != nil {
        os.exit(1)
    }
}

看起来 crd servicemonitor 是 monitoring.coreos.com 的一部分,而不是monitoring.coreos.com/v1,所以在代码中更改它(apiversion)应该足够了:

package controllers

import (
    "context"
    "fmt"

    appsv1alpha1 "k8s-operator/api/v1alpha1"

    monitoring "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
    "gopkg.in/yaml.v2"
    "k8s.io/apimachinery/pkg/api/errors"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/types"
    "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    "sigs.k8s.io/controller-runtime/pkg/reconcile"
)

// ensureSvcMonitor ensures SvcMonitor is Running in a namespace.
func (r *MyappReconciler) ensureSvcMonitor(request reconcile.Request,
    instance *appsv1alpha1.Myapp,
    svcmonitor *monitoring.ServiceMonitor,
) (*reconcile.Result, error) {

    // See if SvcMonitor already exists and create if it doesn't
    found := &monitoring.ServiceMonitor{}
    err := r.Get(context.TODO(), types.NamespacedName{
        Name:      svcmonitor.Name,
        Namespace: instance.Namespace,
    }, found)
    if err != nil && errors.IsNotFound(err) {

        // Create the SvcMonitor
        err = r.Create(context.TODO(), svcmonitor)

        if err != nil {
            // SvcMonitor creation failed
            return &reconcile.Result{}, err
        } else {
            // SvcMonitor creation was successful
            return nil, nil
        }
    } else if err != nil {
        // Error that isn't due to the SvcMonitor not existing
        return &reconcile.Result{}, err
    }

    return nil, nil
}

// backendSvcMonitor is a code for creating a SvcMonitor
func (r *MyappReconciler) backendSvcMonitor(v *appsv1alpha1.Myapp) *monitoring.ServiceMonitor {

    svcmonitor := &monitoring.ServiceMonitor{
        TypeMeta: metav1.TypeMeta{
            Kind:       "ServiceMonitor",
            APIVersion: "monitoring.coreos.com",
        },
        ObjectMeta: metav1.ObjectMeta{
            Name:      v.Spec.Name + "-svcmonitor",
            Namespace: v.Namespace},
        Spec: monitoring.ServiceMonitorSpec{
            Endpoints: []monitoring.Endpoint{{
                Port: v.Spec.Name,
            }},
            Selector: metav1.LabelSelector{
                MatchLabels: labels(v),
            },
        },
    }

    controllerutil.SetControllerReference(v, svcmonitor, r.Scheme)
    yamlData, _ := yaml.Marshal(&svcmonitor)
    fmt.Println(string(yamlData))
    return svcmonitor
}

到这里,我们也就讲完了《"error": "在方案 \"pkg/runtime/scheme.go:100\"" 中没有为类型 v1.ServiceMonitor 注册任何种类}》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>