Kubernetes1.15.2 监控(1)安装 Prometheus 2.11.1
Last updated
Was this helpful?
Last updated
Was this helpful?
k8s 监控我们要完成以下几点:
监控 master/node 本身;
监控集群组件 apiServer、etcd 等;
监控需要关注的 pod;
自定义的监控,包括 jmx 等。
有了这些监控指标之后,我们还需要做到以下几点:
制定相应的告警规则;
提供对应的 webhook 发出告警;
部署 grafana 进行图形展示;
监控相关组件的高可用;
和 k8s metrics-server 进行结合。
目前而言,k8s 的监控业界公认的标准就是使用 Prometheus,Prometheus 也能很好的完成 k8s 的监控工作。只不过如果使用原生 Prometheus 进行监控的话,还要完成上述操作,需要做的工作非常多,需要对 k8s 以及 Prometheus 本身有一定的理解。
为了方便操作,coreos 提供了 这样一个产品,它包装了 Prometheus,并且还提供了四个自定义的 k8s 类型(CustomResourceDefinitions),让你通过定义 manifest 的方式还完成新监控(job)以及告警规则的添加,而无需手动操作 Prometheus 的配置文件,让整个过程更 k8s。
并且在此基础之上,coreos 还有推出了 这样的升级版,它在 prometheus-operator 的基础之上高可用了 Prometheus 和 Alertmanager,提供了 node-exporter 用于宿主机的监控,还有 Kubernetes Metrics APIs 的 Prometheus 适配器和 grafana,让你实现一键部署。
老外喜欢这么搞,是不是一定合适我不知道,但是肯定是存在问题的,毕竟这个 prometheus-operator 依然处于 bate 状态。并且它里面多出的很多组件都只是为了避免让你直接操作配置文件,而这些组件都是额外的消耗。
同时也是因为你不能直接操纵配置文件,所以一旦你想修改配置文件就非常困难了,因为配置文件是自动生成的,一旦你想要修改它的 relabel_config
配置,你只能在它生成的规则后面添加。
这样会出现一种情况,就是你可能想删掉它为你自动生成的标签,但是这个标签本来就没有,是它为你生成的,但是生成之后你又想删除,这样就平白多了两台规则。并且一旦你配置定义错了,因为是 prometheus-operator 帮你 reload 的,因此就算有错误你也收不到。
如果你只是简单使用的话可以直接使用 kube-prometheus。但是只要你想要了解其中的原理部分,或者有自己定制化的需求,那就搞原生的吧,所有 prometheus-operator 能够实现的,原生都能实现。
本文会从 0 开始,一点一点完成一开始的监控需求。即使你还是想用 kube-prometheus,等你看完我的所有文章之后,你使用起来也就没有丝毫的障碍了。
我们要做的就是将 Prometheus 镜像部署到 k8s 中,然后使用 kubernetes_sd_config
对 k8s 进行完成监控。当然,prometheus-operator 也是这么做的。
虽然 Prometheus 可以做到对 k8s 集群中所有 pod 的发现,但是 pod 的 ip 会随时改变,而且你进行所有 pod 的发现让你无从对它们进行分类管理,这样就会非常乱。
因此,我这里会和 prometheus-operator 一样,只对 endpoint 进行发现。因为创建 service 就会创建对应的 endpoint,所以我们完全可以通过 service 对 pod 进行分类,然后针对一类 pod 我们使用一个 Prometheus 的 job,这样就非常简洁明了了。
本文中 k8s 版本为 1.14.2,采用 kubeadm 安装。此外,本文不会对 Prometheus 进行过多的介绍,也就是说你需要有一定的 Prometheus 基础。
大家应该清楚,应用如果想要被 Prometheus 监控,就应该提供一个 url,一旦访问这个 url,那么所有监控项就会以文本的形式一行行打印出来,Prometheus 就通过访问这个 url 来获得所有的监控数据,这个 uri 默认为 http[s]://IP:PORT/metrics
。
因为 Prometheus 已经成为了一个标准,因此 k8s 的所有组件都提供了 /metrics
这个 url。对于一些主机层面或者没有提供这个 url 应用的监控,可以使用一个中间产品,这个产品收集应用相关的监控指标,然后提供这个 url,让 Prometheus 进行采集。
既然 Prometheus 能够通过 http 收集,那通过 curl 一样也行。因此在使用 Prometheus 收集之前,我会使用 curl 命令将所有要收集的指标数据先输出出来,以便大家心中有数。
当然,因为是在 k8s 环境,监控指标在收取之后会附加上一些标签,比如它所在的名称空间、所属的 service、pod 名称,以及 ip 端口等,这些标签你也可以选择加还是不加。
话不多说,我们先看看 kubelet 的指标数据。先创建一个目录,用于存放后续所有的 manifest 文件:
首先创建一个名称空间,所有监控相关的资源都放在这个名称空间之下:
我们知道,pod 都是由 kubelet 创建的,因此 pod 的相关指标(包括使用的 cpu、内存、流量等)是由 kubelet 提供的,我们现在就可以访问 kubelet 的指标页面,看看有哪些指标数据。
作为一个守护进程,kubelet 默认监听 10250 端口,因此可以在 master 或者 node 上直接访问:
其中:
必须使用 https;
metrics/cadvisor
是 kubelet pod 相关的监控指标,它还有一个 metrics
,这是 kubelet 自身的监控指标;
-k
表示不验证 kubelet 证书,因为整个集群都是使用自签署证书,因此没必要验证;
上面提示我们没有认证,看不到指标数据。认证很简单,使用 token 即可,那么我们首先要创建这个 token。大家应该清楚,当我们创建一个 serviceAccount 之后,k8s 会自动为其生成一个 secret,这个 secret 中就有 token 信息。
因此我们需要创建了一个 clusterRole,并创建一个 clusterrolebinding 将权限绑定到一个 serviceAccount 上,那么我们就拿到了这个权限的 token 了。
那我们需要创建 prometheus-clusterRole.yml
、prometheus-clusterRoleBinding.yml
和 prometheus-serviceAccount.yml
这三个文件,它们的内容如下。
prometheus-clusterRole.yml:
prometheus-clusterRoleBinding.yml:
prometheus-serviceAccount.yml:
这样我们就创建了一个 ServiceAccount,名为 prometheus-k8s,这个 ServiceAccount 不仅现在可以用来获取 kubelet 的监控指标,后续 Prometheus 也会使用这个 serviceAccount 启动。
创建完成后,会自动在生成一个 secret,里面包含了 token:
获取 token:
然后使用这个 token 访问 kubelet 的指标页面:
只需要将这个 token 放到请求头中就行,然后就可以看到所有的监控指标了。
可以看到里面有很多这样的标签的指标存在:
我完全没有搞懂这些是干啥的,不知道有没有用,反正我是准备全删除的。使用 Prometheus 就是有这样的问题,什么样的指标数据都有,恨不得把所有的都暴露出来,如果你是默认使用而没有管里面到底有什么指标数据的话,你可能接收了几倍的无用数据(对于很多人来讲,确实是没用的,因为从来都不会关注),造成了大量的资源浪费。
kubelet 除了 /metrics/cadvisor
这个 url 之外,还有一个 /metrics
,这是它本身的监控指标而非 pod 的。说实话,里面的数据我都看不懂,我在考虑要不要接收。
通过这种方式,其他几个 k8s 组件你应该都能够访问了,但是 etcd 不行,它需要验证客户端证书。
etcd 的指标页面的 url 也是 /metrics
,但是你想要访问它需要提供证书,因为它会验证客户端证书。当然你可以在它的启动参数中通过 --listen-metrics-urls http://ip:port
让监控指标页使用 http 而非 https,这样就不用提供证书了。
etcd 虽然部署在容器中,但是由于使用了 hostNetwork
,所以我们可以通过直接访问 master 的 2379 端口访问它。默认它会采用了 https,因此我们需要提供它的 peer 证书。如果 k8s 是使用 kubeadm 安装的,etcd 的证书在 /etc/kubernetes/pki/etcd/
目录下。
因此访问 etcd 的命令为:
后面我们需要将这三个文件挂载到 Prometheus 容器中,以便它能收集 etcd 监控数据。
Prometheus 本身会依赖一些东西,因此在安装之前我们必须做一些准备工作。
我们先创建两个 configmap,一个是 Prometheus 的配置文件,另一个是告警的规则文件。配置文件一定要使用 configmap 进行保存,不能直接放在容器中,不然容器挂了配置文件就没了。
先创建 Prometheus 配置文件 configmap prometheus-config.yml
,它的内容如下:
这里使用的是 endpoint 的方式对 Prometheus 本身进行发现,你可以有疑问了,为什么不直接对自身的 127.0.0.1:9090 进行采集呢?因为考虑到 Prometheus 可能会有多台,这样即使有多台,它们也都在一个 job 下面。
当然,你如果嫌麻烦也可以直接对自身进行采集,没有任何问题。然后下面就是一堆的 relabel_configs 配置了,我一个个解释这些配置是干啥的。
首先看第一个配置:
大家应该知道,每创建一个 service 就会创建一个对应的 endpoint,但是 prometheus 的 endpoint 的发现会对 k8s 指定名称空间下所有 endpoint 进行发现,那么怎么保证 Prometheus 只发现我们需要的 endpoint 呢?答案是通过 relabel_configs
,这里 keep 就是干这个的。
上面配置的意思是只有 service 的标签包含 prometheus=k8s
,k8s 才会对其对应的 endpoint 进行采集。所以我们后面要为 Prometheus 创建一个 service,并且要为这个 service 加上 prometheus: k8s
这样的标签。
这里没有指定 url,Prometheus 会采集默认的 url /metrics
。
接着看下一段配置:
如果 __meta_kubernetes_endpoint_address_target_kind
的值为 Pod,__meta_kubernetes_endpoint_address_target_name
的值为 prometheus-0,在它们之间加上一个 ;
之后,它们合起来就是 Pod;prometheus-0
。使用正则表达式 Pod;(.*)
对其进行匹配,那么 ${1}
就是取第一个分组,它值就是 prometheus-0,最后将这个值交给 pod 这个标签。
因此这一段配置就是为所有采集到的监控指标增加一个 pod=prometheus-0
的标签。
如果
__meta_kubernetes_endpoint_address_target_kind
的值不是 Pod,那么不会添加任何标签。
后面的配置我想就不用多说了,无非就是将指定的元标签转换为指定的标签,因为不转换的话,元标签会在 relabel 之后都会被干掉。
创建它:
我们目前不需要任何规则文件,但是由于会将对应 configmap 挂载进容器中,所以我们创建一个空的规则文件。
先创建一个 prometheus-config-rulefiles.yml
文件,它的内容如下:
创建:
因为 Prometheus 会使用之前创建的 sa(serviceAccount)prometheus-k8s 运行,那么光现在 prometheus-k8s 这个 sa 的权限是没有办法查看 service 以及 endpoint 的。
我们需要创建更多的 role,并通过 roleBinding 将这些权限绑定到 prometheus-k8s 这个 sa 上,之所以不使用 clusterRole 是为了权限最小化。
这里会创建 prometheus-roleConfig.yml
、prometheus-roleBindingConfig.yml
、prometheus-roleSpecificNamespaces.yml
、prometheus-roleBindingSpecificNamespaces.yml
这四个文件,它们的内容如下。
prometheus-roleConfig.yml:
prometheus-roleBindingConfig.yml:
prometheus-roleSpecificNamespaces.yml:
prometheus-roleBindingSpecificNamespaces.yml:
上面的权限中,config 是用来读 configmap 的,后面的就是 Prometheus 用来进行 k8s 发现时必须要的权限了,最后使用 rulebinding 将这些所有的权限都绑定到 prometheus-k8s 这个 sa 上。
这样后续 Prometheus 容器访问 api server 以及集群内的组件时,就会使用这些权限访问。
最后应用:
Prometheus 因为会将数据存储到磁盘上,因此我们必须使用 statefulset,这样就需要一个存储了,我这里就直接使用 nfs 了,你可能需要搭建一个,这里就不多提了。
先创建 prometheus-pv.yml
:
然后应用:
statefulset 必须要一个无头的 service,同时我们要进行 endpoint 发现也需要创建 service,创建一个 service 正好满足它们,不过要为这个 service 添加 prometheus=k8s
这个标签。
因此创建文件 prometheus-service.yml
,它的内容如下:
上面定义了 app=prometheus
这样的标签选择器,因此 Prometheus 容器必须存在这个标签。
创建:
如果你不打算监控 etcd,那么可以直接跳过,并且将下面 Prometheus yml 文件中的 secret 相关的挂载删掉。
直接创建一个 secret 就行:
为了方便后续使用,建议你在这个命令之后加上 --dry-run -o yaml
,然后将输出的内容保存在 prometheus-secret.yml
中。因为加了 --dry-run
之后不会执行,你还需要手动创建:
到此所有前置工作完成,接下来就可以直接部署 prometheus 了。先创建文件 prometheus.yml
,它的内容如下:
基础的 statfulset 相关的知识我就不多提了,说几个重点吧:
--storage.tsdb.retention.time=20d
这个启动选项表示 Prometheus 所收集的监控数据只保留 20 天,这个值最好不要太大。如果历史数据保存很久,建议写到持久存储中,比如 VictoriaMetrics、thanos、influxdb、opentsdb 等;
--web.enable-admin-api
这个启动选项表示启动管理员 api,你可以通过 api 对监控数据进行删除等;
serviceAccount
它的值必须是 prometheus-k8s,不然前面的赋权操作都白干了;
pod 必须存在 app: prometheus
这个标签,不然无法被前面创建的 service 选择到;
挂载了两个 configmap、一个 secret 还有一个存储卷。
其他没有什么好说的了,直接干吧:
然后等待 Prometheus 启动成功:
启动成功之后就可以直接访问了,我们先不创建 ingress,而是将 pod 的端口绑定到宿主机上:
然后通过访问当前主机的 9090 端口就可以打开 Prometheus 页面。我们点开 Status,然后选择 Targets 就可以发现 Prometheus 自身已经被监控了。
可以看到,它显示了额外的 6 个标签,这些都是我们前面通过 relabel_configs
配置附加上去的,你现在只要在 Prometheus 查询任意一条监控指标,都会有这 6 个标签。如果你觉得这些标签中有你不需要的,只需要在前面的配置中删除对应的配置即可。
然后你将鼠标悬浮在这些标签之上,就能看到所有 relabel 之前所有的元标签,如果有你需要的,可以在前面的配置文件中添加响应的配置,将对应的标签加上去。
你可以选择点击左上角的 Prometheus 回到主页,然后在下面的查询框中,随便输入一个字母,然后在出现的所有监控指标中随便点击一个,就可以看到它的所有标签和其对应的值了。
可以看到,额外的 6 个标签都存在,今后你可以通过这些标签来进行查询了。
最后,给 Prometheus 创建一个 ingress,文件名为 prometheus-ingress:
注意将上面的 example.com 替换成你 Prometheus 的域名。
文章中所有的文件我都已上传到 ,你可以直接 clone 下来,而不需要频繁的复制粘贴。
这种产品称为 XXX_exporter,比如 node_exporter、jmx_exporter 等,官方很多的 exporter,有官方和非官方的,你也可以通过它们提供的客户端库自己实现一个。
简单的说明下这个配置文件的内容:这个配置文件只是一个初版,可以看到里面只有一个 job,就是监控 Prometheus 本身。可以看到,这里使用了 kubernetes_sd_configs
,使用这个配置可以自动发现 k8s 中 node、service、pod、endpoint、ingress,并为其添加监控,更多的内容可以直接查看。
我们使用 主要会使用 endpoint 进行发现,因此 prometheus-k8s 必须具备更多的权限。