成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Kubernetes網(wǎng)絡(luò)分析之Flannel

codecraft / 712人閱讀

摘要:從分析可以看出,如果程序如果退出后,容器之間的通信將會(huì)中斷,這里需要注意。最后通過寫本地子網(wǎng)文件,通過這個(gè)文件設(shè)定的網(wǎng)絡(luò)。細(xì)心的讀者可能發(fā)現(xiàn)這里的并不是以太網(wǎng)規(guī)定的,這是因?yàn)橥鈱拥姆獍€要占據(jù)。

Flannel是cereos開源的CNI網(wǎng)絡(luò)插件,下圖flannel官網(wǎng)提供的一個(gè)數(shù)據(jù)包經(jīng)過封包、傳輸以及拆包的示意圖,從這個(gè)圖片中可以看出兩臺(tái)機(jī)器的docker0分別處于不同的段:10.1.20.1/24 和 10.1.15.1/24 ,如果從Web App Frontend1 pod(10.1.15.2)去連接另一臺(tái)主機(jī)上的Backend Service2 pod(10.1.20.3),網(wǎng)絡(luò)包從宿主機(jī)192.168.0.100發(fā)往192.168.0.200,內(nèi)層容器的數(shù)據(jù)包被封裝到宿主機(jī)的UDP里面,并且在外層包裝了宿主機(jī)的IP和mac地址。這就是一個(gè)經(jīng)典的overlay網(wǎng)絡(luò),因?yàn)槿萜鞯腎P是一個(gè)內(nèi)部IP,無法從跨宿主機(jī)通信,所以容器的網(wǎng)絡(luò)互通,需要承載到宿主機(jī)的網(wǎng)絡(luò)之上。

flannel支持多種網(wǎng)絡(luò)模式,常用的是vxlan、UDP、hostgw、ipip以及gce和阿里云等,vxlan和UDP的區(qū)別是:vxlan是內(nèi)核封包,而UDP是flanneld用戶態(tài)程序封包,所以UDP的方式性能會(huì)稍差;hostgw模式是一種主機(jī)網(wǎng)關(guān)模式,容器到另外一個(gè)主機(jī)上容器的網(wǎng)關(guān)設(shè)置成所在主機(jī)的網(wǎng)卡地址,這個(gè)和calico非常相似,只不過calico是通過BGP聲明,而hostgw是通過中心的etcd分發(fā),所以hostgw是直連模式,不需要通過overlay封包和拆包,性能比較高,但hostgw模式最大的缺點(diǎn)是必須是在一個(gè)二層網(wǎng)絡(luò)中,畢竟下一跳的路由需要在鄰居表中,否則無法通行。

在實(shí)際的生產(chǎn)環(huán)境中,最常用的還是vxlan模式,我們先看工作原理,然后通過源碼解析實(shí)現(xiàn)過程。

安裝的過程非常簡(jiǎn)單,主要分為兩步:

第一步安裝flannel

yum install flannel 或者通過kubernetes的daemonset方式啟動(dòng),配置flannel用的etcd地址

第二步配置集群網(wǎng)絡(luò)

curl -L http://etcdurl:2379/v2/keys/flannel/network/config -XPUT -d value="{"Network":"172.16.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan","VNI":1}}"

然后啟動(dòng)每個(gè)節(jié)點(diǎn)的flanned程序。

一、工作原理

1、容器的地址如何分配

Docker容器啟動(dòng)時(shí)通過docker0分配IP地址,flannel為每個(gè)機(jī)器分配一個(gè)IP段,配置在docker0上,容器啟動(dòng)后就在本段內(nèi)選擇一個(gè)未占用的IP,那么flannel如何修改docker0網(wǎng)段呢?

先看一下 flannel的啟動(dòng)文件 /usr/lib/systemd/system/flanneld.service

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/flanneld
ExecStart=/usr/bin/flanneld-start $FLANNEL_OPTIONS
ExecStartPost=/opt/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker

文件里面指定了flannel環(huán)境變量和啟動(dòng)腳本和啟動(dòng)后執(zhí)行腳本 ExecStartPost 設(shè)置的mk-docker-opts.sh,這個(gè)腳本的作用是生成/run/flannel/docker,文件內(nèi)容如下:

