前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >深入浅出Kubernetes网络:跨节点网络通信之Flannel

深入浅出Kubernetes网络:跨节点网络通信之Flannel

作者头像
kubernetes中文社区
发布于 2019-06-24 07:40:02
发布于 2019-06-24 07:40:02
2K00
代码可运行
举报
运行总次数:0
代码可运行

曾记得有一位哲人说过:“在云计算当中,计算最基础,存储最重要,网络最复杂”,而PaaS云平台Kubernetes的出现也使得网络的应用场景变得更加复杂多变。本文试图从Kubernetes当中容器跨节点网络通信方案Flannel的实际应用场景出发,带领读者梳理Kubernetes当中容器跨节点网络通信的实现过程以及背后的实现原理。

Kubernetes网络模型

Docker通过VEth虚拟网络设备以及Linux bridge实现了同一台主机上的容器网络通信,再通过iptables进行NAT实现了容器和外部网络的通信。

这对于简单部署的应用已经能够满足网络通信的需求了,但是Kubernetes作为一个容器编排平台,要处理的是生产环境当中高并发大规模的弹性扩展问题,首先要解决的就是整个集群当中所有节点上的容器网络通信问题。

为了解决Kubernetes当中网络通信的问题,Kubernetes作为一个容器编排平台提出了Kubernetes网络模型,但是并没有自己去实现,具体网络通信方案通过网络插件来实现。

其实Kubernetes网络模型当中总共只作了三点要求:

  1. 运行在一个节点当中的Pod能在不经过NAT的情况下跟集群中所有的Pod进行通信
  2. 节点当中的客户端(system daemon、kubelet)能跟该节点当中的所有Pod进行通信
  3. 以host network模式运行在一个节点上的Pod能跟集群中所有的Pod进行通信

从Kubernetes的网络模型我们可以看出来,在Kubernetes当中希望做到的是每一个Pod都有一个在集群当中独一无二的IP,并且可以通过这个IP直接跟集群当中的其他Pod以及节点自身的网络进行通信,一句话概括就是Kubernetes当中希望网络是扁平化的。

针对Kubernetes网络模型也涌现出了许多的实现方案,例如Calico、Flannel、Weave等等,虽然实现原理各有千秋,但都围绕着同一个问题即如何实现Kubernetes当中的扁平网络进行展开。Kubernetes只需要负责编排调度相关的事情,修桥铺路的事情交给相应的网络插件即可。

Flannel简介

Flannel项目为CoreOS团队对Kubernetes网络设计实现的一种三层网络通信方案,安装部署方式可以参考官方示例文档:https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml,故关于Flannel的安装部署部分这里暂时不进行赘述,有兴趣的同学可以参考官方文档进行部署测试。

为了便于理解和说明,以下内容将用一个1(master)+2(work node)的Kubernetes集群进行举例说明。

在安装部署完成之后应该能看到在各个节点上通过DaemonSet的方式运行了一个Flannel的Pod。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# kubectl get daemonset -n kube-system -l app=flannelNAME              DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR                   AGEkube-flannel-ds   3         3         3         3            3           beta.kubernetes.io/arch=amd64   135d[root@10-10-88-192 ~]#[root@10-10-88-192 ~]# kubectl get pod -n kube-system -o wide -l app=flannelNAME                    READY     STATUS    RESTARTS   AGE       IP               NODEkube-flannel-ds-npcxv   1/1       Running   0          2h        172.16.130.164   10-10-88-170kube-flannel-ds-rv8wv   1/1       Running   0          2h        172.16.130.244   10-10-88-192kube-flannel-ds-t5zlv   1/1       Running   0          2h        172.16.130.140   10-10-88-195[root@10-10-88-192 ~]#

每一个Flannel的Pod当中都运行了一个flanneld进程,且flanneld的配置文件以ConfigMap的形式挂载到容器内的/etc/kube-flannel/目录供flanneld使用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# kubectl get cm -n kube-system -l app=flannelNAME               DATA      AGEkube-flannel-cfg   2         137d[root@10-10-88-192 ~]#

Flannel Backend

