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

换个角度入门K8s

时间:2023-03-20 12:47:31 科技观察

本文通过一个业务发展的故事来分享K8s出现的原因以及它是如何工作的。适合所有技术开发者,尤其是前端开发者。0前言去年下半年,工作调动,开始接触kubernetes。虽然我对K8s的理解还很不完整,但是很想分享一下自己的一些收获。希望本文能帮助大家入门K8s学习。文中有不对的地方,还请各位老司机帮我指正。其实在网上搜了很多介绍K8s的文章,kubernetes官方文档也很友好,所以就直接说K8s了。我觉得我远不如网上的一些文章,所以我想换个角度,通过一个业务发展的故事,来谈谈K8s是怎么出现的,它是如何工作的。本文适合所有从事技术的同学,尤其是前端同学,因为前端工程这几年发展非常迅速。目前K8s所解决的问题和开发形态,相信假以时日,在前端领域也会出现。毕竟,不同领域的工程开发其实是殊途同归。1故事开始随着中国人民生活水平的不断提高,家家户户都有了汽车。小王预测,5年后,汽车报废业务将快速发展,国家也在19年出台新政策《报废机动车回收管理办法》,取消汽车报废回收的“特殊行业”属性,向市场化开放竞赛。小王觉得这是一个很好的创业机会,于是他找到了我和几个志同道合的伙伴一起创业,决定做一个平台叫“淘车网”。2StoryDevelopment淘车网一开始是一个javaallinone应用,部署在物理机上(小王,现在几点了,你要了解阿里云),随着业务的发展,发现机器实在受不了了,赶紧升级服务器规格,从64C256G升级到160C1920G。虽然成本高了点,但至少系统没有问题。经过一年的业务发展,160C1920G扛不住了,不得不进行业务拆分和分布式改造。为了解决分布式改造过程中的各种问题,引入了hsf、tddl、tail、diamond、metaq等一系列中间件。经过艰难的业务架构转型,我们成功地将allinoneJava应用拆分成多个小应用,重走阿里中间件开发和IOE之路。分布式修改后,我们管理的服务器更多了。不同批次的服务器在硬件规格、操作系统版本等方面存在差异,因此出现了应用运维方面的各种问题。好在有虚拟机技术,通过虚拟化技术屏蔽各种底层软硬件的差异。虽然硬件不同,但对于应用来说,所见即所得,只是虚拟化和招致了很大的性能开销。那么,为什么不用docker呢,因为docker是基于cgroup等linux原生技术,在屏蔽了底层差异的同时,没有明显的性能影响,这真是一件好事。而且基于docker镜像的业务交付,让我们的CI/CD运维变得非常轻松。但是,随着docker容器数量的增加,我们又不得不面对新的问题,那就是大量的docker如何调度和通信?毕竟随着业务的发展,淘车网已经不是小公司了。我们运行着上千个docker容器,按照现在的业务发展趋势,很快就会突破10000个。不行,我们必须建立一个系统,可以自动管理服务器(比如是否健康,可以使用多少内存和CPU等),然后根据容器声明选择最优的CPU和内存。服务器创建容器,还需要能够控制容器与容器之间的通信(比如某个部门的内部服务,当然不希望其他部门的容器也可以访问它)。我们给这个系统起个名字吧,我们就叫它容器编排系统吧。3容器编排系统那么问题来了,面对一堆服务器,我们如何实现一个容器编排系统呢?首先假设我们已经实现了这个编排系统,那么我们的一部分服务器会用来运行这个编排系统,剩下的服务器用来运行我们的业务容器。我们称运行编排系统的服务器为主节点,运行业务容器的服务器为工作节点。由于主节点负责管理服务器集群,因此必须提供相关的管理接口。一是方便运维管理员对集群进行相关操作,二是与worker节点进行交互,如资源分配,网络管理等,我们把master上提供管理接口的组件称为kubeapi服务器。相应的,需要两个客户端来与api服务器进行交互。一个是给集群的运维管理员的。我们称之为kubectl;另一个是提供给worker节点的,叫做kubelet。现在集群的运维管理员、master节点、worker节点之间可以进行交互了。例如,运维管理员通过kubectl向master发送命令,“创建1000个Container”,master收到这个请求后,会根据集群中worker节点的资源信息进行计算调度,计算这1000个容器应该在哪些worker上创建,然后向相应的worker发出创建指令。我们称这个组件负责调度kubescheduler。那么master是怎么知道每个worker的资源消耗和容器的运行状态的呢?这个很简单,我们可以通过worker上的kubelet定期主动上报节点资源和容器的运行状态,然后master存储这些数据,以后可以用于调度和容器管理。至于如何存储数据,我们可以写文件,写db等,但是有一个开源的存储系统叫etcd,它满足我们对数据一致性和高可用的要求,而且安装方便,性能好。让我们选择etcd。现在我们有了所有的工作节点和容器运行数据,我们可以做很多事情。比如前面提到的,我们使用淘车用户中心2.0版本的镜像创建了1000个容器,其中5个运行在worker节点A上,如果节点A突然出现硬件故障,导致该节点是不可用。这个时候master会把A从可用的worker节点中移除,同时还需要把原来运行在这个节点上的5个usercenter2.0容器重新调度到其他可用的worker节点上,这样我们usercenter2.0的容器数量就可以了恢复到1000,需要调整相关容器的网络通信配置,使容器之间的通信仍然正常。我们将这一系列组件称为控制器,如节点控制器、副本控制器、端点控制器等,并为这些控制器提供一个统一的运行组件,称为控制器管理器(kube-controller-manager)。master如何实现和管理容器间的网络通信?首先,每个容器必须有一个唯一的ip地址,通过它可以相互通信,但是相互通信的容器可能运行在不同的worker节点上,这就涉及到worker节点之间的网络通信,所以每个worker节点也需要有一个唯一的ip地址,但是容器之间的通信是通过容器ip进行的,容器不会感知到worker节点的ip地址。因此需要容器IP的路由转发信息在worker节点上可用,可以通过iptables、ipvs等技术实现。那么如果容器ip发生变化,或者容器数量发生变化,相关的iptables和ipvs配置也需要做相应的调整。因此,在worker节点上,我们需要一个组件负责监控和调整路由转发配置。我们把这个组件叫做kubeproxy(这里为了便于理解,Service的介绍就不展开了)。我们解决了容器之间的网络通信,但是我们在编码的时候,希望通过域名或者vip来调用一个服务,而不是通过一个随时可能变化的容器ip。因此,我们需要在容器IP之上封装一个Service的概念。这个Service可以是集群的VIP,也可以是集群的域名。为此,我们在集群内部还需要一个DNS域名解析服务。另外,虽然我们已经有了kubectl,可以愉快的和master交互,但是如果有web管理界面,这绝对是再好不过的事情了。除此之外,我们可能还想查看容器的资源信息,整个集群相关组件的运行日志等等。DNS、Web管理界面、容器资源信息、集群日志等能够提升我们体验的组件统称为插件。至此,我们已经成功搭建了一个容器编排系统。简单总结一下上面提到的各个组件:Master组件:kube-apiserver、kube-scheduler、etcd、kube-controller-managerNode组件:kubelet、kube-Proxy插件:DNS、用户界面WebUI、容器资源监控、和集群日志也是K8s的重要组成部分。当然,K8s是生产级的容器编排系统,这里提到的各个组件都可以拿出来单独讲很多内容。本文只是简单介绍,不再赘述。4Serverless容器编排系统虽然我们成功实现了一个容器编排系统,而且用起来也很舒服,但是淘车网的王总(他已经不是当年的小王了)感觉公司花了研究而且在这个编排系统上开发和运维成本太高,想降低这方面的成本。王总思考是否有一种编排系统,可以让员工专注于业务发展,而无需关注集群的运维管理。王总和技术圈的同学了解了一下,发现serverless的概念和他的想法不一样。很巧,所以我在想什么时候搞出serverless容器编排系统。