DOCKER_OPT_BIP="--bip=10.251.81.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=false"
DOCKER_OPT_MTU="--mtu=1450"
DOCKER_NETWORK_OPTIONS=" --bip=10.251.81.1/24 --ip-masq=false --mtu=1450"

而這個(gè)文件又被docker啟動(dòng)文件/usr/lib/systemd/system/docker.service所關(guān)聯(lián),

[Service]
Type=notify
NotifyAccess=all
EnvironmentFile=-/run/flannel/docker
EnvironmentFile=-/etc/sysconfig/docker

這樣便可以設(shè)置docker0的網(wǎng)橋了。

在開發(fā)環(huán)境中,有三臺(tái)機(jī)器,分別分配了如下網(wǎng)段:

host-139.245 10.254.44.1/24

host-139.246 10.254.60.1/24

host-139.247 10.254.50.1/24

2、容器如何通信

上面介紹了為每個(gè)容器分配IP,那么不同主機(jī)上的容器如何通信呢,我們用最常見的vxlan舉例,這里有三個(gè)關(guān)鍵點(diǎn),一個(gè)路由,一個(gè)arp,一個(gè)FDB。我們按照容器發(fā)包的過程,逐一分析上面三個(gè)元素的作用,首先容器出來的數(shù)據(jù)包會(huì)經(jīng)過docker0,那么下面是直接從主機(jī)網(wǎng)絡(luò)出去,還是通過vxlan封包轉(zhuǎn)發(fā)呢?這是每個(gè)機(jī)器上面路由設(shè)定的。

 #ip route  show dev flannel.1
10.254.50.0/24 via 10.254.50.0 onlink
10.254.60.0/24 via 10.254.60.0 onlink

可以看到每個(gè)主機(jī)上面都有到另外兩臺(tái)機(jī)器的路由,這個(gè)路由是onlink路由,onlink參數(shù)表明強(qiáng)制此網(wǎng)關(guān)是“在鏈路上”的(雖然并沒有鏈路層路由),否則linux上面是沒法添加不同網(wǎng)段的路由。這樣數(shù)據(jù)包就能知道,如果是容器直接的訪問則交給flannel.1設(shè)備處理。

flannel.1這個(gè)虛擬網(wǎng)絡(luò)設(shè)備將會(huì)對(duì)數(shù)據(jù)封包,但下面一個(gè)問題又來了,這個(gè)網(wǎng)關(guān)的mac地址是多少呢?因?yàn)檫@個(gè)網(wǎng)關(guān)是通過onlink設(shè)置的,flannel會(huì)下發(fā)這個(gè)mac地址,查看一下arp表

# ip neig show dev flannel.1
10.254.50.0 lladdr ba:10:0e:7b:74:89 PERMANENT
10.254.60.0 lladdr 92:f3:c8:b2:6e:f0 PERMANENT

可以看到這個(gè)網(wǎng)關(guān)對(duì)應(yīng)的mac地址,這樣內(nèi)層的數(shù)據(jù)包就封裝好了

還是最后一個(gè)問題,外出的數(shù)據(jù)包的目的IP是多少呢?換句話說,這個(gè)封裝后的數(shù)據(jù)包應(yīng)該發(fā)往那一臺(tái)機(jī)器呢?難不成每個(gè)數(shù)據(jù)包都廣播。vxlan默認(rèn)實(shí)現(xiàn)第一次確實(shí)是通過廣播的方式,但flannel再次采用一種hack方式直接下發(fā)了這個(gè)轉(zhuǎn)發(fā)表FDB

# bridge fdb show dev flannel.1
92:f3:c8:b2:6e:f0 dst 10.100.139.246 self permanent
ba:10:0e:7b:74:89 dst 10.100.139.247 self permanent

這樣對(duì)應(yīng)mac地址轉(zhuǎn)發(fā)目標(biāo)IP便可以獲取到了。

