简单介绍Kubernetes


【编者的话】Kubernetes是一个强大的开源系统,最初由谷歌开发,用于在集群环境中管理容器化应用程序。它的目标是提供更好的方法来管理不同基础设施之间的相关分布式组件和服务。

在本指南中,我们将讨论一些Kubernetes的基本概念。我们将讨论系统的体系结构、它解决的问题,以及它用来处理容器部署和扩展的模型。

Kubernetes是什么?

在基本级别上,Kubernetes是一个用于跨机器集群运行和协调容器应用程序的系统。它是一个平台,旨在通过提供可预测性、可伸缩性和高可用性的方法,完全管理容器化应用程序和服务的生命周期。

作为Kubernetes用户,您可以定义应用程序的运行方式,以及它们与其他应用程序或外部交互的方式。您可以向上或向下扩展服务、执行优雅的滚动更新、不同版本应用程序的流量切换,以测试特性或回滚问题部署。Kubernetes提供了接口和可组合的平台基元,允许您以高度的灵活性、强大性和可靠性定义和管理应用程序。

Kubernetes架构

要理解Kubernetes是如何提供这些功能的,了解它是如何在高层次上设计和组织的是很有帮助的。Kubernetes可以被视为一个以层(layer)为单位的系统,每个更高层抽象出更低层次的复杂性。

在其基础上,Kubernetes使用共享网络将单个物理或虚拟机组合到一个集群中,以便在每个服务器之间进行通信。这个集群是配置所有Kubernetes组件、功能和工作负载的物理平台。

集群中的机器在Kubernetes生态系统中每个都有一个角色。一个服务器(或高可用部署中的一个小组)充当主服务器。这个服务器充当集群的网关和大脑,它为用户和客户机公开API,检查其他服务器的健康状况,决定如何最好地分割和分配工作(称为“调度”),以及协调其他组件之间的通信。主服务器充当与集群的主要接触点,并负责Kubernetes提供的大部分集中逻辑。

集群中的其他机器被指定为节点:服务器负责使用本地和外部资源接受和运行工作负载。为了帮助实现隔离、管理和灵活性,Kubernetes在容器中运行应用程序和服务,因此每个节点都需要配备一个容器运行时(比如Docker或rkt)。节点从主服务器接收工作指令,并相应地创建或销毁容器,调整网络规则以实现适当的流量路由与转发操作。

如上所述,应用程序和服务本身在容器内的集群上运行。底层组件确保应用程序的期望状态与集群的实际状态匹配。用户通过直接与主API服务器或与客户机和库通信与集群进行交互。要启动应用程序或服务,需要以JSON或YAML的形式提交声明性计划,定义要创建什么以及应该如何管理它。然后,主服务器获取计划,通过检查系统的需求和当前状态,确定如何在基础设施上运行它。这组根据指定计划运行的用户定义应用程序代表了Kubernetes的最后一层。

主服务器组件

如上所述,主服务器充当Kubernetes集群的主要控制平面。它是管理员和用户的主要联系点,也为相对不复杂的工作节点提供了许多集群范围的系统。总体而言,主服务器上的组件协同工作来接受用户请求,确定调度工作负载容器,验证客户端和节点,调整群集范围网络以及管理扩展和运行状况检查职责的最佳方法。

这些组件可以安装在一台机器上,也可以分布在多个服务器上。在本节中,我们将研究与主服务器相关的每个单独组件。

etcd

Kubernetes需要运行的基本组件之一是全局可用的配置存储。 由CoreOS团队开发的etcd项目是一个轻量级的分布式键值存储,可以配置为跨越多个节点。

Kubernetes使用etcd来存储可以由集群中的每个节点访问的配置数据。这可用于服务发现,并可帮助组件根据最新信息配置或重新配置自身。 它还有助于通过领导者选举和分布式锁定等功能维护群集状态。通过提供简单的HTTP/JSON API,用于设置或检索值的界面非常简单。

与控制平面中的大多数其他组件一样,etcd可以在单个主服务器上配置,或者在生产方案中,可以在多台计算机之间分配。唯一的要求是每个Kubernetes机器都可以访问网络。

kube-apiserver

最重要的主服务之一是API服务器。 这是整个群集的主要管理点,因为它允许用户配置Kubernetes的工作负载和组织单位。 它还负责确保etcd存储和已部署容器的服务详细信息一致。 它充当各种组件之间的桥梁,以维护集群健康并传播信息和命令。

API服务器实现RESTful接口,这意味着许多不同的工具和库可以很容易地与它通信。 名为kubectl的客户端可用作从本地计算机与Kubernetes集群交互的默认方法。

