[从零开始学容器] 7.容器的监控

生产环境中监控容器的运行状况十分重要,通过监控我们可以随时掌握容器的运行状态,做到线上隐患和问题早发现,早解决。

虽然传统的物理机和虚拟机监控已经有了比较成熟的监控方案,但是容器的监控面临着更大的挑战,因为容器的行为和本质与传统的虚拟机是不一样的,总的来说,容器具有以下特性:

  • 容器是短期存活的,并且可以动态调度;
  • 容器的本质是进程,而不是一个完整操作系统;
  • 由于容器非常轻量,容器的创建和销毁也会比传统虚拟机更加频繁。

Docker 容器的监控方案有很多,除了 Docker 自带的docker stats命令,还有很多开源的解决方案,例如 sysdig、cAdvisor、Prometheus 等,都是非常优秀的监控工具。

使用 docker stats 命令

使用 Docker 自带的docker stats命令可以很方便地看到主机上所有容器的 CPU、内存、网络 IO、磁盘 IO、PID 等资源的使用情况。

首先使用一下命令创建一个1核2G的nginx容器:

docker run --cpus=1 -m=2g --name=nginx -d nginx

容器启动后,可以使用docker stats命令查看容器的资源使用状态:

docker stats nginx

通过docker stats命令可以看到容器的运行状态如下:

CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
c7dd9d125540        nginx               0.00%               1.395MiB / 2GiB     0.07%               656B / 0B           0B / 17.4kB         2

从容器的运行状态可以看出,docker stats命令确实可以获取并显示 Docker 容器运行状态。但是它的缺点也很明显,因为它只能获取本机数据,无法查看历史监控数据,没有可视化展示面板。

因此,生产环境中我们通常使用另一种容器监控解决方案 cAdvisor。

cAdvisor

cAdvisor 是谷歌开源的一款通用的容器监控解决方案。cAdvisor 不仅可以采集机器上所有运行的容器信息,还提供了基础的查询界面和 HTTP 接口,更方便与外部系统结合。所以,cAdvisor很快成了容器指标监控最常用组件,并且 Kubernetes 也集成了 cAdvisor 作为容器监控指标的默认工具。

cAdvisor 的安装与使用

cAdvisor 官方提供了 Docker 镜像,我们只需要拉取镜像并且启动镜像即可。

首先用命令docker search cadvisor搜索docker hub 中的cadvisor

NAME                        DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
google/cadvisor             DEPRECATED: New images will NOT be pushed.  …   421                                     
google/cadvisor-canary      Analyzes resource usage and performance char…   23                                      [OK]
budry/cadvisor-arm          cAdvisor docker image build for ARM devices …   10                                      
axibase/cadvisor            cAdvisor for ATSD                               5                                       [OK]
braingamer/cadvisor-arm     cAdvisor build for arm (Raspberry Pi)           3 

选择google/cadvisor,使用命令docker pull google/cadvisor拉取镜像

再使用以下命令启动cAdvisor:

docker run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --volume=/dev/disk/:/dev/disk:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  --privileged \
  --device=/dev/kmsg \
  google/cadvisor

如果没有问题,cAdvisor已经启动,可以通过http://host:8080访问到监控页面,如下图所示。
cAdvisor监控页面

使用cAdvisor查看容器监控

如果你想要查看主机上运行的容器资源使用情况,可以访问 http://host:8080/docker/,这个页面会列出 Docker 的基本信息和运行的容器情况,如下图所示。
主机容器监控

监控原理

我们知道 Docker 是基于 Namespace、Cgroups 和联合文件系统实现的。其中 Cgroups 不仅可以用于容器资源的限制,还可以提供容器的资源使用率。无论何种监控方案的实现,底层数据都来源于 Cgroups。

Cgroups 的工作目录为/sys/fs/cgroup/sys/fs/cgroup目录下包含了 Cgroups 的所有内容。Cgroups包含很多子系统,可以用来对不同的资源进行限制。例如对CPU、内存、PID、磁盘 IO等资源进行限制和监控。

为了更详细的了解 Cgroups 的子系统,我们通过 ls -l命令查看/sys/fs/cgroup文件夹,可以看到很多目录:

total 0
drwxr-xr-x. 5 root root  0 Nov 30 11:07 blkio
lrwxrwxrwx. 1 root root 11 Nov 30 11:07 cpu -> cpu,cpuacct
lrwxrwxrwx. 1 root root 11 Nov 30 11:07 cpuacct -> cpu,cpuacct
drwxr-xr-x. 5 root root  0 Nov 30 11:07 cpu,cpuacct
drwxr-xr-x. 3 root root  0 Nov 30 11:07 cpuset
drwxr-xr-x. 5 root root  0 Nov 30 11:07 devices
drwxr-xr-x. 3 root root  0 Nov 30 11:07 freezer
drwxr-xr-x. 3 root root  0 Nov 30 11:07 hugetlb
drwxr-xr-x. 5 root root  0 Nov 30 11:07 memory
lrwxrwxrwx. 1 root root 16 Nov 30 11:07 net_cls -> net_cls,net_prio
drwxr-xr-x. 3 root root  0 Nov 30 11:07 net_cls,net_prio
lrwxrwxrwx. 1 root root 16 Nov 30 11:07 net_prio -> net_cls,net_prio
drwxr-xr-x. 3 root root  0 Nov 30 11:07 perf_event
drwxr-xr-x. 5 root root  0 Nov 30 11:07 pids
drwxr-xr-x. 5 root root  0 Nov 30 11:07 systemd

