Kubernetes开源监控体系搭建试用及后续方案设计
关于kubernetes的监控体系,笔者带着两个问题对其进行了一定的思考和调研,一是k8s原生开源体系的监控方案是如何设计,搭建和使用的?二是针对笔者公司现有监控体系情况,如何做到整合使用,如何合并演进?(笔者公司现状是物理机、虚拟机、以及docker swarm容器上的应用环境,均采用的openfalcon解决方案,并且与其他devops平台已经深度连动)
带着以上两个问题,笔者希望通过本文进行梳理、整理和总结,大概包括以下几个内容:
原生设计
部署搭建
监控效果
分析总结
1、原生设计
对于原生监控设计,笔者主要参考官方文档Tools for Monitoring Resources,还有github上的design-proposals文档kubernetes/community,重点是design文档里面的下面这张图。看起来,图中的core metrics pipeline和monitoring pipeline,应该是分别对应官方文档中的Resource metrics pipeline和Full metrics pipelines。
PS:这个图比较老了,里面少画了一个kube-state-metrics,它是一个全局的服务,可以通过kubernetes api来获取集群的各种信息以及metrics-server提供的实时监控数据,见后文有说
可以看到,这张图里左上角的dashboard、CLI、initial Res. /vert autosc.(一堆组件,具体可以看下monitoring_architecture.md#infrastore的说明,总之是会利用监控历史数据的组件)和左下角的HPA controller(Horizontal Pod Autoscaler,水平扩容,更依赖监控实时数据的组件)为监控体系的最终受益者,他们通过监控数据来进行分析、展现和决策。同时,这两类组件,都会接收两类pipeline的监控数据,core system metrics和 non-core(custom) system metrics。
其中core system metrics是由metrics-server提供,包括container/pod/node的cpu和mem实时数据(metrics-server其实也是通过kubelet获取的监控数据,参考core-metrics-pipeline),metrics-server需要单独部署,部署过程非常简单,只要apply一下yaml文件即可,下面讲部署搭建过程,具体再说。
non-core(custom) system metrics,我们选择试用Prometheus这个主流方案,这个方案的理念主要是通过coreos/prometheus-operator实现Prometheus监控平台与k8s平台操作的无缝衔接,使得一些Prometheus的监控配置,可以通过k8s平台的一些操作得以实现,避免更多的学习和操作成本,实现更好的连动性和一致性。它的设计思路可以通过这个prometheus-operator/design文档了解,主要是定义了4类自定义资源CRD:Prometheus,ServiceMonitor,Alertmanager,PrometheusRule,分别对应Prometheus监控本身,监控的service对象,告警系统本身,监控规则。通过这种方式,保证了监控使用者,几乎不需要直接操作Prometheus的监控配置,仅通过k8s的管理机制,即实现了监控的配置管理。这个思路还是很不错的,xxx-operator貌似也是coreos对于k8s社区支持的一类解决方案,官网上可以看到的有两个比较成型的,一个是etcd,一个就是Prometheus。参考文章:Introducing Operators: Putting Operational Knowledge into Software
2、部署搭建
Resource metrics pipeline(core system metrics)
前文提到,直接执行deploy的yaml文件即可,命令如下:
kubectl create -f deploy/1.8+/
当然,因为式谷歌的东西,这里涉及到了一个科学上网的问题,因为k8s.gcr.io的默认镜像库,国内无法访问,所以我fork了一个版本,在k8s 1.12.x对应的metrics-server v0.3.1这个tag上,修改了镜像源地址,改成我上传到阿里云镜像源上的地址。PS:关于如何快速搬运谷歌云的镜像到阿里云,我特别写了一篇文章说明,见链接谷歌k8s.gcr.io镜像快速传入阿里云镜像源的解决方案(需浏览器科学上网)。
fork的github地址:github.com/KevinTHU/met
部署完成后,执行命令确认(metrics-server run了以后稍等一会,马上执行可能会报error: metrics not available yet):
# kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
test-sdn-001001 2975m 6% 37486Mi 58%
test-sdn-001002 3066m 6% 40261Mi 62%
test-sdn-001003 2309m 4% 38396Mi 59%
test-sdn-001005 937m 1% 29332Mi 45%
# kubectl top pod
NAME CPU(cores) MEMORY(bytes)
cephfs1 2m 21Mi
cephfs2 2m 20Mi
cephrbd-dyn-849fbb5d7d-6cm6f 0m 1Mi
curl-5cc7b478b6-9g6wd 0m 1Mi
Full metrics pipelines(non-core system metrics)
部署过程参考文档/prometheus-operator#quickstart,因为我们之前没有装kube-prometheus,所以需要按照文档里面提到的entire monitoring stack的方式去kube-prometheus目录下看安装说明,链接kube-prometheus,正常来讲,线上应该用一个稳定版本tag来安装,但是我们是试验使用,就直接装master了。如果不做定制化处理,直接按照文档中Quickstart安装即可,但是这样安装完,是没有dashboard的,虽然文档中有Access the dashboards的配置说明,但是只是利用kubectl的proxy能力,做了一个本地代理,只能本地登录,所以基本不可用。为此,笔者同样fork了一个版本,在manifests中,对Prometheus,Grafana,Alert Manager的service加入了NodePort配置,使他们可以通过node ip被外部访问(正常来讲,这个修改应该在jsonnet中做,然后生成自定义的manifests,但是笔者出于偷懒,就直接改样例manifests了,想了解怎么用jsonnet自定义配置的,可以看他们的文档)。
github地址:github.com/KevinTHU/pro
部署命令:
kubectl create -f contrib/kube-prometheus/manifests/
#正如文档中Quickstart所说,有时候这个命令需要执行两次,我正好赶上了,第一次报错如下
Error from server (AlreadyExists): error when creating "contrib/kube-prometheus/manifests/prometheus-adapter-apiService.yaml": apiservices.apiregistration.k8s.io "v1beta1.metrics.k8s.io" already exists
[unable to recognize "contrib/kube-prometheus/manifests/0prometheus-operator-serviceMonitor.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/alertmanager-alertmanager.yaml": no matches for kind "Alertmanager" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/alertmanager-serviceMonitor.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/kube-state-metrics-serviceMonitor.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/node-exporter-serviceMonitor.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/prometheus-prometheus.yaml": no matches for kind "Prometheus" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/prometheus-rules.yaml": no matches for kind "PrometheusRule" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/prometheus-serviceMonitor.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/prometheus-serviceMonitorApiserver.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/prometheus-serviceMonitorCoreDNS.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/prometheus-serviceMonitorKubeControllerManager.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/prometheus-serviceMonitorKubeScheduler.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1", unable to recognize "contrib/kube-prometheus/manifests/prometheus-serviceMonitorKubelet.yaml": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1"]
#两个错,一个是v1beta1.metrics.k8s.io已经存在
#一个是ServiceMonitor这个CRD无法识别,感觉是比较多的yaml文件,执行先后顺序带来的问题,但是总之,再执行一次就可以了。
kubectl create -f contrib/kube-prometheus/manifests/
查看结果:
#kubectl get pods -n monitoring
NAME READY STATUS RESTARTS AGE
alertmanager-main-0 2/2 Running 0 3m
alertmanager-main-1 2/2 Running 0 2m
alertmanager-main-2 2/2 Running 0 1m
grafana-7b9578fb4-5zj8z 1/1 Running 0 6m
kube-state-metrics-78bbfc86f8-cxmb5 4/4 Running 0 4m
node-exporter-lmggr 2/2 Running 0 6m
node-exporter-nxmk8 2/2 Running 0 6m
node-exporter-sbf5r 2/2 Running 0 6m
node-exporter-zdljq 2/2 Running 0 6m
node-exporter-zpp9n 2/2 Running 0 6m
prometheus-adapter-5bb448cb99-g4279 1/1 Running 0 6m
prometheus-k8s-0 3/3 Running 1 3m
prometheus-k8s-1 3/3 Running 1 2m
prometheus-operator-c4b75f7cd-gr7xg 1/1 Running 0 6m
访问页面试一下:
#Prometheus
http://$NodeIp:30090
#grafana
http://$NodeIp:30000
#alertmanager
http://$NodeIp:30093
Prometheus的页面,以及监控的服务
可以看到,对于Prometheus自身的组件,以及node节点,还有k8s的一些服务,都自动提供了监控(你会发现,其中scheduler、controller-manager、coredns有服务发现,但是没有监控起来,这是因为Prometheus-operator虽然帮我们配置了他们的ServiceMonitor,但是我们并没有配置他们的service,这个需要我们手动配一下,文档user-guides/cluster-monitoring.md中也有提到如下)
Aside from the kubelet and the API server the other Kubernetes components all run on top of Kubernetes itself. To discover Kubernetes components that run in a Pod, they simply have to be added to a Service
.
Note the Service
manifests for the scheduler and controller-manager are just examples. They may need to be adapted respective to a cluster.
只要按照文档中的方式,配置service,这几个组件就都可以被监控了,这也就是Prometheus-operator起到的效果,如上文说。
本文因为专注于Prometheus与kubernetes的结合,就不详说Prometheus如何使用,但是可以看下这个文档user-guides/running-exporters.md,讲如何配置Prometheus在k8s上的exporter。
另外,也可以了解一下Prometheus默认会监控的一些metrics,需要看kube-state-metrics的文档kube-state-metrics#exposed-metrics,关于kube-state-metrics,上面整体架构图附注中有提到,它可以通过kube-apiserver获取集群的状态信息以及metrics-server暴露的集群资源实时监控信息。是一个针对集群资源监控的很重要的组件。它监控的metrics类别如下(不少):
CronJob Metrics
DaemonSet Metrics
Deployment Metrics
Job Metrics
LimitRange Metrics
Node Metrics
PersistentVolume Metrics
PersistentVolumeClaim Metrics
Pod Metrics
Pod Disruption Budget Metrics
ReplicaSet Metrics
ReplicationController Metrics
ResourceQuota Metrics
Service Metrics
StatefulSet Metrics
Namespace Metrics
Horizontal Pod Autoscaler Metrics
Endpoint Metrics
Secret Metrics
ConfigMap Metrics
3、监控效果
重点看两部分,一个是实时的资源监控数据是否齐全完备,另一个是对kubernetes集群资源监控的操作易用性如何。
实时监控数据
以container的cpu和mem数据为例,内容相对较全,但是数据较底层,可能还需要通过配置rule,再做抽象封装处理。
这里说到rule,我们可以简单记录一下Prometheus的配置使用,页面如下
重点在这两个位置,先说Configuration,它里面主要是配置alert和scrape(监控抓取信息)的一些配置,alert因为我们并不打算用Prometheus的,所以暂时没细研究,但看起来就是用于发现alertmanager,并进行relabel(标签转换)。这里具体说下scrape,可以看到部分配置如下:
scrape_configs:
- job_name: monitoring/alertmanager/0
scrape_interval: 30s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- monitoring
relabel_configs:
- source_labels: [__meta_kubernetes_service_label_alertmanager]
separator: ;
regex: main
replacement: $1
action: keep
- source_labels: [__meta_kubernetes_endpoint_port_name]
separator: ;
regex: web
replacement: $1
action: keep
- source_labels: [__meta_kubernetes_namespace]
separator: ;
regex: (.*)
target_label: namespace
replacement: $1
action: replace
- source_labels: [__meta_kubernetes_endpoint_address_target_kind, __meta_kubernetes_endpoint_address_target_name]
separator: ;
regex: Node;(.*)
target_label: node
replacement: ${1}
action: replace
- source_labels: [__meta_kubernetes_endpoint_address_target_kind, __meta_kubernetes_endpoint_address_target_name]
separator: ;
regex: Pod;(.*)
target_label: pod
replacement: ${1}
action: replace
- source_labels: [__meta_kubernetes_service_name]
separator: ;
regex: (.*)
target_label: service
replacement: $1
action: replace
- source_labels: [__meta_kubernetes_service_name]
separator: ;
regex: (.*)
target_label: job
replacement: ${1}
action: replace
- separator: ;
regex: (.*)
target_label: endpoint
replacement: web
action: replace
可以看到,这里定义了一个抓取对象monitoring/alertmanager/0,并且定义了路径,服务发现方式,下面也对抓取内容中的label设定了relabel的方式(标签转换就是为了方便用户使用,把复杂标签转换成简单一些的),里面有几个针对k8s的重点标签,转换后如下
像上面查看container_cpu_load_average_10s,你会看到label中有service="kubelet",这样我们就知道,这个数据,其实是从kubelet接口抓取到的。
#relabel配置如下
- job_name: monitoring/kubelet/0
honor_labels: true
scrape_interval: 30s
....
relabel_configs:
....
- source_labels: [__meta_kubernetes_service_name]
separator: ;
regex: (.*)
target_label: service
replacement: $1
action: replace
其他的指标,大家可以自己探索一下,这里不多说。
再来看配置中的Rules,这个就是我刚才提到的,如果抓取到的数据太过于底层,可以通过Rules配置来进行修正封装,可以参考一下自带的修正规则,如下图。(另外,Alert告警规则,也可以通过Rules进行配置,这里不多说)
总结一下:实时数据内容还算可以,但是如果与openfalcon的数据做类比的话,还是缺少一些直观性,有一些比较重要的数据,也有缺失,所以实时数据这块如果想用起来,大家应该还是需要针对自己公司需要的监控数据进行定制,但是这块定制从k8s体系做起来可能会相对较难,因为监控数据来自kubelet的内置cadvisor组件部分,很可能需要改动kubelet代码才能实现。这里附openfalcon的监控指标,大家对比下
操作易用性
这里主要以历史数据的查看为例,以内存举例如下,可以直接输入监控指标,有补全提示(这点不错)
如果想再具体指标内某些特定容器的数据,例如筛选特定的机器,特定的监控来源等,需要指定label。
可以看到,加入pod的筛选以后,会显示pod内所有容器的数据,以及总和数据(这点还不错)。
另外,graph当然也是有图的,如下
看起来还可以,能用,如果想再精细化一下,可以去配置grafana,上文提到自带的。
总结:历史数据的查询能力,还是可以的,但是也有一个基于时间序列存储监控数据的通病,就是没办法top,所以这块,如果想要top的话,可能需要把数据转存到ES或者spark里了,这块,根据实际场景而定,没必要都转存。
还是与openfalcon对比一下,graph的查看类似openfalcon的query,grafana类似openfalcon的screen能力(预先配置,集成展示),所以总体来讲,两者对于历史数据的页面查看、易操作性能力,差不太多。
4、分析总结
1)kubernetes集群自身状态监控★★★★★
对于kubernetes集群的状态监控,Prometheus通过调用k8s API,已经原生支持,这点非常不错,有一些k8s dashboard展现一般,或者没有展现的信息,从监控上可以看到,还是不错的。所以,就这一点,这个原生监控系统值得部署使用。评级五星
2)pod和node的实时监控★★★★☆
Prometheus通过调用kubelet实时监控容器信息,通过node-exporter监控node信息,还是相对可以的,当然,如上文说,相比openfalcon,指标的直观性相对差一下,某些重要指标也不好自定义添加,所以评级四星。
3)对于应用服务的监控★★★☆
Prometheus对于应用服务的监控理念是应用暴露metrics接口,然后Prometheus抓取获取信息,这种理念就需要应用端集成相应语言的sdk,对应用有侵入,比较麻烦,相比来说,openfalcon可以通过url监控来实现,就比较简单,当然,我们其实也可以写一个url监控中转agent来做这个事,把非标准的应用探活接口数据转换成标准的prometheus监控接口数据,供Prometheus抓取使用,但是每个应用的探活接口和数据类型可能是不一样的,那针对每个不同应用的agent配置和管理,就比较麻烦了,没有原生支持,不像openfalcon,是能够对各个agent通过页面管理进行配置的,所以这块评级比较低,最多三星。
4)扩展能力★★☆
针对大量的监控信息,一个Prometheus无法满足性能,需要扩展的时候,这种场景,笔者还没有进行测试,不太清楚Prometheus-operator是否能够帮我们自动划分给多个不通的Prometheus进行监控,但是从现在有情况来看,恐怕不能,需要另外有针对性的配置。这点就明显不如Openfalcon了,Openfalcon可以说最擅长的就是扩展能力了,这里不多说,可以看下开源文档即知。
结论:
结合双方优势,后续方案设计:Prometheus与Openfalcon结合
1、Prometheus负责监控k8s集群自身状态
2、Openfalcon通过宿主机agent监控宿主机状态,通过sidecar(Pod内部署两个容器,一个应用容器,一个agent容器,共享进程PID空间,参考文档Share Process Namespace between Containers in a Pod)或者supervisor部署agent,监控容器状态。
3、历史数据查看和监控策略管理均采用Openfalcon的管理机制
4、Top能力通过Openfalcon传数据到ES,进行聚合处理。
作者:Xin He,擅长云计算,关注深度学习
原文:https://zhuanlan.zhihu.com/p/52056165
---END---
K8S培训推荐
Kubernetes线下实战培训,采用3+1新的培训模式(3天线下实战培训,1年内可免费再次参加),资深一线讲师,实操环境实践,现场答疑互动,培训内容覆盖:Docker架构、镜像、数据存储、网络、以及最佳实践。Kubernetes实战内容,Kubernetes设计、Pod、常用对象操作,Kuberentes调度系统、QoS、Helm、网络、存储、CI/CD、日志监控等。<了解更多详情>
北京站、上海站:1月4-6日; 咨询/报名:曹辉/15999647409