k8s 监控(三)prometheus-adapter

本文属于 k8s 监控系列,其他文章为:node

  1. k8s 监控(一)安装 Prometheus
  2. k8s 监控(二)监控集群组件和 pod
  3. k8s 监控(四)监控宿主机

原本按计划这篇文章应该讲 grafana 和 alertmanager 的,可是因为它们部署起来太简单没有啥写的动力。最近由于研究了 Prometheus adapter,因此想将本身的研究所得写下来,也许下一篇会写 grafana 和 alertmanager。。python

ok,让咱们直接进入正文。git

kubernetes apiserver 提供了两种 api 用于监控指标相关的操做:github

kubernetes apiserver 用于将 kubernetes 的功能经过 restapi 的方式暴露出去,给其余组件使用,可是它提供的都是核心相关功能。有些功能有用,可是非核心,apiserver 又得提供这样的功能咋办?正则表达式

考虑到这样的状况,kubernetes apiserver 提供对应的 api,可是对于达到这个 api 的请求,它并不处理,而是转发到一个扩展 apiserver 上。有意思的是,这个扩展 apiserver 只要遵循规范,任何人均可以开发。json

使用者在使用扩展 apiserver 时,只须要将其注册到 kube-aggregator(kubernetes apiserver 的功能),aggregator 就会将对于这个 api 的请求转发到这个扩展 apiserver 上。固然 kubernetes apiserver 和扩展 apiserver 之间的交互会涉及到很是多的细节,这里就很少提。api

resource metrics API 和 custom metrics API 就是这样的例子,kubernetes apiserver 提供了这两个 api,可是具体的实现它就无论了。markdown

而这篇文章的目的就是经过 Prometheus adapter 实现它们。app

api group 和 api version

在实现这两个 api 以前,咱们先来聊聊 api 组和 api 版本。ide

所谓的 api group 就是你执行 kubectl api-versions 出现的值,这些值由 api group 和 api version 构成。

# kubectl api-versions
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
...
复制代码

内容太多,这里只列出了 5 个。第一个 admissionregistration.k8s.io/v1beta1 中,admissionregistration.k8s.io 是 api group,v1beta1 表示它的版本。

若是 api group 为空表示核心 api,kubernetes 的资源都是由 api group 提供的。那么如何知道哪些资源是由哪些 api group 提供的呢?

执行 kubectl api-resources 就可以知道了:

# kubectl api-resources
NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
bindings                                                                      true         Binding
componentstatuses                 cs                                          false        ComponentStatus
configmaps                        cm                                          true         ConfigMap
endpoints                         ep                                          true         Endpoints
events                            ev                                          true         Event
limitranges                       limits                                      true         LimitRange
namespaces                        ns                                          false        Namespace
nodes                             no                                          false        Node
...
复制代码

内容不少,这里只列出一部分。输出结果为 5 列,NAME 列就是资源名,它的功能由 APIGROUP 列的 api group 提供。SHORTNAMES 列就是这些资源的缩写了,缩写在使用 kubectl 时很是好用。

上面列出的全部结果中,APIGROUP 都为空,表示这些资源都是核心 api 提供的。当你看到某些 role 或者 clusterRole 中 apiGroup 的值为 "" 时,就应该知道它要访问的资源都是核心 api 提供的。

对于咱们要实现的两个 api:

  • resource metrics API 的 api group 是 metrics.k8s.io,版本为 v1beta1
  • custom metrics API 的 api group 是 custom.metrics.k8s.io,版本为 v1beta1

它们的 api group 和 api version 会在后面注册时用到。

custom metrics API

先说这个 custom metrics API,resource metrics API 放在后面。你若是说你只须要 resource metrics API,那你也得看这个,由于这两个 api 都由 Prometheus adapter 来实现。

custom metrics API 彻底就是给 HPA v2 准备的,由于 v1 只能使用 CPU 做为 pod 横向扩展的指标,很明显没法知足使用者的须要。

