DCOS中监控和弹性伸缩方案经验
Posted ilinux_one
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DCOS中监控和弹性伸缩方案经验相关的知识,希望对你有一定的参考价值。
监控的选型
我们的DCOS 主要是面向2种业务形态:互联网应用,NFV组件和相关的数据库。2种不同的业务虽然说都是跑在容器内部,但是其实需要监控的信息和指标都是各不相同。因此在选择监控方案的时候我们更多的考虑了多样性和可定制化方案,同时最重要的是反应速度和自动化的因素 我们的方案需要有告警和自动的弹性伸缩功能来保证业务的可靠性和健壮性。
去年有幸听取了Brian Christner对于容器监控的讲解,所以对他当时提出的cAdvisor+Prometheus+InfluxDB+Grafana 的方案非常感兴趣,也做了一些深入的研究,发现这套方案是非常适合当前的DCOS需求。对于这个方案,我们也并不是照搬照抄,而是结合我们的业务特点作了适当的剪裁。 今天在这里给大家分享以下几点:
- 监控方案的整体架构和部署方案;
- cAdvisor的定制化和监控;
- Prometheus的告警和过滤;
- 修复策略和弹性伸缩;
- 几个最佳实践。
架构
此图是我们DOCS 的监控解决方案架构图,主要有4组服务组成:
- Mesos-Slaves,每个Slave都安装有cAdvisor作为容器服务的监控,在CAdvisor里会有为Prometheus定制化的Exporter来收集信息;
- Monitor-Servers,每个Server都安装有Prometheus和Prometheus Alert Manager来抓取不同cAdvisor集合的数据,并对比数据进行告警;
- Controller-Servers,每个Control节点都有repair service,他们作为集群用来解析告警,匹配规则并触发相关的行为,如弹性伸缩等;
- Marathon和Mesos-Master 集群,负责服务管理和资源调度。
我们暂时没有使用InfluxDB和Grafana,因为公司关注的重点在告警后的快速自动化修复和弹性伸缩,而不是查看历史状态和统计。事实上,没有这两个组件,一切work OK。不过InfluxDB已经在项目日程上,以后有机会再给大家做分享。
我们的DCOS是基于Mesos和Marathon的方式部署,所以cAdvisor、Promethius、alert manager和repair service都是以Marathon的方式启动,并保持long run。所以缺点是cAdvisor都会占用每个mesos-slave 的一定资源。
因为可能有些听众对几个组件不是非常了解,我们在下面的每个部分都会做简单介绍。
CAdvisor
下面介绍一下 cAdvisor,它是一个是谷歌公司用来分析运行中的Docker 容器的资源占用以及性能特性的工具。
cAdvisor部署为一个运行中的daemon,它会收集、聚集、处理并导出运行中容器的信息。这些信息能够包含容器级别的资源隔离参数、资源的历史使用状况、反映资源使用和网络统计数据完整历史状况的柱状图。
cAdvisor的默认监控项 有以下:CPU、Memory、Network、Disk。
这些属性可能可以说明容器的性能,但是或许并不能完全表示用户所关心的服务状态。
我们经常考虑到的指标可能有以下2中情况:
- 一些特殊的统计指标,如CPU占用率,内存占用率, 通常我们可以直接对cAdvisor进行改造,通过计算得到相应的数据。
- 服务自定义的属性,如:从HAProxy或者数据库中取得连接到某个服务的连接数,如果要取这些数据就需要对服务进行改造,对于应用所关心的指标以某种方式发布,可以被cAdvisor截取。
那么这些定制化的开发可以通过以下方式:
对于上述情况1,cAdvisor可以取得相关的数据。比如,CPU的使用率,cAdvisor返回的是数据是每秒钟内CPU使用了多少时间,那么通过计算,可以计算出CPU的占用率。
对于情况2,相对来说,要复杂一些。首先,服务本身需要有API来发布数据。其次,在cAdvisor里需要增加通过该API抓取数据的逻辑。
以HAProxy为例,它通过这样的url:http://x.x.x.x:9090/haproxy?stats;csv;norefresh返回CSV格式的数据。在cAdvisor中解析该数据,提取相关数据,再通过cAdvisor发布。
以下是通过cAdvisor抓取HAProxy的数据后,发布的数据例子:
# HELP container_network_receive_packets_per_second_total_high_result Total receive package per second. # TYPE container_network_receive_packets_per_second_total_high_result gauge container_network_receive_packets_per_second_total_high_result{alert_name="HighRevPackagesAlert",app_id="haproxy",group_id="hssdcos",id="/docker/dockerid",image="linkerrepository/linker_marathon_lb",mesos_task_id="taskid",name="containername",repair_template_id="hssdcos"} 0.13
我们定制化cAdvisor时候,很重要的是对数据的收集,分类和处理,通常遵循以下分组:
- Container Name,用mesos 启动的Container会有 mesos- 的前缀;
- Container Image, 因为通常相同image的处理方式会相同;
- Container Labels,可以根据不同的label 做不同的处理,哪怕他们是相同镜像;
- Container Envs,可以通过Env 来识别不同服务的容器,哪怕他们是相同镜像和Label。
所以来总结一下,cAdvisor定制化开发的目的主要是:
- 抓取自定义的属性;
- 对抓取的数据进行处理和计算;
- 对抓取的数据进行过滤和筛选;
- 发布筛选过的数据,来减轻Prometheus Sever的过滤。
cAdvisor提供了接口与Promethius集成(http://cadvisorhost:8080/metrics),Promethius会定时通过该接口抓取数据。在cAdvisor项目中cadvisor/metrics/prometheus.go实现了上述功能。
Prometheus
还是先普及一下概念,Prometheus不是一个产品,而是产品的组合
Prometheus和其他产品的区别在于,其他工具通常是Push Based,就是Agent 会给Server 发送消息,但是它是问不同的Agent去收集信息,这样有利有弊,好处在于主动抓取可以控制时间,而不是被动收取可能会造成拥塞和攻击。缺点大家都能猜到就是消耗的资源会比被动接受的方式多。
Promethus方案通常由以下组件组成,每个组件负责不同的功能
- Prometheus Server
- Data Exporter
- Prometheus Dashboard
- Alert Manager
每个组件的工作流程图如下
Prometheus Server:主要负责处理和过滤收集来的数据,展示到dashboard,并对比告警规则来控制告警,他自带Dashboard, 虽然比较简单 但是也够看,不过最主要的还是看它的告警(Alert)部分,下面是它的界面 。
Data Exporters:主要负责获取统计的数据,比如获取cAdvisor的数据。 Prometheus 不单只是为了监控容器而存在,它有许多已经开发完的exporters来直接获取服务的数据,具体可以参考
http://prometheus.io/docs/instrumenting/exporters/
当然你也可以通过写customized exporter 以插件形式来获得你自定义的服务数据。
但是分开运行exporters的方式有个不足之处,就是会在一个Server上有很多的进程,管理起来比较麻烦,所以我们推荐用cAdvisor统一处理容器和服务的监控。
Pro DashBoard 是一个额外的插件,整个告警系统没有它也可以正常工作,它主要负责展示Prometheus的数据统计,数据会被记录在数据库中,方便查阅,Prometheus自带的Dashboard,信息也不是很多。Grafana 已经集成 Prometheus,也可以作为Prometheus 的一个展示版。
Alert Manager 是个独立组件,主要负责对Prmetheus的告警进行处理和转发,通常有以下方式 :邮件、pagerduty(IT告警服务)、slack(消息通知平台)、opsgenie(运维告警平台)和WebHook, 我们用的最多是 邮件和web hook 方式(Rest API Call)。这是Alert Manager的界面:
Prometheus 采集的数据通常是以Label分组,可以根据不同的表达式设置告警规则,例如根据镜像类型,或者Container名称,甚至你在cAdvisor发布数据时候自定义的字段和数据持续时间等。 Prometheus Server 会在所有采集的数据中进行规则扫描和匹配,并对符合告警规则的数据进行告警--发送到Alert Manager。
在ALert Manager,你可以对不同告警根据Label进行分组,做出不同的处理. 相同的分组告警也可以避免重复的发送,共享相同规则,比如按照label service分组,service=db 只做邮件和短信,但是service=app的可以直接web hook 弹性伸缩。总体来说 AlertManager 只是个消息转发器,更多的是为了减轻 Prometheus Server的负担。 你也可以设置slience 规则来无视相同的告警,当告警消失的时候,AlertManager 也可以发resolve 信息,告知警告已经结束。
其实把Cadvisor和Prometheus整合在一起工作并不是难点,因为配置是相对简单的。需要大家注意的是cAdvisor的资源使用率,Prometheus的信息抓取频率,和每个Prometheus管理的cAdvisor节点。这些配置可能需要大家在工作中多调试才能找到适合自己DCOS的配置。
我们目前使用的配置是,16G内存的Mesos-slave节点配置一个cAdvisor,每个cAdvisor的内存使用率控制在1G, 每组 Prometheus+AlertManager占用4G Mem的资源,每个Prmetheus 会管理10个Mesos-Slave+cAdvisor的节点信息,抓取频率是1s。
我们遇到的真正难点是如何让cAdvisor发布有效的容器,应用和服务的数据信息,以及如何设置Prometheus的告警规则来应对这些数据信息。 cAdvisor发布数据的时候是带label的,Prometheus 是根据相同label的相同value去决定获取的是不是同一个对象。所以 我们需要保证同一个数据每秒刷新的时候或者变化的时候,对象和label对应的值保持一致性,也就是说不能有数据的变化,cAdvisor发布出去的就是2个对象。这样会导致Prometheus 没办法持续监测到同一个对象来匹配规则。
对于Label的设置和设计,我们的经验是:
- 因为 Prometheus和 Alert Manager 无法直接和容器交互,如果你要把container信息,最后发送给你的Web Hooker 或者邮件,首先记得在cAdvisor取出来放在 Label里 ,比如 AlertName、GroupID、ImageName 等;
- 千万不要把变化的东西当作 label 让cAdvisor 发布,也不要让Prometheus的规则去匹配变化的Label,比如不要设置类似 CPU=50%。 你可以放在Value里,而不是label里;
- 处理告警时候,用label 适当的分组,可以减少告警数量,同时对相同类型的告警进行相同操作的处理;
- 告警的时间间隔很重要,所以对于实时弹性伸缩需求的,我们设置的告警interval 都是0s,其实prometheus的alert manager在这方面感觉做的有一些Bug,希望能够以后的版本会修复这个bug;
修复策略和弹性伸缩
有人或许会问,为什么不用marathon 的health check来做弹性伸缩或者修复,我们这边给出的理由是:
- marathon的health check能够针对的情况太少,没办法满足我们业务各种需求;
- 想让marathon的服务和监控相对解耦,可以做到监控,告警和修复的规则重用;
- 不想marathon 的负载过大,而是用专门的服务 。
所以我们以后会考虑,但是要等marathon的功能足够强大。
那么我们的这个repair Service到底做什么事情呢? repair Service 是基于Go做的开发,主要是:
- 接受来自 Alert Manager的告警并进行过滤;
- 分析告警的内容,并匹配数据库里的修复策略;
- 根据修复策略对marathon的服务进行更新或者弹性伸缩;
- 监听marathon 的event,对修复进度进行跟踪和更新。
就好比是医生的工作一样: 知道什么地方出问题,出的什么问题,开处方治疗问题,最后跟踪问题。
修复策略通常是比较复杂,每家公司可能会根据自己的情况用不同的实现和设计,其实我相信大家的自动弹性伸缩都有自己的方案,只是总结下来要注意以下几点通用经验来定位问题:
- 比对告警应用容器的各种自身信息;
- 比对告警应用容器所在的上下文依赖关系;
- 制定修复操作,以及操作成功和失败的处理办法;
- 尽可能的制定通用的修复策略保证可以使用多种容器和服务。
我们是基于Linker的模型和marathon的JSON,自主研发了规则引擎,这里也给大家推荐一个做规则引擎比较好的工具 http://www.drools.org/
最佳实践
当时Brian Christner 说了一下Docker Monitor的Best Practices,我觉得获益匪浅:
- Label your Containers (key value pair) --label environment="production"
- Set Resource Limits
- Don’t overlert yourself
第一点是很重要的一点,你在启动你的Container的时候,尽量多放信息在Container的Label 或者 env里面,这样能够保证你快速的定位出问题的Container的上下文关系。 有更多的信息,你在处理告警的时候当然会游刃有余。
第二点我相信现在很少有人在启动容器的时候不去set resource limit,无论是用Marathon还是Kubernetes,这点相信大家都做的不错,毕竟资源就是金钱,没有人说会让一个程序有无限的开火权。当初Docker能够火起来,主要也是归功于Cgroups的技术,能做到资源限制,因为Namespace技术很早就有了。
最后一点非常非常重要,因为在实际环境中,出问题的情况会很多,所以一定要对你所要监控的指标进行筛选,剔除你不关心的信息和数据。这样对监控,告警系统是大大的减负,同时也减轻你自己不必要的关注和麻烦。设计和实现方案前多做规划和调研,多关注主要指标,对监控的有非常好的帮助。
Q&A
Q:CPU占用率,内存占用率这些指标为啥要改cAdvisor的代码实现?既然使用了Grafana的话,Grafana本身就有对数据二次加工的能力,比如CPU利用率可以直接通过cAdvisor发送的cpuacct,usage的数据做Derivatives就能取到CPU的利用率了。不知道这块你们是基于什么考虑在cadvisor里去提前算了?
A:首先,我们并没有使用Grafana;其次你说的不错,CPU只是打了一个比方,其实我们计算更多的是网络传输的一些数据,比如收发报的数量,大小,这些都是在我们公司NFV的业务比较常见,这里给大家分享的主要目的是,可以通过cAdvisor 做一些定制化的开发。 我们用cAdvisor的目的主要是 统一信息的收集,并不想用多个监控工具,这样会有点复杂。
Q:请问,每个Prmetheus 会管理10个Mesos-Slave+cAdvisor的节点信息,抓取频率是1s,如何保证在规定时间间隔搜集完所有监控信息,即如何保证监控指标是实时有效的呢?
A:这个结果其实是我们经过反复测量得出来的,是有前提,就是我说的每个Slave的大小其实是有限制的,我们的每个Slave 在8 CPU, 16G内存,这样保证了运行的容器数量是有限制的。我觉得如果容器过多,那么管理10个节点可能就不适合,抓取频率也需要调整。 目前官方没有给出Best Pactice,我们也是经验之谈。 测试下来,我们的配置 基本上没有出现丢失信息的情况。
Q:想问下嘉宾:1、DCOS这套环境是用的社区版?2、方便透露下集群规模么?
A:DCOS的这套环境是我们公司研发的, 但是我们公司和Mesosphere的Open DCOS是合作伙伴,这个消息近期就会宣布。目前我们环境规模是50个mesos-slave 左右。
Q: 请问这个系统本身消耗好资源多少?例如采集CPU用top命令,top本身是消耗很多资源。
A:目前在我们的环境实测下来,cAdvisor的CPU占用率在1~5%; 如果容器非常拥挤的情况下,开销会在10% 一下,我们的cAdvisor是用Marathon启动的,配置的CPU是0.1。
深圳Q:请问每次新增监控纬度时,是否需要同时修改cAdvisor和Prometheus,如何保证通用化?是否考虑过其他的容器监控方案,比如通过FUSE在用户态统计,兼容历史的监控工具?
A:是的, 是需要修改cAdvisor和Prometheus, 这一点也是相对来说比较头疼的部分,我们的主要是通过2方面来做的,第一方面是抽象服务模型来做的,让不同的服务模型的共同部分可以共享我们的监控指标和告警规则。第二是利用灰度升级的方式,对cAdvisor和Prometheus来进行升级,尽量保证服务监控的不中断。正如我说的,提前的规划非常重要。其他方案也有所考虑,但是使用下来还是觉得cAdvisor和Prometheus更加适合自动弹性伸缩。
以上内容根据2016年3月31日晚微信群分享内容整理。分享人忻史,LinkerNetworks 首席架构师。负责Linker DCOS的总体规划和架构设计,负责平台中自动化,监控,网络,弹性伸缩等方案模块,之前任职于HP 企业级服务部门首席技术办公室,有8年云计算经验。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。
转:http://dockone.io/article/1182
以上是关于DCOS中监控和弹性伸缩方案经验的主要内容,如果未能解决你的问题,请参考以下文章