腾讯云容器网络 vpc 对比 vxlan 性能测试

前言

在腾讯云基于VPC(虚拟私有网络)的CVM上使用k8s集群,有两种方式:

  • 使用腾讯云官方容器服务CCS
  • 自己搭建k8s集群

使用腾讯云官方容器服务CCS时, 会使用专有的VPC容器网络, 节点上会给容器分配一个跟VPC CIDR不重叠的容器网段(用户可配置),由CCS负责向VPC网络注册容器网段的路由,容器之间,容器跟节点之间,在用户看来都是直接路由的。

自己搭建k8s集群的话, 常用的容器网络方案是vxlan。

为了弄清楚这两种网络方案下, 容器网络的性能情况,笔者设计并执行了一个简单的对比测试, 对比了吞吐量和时延。

本文不介绍vxlan和vpc网络原理,只呈现一个可复现的详细测试流程,并附上典型测试结果。 只关心测试结果的话,直接看最后一节。

测试流程简介

通过腾讯云容器服务(CCS)创建一个两节点的集群。

通过CCS(或kubectl)创建两个POD, 分布在两个节点上。这两个POD使用的是VPC容器网络。后面简称这两个POD为VPC POD。

通过flannel给两个节点分配另一个虚拟网段,并创建vxlan设备。通过本地docker run命令在两个节点个运行一个docker container, 这两个docker container使用的是flannel管理的vxlan虚拟网络,后面简称这两个容器为vxlan容器

测试容器到容器(c2c)的网络性能对比

在两个VPC POD间运行qperf测试(走的是VPC容器网络), 在两个vxlan 容器之间运行qperf测试(走的是vxlan网络), 然后进行对比。

测试容器到其他节点(c2n)的网络性能对比

从节点二的VPC POD和vxlan容器分别访问节点一, 通过qperf测试性能对比。

关于测试流程的问题

如何屏蔽母机网络负载的影响?

测试使用的节点是CVM, 不可避免收到母机上其他CVM的影响。 为了尽量排除这一影响, 让两个网络下的qperf测试,在同样两台CVM节点上,先后进行(间隔在一分钟之内)。

为了排除两次测试收到母机网络负载的波动影响,每间隔半小时,重复执行一遍对比测试,测试多次。最后取平均值来对比。

为什么不分别创建一个CCS 集群和一个使用flannel网络插件的k8s集群来对比?

参考上一问题的答案。

第一步 申请一个包含两个节点的容器集群

首先创建一个VPC(虚拟私有网络)

https://console.cloud.tencent.com/vpc

CIDR选择 172.31.0.0/16

创建一个k8s集群

https://console.cloud.tencent.com/ccs/cluster

容器网络CIDR选择 10.0.0.0/14

节点配置选择1核CPU, 1G内存

操作系统选择Ubuntu 16.04 64位

等几分钟,两个节点的状态为“健康”以后,说明节点和集群都已经初始化完成了。

两个节点分配到的IP分别为(后面分别记为节点一和节点二):

  • 节点一 172.31.0.5
  • 节点二 172.31.0.16

检查集群的状态

查看节点的内网IP和状态

root@VM-0-5-ubuntu:~# kubectl get nodes
NAME          STATUS    AGE       VERSION
172.31.0.16   Ready     14d       v1.7.8-qcloud
172.31.0.5    Ready     12d       v1.7.8-qcloud

查看CCS(腾讯云容器服务)给每个节点分配的容器网段

# kubectl get node/172.31.0.5  -o jsonpath={.spec.podCIDR}
10.0.1.0/24

kubectl get node/172.31.0.16  -o jsonpath={.spec.podCIDR}
10.0.0.0/24

第二步 安装和配置flannel

在节点上下载flannel

wget https://github.com/coreos/flannel/releases/download/v0.9.1/flannel-v0.9.1-linux-amd64.tar.gz
tar -xzf flannel-v0.9.1-linux-amd64.tar.gz

搭建etcd集群

为了简单,只在节点172.31.0.5上安装和运行etcd:

apt install etcd
systemctl start etcd

