【Kubernetes社区】监控指标稳定性框架介绍

引言

使用Kubernetes 1.15版本,经过API(/metrics)查询Kubernetes监控指标时,在某些指标的 HELP 信息中,能够看到诸如 “[ALPHA]” 、“[STABLE]” 、“(Deprecated)”等字样,用来标明监控指标的稳定性,以便于用户跟据自身需求来放心的使用这些指标来监控集群。golang

一个典型的指标以下所示:编程

# HELP rest_client_request_latency_seconds [ALPHA] (Deprecated) Request latency in seconds. Broken down by verb and URL.
# TYPE rest_client_request_latency_seconds histogram
rest_client_request_latency_seconds_bucket{url="https://[::1]:6443/%7Bprefix%7D",verb="GET",le="0.001"} 36
rest_client_request_latency_seconds_bucket{url="https://[::1]:6443/%7Bprefix%7D",verb="GET",le="0.002"} 148
rest_client_request_latency_seconds_bucket{url="https://[::1]:6443/%7Bprefix%7D",verb="GET",le="0.004"} 166
rest_client_request_latency_seconds_bucket{url="https://[::1]:6443/%7Bprefix%7D",verb="GET",le="0.008"} 172

与其余API的标识同样,ALPHA意味着该监控指标还处理于实验阶段,可能随时会改变,并且不保证会通知用户,用户须要谨慎使用。Deprecated意味着该监控指标已被弃用,在未来的版本中会被删除,用户须要尽快中止使用或使用替代的监控指标。api

本文编写时间为1.16版本发布前夕,既有的监控指标还未所有迁移到该框架中,因此只有部分监控指标会有稳定性标识。app

本文但愿从监控指标稳定性框架的开发背景讲起,接着介绍该框架的实现原理,以帮助开发者更详细的了解和使用这个特性。框架

背景

不少集群监控系统都使用Kubernetes提供的监控指标来监控集群运行情况,然而Kubernetes提供的指标没有任何稳定性的保证,也就是说Kubernetes随时有可能修改这些指标,用户升级新的Kubernetes版本后,有可能原有的监控指标已被修改或直接删除,这给用户带来了困扰,这种用户的困扰引发了社区关注。学习

为了解决这个问题,社区进行了普遍的讨论,总结下来有这两种主流的思路:测试

  • 使用版本标记:为监控指标划分版本标识,好比 /metrics/v1beta1/metrics/v1等;
  • 使用文档标记:提供文档标记那些稳定的监控指标;

这两种思路都有相应的优缺点:this

  • 使用版本标记的办法更相似于Kubernetes API的作法,这种作法优势是能够同时支持多个版本,缺点是实现起来很是笨重;
  • 使用文档标记优势是实现简单,把稳定的监控指标记录到文档中便可,缺点是后续迭代时仍然会不可避免的破坏这个规则,从工程角度讲,很是难以管理。

最后,结合这两个思路的优缺点,社区使用了一个更具创新性的方案,也就是本文要介绍的稳定性框架,该框架在实现层面相对使用版本标记更简单,在工程层面比使用文档标记更易于管理。url

愿景

与每一个公司成立时都须要一个愿景或口号同样,监控指标稳定性框架也有本身的愿景:设计

  • 提供一种描述监控指标稳定性的机制;
  • 提供多种监控稳定性描述;

两个愿景,一个是帮助Kubernetes开发人员定义本身的监控指标,一个是如何向用户呈现稳定性保证。

同时,如下内容不在框架的考虑范围:

  • 不定义某个具体的监控指标稳定级别;
  • 不负责检查具体的监控指标是否符合规范;

事实上,本框架不考虑的这些内容也很重要,会在社区其余事项中去作,只是本框架不负责这些内容。

实现原理

旧的实现

咱们或许都据说过Prometheus已成为Kubernetes监控的事实标准,这体如今Kubernetes的不少组件(kube-scheduler、kubelet、kube-controller-manager和kube-apiserver等)都使用Prometheus客户端来生成Prometheus格式的监控指标。

使用Prometheus,对于每一个监控指标通常会先初始化一个实例,再添加到全局的注册表中,最后当用户使用API访问时,http handler 负责把这些监控指标导出。

初始化实例:

var authenticatedUserCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "authenticated_user_requests",
			Help: "Counter of authenticated requests broken out by username.",
		},
		[]string{"username"},
	)

添加到注册表:

prometheus.MustRegister(authenticatedUserCounter)

http handler 使用的也是 Prometheus提供的handler:

// Install adds the DefaultMetrics handler
func (m DefaultMetrics) Install(c *mux.PathRecorderMux) {
	register()
	c.Handle("/metrics", prometheus.Handler())
}

由上能够看到,原有的监控标标严重依赖Prometheus的特性,而新的框架设计将会对监控指标的定义、初始化、注册过程进行封装,即各组件再也不直接使用Prometheus,而是使用新的框架,尽管新的框架仍是使用Prometheus来实现,但提供了更多个性化的设计。

新的实现:监控指示定义

在监控指标定义环节,新框架提供了新的指标参数结构体,以便于增长稳定性标识。