這里還有個(gè)地方需要注意,無論是arp表還是FDB表都是permanent,它表明寫記錄是手動(dòng)維護(hù)的,傳統(tǒng)的arp獲取鄰居的方式是通過廣播獲取,如果收到對(duì)端的arp相應(yīng)則會(huì)標(biāo)記對(duì)端為reachable,在超過reachable設(shè)定時(shí)間后,如果發(fā)現(xiàn)對(duì)端失效會(huì)標(biāo)記為stale,之后會(huì)轉(zhuǎn)入的delay以及probe進(jìn)入探測(cè)的狀態(tài),如果探測(cè)失敗會(huì)標(biāo)記為Failed狀態(tài)。之所以介紹arp的基礎(chǔ)內(nèi)容,是因?yàn)槔习姹镜膄lannel并非使用本文上面的方式,而是采用一種臨時(shí)的arp方案,此時(shí)下發(fā)的arp表示reachable狀態(tài),這就意味著,如果在flannel宕機(jī)超過reachable超時(shí)時(shí)間的話,那么這臺(tái)機(jī)器上面的容器的網(wǎng)絡(luò)將會(huì)中斷,我們簡(jiǎn)單回顧試一下之前(0.7.x)版本的做法,容器為了為了能夠獲取到對(duì)端arp地址,內(nèi)核會(huì)首先發(fā)送arp征詢,如果嘗試

/proc/sys/net/ipv4/neigh/$NIC/ucast_solicit

此時(shí)后會(huì)向用戶空間發(fā)送arp征詢

/proc/sys/net/ipv4/neigh/$NIC/app_solicit

之前版本的flannel正是利用這個(gè)特性,設(shè)定

# cat   /proc/sys/net/ipv4/neigh/flannel.1/app_solicit
3

從而flanneld便可以獲取到內(nèi)核發(fā)送到用戶空間的L3MISS,并且配合etcd返回這個(gè)IP地址對(duì)應(yīng)的mac地址,設(shè)置為reachable。從分析可以看出,如果flanneld程序如果退出后,容器之間的通信將會(huì)中斷,這里需要注意。Flannel的啟動(dòng)流程如下圖所示:

Flannel啟動(dòng)執(zhí)行newSubnetManager,通過他創(chuàng)建后臺(tái)數(shù)據(jù)存儲(chǔ),當(dāng)前有支持兩種后端,默認(rèn)是etcd存儲(chǔ),如果flannel啟動(dòng)指定“kube-subnet-mgr”參數(shù)則使用kubernetes的接口存儲(chǔ)數(shù)據(jù)。

具體代碼如下:

func newSubnetManager() (subnet.Manager, error) {
    if opts.kubeSubnetMgr {
       return kube.NewSubnetManager(opts.kubeApiUrl, opts.kubeConfigFile)
    }
  
    cfg := &etcdv2.EtcdConfig{
       Endpoints: strings.Split(opts.etcdEndpoints, ","),
       Keyfile:   opts.etcdKeyfile,
       Certfile:  opts.etcdCertfile,
       CAFile:    opts.etcdCAFile,
       Prefix:    opts.etcdPrefix,
       Username:  opts.etcdUsername,
       Password:  opts.etcdPassword,
    }
  
    // Attempt to renew the lease for the subnet specified in the subnetFile
    prevSubnet := ReadCIDRFromSubnetFile(opts.subnetFile, "FLANNEL_SUBNET")
  
    return etcdv2.NewLocalManager(cfg, prevSubnet)
 }

通過SubnetManager,結(jié)合上面介紹部署的時(shí)候配置的etcd的數(shù)據(jù),可以獲得網(wǎng)絡(luò)配置信息,主要指backend和網(wǎng)段信息,如果是vxlan,通過NewManager創(chuàng)建對(duì)應(yīng)的網(wǎng)絡(luò)管理器,這里用到簡(jiǎn)單工程模式,首先每種網(wǎng)絡(luò)模式管理器都會(huì)通過init初始化注冊(cè),

如vxlan