这样两个节点上都可以通过 http://172.31.0.5:4001 来访问这个只有一个实例的etcd集群

往etcd配置flannel网络

etcdctl --endpoint http://172.31.0.5:4001 set /flannel/net/config '{"NetWork":"192.168.0.0/16","SubnetLen": 24, "Backend": {"Type": "vxlan"}}'

在两个节点上启动flanneld

./flanneld -etcd-endpoints=http://172.31.0.5:4001 -etcd-prefix=/flannel/net -iface=eth0 &

查看etcd数据可以看到两个节点上的flanneld各自分配到的网段:

# etcdctl --endpoint http://172.31.0.5:4001 ls /flannel/net/subnets          
/flannel/net/subnets/192.168.24.0-24
/flannel/net/subnets/192.168.81.0-24

# etcdctl --endpoint http://172.31.0.5:4001 get /flannel/net/subnets/192.168.24.0-24
{"PublicIP":"172.31.0.5","BackendType":"vxlan","BackendData":{"VtepMAC":"6a:7d:68:63:b4:d1"}}

# etcdctl --endpoint http://172.31.0.5:4001 get /flannel/net/subnets/192.168.81.0-24
{"PublicIP":"172.31.0.16","BackendType":"vxlan","BackendData":{"VtepMAC":"7e:f8:6a:92:eb:a8"}}

flanneld还会在本地生成一个文件/run/flannel/subnet.env。例如在节点172.31.0.5上:

# cat /run/flannel/subnet.env
FLANNEL_NETWORK=192.168.0.0/16
FLANNEL_SUBNET=192.168.24.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false

修改dockerd启动参数

停止dockerd

systemctl stop dockerd

修改/usr/lib/systemd/system/dockerd.service, 如下所示,增加"EnvironmentFile=-/run/flannel/subnet.env", 并修改ExecStart定义

EnvironmentFile=-/run/flannel/subnet.env
ExecStart=/usr/bin/dockerd ${LOG_LEVEL} --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU} ${STORAGE_DRIVER} ${REGISTRY_MIRROR}

重新启动dockerd

systemctl start dockerd

第三步 运行两个使用VPC容器网络的POD

通过kubectl create -f命令创建一个deployment。 所用yaml文件内容如下:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    qcloud-app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      qcloud-app: nginx
  template:
    metadata:
      labels:
        qcloud-app: nginx
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "qcloud-app"
                    operator: In
                    values: 
                    - nginx
              topologyKey: "kubernetes.io/hostname"
      containers:
      - image: nginx:alpine
        imagePullPolicy: Always
        name: nginx
      imagePullSecrets:
      - name: qcloudregistrykey
      restartPolicy: Always

这个yaml文件中通过podAntiAffinity来确保两个POD被调度到两个不同的节点。

(这一步也可以通过控制台来完成: https://console.cloud.tencent.com/ccs/service)

然后检查pod状态

# kubectl get pod -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP          NODE
nginx-2438677318-d9jv7   1/1       Running   0          3m        10.0.1.10   172.31.0.5
nginx-2438677318-jc4b1   1/1       Running   0          3m        10.0.0.26   172.31.0.16

可以看到,两个POD分布在两个节点, IP分别为10.0.1.10 和 10.0.1.26, 属于之前配置的VPC容器网络10.0.0.0/14。

第四步 运行两个使用flannel网络的容器(后面简称flannel容器)

docker run -d nginx:alpine

第五步 获取四个POD/容器的pid和IP

获取POD和vxlan容器的IP。 以节点一上的VPC POD为例:

# kubectl get pod/nginx-2438677318-d9jv7 -o jsonpath={.status.containerStatuses[0].containerID}
docker://a1173da42e8b395a1b72e9ffe9dad43a135826e32dedc9202acc717d63b21967

# docker inspect --format '{{.State.Pid}}' a1173da42e8b395a1
17694

最终两个VPC POD和vxlan容器的IP, pid如下表所示:

节点

POD

容器

容器IP

pid

172.31.0.5

nginx-2438677318-d9jv7

a1173da42e8b

10.0.1.11

17694

172.31.0.5

---

8b610711dc45

192.168.24.2

28611

172.31.0.16

nginx-2438677318-jc4b1

461b98c72697

10.0.1.30

6512

172.31.0.16

---

5a56b09429b

192.168.81.2

18172

第六步 运行qperf测试

安装qperf

ubuntu下安装qperf:

wget https://www.openfabrics.org/downloads/qperf/qperf-0.4.9.tar.gz
tar -xzvf qperf-0.4.9.tar.gz
cd qperf-0.4.9
/config
make

centos下直接yum install qperf 即可

在节点一上启动三个qperf server

在host, VPC POD, vxlan容器三个不同的网络namespace中启动qperf server。

1) host网络

