当前位置: 首页 > 科技观察

如何做一个容器监控系统,就看这篇文章

时间:2023-03-14 17:32:07 科技观察

随着线上服务全面docker化,docker容器的监控就显得非常重要了。SA的监控系统是对物理机的监控。当一台物理机运行多个容器时,我们无法通过监控图区分每个容器的资源使用情况。为了更好的监控容器的运行状态,更重要的是收集后续容器动态调度算法所需的大量运行时数据,经调研,基于CAdvisor+InfluxDB+Grafana搭建了这套容器监控系统。一、容器监控方案的选择在研究容器监控系统的时候,其实有很多选择,比如docker自带的dockerstats命令,Scout,DataDog,SysdigCloud,SensuMonitoringFramework,CAdvisor等。通过dockerstats命令,可以轻松查看当前主机上所有容器的CPU、内存、网络流量数据。但是dockerstats命令的缺点是它只统计了当前宿主机的所有容器,而且得到的监控数据是实时的,没有地方存放,也没有告警功能。Scout(链接:https://scoutapp.com/)、SysdigCloud、DataDog都提供了比较完善的服务,但都是托管服务,并且收费,所以不考虑。SensuMonitoringFramework(链接:https://sensu.io/)高度集成且免费,但部署过于复杂。最后,我们选择了CAdvisor作为容器监控工具。CAdvisor由Google出品,产品开源,监控指标完备,易于部署,官方docker镜像。缺点是集成度不高,本地默认只保存2分钟的数据。但是经过研究发现可以加入InfluxDB来存储数据,可以连接Grafana显示图表,构建容器监控系统也比较方便。数据采集??和图表展示有效,对系统性能几乎没有影响。2、容器资源监控——CAdvisor2.1部署运行CAdvisor是一个容器资源监控工具,包括对容器内存、CPU、网络IO、磁盘IO等的监控,并提供WEB页面查看实时运行情况容器的状态。CAdvisor默认存储2分钟的数据,并且只针对单台物理机。但是CAdvisor提供了很多数据集成接口,支持集成InfluxDB、Redis、Kafka、Elasticsearch等,可以添加相应的配置将监控数据发送到这些数据库中存储。由于CAdvisor已经容器化,部署和运行都非常简单,执行如下命令即可:运行后在浏览器中打开http://ip:8080即可查看宿主机的容器监控数据。2.2集成InfluxDB如前所述,CAdvisor默认只在本地保存最近2分钟的数据。为了持久化存储数据,统一采集和展示监控数据,需要将数据存储在InfluxDB中。InfluxDB是一个时间序列数据库,专门用来存储时间序列相关的数据,非常适合存储CAdvisor数据。而且CAdvisor本身已经提供了InfluxDB的集成方式,可以在启动容器的时候指定配置。我们使用管理容器来管理CAdvisor,修改后的启动配置如下。主要指定存储引擎为InfluxDB,指定InfluxDB的HTTPAPI地址(这里使用自建DNS的域名influxdb.service.consul,避免暴露对外端口),以及对应的数据库和用户名和密码。{"绑定":["/:/rootfs:ro","/var/run:/var/run:rw","/sys:/sys:ro","/home/docker/var/lib/docker/:/var/lib/docker:ro"],"image":"forum-cadvisor","labels":{"type":"cadvisor"},"command":"-docker_only=true-storage_driver=influxdb-storage_driver_db=cadvisor-storage_driver_host=influxdb.service.consul:8086-storage_driver_user=testuser-storage_driver_password=testpwd","tag":"latest","hostname":"cadvisor-{{lan_ip}}"}注意我们使用我创建了自己的forum-cadvisor镜像来替代官方的cadvisor镜像,这是为了修复cadvisor的一些问题,也是基于方便管理的考虑。2.3CAdvisor存在的问题1)运行报错问题在运行最新的CAdvisor容器时,发现容器有如下错误日志:这个问题是由于没有安装findutils工具导致的。2)容器内存数据无法统计。默认情况下,Debian不启用CGroup内存支持。CAdvisor默认无法统计容器内存数据。需要修改GRUB启动参数,修改文件/etc/default/grub,添加如下行:GRUB_CMDLINE_LINUX="cgroup_enable=memory"然后更新grub2重启。3)网络流量监控数据错误问题。CAdvisor上线一段时间后,蜀南发现容器的网络数据与实际情况不符。容器内有多个overlay网络,需要统计容器内所有网卡的流量。于是修改了CAdvisor统计网络流量部分的代码,重新编译了一个版本供在线使用。修改后的代码在这里。最后我们的自定义镜像文件forum-cadvisor.Dockerfile是这样的(src/cadvisor是修改后重新编译的cadvisor可执行文件):2.4CAdvisor原理介绍CAdvisor运行时挂载宿主机根目录和docker根目录等目录,可以从中读取容器的运行时信息。docker的基础技术包括Linuxnamespace、ControlGroup(CGroup)、AUFS等,其中CGroup用于系统资源限制和优先级控制。CGroup的内容存放在宿主机的/sys/fs/cgroup/目录下。CGroup包括多个子系统,如blkio、cpu、内存、网络IO等对块设备的限制。Docker在CGroup中的各个子系统中创建docker目录,CAdvisor在运行时挂载主机根目录和/sys目录,以便CAdvisor读取容器的资源使用记录。比如你可以看到当前时刻容器b1f257的CPU使用率统计如下。CGroup详细介绍可以参见DOCKER基础技术:LINUXCGROUP(链接https://coolshell.cn/articles/17049.html)#cat/sys/fs/cgroup/cpu/docker/b1f25723c5c3a17df5026cb60e1d1e1600feb293911362328bd17f671802dd31/cpuacct.statuser95191system5028而容器网络流量CAdvisor它是从/proc/PID/net/dev读取的。比如上面容器b1f257进程在宿主机上的PID是6748,可以看到容器内所有网卡的收发流量和错误号。CAdvisor会定时读取对应目录下的数据,并定时发送到指定的存储引擎进行存储,而本地会默认存储最近2分钟的数据,并提供UI界面供查看。#cat/proc/6748/net/devInter-|Receive|Transmitface|bytespacketserrsdropfifoframecompressedmulticast|bytespacketserrsdropfifocollscarriercompressedeth0:626631451200000022787292000000eth1:0000000000000000lo:59268055601000000592680556010000003、容器监控数据存储-InfluxDBInfluxDB(链接:https://docs.influxdata.com/influxdb/v1.3/)是一个开源的分布式时序数据库,使用GO语言开发。特别适用于时间序列数据的存储。CAdvisor收集的容器监控数据存储在InfluxDB中,CAdvisor本身提供了InfluxDB支持,集成起来非常方便。由于所有线上服务都是docker化的,我们也选择使用容器来运行InfluxDB,通过容器管理系统统一管理。容器运行时的核心配置如下。主要是挂载数据库目录,配置consul服务注册。这样,由于CAdvisor和InfluxDB在同一个overlay子网,所以不需要对外开放端口。CAdvisor直接通过influxdb.service.consul:8086连接InfluxDB。为了存储CAdvisor的数据,需要提前创建一个数据库,并配置好用户名、密码和相关权限。InfluxDB提供了一套influxCLI,与mysql客户端非常相似。此外,InfluxDB的数据库操作语言InfluxQL与SQL语法基本一致。进入InfluxDB容器,运行以下命令创建数据库和用户密码并授权。#influxConnectedtohttp://localhost:8086version1.3.5InfluxDBshellversion:1.3.5>createdatabasecadvisor##创建数据库cadvisor>showdatabasesname:databasesname----_internalcadvisor>CREATEUSERtestuserWITHPASSWORD'testpwd'##创建用户并设置密码>GRANTALLPRIVILEGESONcadvisorTOtestuser##授权数据库到Designateduser>CREATERETENTIONPOLICY"cadvisor_retention"ON"cadvisor"DURATION30dREPLICATION1DEFAULT##创建默认的数据保留策略,设置保存时间为30天,副本设置为1次,配置成功后可以看到CAdvisor会自动创建通过InfluxDB的HTTPAPI获取数据表。并将数据发送到InfluxDB进行存储。3.2InfluxDB的重要概念Influxdb有一些重要的概念:数据库、时间戳、字段键、字段值、字段集、标签键、标签值、标签集、度量、保留策略、系列、点。这里简单说明一下:database:数据库,比如cadvisor之前创建的数据库。InfluxDB不是CRUD数据库,更像是CR-ud数据库,它优先考虑添加和读取数据的性能,而不是更新和删除数据。timestamp:时间戳,因为InfluxDB是一个时间序列数据库,所以在它的数据中有一个名为time的列,用来存储记录的生成时间。例如,rx_bytes中的时间列存储时间戳。fields:包括fieldkey,fieldvalue,fieldset几个概念。fieldkey就是字段名,在rx_bytes表中,字段名就是value。fieldvalue为字段值,如17858781633、1359398等。fieldset为字段集合,由fieldkey和fieldvalue组成。例如rx_bytes中设置的字段如下:value=17858781633valuetagkey和tagvalue。标签在InfluxDB中是可选的,但标签是有索引的。如果该字段在查询中经常使用,建议将其设置为标签而不是字段。标签相当于传统数据库中的索引列。retentionpolicy:数据保留策略,cadvisor的保留策略为cadvisor_retention,保存30天,副本为1。一个数据库可以有多个保留策略。measurement:类似于传统数据的表格,是字段、标签、时间列的集合。系列:共享相同保留策略、测量和标记集的数据集合。3.3InfluxDB的特点作为一个时序数据库,InfluxDB相对于传统数据库有很多特点,比如一些独特的特性和连续查询功能。有关InfluxDB的更多详细信息,请参阅官方文档。特色函数:有一些聚合函数比如FILL()用于填充数据,INTEGRAL()用于计算一个字段覆盖的表面积,SPREAD()用于计算一个表中最大值和最小值的差值,STDDEV()用于计算一个字段的标准差,MEAN()计算平均值,MEDIAN()计算中位数,SAMPLE()函数用于随机抽样,DERIVATIVE()计算数据变异率等。连续查询:InfluxDB独有的连续查询功能,可以周期性的减少采样,将原数据库中的数据在减少采样后存储到指定的新数据库或新数据表中,这对于历史数据统计特别有用。4、容器监控数据可视化——Grafana通过CAdvisor收集容器监控数据,存储在InfluxDB中。然后是数据可视化的问题。毕竟可视化图表可以很方便的快速看出容器的一些问题。图表显示我选择了Grafana。Grafana是一个开源的数据监控分析可视化平台,支持多种数据源配置(支持的数据源包括InfluxDB、MySQL、Elasticsearch、OpenTSDB、Graphite等)和丰富的插件和模板功能,支持图表权限控制和告警.Grafana也是以容器模式运行的。容器启动配置如下,主要是挂载grafana数据和日志目录,设置管理员密码,并开放8888端口作为grafana的访问端口:启动后可以使用http://IP:8888/页面访问配置数据源,示例如下:配置数据源后,可以添加Panel实现数据可视化。Grafana的图表功能非常强大,在配置数据查询语句时也非常智能。会自动提示数据源、数据表、数据字段,InfluxDB的所有功能都进行了分类,可以直接选择配置。需要注意的一点是,在配置字节类型的数据时(比如网卡接收流量rx_bytes和内存使用memory_usage),单位要选择数据(IEC)类别。5.总结使用CAdvisor+InfluxDB+Grafana搭建容器资源监控系统是可行的,也比较简单。这三个组件都是以容器的形式运行的,这也符合我们所有在线服务都是容器的理念。目前,监控系统已全面上线,运行正常,数据可视化效果良好。这些数据除了用于可视化监控外,还将用于系统异常检测算法和容器智能调度算法。