摘要:今天主要針對版本進行源碼分析。外部接口的定義如下創(chuàng)建子網(wǎng)管理器負責子網(wǎng)的創(chuàng)建更新添加刪除監(jiān)聽等,主要和打交道定義續(xù)約。在到期之前,子網(wǎng)管理器調(diào)用該方法進行續(xù)約。
前言
之前在k8s與網(wǎng)絡(luò)--Flannel解讀一文中,我們主要講了Flannel整體的工作原理。今天主要針對Flannel v0.10.0版本進行源碼分析。首先需要理解三個比較重要的概念:
網(wǎng)絡(luò)(Network):整個集群中分配給 flannel 要管理的網(wǎng)絡(luò)地址范圍
子網(wǎng)(Subnet):flannel 所在的每臺主機都會管理 network 中一個子網(wǎng),子網(wǎng)的掩碼和范圍是可配置的
后端(Backend):使用什么樣的后端網(wǎng)絡(luò)模型,比如默認的 udp,還是 vxlan 等
源碼分析整體的代碼組織如下:
除了可執(zhí)行文件的入口 main.go之外,有backend,network,pkg和subnet這么幾個代碼相關(guān)的文件夾。
network主要是iptables相關(guān)。主要是供main函數(shù)根據(jù)設(shè)置進行MasqRules和ForwardRules規(guī)則的設(shè)定。
pkg主要是抽象封裝的ip功能庫。
backed 主要是后端實現(xiàn),目前支持 udp、vxlan、host-gw 等。
subnet 子網(wǎng)管理。主要支持etcdv2和k8s兩種實現(xiàn)。
啟動參數(shù)name | 默認值 | 說明 |
---|---|---|
etcd-endpoints | http://127.0.0.1:4001,http://127.0.0.1:2379 | etcd終端節(jié)點列表 |
etcd-prefix | /coreos.com/network | etcd 前綴 |
etcd-keyfile | 無 | SSL key文件 |
etcd-certfile | 無 | SSL certification 文件 |
etcd-cafile | 無 | SSL Certificate Authority 文件 |
etcd-username | 無 | 通過BasicAuth訪問etcd 的用戶名 |
etcd-password | 無 | 通過BasicAuth訪問etcd 的密碼 |
iface | 無 | 完整的網(wǎng)卡名或ip地址 |
iface-regex | 無 | 正則表達式表示的網(wǎng)卡名或ip地址 |
subnet-file | /run/flannel/subnet.env | 存放運行時需要的一些變量 (subnet, MTU, ... )的文件名 |
public-ip | 無 | 主機IP |
subnet-lease-renew-margin | 60分鐘 | 在租約到期之前多長時間進行更新 |
ip-masq | false | 是否為覆蓋網(wǎng)絡(luò)外部的流量設(shè)置IP偽裝規(guī)則 |
kube-subnet-mgr | false | 是否使用k8s作為subnet的實現(xiàn)方式 |
kube-api-url | "" | Kubernetes API server URL ,如果集群內(nèi)部署,則不需要設(shè)置,做好rbac授權(quán)即可 |
kubeconfig-file | "" | kubeconfig file 位置,如果集群內(nèi)部署,則不需要設(shè)置,做好rbac授權(quán)即可 |
healthz-ip | 0.0.0.0 | 要監(jiān)聽的healthz服務器的IP地址 |
healthz-port | 0 | 要監(jiān)聽的healthz服務器的端口,0 表示停用 |
從main函數(shù)開始分析,主要步驟如下:
1. 校驗subnet-lease-renew-marginif opts.subnetLeaseRenewMargin >= 24*60 || opts.subnetLeaseRenewMargin <= 0 { log.Error("Invalid subnet-lease-renew-margin option, out of acceptable range") os.Exit(1) }
需要小于等于24h,大于0。
2. 計算去使用哪一個網(wǎng)絡(luò)接口假如主機有多個網(wǎng)卡,flannel會使用哪一個?
這就和咱們前面提到的iface和iface-regex兩個參數(shù)有關(guān)。這兩個參數(shù)每一個可以指定多個。flannel將按照下面的優(yōu)先順序來選?。?br>1) 如果”–iface”和”—-iface-regex”都未指定時,則直接選取默認路由所使用的輸出網(wǎng)卡
2) 如果”–iface”參數(shù)不為空,則依次遍歷其中的各個實例,直到找到和該網(wǎng)卡名或IP匹配的實例為止
3) 如果”–iface-regex”參數(shù)不為空,操作方式和2)相同,唯一不同的是使用正則表達式去匹配
最后,對于集群間交互的Public IP,我們同樣可以通過啟動參數(shù)”–public-ip”進行指定。否則,將使用上文中獲取的網(wǎng)卡的IP作為Public IP。
外部接口的定義如下:
type ExternalInterface struct { Iface *net.Interface IfaceAddr net.IP ExtAddr net.IP }3.創(chuàng)建SubnetManager
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 := ReadSubnetFromSubnetFile(opts.subnetFile) return etcdv2.NewLocalManager(cfg, prevSubnet) }
子網(wǎng)管理器負責子網(wǎng)的創(chuàng)建、更新、添加、刪除、監(jiān)聽等,主要和 etcd 打交道,定義:
type Manager interface { GetNetworkConfig(ctx context.Context) (*Config, error) AcquireLease(ctx context.Context, attrs *LeaseAttrs) (*Lease, error) RenewLease(ctx context.Context, lease *Lease) error WatchLease(ctx context.Context, sn ip.IP4Net, cursor interface{}) (LeaseWatchResult, error) WatchLeases(ctx context.Context, cursor interface{}) (LeaseWatchResult, error) Name() string }
RenewLease 續(xù)約。在lease到期之前,子網(wǎng)管理器調(diào)用該方法進行續(xù)約。
GetNetworkConfig 獲取本機的subnet配置,進行一些初始化的工作。
4. 獲取網(wǎng)絡(luò)配置config, err := getConfig(ctx, sm) if err == errCanceled { wg.Wait() os.Exit(0) }
這個配置主要是管理網(wǎng)絡(luò)的配置,需要在flannel啟動之前寫到etcd中。例如:
{ "Network": "10.0.0.0/8", "SubnetLen": 20, "SubnetMin": "10.10.0.0", "SubnetMax": "10.99.0.0", "Backend": { "Type": "udp", "Port": 7890 } }
/coreos.com/network/config 保存著上面網(wǎng)絡(luò)配置數(shù)據(jù)。
詳細解讀一下:
SubnetLen表示每個主機分配的subnet大小,我們可以在初始化時對其指定,否則使用默認配置。在默認配置的情況下,如果集群的網(wǎng)絡(luò)地址空間大于/24,則SubnetLen配置為24,否則它比集群網(wǎng)絡(luò)地址空間小1,例如集群的大小為/25,則SubnetLen的大小為/26
SubnetMin是集群網(wǎng)絡(luò)地址空間中最小的可分配的subnet,可以手動指定,否則默認配置為集群網(wǎng)絡(luò)地址空間中第一個可分配的subnet。
SubnetMax表示最大可分配的subnet
BackendType為使用的backend的類型,如未指定,則默認為“udp”
Backend中會包含backend的附加信息,例如backend為vxlan時,其中會存儲vtep設(shè)備的mac地址
5. 創(chuàng)建backend管理器,然后使用它來創(chuàng)建backend并使用它注冊網(wǎng)絡(luò),然后執(zhí)行run方法bm := backend.NewManager(ctx, sm, extIface) be, err := bm.GetBackend(config.BackendType) if err != nil { log.Errorf("Error fetching backend: %s", err) cancel() wg.Wait() os.Exit(1) } bn, err := be.RegisterNetwork(ctx, config) if err != nil { log.Errorf("Error registering network: %s", err) cancel() wg.Wait() os.Exit(1) } ... log.Info("Running backend.") wg.Add(1) go func() { bn.Run(ctx) wg.Done() }()
backend管理器
type manager struct { ctx context.Context sm subnet.Manager extIface *ExternalInterface mux sync.Mutex active map[string]Backend wg sync.WaitGroup }
主要是提供了GetBackend(backendType string) (Backend, error)方法,根據(jù)配置文件的設(shè)置backend標志,生產(chǎn)對應的backend。
此處注意
go func() { <-bm.ctx.Done() // TODO(eyakubovich): this obviosly introduces a race. // GetBackend() could get called while we are here. // Currently though, all backends" Run exit only // on shutdown bm.mux.Lock() delete(bm.active, betype) bm.mux.Unlock() bm.wg.Done() }()
在生產(chǎn)backend以后,會啟動一個協(xié)程,在flanneld退出運行之前,將會執(zhí)行激活的backend map中刪除操作。
最后run方法:
func (n *RouteNetwork) Run(ctx context.Context) { wg := sync.WaitGroup{} log.Info("Watching for new subnet leases") evts := make(chan []subnet.Event) wg.Add(1) go func() { subnet.WatchLeases(ctx, n.SM, n.SubnetLease, evts) wg.Done() }() n.routes = make([]netlink.Route, 0, 10) wg.Add(1) go func() { n.routeCheck(ctx) wg.Done() }() defer wg.Wait() for { select { case evtBatch := <-evts: n.handleSubnetEvents(evtBatch) case <-ctx.Done(): return } } }
run方法中主要是執(zhí)行:
subnet 負責和 etcd 交互,把 etcd 中的信息轉(zhuǎn)換為 flannel 的子網(wǎng)數(shù)據(jù)結(jié)構(gòu),并對 etcd 進行子網(wǎng)和網(wǎng)絡(luò)的監(jiān)聽;
backend 接受 subnet 的監(jiān)聽事件,并做出對應的處理。
事件主要是subnet.EventAdded和subnet.EventRemoved兩個。
添加子網(wǎng)事件發(fā)生時的處理步驟:檢查參數(shù)是否正常,根據(jù)參數(shù)構(gòu)建路由表項,把路由表項添加到主機,把路由表項添加到自己的數(shù)據(jù)結(jié)構(gòu)中。
刪除子網(wǎng)事件發(fā)生時的處理步驟:檢查參數(shù)是否正常,根據(jù)參數(shù)構(gòu)建路由表項,把路由表項從主機刪除,把路由表項從管理的數(shù)據(jù)結(jié)構(gòu)中刪除
6. 其他除了上面的核心的邏輯,還有一些iptables規(guī)則和SubnetFile相關(guān)的操作。
// Set up ipMasq if needed if opts.ipMasq { go network.SetupAndEnsureIPTables(network.MasqRules(config.Network, bn.Lease())) } // Always enables forwarding rules. This is needed for Docker versions >1.13 (https://docs.docker.com/engine/userguide/networking/default_network/container-communication/#container-communication-between-hosts) // In Docker 1.12 and earlier, the default FORWARD chain policy was ACCEPT. // In Docker 1.13 and later, Docker sets the default policy of the FORWARD chain to DROP. go network.SetupAndEnsureIPTables(network.ForwardRules(config.Network.String()))
可以看出主要是調(diào)用了network文件里的SetupAndEnsureIPTables方法。
PS
在Docker 1.13及更高版本中,Docker設(shè)置了FORWARD的默認策略是drop,所以需要flannel做一些工作。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/33085.html
摘要:今天主要針對版本進行源碼分析。外部接口的定義如下創(chuàng)建子網(wǎng)管理器負責子網(wǎng)的創(chuàng)建更新添加刪除監(jiān)聽等,主要和打交道定義續(xù)約。在到期之前,子網(wǎng)管理器調(diào)用該方法進行續(xù)約。 前言 之前在k8s與網(wǎng)絡(luò)--Flannel解讀一文中,我們主要講了Flannel整體的工作原理。今天主要針對Flannel v0.10.0版本進行源碼分析。首先需要理解三個比較重要的概念: 網(wǎng)絡(luò)(Network):整個集群中...
摘要:今天主要針對版本進行源碼分析。外部接口的定義如下創(chuàng)建子網(wǎng)管理器負責子網(wǎng)的創(chuàng)建更新添加刪除監(jiān)聽等,主要和打交道定義續(xù)約。在到期之前,子網(wǎng)管理器調(diào)用該方法進行續(xù)約。 前言 之前在k8s與網(wǎng)絡(luò)--Flannel解讀一文中,我們主要講了Flannel整體的工作原理。今天主要針對Flannel v0.10.0版本進行源碼分析。首先需要理解三個比較重要的概念: 網(wǎng)絡(luò)(Network):整個集群中...
摘要:即配置網(wǎng)絡(luò)和解除網(wǎng)絡(luò)配置。類類型的插件,在執(zhí)行命令時會分配一個給調(diào)用者。執(zhí)行命令時會將調(diào)用者指定的放回池。向刪除時,同樣通過請求,解除該的租約。組件通常在組件執(zhí)行完畢后執(zhí)行 目前不論是個人還是企業(yè),在使用k8s時,都會采用CNI作為集群網(wǎng)絡(luò)方案實現(xiàn)的規(guī)范。 在早先的k8s版本中,kubelet代碼里提供了networkPlugin,networkPlugin是一組接口,實現(xiàn)了pod的網(wǎng)...
摘要:是一個專為定制的三層網(wǎng)絡(luò)解決方案,主要用于解決容器的跨主機通信問題。收到的數(shù)據(jù)包被轉(zhuǎn)發(fā)到進程。查詢路由表,解封包,并將數(shù)據(jù)包發(fā)送到。然后在網(wǎng)絡(luò)層的源和目的均是容器的,虛擬。默認也是使用容器網(wǎng)絡(luò)方案,其官網(wǎng)也清晰的畫出了的。 前言 我們知道docker官方并沒有提供多主機的容器通信方案,單機網(wǎng)絡(luò)的模式主要有host,container,brige,none。none這種模式,顧名思義就是...
摘要:是一個專為定制的三層網(wǎng)絡(luò)解決方案,主要用于解決容器的跨主機通信問題。收到的數(shù)據(jù)包被轉(zhuǎn)發(fā)到進程。查詢路由表,解封包,并將數(shù)據(jù)包發(fā)送到。然后在網(wǎng)絡(luò)層的源和目的均是容器的,虛擬。默認也是使用容器網(wǎng)絡(luò)方案,其官網(wǎng)也清晰的畫出了的。 前言 我們知道docker官方并沒有提供多主機的容器通信方案,單機網(wǎng)絡(luò)的模式主要有host,container,brige,none。none這種模式,顧名思義就是...
閱讀 2269·2021-11-23 09:51
閱讀 5656·2021-09-22 15:39
閱讀 3343·2021-09-02 15:15
閱讀 3492·2019-08-30 15:54
閱讀 2354·2019-08-30 15:53
閱讀 1397·2019-08-30 14:04
閱讀 2445·2019-08-29 18:33
閱讀 2364·2019-08-29 13:08