介绍
Kubernetes是一个功能强大的开源系统,最初由谷歌开发,并得到云原生计算基金会(CNCF)的支持,用于在集群环境中管理容器化应用程序。它旨在提供更好的方法来管理相关的、分布式的组件和服务,跨越各种基础设施。要了解更多关于Kubernetes的信息,请查看下面的指南。如果您正在寻找托管的Kubernetes托管服务,请查看我们为增长构建的简单的托管Kubernetes服务。
在本指南中,我们将讨论什么是Kubernetes,一些Kubernetes的基本概念。我们将讨论系统的架构,它解决的问题,以及它使用的模型来处理容器化的部署和扩展。
什么是Kubernetes?
Kubernetes在基本层面上是一个系统,用于在一组计算机集群上运行和协调容器化应用程序。它是一个平台,旨在使用提供可预测性、可扩展性和高可用性的方法来完全管理容器化应用程序和服务的生命周期。
作为 Kubernetes 用户,您可以定义应用程序的运行方式以及它们与其他应用程序或外部世界交互的方式。您可以按需缩放服务,执行优雅的滚动更新,并在不同版本的应用程序之间切换流量,以测试功能或回滚问题部署。Kubernetes 提供了接口和可组合的平台原语,使您能够以高度灵活、强大和可靠的方式定义和管理应用程序。
Kubernetes 架构
要了解 Kubernetes 如何提供这些功能,有助于从高层次了解其设计和组织方式。Kubernetes 可以被视为一种分层构建的系统,每个更高的层次都在抽象底层的复杂性。
在其基础层次,Kubernetes 将个别物理或虚拟机器汇集成一个集群,使用共享网络在每台服务器之间进行通信,无论是物理还是虚拟机器。这个 Kubernetes 集群是配置所有 Kubernetes 组件、功能和工作负载的物理平台。
Kubernetes集群中的机器都被赋予了Kubernetes生态系统中的角色。一个服务器(或者在高可用部署中是一个小型组)充当主服务器。该服务器通过为用户和客户端暴露Kubernetes API、对其他服务器进行健康检查、决定如何最佳地分配和指定工作(称为“调度”)以及协调其他组件之间的通信(有时称为容器编排),作为集群的网关和大脑。主服务器充当了与集群的主要联系点,并负责大部分Kubernetes提供的集中式逻辑。
集群中的其他机器被指定为节点:负责接受并使用本地和外部资源运行工作负载的服务器。为了帮助隔离、管理和灵活性,Kubernetes在容器中运行应用程序和服务,因此每个节点都需要配备容器运行时(如Docker或rkt)。节点从主服务器接收工作指令,并相应地创建或销毁容器,调整网络规则以适当地路由和转发流量。
如上所述,应用程序和服务本身在集群中的容器内运行。底层组件确保应用程序的期望状态与集群的实际状态相匹配。用户通过与主要的 Kubernetes API 服务器直接通信或使用客户端和库来与集群交互。要启动应用程序或服务,需要提交一个声明性计划,以 JSON 或 YAML 格式定义要创建的内容以及如何管理。然后,主服务器接受计划并通过检查系统的要求和当前状态来确定如何在基础设施上运行它。这组根据用户定义的计划运行的应用程序代表了 Kubernetes 的最终层。
主服务器组件
如上所述,主服务器充当 Kubernetes 集群的主要控制平面。它作为管理员和用户的主要联系点,并为相对不那么复杂的工作节点提供许多集群范围的系统。总体而言,主服务器上的组件协同工作,接受用户请求,确定最佳的工作负载容器调度方式,对客户端和节点进行身份验证,调整集群范围的网络,以及管理扩展和健康检查责任。
这些组件可以安装在一台机器上,也可以分布在多台服务器上。在本节中,我们将查看与 Kubernetes 集群的主服务器相关联的每个单独组件。
etcd
Kubernetes 需要的基本组件之一是一个全局可用的配置存储。由 CoreOS 团队(操作系统)开发的etcd项目是一个轻量级的分布式键值存储,可以配置为跨多个节点。
Kubernetes 使用 etcd
来存储配置数据,每个集群中的节点都可以访问这些数据。这可以用于服务发现,并可以帮助组件根据最新信息配置或重新配置自己。它还通过提供简单的 HTTP/JSON API 来帮助维护集群状态,用于领导者选举和分布式锁定等功能,设置或检索值的接口非常直接。
与控制平面中的大多数其他组件一样,etcd
可以在单个主服务器上配置,也可以在生产场景中分布在多台机器上。唯一的要求是它对每个 Kubernetes 机器都是网络可访问的。
kube-apiserver
其中一个最重要的主服务是 API 服务器。这是整个集群的主要管理点,因为它允许用户配置 Kubernetes 的工作负载和组织单位。它还负责确保 etcd
存储和已部署容器的服务详细信息保持一致。它充当各种组件之间的桥梁,以维护集群健康并传播信息和命令。
API 服务器实现了 RESTful 接口,这意味着许多不同的工具和库可以轻松地与其通信。一个名为 kubectl 的客户端作为与本地计算机交互的默认方法,可用于与 Kubernetes 集群交互。
kube-controller-manager
控制器管理器是一个通用服务,拥有许多责任。主要是管理不同的控制器,以调节集群的状态,管理工作负载的生命周期并执行常规任务。例如,一个复制控制器确保一个 pod 定义的副本数(相同副本)与当前部署在集群上的数量相匹配。这些操作的详细信息被写入 etcd
,其中控制器管理器通过 API 服务器监视变化。
当发生变化时,控制器读取新信息并实施满足所需状态的过程。这可能涉及扩展或缩减应用程序、调整端点等。
kube-scheduler
实际将工作负载分配给集群中特定节点的过程是调度程序。该服务读取工作负载的操作要求,分析当前基础设施环境,并将工作负载放置在可接受的节点上。
调度程序负责跟踪每个主机上的可用容量,以确保工作负载不会超出可用资源。调度程序必须了解每台服务器上已分配给现有工作负载的总容量以及资源。
cloud-controller-manager
Kubernetes 可以部署在许多不同的环境中,并可以与各种基础架构提供商进行交互,以了解和管理集群中资源的状态。虽然 Kubernetes 使用资源的通用表示,例如可附加的存储和负载均衡器,但它需要一种将这些资源映射到非均质云提供商提供的实际资源的方式。
云控制器管理器充当着粘合剂的作用,使 Kubernetes 能够与具有不同能力、特性和 API 的提供商进行交互,同时在内部保持相对通用的构造。这使得 Kubernetes 能够根据从云提供商收集的信息更新其状态信息,根据系统中所需的变化调整云资源,并创建和使用额外的云服务以满足提交给集群的工作需求。
节点服务器组件
在 Kubernetes 中,通过运行容器执行工作的服务器被称为 节点。节点服务器具有与主组件通信、配置容器网络和运行分配给它们的实际工作负载所必需的一些要求。
A Container Runtime
每个节点必须具有的第一个组件是容器运行时。通常,此要求通过安装和运行 Docker 来满足,但也有 rkt 和 runc 等替代方案可用。
容器运行时负责启动和管理容器,即封装在相对隔离但轻量级操作环境中的应用程序。集群上的每个工作单元基本上都是作为一个或多个容器来实现的,这些容器必须被部署。每个节点上的容器运行时是最终运行提交给集群的工作负载中定义的容器的组件。
kubelet
每个节点与集群组的主要联系点是一个名为kubelet的小型服务。该服务负责将信息传递到控制平面服务,以及与etcd
存储交互以读取配置详细信息或写入新值。
kubelet
服务与主组件通信,以对集群进行身份验证并接收命令和工作。工作以清单的形式接收,其中定义了工作负载和操作参数。然后,kubelet
进程负责在节点服务器上维护工作状态。它控制容器运行时以根据需要启动或销毁容器。
kube-proxy
为了管理每个主机的子网划分并使服务可供其他组件使用,每个节点服务器上都运行一个称为kube-proxy的小型代理服务。该过程将请求转发到正确的容器,可以进行基本的负载均衡,并且通常负责确保网络环境是可预测且可访问的,但在适当的情况下是隔离的。
Kubernetes 对象和工作负载
虽然容器是部署容器化应用程序的基础机制,但 Kubernetes 使用额外的抽象层覆盖容器接口,以提供扩展性、弹性和生命周期管理功能。用户不直接管理容器,而是定义并与由 Kubernetes 对象模型提供的各种原语组成的实例进行交互。我们将在下面讨论可以用来定义这些工作负载的不同类型的对象。
Pods
A pod is the most basic unit that Kubernetes deals with. Containers themselves are not assigned to hosts. Instead, one or more tightly coupled containers are encapsulated in an object called a pod.
A pod generally represents containers that should be controlled as a single application. Pods consist of containers that operate closely together, share a life cycle, and should always be scheduled on the same node. They are managed entirely as a unit and share their environment, volumes, and IP space. In spite of their containerized implementation, you should generally think of pods as a single, monolithic application to best conceptualize how the cluster will manage the pod’s resources and scheduling.
通常,Pod 包含一个主容器,满足工作负载的一般目的,以及可选的一些辅助容器,用于执行密切相关的任务。这些程序适合在自己的容器中运行和管理,但与主应用程序紧密关联。例如,一个 Pod 可能有一个容器运行主应用程序服务器,另一个辅助容器在检测到外部存储库中的更改时拉取文件到共享文件系统。通常不建议在 Pod 级别上进行水平扩展,因为有其他更适合此任务的更高级别对象。
一般来说,用户不应该自己管理 Pod,因为它们不提供应用程序通常所需的一些功能(比如复杂的生命周期管理和扩展)。相反,鼓励用户使用使用 Pod 或 Pod 模板作为基本组件但实现附加功能的更高级别对象。
复制控制器和复制集
在使用 Kubernetes 时,通常不是处理单个 Pod,而是管理一组相同的、复制的 Pod。这些 Pod 是从 Pod 模板创建的,可以通过称为复制控制器和复制集的控制器进行水平扩展。
A replication controller is an object that defines a pod template and control parameters to scale identical replicas of a pod horizontally by increasing or decreasing the number of running copies. This is an easy way to distribute load and increase availability natively within Kubernetes. The replication controller knows how to create new pods as needed because a template that closely resembles a pod definition is embedded within the replication controller configuration.
复制控制器负责确保集群中部署的 Pod 数量与其配置中的 Pod 数量相匹配。如果 Pod 或基础主机失败,控制器将启动新的 Pod 进行补偿。如果控制器配置中的副本数量发生变化,控制器将启动或销毁容器以匹配所需数量。复制控制器还可以执行滚动更新,逐个将一组 Pod 滚动到新版本,最大程度地减少对应用程序可用性的影响。
复制集是对复制控制器设计的迭代,具有更大的灵活性,可以更好地识别控制器需要管理的 Pod。由于复制集具有更强大的副本选择能力,因此开始取代复制控制器,但是它们无法像复制控制器那样执行滚动更新,将后端逐步转换到新版本。相反,复制集意味着用于在提供该功能的附加高级单元内部使用。
与 Pod 一样,复制控制器和复制集都不是您直接使用的单元。虽然它们基于 Pod 设计以添加水平扩展和可靠性保证,但它们缺少一些在更复杂对象中找到的精细的生命周期管理功能。
部署
部署是直接创建和管理的最常见的工作负载之一。部署使用复制集作为构建模块,为混合添加了灵活的生命周期管理功能。
虽然使用复制集构建的部署似乎重复了复制控制器提供的功能,但部署解决了实现滚动更新时存在的许多痛点。在使用复制控制器更新应用程序时,用户需要提交一个新复制控制器的计划,以替换当前的控制器。当使用复制控制器时,跟踪历史记录、在更新期间从网络故障中恢复以及回滚错误更改等任务要么很困难,要么由用户负责。
部署是一个高级对象,旨在简化复制的Pod的生命周期管理。通过更改配置,可以轻松修改部署,Kubernetes将调整复制集,管理不同应用程序版本之间的过渡,并可选地自动维护事件历史记录和撤消功能。由于这些特性,部署可能是您最频繁使用的Kubernetes对象类型。
有状态集
有状态集是专门的 Pod 控制器,提供顺序和唯一性保证。主要用于在部署顺序、持久化数据或稳定网络方面有特殊要求时,可以更精细地控制。例如,有状态集通常与面向数据的应用程序(如数据库)相关联,这些应用程序需要即使重新调度到新节点也能访问相同的卷。
有状态集通过为每个 Pod 创建一个唯一的基于数字的名称,提供稳定的网络标识符,即使需要将 Pod 移动到另一个节点,这个名称也将持续存在。同样,持久性存储卷可以在需要重新调度时与 Pod 一起转移。这些卷甚至在删除 Pod 后仍然保持持久,以防止意外数据丢失。
守护进程集
守护进程集是另一种专门的 Pod 控制器形式,它在集群中的每个节点上运行一个 Pod 的副本(如果指定,则是子集)。这在部署帮助执行维护并为 Kubernetes 节点本身提供服务的 Pod 时最常用。
例如,收集和转发日志、汇总指标以及运行增加节点自身能力的服务都是常见的守护进程集的候选对象。由于守护进程集通常提供基本服务,并且在整个群集中都是必需的,它们可以绕过 Pod 调度限制,防止其他控制器将 Pod 分配给特定主机。例如,由于其独特的职责,主服务器经常被配置为无法用于正常的 Pod 调度,但守护进程集可以在 Pod 按照 Pod 的基础上覆盖限制,以确保关键服务正在运行。
作业和定时作业
到目前为止,我们描述的工作负载都假设了长时间运行的服务式生命周期。Kubernetes 使用名为 作业 的工作负载来提供更加基于任务的工作流程,其中运行的容器预计在完成工作后的一段时间内成功退出。如果您需要执行一次性或批处理处理而不是运行连续服务,则作业非常有用。
在工作中建立了定时作业。就像 Linux 和类 Unix 系统上的传统cron
守护程序一样,Kubernetes 中的 cron 作业提供了一个界面,用于带有调度组件的作业运行。Cron 作业可用于安排未来执行的作业,或定期执行。Kubernetes cron 作业基本上是经典 cron 行为的重新实现,使用集群作为平台,而不是单个操作系统。
其他 Kubernetes 组件
除了您可以在集群上运行的工作负载之外,Kubernetes 还提供了许多其他抽象,帮助您管理应用程序,控制网络,并实现持久性。我们将在这里讨论一些更常见的示例。
Kubernetes 服务
到目前为止,我们一直在使用“服务”这个术语,以传统的类 Unix 方式来表示:用于表示长时间运行的进程,通常是网络连接的,能够响应请求。然而,在 Kubernetes 中,服务是一个充当基本内部负载均衡器和代理的组件,用于 pod。服务将执行相同功能的逻辑 pod 集合组合在一起,以将它们呈现为单个实体。
这使您能够部署一个能够跟踪和路由特定类型的所有后端容器的服务。内部消费者只需要知道服务提供的稳定端点。同时,服务抽象允许您根据需要扩展或替换后端工作单元。服务的IP地址保持稳定,不受路由到的Pod的更改影响。通过部署服务,您可以轻松获得可发现性,并简化容器设计。
每当您需要为另一个应用程序或外部消费者提供对一个或多个Pod的访问时,您应该配置一个服务。例如,如果您有一组运行Web服务器的Pod,应该可以从互联网访问它们,服务将提供必要的抽象。同样,如果您的Web服务器需要存储和检索数据,您将希望配置一个内部服务,以使它们能够访问您的数据库Pod。
尽管服务默认仅使用内部可路由的IP地址可用,但可以通过选择几种策略之一使其在集群外可用。NodePort配置通过在每个节点的外部网络接口上打开静态端口来工作。外部端口的流量将自动路由到适当的Pod,使用内部集群IP服务。
另外,LoadBalancer服务类型将创建一个外部负载均衡器,以通过云提供商的Kubernetes负载均衡器集成路由到服务。云控制器管理器将创建适当的资源,并使用内部服务服务地址进行配置。
卷和持久卷
在许多容器化环境中,可靠地共享数据并保证其在容器重新启动时可用是一个挑战。容器运行时通常提供一些机制,将存储附加到容器上,使其持久化超出容器的生命周期,但是这些实现通常缺乏灵活性。
为了解决这个问题,Kubernetes 使用了自己的 卷 抽象,允许数据被所有在一个 pod 内的容器共享,并保持可用直到 pod 终止。这意味着紧密耦合的 pods 可以轻松地共享文件,而无需复杂的外部机制。 pod 内的容器失败不会影响对共享文件的访问。一旦 pod 终止,共享卷就会被销毁,因此它不是真正持久数据的好解决方案。
持久卷 是一种用于抽象更强大的存储的机制,它不与 pod 生命周期绑定。相反,它们允许管理员为集群配置存储资源,用户可以为其运行的 pod 请求和声明这些资源。一旦一个 pod 使用完持久卷,卷的回收策略决定了卷是否保留直到手动删除或立即与数据一起删除。持久数据可用于防止基于节点的故障,并分配比本地可用的更多的存储空间。
标签和注释
A Kubernetes organizational abstraction related to, but outside of the other concepts, is labeling. A label in Kubernetes is a semantic tag that can be attached to Kubernetes objects to mark them as a part of a group. These can then be selected for when targeting different instances for management or routing. For instance, each of the controller-based objects use labels to identify the pods that they should operate on. Services use labels to understand the backend pods they should route requests to.
标签被给定为简单的键值对。每个单元可以有多个标签,但每个单元只能有一个键的条目。通常,一个“名称”键被用作通用标识符,但你还可以通过其他标准如开发阶段、公共可访问性、应用程序版本等来分类对象。
注释是一种类似的机制,允许你将任意键值信息附加到对象上。虽然标签应该用于语义信息,有助于将一个 pod 与选择标准匹配,但注释更自由形式,可以包含较少结构化数据。总的来说,注释是一种向对象添加丰富元数据的方式,这些元数据对于选择目的并不有用。
结论
Kubernetes是一个令人兴奋的项目,它允许用户在高度抽象的平台上运行可扩展、高可用的容器化工作负载。虽然 Kubernetes 的架构和一系列内部组件乍一看可能令人望而却步,但它们的强大、灵活性和健壮的功能集在开源世界和云原生开发中是无与伦比的。通过理解基本构建块如何相互配合,您可以开始设计系统,充分利用平台的功能来运行和管理规模化的工作负载,构建出色的云原生应用。
Source:
https://www.digitalocean.com/community/tutorials/an-introduction-to-kubernetes