Flannel通过在每一个节点上启动一个叫flanneld的进程,负责每一个节点上的子网划分,并将相关的配置信息如各个节点的子网网段、外部IP等保存到etcd当中,而具体的网络包转发交给具体的Backend来实现。

flanneld可以在启动的时候通过配置文件来指定不同的Backend来进行网络通信,目前比较成熟的Backend有VXLAN、host-gw以及UDP三种方式,也已经有诸如AWS,GCE and AliVPC这些还在实验阶段的Backend。VXLAN是目前官方最推崇的一种Backend实现方式,host-gw一般用于对网络性能要求比较高的场景,但需要基础架构本身的支持,UDP则一般用于Debug和一些比较老的不支持VXLAN的Linux内核。

这里只展开讲讲最成熟也是最通用的三种Backend网络通信实现流程:

  • UDP
  • VXLAN
  • host-gw

UDP

由于UDP模式相对容易理解,故这里先采用UDP这种Backend模式进行举例说明然后再对其他Backend模式进行展开讲解。

采用UDP模式时需要在flanneld的配置文件当中指定Backend type为UDP,可以通过直接修改flanneld的ConfigMap的方式实现,配置修改完成之后如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# kubectl get cm -n kube-system -o yaml kube-flannel-cfgapiVersion: v1data:  cni-conf.json: |    {      "name": "cbr0",      "type": "flannel",      "delegate": {        "isDefaultGateway": true      }    }  net-conf.json: |    {      "Network": "10.244.0.0/16",      "Backend": {        "Type": "udp"      }    }kind: ConfigMapmetadata:  creationTimestamp: 2018-10-30T08:34:01Z  labels:    app: flannel    tier: node  name: kube-flannel-cfg  namespace: kube-system  resourceVersion: "33718154"  selfLink: /api/v1/namespaces/kube-system/configmaps/kube-flannel-cfg  uid: 8d981eff-dc1e-11e8-8103-fa900126bc00[root@10-10-88-192 ~]#

关键字段为Backend当中的Type字段,采用UDP模式时Backend Port默认为8285,即flanneld的监听端口。

flanneld的ConfigMap更新完成之后delete flannel pod进行配置更新:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# kubectl delete pod -n kube-system -l app=flannelpod "kube-flannel-ds-npcxv" deletedpod "kube-flannel-ds-rv8wv" deletedpod "kube-flannel-ds-t5zlv" deleted[root@10-10-88-192 ~]#

当采用UDP模式时,flanneld进程在启动时会通过打开/dev/net/tun的方式生成一个TUN设备,TUN设备可以简单理解为Linux当中提供的一种内核网络与用户空间(应用程序)通信的一种机制,即应用可以通过直接读写tun设备的方式收发RAW IP包。

flanneld进程启动后通过ip a命令可以发现节点当中已经多了一个叫flannel0的网络接口:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00    inet 127.0.0.1/8 scope host lo       valid_lft forever preferred_lft forever    inet6 ::1/128 scope host       valid_lft forever preferred_lft forever2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000    link/ether fa:90:01:26:bc:00 brd ff:ff:ff:ff:ff:ff    inet 10.10.88.192/24 brd 10.10.88.255 scope global eth0       valid_lft forever preferred_lft forever    inet6 fe80::f890:1ff:fe26:bc00/64 scope link       valid_lft forever preferred_lft forever3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000    link/ether fa:86:b8:79:70:01 brd ff:ff:ff:ff:ff:ff    inet 172.16.130.244/24 brd 172.16.130.255 scope global eth1       valid_lft forever preferred_lft forever    inet6 fe80::f886:b8ff:fe79:7001/64 scope link       valid_lft forever preferred_lft forever4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN    link/ether 02:42:ae:dd:19:83 brd ff:ff:ff:ff:ff:ff    inet 172.17.0.1/16 scope global docker0       valid_lft forever preferred_lft forever5: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN qlen 500    link/none    inet 10.244.0.0/16 scope global flannel0       valid_lft forever preferred_lft forever    inet6 fe80::969a:a8eb:e4da:308b/64 scope link flags 800       valid_lft forever preferred_lft forever6: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1472 qdisc noqueue state UP qlen 1000    link/ether 0a:58:0a:f4:00:01 brd ff:ff:ff:ff:ff:ff    inet 10.244.0.1/24 scope global cni0       valid_lft forever preferred_lft forever    inet6 fe80::3428:a4ff:fe6c:bb77/64 scope link       valid_lft forever preferred_lft forever

