前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入理解kubernetes(k8s)网络原理之四-pod流量控制

深入理解kubernetes(k8s)网络原理之四-pod流量控制

原创
作者头像
一生无聊
修改2021-09-01 18:04:34
3.7K0
修改2021-09-01 18:04:34
举报

深入理解kubernetes(k8s)网络原理之四-pod流量控制

在前面的几篇文章中,我们解决了pod连接主机、pod连接外网、pod与相同节点或不同节点的pod连接、用clusterIP和nodeport的方式访问pod等几个问题,可以说,对于组织pod的网络的每一环都已经完成了。

和CPU、内存这类资源一样,我们肯定希望网络资源对于每个pod来说也是平均分配的,起码能做到每个pod的数据包发送与接收的速度都能控制在一定的范围内,节点的带宽不能被某个pod耗光而影响其它的pod,所以这一章我们来讨论如何控制pod的进出流量速率。

首先我们来看看这回linux给我们准备了哪些工具;

TC(traffic control)

linux自带流量控制框架,这个框架允许用户在数据发送前配置数据包排队规则qdisc(queueing discipline),对流量进行限制或整形,linux的tc只控制发送速率不控制接收速率,当然要控制接收速率也是有办法实现的。

对于限制网卡的发送速率,一般有两种方式:

  1. 第一种是对整个网卡的发送速率进行简单粗暴的限制,例如eth0网卡的发送速率限制100mbit;
  2. 第二种是对网卡发出的流量先进行分类,再分别对每一分类的的速率单独限制,例如访问mysql的流量限制80mbit,访问http服务的流量限制20mbit;

对于第一种方式,我们选择无类别队列,对于第二种方式,我们选择可分类队列。

无类别队列

主要有:

  • pfifo/bfifo(First In First Out):先进先出队列,只需设置队列的长度,pfifo是以数据包的个数为单位,bfifo是以字节数为单位;
  • pfifo_fast:数据包是按照TOS被分配多三个波段里,band0优先级最高,band1次之,band2最低,按优先级从高到低发送,在每个波段里面,使用先进先出规则;
  • tbf(Token Bucket Filter):针对数据字节数进行限制,适合于把流速降低到某个值,但允许短暂突发流量超过设定值,我们限制pod的发送速率主要就用这个队列;
  • red(Random Early Detection):当带宽的占用接近于规定的带宽时,系统会随机地丢弃一些数据包
  • sfq(Stochastic Fairness Queueing):它按照会话为流量进行排序,然后循环发送每个会话的数据包。
  • FQ (Fair Queue):公平队列

在这里我们只介绍下如何创建tbf队列,因为后面主要是使用这个队列来限制pod的发送速率,下面的命令可以控制eth0的发送速率为100mbit:

tc qdisc add dev eth0 root tbf rate 100mbit burst 100mbit limit 100mbit

## rate:传输速率
## burst:桶的大小
## limit:确定最多有多少数据(byte)在队列中等待令牌

流量控制单位kbps:千字节/秒 mbps:兆字节/秒 kbit:KBits/秒 mbit:MBits/秒 bps:字节数/秒(如果不带单位,则默认单位是这个)

可分类队列

不同于无分类队列,可分类队列使用时步骤稍微复杂些,产要分三步:

  1. 给网卡创建一个队列
  2. 创建队列的分类,在各个分类里可以设置不同的流量策略
  3. 创建分类规则,把流量导到第二步创建的分类

可分类队列主要有:

  • cbq(class based queueing:基于类别排队):没用过,自行google
  • htb(hierarchy token bucket:层级令牌桶):看下面的示例

示例配置:访问mysql的速率限制80mbit,访问http服务的速率限制20mbit

  • 创建htb队列:
tc qdisc add dev eth0 root handle 1: htb default 11 ##使用htb队列,默认流量去分类11
  • 创建队列分类:
tc class add dev eth0 parent 1: classid 1:11 htb rate 80mbit ceil 80mbit  ## 创建分类11,速率限制80mbit
tc class add dev eth0 parent 1: classid 1:12 htb rate 20mbit ceil 20mbit  ## 创建分类12,速率限制20mbit
  • 引导流量到分类:
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 3306 0xffff flowid 1:11  ## 所有访问3306端口的流量导到分类11中
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 80 0xffff flowid 1:12  ## 所有访问80端口的流量导到分类12中

