硬核干货——《中小企业 AI 实战指南》免费下载! 了解详情
写点什么

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:471285

评论

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

带你熟悉NLP预训练模型:BERT

华为云开发者联盟

人工智能 华为云 语言模型 华为云开发者联盟

​MES管理系统有哪些强大的功能?

万界星空科技

生产管理系统 mes 云mes 万界星空科技 智能制造业

DAPP节点矿池挖矿系统开发(源码搭建)

l8l259l3365

这些定律,在职场越早知道越好

伤感汤姆布利柏

云小课|HSS对近期Cactus勒索病毒的分析

华为云开发者联盟

安全 华为云 华为云开发者联盟 华为云云小课

Agent应用如何撰写角色指令 ——【Agent】角色指令设计攻略

AI大咚咚

AI agent AI Agent AI原生应用 Agent构建

交易员资管平台

区块链技术

开发第一个Flutter App需要注意什么

FN0

flutter

Kmesh v0.1.0 版本发布

华为云开发者联盟

开发 华为云 华为云开发者联盟 Kmesh

百度营销共拓开放平台全新上线,全链路共建AIGC营销新图景

科技热闻

纽约时报:揭秘美国比特币矿场背后的中国主人

TechubNews

解锁加密货币增长的秘密:通过 Token Explorer 解读市场信号

Footprint Analytics

区块链 Token 代币

团队如何限制合适的在制品(WIP)数量

敏捷开发

项目管理 敏捷开发 看板方法 禅道项目管理软件 在制品限制

美国现货比特币 ETF 在 3 天内突破 100 亿美元:这将如何影响加密市场

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

打破这四点,别再说敏捷无法落地了

敏捷开发

项目管理 Scrum 敏捷开发 敏捷团队 敏捷落地

BLCR:区块链游戏革新,激发无尽策略乐趣!

Footprint Analytics

区块链 区块链游戏 web3游戏 Web3 游戏 BLCR

自动弹性,QPS线性提升|一文读懂云原生数仓AnalyticDB弹性技术原理

阿里云瑶池数据库

数据库 阿里云 数据结构 云原生

IoTeX 研究员:我对 DePIN 赛道发展的十项预测

TechubNews

#Web3 DePIN

基于 Vue3 + Springboot 构建的前端低代码框架

互联网工科生

Vue 低代码 spring-boot JNPF

孙文龙理事长参加第二十一届中国国际软件合作洽谈会主题大会并致辞

开放原子开源基金会

开放原子校源行(北理工站)成功举办,多举措赋能开源人才建设,助力开源生态繁荣发展

开放原子开源基金会

每日一题:LeetCode-468. 验证IP地址

Geek_4z9ami

面试 算法 LeetCode 字符串 IP地址

集力向新 共博未来 | 博科资讯与东集技术达成战略合作

极客天地

带你手把手玩转【RAG】应用!

AI大咚咚

AI AI应用 rag AI原生应用

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