细心的同学就会发现此时flannel0这个网络接口上的MTU为1472,相比Kubernetes集群网络接口eth1小了28个字节,为什么呢?

通过可以ip -d link show flannel0可以看到这是一个tun设备:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# ip -d link show flannel05: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN mode DEFAULT qlen 500    link/none  promiscuity 0    tun[root@10-10-88-192 ~]#

通过netstat -ulnp命令可以看到此时flanneld进程监听在8285端口:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# netstat -ulnp | grep flanneldudp        0      0 172.16.130.140:8285     0.0.0.0:*                           2373/flanneld[root@10-10-88-192 ~]#

容器跨节点通信实现流程:

假设在节点A上有容器A(10.244.1.96),在节点B上有容器B(10.244.2.194),此时容器A向容器发送一个ICMP请求报文(ping),我们来逐步分析一下ICMP报文是如何从容器A到达容器B的。

1、容器A当中发出ICMP请求报文,通过IP封装后形式为:10.244.1.96 -> 10.244.2.194,此时通过容器A内的路由表匹配到应该将IP包发送到网关10.244.1.1(cni0网桥)。

完整的帧格式为:

2、此时到达cni0的IP包目的地IP 10.244.2.194匹配到节点A上第一条路由规则(10.244.0.0),内核将RAW IP包发送给flannel0接口。

3、flannel0为tun设备,发送给flannel0接口的RAW IP包(无MAC信息)将被flanneld进程接收到,flanneld进程接收到RAW IP包后在原有的基础上进行UDP封包,UDP封包的形式为:172.16.130.140:src port -> 172.16.130.164:8285。

这里有一个问题就是flanneld怎么知道10.244.2.194这个容器到底是在哪个节点上呢?

flanneld在启动时会将该节点的网络信息通过api-server保存到etcd当中,故在发送报文时可以通过查询etcd得到10.244.2.194这个容器的IP属于host B,且host B的IP为172.16.130.164。

RAW IP包示例:

4、flanneld将封装好的UDP报文经eth1发出,从这里可以看出网络包在通过eth1发出前先是加上了UDP头(8个字节),再然后加上了IP头(20个字节)进行封装,这也是为什么flannel0的MTU要比eth1的MTU小28个字节的原因(防止封装后的以太网帧超过eth1的MTU而在经过eth1时被丢弃)。

此时完整的以太网帧格式为:

5、网络包经节点A和节点B之间的网络连接到达host B。

6、host B收到UDP报文后经Linux内核通过UDP端口号8285将包交给正在监听的应用flanneld。

7、运行在host B当中的flanneld将UDP包解包后得到RAW IP包:10.244.1.96 -> 10.244.2.194。

8、解封后的RAW IP包匹配到host B上的路由规则(10.244.2.0),内核将RAW IP包发送到cni0。

此时的完整的以太网帧格式为:

9、cni0将IP包转发给连接在cni0网桥上的container B,而flanneld在整个过程中主要主要负责两个工作:

  • UDP封包解包
  • 节点上的路由表的动态更新

从上面虚线部分就可以看到container A和container B虽然在物理网络上并没有直接相连,但在逻辑上就好像是处于同一个三层网络当中,这种基于底下的物理网络设备通过Flannel等软件定义网络技术实现的网络我们称之为Overlay网络。

那么上面通过UDP这种Backend实现的网络传输过程有没有问题呢?最明显的问题就是,网络数据包先是通过tun设备从内核当中复制到用户态的应用,然后再由用户态的应用复制到内核,仅一次网络传输就进行了两次用户态和内核态的切换,显然这种效率是不会很高的。那么有没有高效一点的办法呢?当然,最简单的方式就是把封包解包这些事情都交给内核去干好了,事实上Linux内核本身也提供了比较成熟的网络封包解包(隧道传输)实现方案VXLAN,下面我们就来看看通过内核的VXLAN跟flanneld自己通过UDP封装网络包在实现上有什么差别。

VXLAN

VXLAN简介