func init() {
    backend.Register("vxlan", New)

如果是udp

  func init() {
    backend.Register("udp", New)
 }

其它也是類似,將構(gòu)建方法都注冊(cè)到一個(gè)map里面,從而根據(jù)etcd配置的網(wǎng)絡(luò)模式,設(shè)定啟用對(duì)應(yīng)的網(wǎng)絡(luò)管理器。

3、注冊(cè)網(wǎng)絡(luò)

RegisterNetwork,首先會(huì)創(chuàng)建flannel.vxlanID的網(wǎng)卡,默認(rèn)vxlanID是1.然后就是向etcd注冊(cè)租約并且獲取相應(yīng)的網(wǎng)段信息,這樣有個(gè)細(xì)節(jié),老版的flannel每次啟動(dòng)都是去獲取新的網(wǎng)段,新版的flannel會(huì)遍歷etcd里面已經(jīng)注冊(cè)的etcd信息,從而獲取之前分配的網(wǎng)段,繼續(xù)使用。

最后通過WriteSubnetFile寫本地子網(wǎng)文件,

    # cat /run/flannel/subnet.env 
FLANNEL_NETWORK=10.254.0.0/16
FLANNEL_SUBNET=10.254.44.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

通過這個(gè)文件設(shè)定docker的網(wǎng)絡(luò)。細(xì)心的讀者可能發(fā)現(xiàn)這里的MTU并不是以太網(wǎng)規(guī)定的1500,這是因?yàn)橥鈱拥膙xlan封包還要占據(jù)50 Byte。

