1. flannel 的作用
https://github.com/coreos/flannel/releases flannel github 地址
K8S 網絡插件用的最多的flannel 和calico,主要是解決不同宿主機之間的pod 通信問題。flannel 支持UDP、VxLAN、host-GW, AWS VPC和GCE路由等數據轉發方式。
1. VxLAN:使用內核中的VxLAN模塊進行封裝報文。也是flannel推薦的方式.
2. host-gw:要求各節點必須在同一個2層網絡,通過在節點上創建目標容器地址的路由直接完成報文轉發,對報文轉發性能要求較高的場景使用。
3. UDP:使用普通的UDP報文封裝完成隧道轉發,效率低下,不推薦。
2. Flannel容器的跨主機通信通過程
flannel 的 配置信息保存在etcd 中的,查看。
-
/opt/etcd/etcdctl ls /coreos.com/network /coreos.com/network/config /coreos.com/network/subnets [root@hdss7-21 ~]# /opt/etcd/etcdctl get /coreos.com/network/config {"Network": "172.7.0.0/16", "Backend": {"Type": "VxLAN","Directrouting": true}}
當需要與其他主機上的容器進行通信時,查找etcd數據庫,找到目的容器的子網所對應的outip(目的宿主機的IP);
將原始數據包封裝在VXLAN或UDP數據包中,IP層以outip爲目的IP進行封裝;
由於目的IP是宿主機IP,因此路由是可達的。
VXLAN或UDP數據包到達目的宿主機解封裝,解出原始數據包(原始包就是pod 之前訪問的包),通過內核轉發將數據包從宿主機轉到本地容器。
3. 部署flannel 網絡插件
在7.21 和7.22 上部署
#在7.21 上執行
wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
[root@hdss7-21 src]# mkdir /opt/flannel-v0.11.0
[root@hdss7-21 src]# tar xf flannel-v0.11.0-linux-amd64.tar.gz -C /opt/flannel
[root@hdss7-21 conf]# cd /opt/flannel/cert/
[root@hdss7-21 cert]# scp hdss7-200:/opt/certs/ca.pem .
[root@hdss7-21 cert]# scp hdss7-200:/opt/certs/client.pem .
[root@hdss7-21 cert]# scp hdss7-200:/opt/certs/client-key.pem .
cd /opt/flannel
vi subnet.env
FLANNEL_NETWORK=172.7.0.0/16
FLANNEL_SUBNET=172.7.21.1/24 #7.22 要改成 172.7.22.1/24
FLANNEL_MTU=1500
FLANNEL_IPMASQ=false
[root@hdss7-21 flannel]# vi flanneld.sh
#!/bin/sh
./flanneld \
--public-ip=10.4.7.21 \ #7.22 改下ip
--etcd-endpoints=https://10.4.7.12:2379,https://10.4.7.21:2379,https://10.4.7.22:2379 \
--etcd-keyfile=./cert/client-key.pem \
--etcd-certfile=./cert/client.pem \
--etcd-cafile=./cert/ca.pem \
--iface=eth0 \
--subnet-file=./subnet.env \
--healthz-port=2401
chmod +x flanneld.sh
mkdir -p /data/logs/flanneld
vi /etc/supervisord.d/flannel.ini
[program:flanneld]
command=/opt/flannel/flanneld.sh ; the program (relative uses PATH, can take args)
numprocs=1 ; number of processes copies to start (def 1)
directory=/opt/flannel ; directory to cwd to before exec (def no cwd)
autostart=true ; start at supervisord start (default: true)
autorestart=true ; retstart at unexpected quit (default: true)
startsecs=30 ; number of secs prog must stay running (def. 1)
startretries=3 ; max # of serial start failures (default 3)
exitcodes=0,2 ; 'expected' exit codes for process (default 0,2)
stopsignal=QUIT ; signal used to kill process (default TERM)
stopwaitsecs=10 ; max num secs to wait b4 SIGKILL (default 10)
user=root ; setuid to this UNIX account to run the program
redirect_stderr=true ; redirect proc stderr to stdout (default false)
stdout_logfile=/data/logs/flanneld/flanneld.stdout.log ; stderr log path, NONE for none; default AUTO
stdout_logfile_maxbytes=64MB ; max # logfile bytes b4 rotation (default 50MB)
stdout_logfile_backups=4 ; # of stdout logfile backups (default 10)
stdout_capture_maxbytes=1MB ; number of bytes in 'capturemode' (default 0)
stdout_events_enabled=false ; emit events on stdout writes (default false)
4. flannel vxlan 模型配置和相關信息查看
在10.4.7.21 和22 上配置 vlxan 模式。
/opt/etcd/etcdctl set /coreos.com/network/config '{"Network": "172.7.0.0/16", "Backend": {"Type": "VxLAN"}}' # 設置行vxlan 模型 #查看etcd 中保存的信息 /opt/etcd/etcdctl ls /coreos.com/network /coreos.com/network/config /coreos.com/network/subnets [root@hdss7-21 ~]# /opt/etcd/etcdctl get /coreos.com/network/config {"Network": "172.7.0.0/16", "Backend": {"Type": "VxLAN"}} /opt/etcd/etcdctl ls /coreos.com/network/subnets /coreos.com/network/subnets/172.7.21.0-24 /coreos.com/network/subnets/172.7.22.0-24 #會發現宿主機上多了flannel.1 的接口。 這個flannel.1是一個vtep二層設備 ifconfig flannel.1 flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 172.7.21.0 netmask 255.255.255.255 broadcast 0.0.0.0 inet6 fe80::5478:5aff:fe1a:7304 prefixlen 64 scopeid 0x20<link> ether 56:78:5a:1a:73:04 txqueuelen 0 (Ethernet) RX packets 25979967 bytes 17410555331 (16.2 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 19077703 bytes 8443811676 (7.8 GiB) TX errors 0 dropped 8 overruns 0 carrier 0 collisions 0 #查看路由 ip route ls default via 10.4.7.1 dev eth0 proto static metric 100 10.4.7.0/24 dev eth0 proto kernel scope link src 10.4.7.21 metric 100 172.7.21.0/24 dev docker0 proto kernel scope link src 172.7.21.1 172.7.22.0/24 via 172.7.22.0 dev flannel.1 onlink 會發現多了 172.7.22.0/24 via 172.7.22.0 dev flannel.1 onlink 路由,pod垮宿主機訪問都通過這條路由了。 #查看 vxlan fdb(forwarding database) [root@hdss7-21 ~]# bridge fdb show dev flannel.1 ea:99:e1:f0:37:cf dst 10.4.7.22 self permanent #這個mac 就是另外一臺的宿主機的flannel.1 的mac ,這樣就實現了arp 解析了。 56:eb:a4:dd:7d:a5 dst 10.4.7.22 self permanent 6a:2c:6a:1e:2b:2e dst 10.4.7.22 self permanent 9a:53:36:4c:ef:12 dst 10.4.7.22 self permanent 06:ea:23:b0:6f:b5 dst 10.4.7.22 self permanent
flannel 另外兩種模式配置:
/opt/etcd/etcdctl set /coreos.com/network/config '{"Network": "172.7.0.0/16", "Backend": {"Type": "VxLAN","Directrouting": true}}' #配置vxlan 直接路由 VXLAN的Direct routing模式解釋: 兩個節點在同一網段時使用host-gw通信,如果不在同一網段中,即 當前pod所在節點與目標pod所在節點中間有路由器,就使用VXLAN這種方式,使用疊加網絡。 結合了Host-gw和VXLAN。 ./etcdctl set /coreos.com/network/config '{"Network": "172.7.0.0/16", "Backend": {"Type": "host-gw"}}' #這個是設置host-gw 的,這種模式node 上不會有flannel.1 的接口了,pod 的跨宿主及訪問路由先到 docker0 ,再通過宿主機的eth0 出去。這種適合宿主機在同一個網段的情況下,效率比vlxan還高,因爲沒有了vxlan 封裝了。 ip route ls default via 10.4.7.1 dev eth0 proto static metric 100 10.4.7.0/24 dev eth0 proto kernel scope link src 10.4.7.22 metric 100 172.7.21.0/24 via 10.4.7.21 dev eth0 172.7.22.0/24 dev docker0 proto kernel scope link src 172.7.22.1
5. 宿主機iptables 優化--非常重要
通過上面配置了 vxan 模式實現了跨宿主訪問,但是看日誌發下對方看到的flannel.1 的ip!起兩臺nginx pod,然後curl
kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-7bfb85948d-8d4wd 1/1 Running 0 3d19h 172.7.21.15 hdss7-21.host.com <none> <none> nginx-deployment-7bfb85948d-xg4bt 1/1 Running 1 3d19h 172.7.22.10 hdss7-22.host.com <none> <none> kubectl logs -f nginx-deployment-7bfb85948d-8d4wd #這個是21 上pod ,看到的卻不是172.7.22.10 的ip 172.7.22.0 - - [01/Jul/2020:16:45:16 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
修改iptables 規則----兩臺宿主機都要改!
上面情況是由於: A POSTROUTING -s 172.7.22.0/24 ! -o docker0 -j MASQUERADE 這條規則導致的! 這條規則意思是 172.7.22.0/24 不是 docker0 就轉換了。 因爲pod 出去是通過flannel.1 接口出了! 所以有了上面的規則後pod 的ip 就被轉成flannel.1 的ip 了! 改成: -A POSTROUTING -s 172.7.22.0/24 ! -d 172.7.0.0/16 ! -o docker0 -j MASQUERADE 172.7.0.0/16 是k8s 集羣的ip,意思是訪問k8s 集羣外部的ip 才做nat,這樣既保證了pod 可以出外網,也保證了集羣內部訪問pod ip 不會被轉換!
改完後再看訪問日誌:
172.7.22.10 - - [02/Jul/2020:19:19:58 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
172.7.22.10 - - [02/Jul/2020:19:20:00 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
可以看到pod 真是IP 了!