也可以通过来源IP+目标端口来引导流量

tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 192.168.6.160 match ip dport 23 oxffff flowid 1:11

也可以通过数据标记来引导流量:

iptables -t mangle -A POSTROUTING -d 10.244.1.10 -j MARK –set-mark 100 ## 用iptables给数据打标记
tc filter add dev eth0 protocol ip parent 1:0 prio 2 handle 100 fw flowid 1:11  ## 标记了100的数据包引导到分类11中

pod的流量限制

首先还是在测试的主机上创建一个pod:(笔者的测试主机IP为192.168.6.160)

ip netns add pod-a
ip link add eth0 type veth peer name veth-pod-a
ip link set eth0 netns pod-a
ip netns exec pod-a ip addr add 192.168.10.10/24 dev eth0
ip netns exec pod-a ip link set eth0 up
ip netns exec pod-a ip route add default via 169.254.10.24 dev eth0 onlink
ip link set veth-pod-a up
echo 1 > /proc/sys/net/ipv4/conf/veth-pod-a/proxy_arp
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -I FORWARD -s 192.168.0.0/16 -d 192.168.0.0/16 -j ACCEPT
ip route add 192.168.10.10 dev veth-pod-a scope link

然后在主机上安装iperf3:

yum install iperf3

在pod-a中启动服务端:

ip netns exec pod-a iperf3 -s

再开一个终端,测试一下限速前的速度:

iperf3 -c 192.168.10.10 -i 1 -t 10

Connecting to host 192.168.10.10, port 5201
[  5] local 192.168.6.160 port 50768 connected to 192.168.10.10 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  8.19 GBytes  70.3 Gbits/sec    0   1.35 MBytes
[  5]   1.00-2.00   sec  8.27 GBytes  71.0 Gbits/sec    0   1.35 MBytes
[  5]   2.00-3.00   sec  8.18 GBytes  70.3 Gbits/sec    0   1.35 MBytes
[  5]   3.00-4.00   sec  8.36 GBytes  71.8 Gbits/sec    0   1.35 MBytes
[  5]   4.00-5.00   sec  8.46 GBytes  72.7 Gbits/sec    0   1.35 MBytes
[  5]   5.00-6.00   sec  8.40 GBytes  72.2 Gbits/sec    0   1.35 MBytes
[  5]   6.00-7.00   sec  8.50 GBytes  73.1 Gbits/sec    0   1.42 MBytes
[  5]   7.00-8.00   sec  8.25 GBytes  70.8 Gbits/sec    0   1.57 MBytes
[  5]   8.00-9.00   sec  8.53 GBytes  73.2 Gbits/sec    0   1.57 MBytes
[  5]   9.00-10.00  sec  8.45 GBytes  72.6 Gbits/sec    0   1.57 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  83.6 GBytes  71.8 Gbits/sec    0             sender
[  5]   0.00-10.04  sec  83.6 GBytes  71.5 Gbits/sec                  receiver
iperf Done.

可以看到,限制前的速度为71G/秒;

因为pod使用的是veth网卡对,所以我们可以通过主机端的网卡,达到控制pod流量的目的;

控制pod的接收速率

我们控制主机网卡veth-pod-a的发送速率,就相当于是控制pod的接收速率,我们限制pod的接收速率为100mbit:

tc qdisc add dev veth-pod-a root tbf rate 100mbit burst 100mbit limit 100mbit

此时再测:

iperf3 -c 192.168.10.10 -i 1 -t 10
 
Connecting to host 192.168.10.10, port 5201
[  5] local 192.168.6.160 port 50626 connected to 192.168.10.10 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  24.9 MBytes   209 Mbits/sec    0    389 KBytes
[  5]   1.00-2.00   sec  11.6 MBytes  97.5 Mbits/sec    0    389 KBytes
[  5]   2.00-3.00   sec  11.6 MBytes  97.5 Mbits/sec    0    389 KBytes
[  5]   3.00-4.00   sec  11.7 MBytes  98.0 Mbits/sec    0    389 KBytes
[  5]   4.00-5.00   sec  10.8 MBytes  90.2 Mbits/sec    0    389 KBytes
[  5]   5.00-6.00   sec  11.7 MBytes  98.0 Mbits/sec    0    389 KBytes
[  5]   6.00-7.00   sec  11.6 MBytes  97.5 Mbits/sec    0    389 KBytes
[  5]   7.00-8.00   sec  11.0 MBytes  92.3 Mbits/sec    0    389 KBytes
[  5]   8.00-9.00   sec  11.6 MBytes  97.5 Mbits/sec    0    389 KBytes
[  5]   9.00-10.00  sec  11.6 MBytes  97.5 Mbits/sec    0    389 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec   128 MBytes   107 Mbits/sec    0             sender
[  5]   0.00-10.05  sec   126 MBytes   105 Mbits/sec                  receiver
iperf Done.

