k8s 二进制部署 八 (flannel)

大番茄 2019年11月23日 318次浏览

v0.11.0

flannel 是常用的网络打通的工具。
在github搜索flannel。
网址: https://github.com/coreos/flannel

一、介绍

flannel可以单独启动, 也可以k8s启动, 在k8s启动可以直接从K8S获取网段信息,单独启动需要在etcd里添加flannel配置。这里是单独启动的。

flannel网络模式

https://github.com/coreos/flannel/blob/master/Documentation/backends.md
其中vxlan比较常用,自动创建vxlan隧道, 有一定网络损耗。
如果是在相同网段的物理局域网,可以使用host-gw,通过给给节点创建路由规则,每多一个节点就多创建一条规则,就是路由规则多点, 没有网络损耗。

配置网段

https://github.com/coreos/flannel/blob/master/Documentation/configuration.md

{
	"Network": "10.0.0.0/8",
	"SubnetLen": 20,
	"SubnetMin": "10.10.0.0",
	"SubnetMax": "10.99.0.0",
	"Backend": {
		"Type": "udp",
		"Port": 7890
	}
}

Network : 就是flannel可以使用,可以分配的所有ip。
SubnetLen: 让docker使用的掩码。默认24。

如果没有下面那两个参数限制最大最小, 可分配网段的范围就是:
10.0.0.0/20 - 10.255.240.0/20
2的12次方个可用网段。


SubnetMin: 最小网段。 默认为网段最小的一个。
SubnetMax: 最大网段。 这个最小最大就是可以分配给节点docker使用的网段范围。 默认为网段最大的一个。
上面这个例子可不是10-99, 而是:
1010.0000 - 1100011.0000
后面那个减去前面那个等于:101 1001 0000,1424
1424 + 1, 有1425个网段可以使用。

然后每个网段4096个地址,4094个可以使用。


Backend 就是flannel的网络模式, 例子里是udp。
常用的就Network以及Backend。


以上面的参数启动flannel,只是把Type改成了vxlan, 去掉了port。 所生成的文件,重点就是网段部分:

[root@k8s-node1 etcd]# cat /run/flannel/subnet.env 
FLANNEL_NETWORK=10.0.0.0/8
FLANNEL_SUBNET=10.12.16.1/20
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
[root@k8s-node1 etcd]# cat /run/flannel/docker_opts.env 
DOCKER_OPT_BIP="--bip=10.12.16.1/20"
DOCKER_OPT_IPMASQ="--ip-masq=false"
DOCKER_OPT_MTU="--mtu=1450"
DOCKER_OPTS=" --bip=10.12.16.1/20 --ip-masq=false --mtu=1450"

二、给flannel创建证书。

因为集群里的etcd是双向认证的, 所以flannel想要连接etcd需要证书。
etcd不会验证证书的Common Name, 所以不需要生成san扩展的证书。
使用集群CA生成证书就可以。

[root@k8s-ca data]# ./openssl.sh build flannel
Generating RSA private key, 2048 bit long modulus
.....+++
.......+++
。。。。。。。。。。。。。

我这里是使用自己的脚本生成的。
https://www.yxingxing.net/articles/2019/10/25/1571997217121.html

三、安装flannel

1、下载

https://www.yxingxing.net/articles/2019/10/25/1571997217121.html

2、目录结构
[root@k8s-node1 flannel]# tree
.
├── bin
│   ├── flanneld
│   └── mk-docker-opts.sh
└── ssl
    ├── cacert.pem
    ├── flannel.crt
    └── flannel.key

2 directories, 5 files
3、在etcd创建网络配置。

使用etcdctl添加配置。
注意etcdctl要工作在v2模式,在v2里添加配置, 因为flannel不支持v3的etcd。

[root@k8s-node1 etcd]# bin/etcdctl --endpoints "https://172.100.102.71:2379,https://172.100.102.72:2379,https://172.100.102.73:2379" --cert-file ssl/etcd.crt --key-file ssl/etcd.key --ca-file ssl/cacert.pem set /coreos.com/network/config '
{
    "Network": "10.1.0.0/16",
    "SubnetLen": 24,
    "SubnetMin": "10.1.10.0",
    "SubnetMax": "10.1.90.0",
    "Backend": {
        "Type": "vxlan"
    }
}'