VXLAN全称Virtual Extensible LAN,是一种虚拟化隧道通信技术,主要是为了突破VLAN的最多4096个子网的数量限制,以满足大规模云计算数据中心的需求。VLAN技术的缺陷是VLAN Header预留的长度只有12 bit,故最多只能支持2的12次方即4096个子网的划分,无法满足云计算场景下主机数量日益增长的需求。当前VXLAN的报文Header内有24 bit,可以支持2的24次方个子网,并通过VNI(Virtual Network Identifier)来区分不同的子网,相当于VLAN当中的VLAN ID。

不同于其他隧道协议,VXLAN是一个一对多的网络,并不仅仅是一对一的隧道协议。一个VXLAN设备能通过像网桥一样的学习方式学习到其他对端的IP地址,也可以直接配置静态转发表。

VXLAN包格式:

从VXLAN的包格式就可以看到原本的二层以太网帧被放在VXLAN包头里进行封装,VXLAN实际实现的是一个二层网络的隧道,通过VXLAN让处于同一个VXLAN网络(VNI相同则为同一个VXLAN网络)当中的机器看似处在同一个二层网络当中(逻辑上处于同一个二层网络),而网络包转发的方式也类似二层网络当中的交换机(这样虽然不是很准确,但更便于理解)。

当采用VXLAN模式时,flanneld在启动时会通过Netlink机制与Linux内核通信,建立一个VTEP(Virtual Tunnel Access End Point)设备flannel.1 (命名规则为flannel.[VNI],VNI默认为1),类似于交换机当中的一个网口。

可以通过ip -d link查看VTEP设备flannel.1的配置信息,从以下输出可以看到,VTEP的local IP为172.16.130.244,destination port为8472。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# ip -d link show flannel.15: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT    link/ether a2:5e:b0:43:09:a7 brd ff:ff:ff:ff:ff:ff promiscuity 0    vxlan id 1 local 172.16.130.244 dev eth1 srcport 0 0 dstport 8472 nolearning ageing 300 addrgenmode eui64[root@10-10-88-192 ~]#

在UDP模式下由flanneld进程进行网络包的封包和解包的工作,而在VXLAN模式下解封包的事情交由内核处理,那么此时FlannnelD的作用是什么呢?带着这个疑问我们先来简单看一下VXLAN Backend是如何工作的。

VXLAN Backend工作原理

Flannel当中对VXLAN Backend的实现经过了几个版本的改进之后目前最新版本的flanneld当中的处理流程为:

当flanneld启动时将创建VTEP设备(默认为flannel.1,若已经创建则跳过),并将VTEP设备的相关信息上报到etcd当中,而当在Flannel网络中有新的节点发现时,各个节点上的flanneld将依次执行以下流程:

在节点当中创建一条该节点所属网段的路由表,主要是能让Pod当中的流量路由到flannel.1接口。

通过route -n可以查看到节点当中已经有两条flannel.1接口的路由:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# route -nKernel IP routing tableDestination     Gateway         Genmask         Flags Metric Ref    Use Iface0.0.0.0         10.10.88.254    0.0.0.0         UG    0      0        0 eth010.10.88.0      0.0.0.0         255.255.255.0   U     0      0        0 eth010.244.0.0      0.0.0.0         255.255.255.0   U     0      0        0 cni010.244.1.0      10.244.1.0      255.255.255.0   UG    0      0        0 flannel.110.244.2.0      10.244.2.0      255.255.255.0   UG    0      0        0 flannel.1169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0169.254.0.0     0.0.0.0         255.255.0.0     U     1003   0        0 eth1172.16.130.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0[root@10-10-88-192 ~]#

在节点当中添加一条该节点的IP以及VTEP设备的静态ARP缓存。

可通过arp -n命令查看到master节点当中已经缓存了另外两个节点以及VTEP的ARP信息(已删除无关ARP缓存信息)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# arp -nAddress                  HWtype  HWaddress           Flags Mask            Iface10.244.2.0               ether   42:7f:69:c7:cd:37   CM                    flannel.110.244.1.0               ether   7a:2c:d0:7f:48:3f   CM                    flannel.1172.16.130.140           ether   fa:89:cf:03:e3:01   C                     eth1172.16.130.164           ether   fa:88:2a:44:2b:01   C                     eth1

