参考
- https://blog.csdn.net/liukuan73/article/details/78881008
- https://github.com/liukuan73/kubernetes-addons
总体目标
从监控平台本身的业务需求来看,至少应该通过平台获取到以下的监控数据:
性能指标(如:CPU、Memory、Load、磁盘、网络等)
- 容器、Pod相关的性能指标数据
- 主机节点相关的性能指标数据
- 容器内进程自己主动暴露的指标数据
- k8s上应用的网络性能,如http、tcp等数据
状态指标
- k8s资源对象(Deployment、Daemonset、Pod等)的运行状态指标
- k8s平台组件(如kube-apiserver、kube-scheduler等)的运行状态指标
获取监控数据之后,还需要对监控进行可视化展示,以及对监控中出现的异常情况进行告警。
主流方案
目前对于kubernetes的主流监控方案主要有以下几种:
Heapster+InfluxDB+Grafana
每个K8S节点的Kubelet内含cAdvisor,暴露出API,Heapster通过访问这些端点得到容器监控数据。它支持多种储存方式,常用的是InfluxDB。这套方案的缺点是数据来源单一、缺乏报警功能以及InfluxDB的单点问题,而且Heapster也已经在新版本中被deprecated(被metrics server取代)了。这种实现方案的详细介绍请见这篇文章。
Metrics-Server+InfluxDB+Grafana
k8s从1.8版本开始,CPU、内存等资源的metrics信息可以通过 Metrics API来获取,用户还可以通过kubectl top直接获取这些metrics信息。Metrics API需要部署Metrics-Server。
各种Exporter+Prometheus+Grafana
通过各种export采集不同维度的监控指标,并通过Prometheus支持的数据格式暴露出来,Prometheus定期pull数据并用Grafana展示,异常情况使用AlertManager告警。本方案下文详细叙述。
架构
总体实现思路如下:
采集
通过cadvisor采集容器、Pod相关的性能指标数据,并通过暴露的/metrics接口用prometheus抓取
通过prometheus-node-exporter采集主机的性能指标数据,并通过暴露的/metrics接口用prometheus抓取
应用侧自己采集容器中进程主动暴露的指标数据(暴露指标的功能由应用自己实现,并添加平台侧约定的annotation,平台侧负责根据annotation实现通过Prometheus的抓取)
通过blackbox-exporter采集应用的网络性能(http、tcp、icmp等)数据,并通过暴露的/metrics接口用prometheus抓取
通过kube-state-metrics采集k8s资源对象的状态指标数据,并通过暴露的/metrics接口用prometheus抓取
通过etcd、kubelet、kube-apiserver、kube-controller-manager、kube-scheduler自身暴露的/metrics获取节点上与k8s集群相关的一些特征指标数据。
存储(汇聚),通过prometheus pull并汇聚各种exporter的监控数据
展示,通过grafana展示监控信息
告警,通过alertmanager进行告警
监控指标采集实现
容器、Pod相关的性能指标数据—cAdvisor
cAdvisor是谷歌开源的一个容器监控工具,cadvisor采集了主机上容器相关的性能指标数据,通过容器的指标还可进一步计算出pod的指标。
cadvisor提供的一些主要指标有:
1 | container_cpu_* |
cadvisor接口
目前cAdvisor集成到了kubelet组件内,可以在kubernetes集群中每个启动了kubelet的节点使用cAdvisor提供的metrics接口获取该节点所有容器相关的性能指标数据。1.7.3版本以前,cadvisor的metrics数据集成在kubelet的metrics中,在1.7.3以后版本中cadvisor的metrics被从kubelet的metrics独立出来了,在prometheus采集的时候变成两个scrape的job。
cAdvisor对外提供服务的默认端口为4194,主要提供两种接口:
Prometheus格式指标接口:nodeIP:4194/metrics(或者通过kubelet暴露的cadvisor接口nodeIP:10255/metrics/cadvisor);
WebUI界面接口:nodeIP:4194/containers/
Prometheus作为一个时间序列数据收集,处理,存储的服务,能够监控的对象必须通过http api暴露出基于Prometheus认可的数据模型的监控数据,cAdvisor接口(nodeIP:4194/metrics)暴露的监控指标数据如下所示:
1 | # HELP cadvisor_version_info A metric with a constant '1' value labeled by kernel version, OS version, docker version, cadvisor version & cadvisor revision. |
Prometheus配置
1 | - job_name: 'cadvisor' |
之后,在prometheus的target(IP:Port/targets)中可以看到cadvisor相应的target
PS:
关于配置文件的一些说明:
- 以上配置遵照官方example配置,通过apiserver提供的api做代理获取cAdvisor( https://kubernetes.default.svc:443/api/v1/nodes/k8smaster01/proxy/metrics/cadvisor )的监控指标(和从nodeIP:4194/metrics获取到的内容是一样的),而不是直接从node上获取。为什么这样做,官方这样解释的:This means it will work if Prometheus is running out of cluster, or can’t connect to nodes for some other reason (e.g. because of firewalling)。
- Promethues在K8S集群内通过DNS地址 https://kubernetes.default.svc访问apiserver来scrape数据
- Prometheus配置文件的语法规则较复杂,为便于理解,我加了一些注释;更多语法规则请见Prometheus官方文档。
关于target中label的一些说明,target中必有的几个source label有:
- __address__(当static_configs时通过targets手工配置,当kubernetes_sd_configs时,值从apiserver中获取)、
- __metrics_path__(默认值是/metrics)、
- __scheme__(默认值是http)
- job
其他source label则是根据kubernetes_sd_configs时设置的- role(如endpoints、nodes、service、pod等)从k8s资源对象的label、annotation及其他一些信息中提取的
主机节点性能指标数据—node-exporter
Prometheus社区提供的NodeExporter项目可以对主机的关键度量指标进行监控,通过Kubernetes的DeamonSet可以在各个主机节点上部署有且仅有一个NodeExporter实例,实现对主机性能指标数据的监控。node-exporter所采集的指标主要有:
1 | node_cpu_* |
Prometheus配置
node-exporter-daemonset.yaml, node-exporter-svc.yaml
1 | apiVersion: extensions/v1beta1 |
PS:
1.为了让容器里的node-exporter获取到主机上的网络、PID、IPC指标,这里设置了hostNetwork: true、hostPID: true、hostIPC: true,来与主机共用网络、PID、IPC这三个namespace。
2.此处在Service的annotations中定义标注prometheus.io/scrape: ‘true’,表明该Service需要被Promethues发现并采集数据。
通过NodeExporter暴露的metrics接口(nodeIP:9100/metrics)查看采集到的数据,可以看到是按Prometheus的格式输出的数据:
1 | # HELP node_arp_entries ARP entries by device |
Prometheus配置
1 | - job_name: 'prometheus-node-exporter' |
采集应用实例中某个进程自己暴露的指标数据
有的应用具有暴露容器内具体进程性能指标的需求,这些指标由应用侧实现采集并暴露,平台侧做汇聚。
如何标识哪些是主动暴露监控指标的应用并获取指标
平台侧可以约定好带哪些annotation前缀的服务是自主暴露监控指标的服务。应用添加平台侧约定的这些annotations,平台侧可以根据这些annotations实现Prometheus的scrape。
例如,应用侧为自己的服务添加如下平台侧约定约定的annotation:
1 | prometheus.io/scrape: 'true' |
Prometheus可以:
- 根据prometheus.io/scrape: ‘true’获知对应的endpoint是需要被scrape的
- 根据prometheus.io/app-metrics: ‘true’获知对应的endpoint中有应用进程暴露的metrics
- 根据prometheus.io/app-metrics-port: ‘8080’获知进程暴露的metrics的端口号
- 根据prometheus.io/app-metrics-path: ‘/metrics’获知进程暴露的metrics的具体路径
如何给应用加一些标志信息,并带到Prometheus侧
可能还需要根据平台和业务的需求添加其他一些以prometheus.io/app-info-为前缀的annotation,Prometheus截取下前缀,保留后半部分做key,连同value保留下来。这样满足在平台对应用做其他一些标识的需求。比如加入如下annotation来标识应用所属的的环境、租户以及应用名称
1 | prometheus.io/app-info-env: 'test' |
Prometheus配置
1 | - job_name: 'kubernetes-app-metrics' |
PS:
最后两行的作用是将例如
prometheus.io/app-info-tenant
的annotation名切割成名为tenant
的label。
通过blackbox-exporter采集应用的网络性能数据
blackbox-exporter是一个黑盒探测工具,可以对服务的http、tcp、icmp等进行网络探测。
blackbox-exporter部署
blackbox-exporter-deploy.yml
1 | apiVersion: extensions/v1beta1 |
black-exporter-config.yml
1 | apiVersion: v1 |
black-exporter-svc.yml
1 | --- |
PS:
blackbox-exporter的配置文件为/etc/blackbox_exporter/blackbox.yml,可以运行时动态的重新加载配置文件,当重新加载配置文件失败时,不影响在运行的配置。重载方式:curl -XPOST http://IP:9115/-/reload
Prometheus配置
在Prometheus的config文件中分别配置对http和tcp的探测:
1 | - job_name: 'kubernetes-service-http-probe' |
应用侧配置
应用可以在service中指定平台侧约定的annotation,实现监控平台对该应用的网络服务进行探测:
http探测
1 | prometheus.io/scrape: 'true' |
tcp探测
1 | prometheus.io/scrape: 'true' |
Prometheus根据这些annotation可以获知相应service是需要被探测的,探测的具体网络协议是http还是tcp或其他,以及具体的探测端口。http探测的话还要知道探测的具体url。
资源对象(Deployment、Pod等)的状态—kube-state-metrics
kube-state-metrics采集了k8s中各种资源对象的状态信息:
1 | kube_daemonset_*(创建时间、所处的阶段、期望跑在几台节点上、应当正在运行的节点数量、不应该跑却跑了daemon pod的节点数、跑好了pod(ready)的节点数) |
部署
kube-state-metrics-deploy.yml
1 | apiVersion: apps/v1 |
kube-state-metrics-svc.yml
1 | apiVersion: v1 |
Prometheus配置
1 | - job_name: 'kube-state-metrics' |
k8s集群组件的状态指标采集
etcd、kube-controller-manager、kube-scheduler、kube-proxy、kube-apiserver、kubelet这几个k8d平台组件分别向外暴露了prometheus标准的指标接口/metrics。可通过配置prometheus来进行读取。
etcd指标获取
以kubeadm启动的k8s集群中,etcd是以static pod的形式启动的,默认没有service及对应的endpoint可供集群内的prometheus访问。所以首先创建一个用来为prometheus提供接口的service(endpoint),etcd-svc.yaml文件如下:
1 | apiVersion: v1 |
prometheus配置抓取的文件加入如下配置:
1 | - job_name: 'etcd' |
kube-proxy指标获取
kube-proxy通过10249端口暴露/metrics指标。与3.6.1同理,kube-proxy-svc.yaml如下:
1 | apiVersion: v1 |
prometheus配置抓取的文件加入如下配置:
1 | - job_name: 'kube-proxy' |
kube-scheduler指标获取
kube-scheduler通过10251端口暴露/metrics指标。与3.6.1同理,kube-scheduler-svc.yaml如下:
1 | apiVersion: v1 |
prometheus对应的配置如下:
1 | - job_name: 'kube-scheduler' |
kube-controller-manager指标获取
kube-controller-manager通过10252端口暴露/metrics指标。与etcd同理,kube-controller-manager-svc.yaml如下:
1 | apiVersion: v1 |
prometheus配置抓取的文件加入如下配置:
1 | - job_name: 'kube-controller-manager' |
以上四步配置好后可以在promethues的web UI中看到对应的targets
kube-apiserver数据获取
kube-apiserver与上面四个组件不同的是,部署好后集群中默认会有一个名为kubernetes的service和对应的名为kubernetes的endpoint,这个endpoint就是集群内的kube-apiserver的访问入口。可以如下配置prometheus抓取数据:
1 | - job_name: 'kube-apiservers' |
kubelet数据获取
kubelet暴露的metrics端口默认为 10255:
- 提供的prometheus格式指标接口:nodeIP:10255/metrics,使用Prometheus从这里取数据
- kubelet提供的stats/summary接口:nodeIP:10255/stats/summary,heapster和最新的metrics-server从这里获取数据
kubelet采集的指标主要有:
1 | apiserver_client_certificate_expiration_seconds_bucket |
查看kubelet监控指标数据(nodeIP:10255/metrics):
1 | # HELP apiserver_audit_event_total Counter of audit events generated and sent to the audit backend. |
kubelet由于在每个节点上都有且仅有一个,所以可以通过k8s的node对象找到kubelet的指标,prometheus配置如下:
1 | - job_name: 'kubelet' |
Prometheus部署
prometheus-rbac.yml
1 | --- |
prometheus-sts.yml
1 | apiVersion: apps/v1 |
对args参数做几点说明:
–storage.tsdb.path:tsdb数据库存储路径
–storage.tsdb.retention:数据保留多久,可以看官方文档存储部分
–config.file:指定prometheus的config文件的路径
–web.enable-lifecycle:加上这个参数后可以向/-/reload(curl -XPOST 10.142.232.150:30006/-/reload)发送HTTP POST请求实现prometheus在config文件修改后的动态reload,更多信息请查看官方文档
–web.enable-admin-api:加上这个参数可以为一些高级用户暴露操作数据库功能的API,比如快照备份(curl -XPOST http://
/api/v2/admin/tsdb/snapshot),更多信息请查看官方文档 TSDB Admin APIs部分
prometheus-svc.yml
1 | kind: Service |
prometheus-config.yml
1 | apiVersion: v1 |
prometheus-rules.yml
1 | apiVersion: v1 |
可视化展示Grafana
部署
1 | --- |
grafana配置
- 添加数据源
- 添加dashboard
一些比较实用的模板:
315这个模板是cadvisor采集的各种指标的图表
1860这个模板是node-exporter采集的各种主机相关的指标的图表
6417这个模板是kube-state-metrics采集的各种k8s资源对象的状态的图表
4859和4865这两个模板是blackbox-exporter采集的服务的http状态指标的图表(两个效果基本一样,选择其一即可)
5345这个模板是blackbox-exporter采集的服务的网络状态指标的图表
告警
设置警报和通知的主要步骤:
- 安装配置Alertmanager
- 配置Prometheus与Alertmanager通信
- 在Prometheus中创建告警规则
部署
1 | apiVersion: apps/v1beta2 |
关联Prometheus与alertmanager
在Prometheus的架构中被划分成两个独立的部分。Prometheus负责产生告警,而Alertmanager负责告警产生后的后续处理。因此Alertmanager部署完成后,需要在Prometheus中设置Alertmanager相关的信息。
编辑Prometheus配置文件prometheus.yml,并添加以下内容
1 | alerting: |
reload Prometheus后可以在AlertManager的webui上查看告警信息:http://IP:Port
设置报警规则
详见prometheus-rules.yml