转载

Docker Monitor Part2&3

这一部分主要参考的是 这篇

这一部分主要是讲,对于docker容器而言,应该对哪些具体的指标进行监控,以及这些数值应该如何获取到。

docker 在某种程度上可以被认为是轻量级的虚拟机,就像常见的host一样,它会使用CPU,memory,I/O以及网络资源。然而同时docker容器又运行在cgroup中,这又于宿主机有所不同(其实就是某些资源得不到监控,同时又多了一些额外的资源比如throttle限制),你可能不希望采用同样类似的监控指标。

对于docker 而言,主要是通过三种方式获取这些监控数据:Pseudo-files,state command 以及 API。

pseudo-files就是直接通过/sys/fs/cgroup/<容器id>(ubuntu下)这样直接通过读取文件的方式查看相关指标,这样速度最快,但是获取的信息可能不全。对于I/O以及对于network的监控信息可能搜集的不够充分,这也是一个比较根本的方法,应为信息最终都是来自这里。

states command就是直接利用docker states命令来查看相关的信息。

API指的是通过docker states的API来查看相关信息,返回的都是json形式的已经分好类别的数据,这个还是比较方便使用的。

关于性能指标与应用类型

可以参考下在host上运行应用的时候,相关的监控指标与应用类型的划分,参考 这个 这里摘录一点相关的内容:找到性能的瓶颈性能监控的目的,是系统优化的关键,系统由若干子系统组成,修改一个子系统可能会影响到另外一个子系统,优化过程是一个不断循环的过程。通常监控的子系统包括CPU Memory IO Network 几个部分。通常应用可以分为几种类型:IO相关(比如数据库读写服务),CPU相关(比如科学计算程序)。可以根据原文的两个程序的对比明显看出IO相关程序和CPU相关程序在数值指标上的区别。

如何评价一个系统的性能是好还是差?感觉这里的好坏都是相对而言的,由于硬件性能的差别,不同平台下的绝对数值的比较显然意义不大。强烈推荐 这个系列的文章 就像金融专家通过公司的财务报表进行决策一样,能通过这些性能监控数据发现服务的问题,是一个很重要的技能,好多情况下,提供给数据出来是没有用的,事实上确实如此,大部分人都看不懂这些数据是神马意思,需要专业人员做的,就是通过数据,并且利用专业知识,告诉用户,当前你的服务,出了神马问题,这个需要大量的案例积累,事实上也没人愿意看那些旧的历史数据。

Key docker metrics

CPU

Name Description Metric type
user cpu Percent of time that CPU is under direct control of processes Resource: Utilization
system cpu Percent of time that CPU is executing system calls on behalf of processes Resource: Utilization
限制 节流throttling (count) Number of CPU throttling enforcements for a container Resource: Saturation
限制 节流throttling (time) Total time that a container’s CPU usage was throttled Resource: Saturation

其实关于us(用户态使用的时间比)和sy(系统态使员工的cpu时间比)的理解不是那么太直接,可以参考 这个 。当然还有许多更多cpu相关的细节参数。

我们更关注的是,这个指标能说明什么问题:如果容器中的进程执行的速度很慢,那么CPU的数值应该是我们首先要查看的。docker并不像真正的host那样, nice, idle, iowait, or irq CPU time 这些数值,docker是不会记录的。

有几个文件需要留意下,主要是cgroup记录的相关文件,比如ubuntu14.04的系统中进行如下实验: 创建 /sys/fs/cgroup/cpuacct/g1

通常的cpu指标

其实就是创建一个g1的任务在cpuacct(CPU Accounting Controller)的子系统下,之后会自动生成很多文件:

cgroup.clone_children  cgroup.procs  cpuacct.usage         notify_on_releasecgroup.event_control   cpuacct.stat  cpuacct.usage_percpu  tasks

之后 echo $$ > tasks 就是把当前shell进程的pid写入到tasks文件中,这样当前进程的cpu使用情况就受到了cgroups的监控,使用起来很容易。

  • cpuacct.stat 中分为 user 和 system两个数值,就像上面所说的那样,在x86架构下, 这两个数值的单位是10ms 。比如像 这个blog 中实验的那样,大量的系统调用会导致sy很高。
  • cpuacct.usage_percpu可以用来帮助用户发现对于这个进程来说,从启动起来,到目前为止所占用的各个cpu的时间, 这个单位是ns ,这个指标可以帮助用户查看,对于指定的进程,它是否均匀地使用了各个cpu资源。
  • cpuacct.usage 这个数值是总的cpu的使用时间,从进程开始启动开始计算,相当于是之前各个数值的总和。

传统机器常用工具列出来的CPU指标

比如vmstat工具,与cpu相关的指标 如下 ,里面的例子分析得比较好。