# 输出
{
    "Network": "10.1.0.0/16",
    "SubnetLen": 24,
    "SubnetMin": "10.1.10.0",
    "SubnetMax": "10.1.90.0",
    "Backend": {
        "Type": "vxlan"
    }
}
[root@k8s-node1 etcd]# 

上面有81个网段,每个网段253个可用ip。


如果节点需要启动很多pod, 大于253,节点不多,可以改一下SubnetLen, 比如改成23, 可用ip就成510个,可用网段是39个。 就是ip掩码计算,长时间没有算这东西,也不知道算的对不对。


这里只是说明参数的使用,
大多数情况下SubnetLen, SubnetMin, SubnetMax 都会省略, 使用默认值。 如:

{"Network": "10.1.0.0/16", "Backend": {"Type": "vxlan" } }
4、创建Unit
vim /lib/systemd/system/flannel.service

[Unit]
Description=Etcd server
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/local/flannel/bin/flanneld \
-etcd-cafile /usr/local/flannel/ssl/cacert.pem \
-etcd-certfile /usr/local/flannel/ssl/flannel.crt \
-etcd-keyfile /usr/local/flannel/ssl/flannel.key \
-etcd-endpoints "https://172.100.102.71:2379,https://172.100.102.72:2379,https://172.100.102.73:2379" \
-ip-masq \
-healthz-port 300
ExecStartPost=/usr/local/flannel/bin/mk-docker-opts.sh -d /var/run/flannel/docker_opts.env

[Install]
RequiredBy=docker.service
WantedBy=multi-user.target

那4个etcd参数是用来连接etcd的。
-ip-masq是用来生成iptables的SNAT规则。用于容器里的地址可以访问外网。
在flannel这里要加上这个参数,如果这里不加,docker的启动参数就要加上,但是docker生成的iptables规则没有考虑不同主机pod之间的通信,因为不同的主机pod的网段是不同的, 所以就导致访问其他主机pod也会SNAT。在下面还有flannel的iptables,可以对比一下。

Chain POSTROUTING (policy ACCEPT)

target  prot opt source  destination         

MASQUERADE all -- 10.1.0.0/16 0.0.0.0/0

启动以后会在/var/run/flannel下面生成docker网络相关的启动参数, 可以在docker的Unit文件以变量文件加载。

5、启动flannel, 并修改docker启动参数。
[root@k8s-node1 etcd]# systemctl start flannel

启动以后会生成一个类型为vxlan的flannel网卡。类型这样看不出来,需要ip link list type vxlan来查看。

[root@k8s-node1 etcd]# ip addr show dev flannel.1
5: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default 
    link/ether ca:a6:ef:90:97:e7 brd ff:ff:ff:ff:ff:ff
    inet 10.1.44.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
    inet6 fe80::c8a6:efff:fe90:97e7/64 scope link 
       valid_lft forever preferred_lft forever
[root@k8s-node1 etcd]# 

之后访问其他节点容器的地址都是会通过flannel网卡的vxlan隧道发出去, 因为这里现在只有一个节点,路由看不出来, 下面截了其他测试集群的信息:

[root@k8s-node1 bin]# ip route list
default via 172.100.101.1 dev eth0 proto static metric 100 
10.1.15.0/24 via 10.1.15.0 dev flannel.1 onlink 
10.1.37.0/24 via 10.1.37.0 dev flannel.1 onlink 
10.1.51.0/24 via 10.1.51.0 dev flannel.1 onlink 
10.1.53.0/24 via 10.1.53.0 dev flannel.1 onlink 
10.1.65.0/24 via 10.1.65.0 dev flannel.1 onlink 
10.1.68.0/24 via 10.1.68.0 dev flannel.1 onlink 
10.1.72.0/24 via 10.1.72.0 dev flannel.1 onlink 
10.1.81.0/24 via 10.1.81.0 dev flannel.1 onlink 
10.1.90.0/24 dev docker0 proto kernel scope link src 10.1.90.1 
172.100.101.0/24 dev eth0 proto kernel scope link src 172.100.101.193 metric 100 
[root@k8s-node1 bin]# 