在节点当中添加一条该节点的转发表。

通过bridge命令查看节点上的VXLAN转发表(FDB entry),MAC为对端VTEP设备即flannel.1的MAC,IP为VTEP对应的对外IP(可通过flanneld的启动参数--iface=eth1指定,若不指定则按默认网关查找网络接口对应的IP),可以看到已经有两条转发表。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# bridge fdb show dev flannel.142:7f:69:c7:cd:37 dst 172.16.130.164 self permanent7a:2c:d0:7f:48:3f dst 172.16.130.140 self permanent[root@10-10-88-192 ~]#

VXLAN Backend配置

跟UDP Backend一样,将Flannel Backend修改为VXLAN只需要将Flannel ConfigMap当中的Backend type字段修改为VXLAN即可。由于VXLAN类型相对UDP复杂并且有较好的灵活性,这里简单说一下VXLAN当中的几个配置选项:

  • VNI(Number):VXLAN Identifier,默认为1
  • Port(Number):用于发送VXLAN UDP报文的端口,默认为8472
  • DirectRouting(Boolean):当两台主机处于同一个网段当中时,启用后将采用直接路由的方式进行跨节点网络通信(此时工作模式跟后面要讲的host-gw Backend一样),只有当两台主机处于不同的网段当中时才会采用VXLAN进行封包,默认为关闭状态。

修改完成后的ConfigMap如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# kubectl get cm -o yaml -n kube-system kube-flannel-cfgapiVersion: v1data:  cni-conf.json: |    {      "name": "cbr0",      "type": "flannel",      "delegate": {        "isDefaultGateway": true      }    }  net-conf.json: |    {      "Network": "10.244.0.0/16",      "Backend": {        "Type": "vxlan"      }    }kind: ConfigMapmetadata:  creationTimestamp: 2018-10-30T08:34:01Z  labels:    app: flannel    tier: node  name: kube-flannel-cfg  namespace: kube-system  resourceVersion: "33872104"  selfLink: /api/v1/namespaces/kube-system/configmaps/kube-flannel-cfg  uid: 8d981eff-dc1e-11e8-8103-fa900126bc00[root@10-10-88-192 ~]#

同样在更新配置后delete pod使配置生效,并可以通过Flannel的日志查看到Backend已经更新为VXLAN模式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# kubectl logs -f -n kube-system kube-flannel-ds-7bjfmI0318 03:24:02.148654       1 main.go:487] Using interface with name eth1 and address 172.16.130.244I0318 03:24:02.148754       1 main.go:504] Defaulting external address to interface address (172.16.130.244)I0318 03:24:02.207525       1 kube.go:130] Waiting 10m0s for node controller to syncI0318 03:24:02.207596       1 kube.go:283] Starting kube subnet managerI0318 03:24:03.207695       1 kube.go:137] Node controller sync successfulI0318 03:24:03.207729       1 main.go:234] Created subnet manager: Kubernetes Subnet Manager - 10-10-88-192I0318 03:24:03.207735       1 main.go:237] Installing signal handlersI0318 03:24:03.207812       1 main.go:352] Found network config - Backend type: vxlanI0318 03:24:03.227332       1 vxlan.go:119] VXLAN config: VNI=1 Port=0 GBP=false DirectRouting=falseI0318 03:24:03.587362       1 main.go:299] Wrote subnet file to /run/flannel/subnet.envI0318 03:24:03.587379       1 main.go:303] Running backend.I0318 03:24:03.587390       1 main.go:321] Waiting for all goroutines to exitI0318 03:24:03.587418       1 vxlan_network.go:56] watching for new subnet leases

同样可以通过netstat -ulnp命令查看VXLAN监听的端口:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@10-10-88-192 ~]# netstat -ulnp | grep 8472udp        0      0 0.0.0.0:8472            0.0.0.0:*                           -[root@10-10-88-192 ~]#

但跟UDP模式下查看flanneld监听的端口的区别为,最后一栏显示的不是进程的ID和名称,而是一个破折号“-”,这说明UDP的8472端口不是由用户态的进程在监听的,也证实了VXLAN模块工作在内核态模式下。