好比,曾经使用Prometheus定义一个计数器时会使用prometheus.CounterOpts结构体,以下所示:

var someMetricDefinition = prometheus.CounterOpts{
    Name: "some_metric",
    Help: "some description",
}

新框架则提供了一个通过扩展的参数结构体kubemetrics.CounterOpts,新增长了StabilityLevelDeprecatedVersion等字段用于表示稳定性和弃用标示。

表示一个监控指标被废弃,能够以下定义:

var deprecatedMetricDefinition = kubemetrics.CounterOpts{
    Name: "some_deprecated_metric",
    Help: "some description",
    StabilityLevel: kubemetrics.STABLE, // 自定义字段,稳定性标识
    DeprecatedVersion: "1.15", // 自定义字段,弃用标识
}

表示一个ALPHA监控指标,能够以下定义:

var alphaMetricDefinition = kubemetrics.CounterOpts{
    Name: "some_alpha_metric",
    Help: "some description",
    StabilityLevel: kubemetrics.ALPHA,
    DeprecatedVersion: "1.15", // 可选字段,标明将在哪一个版本弃用
}

与Prometheus一致,新框架对4种监控指标分别作了扩展:

  • CounterOpts
  • GaugeOpts
  • HistogramOpts
  • SummaryOpts

本节暂不对每种监控指标展开介绍,仍是聚焦在阐述新框架的实现思路上。

新的实现:监控指标初始化

曾经,使用Prometheus来初始化监控指标(获取监控指标实例),将使用一系列的prometheus.NewXXX()方法,以下所示:

var someCounterVecMetric = prometheus.NewCounterVec(
    someMetricDefinition, // 指标定义
    []string{"some-label", "other-label"}, // 指标的label
}

一方面,因为新的框架扩展了指标定义结构体,没法继续使用prometheus.NewXXX()方法,另外一方面新框架也但愿能在指标初始化时扩展自定义行为(好比处理定义环节加入的字段),因此新框架中也提供了相似的一系列方法。

使用新框架的方法来初始化实例示例以下:

var deprecatedMetric = kubemetrics.NewCounterVec(
    deprecatedMetricDefinition, // 扩展的指标定义
    []string{"some-label", "other-label"},
}

一样与Prometheus保持一致,新框架也提供了全部的初始化方法:

  • NewCounter() 和 NewCounterVec()
  • NewGauge() 和 NewGaugeVec()
  • NewHistogram() 和 NewHistogramVec()
  • NewSummary() 和 NewSummaryVec()

一样,本节暂不对每种初始化方法展开介绍,这部份内容留到后面的章节中。

新的实现:监控指标注册

曾经,使用Prometheus来注册一个监控指标实例时,其实是注册到一个全局的注册表,以下所示:

prometheus.MustRegister(someCounterVecMetric)

新框架中对注册也进行了封装,以便增长自定义的行为,好比废弃版本检查,注册逻辑伪代码以下:

import version "k8s.io/apimachinery/pkg/version"

type Registry struct {
    promregistry *prometheus.Registry
    KubeVersion version.Info
}

func (r *Registry) MustRegister(metric kubemetrics.Metric) {
    if metricutils.compare(metric.DeprecatedVersion).isLessThan(r.KubeVersion) { // 若是废弃版本比当前版本低,检查废弃规则,不知足则再也不注册
        // check if binary has deprecated metrics enabled otherwise
        // no-op registration
        return
    } else if metricutils.compare(metric.DeprecatedVersion).isEqual(r.KubeVersion) { // 若是废弃版本与当前版本一致,则把弃用信息增长到指标的 HELP 信息中并记录 warning 日志
        // append deprecated text to description
        // emit warning in logs
        // continue to actual registration
    }
    // 若是是 ALPHA 监控指标,增长相应的标识到 HELP 信息中
    
    r.promregistry.MustRegister(metric.realMetric) // 最后仍是使用Prometheus来完成注册
}

使用新框架注册,以下所示:

kubemetrics.MustRegister(deprecatedMetric)
kubemetrics.MustRegister(alphaMetric)

由上综述,能够看到在编程层面,既有的监控指标能够方便的迁移到新框架,若是监控指标没有个性化的需求,那么其行为与原Prometheus彻底一致,若是有个性化的需求,经过简单的配置就可完成,具体的实现细节所有由新框架负责。

稳定性声明

当前版本(kubernetes 1.15 & 1.16)提供两个级别的稳定性,用来阐述每一个监控指标的稳定性:

  • Alpha
  • Stable

须要额外说起的时,在当前的设计中并无考虑 Beta 级别,新框架做者表示未来有须要时再添加,添加也会很是简单。

Alpha 级别的监控指标,基本上不提供任何稳定性的保证,它们能够随时被修改,并且新框架引入后,既有的监控指标都将标记为这个级别。

Stable 级别的监控指示,基本上能够保证“再也不修改”,除非未来被废弃。这里所说的“再也不修改”指如下三个内容不会修改:

  • 监控指标自己不会被删除或重命名;
  • 监控指标类型不会被修改;
  • 监控指标的lable列表不会增长或减小;

