基于ebpf统计docker容器网络流量

本文介绍了如何利用ebpf技术在Linux下统计Docker容器的网络流量,包括L3、L4和L2层面的流量统计方法。在实践中,面临如cgroupID获取、流量统计误差、性能瓶颈等问题,并分享了对应的解决方案,如使用percpu_hash_map以提高并发计数的准确性和性能。

Linux下统计网络带宽的工具很多,但大部分是按网卡、进程、IP维度进行统计。统计容器维度的网络流量,虽然可在容器的namespace查看,或者由cgroup提供的net_cls做标记再配合iptable统计,但使用起来并不方便,这里介绍一种基于ebpf来统计容器维度网络流量的办法,以及使用时遇到的坑。

原理与实现

ebpf的原理不再介绍了,用来做流量统计,最大的优势是十分灵活,能够根据需求对统计项目进行定制。基本原理就是记录内核中各网络相关函数的参数,再按不同维度,如 cgroupID, 进程,IP地址等进行分类,统计,计算,输出。

统计流量

ebpf可通过跟踪内核函数,统计不同层次的网络流量。各层的流量差异主要在于包头,重传,控制报文等等。

L4 TCP 纯数据流量:

上行:kprobe统计  tcp_sendmsg(struct sock *sk,struct msghdr *msg, size_t size)   size 

下行:kprobe统计  tcp_cleanup_rbuf(struct sock *sk, int copied)   copied 

L4 UDP 纯数据流量:

上行:kprobe统计 udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)   len 

下行:kprobe统计 skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)   len 

L3 IP 流量

上行: kprobe统计 ip_output(struct net *net, struct sock *sk, struct sk_buff *skb) skb->len 

下行: kprobe统计 ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,struct net_device *orig_dev) skb->len 

L2 全部网络包流量:

上行:tracepoint统计 net/net_dev_queue   args->len 

下行:tracepoint统计 net/netif_receive_skb  args->len 

获取容器ID

容器基于cgroup创建,容器内的进程生成时其 task_struct->cgroups 会记录其所属cgroup相关信息。ebpf程序运行在内核态,可直接访问进程的task_struct结构,进而获取其cgroupID, 在统计流量时即可方便的区分当前网络流量属于哪个cgroup。

static void fill
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值