看到限速后的结果为105mbit/秒左右,符合预期

删除接收限速:

tc qdisc del dev veth-pod-a root tbf rate 100mbit burst 100mbit limit 100mbit

控制pod的发包速率

因为linux的tc框架控发不控收,所以我们不能像上面一样,通过控制主机端veth-pod-a网卡的接收速率来控制pod发送速率的目的,但也不是完全没有办法:

在pod内直接限制发送速率

虽然不能在主机端控制pod的发送,但是可以直接在容器里控制,命令和上面的一样,只不过是在pod-a的ns中执行:

ip netns exec pod-a tc qdisc add dev eth0 root tbf rate 100mbit burst 100mbit limit 100mbit

因为是测试从容器发送的速率,所以我们要把iperf3的服务端调整一下,服务端跑在主机上,然后再在容器中进行发送测试:

ip netns exec pod-a iperf3 -c 192.168.6.160 -i 1 -t 10

Connecting to host 192.168.6.160, port 5201
[  5] local 192.168.10.10 port 49224 connected to 192.168.6.160 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  26.6 MBytes   223 Mbits/sec    0    641 KBytes
[  5]   1.00-2.00   sec  11.2 MBytes  94.4 Mbits/sec    0    641 KBytes
[  5]   2.00-3.00   sec  11.2 MBytes  94.4 Mbits/sec    0    641 KBytes
[  5]   3.00-4.00   sec  11.2 MBytes  94.4 Mbits/sec    0    641 KBytes
[  5]   4.00-5.00   sec  11.2 MBytes  94.4 Mbits/sec    0    641 KBytes
[  5]   5.00-6.00   sec  12.5 MBytes   105 Mbits/sec    0    641 KBytes
[  5]   6.00-7.00   sec  11.2 MBytes  94.4 Mbits/sec    0    641 KBytes
[  5]   7.00-8.00   sec  11.2 MBytes  94.4 Mbits/sec    0    641 KBytes
[  5]   8.00-9.00   sec  11.2 MBytes  94.4 Mbits/sec    0    641 KBytes
[  5]   9.00-10.00  sec  11.2 MBytes  94.4 Mbits/sec    0    641 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec   129 MBytes   108 Mbits/sec    0             sender
[  5]   0.00-10.04  sec   126 MBytes   105 Mbits/sec                  receiver
iperf Done.

结果是105mbit/秒,也是符合预期

删除限制:

ip netns exec pod-a tc qdisc del dev eth0 root tbf rate 100mbit burst 100mbit limit 100mbit

通常我们会把容器的命令执行权限开给业务方,这样他们就有可能在容器里把这个速率限制取消,有没有一种办法是在主机端限制pod的发送速率呢?有。

在主机端用ifb网卡的方式限制收包速率

ifb网卡也是linux虚拟网络设备,类似于tun/tap/veth,只不过ifb的原理要简单得多,可以看作是一张只有tc过滤功能的虚拟网卡,而且它不会改变数据包的流向,比如把某张网卡接收流量导给ifb网卡,经过ifb的流量控制过滤后,继续走原网卡的接收流程,发送也是如此;这样我们就可以把pod在主机一端的网卡的接收重定向到ifb网卡,然后通过控制ifb网卡的发送速率,来间接控制pod的发送速率。

首先要确认内核有加载ifb模块,如果没有则加载

modprobe ifb    //需要加载ifb模块

然后创建ifb网卡,并设置发送队列长度为1000:

ip link add ifb0 type ifb
ip link set dev ifb0 up txqueuelen 1000

veth-pod-a的接收重定向到ifb网卡上:

tc qdisc add dev veth-pod-a ingress handle ffff: 
tc filter add dev veth-pod-a parent ffff: protocol ip u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0   //重定向流量到ifb

