1、将需要用到的cni组件(二进制可执行文件)放到/opt/cni/bin目录下
2、在/etc/cni/net.d中增加cni的配置文件,配置文件中可以指定需要使用的cni组件及参数
3、kubelet启动参数中networkPlugin设置为cni
4、创建网桥
5、添加本机网络端口到网桥中
https://github.com/containernetworking/cni
cd $GOPATH/src/github.com/containernetworking/plugins
./build_linux.sh
mkdir -p /etc/cni/net.d
cat >/etc/cni/net.d/10-mynet.conf <
--network-plugin=cni
--cni-conf-dir=/etc/cni/net.d
--cni-bin-dir=/opt/cni/bin
[root@node1 ~]# cat /etc/rc.local
#!/bin/bash
# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
#
# It is highly advisable to create own systemd services or udev rules
# to run scripts during boot instead of using this file.
#
# In contrast to previous versions due to parallel execution during boot
# this script will NOT be run after all other services.
#
# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
# that this script will be executed during boot.
touch /var/lock/subsys/local
/usr/sbin/ip link add cni0 type bridge//添加网桥
/usr/sbin/ip link set ens33 master cni0//
/usr/sbin/ifconfig ens33 192.168.204.143/24//主机网卡恢复IP
/usr/sbin/ifconfig cni0 192.168.204.3/24//给网桥设置IP
/usr/sbin/ip link add cni0 type bridge:创建网桥
1-4步将bridge搭建好了,但本机网卡eth0与bridge网桥是还没有建立通信的。也就是说外界还是无法访问通过bridge创建的容器。
所以当eth0加入bridge之后,从外面网络收到的数据包将无条件的转发给bridge,自己变成了一根网线。就可以访问通过bridge创建的容器了。
bridge不区分接入进来的是物理设备还是虚拟设备,对它来说都一样的,都是网络设备。
ens33是本机网卡名称,不同主机名称会不同,ens33对应下图的eth0,cni0对应bridge
192.168.204.189是pod的ip
[root@master1 ~]# curl 192.168.204.189
This request was processed by host: first-deployment-5bc5c8cd58-p2kqk
![未命名文件 (4)](/Users/tcy/Documents/Typora/Picture/未命名文件 (4).png)
使用新建的bridge网桥代替docker0网桥(docker0也可以继续保留,常规容器还是用docker0,而需要互通的容器可以借助于这个工具给docker容器新建虚拟网卡并绑定IP桥接到bridge)
bridge和主机eth0之间是也是利用veth pair这个技术:
https://blog.csdn.net/sld880311/article/details/77650937
https://segmentfault.com/a/1190000009491002#articleHeader6
查看网桥:
[root@node1 ~]# brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.000c294220a7 no ens33
veth1b8fe73a
veth31fc4222
veth5ed676bc
vethf0b15c0b
docker0 8000.0242814c9fe7 no
查看路由:
[root@node1 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.204.2 0.0.0.0 UG 0 0 0 cni0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.204.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
查看网卡:
[root@node1 ~]# ip addr
1: lo: 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 forever
2: ens33: mtu 1500 qdisc pfifo_fast master cni0 state UP qlen 1000
link/ether 00:0c:29:42:20:a7 brd ff:ff:ff:ff:ff:ff
inet 192.168.204.143/24 brd 192.168.204.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::7c8e:9fcd:f1c1:f52b/64 scope link
valid_lft forever preferred_lft forever
3: cni0: mtu 1500 qdisc noqueue state UP qlen 1000
link/ether 00:0c:29:42:20:a7 brd ff:ff:ff:ff:ff:ff
inet 192.168.204.3/24 brd 192.168.204.255 scope global cni0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe42:20a7/64 scope link
valid_lft forever preferred_lft forever
4: docker0: mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:81:4c:9f:e7 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
1)brdige组件创建一个指定名字的网桥,如果网桥已经存在,就使用已有的网桥;
2)创建vethpair,将node端的veth设备连接到网桥上;
3)从ipam获取一个给容器使用的ip数据,并根据返回的数据计算出容器对应的网关;
4)进入容器网络名字空间,修改容器中网卡名和网卡ip,以及配置路由,并进行arp广播(注意我们只为vethpair的容器端配置ip,node端是没有ip的);
5)如果IsGW=true,将网桥配置为网关,具体方法是:将第三步计算得到的网关IP配置到网桥上,同时根据需要将网桥上其他ip删除。最后开启网桥的ip_forward内核参数;
6)如果IPMasq=true,使用iptables增加容器私有网网段到外部网段的masquerade规则,这样容器内部访问外部网络时会进行snat,在很多情况下配置了这条路由后容器内部才能访问外网。(这里代码中会做exist检查,防止生成重复的iptables规则);
7)配置结束,整理当前网桥的信息,并返回给调用者。DEL命令
1)根据命令执行的参数,确认要删除的容器ip,调用ipam的del命令,将IP还回IP pool;
2)进入容器的网络名字空间,根据容器IP将对应的网卡删除;
3)如果IPMasq=true,在node上删除创建网络时配置的几条iptables规则。