下面是docker的,flannel启动以后会生成一个文件,就是subnet.env, 还有一个是由flannel的mk-docker-opts.sh脚本生成的可以直接让docker使用的docker_opts.env文件。

[root@k8s-node1 etcd]# cat /var/run/flannel/docker_opts.env 
DOCKER_OPT_BIP="--bip=10.1.44.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=false"
DOCKER_OPT_MTU="--mtu=1450"
DOCKER_OPTS=" --bip=10.1.44.1/24 --ip-masq=false --mtu=1450"

[root@k8s-node1 etcd]# cat /var/run/flannel/subnet.env 
FLANNEL_NETWORK=10.1.0.0/16
FLANNEL_SUBNET=10.1.44.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
[root@k8s-node1 etcd]# 

这里因为flannel启动的时候加上了--ip-masq,所以在生成的docker参数里ip-masq就是false了。 mtu为1450是因为使用的是vxlan, 如果使用host-gw就是1500了。

这个就是--ip-masq加的规则。

Chain POSTROUTING (policy ACCEPT 2 packets, 120 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 RETURN     all  --  *      *       10.1.0.0/16          10.1.0.0/16         
2        0     0 MASQUERADE  all  --  *      *       10.1.0.0/16         !224.0.0.0/4         
3        0     0 RETURN     all  --  *      *      !10.1.0.0/16          10.1.44.0/24        
4        0     0 MASQUERADE  all  --  *      *      !10.1.0.0/16          10.1.0.0/16   

改一下docker的启动参数。可以看到现在docker0的地址。

[root@k8s-node1 etcd]# ip addr show dev docker0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:de:8a:a3:35 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
[root@k8s-node1 etcd]# 
添加读取flannel生成的文件。并在启动参数里使用。

EnvironmentFile=/var/run/flannel/docker_opts.env

vim /lib/systemd/system/docker.service

image-c98afc6e

重启docker
[root@k8s-node1 etcd]# systemctl daemon-reload
[root@k8s-node1 etcd]# systemctl restart docker
[root@k8s-node1 etcd]# ip addr show dev docker0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:de:8a:a3:35 brd ff:ff:ff:ff:ff:ff
    inet 10.1.44.1/24 brd 10.1.44.255 scope global docker0
       valid_lft forever preferred_lft forever
[root@k8s-node1 etcd]# 

在etcd里可以查看到节点的信息

[root@k8s-node1 etcd]# bin/etcdctl --endpoints "https://172.100.102.71:2379,https://172.100.102.72:2379,https://172.100.102.73:2379" --cert-file ssl/etcd.crt --key-file ssl/etcd.key --ca-file ssl/cacert.pem ls /coreos.com/network
/coreos.com/network/config
/coreos.com/network/subnets

[root@k8s-node1 etcd]# bin/etcdctl --endpoints "https://172.100.102.71:2379,https://172.100.102.72:2379,https://172.100.102.73:2379" --cert-file ssl/etcd.crt --key-file ssl/etcd.key --ca-file ssl/cacert.pem ls /coreos.com/network/subnets
/coreos.com/network/subnets/10.1.44.0-24

[root@k8s-node1 etcd]# bin/etcdctl --endpoints "https://172.100.102.71:2379,https://172.100.102.72:2379,https://172.100.102.73:2379" --cert-file ssl/etcd.crt --key-file ssl/etcd.key --ca-file ssl/cacert.pem get /coreos.com/network/subnets/10.1.44.0-24
{"PublicIP":"172.100.102.71","BackendType":"vxlan","BackendData":{"VtepMAC":"ca:a6:ef:90:97:e7"}}
[root@k8s-node1 etcd]#