我们在本系列的第一期就提到过,孙猴子的两个重要技能是召唤分身和筋斗云。虚拟化技术的起源也借鉴了这一思想,用户可以基于虚拟机镜像快速批量启动虚拟机,以及虚拟机迁移,来实现虚拟机的便捷调度。
在容器技术出现后,我们发现,容器的快速批量启动变得更加容易。由于容器中运行的应用,实质上是工作节点(Worker Node)上的一个进程,启动一个容器所需的时间与在服务器上启动服务进程所需的时间相差无几。因此,相比于虚拟化,容器的弹性伸缩和自动化编排来得更加普遍。
最常见的容器自动化编排系统叫Kubernetes,其希腊文原词为“κυβερνήτης”,意为“舵手”。由于这个单词较长,超出了以某A公司为代表的国内部分IT行业从业者的英文学习与运用能力,被一些人以谐音为抓手,称之为K8S,并反哺了开源生态,影响全球化用户心智。
K8S实质上是一个自动化调用以docker为代表的容器运行时(container runtime),在工作节点上创建或销毁容器的平台,也就是所谓的容器编排平台。
熟悉docker的同学可能会了解,启动一个docker容器时,可以让docker容器通过docker0获取一个IP地址,也可以通过docker启动参数--bit来指定其IP地址。但是,无论哪种方式,在docker容器数量越来越多的情况下,解决以下问题都会遇到困难:
1. 如何让容器以统一的方式(NAT方式/桥接方式等)接入网络,实现容器之间互通?
2. 如何为容器统一分配IP地址避免冲突?
3. 如何为容器提供DNS和负载均衡等网络服务?
4. 容器需要访问其他容器集群或互联网等外部网络的时候,怎么样实现数据流的打通?
虽然以上问题都可以在创建一个容器的时候手工配置,但在大规模容器集群下,手工配置显然无法满足业务扩展的需求。
K8S给出的答案是,既然手工配置无法满足需求,我们就让计算机来代替人的工作!
这就需要从K8S的设计理念讲起。K8S的设计理念在一定程度上参照了上一代云计算技术Openstack,采用插件式的开放设计。熟悉Openstack的同学会发现,Openstack本身不实现任何数据平面的机制,计算虚拟化、块存储、网络转发等关键组件均由第三方实现,并通过cinder驱动、neutron驱动等机制向第三方开放,第三方块存储设备、网络设备、负载均衡及安全设备可以通过开发cinder/neutron/fwaas/lbaas等驱动,注册到openstack上为Openstack所用,Openstack实际上只实现镜像服务 (Glance),计算调度 (Nova),认证鉴权 (Keystone),门户界面 (Horizon)和监控 (ceilmeter)几个控制平面模块。
类似地,K8S也只实现了计算调度(scheduler),认证鉴权(k8s RBAC)等控制平面功能。比Openstack更为灵活的是,K8S的监控、镜像管理等功能也通过prometheus和harbor等第三方组件实现。而三大核心组件:计算、存储与网络则通过CRI,CSI和CNI三大接口,调用第三方组件实现。其中,CNI是container network interface的缩写,也就是为K8S实现网络功能的接口。
要理解K8S,首先要理解K8S的工作模型以及网络的几条基本原则。
在K8S中,容器调度的最小单位为Pod,Pod运行于工作节点(node)上,每个node上可以运行多个Pod。每个Pod内部可以有1个或多个容器,但这些容器会共享一个namespace,并且共享一个ip地址对外通信。
Kubenetes的CNI插件,需要解决的就是以下四个问题中的前两个:
后两个问题可以由Kubernetes通过其他机制解决。
目前社区的CNI插件种类繁多,有较为传统的flannel, calico等,也有比较先进的cilium等。我们将在后面为大家详解这些CNI插件的实现。