K8S集群架构当中,容器网络的处理方法:就是 flannel项目的Vxlan模式
(不同点: cni0 代替docker0作为网桥)

一 K8S集群CNI插件的必要性:

`cni0`并非简单替代`docker0`,而是K8S为构建“以Pod为中心”的分布式网络架构而设计的关键一环,其背后是容器网络从“单机桥接”向“集群级网络编排”的技术演进
Docker作为容器运行时,其原生网络模型以`docker0`网桥为核心,采用“桥接模式”实现容器间通信。
`docker0`是一个Linux网桥设备,默认IP地址为`172.17.0.1/16`,
所有通过Docker启动的容器(未指定网络模式时)都会连接到该网桥,并通过NAT(网络地址转换)实现与外部网络的通信。
`CNI` 是通过 Container  network Interface 规范定义的容器网络的标准化接口。支持多种网络插件(Caloco /  Cilium / Multus )
CNI0 : 网络插件(Caloco /  Cilium / Multus )在主机节点上创建的虚拟网桥 

必要性分析:
(1) docker0是全局共享的,所有容器默认接入docker0。nat地址转换实现网络访问
          cni0 通过自定义网络规则,灵活实现基于Namespace  基于tag的网络隔离策略
(2)docker0 是bridge模式,只能支持单机容器访问 
         cni 插件通过cni0网桥 + Overlay Network + 路由规则:可以实现pod在不同节点具备扁平的网络地址空间(pod ip 在K8S集群全局可达)

二  CNI的设计思想

Kubernetes 创建一个 Pod 的第一步,就是创建并启动一个 Infra 容器,用来“hold”住这个 Pod 的 Network Namespace。
K8S在启动Infra容器之后,就可以直接调用CNI网络插件 ,
为这个Infra容器的Network Namespace 设置符合预期的网络栈。

三 CNI插件:

Flannel:通过`cni0`网桥将Pod流量转发到`flannel.1`虚拟网卡(VXLAN隧道端点),再通过VXLAN协议封装数据包,发送到目标节点的`flannel.1`网卡,最终由目标节点的`cni0`网桥转发至目标Pod。
Calico:基于BGP路由协议,`cni0`网桥将Pod IP的路由信息通过BGP客户端(如`bird`)广播到集群内其他节点,实现跨节点Pod的直接路由(无需NAT)。

 四 CNI插件安装到K8S

(4.1)K8S 初始化node节点 (自动安装上cni插件):除weave Calico外其他插件都需要将CNI插件的可执行文件放置到/opt/cni/bin 下
(4.2)每个node节点都需要安装flannel程序
当flanneld程序在节点运行后,自动生成CNI配置文件(configmap)
CNI配置文件如下:(K8S不支持插件混用, /etc/cni/net.d/下第一个插件配置才生效)
$ cat /etc/cni/net.d/10-flannel.conflist
{
    "name": "cbr0",
    "plugins": [  # 此字段可定义多个插件协作
        {
            "type": "flannel",
            "delegate": {
                "hairpinMode": true,
                "isDefaultGateway": true
            }
        },
        {
            "type": "portmap",
            "capabilities": {
                "portMappings": true
            }
        }
    ]
}
(4.3)dockershim 加载(4.2)CNI配置文件
容器的网络逻辑是通过CRI实现的,不是写在kubelet的主干代码
docker的CRI是dockershim
kubelet的代码里面有dockershim部分

(4.4)按照CNI配置文件的定义顺序,完成 容器网络配置 + 端口映射配置 
Flannel 的 CNI 配置文件(/etc/cni/net.d/10-flannel.conflist)里有一个字段,叫作 delegate:
…
"delegate": {
    "hairpinMode": true,
    "isDefaultGateway": true
}
…
注意:CNI插件并不是自己在做事
调用CNI插件,本质上就是:CNI插件 调用delegate方法,delegate指定一个CNI内置插件完成动作
例子:Flannel 项目,调用CNI插件(其实就是调用delegate方法,此方法指定了CNI网桥,即CNI0)
这个方法运行的同时,就是对dockershim传来的Network Configuration 进行补充
eg:
把Delegate的hairpinMode字段设置成 true
把Delegate的isDefaultGateway 字段设置成 true
把 Delegate 的 Type字段设置成 bridge
把Delegate的IPAM字段设置成 host-local 等等
经过 Flannel CNI 插件补充后的、完整的 Delegate 字段如下所示:
{
    "hairpinMode":true,
    "ipMasq":false,
    "ipam":{
        "routes":[
            {
                "dst":"10.244.0.0/16"
            }
        ],
        "subnet":"10.244.1.0/24", 
        # 读取Flannel程序在宿主机上生成的那个 Flannel配置文件 /run/flannel/subnet.env文件
        "type":"host-local"
    },
    "isDefaultGateway":true,
    "isGateway":true,
    "mtu":1440,
    "name":"cbr0",
    "type":"bridge"
}

更多推荐