当前位置: 首页 > 科技观察

关于Kubernetes的架构原理,这是我看过最清晰的一篇文章_0

时间:2023-03-14 21:54:45 科技观察

点开这篇文章的同学一定对Docker不陌生。Docker是一种虚拟容器技术。上手相对简单。只需要在宿主机上启动一个DockerEngine,就可以尽情的玩了,比如:拉取镜像,启动容器,挂载数据,映射端口等等。与上手Kubernetes(K8S)相比,简单多了。那么什么是K8S,为什么上手这么难?K8S是基于容器技术的分布式集群管理系统。它是谷歌积累数十年容器技术大规模应用经验的重要成果。因此,为了支持大规模的集群管理,它承载了很多组件,分发本身的复杂度非常高。并且由于K8S是谷歌出品,大量依赖谷歌自己的镜像,所以国内同学搭建环境的难度比较大。接下来我们带着疑问一步步看一下K8S里都有什么?首先,既然是分布式系统,那么肯定有多个Node节点(物理主机或者虚拟机),它们共同组成一个分布式集群,而这些节点之间会有一个Master节点,负责管理其中的Node节点统一的方式。如图:问题一:master节点和worker节点如何通信?首先,当Master节点启动时,会运行一个kube-apiserver进程,它提供集群管理的API接口,是集群中各功能模块之间数据交互和通信的中心枢纽,它提供了一个完整的集群安全机制(后面会讲到)。在Node节点上,利用K8S中的kubelet组件,每个Node节点上都会运行一个kubelet进程,负责向Master汇报本节点的运行状态,如节点的注册、终止、定时上报等Node节点的健康状态,接收Master下发的命令,创建相应的Pod。在K8S中,Pod是最基本的运行单元,与docker容器略有不同,因为Pod中可能包含一个或多个容器(可以是docker容器),这些容器内部共享网络资源,即它们可以相互通过本地主机访问。关于如何在Pod中实现网络共享,在每个Pod启动的时候,都会在里面启动一个pause容器(谷歌的镜像),它使用默认的网络模式,其他容器的网络都设置给它,所以至于完成网络共享问题。如图:问题2:Master如何将Pod调度到指定的Node?这项工作由kube-scheduler完成。整个调度过程通过执行一系列复杂的算法,为每个Pod计算出一个最优的目标Node。这个过程由kube-scheduler进程自动完成。常见的一种是循环调度(RR)。当然也有可能我们需要将Pod调度到指定的Node上。我们可以通过将节点的标签(Label)与Pod的nodeSelector属性进行匹配来达到指定的效果。如图:关于标签(Label)和选择器(Selector)的概念,后面会进一步介绍第三个问题:各个节点和Pod的信息在哪里统一维护,由谁来维护?从上面的Pod调度来看,我们必须有一个存储中心来存储每个Pod的资源使用情况、健康状态、基本信息,这样Pod调度才能正常进行。在K8S中,etcd组件作为一个高可用和一致的存储仓库。该组件可以内置在K8S中,也可以外部构建供K8S使用。集群上的所有配置信息都存储在etcd中。为了考虑到各个组件的相对独立性和整体的可维护性,这些存储数据的增删改查,统一由kube-apiserver调用,并且apiserver还提供了REST支持,不仅提供服务给各种内部组件,但也向集群的外部用户公开服务。外部用户可以通过REST接口或kubectl命令行工具管理集群,它与apiserver内部通信。如图:问题4:外部用户如何访问集群中运行的Pod?我们讲了外部用户如何管理K8S,但我们更关心的是外部如何访问内部运行的Pod。用过Docker的同学应该都知道,如果使用bridge模式,在创建容器的时候会分配一个虚拟IP,这个IP是外部无法访问的。我们需要做一层端口映射,将容器中的端口与宿主机的端口进行映射绑定,这样外部就可以通过访问宿主机的指定端口来访问容器内部的端口。那么,K8S的外部访问也是这样实现的吗?答案是否定的,K8S中的情况更加复杂。因为上面说的Docker是单机模式,一个容器对外暴露一个服务。在分布式集群中,一个服务往往由多个应用提供,以分担访问压力,而这些应用可能分布在多个节点上,这就涉及到跨主机通信。这里K8S引入了Service的概念,将多个相同的Pod打包成一个完整的服务对外提供服务。至于获取这些相同的Pod,每个Pod在启动时都会设置labels属性。在Service中,我们通过选择器Selector选择具有相同Name标签属性的Pod作为一个整体服务,并通过Apiserver将服务信息存储到etcd中,由ServiceController完成。同时在每个节点上都会启动一个kube-proxy进程,负责从服务地址到Pod地址的代理和负载均衡。如图:问题5:Pod如何动态扩展和伸缩?现在我们知道服务是由Pod组成的,那么服务的扩展也意味着Pod的扩展。通俗地说,就是在需要的时候将Pod做多个副本,在不需要的时候将Pod缩减到指定的副本数。K8S通过ReplicationController进行管理,它为每个Pod设置了预期的副本数。当实际副本数与预期不符时,动态调整数量以达到预期值。所需值可以由我们手动更新,也可以由代理自动扩展。如图:问题6:各个组件如何相互配合?最后说一下kube-controller-manager进程的作用。我们知道,ectd作为集群数据的存储中心,apiserver用来管理数据中心,作为其他进程与数据中心通信的桥梁。ServiceController和ReplicationController都由kube-controller-manager管理。作为守护进程,kube-controller-manager是一个控制循环。它通过apiserver监控集群的共享状态,并尝试更新实际状态。做出不符合预期的改变。关于Controller,manager还包括NodeController、ResourceQuotaController、NamespaceController等。如图:综上所述,本文通过问答的方式不涉及任何深入的实现细节。从整体的角度,从概念上介绍了K8S涉及的基本概念。相关用法包括:NodePodLabelSelectorReplicationControllerServiceControllerResourceQuotaControllerNamespaceControllerNodeController以及相关的运行过程:kube-apiserverkube-controller-managerkube-schedulerkubeletkube-proxypause