qperf &

2) VPC POD

# 其中17694是节点一上VPC POD的pid
nsenter -t 17694 -n qperf &

3) vxlan容器

# 其中28611是节点一上vxlan容器的pid
nsenter -t 28611 -n qperf &

测试两个VPC POD之间的网络性能

在172.31.0.16上,运行

# 其中10.0.1.11是远端POD的IP
nsenter -t 6512 -n qperf 10.0.1.11 -oo msg_size:64:64K:*2 -vu -vvc tcp_bw tcp_lat > vpc-c2c.raw

测试两个vxlan容器之间的网络性能

在172.31.0.16上,运行

# 其中192.168.24.2是远端vxlan容器的IP
nsenter -t 18172 -n qperf 192.168.24.2 -oo msg_size:64:64K:*2 -vu -vvc tcp_bw tcp_lat > vxlan-c2c.raw

测试VPC POD访问另一个节点

在172.31.0.16上,运行

nsenter -t 6512 -n qperf 172.31.0.5 -oo msg_size:64:64K:*2 -vu -vvc tcp_bw tcp_lat > vpc-c2n.raw

测试vxlan容器访问另一个节点

在172.31.0.16上,运行

nsenter -t 18172 -n qperf 172.31.0.5 -oo msg_size:64:64K:*2 -vu -vvc tcp_bw tcp_lat > vxlan-c2n.raw

测试节点二访问节点一

qperf 172.31.0.5 -oo msg_size:64:64K:*2 -vu -vvc tcp_bw tcp_lat > n2n.raw

处理原始数据生成对比图表

下载qperf-plot工具: https://github.com/honkiko/qperf-plot

把原始qperf报告转换为plot数据文件

cat vxlan-c2c.raw | ./qperf-parse.py > vxlan-c2c
cat vpc-c2c.raw | ./qperf-parse.py > vpc-c2c
cat vxlan-c2n.raw | ./qperf-parse.py > vxlan-c2n
cat vpc-c2n.raw | ./qperf-parse.py > vpc-c2n
cat n2n.raw | ./qperf-parse.py > n2n

生成对比图表

gnuplot -c qperf-plot.plt vpc-c2c vxlan-c2c

会在当前目录生成bw-[vpc-c2c]-vs-[vxlan-c2c].png和lat-[vpc-c2c]-vs-[vxlan-c2c].png

gnuplot -c qperf-plot.plt vpc-c2n vxlan-c2n

会在当前目录生成bw-[vpc-c2n]-vs-[vxlan-c2n].png和lat-[vpc-c2n]-vs-[vxlan-c2n].png

测试环境和结果

节点配置: 腾讯云北京一区 标准型S1 1核1G

节点操作系统: Ubuntu 16.04.1 LTS

节点内核版本: 4.10.0-32-generic

qperf版本: qperf 0.4.9

flannel版本: v0.9.1

容器到容器(c2c)

以上5个qperf测试(vpc-c2c, vxlan-c2c, vpc-c2n, vxlan-c2n, n2n),重复5轮, 每轮之间间隔两分钟。5轮测试结果取平均值。结果如下。

容器到容器的对比

加入节点到节点(n2n)的曲线(图中紫色曲线)作为参照

容器到其他节点的对比

加入节点到节点(n2n)的曲线(图中紫色曲线)作为参照

CPU占用率的对比

吞吐率方面,VPC容器网络要比vxlan高40%, 是不是消耗了特别多的CPU资源换来的呢。为此笔者专门做了一个对比测试。

