本文转自刘斌博文 「如何选择 Docker 监控方案 」 ,文中刘斌从技术的角度深入解释了Docker 监控的数据采集原理,介绍了现有开源的监控方案,以及能够对 Docker 进行监控功能的主流SaaS 服务工具。
刘斌,拥有 10 多年编程经验,曾参与翻译过「第一本 Docker 书」、「GitHub 入门与实践」、「Web应用安全权威指南」等多本技术书籍,主讲过「Docker入门与实践 」课程的Cloud Insight 后台工程师。
作为一名工程师,我们要对自己系统的运行状态了如指掌,有问题及时发现,而不是让用户先发现系统不能使用,打电话找客服,再反映到开发。这个过程很长,而且对工程师来说,是一件比较没面子的事情。
当领导问我们这个月的 MySQL 并发什么情况?slowsql 处于什么水平,平均响应时间超过 200ms 的占比有百分之多少的时候,回答不出来这个问题很尴尬。尽管你工作很辛苦,但是却没有拿得出来的成果。不能因为暂时没出问题就掉以轻心,换位想想,站在领导的角度,领导什么都不干,你提案,他签字,出了谁背锅?
减少宕机时间
扩展和性能管理
资源计划
识别异常事件
故障排除、分析
为什么需要监控我们的服务?其中有一些显而易见的原因,比如需要监控工具来提醒服务故障,比如通过监控服务的负载来决定扩容或缩容。如果机器普遍负载不高,则可以考虑缩减一下机器规模,如果数据库连接经常维持在一个高位水平,则可以考虑一下是否可以进行拆库处理,优化一下架构。
Docker特点
* 像host但不是host * 量大 * 生命周期短
监控盲点(断层)
集群
全方位
* Host(VM) + Services + Containers + Apps
容器为我们的开发和运维带来了更多的方向和可能性,我们也需要一种现代的监控方案来应对这种变化。
随着不可变基础设施概念的普及,云原生应用的兴起,云计算组件已经越来越像搭建玩具的积木块。很多基础设施生命周期变短,不光容器如此,云主机、VM也是。
在云计算出现之前,一台机器可能使用3、5年甚至更长都不需要重装,主机名也不会变,而现在,可能升级一个版本,就要重建一个云主机或重新启动一个容器。监控对象动态变化,而且非常频繁。即使全部实现自动化,也会在负载和复杂度方面带来不利影响。
监控还有助于进行内部统制,尤其是对安全比较敏感的行业,比如证券、银行等。比如服务器受到攻击时,我们需要分析事件,找到根本原因,识别类似攻击,发现未知的被攻击系统,甚至完成取证等工作。
集群的出现,使应用的拓扑结构也变得复杂,不同应用的指标和日志格式也不统一,再加上要考虑应对多租户的问题,这些都给监控带来了新挑战。
传统的监控内包括对主机、网络和应用的监控,但是Docker出现之后,容器这一层很容易被忽略,成为三不管地区,即监控的盲点。
有人说,容器不就是个普通的OS么?装个Zabbix的探针不就行了么?Docker host和Docker 容器都要装 Zabbix探针……其实问题很多。
除了容器内部看到的cpu内存情况不准之外,而且容器生命周期短,重启之后host名,ip地址都会变,所以最好在Docker host上安装Zabbix agent。
如果每个容器都像OS那样监控,则metric数量将会非常巨大,而且这些数据很可能几分钟之后就无效率了(容器已经停止)。容器生命周期短暂,一旦容器结束运行,之前收集的数据将不再有任何意义。
主要的解决方式就是以App或者Service为单位进行监控(通过Tag等方式)。
docker stats
Remote API
伪文件系统
我们可以通过 docker stats 命令或者Remote API以及Linux的伪文件系统来获取容器的性能指标。
使用API的话需要注意一下,那就是不要给Docker daemon带来性能负担。如果你一台主机有200个容器,如果非常频繁的采集系统性能可能会大量占据CPU时间。
最好的方式应该就是使用伪文件系统。如果你只是想通过shell来采集性能数据,则 docker stats 可能是最简单的方式了。
该命令默认以流式方式输出,如果想打印出最新的数据并立即退出,可以使用 no-stream=true 参数。
伪文件系统
CPU、内存、磁盘
网络
文件位置大概在(跟系统有关,这是 Systemd 的例子):
Docker各个版本对这三种方式的支持程度不同,取得metric的方式和详细程度也不同,其中网络metric是在1.6.1之后才能从伪文件系统得到。
内存的很多性能指标都来自于 memory.stat 文件:
前面的不带total的指标,表示的是该cgroup中的process所使用的、不包括子cgroup在内的内存量,而total开头的指标则包含了这些进程使用的包括子cgroup数据。这里我们看到的数据都是一样的,由于这里并没有子cgroup。
两个比较重要的指标:
RSS: resident set size
进程的所有数据堆、栈和memory map等。rss可以进一步分类为active和inactive(active anon and inactive anon)。在内存不够需要swap一部分到磁盘的时候,会选择inactive 的rss进行swap 。
cache memory
缓存到内存中的硬盘文件的大小。比如你读写文件的时候,或者使用mapped file的时候,这个内存都会增加。这类内存也可以再细分为active和inactive的cache,即active file和inactive file。如果系统需要更多内存,则inactive的cache会被优先重用。
cpuacct.stat文件
docker.cpu.system
docker.cpu.user
但是比较遗憾,Docker 不会报告nice,idle和iowait等事件。
System也叫kernel时间,主要是系统调用所耗费的部分,而user则指自己程序的耗费CPU,如果User时间高,则需要好好检查下自己的程序是否有问题,可能需要进行优化。
优先从CFQ(Completely Fair Queuing 完全公平的排队)拿数据,拿不到从这两个文件拿: · blkio.throttle.io service bytes,读写字节数 · blkio.throttle.io_serviced,读写次数
Throttle这个单纯可能有误导,实际这些都不是限制值,而是实际值。每个文件的第一个字段是 major:minor 这样格式的device ID。
iptables
伪文件系统
网络设备接口
Virtual Ethernet
针网络的监控要精确到接口级别,即网卡级别。每个容器在host上都有一个对应的virtual Ethernet,我们可以从这个设备获得tx和rx信息。
不过找到容器在主机上对应的虚拟网卡比较麻烦。这时候可以在宿主机上通过 ip netns 命令从容器内部取得网络数据。
为了在容器所在网络命名空间中执行 ip netns 命令,我们首先需要找到这个容器进程的PID。
或者:
实际上Docker的实现也是从伪文件系统中读取网络metric的:
以上,是不是意犹未尽呢? 下一部分,斌哥将为大家介绍: 《Docker 监控方案的实现》
超好用的监控软件Cloud Insight 不仅能监控 Docker,还能对 Nagios 进行更好的可视化 哦~
阅读更多技术文章,请访问OneAPM 官方博客。