总结:目前我们主要做版本源码分析。 外部接口的定义如下。 创建子网管理员负责子网的创建、更新、添加、删除、监控等。 主要处理更新定义。 到期前,子网管理器调用该方法进行续订。
简介
上一篇文章《K8s与网络--解读Flannel》主要围绕我讲解了Flannel的整体工作原理。关于它。 。 今天我们主要分析Flannel v0.10.0版本的源码。 首先,您需要了解三个重要概念:
网络:分配给 Flannel 进行集群范围管理的网络地址范围。
子网:Flannel 所在的网络中每个主机都有一个子网、子网掩码和范围。是可配置的。
Backend:使用的后端网络模型类型,例如默认UDP或VXLAN。
源码分析
整体代码结构如下。
除了可执行入口main.go之外,还有几个与代码相关的文件夹。 后端、网络、包、子网等。
网络主要和iptables相关。 主要是根据你的配置设置MasqRules和ForwardRules规则的main函数。
pkg主要是一个抽象封装的IP函数库。
backed主要是后端实现,目前支持udp、vxlan、host-gw等。
子网 子网管理。 它主要支持两种实现:etcdv2和k8s。
启动参数
名称 | 默认值 | 描述 |
---|---|---|
etcd-端点 | http://127.0.0.1:4001,http://127.0.0.1:2379 | etcd终端节点列表 |
etcd-前缀 | /coreos.com/network | etcd 前缀 |
etcd-密钥文件 | 无 | SSL密钥文件 |
etcd-certfile | 无 | SSL证书文件 |
etcd-cafile | 无 | SSL证书颁发机构文件 |
etcd-用户名 | 无 | 通过 BasicAuth 访问 etcd 的用户名 |
etcd-密码 | 无 | 通过BasicAuth访问etcd的密码 |
iface | 无 | 完整网卡名称或IP地址 |
iface-regex | 无 | 网卡作为正则表达式名称或IP地址 |
subnet-file | /run/flannel/subnet.env | 运行时所需的变量要保存的文件名(子网、MTU等) |
public-ip | 无 | 主机 IP |
子网 - 租用e-续订-保证金 | 60分钟 | 租约到期前的持续时间 |
ip [ k4 ]masq | false | 是否对覆盖网络外的流量设置IP伪装规则 |
kube-subnet-mgr | false | 是否使用k8s作为子网的实现方式 |
kube-api -url | "" | Kubernetes API 服务器 URL。 如果部署在集群中,则无需配置。 只需完成rbac认证即可。 |
kubeconfig-file | "" | kubeconfig 文件的位置。 如果部署在集群中,则无需配置。 只需完成rbac认证即可。 |
healthz-ip | 0.0.0.0 | 需要监控的healthz服务器IP地址 |
healthz -port | 0 | 要监控的 healthz 服务器端口。 0表示禁用 |
分析
从主函数开始分析。 主要步骤是:
1. 检查子网-租用-续订-保证金
如果 opts.subnetLeaseRenewMargin > = 24*60 || opts.subnetLeaseRenewMargin <= 0 { log.Error("无效子网-租用-通道w-margin 可选,超出范围") os.Exit(1) }
必须小于或等于 24 小时且大于 0。
2. 网络使用计算接口
如果主机有多个网卡,Flannel 应该使用哪一个?
这就是前面提到的 iface 和 iface-regex 相关的两个可能的规格。按以下优先顺序选择:
1) 如果既没有指定“--iface”也没有指定“--iface-regex”,则默认路由中使用的那个。 直接选择输出网卡。
2)如果“-iface”参数不为空,则会依次遍历每个实例,直到找到与网卡名称或IP匹配的实例。
3)如果“-iface-regex”参数不为空,则操作与2)相同,唯一的区别是使用正则表达式进行匹配。
最后,还可以通过启动参数“-public-ip”指定集群之间通信的公共IP。 否则,将使用上面获取的网卡IP作为公网IP。
外部接口的定义为:
typeExternalInterface struct { Iface *net.Interface IfaceAddr net.IP ExtAddr net.IP}
3 . 创建 SubnetManager
func newSubnetManager() (subnet.Manager, error) { if opts .kubeSubnetMgr { return kube.NewSubnetManager(opts.kubeApiUrl, opts.kubeConfigFil)e) } cfg := &etcdv2.EtcdConfig{ 端点:strings.Split(opts.etcdEndpoints, ","),密钥文件:opts.etcdKeyfile,证书文件:opts.etcdCertfile,CA 文件:opts.etcdCAFile,前缀:opts。 etcdPrefix, Username: opts.etcdUsername, Password: opts.etcdPassword, } // 尝试续订由subnetFile指定的子网的租约 prevSubnet := ReadSubnetFromSubnetFile(opts.subnetFile) return etcdv2.NewLocalManager(cfg, prevSubnet )}
子网管理员创建、更新、添加、删除和监控子网。 主要处理etcd。 定义:
type Manager接口{ GetNetworkConfig(ctx context.Context) (*Config, error) AcquireLease(ctx context.Context, attrs *LeaseAttrs) (*Lease, error) RenewLease(ctx context.Context,租赁 *Lease) 错误 WatchLease(ctx context.Context, sn ip.IP4Net, 游标接口 {}) (LeaseWatchResult, error) WatchLeases(ctx context.Context, 游标接口 {}) (LeaseWatchResult, error) Name() string}
RenewLease 刷新 . 子网管理器调用此方法在租约到期之前续订租约。
GetNetworkConfig 检索本地计算机的子网配置并执行一些初始化任务。
4. 获取网络配置
config, err := getConfig(ctx, sm) if err == errCanceled { wg.Wait() os.Exit(0) }
此配置主要是管理网络配置,必须在 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 存储上述网络配置数据。
详细说明:
SubnetLen表示分配给每个主机的子网大小。 您可以在初始化期间指定它。 否则,使用默认配置。 在默认配置中,如果集群的网络地址空间大于/24,则 SubnetLen 将配置为 24。 否则,它将比集群网络地址空间减一,例如集群的大小。如果是/25,则SubnetLen的大小是/26。
SubnetMin是集群网络地址空间内可以分配的最小子网,可以手动指定。 否则,默认配置是群集网络地址空间中的第一个可分配子网。 子网。
SubnetMax表示可以分配的最大子网。
BackendType 是使用的后端类型。 如果未指定,则默认为“udp”。
后端包含有关后端的附加信息。 例如,如果后端是vxlan,则存储VTEP设备的MAC地址。
5.创建后端管理器,用它创建后端,注册网络,然后执行run方法。
bm := backend.NewManager(ctx, sm, extIface) be, err := bm.GetBackend(config.BackendType) if err != nil { log.Errorf("获取后端时出错: %s " , err) cancel() wg.Wait() os.Exit(1) } bn, err := be.RegisterNetwork(ctx, config) if err != nil { log.Errorf("网络注册错误: % s" , err) cancel() wg.Wait() os.Exit(1) }...log.Info ("正在运行后端。") wg.Add(1) go func() { bn .Run(ctx) wg.完毕 () }()
后端管理器
type manager struct { ctx context.Context smsubnet.Manager extIface *ExternalInterface muxsync.Mutex active map[string]Backend wgsync.WaitGroup }
主要提供GetBackend(backendType string)(Backend, error)方法,根据配置文件中设置的后端标志生成对应的后端。
请注意此处
go func() { <-bm.ctx.Done() // TODO(eyakubovich):这显然引入了一场竞赛。 // 此处可能会调用 GetBackend()。 // 但是,当前所有后端仅在退出时执行 // 在关闭时 bm.mux.Lock() delete(bm.active, betype) bm.mux.Unlock() bm.wg.Done() } ( )
后端生成后,flanneld 完成之前,启动一个协程,对激活的后端映射执行删除操作。
func (n * root network)。Run(ctx context.Context) { wg :=sync.WaitGroup{} log.Info("监控新子网租用") 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方法主要执行以下内容。
子网与etcd交互,将etcd中的信息转换为flannel子网数据结构,并运行etcd。 监控子网和网络。
后端接收来自子网的监控事件并进行相应处理。
事件主要是subnet.EventAdded和subnet.EventRemoved。
发生子网添加事件时采取的步骤:检查参数是否正常,根据参数构建路由表条目,为主机添加路由表条目,为自己的数据添加路由表条目我会。从结构上来说。
发生子网删除事件时采取的步骤:检查参数是否正常,根据参数构建路由表项,从主机中删除路由表项,管理从主机中删除路由表项目标主机。 数据结构
p>6.其他
除了上面的核心逻辑之外,还有一些iptables规则和SubnetFile相关操作。
// 根据需要配置 ipMasq if opts.ipMasq { go network.SetupAndEnsureIPTables(network.MasqRules(config.Network, bn.Lease())) } // 始终设置转发规则启用。 对于 Docker 版本 > 1.13 是必需的 (https://docs.docker.com/engine/userguide/networking/default_network/container-communication/#container-communication- Between-hosts) //在 Docker 1.12 之前,默认的 FORWARD 链策略是 ACCEPT。 // 从 Docker 1.13 开始,Docker 将 FORWARD 链的默认策略设置为 DROP。 go network.SetupAndEnsureIPTables(network.ForwardRules(config.Network.String()))
可以看到SetupAn主要是在网络文件里面被调用。dEnsureIPTables 方法。
补充说明
从 Docker 1.13 开始,Docker 将 FORWARD 的默认策略设置为 drop,因此 flannel 需要做一些工作。
评论前必须登录!
注册