之前围绕阿里云的容器服务,内部做了一次阿里云基于k8s服务治理的总结。这次系统地学习了docker与k8s的网络模型,并从kubelet出发研究了kubelet -> dockershim -> cni -> flannel的调用链路,对cni项目的源码做了些许分析。

  • Docker网络模型
  • K8S网络模型
    • 同POD网络
    • 同NODE网络
    • 不同NODE网络
  • CNI分析

Docker网络模型

根据docker官方对于network的介绍,网络方案可以分为以下几种:

  1. bridge
    用于单个host上多个容器之间通信,bridge也是docker的默认网络方案
  2. overlay
    基于docker swarm,用于不同容器在多个host上进行通信
  3. host
    移除容器的网络隔离性,直接使用host上的网络命名空间
  4. macvlan
    自定义容器的mac地址,将容器作为硬件设备。最佳实践是想将容器直接连接到物理网络时,可以考虑使用macvlan的方案
  5. none
    容器没有网络联通需求时,可以不配置

容器体系应用的网络架构如下:
容器网络

k8s网络模型

k8s同pod

同一个pod内的容器共用一个网络命名空间,直接访问本地的端口就能通信

同pod网络

k8s同node

同一个主机上的不同pod之间,通过docker0网络进行通信,接入同一个网桥内的容器属于相同的网段。

不同pod网络

k8s不同node,分布式网络

多node网络

分布式的网络模型,常见的解决方案有Coreos的flannel与calico。阿里云的k8s容器服务就是使用flannel对接Ali VPC接口完成的。

参考:
flannel

calico

CNI分析

CNI是Container Network Interface的缩写,简单地说,就是一个标准的,通用的接口。已知我们现在有各种各样的容器平台:docker,kubernetes,mesos,我们也有各种各样的容器网络解决方案:flannel,calico,weave,并且还有各种新的解决方案在不断涌现。

如果每出现一个新的解决方案,我们都需要对两者进行适配,那么由此带来的工作量必然是巨大的,而且也是重复和不必要的。事实上,只要提供一个标准的接口,更准确的说是一种协议,就能完美地解决上述问题。一旦有新的网络方案出现,只要它能满足这个标准的协议,那么它就能为同样满足该协议的所有容器平台提供网络功能,而CNI正是这样的一个标准接口协议。

源码结构

仓库:cni

repo主要组成

      |- cnitool (cni命令行工具)
      |- libcni (cni的interface申明与默认CNIConfig实现)
      |- pkg (调用插件的方法库及网络定义相关的结构)
      |- scripts(打包编译脚本与执行脚本)

###源码

type CNI interface {
    //network list
    AddNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
    CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
    DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
 
    //network
    AddNetwork(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
    CheckNetwork(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
    DelNetwork(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error

    //Validation
    ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error)
    ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error)
}

核心配置主要有RuntimeConf与NetworkConfig

RuntimeConf

type RuntimeConf struct {
    ContainerID string //在cnitool里containerID是根据net namespace做sha512得到
    NetNS string //network namespace
    IfName string //网卡名
    Args [][2]string //执行命令行参数,底层是转换为环境变量
    CapabilityArgs map[string]interface{} //用于网络插件执行的输入参数
    CacheDir string
}

NetworkConf

type NetworkConfig struct {
    Network *types.Netconf
    Bytes []byte
}

type NetworkConfigList struct {
    Name string
    CNIVersion string
    DisableCheck bool
    Plugins []*NetworkConfig
    Bytes []byte
}

type NetConf struct {
    CNIVersion string
    Name string
    Type string
    Capabilities map[string]bool
    IPAM IPAM
    DNS DNS
    RawPrevResult map[string]interface{}
    PrevResult Result
}

默认没有自定义plugin执行器时,cni默认的exec为CNIConfig{},Exec是interface类型,默认有ExecPlugin、FindInPath与Decode三个函数。

执行逻辑

以AddNetwork为例

CNI.AddNetwork -> 
addNetwork -> 
exec.FindInPath -> 
buildOneConfig(network config) -> 
ExecPluginWithResult -> 
setCachedResult

CNI执行逻辑

参考:

  • CNI源码:https://github.com/containernetworking/cni
  • k8s网络原理:http://www.youruncloud.com/blog/131.html
    …(img-3U65HuYc-1586319883545)]

参考:

  • CNI源码:https://github.com/containernetworking/cni
  • k8s网络原理:http://www.youruncloud.com/blog/131.html
  • K8S-CNI https://feisky.gitbooks.io/kubernetes/network/cni/
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