使用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
最后,结合这两个思路的优缺点,社区使用了一个更具创新性的方案,也就是本文要介绍的稳定性框架,该框架在实现层面相对使用版本标记
更简单,在工程层面比使用文档标记
更易于管理。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
,新增长了StabilityLevel
和DeprecatedVersion
等字段用于表示稳定性和弃用标示。
表示一个监控指标被废弃,能够以下定义:
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种监控指标分别作了扩展:
本节暂不对每种监控指标展开介绍,仍是聚焦在阐述新框架的实现思路上。
曾经,使用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保持一致,新框架也提供了全部的初始化方法:
一样,本节暂不对每种初始化方法展开介绍,这部份内容留到后面的章节中。
曾经,使用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)提供两个级别的稳定性,用来阐述每一个监控指标的稳定性:
须要额外说起的时,在当前的设计中并无考虑 Beta 级别,新框架做者表示未来有须要时再添加,添加也会很是简单。
Alpha 级别的监控指标,基本上不提供任何稳定性的保证,它们能够随时被修改,并且新框架引入后,既有的监控指标都将标记为这个级别。
Stable 级别的监控指示,基本上能够保证“再也不修改”,除非未来被废弃。这里所说的“再也不修改”指如下三个内容不会修改:
针对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.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)来显式的启用。
若是用户忘记在上个版本中作好适配,仍然能够在本版本中继续使用,这无疑给用户延长了适配窗口。
另外,须要特别说起的几点是:
新的监控指标框架是社区众多专家智慧的结晶,从其设计理念上能够看出Kubernetes社区对用户承诺的重视,能够看出对软件工程的深层次的思考,值得学习。