custom metrics API 的实现有多个,咱们之因此选择 Prometheus adapter,是由于咱们已经安装了 Prometheus。而经过 Prometheus adapter,只要存在于 Prometheus 中的指标,均可以拿来作 HPA 的条件,这样就能知足全部的使用场景了。

kubernetes 1.14 中 apiserver 已经开启了 Aggregation layer,所以咱们只须要安装 Prometheus adapter 就行。

咱们会使用 deployment 部署 Prometheus adapter,固然会为启动它的 serviceAccount 绑定各类角色。由于它自己就是一个 apiserver,所以它会监听一个端口,对外提供 http 服务。

咱们还须要为它建立一个 service,kubernetes apiserver 转发请求时,会将请求发送到 service 上,经由 service 到达后面的 Prometheus adapter。

本文全部的 yml 文件均保存在 GitHub,这里就不一一列出了。Prometheus adapter 相关的文件都在 adapter 目录下,custom metrics API 用到的文件有:

prometheus-adapter-apiServiceCustomMetrics.yml
prometheus-adapter-apiServiceMetrics.yml
prometheus-adapter-clusterRoleAggregatedMetricsReader.yml
prometheus-adapter-clusterRoleBindingDelegator.yml
prometheus-adapter-clusterRoleBinding.yml
prometheus-adapter-clusterRole.yml
prometheus-adapter-configMap.yml
prometheus-adapter-deployment.yml
prometheus-adapter-roleBindingAuthReader.yml
prometheus-adapter-serviceAccount.yml
prometheus-adapter-service.yml
复制代码

其中:

  • apiServiceCustomMetrics:用来提供注册 api,api 组为 custom.metrics.k8s.io,版本为 v1beta1
  • apiServiceMetrics:用来提供注册 api,api 组为 metrics.k8s.io,版本为 v1beta1。这是给 resource metrics 使用的;
  • roleBindingAuthReader:让扩展 apiserver 能够去读取 configMap 来验证 kubernetes apiserver 的身份,这个不用细究;
  • clusterRoleAggregatedMetricsReader:对 metrics.k8s.iocustom.metrics.k8s.io 下面的任意资源具备任意权限;
  • clusterRoleBindingDelegator:绑定权限,让 Prometheus adapter 有权限提交 SubjectAccessReview 请求到 kubernetes apiserver;
  • clusterRole:Prometheus adapter 须要访问集群内的资源;
  • configMap:Prometheus adapter 的配置文件,这是重点之一;
  • service:kubernetes apiserver 先将请求发送到这个 service,再由它转发到后面的 Prometheus adapter pod。

部署和测试

不少人在使用的时候会使用 kubernetes CA 签署一个证书以后用这个证书来为 Prometheus adapter 提供 https。其实不须要如此,Prometheus adapter 启动的时候,若是你没有给它提供证书,它会生成一个自签署的证书来提供 https。

至于这个证书是否受信任并不重要,由于 prometheus-adapter-apiServiceCustomMetrics.yml 文件中存在 insecureSkipTLSVerify: true 这个选项。

clone 并部署:

git clone https://github.com/maxadd/k8s-prometheus
kubectl apply -f k8s-prometheus/adapter
复制代码

经过下面直接访问 api 的方式来测试部署是否 ok(你可能须要略等一下子):

kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | python -mjson.tool
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/monitoring/pods/*/fs_usage_bytes" | python -mjson.tool
复制代码

第一条命令会输出很是多的值,都是能够用做 HPA 的指标。若是你没有,那么部署存在问题,缘由后面会讲。

第二条命令会输出 monitoring 名称空间下全部 pod 的 fs_usage_bytes 指标的值,若是你没有,那么部署一样存在问题。

由于我前面安装 Prometheus 的文章中对 Prometheus 中的一些指标和标签作了一些修改,所以若是你直接使用官方的配置,那么确定会出问题的。配置相关的内容下面会提到。

另外,Prometheus adapter 启动参数中的 -v 至关于 debug 级别,值越大,输出的日志就越详细,最高貌似为 10?可是好像这个日志没啥做用。。

配置文件

Prometheus adapter 的配置文件格式以下所示(因为过长,因此截取了一部分)。它分为两个部分,第一个是 rules,用于 custom metrics;另外一个是 resourceRules,用于 metrics。若是你只用 Prometheus adapter 作 HPA,那么 resourceRules 就能够省略,反之亦然。

咱们从 rules 规则讲起,这个规则下面有不少的查询语句,这些查询语句的做用就是尽量多的获取指标,从而让这些指标均可以用于 HPA。

也就是说经过 Prometheus adapter,你能够将 Prometheus 中的任何一个指标都用于 HPA,可是前提是你得经过查询语句将它拿到(包括指标名称和其对应的值)。也就是说,若是你只须要使用一个指标作 HPA,那么你彻底就能够只写一条查询,而不像下面使用了好多个查询。

rules:
 - seriesQuery: '{__name__=~"^container_.*",container_name!="POD",namespace!="",pod!=""}'
 seriesFilters: []
 resources:
 overrides:
 namespace:
 resource: namespace
 pod: # 官方示例中的这个值为 pod_name,因为我以前将 pod_name 改成了 pod,因此这里也为 pod
 resource: pods
 name:
 matches: ^container_(.*)_seconds_total$
 as: ""
 metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>,container_name!="POD"}[1m])) by (<<.GroupBy>>)
---
resourceRules:
 cpu:
 containerQuery: sum(rate(container_cpu_usage_seconds_total{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)
 nodeQuery: sum(rate(container_cpu_usage_seconds_total{<<.LabelMatchers>>, id='/'}[1m])) by (<<.GroupBy>>)
 resources:
 overrides:
 instance:
 resource: nodes
 namespace:
 resource: namespace
 pod:
 resource: pods
 containerLabel: container_name
复制代码

接下来咱们会对其关键字进行解释:

  • seriesQuery:查询 Prometheus 的语句,经过这个查询语句查询到的全部指标均可以用于 HPA;
  • seriesFilters:查询到的指标可能会存在不须要的,能够经过它过滤掉。过滤器有两种方式:
    • is: <regex>:只获取正则表达式匹配到的指标名称;
    • isNot: <regex>
  • resources:经过 seriesQuery 查询到的只是指标,我若是要查询某个 pod 的指标,确定要将它的名称和所在的名称空间做为指标的标签进行查询,resources 就是将指标的标签和 k8s 的资源类型关联起来,最经常使用的就是 pod 和 namespace。有两种添加标签的方式,一种是 overrides,另外一种是 template
    • overrides:它会将指标中的标签和 k8s 资源关联起来。上面示例中就是将指标中的 pod 和 namespace 标签和 k8s 中的 pods(pod 和 pods 都行,这就跟你 kubectl get pod/pods 同样)和 namespace 关联起来,由于 pod 和 namespace 都属于核心 api 组,因此不须要指定 api 组。等你查询某个 pod 的指标时,它会自动将 pod 的名称和名称空间做为标签加入到查询条件中;
      • microservice: {group: "apps", resource: "deployment"} 这么写表示将指标中 microservice 这个标签和 apps 这 api 组中 deployment 资源关联起来;
    • template:经过 go 模板的形式。
      • template: "kube_<<.Group>>_<<.Resource>>" 这么写表示,假如 <<.Group>> 为 apps,<<.Resource>> 为 deployment,那么它就是将指标中 kube_apps_deployment 标签和 deployment 资源关联起来;
  • name:用来给指标重命名的。之因此要给指标重命名是由于有些指标是只增的,好比以 total 结尾的指标。这些指标拿来作 HPA 是没有意义的,咱们通常计算它的速率,以速率做为值,那么此时的名称就不能以 total 结尾了,因此要进行更名。
    • matches:经过正则表达式来匹配指标名,能够进行分组;
    • as:默认值为 $1,也就是第一个分组。as 为空就是使用默认值的意思。
  • metricsQuery:这就是查询 Prometheus 了,前面的 seriesQuery 查询是得到 HPA 指标。当咱们要查某个指标的值时就要经过它指定的查询语句进行了。能够看到查询语句使用了速率和分组,这就是解决上面提到的只增指标的问题,它还用到了模板。
    • Series:指标名称;
    • LabelMatchers:附加的标签,目前只有 pod 和 namespace 两种,所以咱们要在以前使用 resources 进行关联;
    • GroupBy:就是 pod 名称,一样须要使用 resources 进行关联。

前面访问 /apis/custom.metrics.k8s.io/v1beta1/ 出现的全部指标都是这些规则中 seriesQuery 查询到的,固然名称可能和 Prometheus 中不彻底同样,由于这里使用了 name 进行了重命名。

其实不少指标拿来作 HPA 是没有必要的,好比说 Prometheus 自身的指标以及 k8s 组件指标等,可是 Prometheus adapter 确定但愿将全部的指标都暴露出来,让你想使用啥就使用啥,因此它的 seriesQuery 才会这么多。

访问 /apis/custom.metrics.k8s.io/v1beta1/namespaces/monitoring/pods/*/fs_usage_bytes 则是经过 metricsQuery 进行查询,从而获取每一个 pod 的指标值。

