kubernetes+ prometheus自动伸缩的设计与实现(三)

现在还剩下最后一东西没有解决了,就是一个查询的接口,提供一个prometheus转接的地方。第一篇blog已经介绍了通过自定义指标采集器调用custom-metrics接口。现在看看这个接口的实现,首先得有这样一个接口
这个是基于k8s的一个孵化项目:
github.com/kubernetes-incubator/custom-metrics-apiserver
他就是提供一个自定义服务接口,我们只要自己去实现就可以了,当然如果其他的监控也可以自己去实现他的接口。先看看这个项目如果启动服务的注册接口的github.com/kubernetes-incubator/custom-metrics-apiserver/pkg/apiserver/apiserver.go,

func (c completedConfig) New(cmProvider provider.CustomMetricsProvider) (*CustomMetricsAdapterServer, error) {
    genericServer, err := c.Config.GenericConfig.SkipComplete().New(genericapiserver.EmptyDelegate) // completion is done in Complete, no need for a second time
    if err != nil {
        return nil, err
    }

    s := &CustomMetricsAdapterServer{
        GenericAPIServer: genericServer,
        Provider:         cmProvider,
    }

    if err := s.InstallCustomMetricsAPI(); err != nil {
        return nil, err
    }

    return s, nil
}

通过InstallCustomMetricsAPI去注册github.com/kubernetes-incubator/custom-metrics-apiserver/pkg/apiserver/cmapis.go,

    groupMeta := registry.GroupOrDie(custom_metrics.GroupName)

    ...

    cmAPI := s.cmAPI(groupMeta, &groupMeta.GroupVersion)

    if err := cmAPI.InstallREST(s.GenericAPIServer.Handler.GoRestfulContainer); err != nil {
        return err
    }

如果熟悉k8s api注册的人,对此肯定很熟悉,这个和k8s api注册一样。上面的custom_metrics.GroupName就是custom-metrics.metrics.k8s.io,ok关于api如果去注册,不在我的重点,在此先略过。
重点是我们去实现的数据转化的接口
github.com/kubernetes-incubator/custom-metrics-apiserver/pkg/provider/interfaces.go

type CustomMetricsProvider interface {
    // root级别指定的一个指标
    GetRootScopedMetricByName(groupResource schema.GroupResource, name string, metricName string) (*custom_metrics.MetricValue, error)

    // root级别通过label筛选的指标
    GetRootScopedMetricBySelector(groupResource schema.GroupResource, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error)

    // 特定namespace下的某个指标
    GetNamespacedMetricByName(groupResource schema.GroupResource, namespace string, name string, metricName string) (*custom_metrics.MetricValue, error)

    // 特定namespace下通过label筛选的指标
    GetNamespacedMetricBySelector(groupResource schema.GroupResource, namespace string, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error)

    // 查询所有的指标
    ListAllMetrics() []MetricInfo
}

我们要写的prometheus的provider当然也要实现这些指标查询的接口。
下面看具体代码,拿一个namespace下通过指标名称和label的接口举例,

func (p *prometheusProvider) GetNamespacedMetricBySelector(groupResource schema.GroupResource, namespace string, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error) {
    info := provider.MetricInfo{
        GroupResource: groupResource,
        Metric:        metricName,
        Namespaced:    true,
    }
    return p.getMultiple(info, namespace, selector)
}

这个就是具体接口的实现,getMultiple具体实现如下pkg/custom-provider/provider.go

//查询数据
queryResults, err := p.buildQuery(info, namespace, resourceNames...)
//封装数据
p.metricsFor(queryResults, info, matchingObjectsRaw)

具体的查询无非是调用prometheus的查询api

queryResults, err := p.promClient.Query(context.Background(), pmodel.Now(), fullQuery)

封装数据代码如下

err := apimeta.EachListItem(list, func(item runtime.Object) error {
        objUnstructured := item.(*unstructured.Unstructured)
        objName := objUnstructured.GetName()
        if _, found := values[objName]; !found {
            return nil
        }
        value, err := p.metricFor(values[objName], info.GroupResource, objUnstructured.GetNamespace(), objName, info.Metric)
        if err != nil {
            return err
        }
        res = append(res, *value)

        return nil
    })
    if err != nil {
        return nil, err
    }

    return &custom_metrics.MetricValueList{
        Items: res,
    }, nil

就是拼装成k8s.io/metrics/pkg/apis/custom_metrics/types.go下面定义的MetricValueList

type MetricValueList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items []MetricValue `json:"items"`
}

type MetricValue struct {
    metav1.TypeMeta `json:",inline"`
    DescribedObject api.ObjectReference `json:"describedObject"`
    // 指标名称
    MetricName string `json:"metricName"`
    // 采集时间
    Timestamp metav1.Time `json:"timestamp"`
    // 采集时间窗口
    WindowSeconds *int64 `json:"window,omitempty"`
    // 指标值
    Value resource.Quantity `json:"value"`
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柳清风09

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值