设置ifb0的发送速率:

tc qdisc add dev ifb0 root tbf rate 100mbit burst 100mbit limit 100mbit

此时再测:

ip netns exec pod-a  iperf3 -c 192.168.6.160 -i 1 -t 10

Connecting to host 192.168.6.160, port 5201
[  5] local 192.168.10.10 port 54762 connected to 192.168.6.160 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  26.5 MBytes   223 Mbits/sec    0    700 KBytes
[  5]   1.00-2.00   sec  11.2 MBytes  94.4 Mbits/sec    0    700 KBytes
[  5]   2.00-3.00   sec  11.2 MBytes  94.4 Mbits/sec    0    700 KBytes
[  5]   3.00-4.00   sec  11.2 MBytes  94.4 Mbits/sec    0    700 KBytes
[  5]   4.00-5.00   sec  12.5 MBytes   105 Mbits/sec    0    700 KBytes
[  5]   5.00-6.00   sec  11.2 MBytes  94.4 Mbits/sec    0    700 KBytes
[  5]   6.00-7.00   sec  11.2 MBytes  94.4 Mbits/sec    0    700 KBytes
[  5]   7.00-8.00   sec  11.2 MBytes  94.4 Mbits/sec    0    700 KBytes
[  5]   8.00-9.00   sec  11.2 MBytes  94.4 Mbits/sec    0    700 KBytes
[  5]   9.00-10.00  sec  11.2 MBytes  94.4 Mbits/sec    0    700 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec   129 MBytes   108 Mbits/sec    0             sender
[  5]   0.00-10.05  sec   126 MBytes   105 Mbits/sec                  receiver
iperf Done.

105mbit/秒,符合预期,改一下速率限制,从100mbit改为200mbit:

tc qdisc replace dev ifb0 root tbf rate 200mbit burst 200mbit limit 200mbit

然后再测:

ip netns exec pod-a  iperf3 -c 192.168.6.160 -i 1 -t 10

Connecting to host 192.168.6.160, port 5201
[  5] local 192.168.10.10 port 56044 connected to 192.168.6.160 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  48.0 MBytes   403 Mbits/sec    0    354 KBytes
[  5]   1.00-2.00   sec  23.1 MBytes   194 Mbits/sec    0    354 KBytes
[  5]   2.00-3.00   sec  23.1 MBytes   194 Mbits/sec    0    354 KBytes
[  5]   3.00-4.00   sec  22.4 MBytes   188 Mbits/sec    0    354 KBytes
[  5]   4.00-5.00   sec  23.1 MBytes   194 Mbits/sec    0    354 KBytes
[  5]   5.00-6.00   sec  22.4 MBytes   188 Mbits/sec    0    354 KBytes
[  5]   6.00-7.00   sec  23.1 MBytes   194 Mbits/sec    0    354 KBytes
[  5]   7.00-8.00   sec  23.1 MBytes   194 Mbits/sec    0    354 KBytes
[  5]   8.00-9.00   sec  22.4 MBytes   188 Mbits/sec    0    354 KBytes
[  5]   9.00-10.00  sec  23.1 MBytes   194 Mbits/sec    0    354 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec   254 MBytes   213 Mbits/sec    0             sender
[  5]   0.00-10.04  sec   252 MBytes   210 Mbits/sec                  receiver
iperf Done.

210mbit/秒,都符合预期。

删除pod-a的发送限速:

tc qdisc del dev veth-pod-a ingress
tc qdisc del dev ifb0 root tbf rate 200mbit burst 200mbit limit 200mbit
ip link del ifb0

OK,pod的流量控制也就说完了。

到目前为止,我们已经解决了一个常规则的k8s的cni需要解决的一切问题,但直到现在,也没见过go语言的影子,所以说k8s都是负责粘合功能的胶水代码,真正工作的是linux系统,与其说学习k8s的网络,不如说在学习linux提供的各种虚拟网络设备及内核协议栈的工作机制。

下一章我们来详细介绍下flannel,然后再动手用go语言撸个cni出来。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 深入理解kubernetes(k8s)网络原理之四-pod流量控制
    • TC(traffic control)
      • 无类别队列
    • pod的流量限制
      • 控制pod的接收速率
      • 控制pod的发包速率
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档