Kubernetes网络总体架构图
本小节内容摘自:Kubernetes网络权威指南 基础、原理与实践
上图描绘了当用户在Kubernetes里创建了一个Pod后,CRI和CNI协同创建所有容器并为他们初始化网络栈的全过程。具体过程如下:
- 当用户在Kubernetes的Master那边创建了一个Pod后,Kubelet观察到新Pod的创建,于是首先调用CRI(后面的Runtime实现,比如:dockershim,containerd等)创建Pod内的若干个容器。
- 在这些容器里面,第一个被创建的Pause容器是比较特殊的,这是Kubernetes系统“赠送”的容器,里面跑着一个功能十分简单的Go语言程序,具体逻辑是一启动就去select一个空的Go语言channel,自然就永远阻塞在那里了。一个永远阻塞而且没有实际业务逻辑的pause容器到底有什么用呢?用处大了。我们知道容器的隔离功能利用的是Linux内核的namespace机制,而只要是一个进程,不管这个进程是否处于运行状态(挂起亦可),它都能“占”着一个namespace。因此,每个Pod内的第一个系统容器Pause的作用就是为占用一个Linux的network namespace。
- Pod内其他用户容器通过加入到这个network namespace的方式来共享同一个network namespace。用户容器和Pause容器之间的关系有点类似于寄居蟹和海螺的关系。因此,Container Runtime创建Pod内所有容器时,调用的都是同一个命令: docker run --net=none,意思是只创建一个network namespace,而不初始化网络协议栈。如果这个时候通过nsenter方式进入到容器,会看到里面只有一个本地回环设备lo。
- 那么容器的eth0是怎么创建出来的呢?答案是CNI。
CNI主要负责容器的网络设备初始化工作。Kubelet目前支持两个网络驱动,分别是:kubenet和CNI。
Kubenet是一个历史产物,即将废弃,因此这里也不准备过多介绍。CNI有多个实现,官方自带的插件就有p2p,bridge等,这些插件负责初始化Pause容器的网络设备,也就是给eth0分配IP等,到时候Pod内其他容器就用这个IP与外界通信。Flanne,Calico这些第三方插件解决Pod之间的跨机通信问题。容器之间的跨机通信,可以通过bridge网络或overlay网络来完成。
kubernetes使用CNI网络插件的工作流程
本小节内容摘自:Kubernetes网络权威指南 基础、原理与实践
- kubernetes调用CRI创建puse容器,生成对应的network namespce;
- 调用网络driver
- CNI driver根据配置调用具体的CNI插件
- CNI插件给pause容器配置正确的网络,Pod中的其他容器都是用pause容器的网络栈。
k8s如何使用CNI
本小节内容参考:从零开始入门 K8s:理解 CNI 和 CNI 插件
K8s 通过 CNI 配置文件来决定使用什么 CNI。
基本的使用方法为:
- 首先在每个结点上配置 CNI 配置文件(/etc/cni/net.d/xxnet.conf),其中 xxnet.conf 是某一个网络配置文件的名称;
- 安装 CNI 配置文件中所对应的二进制插件;
- 在这个节点上创建 Pod 之后,Kubelet 就会根据 CNI 配置文件执行前两步所安装的 CNI 插件;
- 上步执行完之后,Pod 的网络就配置完成了。
在集群里面创建一个 Pod 的时候,首先会通过 apiserver 将 Pod 的配置写入。
apiserver 的一些管控组件(比如 Scheduler)会调度到某个具体的节点上去。
Kubelet 监听到这个 Pod 的创建之后,会在本地进行一些创建的操作。当执行到创建网络这一步骤时,它首先会读取刚才我们所说的配置目录中的配置文件,配置文件里面会声明所使用的是哪一个插件,然后去执行具体的 CNI 插件的二进制文件,再由 CNI 插件进入 Pod 的网络空间去配置 Pod 的网络。配置完成之后,Kubelet 也就完成了整个 Pod 的创建过程,这个 Pod 就在线了。
kubernetes官方文档介绍CNI
参考地址:CNI
通过给 Kubelet 传递 --network-plugin=cni 命令行选项可以选择 CNI 插件。 Kubelet 从 --cni-conf-dir (默认是 /etc/cni/net.d) 读取文件并使用 该文件中的 CNI 配置来设置各个 Pod 的网络。 CNI 配置文件必须与 CNI 规约 匹配,并且配置所引用的所有所需的 CNI 插件都应存在于 --cni-bin-dir(默认是 /opt/cni/bin)下。
如果这个目录中有多个 CNI 配置文件,kubelet 将会使用按文件名的字典顺序排列 的第一个作为配置文件。
除了配置文件指定的 CNI 插件外,Kubernetes 还需要标准的 CNI lo 插件,最低版本是0.2.0。
CNI简介
- Container Network Interface,容器网络的 API 接口。Google和CoreOS联合定制的网络标准,这个标准基于rkt实现多容器通信的网络模型。
生产中的网络环境可能是多种多样的,有可能是二层连通的,也可能用的公有云的环境,所以各个厂商的网络解决方案百花争鸣,这些解决方案也不能全都集成在kubelet的代码中,所以CNI就是能让各个网络厂商对接进来的接口。 - K8s 中标准的一个调用网络实现的接口,Kubelet 通过这个标准的 API 调用不同的网络插件配实现置网络
- CNI 插件:一系列实现了 CNI API 接口的网络插件。常见的 CNI 插件包括 Calico、flannel、Terway、Weave Net 以及 Contiv。
CNI原理
本小节内容参考:从零开始入门 K8s:理解 CNI 和 CNI 插件
注:一个Network Namespace的网络栈包括:网卡(Network interface)、回环设备(Loopback Device)、路由表(Routing Table)和iptables规则。
CNI的原理主要分为两个部分:
- 二进制插件配置POD的网络栈(runtime):给POD插上网线
- Deamon进程实现网络互通(plugin): 给POD连上网络