针对Stable级别的监控指标,lable列表不会改变,但lable 值是能够改变的。好比,某个指标用于记录鉴权的次数,使用"result"做为lable进行区分,lable 值原来是"success"和"failure",是容许增长新的lable 值的,好比增长一个"error"(不是简单的鉴权失败,而是出现某种异常)。

好比,你以前获得的指标将会由:

authentication_attempts{result="success"} 1345
authentication_attempts{result="failure"} 100

变成:

authentication_attempts{result="success"} 1345
authentication_attempts{result="failure"} 100
authentication_attempts{result="error"} 1     // 增长新的lable 值

通常来说,这种变化对用户的冲击不会很大。

针对Stable级别的监控指标,删除或增长 lable 是不容许的,若是必需要这么作,须要先把当前的指标废弃,再提供一个新的监控指标。

对于用户来说,新框架还提供了一个由用户显式的屏蔽某些监控指标的能力,默认状况下,全部的监控指标都会被注册并最终经过API提供给用户,但使用新框架后,用户能够经过相应组件的启动参数显式的关掉某些监控指标,好比:

--disable-metrics=somebrokenmetric,anothermetric

稳定性保证

把一个监控指标标记为 Stable 意味着对广大用户作出了一个承诺,这跟 API 是一致的。因此将某个监控指标标记为 Stable 或者 废弃某个监控指标时,须要很是谨慎的 review。

然而,跟据Kubernetes社区的组织划分,各个组件分别有不一样的 group (准确叫法是SIG)来负责相应的组件开发,各group的 reviewer 可能并不彻底了解新框架所引入的这个理念,因此各group颇有可能未来破坏以前作出的稳定性承诺。而每一个相关监控指标的修改都由负责监控的group来review,代价会很是大,而变得不可取。

针对这个问题,kubernetes社区又提供了让人眼前一亮的方法,即引入新的一致性测试。 即,生成一份现有的稳定性列表,并存放到某个由监控组管理的目录中,增长新的CI工做流收集最新的稳定性监控指标,两者对比,若是不一致,CI 会失败并拒绝合入,除非显式的修改稳定性列表。CI能够保证当显式的修改稳定性列表时,必须通过监控组的批准。

弃用规则

每一个Stable的监控指标,在决定要将其废弃后,能够在监控指标定义处显式的指定将要弃用的版本(DeprecatedVersion)。某个指标标记为废弃后不会立刻被删除,须要留给用户一个适配的窗口,在接下来的某些版本中才会真正被删除。

被废弃的监控指标都会经历以下阶段(每一个阶段表明一个kubernetes minor版本):

Stable metric -> Deprecated metric -> Hidden metric -> Deletion

好比,某个监控指标在1.16版本进入 Stable 阶段,将在 1.17版本弃用,那么在各版本其状态以下:

  • 1.16(Stable metric):可正常使用;
  • 1.17(Deprecated metric):标记为弃用,当前版本仍然能够用,可是用户须要准备适配;
  • 1.18(Hidden metric):默认不开启该监控指标,管理员可经过参数显式的启用该指标;
  • 1.19(Deletion):完全删除,没法再使用;

弃用阶段

好比,某个监控指标将在1.17版本废弃,那么1.17版本(或更早的版本)开发时能够这样设置:

var someCounter = kubemetrics.CounterOpts{
    Name: "some_counter",
    Help: "this counts things",
    StabilityLevel: kubemetrics.STABLE,
    DeprecatedVersion: "1.17", // this metric is deprecated when the Kubernetes version == 1.17
}

使用1.17以前的版本,监控指标信息以下:

# HELP some_counter this counts things
# TYPE some_counter counter
some_counter 0

那么用户在使用1.17版本时,将会看到相应的指标信息中出现弃用信息:

# HELP some_counter (Deprecated from 1.17) this counts things
# TYPE some_counter counter
some_counter 0

此外,当监控指标被标记为废弃后,虽然能正常使用,可是在相应的组件日志中能够看到告警日志。

隐藏阶段

当监控指标被弃用的下一个版本,即DeprecatedVersion == current_kubernetes_version - 1时,该监控指标默认会被隐藏:即不会自动注册。

被隐藏的指标能够经过相应组件的启动参数(--enable-hidden-metrics=really_deprecated_metric)来显式的启用。

若是用户忘记在上个版本中作好适配,仍然能够在本版本中继续使用,这无疑给用户延长了适配窗口。

另外,须要特别说起的几点是:

  • 被标记为弃用的监控指标仍然尊守以前的稳定性约定,除了增长弃用标记外不会修改指标内容;
  • 本弃用规则是针对Stable监控指标的,不对 Alpha 监控指标作强制要求。
  • 处于 Alpha 阶段的监控指标也能够标记废弃版本号,它能够帮助使用 Alpha 监控指标的用户准确的了解某个监控指标什么时候会被删除,仅用于说明,被删除前能够不遵循弃用规则;

总结

新的监控指标框架是社区众多专家智慧的结晶,从其设计理念上能够看出Kubernetes社区对用户承诺的重视,能够看出对软件工程的深层次的思考,值得学习。

相关文章
相关标签/搜索