K8S flannel 網絡

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 了!

  

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章