kube控制器管理器

控制器管理器是一项具有许多职责的通用服务。它主要管理不同的控制器,用于管理集群状态,管理工作负载生命周期以及执行例行任务。例如,复制控制器可确保为Pod定义的副本数(相同副本)与当前在群集上部署的数量相匹配。这些操作的详细信息将写入etcd,其中控制器管理器通过API服务器监视更改。

当看到更改时,控制器读取新信息并实现满足所需状态的过程。这可能涉及向上或向下扩展应用程序,调整端点等。

kube调度

实际将工作负载分配给集群中特定节点的过程是调度程序。此服务读取工作负载的操作要求,分析当前的基础结构环境,并将工作放在可接受的节点上。

调度程序负责跟踪每台主机上的可用容量,以确保未调度超出可用资源的工作负载。调度程序必须知道总容量以及已分配给每台服务器上现有工作负载的资源。

云控制器管理器

Kubernetes可以部署在许多不同的环境中,并且可以与各种基础架构提供商进行交互,以了解和管理集群中的资源状态。尽管Kubernetes能够支持附加存储与负载均衡器等常规资源形式,但其仍需要将这些形式与由不同云服务供应商提供的实际资源映射起来。

云控制器管理器充当粘合剂,允许Kubernetes使提供者具有不同的功能,特性和API,同时在内部维护相对通用的构造。这允许Kubernetes根据从云提供商收集的信息更新其状态信息,在系统中需要更改时调整云资源,以及创建和使用其他云服务以满足提交到群集的工作要求。

节点服务器组件

在Kubernetes中,通过运行容器执行工作的服务器称为节点。 节点服务器有一些要求,这些要求是与主组件通信,配置容器网络以及运行分配给它们的实际工作负载所必需的。

一个容器运行时

每个节点必须具有的第一个组件是容器运行时。通常,通过安装和运行Docker可以满足此要求,但也可以使用rkt和runC等替代方案。

容器运行时负责启动和管理容器,应用程序封装在相对隔离但轻量级的操作环境中。集群上的每个工作单元在其基本级别上实现为必须部署的一个或多个容器。每个节点上的容器运行时是最终运行提交到集群的工作负载中定义的容器的组件。

kubelet

每个节点与群集组的主要联系点是一个名为kubelet的小型服务。该服务负责向控制平面服务中继信息,以及与etcd存储交互以读取配置细节或写入新值。

kubelet服务与主组件通信以向集群进行身份验证并接收命令和工作。以清单的形式接收工作,该清单定义工作量和操作参数。然后,kubelet进程负责维护节点服务器上的工作状态。它控制容器运行时根据需要启动或销毁容器。

kube-代理

为了管理单个主机子网并使服务可用于其他组件,在每个节点服务器上运行一个名为kube-proxy的小型代理服务。此过程将请求转发到正确的容器,可以进行原始负载平衡,并且通常负责确保网络环境是可预测和可访问的,但在适当时隔离。

Kubernetes对象和工作量

虽然容器是用于部署应用程序的底层机制,但Kubernetes在容器接口上使用了额外的抽象层来提供扩展,弹性和生命周期管理功能。用户不是直接管理容器,而是定义由Kubernetes对象模型提供的各种基元组成的实例并与之交互。我们将介绍可用于定义下面这些工作负载的不同类型的对象。

Pod

Pod是Kubernetes处理的最基本单位。容器本身未分配给主机。相反,一个或多个紧密耦合的容器被封装在称为Pod的对象中。

Pod通常表示应作为单个应用程序控制的一个或多个容器。Pod由密集操作的容器组成,共享生命周期,并且应始终安排在同一节点上。它们完全作为一个单元进行管理,并共享其环境,数量和IP空间。尽管它们是容器化的实现,但您通常应该将Pod视为一个单一的整体应用程序,以便最好地概念化集群如何管理Pod的资源和调度。

通常,Pod包含满足工作负载一般用途的主容器,以及可选的一些帮助密切相关任务的帮助容器。这些程序受益于在自己的容器中运行和管理,但与主应用程序紧密相关。例如,当外部存储库中检测到更改时,Pod可能有一个运行主应用程序服务器的容器和一个帮助容器将文件下拉到共享文件系统。通常不鼓励在Pod级别进行水平缩放,因为还有其他更高级别的对象更适合该任务。

通常,用户不应自行管理Pod,因为它们不提供应用程序中通常需要的某些功能(如复杂的生命周期管理和扩展)。相反,鼓励用户使用更高级别的对象,这些对象使用Pod或Pod模板作为基本组件,但实现其他功能。