此时容器跨节点网络通信实现流程为:

  1. 同UDP Backend模式,容器A当中的IP包通过容器A内的路由表被发送到cni0
  2. 到达cni0当中的IP包通过匹配host A当中的路由表发现通往10.244.2.194的IP包应该交给flannel.1接口
  3. flannel.1作为一个VTEP设备,收到报文后将按照VTEP的配置进行封包,首先通过etcd得知10.244.2.194属于节点B,并得到节点B的IP,通过节点A当中的转发表得到节点B对应的VTEP的MAC,根据flannel.1设备创建时的设置的参数(VNI、local IP、Port)进行VXLAN封包
  4. 通过host A跟host B之间的网络连接,VXLAN包到达host B的eth1接口
  5. 通过端口8472,VXLAN包被转发给VTEP设备flannel.1进行解包
  6. 解封装后的IP包匹配host B当中的路由表(10.244.2.0),内核将IP包转发给cni0
  7. cni0将IP包转发给连接在cni0上的容器B

这么一看是不是觉得相比UDP模式单单从步骤上就少了很多步?VXLAN模式相比UDP模式高效也就不足为奇了。

host-gw

host-gw即Host Gateway,从名字中就可以想到这种方式是通过把主机当作网关来实现跨节点网络通信的。那么具体如何实现跨节点通信呢?

同理UDP模式和VXLAN模式,首先将Backend中的type改为host-gw,这里就不再赘述,只讲一下网络通信的实现流程。

采用host-gw模式后flanneld的唯一作用就是负责主机上路由表的动态更新, 想一下这样会不会有什么问题?

使用host-gw Backend的Flannel网络的网络包传输过程如下图所示:

  1. 同UDP、VXLAN模式一致,通过容器A的路由表IP包到达cni0
  2. 到达cni0的IP包匹配到host A当中的路由规则(10.244.2.0),并且网关为172.16.130.164,即host B,所以内核将IP包发送给host B(172.16.130.164)
  3. IP包通过物理网络到达host B的eth1
  4. 到达host B eth1的IP包匹配到host B当中的路由表(10.244.2.0),IP包被转发给cni0
  5. cni0将IP包转发给连接在cni0上的容器B

host-gw模式其中一个局限性就是,由于是通过节点上的路由表来实现各个节点之间的跨节点网络通信,那么就得保证两个节点是可以直接路由过去的。按照内核当中的路由规则,网关必须在跟主机当中至少一个IP处于同一网段,故造成的结果就是采用host-gw这种Backend方式时则集群中所有的节点必须处于同一个网络当中,这对于集群规模比较大时需要对节点进行网段划分的话会存在一定的局限性。另外一个则是随着集群当中节点规模的增大,flanneld需要维护主机上成千上万条路由表的动态更新也是一个不小的压力。

后记

本文主要讲述了Flannel当中UDP、VXLAN、host-gw三种Backend的跨节点网络通信实现流程,并作了简单的分析对比,跨节点网络通信的流程从UDP到VXLAN再到host-gw依次变得简单,效率也逐步提升。这一切还是离不开Linux的设计哲学:Less Is More。