r:可运行队列的线程数,这些线程都是可运行状态,只不过 CPU 暂时不可用 b:被 blocked 的进程数,正在等待 IO 请求; us:用户态进程使用CPU的百分比. sy:内核态进程使用CPU的百分比. id:处于空闲的CPU百分比. wa:系统等待IO的CPU时间百分比. st:来自于一个虚拟机偷取的CPU时间的百分比. in(interrupts):被处理过的中断次数. cs(context switch ):系统正在做上下文切换的数目.

要了解上面的相关概念,首先要明白cpu进行资源调度时候的整个流程,以及具体细节,不同指标展示出来的数据就是相关的具体情况。

几个实际案例,有待于继续分析:

$ vmstat 1 r b swpd free buff cache si so bi bo in cs us sy id wa st 5 0 92 185724 735036 2736384 0 0 2 11 0 1 2 0 98 0 0 7 0 92 184980 735044 2736376 0 0 0 124 6682 7806 39 3 58 0 0 6 0 92 184856 735044 2737064 0 0 0 1888 6721 7601 38 5 49 8 0 2 0 92 184732 735044 2737064 0 0 0 0 6549 7525 46 4 50 0 0 3 0 92 183988 735044 2737904 0 0 0 0 6375 7081 45 3 52 0 0 1 0 92 184360 735048 2738156 0 0 0 0 6764 7601 44 4 51 0 0 8 1 92 183368 735048 2738508 0 0 0 1384 6774 8005 42 4 54 0 0

分析: 首先 si so 都是 0,free 也有,说明内存足够,排除内存。再看硬盘,bi bo 都不大,所以 io 似乎不严重,最后剩下 CPU,cs 和 in 都较大,说明 CPU 频于应付上下文切换和中断,而且从 r 的数字来看正在等 CPU 的进程较多,所以猜测服务器上运行的进程较多,CPU 疲于切换进程以及应付中断,猜测瓶颈是 CPU。单从你给的这些数字来看是不够的,还需要根据你服务器配置、环境、应用等来综合考虑。

 $ vmstat 1 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st  4  0    140 2915476 341288 3951700  0    0     0     0 1057  523 19 81  0  0  0  4  0    140 2915724 341296 3951700  0    0     0     0 1048  546 19 81  0  0  0  4  0    140 2915848 341296 3951700  0    0     0     0 1044  514 18 82  0  0  0  4  0    140 2915848 341296 3951700  0    0     0    24 1044  564 20 80  0  0  0  4  0    140 2915848 341296 3951700  0    0     0     0 1060  546 18 82  0  0  0

分析:

interrupts(in)非常高,context switch(cs)比较低,说明这个 CPU 一直在不停的请求资源; system time(sy)一直保持在 80% 以上,而且上下文切换较低(cs),说明某个进程可能一直霸占着 CPU(不断请求资源); run queue(r)刚好在4个。

$ vmstat 1 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 14  0    140 2904316 341912 3952308  0    0     0   460 1106 9593 36 64  1  0  0 17  0    140 2903492 341912 3951780  0    0     0     0 1037 9614 35 65  1  0  0 20  0    140 2902016 341912 3952000  0    0     0     0 1046 9739 35 64  1  0  0 17  0    140 2903904 341912 3951888  0    0     0    76 1044 9879 37 63  0  0  0 16  0    140 2904580 341912 3952108  0    0     0     0 1055 9808 34 65  1  0  0

分析:

context switch(cs)比 interrupts(in)要高得多,说明内核不得不来回切换进程; 进一步观察发现 system time(sy)很高而 user time(us)很低,而且加上高频度的上下文切换(cs),说明正在运行的应用程序调用了大量的系统调用(system call); run queue(r)在14个线程以上,按照这个测试机器的硬件配置(四核),应该保持在12个以内。

限制cpu使用率的指标(Throttling)

当然,使用docker的话,可以对cpu quota进行限制,比如像 官方文档中解释的这样 说的是明明白白,对于完全公平调度器,默认的度量是100,000(单位us),在一个cpu的情况下,把cpu-quota的数值调成50,000则对应的容器就会使用50%的cpu分片时间。对于多个cpu的情况下,可以参考 这个

文档里说的很清楚,通过两个数值(/sys/fs/cgroup/cpu/docker/<容器id>)进行管理

  • cpu.cfs _ quota _ us 表示一个周期之内的可以使用的时间(us)
  • cpu.cfs _ period _ us 表示一个周期的时间长度(us)

初始值是分别是:

cpu.cfs_period_us=100ms cpu.cfs_quota=-1 

quota为任何负值都会使得该进程被置于unconstrained的状态,就是完全由cfs公平调度器来接管,当多个cpu的时候,就把quota设置成为对应period_us的倍数即可,

# echo 1000000 > cpu.cfs_quota_us /* quota = 1000ms */ # echo 500000 > cpu.cfs_period_us /* period = 500ms */

以上就是限制对应group可以使用两个cpu。