复制控制器和复制集

通常,在与Kubernetes合作时,不是使用单个Pod,而是管理相同,复制的Pod组。这些是从Pod模板创建的,可以通过称为复制控制器和复制集的控制器进行水平扩展。

复制控制器是一个对象,它定义Pod模板和控制参数,以通过增加或减少运行副本的数量来水平扩展Pod的相同副本。这是在Kubernetes中本地分配负载和增加可用性的简单方法。复制控制器知道如何根据需要创建新的Pod,因为复制控制器配置中嵌入了与Pod定义非常相似的模板。

复制控制器负责确保群集中部署的Pod数量与其配置中的Pod数量相匹配。如果Pod或底层主机出现故障,控制器将启动新的Pod以进行补偿。如果控制器配置中的副本数量发生更改,控制器将启动或终止容器以匹配所需的数字。复制控制器还可以执行滚动更新,将一组Pod逐个滚动到新版本,从而最大限度地降低对应用程序可用性的影响。

复制集是复制控制器设计的迭代,在控制器识别其要管理的Pod方面具有更大的灵活性。复制集开始取代复制控制器,因为它们具有更强的副本选择功能,但它们无法进行滚动更新以将后端循环到新版本,如复制控制器。相反,复制集旨在用于提供该功能的其他更高级别单元内部。

与Pod一样,复制控制器和复制集很少是您直接使用的单元。虽然它们基于Pod设计以增加水平扩展和可靠性保证,但它们缺少一些在更复杂的对象中发现的细粒度生命周期管理功能。

Deployment

Deployment是直接创建和管理的最常见工作负载之一。Deployment使用复制集作为构建块,为整个体系添加灵活的生命周期管理功能。

虽然使用复制集构建的部署可能会复制复制控制器提供的功能,但Deployment解决了滚动更新实现中存在的许多难点。使用复制控制器更新应用程序时,用户需要为将替换当前控制器的新复制控制器提交计划。使用复制控制器时,跟踪历史记录,在更新期间从网络故障中恢复以及回滚不良更改等任务要么很困难,要么由用户负责。

Deployment是一个高级对象,旨在简化复制Pod的生命周期管理。通过更改配置可以轻松修改部署,Kubernetes将调整副本集,管理不同应用程序版本之间的转换,并可选择自动维护事件历史记录和撤消功能。由于这些功能,Deployment可能是您最常使用的Kubernetes对象类型。

有状态集

有状态集是专门的Pod控制器,提供排序和唯一性保证。首先,当您有与部署顺序,持久数据或稳定网络相关的特殊要求时,这些用于进行更细粒度的控制。例如,有状态集通常与面向数据的应用程序相关联,如数据库,即使重新安排到新节点,也需要访问相同的卷。

有状态集通过为每个Pod创建唯一的,基于数字的名称来提供稳定的网络标识符,即使将Pod移动到另一个节点也会持久存在。同样,当需要重新安排时,可以使用Pod传输持久存储卷。即使在删除Pod后,卷仍然存在,以防止意外数据丢失。

在部署或调整比例时,有状态集根据其名称中的编号标识符执行操作。这提供了更高的可预测性和对执行顺序的控制,这在某些情况下很有用。

守护进程集

守护程序集是另一种特殊形式的Pod控制器,它在集群中的每个节点上运行Pod的副本(如果指定,则为子集)。在部署有助于执行维护并为节点本身提供服务的Pod时,这通常很有用。

例如,收集和转发日志,聚合度量以及运行增加节点本身功能的服务是守护进程集的流行候选者。由于守护程序集通常提供基本服务并且在整个机群中都需要,因此它们可以绕过Pod调度限制,从而阻止其他控制器将Pod分配给某些主机。例如,由于其独特的职责,主服务器经常被配置为不可用于正常的Pod调度,但是守护进程集能够逐个Pod地覆盖限制以确保基本服务正在运行。

Job和Cron Jobs

到目前为止,我们所描述的工作负载都假定为长期运行,类似服务的生命周期。Kubernetes使用称为Job的工作负载来提供更多基于任务的工作流,其中运行的容器在完成工作后的一段时间后会成功退出。如果您需要执行一次性或批量处理而不是运行连续服务,则Job非常有用。

以jobs为基础的是cron jobs。与Linux上的传统cron守护程序和按计划执行脚本的类Unix系统一样,Kubernetes中的cron jobs提供了一个用于运行具有调度组件的jobs的接口。 Cron jobs可用于安排job在将来执行或定期重复执行。 Kubernetes cron jobs基本上是对经典cron行为的重新实现,使用集群作为平台而不是单个操作系统。