在Kubernetes当中往往很多问题都是出在网络层面,如何在出现问题时能快速地定位到问题原因需要我们对Kubernetes的网络模型有一个熟悉的认知。很多事物的出现都有他的历史原因,永远没有适合各种场景的最好的方案,只有某些应用场景最合适的方案,网络选型还是得根据自身情况进行决定。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 kubernetes中文社区 微信公众号,前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
最新puppeteer爬虫boss直聘招聘公司及职位信息
尝试使用了requests,selenium,pyppeteer,发现都不能正常访问boss直聘,厉害了我的老板!
Python疯子
2020/03/20
1.2K0
自动化 Web 性能分析之 Puppeteer 爬虫实践
通过上篇文章《自动化 Web 性能优化分析方案》的分享想必大家对“百策系统”有了初步的了解。本文将向大家介绍自动化性能分析使用的核心库——Puppeteer,并结合页面登录场景,介绍 Puppeteer 在百策系统中的应用。
政采云前端团队
2019/12/20
3.6K0
自动化 Web 性能分析之 Puppeteer 爬虫实践
使用 Puppeteer 绕过 Captcha:实现商家数据自动化采集
大众点评作为中国领先的本地生活服务平台,不仅是消费者获取商家信息和用户评价的重要工具,同时也是商家推广的关键渠道。通过优质的内容呈现和精准的用户推荐,大众点评能够为商家带来显著的流量提升和品牌曝光,成为商业竞争中不可忽视的资源。
jackcode
2024/11/25
1750
使用 Puppeteer 绕过 Captcha:实现商家数据自动化采集
Node:使用Puppeteer完成一次复杂的爬虫
架构图 Puppeteer架构图 Puppeteer 通过 devTools 与 browser 通信 Browser 一个可以拥有多个页面的浏览器(chroium)实例 Page 至少含有一个
MrTreasure
2018/05/10
3.5K0
Puppeteer的高级用法:如何在Node.js中实现复杂的Web Scraping
随着互联网的发展,网页数据抓取(Web Scraping)已成为数据分析和市场调研的重要手段之一。Puppeteer作为一款强大的无头浏览器自动化工具,能够在Node.js环境中模拟用户行为,从而高效地抓取网页数据。然而,当面对复杂的网页结构和反爬虫机制时,基础的爬虫技术往往无法满足需求。本文将深入探讨如何在Node.js中利用Puppeteer的高级功能,实现复杂的Web Scraping任务,并通过代理IP、User-Agent、Cookies等技术提高爬虫的成功率。
jackcode
2024/09/02
4340
Puppeteer的高级用法:如何在Node.js中实现复杂的Web Scraping
领导让我做 PPT,我用代码来生成
我们用 puppeteer 来爬取大学的校徽、名字、介绍,然后用这些信息来生成 pdf 等。
神说要有光zxg
2024/05/10
3460
领导让我做 PPT,我用代码来生成
前端人的爬虫工具【Puppeteer】
Puppeteer 是 Chrome 开发团队在 2017 年发布的一个 Node.js 包,同时还有 Headless Chrome。用来模拟 Chrome 浏览器的运行。它提供了高级API来通过 DevTools 协议控制无头 Chrome 或 Chromium ,它也可以配置为使用完整(非无头)Chrome 或 Chromium。
Snine
2022/02/11
3.6K0
前端人的爬虫工具【Puppeteer】
Puppeteer教程:使用CSS选择器点击和爬取动态数据
在现代的网页中,许多数据是通过JavaScript动态加载的,这使得传统的爬虫工具(如requests或BeautifulSoup)无法获取到这些数据。因此,为了更好地处理动态网站的数据爬取,我们需要使用像Puppeteer这样的浏览器自动化工具。
jackcode
2024/11/14
2550
Puppeteer教程:使用CSS选择器点击和爬取动态数据
用Scrapy精准爬取BOSS直聘特定行业职位
BOSS直聘作为国内领先的招聘平台,拥有海量的职位信息,对于求职者、招聘者以及行业分析师来说,这些数据具有极高的价值。本文将详细介绍如何使用Scrapy框架精准爬取BOSS直聘上特定行业的职位信息,并在爬虫中集成代理服务器以提高爬取的稳定性和安全性。
小白学大数据
2025/01/09
1720
Puppeteer已经取代PhantomJs
记得前几年,我们通常会用PhantomJs做一下自动化测试,或者为了SEO优化,会用它对SPA页面进行预渲染,现在有更好的Puppeteer来代替它的工作了,性能更好,使用起来也更加方便,Puppeteer 是 Chrome 开发团队在 2017 年发布的一个 Node.js 包,用来模拟 Chrome 浏览器的运行。
javascript.shop
2020/04/10
6.5K0
TypeScript 爬虫实践:选择最适合你的爬虫工具
今天我们将探讨如何使用 TypeScript 构建网络爬虫。网络爬虫是一种强大的工具,可以帮助我们从互联网上收集数据,进行分析和挖掘。而 TypeScript,则是一种类型安全的 JavaScript 超集,它可以让我们在编写 JavaScript 代码时享受到更严格的类型检查和更好的开发体验。本文将介绍如何选择最适合你的网络爬虫工具,并分享一些实用的案例。
小白学大数据
2024/05/16
4220
用Puppeteer点击与数据爬取:实现动态网页交互
在数据采集领域,传统的静态网页爬虫方式难以应对动态加载的网页内容。动态网页通常依赖JavaScript加载数据,用户需要与页面交互才能触发内容显示。因此,我们需要一种更智能的爬虫技术。Puppeteer作为强大的浏览器自动化工具,能模拟用户操作、加载动态数据、实现点击操作和内容采集。此外,为了提高抓取成功率并避免IP封禁,结合代理IP技术必不可少。本文将介绍如何使用Puppeteer和代理IP抓取51job招聘信息,同时从招聘信息的价值、市场应用以及大数据分析角度进行拓展。
jackcode
2024/11/06
2130
用Puppeteer点击与数据爬取:实现动态网页交互
使用Puppeteer爬取地图上的用户评价和评论
在互联网时代,获取用户的反馈和意见是非常重要的,它可以帮助我们了解用户的需求和喜好,提高我们的产品和服务质量。有时候,我们需要从地图上爬取用户对某些地点或商家的评价和评论,这样我们就可以分析用户对不同地区或行业的态度和偏好。但是,如何从地图上爬取用户评价和评论呢?本文将介绍一种使用Puppeteer的方法,它是一个基于Node.js的库,可以控制Chrome或Chromium浏览器进行各种操作,包括爬虫。
jackcode
2023/09/06
5150
使用Puppeteer爬取地图上的用户评价和评论
使用Pyppeteer抓取渲染网页
GitHub地址是:https://miyakogi.github.io/pyppeteer
SeanCheney
2019/01/28
6.8K0
使用Pyppeteer抓取渲染网页
把 puppeteer 融入调试流程,调试体验爽翻了!
最近一直在做业务需求,表单类的,每次调试都要填一堆东西,而且项目需要登录,经常需要来一遍登录流程,再填写表单来调试。这个流程还是比较繁琐的。
神说要有光zxg
2023/02/01
1.2K0
视觉爬虫开发:通过Puppeteer截图+CV定位动态元素坐标
本文为「视觉爬虫开发:通过 Puppeteer 截图 + CV 定位动态元素坐标」的速查指南,帮助你快速掌握在小红书(https://www.xiaohongshu.com/)上使用 Puppeteer 结合 OpenCV 实现视频截图与评论采集的核心思路与代码示例。文章分为四大部分:功能点列表、常用代码片段、配置建议、快速测试方式,并集成爬虫代理设置,以便直接在项目中复用。
jackcode
2025/05/06
1180
视觉爬虫开发:通过Puppeteer截图+CV定位动态元素坐标
Puppeteer 入门指引
Puppeteer 是一个 Node library,提供了一套完整的通过 DevTools 协议操纵 Chrome 或 Chromium 的 API。Puppeteer 默认以 无头(headless) 的方式运行, 也可以使用 GUI 的方式运行 Chrome 和 Chromium。
MudOnTire
2022/03/22
1.8K0
Puppeteer 入门指引
上天的Node.js之爬虫篇 15行代码爬取京东淘宝资源 【深入浅出】
中的所有<a> 标签对应的跳转网页中的所有 title的文字内容,最后放到一个数组中。
Peter谭金杰
2019/08/02
2.2K0
使用Node.js爬取任意网页资源并输出高质量PDF文件到本地~
中的所有<a> 标签对应的跳转网页中的所有 title的文字内容,最后放到一个数组中。
Peter谭金杰
2019/08/02
3.3K0
使用Puppeteer提升社交媒体数据分析的精度和效果
社交媒体是互联网上最受欢迎的平台之一,它们包含了大量的用户生成内容,如文本、图片、视频、评论等。这些内容对于分析用户行为、舆情、市场趋势等有着重要的价值。但是,如何从社交媒体上获取这些数据呢?一种常用的方法是使用网络爬虫,即一种自动化地从网页上提取数据的程序。
jackcode
2023/08/29
4780
使用Puppeteer提升社交媒体数据分析的精度和效果
推荐阅读
相关推荐
最新puppeteer爬虫boss直聘招聘公司及职位信息
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档