當(dāng)然flannel啟動(dòng)后還需要持續(xù)的watch etcd里面的數(shù)據(jù),這是當(dāng)有新的flannel節(jié)點(diǎn)加入,或者變更的時(shí)候,其他flannel節(jié)點(diǎn)能夠動(dòng)態(tài)更新的那三張表。主要的處理方法都在handleSubnetEvents里面

    func (nw *network) handleSubnetEvents(batch []subnet.Event) {
 . . .
  
       switch event.Type {//如果是有新的網(wǎng)段加入(新的主機(jī)加入)
       case subnet.EventAdded:
  . . .//更新路由表
if err := netlink.RouteReplace(&directRoute); err != nil {
    log.Errorf("Error adding route to %v via %v: %v", sn, attrs.PublicIP, err)
    continue
 } 
//添加arp表
log.V(2).Infof("adding subnet: %s PublicIP: %s VtepMAC: %s", sn, attrs.PublicIP, net.HardwareAddr(vxlanAttrs.VtepMAC))
             if err := nw.dev.AddARP(neighbor{IP: sn.IP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
                log.Error("AddARP failed: ", err)
                continue
             }
 //添加FDB表
             if err := nw.dev.AddFDB(neighbor{IP: attrs.PublicIP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
                log.Error("AddFDB failed: ", err)
  
                              if err := nw.dev.DelARP(neighbor{IP: event.Lease.Subnet.IP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
                   log.Error("DelARP failed: ", err)
                }
  
                continue
             }//如果是刪除實(shí)踐
      case subnet.EventRemoved:
//刪除路由
             if err := netlink.RouteDel(&directRoute); err != nil {
                log.Errorf("Error deleting route to %v via %v: %v", sn, attrs.PublicIP, err)
             
          } else {
             log.V(2).Infof("removing subnet: %s PublicIP: %s VtepMAC: %s", sn, attrs.PublicIP, net.HardwareAddr(vxlanAttrs.VtepMAC))
  
           //刪除arp            if err := nw.dev.DelARP(neighbor{IP: sn.IP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
                log.Error("DelARP failed: ", err)
             }
 //刪除FDB
             if err := nw.dev.DelFDB(neighbor{IP: attrs.PublicIP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
                log.Error("DelFDB failed: ", err)
             }
  
             if err := netlink.RouteDel(&vxlanRoute); err != nil {
                log.Errorf("failed to delete vxlanRoute (%s -> %s): %v", vxlanRoute.Dst, vxlanRoute.Gw, err)
             }
          }
       default:
          log.Error("internal error: unknown event type: ", int(event.Type))
       }
    }
 }

這樣flannel里面任何主機(jī)的添加和刪除都可以被其它節(jié)點(diǎn)所感知到,從而更新本地內(nèi)核轉(zhuǎn)發(fā)表。

作者:陳曉宇

來源:宜信技術(shù)學(xué)院

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/32984.html

相關(guān)文章

  • Kubernetes 1.14 正式發(fā)布,Windows節(jié)點(diǎn)生產(chǎn)級(jí)支持!

    摘要:此次新版的最重大更新無疑為對(duì)節(jié)點(diǎn)的生產(chǎn)級(jí)支持。持久化本地存儲(chǔ)的最主要用例是分布式文件系統(tǒng)和數(shù)據(jù)庫(kù),主要是由于性能和成本的原因。在裸機(jī)上,除了性能之外,本地存儲(chǔ)通常也更便宜,并且使用它是配置分布式文件系統(tǒng)的必要條件。 Kubernetes 1.14現(xiàn)已正式發(fā)布,這是Kubernetes在2019年的首次更新! Kubernetes 1.14由31個(gè)增強(qiáng)功能組成:10個(gè)功能現(xiàn)進(jìn)入Stabl...

    wean 評(píng)論0 收藏0
  • Kubernetes Master High Availability 高級(jí)實(shí)踐

    摘要:才云科技云開源高級(jí)工程師唐繼元受邀社群,在線分享高級(jí)實(shí)踐,介紹如何構(gòu)建環(huán)境。除命令外的停止都是異常停止。 才云科技云開源高級(jí)工程師唐繼元受邀DBAplus社群,在線分享《Kubernetes Master High Availability 高級(jí)實(shí)踐》,介紹如何構(gòu)建Kubernetes Master High Availability環(huán)境。 以下是分享實(shí)錄: 大家好,我是才云科技的唐繼...

    JiaXinYi 評(píng)論0 收藏0
  • 關(guān)于容器,你不能不看這篇

    摘要:其次,青云的負(fù)載均衡器能感知到容器網(wǎng)絡(luò),而傳統(tǒng)的方案在內(nèi)部還需要再做一層虛擬網(wǎng)絡(luò),層的負(fù)載均衡器無法感知容器網(wǎng)絡(luò)。 前言 容器技術(shù)目前的市場(chǎng)現(xiàn)狀是一家獨(dú)大、百花齊放。 關(guān)于容器技術(shù),看看青云QingCloud 王淵命(老王)是如何看待它的,本文來自他在青云QingCloud 深圳站實(shí)踐課堂的演講。全文 2780字,閱讀時(shí)長(zhǎng)約為 11 分鐘。 容器是什么 容器的概念外延比較廣,討論的時(shí)候...

    zzzmh 評(píng)論0 收藏0
  • k8s與網(wǎng)絡(luò)--Flannel解讀

    摘要:是一個(gè)專為定制的三層網(wǎng)絡(luò)解決方案,主要用于解決容器的跨主機(jī)通信問題。收到的數(shù)據(jù)包被轉(zhuǎn)發(fā)到進(jìn)程。查詢路由表,解封包,并將數(shù)據(jù)包發(fā)送到。然后在網(wǎng)絡(luò)層的源和目的均是容器的,虛擬。默認(rèn)也是使用容器網(wǎng)絡(luò)方案,其官網(wǎng)也清晰的畫出了的。 前言 我們知道docker官方并沒有提供多主機(jī)的容器通信方案,單機(jī)網(wǎng)絡(luò)的模式主要有host,container,brige,none。none這種模式,顧名思義就是...

    laznrbfe 評(píng)論0 收藏0
  • k8s與網(wǎng)絡(luò)--Flannel解讀

    摘要:是一個(gè)專為定制的三層網(wǎng)絡(luò)解決方案,主要用于解決容器的跨主機(jī)通信問題。收到的數(shù)據(jù)包被轉(zhuǎn)發(fā)到進(jìn)程。查詢路由表,解封包,并將數(shù)據(jù)包發(fā)送到。然后在網(wǎng)絡(luò)層的源和目的均是容器的,虛擬。默認(rèn)也是使用容器網(wǎng)絡(luò)方案,其官網(wǎng)也清晰的畫出了的。 前言 我們知道docker官方并沒有提供多主機(jī)的容器通信方案,單機(jī)網(wǎng)絡(luò)的模式主要有host,container,brige,none。none這種模式,顧名思義就是...

    Pink 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<