查看原文
其他

Kubernetes开源监控体系搭建试用及后续方案设计

Xin He K8S中文社区 2019-12-18


关于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。

https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/monitoring_architecture.md#open-source-monitoring-pipeline
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

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存