机器环境
两台虚拟机器
node60 eth1 ip 10.5.7.60
node61 eth1 ip 10.5.7.61
vxlan 模式配置:
- nolearning
模拟 flannel 集群网段: 10.239.0.0/16, 每个节点分配一个网段 10.239.x.0/24
node60 容器网络 10.239.1.0/16 vxlan flannel0 地址: 10.239.1.0/32 网桥cni0地址: 10.239.1.1/24
node61 容器网络 10.239.2.0/16 vxlan flannel0 地址: 10.239.2.0/32 网桥cni0地址: 10.239.2.1/24
flanneld 当前master 改进
之前每机器arp表目随着容器增加而增加。当前改进的是,采用路由模式, 每个节点只保存其他所有节点flannel0 网卡mac项目,以及vxlan fdb项目。
配置步骤
创建 vxlan 网卡 flannel0
node60:
$ ip link add flannel0 type vxlan id 42 dstport 4789 dev eth1 nolearning
$ ip link list flannel0
5: flannel0: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 12:81:6d:d9:6c:df brd ff:ff:ff:ff:ff:ff
$ ip addr add 10.239.1.0/32 dev flannel0
$ ip link set flannel0 up
node60:
- flannel mac 地址是: 12:81:6d:d9:6c:df ip 地址是: 10.239.1.0/32
node61:
$ ip link add flannel0 type vxlan id 42 dstport 4789 dev eth1 nolearning
$ ip link list flannel0
4: flannel0: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether ae:e7:b9:16:44:08 brd ff:ff:ff:ff:ff:ff
$ ip addr add 10.239.2.0/32 dev flannel0
$ ip link set flannel0 up
node61: flannel mac 地址是:ae:e7:b9:16:44:08, ip 地址是: 10.239.2.0/32
创建网桥cni0
node60
$ip link add cni0 type bridge
$ip link set cni0 up
$ip addr add 10.239.1.1/24 dev cni0
node61
$ip link add cni0 type bridge
$ip link set cni0 up
$ip addr add 10.239.2.1/24 dev cni0
路由配置
网络数据传输路线
node60 container veth_p1 -> veth_p2 -> cni0 (ip route) -> flannel0 -> node61: flannel0 (ip route) -> cni0
node60
10.239.1.0/24 由cni0 去转发 (配置bridge ip 后自动加上)
$ ip route add 10.239.1.0/24 via 10.239.1.1 dev cni0
按照flannel 数据动态增加节点路由
例如 :node61 网段是 10.239.2.0/24, 发送到node61 fannel0 上,
$ ip route add 10.239.2.0/24 via 10.239.2.0 dev flannel0 onlink
flannel 动态增删节点路由通过watch etch 实现的
node60
$ ip route add 10.239.1.0/24 via 10.239.1.0 dev flannel0 onlink
ARP 和 FDB 表配置
为了防止ARP风暴, vxlan 没有配置group 组播, flannel增加路由节点后, 同时需要告诉flannel vxlan 下一跳 10.239.2.0
路由器ip mac, vxlan发送什么主机上,需要通过配置arp, fdb。 这样的好处是一个节点一个arp, 一个fdb。arp和fdb表项目只会随主机增加而增加,不会随容器增加而增加。
node60 上配置
$ ip neigh add 10.239.2.0 lladdr ae:e7:b9:16:44:08 dev flannel0
$ bridge fdb append ae:e7:b9:16:44:08 dev flannel0 dst 10.5.7.61
node61 上配置
$ ip neigh add 10.239.2.0 lladdr ae:e7:b9:16:44:08 dev flannel0
$ bridge fdb append ae:e7:b9:16:44:08 dev flannel0 dst 10.5.7.60
创建容器网络
以 node60 为例子,创建容器网络过程。创建网络命名空间, 以及一对veth pair, 把 veth pair 一端放到容器网络空间上, 另外一端接到bridge0 上。 容器网络接口配置ip 地址为10.239.1.2
创建container1网络
创建 container1 命名空间
$ ip netns add container1
创建容器网卡
创建veth对veth0-veth1, 把一端 veth1 移动到container1空间上。
# 创建 veth 对
$ ip link add veth0 type veth peer name veth1
# veth0 接到网桥 bridge0 上
$ ip link set dev veth0 master bridge0
# veth1 移动命名空间 container1
$ ip link set dev veth1 netns container1
# 启动 lo 接口, 否则ping 127.0.0.1 / 自己 ip 地址不通
$ ip netns exec container1 ip link set lo up
# 修改接口名字为 eth0
$ ip netns exec container1 ip link set veth1 name eth0
# 配置 eth0 地址
$ ip netns exec container1 ip addr add 10.239.1.2/24 dev eth0
# 启动 eth0
$ ip netns exec container1 ip link set eth0 up
- node62 进行同样的配置
在容器配置默认路由为 bridge0
$ ip netns exec container1 ip route add default via 10.239.1.1 dev eth0
$ echo "1" > /proc/sys/net/ipv4/ip_forward
测试
ip netns exec container1 ping 10.239.2.1
如果ping通基本算是联通网络了。
容器允许访问主机外网络
测试发现容器里面不能 ping 通主机外网络, 例如 10.5.7.61。 容器出去以后,还是10.239 网络, 其他机器返回包不能收到,所有需要在iptable net 给容器网络段 10.239.0.0/16 出外网的时候做地址伪装, 主要分段
node61
# flannel 10.239.0.0/16 网段内部通信不做snat伪装
$ iptables -t nat -A POSTROUTING -s 10.239.0.0/16 -d 10.239.0.0/16 -j RETURN
# flannel 10.239.0.0/16 网段出去外网,而且外网地址非组播地址,把flannel地址换主机地址
$ iptables -t nat -A POSTROUTING -s 10.239.0.0/16 ! -d 224.0.0.0/4 -j MASQUERADE
# 其他机器调转本主机flannel网段请求不用做地址伪装
$ iptables -t nat -A POSTROUTING ! -s 10.239.0.0/16 -d 10.239.1.0/24 -j RETURN
# 其他机器调转本进入flannel网段,但是不是本主机的网段,需要地址伪装(转发其他flannel节点,返回本几点,再转发回去)
$ iptables -t nat -A POSTROUTING ! -s 10.239.0.0/16 -d 10.239.0.0/16 -j MASQUERADE
node62
# flannel 10.239.0.0/16 网段内部通信不做snat伪装
$ iptables -t nat -A POSTROUTING -s 10.239.0.0/16 -d 10.239.0.0/16 -j RETURN
# flannel 10.239.0.0/16 网段出去外网,而且外网地址非组播地址,把flannel地址换主机地址
$ iptables -t nat -A POSTROUTING -s 10.239.0.0/16 ! -d 224.0.0.0/4 -j MASQUERADE
# 其他机器调转本主机flannel网段请求不用做地址伪装
$ iptables -t nat -A POSTROUTING ! -s 10.239.0.0/16 -d 10.239.2.0/24 -j RETURN
# 其他机器调转本进入flannel网段,但是不是本主机的网段,需要地址伪装(转发其他flannel节点,返回本几点,再转发回去)
$ iptables -t nat -A POSTROUTING ! -s 10.239.0.0/16 -d 10.239.0.0/16 -j MASQUERADE
容器网络出去以后,地址就会替换为主机ip地址,容器网络就可以访问外网了
ip netns exec container1 ping 123.58.180.7
PING 123.58.180.7 (123.58.180.7) 56(84) bytes of data.
64 bytes from 123.58.180.7: icmp_seq=1 ttl=61 time=27.6 ms
64 bytes from 123.58.180.7: icmp_seq=2 ttl=61 time=27.5 ms
64 bytes from 123.58.180.7: icmp_seq=3 ttl=61 time=27.2 ms
64 bytes from 123.58.180.7: icmp_seq=4 ttl=61 time=27.2 ms