记一次flannel vxlan的debug过程

自从部署好k8之后,用了一段时间都是自己配置路由,简单的使用 cni 的网络,简直是累得不行,每次加减新节点都得配置路由,因此就部署了 flannel , 结果今天晚上发现在 node 上居然访问不到服务,仔细看才知道节点之间的 pod 竟无法相互 ping 通,因此才有了今晚的这个过程。

首先介绍一下我的这个环境是由一个master和四个node组成的一个集群,工作节点分别是node1,node2,node3和node4,对应的ip地址分别是192.168.1.12{1,2,3,4} , 之间的网络方案是使用的 flannel 的 vxlan 模式。简单说一下,flannel有三种工作模式,分别是 udp, vxlan 和 gw-host,官网有大致的介绍,请看 这里

简单说一下 vxlan 是怎么实现的,也就清楚了我的解题思路了。首先可能会发现部署了 flannel 的 vxlan 模式后,只要正常运行的话,都会看到一个 flannel.1 的网络设备,比如说我这个:


```shell

root@node1:~# ip a s flannel.1

5: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default

    link/ether 3e:7f:7a:12:51:fd brd ff:ff:ff:ff:ff:ff

    inet 9.0.2.0/32 scope global flannel.1

      valid_lft forever preferred_lft forever

    inet6 fe80::3c7f:7aff:fe12:51fd/64 scope link

      valid_lft forever preferred_lft forever

```

这是一个叫 vtep 的设备,在这个模式中主要是为了封装和解封二层数据帧。也就是说如果从一个节点上的 pod1 发送流量到另外一个节点上的 pod2 的话,网络流量首先从 pod1 出来,经过 veth pair 的链接出现在了 cni0 的网桥上,这个 cni0 跟 docker0 是一样的,这是 k8s 为了隐藏容器细节而抽象出来的一个设备,然后这时根据路由表,比如我的路由表这样:

```shell

root@node1:~# ip route

default via 192.168.1.1 dev eth1

9.0.0.0/24 via 9.0.0.0 dev flannel.1 onlink

9.0.1.0/24 via 9.0.1.0 dev flannel.1 onlink

9.0.2.0/24 dev cni0 proto kernel scope link src 9.0.2.1

9.0.3.0/24 via 9.0.3.0 dev flannel.1 onlink

172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown

192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.121

root@node1:~#

```

为了方便解释,这里假设 pod1 的 ip 是 9.0.2.18 ,pod2 的 ip 是 9.0.3.3, 根据路由规则要去 9.0.3.3 的流量下一跳应该是 经过 flannel.1 到 9.0.3.0 这里,(onlink的意思是下一跳是直接连接到当前设备的),因此这个流量从 cni0 出来之后就到了 flannel.1 ,当 flannel.1 收到这个数据包之后呢,就需要把这个包封装成二层数据帧,也就是添加对应的 MAC 地址,比如说:

```shell

root@node2:~# ip neigh show dev flannel.1 | grep 9.0.3.0

9.0.3.0 lladdr c2:8a:fe:64:a4:f0 PERMANENT

```

可能有人会问,为什么是 9.0.3.0 而不是 9.0.3.3 呢?因为这个 vxlan 的设计是通过每个 flannel.1 设备虚拟连接成一个二层网络,而根据上面的路由表我们知道要去往 9.0.3.3 的路必须先经过 9.0.3.0 ,也就是另外一个节点上的 flannel.1 设备。等 flannel.1 封装完这个包之后呢, linux 内核还需要给这个包加一个 VXLAN 的头以表示这是一个 VXLAN 的包,然后再送到真正的网卡通过 udp 发送出去,可是发送到哪里呢?怎么知道发送到哪里呢? 这就是 FDB 的作用了。

```shell

root@node2:~# bridge fdb show | grep c2:8a:fe:64:a4:f0

c2:8a:fe:64:a4:f0 dev flannel.1 dst 10.0.2.15 self permanent

root@node2:~#

```

这就是我的 FDB 的数据了,用过 vagrant 的同学可能会知道问题出在哪里了,解释完这个流程先。这个 fdb 规则告诉 linux 内核,发往 c2:8a:fe:64:a4:f0 也就是 9.0.3.0 的数据包应该通过 flannel.1 发向 10.0.2.15 这个地址去。正常来说这个 ip 地址就应该是 pod2 运行的节点地址了,然后当接收节点 node2 接收到这个数据包之后呢,就会先拆下 10.0.2.15 这个三层地址头之后发现是一个 VXLAN 的包,然后拆下对应的包头后发现是给 node2  上的 flannel.1 设备,就把包交给 flannel.1 然后 flannel.1 解封这个包之后发现是给 pod2 的就会送到 cni0 然后给到 pod2.

我这个问题就出在 10.0.2.15 上,这是 vagrant 设置的一个默认网卡,使用的是 nat 模式的网络,因此这个 ip 只能用于虚拟机和 host 之间通讯,导致网络包无法发送到另外一个虚拟机节点上。那怎么解决这个问题呢?

其实首先我查看了官网,发现有这么一段话 :

```english

Running on Vagrant

Vagrant has a tendency to give the default interface (one with the default route) a non-unique IP (often 10.0.2.15).

This causes flannel to register multiple nodes with the same IP.

To work around this issue, use --iface option to specify the interface that has a unique IP.

If you're running on CoreOS, use cloud-config to set coreos.flannel.interface to $public_ipv4.

```

这个问题呢,其实有两种解决办法,第一个是禁用掉这个网卡,不过如果禁用了这个虚拟设备的话,以后就无法使用 vagrant 的 provision 功能了,因为这个 10.0.2.15 对我来说并没啥作用,因此我直接在系统里面禁用掉了这个虚拟网卡,这回这个 daemonset 就能正常运行了,问题到这里也就解决了。但是我这个并不是最好的解决办法,因为有些机器避免不了会使用到多网卡,这时候就应该是自己指定 iface 了。

由于我是使用 vagrant 加 ansible 来部署这个集群,因此禁用网卡这个事情就交回给了 vagrant 了,也算是有始有终了,就是在 Vagrantfile 里面加这么一段:

```ruby

config.vm.provision "shell",

      run: "once",

      inline: "sudo sed '/eth0/d' /etc/network/interfaces && sudo systemctl restart networking"

```

第二个解决办法呢,就是使用 flanneld 的 --iface, 因为我是部署的 flanneld 的 daemonset , 因此在环境里执行这个命令, `kubectl -n kube-system edit daemonset kube-flannel` ,然后在对应的 `container`里的`args`添加上`--iface=eth`,如下:

```

containers:

      - name: kube-flannel

        image: quay.io/coreos/flannel:v0.11.0-amd64

        command:

        - /opt/bin/flanneld

        args:

        - --ip-masq

        - --kube-subnet-mgr

        - --iface=eth1    #添加了这一行

```

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,104评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,816评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,697评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,836评论 1 298
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,851评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,441评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,992评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,899评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,457评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,529评论 3 341
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,664评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,346评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,025评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,511评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,611评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,081评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,675评论 2 359

推荐阅读更多精彩内容