两种网络模式下,使用固定msg_size=1440, 执行qperf tcp_bw测试, 时长60秒, 同时通过mpstat每秒采集一次CPU利用率指标。 重复执行10轮测试,取平均值。结果如下:

同样的msg_size, 吞吐率大40%, 也意味着同样时间的发包数量多40%, 从而send系统调用次数也多40%。 因此mpstat统计出来的VPC容器网络下sys要高。 vxlan的封包解包是在软中断中执行的,所以即使多发送了40%的报文, VPC容器网络模式下, mpstat统计出来的softirq CPU占用反而还比vxlan要低。

进行吞吐率测试时, usr和sys这两个CPU消耗,肯定是随着每秒发包数量(pps, PacketPerSecond)增加而增加的。但是softirq的消耗对比, 则体现出了vxlan模式下额外的封包解包带来的额外CPU开销。

结论

容器到容器,VPC容器网络是直接路由,无论是吞吐率还是时延,都很接近节点到节点通信的性能;

而vxlan需要多一层隧道封装,因此带来了很大的开销。

吞吐率方面,VPC容器网络要比vxlan高40%,时延要小5%~10%。

容器到其他节点, VPC容器网络仍然是直接路由,而vxlan容器则是通过iptables规则实现的NAT来完成通信,因此性能损耗不算大。但是不得不面对NAT带来的各种复杂性。

因此,想要在腾讯云上使用k8s, 建议还是选择官方CCS。官方CCS由专业团队来提供保障和服务,在网络性能上也有巨大的优势。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏全华班

springcloud学习手册-API Gateway (API网关)

导读 | API Gateway (API网关) ? 一、为什么服务之间需要使用API Gateway (API网关)呢? 引用「Chris Richardso...

3186
来自专栏程序猿DD

Spring Cloud构建微服务架构:服务网关(基础)【Dalston版】

通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了。比如下图所示: ? 我们使用Spring Clou...

1947
来自专栏Linyb极客之路

SpringCloud微服务(原理篇)

微服务的模式和形式我在前面已经进行部分的提及,但是一直没落实到技术层面,这段时间我也在次研究了一下微服务,下面我先贴出SpringCloud整体涉及的结构

754
来自专栏哲学驱动设计

WCF 中 TCP 与 HTTP 性能简单比较

在使用 WCF 时,为了更好地进行调试,我都选择了 HTTP 协议进行数据传输。最近项目对性能要求比较高,所以就换成了使用 TCP 协议。并对二者的性能进行了一...

1876
来自专栏Linux驱动

IIC接口下的24C02 驱动分析

本节来学习IIC接口下的24C02 驱动分析,本节学完后,再来学习Linux下如何使用IIC操作24C02 1.I2C通信介绍 它是由数据线SDA和时钟SCL构...

1909
来自专栏北京马哥教育

LVS详解及基于LVS实现web服务器负载均衡

前言 LVS(Linux Virtual Server)Linux虚拟服务器,是一个虚拟的服务器集群系统。本项目在1998年5月由章文嵩博士成立,是中国国内...

3404
来自专栏大魏分享(微信公众号:david-share)

微服务架构模式解析 | 大魏学微服务系列第一篇

微服务架构( Microservice Architecture MSA)环境的定义特征是:模块化服务是单独部署的、每个模块化服务可以独立于其他服务,或同一服务...

893
来自专栏Aloys的开发之路

Python第三方常用工具、库、框架等

       Python ImagingLibrary(PIL):它提供强大的图形处理的能力,并提供广泛的图形文件格式支持,该库能进行图形格式的转换、打印和显...

33210
来自专栏后端技术探索

几种web并行化编程实现

当网站做到一定规模的时候,web单个页面需要涉及到的业务也会越来越多,每个页面可能会向后端发起几个、十几个甚至几十个请求。对于java、python之类的支持多...

1003
来自专栏性能与架构

realtime 库和框架概览

Websocket 库 现在大部分新版浏览器、Android、IOS 都已经支持了 Websocket,直接使用 Websocket 问题不大,那么 Webso...

3347

扫码关注云+社区