1.3 Kubernetes介绍
![](https://bookbk.img.zhangyue01.com/group61/M00/77/93/CmQUOF8KrwOEGX6fAAAAAB76RfE908976629.png?v=ywDc_OF-&t=CmQUOF8KrwM.)
我们已经展示了,随着系统可部署组件的数量增长,把它们都管理起来会变得越来越困难。需要一个更好的方式来部署和管理这些组件,并支持基础设施的全球性伸缩,谷歌可能是第一个意识到这一点的公司。谷歌等全球少数几个公司运行着成千上万的服务器,而且在如此海量规模下,不得不处理部署管理的问题。这推动着他们找出解决方案使成千上万组件的管理变得有效且成本低廉。
1.3.1 初衷
这些年来,谷歌开发出了一个叫Borg的内部系统(后来还有一个新系统叫Omega),应用开发者和系统管理员管理那些数以千计的应用程序和服务都受益于它的帮助。除了简化开发和管理,它也帮助他们获得了更高的基础设施利用率,在你的组织如此庞大时,这很重要。当你运行成千上万台机器时,哪怕一丁点的利用率提升也意味着节约了数百万美元,所以,开发这个系统的动机是显而易见的。
在保守Borg和Omega秘密数十年之后,2014年,谷歌开放了Kubernetes,一个基于Borg、Omega及其他谷歌内部系统实践的开源系统。
1.3.2 深入浅出地了解Kubernetes
Kubernetes是一个软件系统,它允许你在其上很容易地部署和管理容器化的应用。它依赖于Linux容器的特性来运行异构应用,而无须知道这些应用的内部详情,也不需要手动将这些应用部署到每台机器。因为这些应用运行在容器里,它们不会影响运行在同一台服务器上的其他应用,当你是为完全不同的组织机构运行应用时,这就很关键了。这对于云供应商来说是至关重要的,因为它们在追求高硬件可用率的同时也必须保障所承载应用的完全隔离。
Kubernetes使你在数以千计的电脑节点上运行软件时就像所有这些节点是单个大节点一样。它将底层基础设施抽象,这样做同时简化了应用的开发、部署,以及对开发和运维团队的管理。
通过Kubernetes部署应用程序时,你的集群包含多少节点都是一样的。集群规模不会造成什么差异性,额外的集群节点只是代表一些额外的可用来部署应用的资源
Kubernetes的核心功能
图1.8展示了一幅最简单的Kubernetes系统图。整个系统由一个主节点和若干个工作节点组成。开发者把一个应用列表提交到主节点,Kubernetes会将它们部署到集群的工作节点。组件被部署在哪个节点对于开发者和系统管理员来说都不用关心。
![](https://bookbk.img.zhangyue01.com/group61/M00/77/AE/CmQUOV8Kru6EAssBAAAAAI9sWyg002332032.jpg?v=qldLO2KL&t=CmQUOV8Kru4.)
图1.8 Kubernetes暴露整个数据中心作为单个开发平台
开发者能指定一些应用必须一起运行,Kubernetes将会在一个工作节点上部署它们。其他的将被分散部署到集群中,但是不管部署在哪儿,它们都能以相同的方式互相通信。
帮助开发者聚焦核心应用功能
Kubernetes可以被当作集群的一个操作系统来看待。它降低了开发者不得不在他们的应用里实现一些和基础设施相关服务的心智负担。他们现在依赖于Kubernetes来提供这些服务,包括服务发现、扩容、负载均衡、自恢复,甚至领导者的选举。应用程序开发者因此能集中精力实现应用本身的功能而不用浪费时间思索怎样集成应用与基础设施。
帮助运维团队获取更高的资源利用率
Kubernetes将你的容器化应用运行在集群的某个地方,并提供信息给应用组件来发现彼此并保证它们的运行。因为你的应用程序不关心它运行在哪个节点上,Kubernetes能在任何时间迁移应用并通过混合和匹配应用来获得比手动调度高很多的资源利用率。
1.3.3 Kubernetes集群架构
我们已经以上帝视角看到了Kubernetes的架构,现在让我们近距离看一下Kubernetes集群由什么组成。在硬件级别,一个Kubernetes集群由很多节点组成,这些节点被分成以下两种类型:
主节点,它承载着Kubernetes控制和管理整个集群系统的控制面板
工作节点,它们运行用户实际部署的应用
图1.9展示了运行在这两组节点上的组件,接下来进一步解释。
![](https://bookbk.img.zhangyue01.com/group61/M00/77/AE/CmQUOV8Kru6EbyJGAAAAAGFiRrI874871893.jpg?v=6WApLNGV&t=CmQUOV8Kru4.)
图1.9 组成一个Kubernetes集群的组件
控制面板
控制面板用于控制集群并使它工作。它包含多个组件,组件可以运行在单个主节点上或者通过副本分别部署在多个主节点以确保高可用性。这些组件是:
Kubernetes API服务器,你和其他控制面板组件都要和它通信
Scheculer,它调度你的应用(为应用的每个可部署组件分配一个工作节点)
Controller Manager,它执行集群级别的功能,如复制组件、持续跟踪工作节点、处理节点失败等
etcd,一个可靠的分布式数据存储,它能持久化存储集群配置
控制面板的组件持有并控制集群状态,但是它们不运行你的应用程序。这是由工作节点完成的。
工作节点
工作节点是运行容器化应用的机器。运行、监控和管理应用服务的任务是由以下组件完成的:
Docker、rtk或其他的 容器类型
Kubelet,它与API服务器通信,并管理它所在节点的容器
Kubernetes Service Proxy(kube-proxy),它负责组件之间的负载均衡网络流量
我们将在第11章中详细解释所有这些组件。笔者不喜欢先解释事物是如何工作的,然后再解释它的功能并教人们如何使用它。就像学习开车,你不想知道引擎盖下是什么,你首先想要学习怎样从A点开到B点。只有在你学会了如何做到这一点后,你才会对汽车如何使这成为可能产生兴趣。毕竟,知道引擎盖下面是什么,可能在有一天它抛锚后你被困在路边时,会帮助你让车再次移动。
1.3.4 在Kubernetes中运行应用
为了在Kubernetes中运行应用,首先需要将应用打包进一个或多个容器镜像,再将那些镜像推送到镜像仓库,然后将应用的描述发布到Kubernetes API服务器。
该描述包括诸如容器镜像或者包含应用程序组件的容器镜像、这些组件如何相互关联,以及哪些组件需要同时运行在同一个节点上和哪些组件不需要同时运行等信息。此外,该描述还包括哪些组件为内部或外部客户提供服务且应该通过单个IP地址暴露,并使其他组件可以发现。
描述信息怎样成为一个运行的容器
当API服务器处理应用的描述时,调度器调度指定组的容器到可用的工作节点上,调度是基于每组所需的计算资源,以及调度时每个节点未分配的资源。然后,那些节点上的Kubelet指示容器运行时(例如Docker)拉取所需的镜像并运行容器。
仔细看图1.10以更好地理解如何在Kubernetes中部署应用程序。应用描述符列出了四个容器,并将它们分为三组(这些集合被称为pod,我们将在第3章中解释它们是什么)。前两个pod只包含一个容器,而最后一个包含两个。这意味着两个容器都需要协作运行,不应该相互隔离。在每个pod旁边,还可以看到一个数字,表示需要并行运行的每个pod的副本数量。在向Kubernetes提交描述符之后,它将把每个pod的指定副本数量调度到可用的工作节点上。节点上的Kubelets将告知Docker从镜像仓库中拉取容器镜像并运行容器。
保持容器运行
一旦应用程序运行起来,Kubernetes就会不断地确认应用程序的部署状态始终与你提供的描述相匹配。例如,如果你指出你需要运行五个web服务器实例,那么Kubernetes总是保持正好运行五个实例。如果实例之一停止了正常工作,比如当进程崩溃或停止响应时,Kubernetes将自动重启它。
同理,如果整个工作节点死亡或无法访问,Kubernetes将为在故障节点上运行的所有容器选择新节点,并在新选择的节点上运行它们。
![](https://bookbk.img.zhangyue01.com/group61/M00/77/AE/CmQUOV8Kru6EFKcTAAAAAO1jSoY486905015.jpg?v=HR3U4Fh_&t=CmQUOV8Kru4.)
图1.10 Kubernetes体系结构的基本概述和在它之上运行的应用程序
扩展副本数量
当应用程序运行时,可以决定要增加或减少副本量,而Kubernetes将分别增加附加的或停止多余的副本。甚至可以把决定最佳副本数目的工作交给Kubernetes。它可以根据实时指标(如CPU负载、内存消耗、每秒查询或应用程序公开的任何其他指标)自动调整副本数。
命中移动目标
我们已经说过,Kubernetes可能需要在集群中迁移你的容器。当它们运行的节点失败时,或者为了给其他容器腾出地方而从节点移除时,就会发生这种情况。如果容器向运行在集群中的其他容器或者外部客户端提供服务,那么当容器在集群内频繁调度时,它们该如何正确使用这个容器?当这些容器被复制并分布在整个集群中时,客户端如何连接到提供服务的容器呢?
为了让客户能够轻松地找到提供特定服务的容器,可以告诉Kubernetes哪些容器提供相同的服务,而Kubernetes将通过一个静态IP地址暴露所有容器,并将该地址暴露给集群中运行的所有应用程序。这是通过环境变量完成的,但是客户端也可以通过良好的DNS查找服务IP。kube-proxy将确保到服务的连接可跨提供服务的容器实现负载均衡。服务的IP地址保持不变,因此客户端始终可以连接到它的容器,即使它们在集群中移动。
1.3.5 使用Kubernetes的好处
如果在所有服务器上部署了Kubernetes,那么运维团队就不需要再部署应用程序。因为容器化的应用程序已经包含了运行所需的所有内容,系统管理员不需要安装任何东西来部署和运行应用程序。在任何部署Kubernetes的节点上,Kubernetes可以在不需要系统管理员任何帮助的情况下立即运行应用程序。
简化应用程序部署
由于Kubernetes将其所有工作节点公开为一个部署平台,因此应用程序开发人员可以自己开始部署应用程序,不需要了解组成集群的服务器。
实际上,现在所有节点都是一组等待应用程序使用它们的计算资源。开发人员通常不关心应用程序运行在哪个服务器上,只要服务器能够为应用程序提供足够的系统资源即可。
在某些情况下,开发人员确实关心应用程序应该运行在哪种硬件上。如果节点是异构的,那么你将会发现你希望某些应用程序在具有特定功能的节点上运行,并在其他的节点上运行其他应用程序。例如,你的一个应用程序可能需要在使用ssd而不是HDDs的系统上运行,而其他应用程序在HDDs上运行良好。在这种情况下,你显然希望确保特定的应用程序总是被调度到有SSD的节点上。
在不使用Kubernetes的情况下,系统管理员将选择一个具有SSD的特定节点,并在那里部署应用程序。但是当使用Kubernetes时,与其选择应用程序应该运行在某一特定节点上,不如告诉Kubernetes只在具有SSD的节点中进行选择。你将在第3章学到如何做到这一点。
更好地利用硬件
通过在服务器上装配Kubernetes,并使用它运行应用程序而不是手动运行它们,你已经将应用程序与基础设施分离开来。当你告诉Kubernetes运行你的应用程序时,你在让它根据应用程序的资源需求描述和每个节点上的可用资源选择最合适的节点来运行你的应用程序。
通过使用容器,不再用把这个应用绑定到一个特定的集群节点,而允许应用程序在任何时候都在集群中自由迁移,所以在集群上运行的不同应用程序组件可以被混合和匹配来紧密打包到集群节点。这将确保节点的硬件资源得到尽可能好的利用。
可以随时在集群中移动应用程序的能力,使得Kubernetes可以比人工更好地利用基础设施。人类不擅长寻找最优的组合,尤其是当所有选项的数量都很大的时候,比如当你有许多应用程序组件和许多服务器节点时,所有的组件可以部署在所有的节点上。显然,计算机可以比人类更好、更快地完成这项工作。
健康检查和自修复
在服务器发生故障时,拥有一个允许在任何时候跨集群迁移应用程序的系统也很有价值。随着集群大小的增加,你将更频繁地处理出现故障的计算机组件。
Kubernetes监控你的应用程序组件和它们运行的节点,并在节点出现故障时自动将它们重新调度到其他节点。这使运维团队不必手动迁移应用程序组件,并允许团队立即专注于修复节点本身,并将其修好送回到可用的硬件资源池中,而不是将重点放在重新定位应用程序上。
如果你的基础设施有足够的备用资源来允许正常的系统运行,即使故障节点没有恢复,运维团队甚至不需要立即对故障做出反应,比如在凌晨3点。他们可以睡得很香,在正常的工作时间再处理失败的节点。
自动扩容
使用Kubernetes来管理部署的应用程序,也意味着运维团队不需要不断地监控单个应用程序的负载,以对突发负载峰值做出反应。如前所述,可以告诉Kubernetes监视每个应用程序使用的资源,并不断调整每个应用程序的运行实例数量。
如果Kubernetes运行在云基础设施上,在这些基础设施中,添加额外的节点就像通过云供应商的API请求它们一样简单,那么Kubernetes甚至可以根据部署的应用程序的需要自动地将整个集群规模放大或缩小。
简化应用部署
前一节中描述的特性主要对运维团队有利。但是开发人员呢?Kubernetes是否也给他们带来什么好处?这毋庸置疑。
如果你回过头来看看,应用程序开发和生产流程中都运行在同一个环境中,这对发现bug有很大的影响。我们都同意越早发现一个bug,修复它就越容易,修复它需要的工作量也就越少。由于是在开发阶段就修复bug,所以这意味着他们的工作量减少了。
还有一个事实是,开发人员不需要实现他们通常会实现的特性。这包括在集群应用中发现服务和对端。这是由Kubernetes来完成的而不是应用。通常,应用程序只需要查找某些环境变量或执行DNS查询。如果这还不够,应用程序可以直接查询Kubernetes API服务器以获取该信息和其他信息。像这样查询Kubernetes API服务器,甚至可以使开发人员不必实现诸如复杂的集群leader选举机制。
作为最后一个关于Kubernetes带来什么的例子,还需要考虑到开发者们的信心增加。当他们知道,新版本的应用将会被推出时Kubernetes可以自动检测一个应用的新版本是否有问题,如果是则立即停止其滚动更新,这种信心的增强通常会加速应用程序的持续交付,这对整个组织都有好处。