写点什么

Container 及其内部进程监控剖析

  • 2020-02-13
  • 本文字数:2917 字

    阅读完需:约 10 分钟

Container及其内部进程监控剖析

目前市场上的虚拟化技术种类很多,例如 moby(docker)、LXC、RKT 等等。在带来方便应用部署和资源充分利用的好处的同时,如何监控相应 Container 及其内部应用进程成为运维人员不可避免遇到的新情况。UAV.Container 从虚拟化技术的基础原理和 Linux 操作系统的内核特性出发,得到 Container 容器和内部进程的各维度监控数据,使无论是虚拟机或物理机运维人员,还是业务运维人员角度,都能得到合适的监控维度。


虚拟化技术从基础原理上主要是 cgroups、namespace 和 file system 的应用,而操作系统作为 cgroup 和 namespace 根节点,无论在 container 里启动何种应用,从内核角度上来说,肯定在操作系统有其一定的特征和表现形式。我们需要做的就是对这些特征做加工处理,以得到相应的监控数据。


下面我们以 docker 技术举例,其他虚拟化技术类似。

1. Container ID

Container ID 是一个 Container 的唯一标识。从容器监控的角度我们需要能得到该进程在哪个 Container 里运行。在操作系统层面,进程的 cgroup 的挂载情况就能有所体现。如图所示,我们在一个 ID 为 3411554ff684 的 Container 内部跑一个 Tomcat 进程。



由于 Container 的 pid namespace 是操作系统的 pid namespace 的子 namespace,那么该进程在操作系统级也应该有相应的 pid,用 docker top 命令验证一下:



该容器内进程在宿主机上的进程号为 1848。接下来进入/proc/1848/cgroup 下看看该进程的 cgroup 挂载情况



从 cgroup 文件里清楚的显示了实现了该容器的虚拟化技术、Container ID 和此 container 的资源挂载路径,对比一下这里面显示的 Container ID,和创建 Container 时的 ID 完全相同。这也验证了通过扫描宿主机进程的 cgroup 信息可以获得 Container ID。这样就将 pid 和 Container ID 做了关联。

2. CPU

虽然 cgroup 管控了该 cgroup 下所有进程的 CPU 使用情况,但从操作系统的角度上,不论进程是否隶属于某个子 cgroup 下,仍然是共用宿主机的 CPU。所以监控宿主机上该进程的 CPU 就能得到进程的 CPU 监控指标。


Linux 上常用的 CPU 监控命令是 top。top 对 CPU 监控的原理是在 time1 时刻获取 CPU 从启动时的累计总时间 countAll1 和 busy 总时间 countBusy1,再到 time2 时刻获取 CPU 总时间 countAll2 和 busy 总时间 countBusy2,最后用 busy 的时间差值减去总时间的差值得到了在 time1 到 time2 这个时间段内机器 CPU 的占用情况。也就是:


CPU 占用率(%) = (countBusy2 - countBusy1)/(countAll2 - countAll1) * 100


进程同理,在两个时刻分别得到每个进程的 busy 总时间 countProcBusy1 和 countProcBusy2,则得到进程 CPU 占用率:


进程 CPU 占用率(%) = (countProcBusy2 - countProcBusy1)/(countProcAll2 - countProcAll1)*100


宿主机从启动开始的 CPU 总时间片可以从/proc/stat 下获取:



第一行是总的 CPU 使用情况,具体参数的意思:


所以,选择当前为 time1,3 秒后为 time2,countAll = user + nice + system + idle + iowait + irq + softirq + stealstolean + guest + guest_nice。countBusy 为 countAll 减去 idle 的值,这样上面第一个公式的所有需要的值就齐了,可以直接计算。


第二行、第三行是每个逻辑 CPU 的使用情况,这里记下有两个逻辑 CPU,CPU 的逻辑核数与 CPU 显示模式 irix 和 solaris 有关。


接下来是 countProcBusy 的计算,进程的 CPU 时间片位于/proc/$pid/stat 下,如图所示:



这个文件里面体现了很多进程的相关信息。其中第 14、15、16、17 个参数与 CPU 有关。


所以,countProcBusy = utime + stime + cutime + cstime,该值包括其所有线程的 cpu 时间。而 countProcAll2-countProcAll1=3s,通过两个时刻的 countProcBusy 和 countProcAll,进程 CPU 的占用率就能得到了。


其中需要注意的问题有两点:


1).jiffies 实际上指的是内核时钟使用的节拍总数,所以这里的 jiffies 需要换算成秒才能应用上面的除法公式。


2).刚刚我们谈到 CPU 显示模式 irix 和 solaris,简单来说 irix 模式就是机器有 N 个逻辑 CPU,CPU 显示上限就是 N*100%,solaris 模式就是不管机器有多少逻辑 CPU,CPU 显示上限就是 100%,而/proc/$pid/stat 显示的是计算了所有逻辑 CPU 时间的,所以两种显示方式意味着计算方法稍有差异,solaris 模式的结果需要在上面进程 CPU 占用率公式基础之上除以逻辑核数。

3. 内存

进程内存的监控有两个维度的数据:一是物理占用内存大小,二是进程内存占用百分比的大小。


进程内存占用率(%) = 进程物理内存占用大小 / 宿主机总内存大小 * 100


与 CPU 类似,/proc/$pid/status 文件记录了进程物理内存使用情况,其中 VmRSS 即为该进程目前所占实际物理内存的大小。



/proc/meminfo 文件下记录了机器内存占用情况,这个文件很长,截取其中的一部分展示一下,MemTotal 就是宿主机总内存大小:



这样,这个进程的物理内存占用和机器总内存就都得到了,相应的进程内存的占用率也就得到了。

4. 磁盘 IO

磁盘 IO 获取也很简单,/proc/$pid/io 已经帮我们把这个进程的 io 情况记录下来了,但是与 CPU 类似,io 文件里存的也是该进程从启动到现在的 io 总量,那么:


磁盘 I/O(bytes/秒) = (time2 时刻 I/O – time1 时刻 I/O) / (time2 – time1)



其中的 read_bytes 和 write_bytes 分别为该进程从启动到目前为止的读取字节数和写入字节数,分别取 2 个时刻的值,根据上面的公式,就得到了该进程的磁盘 IO。

5. 端口号和连接数

由于 Network Namespace 对网络做了隔离,所以如果进程在 Container 内部运行,该进程的端口信息也应该是进程本身监听的端口号,而不是真正实际对外的端口,而 Container 内外端口的映射机制是由应用的虚拟化技术本身控制的,这就避免不了与实现容器的虚拟化技术打交道了,那么问题就转化成获取容器内进程本身监听的端口了。


/proc/$pid/net/tcp(tcp6,udp,udp6)就对端口号和连接数做了相应的历史记录。这些文件格式都类似,以 tcp6 举例



解释几个关键的 key:


因为 st = 0A 代表 listen,所以从其中挑选出 st = 0A 的数据,取出对应的 inode 号,这里这个 inode 号是 socket 号,则问题转换为了这个进程是否还存在这个 socket 号代表的 socket。在/proc/$pid/fd 下有该进程所有的 fd(file descriptor),截取一段举个例子。



每个文件描述符后面的软链实际上就是打开的文件,以 socket 开头的就是这个进程打开的 socket,在中括号中间的部分就是 socket 号。拿着这个 socket 号和上面 tcp6 里获得的 inode 号做一个匹配,如果对应上,那么 tcp6 里的 st = 0A 的端口就是这个进程监听的。至于容器内外端口的映射,这就需要根据应用的虚拟化技术的映射方法来获取了。连接数计算与端口扫描是同理的,区别只在于需要对 st = 01(establish)进行扫描计数累加。

总结:

  1. 上面的方法将容器内所有进程的 CPU、内存、磁盘 IO、端口号和连接数都拿到了。根据 Container ID 就可以对不同的 Container 的对应数据做加和,就获得了 Container 级的监控数据。

  2. 在容器内的进程是通过在操作系统级别反映出的 pid 和 Container ID 的对应关系来关联的。这样就可以通过读取/proc 下的文件来获取监控数据。


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/178


2020-02-13 21:471011

评论

发布
暂无评论
发现更多内容

支持向量机(SVM)是什么?

小齐写代码

如何评估 RAG 应用的质量?最典型的方法论和评估工具都在这里了

Zilliz

评估 AIGC LLM rag

语音AI小夜灯项目

芯动大师

Allins 官网正式上线,铭文赛道进入 AMM 交易时代

西柚子

Mycat分库分表实时同步到GreatSQL

GreatSQL

数据迁移 greatsql

测试开发 | 神经网络架构与设计:探索人工智能的大脑

测吧(北京)科技有限公司

测试

实施管家式运维:为企业打造 定制化IT支持体系

太乙闲人

IPQ9574 and QCN9274: Explore the WiFi7 MLO feature Test with Wallys DR9274

wallyslilly

qcn9274 ipq9574

【JAVA】AI医疗智能导诊系统源码

源码星辰

Java 源码 智能导诊

极狐GitLab Helm Chart 已上线,玩转云原生极狐GitLab!

极狐GitLab

深入理解左倾红黑树 | 京东物流技术团队

京东科技开发者

什么是DePIN,2024年需要了解的DePIN项目

TechubNews

区块链 DePIN

软件测试/测试开发丨Web端测试—CSS讲解 学习笔记

测试人

软件测试

Allins 官网正式上线,铭文赛道进入 AMM 交易时代

股市老人

Allins 官网上线,标志铭文赛道正式进入 AMM 交易时代

BlockChain先知

解读 $mash 通证 “Fair Launch” 规则,将公平发挥极致

股市老人

shopee虾皮商品详情数据接口(Shopee.item_get)丨shopee虾皮API接口

tbapi

shopee商品详情数据接口 shopee API 虾皮shopee详情数据接口 虾皮商品详情数据接口

监督学习算法详解:模型训练、分类与预测

测吧(北京)科技有限公司

测试

低代码技术:颠覆数据孤岛的技术利器

快乐非自愿限量之名

数据 低代码 数据孤岛

苹果市值一夜蒸发 1071 亿美元;「团结引擎创世版」发布丨 RTE 开发者日报 Vol.118

声网

Allins 官网正式上线,铭文赛道进入 AMM 交易时代

小哈区块

全国范围AOI数据2023年12月更新,共计超过234.5万个(AOI数据更新系列)

Geek_f9782a

2023年12月全国范围POI数据更新《POI数据更新系列》

Geek_f9782a

GIS POI 地理空间数据

TuGraph Analytics交互式图查询:让图所见即所得

TuGraphAnalytics

图分析 图查询 图可视化

Allins 官网正式上线,铭文赛道进入 AMM 交易时代

石头财经

测试开发 | 无监督学习与聚类算法:数据中的潜在结构解析

测吧(北京)科技有限公司

测试

调试技巧 | AI工程化部署

AIWeker

c AI AI工程化部署

Container及其内部进程监控剖析_行业深度_周新宇_InfoQ精选文章