这些目录代表了 Cgroups 的子系统,Docker 会在每一个 Cgroups 子系统下创建 docker 文件夹。

监控系统是如何获取容器的内存限制的?

下面我们以 memory 子系统(memory 子系统是Cgroups 众多子系统的一个,主要用来限制内存使用,Cgroups 会在第十课时详细讲解)为例,讲解一下监控组件是如何获取到容器的资源限制和使用状态的(即容器的内存限制)。

我们首先在主机上使用以下命令启动一个资源限制为 1 核 2G 的 nginx 容器:

docker run --name=nginx --cpus=1 -m=2g --name=nginx  -d nginx

## 记录ID
242cff20c5d804c7d32f3779046abf3c460b0fadc4c0ed2895e91ca271d68547

容器启动后,我们通过命令行的输出可以得到容器的 ID,同时 Docker 会在/sys/fs/cgroup/memory/docker目录下以容器 ID 为名称创建对应的文件夹。

242cff20c5d804c7d32f3779046abf3c460b0fadc4c0ed2895e91ca271d68547  memory.max_usage_in_bytes
7d8786780f1cba1ec40a452e103c5ca11c3826203452aefbc9f8d08306ada012  memory.memsw.failcnt
cgroup.clone_children                                             memory.memsw.limit_in_bytes
cgroup.event_control                                              memory.memsw.max_usage_in_bytes
cgroup.procs                                                      memory.memsw.usage_in_bytes
memory.failcnt                                                    memory.move_charge_at_immigrate
memory.force_empty                                                memory.numa_stat
memory.kmem.failcnt                                               memory.oom_control
memory.kmem.limit_in_bytes                                        memory.pressure_level
memory.kmem.max_usage_in_bytes                                    memory.soft_limit_in_bytes
memory.kmem.slabinfo                                              memory.stat
memory.kmem.tcp.failcnt                                           memory.swappiness
memory.kmem.tcp.limit_in_bytes                                    memory.usage_in_bytes
memory.kmem.tcp.max_usage_in_bytes                                memory.use_hierarchy
memory.kmem.tcp.usage_in_bytes                                    notify_on_release
memory.kmem.usage_in_bytes                                        tasks
memory.limit_in_bytes

可以看到 Docker 已经创建了以容器 ID 为名称的目录,我们再使用 ls 命令查看一下该目录的内容:

[root@centeros ~]# ls /sys/fs/cgroup/memory/docker/242cff20c5d804c7d32f3779046abf3c460b0fadc4c0ed2895e91ca271d68547/
cgroup.clone_children           memory.kmem.tcp.max_usage_in_bytes  memory.oom_control
cgroup.event_control            memory.kmem.tcp.usage_in_bytes      memory.pressure_level
cgroup.procs                    memory.kmem.usage_in_bytes          memory.soft_limit_in_bytes
memory.failcnt                  memory.limit_in_bytes               memory.stat
memory.force_empty              memory.max_usage_in_bytes           memory.swappiness
memory.kmem.failcnt             memory.memsw.failcnt                memory.usage_in_bytes
memory.kmem.limit_in_bytes      memory.memsw.limit_in_bytes         memory.use_hierarchy
memory.kmem.max_usage_in_bytes  memory.memsw.max_usage_in_bytes     notify_on_release
memory.kmem.slabinfo            memory.memsw.usage_in_bytes         tasks
memory.kmem.tcp.failcnt         memory.move_charge_at_immigrate
memory.kmem.tcp.limit_in_bytes  memory.numa_stat

由上可以看到,容器 ID 的目录下有很多文件,其中 memory.limit_in_bytes 文件代表该容器内存限制大小,单位为 byte,我们使用 cat 命令(cat 命令可以查看文件内容)查看一下文件内容:

cat /sys/fs/cgroup/memory/docker/242cff20c5d804c7d32f3779046abf3c460b0fadc4c0ed2895e91ca271d68547/memory.limit_in_bytes 
# 2147483648

这里可以看到memory.limit_in_bytes 的值为2147483648,转换单位后正好为 2G,符合我们启动容器时的内存限制 2G。

通过 memory 子系统的例子,我们可以知道监控组件通过读取 memory.limit_in_bytes 文件即可获取到容器内存的限制值。了解完容器的内存限制我们来了解一下容器的内存使用情况。

监控系统是如何获取容器的内存使用状态的?

内存使用情况存放在 memory.usage_in_bytes 文件里,同样我们也使用 cat 命令查看一下文件内容:

[root@centeros ~]# cat /sys/fs/cgroup/memory/docker/242cff20c5d804c7d32f3779046abf3c460b0fadc4c0ed2895e91ca271d68547/memory.usage_in_bytes 
1482752

网络的监控数据来源是从 /proc/{PID}/net/dev 目录下读取的,其中 PID 为容器在主机上的进程 ID。下面我们首先使用 docker inspect 命令查看一下上面启动的 nginx 容器的 PID,命令如下:

docker inspect nginx |grep Pid

###
"Pid": 23516,
"PidMode": "",
"PidsLimit": null,

可以看到容器的 PID 为 23516,使用 cat 命令查看一下 /proc/23516/net/dev 的内容:

[root@centeros ~]# cat  /proc/23516/net/dev
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
  eth0:     656       8    0    0    0     0          0         0        0       0    0    0    0     0       0          0
    lo:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0

/proc/23516/net/dev 文件记录了该容器里每一个网卡的流量接收和发送情况,以及错误数、丢包数等信息。可见容器的网络监控数据都是定时从这里读取并展示的。

容器的监控原理其实就是定时读取 Linux 主机上相关的文件并展示给用户。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值