大家好,我是Coder哥,最近在交付项目,部署脚本,k8s, docker用的比较多,我发现一个问题,大家对k8s的监控聊的比较多,但是对docker的监控好像兴致不是很高,可能是现在用docker部署整套项目的公司比较少的原因吧。由于自己的项目用docker比较多(穷逼没钱搞k8s),我们今天来聊聊Docker中的监控。
我们从以下几个主题开聊:
- 监控的必要性。
- Docker下命令监控资源
- 可视化监控方案的实施。
- Docker监控的原理。
监控的必要性
答案 监控是必须的
Docker,k8s这些工具的设计初衷就是为了实现自动化运维,自动化的运维包括应用的生命周期管理、应用的监控、流量治理等。哪为什么我们还要对应用进行监控呢?因为Docker,k8s 提供的自动化运维是没有办法对应用的实际运行情况包括cpu、内存的实际使用率、日志等信息进行实时的监控,因此为了监控应用的实际运行情况,我们需要搭建一套对docker,k8s中的应用实行实时监控的平台。
特别是在生产环境中,监控容器的运行状态十分重要,通过监控我们可以随时掌握容器的运行状态,做到线上隐患和问题早发现早处理。
下面我们首先来看下,不借助任何外部工具,如何用 Docker 自带的docker stats
命令实现容器的监控。
Docker命令监控资源
Docker提供了docker stats
命令,可以方便地查看主机上所有容器的资源使用情况,包括CPU、内存、网络IO、磁盘IO和进程ID等。下面我们将进行具体操作。
首先,在主机上使用以下命令启动一个资源限制为1核心、2GB内存的nginx容器:
代码语言:javascript复制$ docker run --cpus=1 -m=2g --name=todocoder-nginx -d todocoder/nginx-vue:v2021.06
容器启动后,可以使用docker stats
命令查看容器的资源使用状态:
$ docker stats todocoder-nginx
通过docker stats
命令可以看到容器的运行状态如下:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
2658df1012de todocoder-nginx 0.00% 1.992MiB / 2GiB 0.10% 3.26kB / 0B 0B / 4.1kB 2
从容器的运行状态可以看出,docker stats命令确实可以获取并显示Docker容器实时的运行状态,类似于系统的top命令。然而,它的缺点也很明显,因为它只能获取本机数据,无法查看历史监控数据,并且没有可视化展示面板。
在生产环境中,如果没有历史记录,也很难发现和排查问题,因此通常会使用可视化监控方案。在Docker中,有许多监控工具可供选择,除了Docker自带的docker stats命令外,还有一些开源解决方案,如sysdig、cAdvisor和Prometheus等,它们都是非常优秀的监控工具。
在生产环境中,我们通常使用cAdvisor作为容器监控解决方案。cAdvisor是一个开源工具,由Google开发和维护。它可以提供对容器的实时监控和性能分析,包括CPU、内存、磁盘、网络等方面的指标。
通过使用cAdvisor,我们可以获得更全面的容器监控数据,并且可以通过其可视化界面和API来查看历史数据、趋势分析和自定义监控。因此,在生产环境中,cAdvisor是一个非常有用的容器监控工具。
可视化监控方案的实施
cAdvisor简介
cAdvisor(Container Advisor)是一个开源的容器监控工具,由Google开发并维护。它可以提供对容器的实时监控和性能分析,包括CPU、内存、磁盘、网络等方面的指标。
要在Docker中使用cAdvisor,可以按照以下步骤进行操作, 首先,确保已经安装了Docker。如果没有安装,请根据您的操作系统和发行版的要求进行安装。
cAdvisor 的安装与使用
下面我们以 cAdvisor 0.47.2 版本为例,演示一下 cAdvisor 的安装与使用。
cAdvisor 官方提供了 Docker 镜像,我们只需要拉取镜像并且启动镜像即可。
由于 cAdvisor 镜像存放在谷歌的 gcr.io 镜像仓库中,国内无法访问到。我把最新版的打好的镜像放在了 Docker Hub。你可以直接使用 docker pull todocoder/cadvisor:v0.47.2 命令从 Docker Hub 拉取。
首先使用以下命令启动 cAdvisor:
代码语言:javascript复制$ docker run
-v=/:/rootfs:ro
-v=/var/run:/var/run:ro
-v=/sys:/sys:ro
-v=/var/lib/docker/:/var/lib/docker:ro
-v=/dev/disk/:/dev/disk:ro
-p=8088:8080
-d=true
--privileged=true
--name=todocoder-cadvisor
todocoder/cadvisor:v0.47.2
上述命令说明:
-v,--volume: 挂载本地目录到镜像内目录: 宿主机目录:容器目录 -p,--publish: 指定端口映射,格式为:主机(宿主)端口:容器端口 -d, --detach: 指定容器在后台运行,默认为 false --privileged=true: 放开容器的权限 --name: todocoder-cadvisor 为容器指定一个名称,名字叫 todocoder-cadvisor ;
可以看到,cAdvisor 已经成功启动,我们可以通过 http://localhost:8088 访问到 cAdvisor 的 Web 界面。
访问 http://localhost:8088/containers/ 地址,在首页可以看到主机的资源使用情况包括CPU、内存、文件系统、网络等资源,如图:
cAdvisor 查看容器监控
如果想要查看Docker容器的使用情况,可以访问 http://localhost:8088/docker/,在这个页面会显示Docker的基本信息和容器的运行情况,如图:
上图中的 Subcontainers 下会列出当前主机上Docker运行的所有容器,点击其中一个容器即可查看该容器的详细运行状态,如下图:
cAdvisor的Web界面提供了容器的实时监控信息,包括CPU使用率、内存使用量、网络流量、磁盘IO等指标。你也可以通过界面上的图表和表格来查看这些指标的历史数据和趋势。
总体来说,使用 cAdvisor 监控容器具有以下特点:
- 可以同时采集物理机和容器的状态;
- 可以展示监控历史数据;
此外,cAdvisor还提供了RESTful API,可以通过API获取容器的监控数据,以便进行自定义的监控和集成。
注意: cAdvisor 这个历史数据只能显示几分钟的,要想跨天甚至跨月级别显示,需要保存数据,并对存储的数据进行可视化,篇幅有限后面我会出一篇文章来专门的来介绍,记得关注一下。
我们了解了cAdvisor的运用及部署,也看到了上面的事实数据,那么这些显示的数据是如何来的呢?接下来我们就来看一下Docker监控的原理:
Docker监控的原理
如果是新学Docker的这里可以先收藏,回头再看,这里需要一定的基础,当然看看混个面熟也有益无害。
监控数据的来源
我们先来简单了解一下Docker的实现原理:
Docker 是基于 Namespace、Cgroups 和文件系统实现的。通过Namespace的技术进行进程资源的隔离,而资源的限制是通过Cgroups来实现的,其中 Cgroups 除了可以用于容器资源的限制,还可以提供容器的资源使用率。所以监控的数据基本都来源于Cgroups。
Cgroups是Linux的特性,它的工作目录在/sys/fs/cgroup
下,并且Cgroups包含很多子系统,可以对不同的资源进行限制。比如CPU、内存、磁盘 IO等资源进行限制和监控。我们可以查看一下:
root@todocoder:/sys/fs/cgroup# ls -l
total 0
dr-xr-xr-x 5 root root 0 Jul 10 09:35 blkio
lrwxrwxrwx 1 root root 11 Jul 10 09:35 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 Jul 10 09:35 cpuacct -> cpu,cpuacct
dr-xr-xr-x 5 root root 0 Jul 10 09:35 cpu,cpuacct
dr-xr-xr-x 4 root root 0 Jul 10 09:35 cpuset
dr-xr-xr-x 5 root root 0 Jul 10 09:35 devices
dr-xr-xr-x 5 root root 0 Jul 10 09:35 freezer
dr-xr-xr-x 4 root root 0 Jul 10 09:35 hugetlb
dr-xr-xr-x 5 root root 0 Jul 10 09:35 memory
lrwxrwxrwx 1 root root 16 Jul 10 09:35 net_cls -> net_cls,net_prio
dr-xr-xr-x 4 root root 0 Jul 10 09:35 net_cls,net_prio
lrwxrwxrwx 1 root root 16 Jul 10 09:35 net_prio -> net_cls,net_prio
dr-xr-xr-x 4 root root 0 Jul 10 09:35 perf_event
dr-xr-xr-x 5 root root 0 Jul 10 09:35 pids
dr-xr-xr-x 2 root root 0 Jul 10 09:35 rdma
dr-xr-xr-x 6 root root 0 Jul 10 09:35 systemd
dr-xr-xr-x 6 root root 0 Jul 10 09:35 unified
上面这些目录可以看做Cgroup要限制的子系统,比如memory, 刚上面我们创建的容器 todocoder-nginx
, 就会在memory目录下创建个 docker目录,并且docker目录下会有 镜像ID的目录,限制资源的数据就在 /sys/fs/cgroup/memory/docker/{容器ID}
下,我们可以验证一下:
# 获取一下我们的容器ID信息
root@todocoder:/sys/fs/cgroup# docker inspect todocoder-nginx | grep Id
"Id": "6b8aa4a8f6fdf57442b7db32e91afbb1ca09b6aece8ba44af349e60baebb061d",
# 查看限制信息
root@todocoder:cd /sys/fs/cgroup/memory/docker/6b8aa4a8f6fdf57442b7db32e91afbb1ca09b6aece8ba44af349e60baebb061d
root@todocoder:ls -l
total 0
-rw-r--r-- 1 root root 0 Jul 19 10:14 cgroup.clone_children
--w--w--w- 1 root root 0 Apr 23 23:07 cgroup.event_control
-rw-r--r-- 1 root root 0 Apr 23 23:06 cgroup.procs
-rw-r--r-- 1 root root 0 Jul 19 10:14 memory.failcnt
--w------- 1 root root 0 Jul 19 10:14 memory.force_empty
-rw-r--r-- 1 root root 0 Jul 19 10:14 memory.kmem.failcnt
-rw-r--r-- 1 root root 0 Jul 19 10:14 memory.kmem.limit_in_bytes
-rw-r--r-- 1 root root 0 Jul 19 10:14 memory.kmem.max_usage_in_bytes
-r--r--r-- 1 root root 0 Jul 19 10:14 memory.kmem.slabinfo
-rw-r--r-- 1 root root 0 Jul 19 10:14 memory.kmem.tcp.failcnt
-rw-r--r-- 1 root root 0 Jul 19 10:14 memory.kmem.tcp.limit_in_bytes
-rw-r--r-- 1 root root 0 Jul 19 10:14 memory.kmem.tcp.max_usage_in_bytes
-r--r--r-- 1 root root 0 Jul 19 10:14 memory.kmem.tcp.usage_in_bytes
-r--r--r-- 1 root root 0 Jul 19 10:14 memory.kmem.usage_in_bytes
-rw-r--r-- 1 root root 0 Jul 19 10:14 memory.limit_in_bytes
-rw-r--r-- 1 root root 0 Jul 19 10:14 memory.max_usage_in_bytes
我们可以看到,容器todocoder-nginx
的 memory 控制信息都在这个目录下。还记得我们运行容器的时候给的内存限制是多少不:
$ docker run --cpus=1 -m=2g --name=todocoder-nginx -d todocoder/nginx-vue:v2021.06
上面的这个是运行命令,我们限制的是 -m=2g
,我们可以验证一下:
cat /sys/fs/cgroup/memory/docker/6b8aa4a8f6fdf57442b7db32e91afbb1ca09b6aece8ba44af349e60baebb061d/memory.limit_in_bytes
2147483648
我们可以看到结果是 2147483648 byte = 2G
。到这里就明白了吧,其实监控也是根据cgroup下的记录来展示的。
那么监控数据要找内存使用的话怎么找呢?
监控是如何获取容器的内存占用
内存占用是在 memory.usage_in_bytes
下
memory.limit_in_bytes: 内存限制大小 memory.usage_in_bytes:内存用了多少
我们可以通过如下命令看一下:
代码语言:javascript复制cat /sys/fs/cgroup/memory/docker/6b8aa4a8f6fdf57442b7db32e91afbb1ca09b6aece8ba44af349e60baebb061d/memory.usage_in_bytes
3216890
可以看到,占用了 3216890 byte = 3.01 M
。
监控的原理其实很简单,就是定时读取 Linux 主机上相关的资源使用文件展示给用户。
结语
其实这里有个坑是,cAdvisor 只能临时存储很短的一段历史数据,如果要按天显示或者按月显示,cAdvisor明显不能胜任,所以这里留个坑,篇幅有限我们后面文章来解答这个问题,记得关注一下。
感谢各位能看到这里,觉得文章有用的话记得关注一下,别忘了点赞收藏哦,最后打个小广告
微信工号搜: TodoCoder 会不定时分享 Java,Go,Docker,k8s等 技术文章,公号无广告,无推荐,纯分享
我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表