登录
  • 人们都希望被别人需要 却往往事与愿违
  • 没有哪种编程语言能阻止程序员写出糟糕的代码, 不管这种语言的结构有多么好@Larry Flon

使用vnstat获取容器网络流量

编程 Benny小土豆 2623次浏览 2542字 0个评论
文章目录[显示]

背景

在我使用pyrogram重构了YouTube Download之后,bot的SLA从9个6变为6个9,同时也迎来了使用量上的增加。这样的结果是,每天我的服务器都会跑掉100-200G的流量。

使用vnstat获取容器网络流量

(这段统计信息是从docker stats拿到的,为了方便复用,我发布了一个wrapper到pypi,同样也可以go get,代码可以看这里 https://github.com/tgbot-collection/tgbot_ping

于是我就想,我一定要想办法记录这个容器每天究竟跑了多少流量,不能每次都亲自指挥,亲自部署吧。那咋办呢……

宿主机上使用vnstat

在宿主机上使用vnstat,就可以看到本机一共跑了多少流量,不过这个数值通常来讲是会大于YouTube Download的流量的,当然也有一些例外情况,比如容器之间通信,那么自然不会被记录到宿主机的外网网卡。

直接用宿主机的vnstat做参考,对于我的场景也没什么大问题,因为这个bot是单独跑在一台机器上的,没有太多的影响因素。那么如何在容器中执行宿主机上的某个命令呢?

坏消息是,这个恐怕是没办法的。容器的namespace是隔离的,看不到宿主机上的信息。

非想搞呢,在宿主机上跑一个web程序,用于调用vnstat,然后容器访问宿主机的web程序好了……

docker stats

docker stats可以用于获取容器的运行时统计信息,比如CPU、RAM等。

比如在某台机器上,我执行下stats,能看到这样的结果

使用vnstat获取容器网络流量

本质上docker是C/S架构的一个东西,所以其实这东西是有一个REST API的。

对于 docker stats,是这个接口

http://socat:2375/containers/dreamy_hugle/stats?stream=0

哦我预先用了下socat,在实际部署中,我有一个名为socat的容器,专门干这事的。当然这也意味着容器可以控制宿主机上的docker engine,有一定的风险。

socat tcp-listen:2375,fork,reuseaddr unix-connect:/var/run/docker.sock

拿到的响应是json,其中有一段networks

使用vnstat获取容器网络流量

那么我只要去解析这个json,然后定时算diff,这样就可以啦!只不过实现难度 🌟🌟🌟🌟🌟,万一以后想看小时、月的呢,容器重启了怎么办,数据存哪,这代码怎么维护呀……

vnstat

在统计流量这方面,已经有了成熟的vnstat,在容器里怎么就不行了?容器也是能跑很多个进程的啊,我还见过容器跑sshd的呢。

vnstat其实也是个C/S架构的东西,vnstatd负责存储流量信息到SQLite,vnstat用于读取显示信息,还有一个vnstati,能够生成图表。在某些廉价VPS厂商能看到如下简陋的流量图,那么很有可能就是vnstati生成的。

使用vnstat获取容器网络流量

在容器里用vnstat并不复杂,先开启vnstatd,然后再开我们的应用程序。

那么就先搞一段shell脚本,为了避免问题使用绝对路径吧

/usr/sbin/vnstatd -d
/usr/local/bin/python ytdl.py

然后把入口从 python xxx.py改成sh xxx.sh

看进程树是这样子的

使用vnstat获取容器网络流量

需要的时候,写代码调用vnstat就可以了。为了避免干扰,代码中可以用 /usr/bin/vnstat -i eth0 排除其他网卡哦。

一个示例Dockerfile如下,使用了多阶段构建,所以vnstat要安装在运行时而不是构建时:

FROM python:alpine as builder

RUN apk update && apk add  --no-cache tzdata alpine-sdk libffi-dev ca-certificates
ADD requirements.txt /tmp/
RUN pip3 install --user -r /tmp/requirements.txt && rm /tmp/requirements.txt


FROM python:alpine
WORKDIR /ytdlbot
ENV TZ=Asia/Shanghai

RUN apk update && apk add  --no-cache ffmpeg vnstat
COPY --from=builder /root/.local /usr/local
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY . /ytdlbot
RUN echo "/usr/sbin/vnstatd -d;/usr/local/bin/python ytdl.py"> /ytdlbot/start.sh

CMD ["sh", "start.sh"]

需要注意的是,为了避免容器重启后数据丢失,记得做个volume到 /var/lib/vnstat哦。

完美!结果如下图

使用vnstat获取容器网络流量

当然了,在容器中运行多个进程有很多种办法,使用shell脚本是一种,缺点很多,比如进程崩溃了,那shell脚本也没法给守护起来……更好的更优雅的方案就是用supervisor,或者是一些好用的init,那些想用systemd的还是劝您放弃

supervisor可以参考这个配置,会把log重定向到stdout中

[supervisord]
nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
user=root

[program:vnstat]
command=vnstatd -n
autorestart=true

[program:ytdl]
directory=/ytdlbot
command=python ytdl.py
autorestart=true

stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true

总结

我不知道你们是怎么想的,反正我感觉我快要被薅🐰了。

使用vnstat获取容器网络流量

尽管我已经开启了VIP模式,试图通过10G/24h来产生一定威慑效果,但是依旧架不住人多啊🤣

使用vnstat获取容器网络流量

 


文章版权归原作者所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明原作者和本文原始地址:
https://dmesg.app/vnstat-container.html
喜欢 (64)
分享:-)
关于作者:
If you have any further questions, feel free to contact me in English or Chinese.
发表我的评论(代码和日志请使用Pastebin或Gist)
取消评论

                     

去你妹的实名制!

  • 昵称 (必填)
  • 邮箱 (必填,不要邮件提醒可以随便写)
  • 网址 (选填)