其他的相关信息, 官方文档 中说的都很明确了。

关于period的长度,如果period时间设置较长,就会增加burst capacity。要是时间设置较短,就会确保consistent latency response,以牺牲burst capacity为代价

关于被限制的group被限制的次数的相关信息,可以查看cpu.stat文件。

还有很多的方式可以活动cpu的使用情况,比如通过docker的api得到cpu的信息,本质上应该就是把上面的提到的这些文件拼起来返回来,具体的细节在part3中有描述。

Memory

Docker可以返回可用的总的memory总量,以及其使用的memory数量。 具体包括以下几种类型:

Name Description Metric type
Memory Memory usage of a container Resource: Utilization
Rss Non-cache memory for a process (stacks, heaps, etc.) Resource: Utilization
Cache memory Data from disk cached in memory Resource: Utilization
Swap Amount of swap space in use Resource: Saturation

使用到的memory可以被细分为两种类型:

  • RSS(resident set size 驻留集大小?) 表示属于进程的数据,包括stack,heap等等。RSS信息本身又可以被分解成active memory以及inactive memory两个类别(active_anon 以及 inactive_anon)inactive rss memory只有在必要的时候才会被swapp到内存中。

  • cache memory 这个表示被缓存到内存中的,原本存储在disk中的数据。cache也可以被进一步分类为active and inactive memory (active_file, inactive_file)当系统需要内存资源的时候,inactive memory可能被再次回收。

docker也可以给出当前使用的swamp的总数。还有一些有价值的度量指标,比如page faults可能会影响应用的性能以及稳定性。

这里 介绍了docker搜集memory metrics的相关信息。

对于传统的在host上运行着的应用,当出现性能问题的时候,首先会想到的一些metrics就是memory availability 以及 swap 使用量。

直接查看memory.stat的信息就可以获取到很多内存的指标: cat /sys/fs/cgroup/memory/docker/$CONTAINER_ID/memory.stat 其中有一些指标的前面没有带total这些指标不会把sub-cgroups算在内,剩下的那些有 total_ 前缀的度量字段,这些数值把sub-cgroup也包括在内了。

还有一些单独的文件,可以针对性地查看某个指标:

  • cached + rss : memory.usage_in_bytes
  • Total memory used + swap in use memory.memsw.usage_in_bytes
  • 内存使用达到上线的次数 memory.failcnt
  • cgroup 中规定的 内存上限 memory.limit_in_bytes

如果limit_in_bytes是一个很大的数字,那么有可能在启动docker容器的时候,没有加上对应的cgroup限制。

docker 的 官方文档 中介绍了许多metrics的详细信息,比如具体某个指标表示的含义是什么。

磁盘I/O

对每一个块设备,docker 从下面两个指标汇报信息:synchronous versus asynchronous I/O,以及读和写。

Name Description Metric type
I/O serviced Count of I/O operations performed, regardless of size Resource: Utilization
I/O service bytes Bytes read or written by the cgroup Resource: Utilization

获得I/O性能的指标也有多种: 直接通过读取宿主机的文件: /sys/fs/cgroup/blkio/docker/$CONTAINER_ID/ 之后可能有如下的文件: blkio.io_queued_recursive, blkio.io_service_time_recursive, blkio.io_wait_time_recursive 等等。在大部分系统中,通常只有这两个文件的信息是有效的: blkio.throttle.io_service_bytes

Network

就像传统的host一样,docker可以统计network的相关信息,每个指标又可以进一步细分为inbound与outbound两方面。

Name Description Metric type
Bytes Network traffic volume (send/receive) Resource: Utilization
Packets Network packet count (send/receive) Resource: Utilization
Errors (receive) Packets received with errors Resource: Error
Errors (transmit) Errors in packet transmission Resource: Error
Dropped Packets dropped (send/receive) Resource: Error

通过API是最容易的一种得到容器network metrics信息的方式,比如stat api中的关于网络的部分,其中rx表示 received 而 tx 则表示 transmitted。

 "network": {     "rx_bytes": 197942,     "rx_packets": 51,     "rx_errors": 0,     "rx_dropped": 0,     "tx_bytes": 3549,     "tx_packets": 50,     "tx_errors": 0,     "tx_dropped": 0 } 

LinuxSystemPerformanceIntruduction http://www.vpsee.com/2009/11/linux-system-performance-monitoring-introduction/

Linux系统监控(较全面): http://os.51cto.com/art/201012/239886.htm

关于如何搜集valuable的数据: https://www.datadoghq.com/blog/monitoring-101-collecting-data/

cpu数值相关参考:

https://www.kernel.org/doc/Documentation/cgroups/cpuacct.txt

https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Resource_Management_Guide/sec-cpuacct.html

https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt

关于collecting data的一篇 https://www.datadoghq.com/blog/monitoring-101-collecting-data/

正文到此结束
Loading...