部署有问题的多半就是配置文件中的关联没有作好,只有理解了这个配置文件的意思才能保证部署没有问题。

剩下的 resourceRules 规则则是用于 resource metrics,只有 cpu 和 memory 两个属性,而这两个属性又分为 node 和 pod,很容易看懂。当执行 kubectl top pods/nodes 时就会执行这两条查询语句。

关于 custom metrics 就到此为止了,HPA 的内容这里就不涉及了。

resource metrics API

resource metrics API 官方的说法是给 k8s 核心组件提供监控指标的,可是它只提供了 pod 和 node 的 CPU 和内存指标,功能实在有限。

官方给出它能够作如下工做:

  • HPA:CPU 指标能够拿来作 HPA。v1 版本的 HPA 也许依赖这个,如今已经无所谓了;
  • pod 调度:官方的意思是这是个扩展的功能,由于如今的 pod 调度根本没有考虑到 node 的使用状况;
  • 集群联邦:一样是资源使用,可是如今没有使用;
  • dashboard:出图,没用过 dashboard,也不知道是否是有效果;
  • kubectl top:这算是最实用的功能吧。

因此总结下来,resource metrics API 的最大做用就是居然是让你可使用 kubectl top 命令?固然我们先无论它是否有用,咱们目的之一就是部署一个扩展 apiserver 来实现它,接下来就是选一个扩展 apiserver。

不少人会使用 metrics server 提供 resource metrics API,而后使用 Prometheus adapter 提供 custom metrics API。可是其实 Prometheus adapter 彻底能够支持这两种 api,所以咱们彻底不须要 metrics server,只部署一个 Prometheus adapter 就行。

前面咱们其实已经部署好了,只须要验证就行。

# kubectl -n monitoring top pods
NAME                                  CPU(cores)   MEMORY(bytes)
alertmanager-c8d754fbc-2slzr          1m           15Mi
grafana-74bf6c49f6-lf7vw              7m           50Mi
kube-state-metrics-856448748c-xtdxl   0m           24Mi
prometheus-adapter-548c9b9c4c-mr9zq   0m           39Mi
复制代码

可是执行 kubectl top node 会出现问题,由于我将 id='/' 的指标都删掉了,若是不想将这些指标恢复,能够看我下一篇收集宿主机指标的文章。

这篇文章就到这了,感谢阅读,谢谢!