其他Kubernetes组件

除了可以在群集上运行的工作负载之外,Kubernetes还提供了许多其他抽象,可帮助您管理应用程序,控制网络和启用持久性。我们将在这里讨论一些更常见的例子。

Services

到目前为止,我们一直在使用传统的类似于Unix的术语“Services”:表示长期运行的进程,通常是网络连接的,能够响应请求。但是,在Kubernetes中,Services是一个组件,充当基本内部负载平衡器和Pod的大使。Services将执行相同功能的Pod的逻辑集合组合在一起,以将它们显示为单个实体。

这允许您部署可以跟踪和路由到特定类型的所有后端容器的Services。内部消费者只需要了解Services提供的稳定端点。同时,Services抽象允许您根据需要扩展或替换后端工作单元。无论其路由到的Pod的变化如何,服务的IP地址都保持稳定。通过部署Services,您可以轻松获得可发现性并简化容器设计。

每当您需要为一个或多个Pod提供对另一个应用程序或外部使用者的访问权限时,您应该配置一项服务。例如,如果您有一组运行Web服务器的Pod应该可以从Internet访问,则Services将提供必要的抽象。同样,如果您的Web服务器需要存储和检索数据,您可能希望配置内部服务以授予它们访问数据库窗格的权限。

虽然默认情况下Services只能使用内部可路由的IP地址,但只要选择多种策略之一,就可以在群集外部使用它们。 NodePort配置通过在每个节点的外部网络接口上打开静态端口来工作。到外部端口的流量将使用内部群集IP服务自动路由到相应的Pod。

或者,LoadBalancer服务类型使用云提供程序的Kubernetes负载均衡器集成创建外部负载均衡器以路由到服务。云控制器管理器将创建适当的资源并使用内部Services服务地址对其进行配置。

存储卷和持久存储卷

在许多容器化环境中,可靠地共享数据并保证容器重启之间的可用性是一项挑战。容器运行时通常提供一些机制来将存储连接到容器,该容器持续超出容器的生命周期,但实现通常缺乏灵活性。

为了解决这个问题,Kubernetes使用自己的卷抽象,允许数据由Pod中的所有容器共享,并在Pod终止之前保持可用。这意味着紧密耦合的Pod可以轻松共享文件而无需复杂的外部机制。 Pod中的容器故障不会影响对共享文件的访问。 Pod终止后,共享卷被破坏,因此它不是真正持久数据的好解决方案。

持久卷是一种机制,用于抽象与Pod生命周期无关的更强大的存储。相反,它们允许管理员为群集配置存储资源,用户可以请求并声明正在运行的Pod。使用持久卷完成Pod后,卷的回收策略将确定是否保留卷,直到手动删除或立即删除数据。持久性数据可用于防止基于节点的故障,并分配比本地可用的存储量更大的存储量。

Label和Annotation

还有一条与其它概念相关,但又独立于其外的Kubernetes组织抽象存在,就是labeling。Kubernetes中的Label是一个语义标签,可以附加到Kubernetes对象上,以将它们标记为组的一部分。然后,可以在针对管理或路由的不同实例进行选择时选择这些。例如,每个基于控制器的对象使用Label来标识它们应该操作的Pod。服务使用标签来理解他们应该将请求路由到的后端Pod。

Label以简单的键值对的形式给出。每个单元可以有多个Label,但每个单元每个键只能有一个条目。通常,“name”键用作通用标识符,但您还可以通过开发阶段,公共可访问性,应用程序版本等其他标准对对象进行分类。

Annotation是一种类似的机制,允许您将任意键值信息附加到对象。虽然Label应该用于将Pod与选择标准语义信息相匹配,但Annotation更自由,并且可以包含更少的结构化数据。通常,Annotation是一种向对象添加丰富元数据的方法,这对于选择目的没有帮助。

结论

Kubernetes是一个令人兴奋的项目,它允许用户在高度抽象的平台上运行可伸缩的、高可用的容器化工作负载。虽然Kubernetes的体系结构和内部组件集乍一看可能令人生畏,但它们的功能、灵活性和健壮的特性集在开源领域是无与伦比的。通过了解基本构建块是如何组合在一起的,您可以开始设计系统,充分利用平台的功能来按比例运行和管理工作负载。

原文链接:An Introduction to Kubernetes(翻译:张亚龙)

0 个评论

要回复文章请先登录注册