Kubernetes 部署的工作原理

已完成

无人机跟踪应用具有多个彼此独立部署的组件。 你需要在群集上为这些组件配置部署。 本文将介绍一些用于部署这些组件的可用部署选项。

Diagram of the high-level architecture that shows the drone-tracking solution components.

Pod 部署选项

使用 kubectl 时,有几个选项可用于管理 Kubernetes 群集中 Pod 的部署。 选项包括:

  • Pod 模板
  • 复制控制器
  • 副本集
  • 部署

你可以使用上述 4 个 Kubernetes 对象类型定义中的任意一个来部署一个或多个 Pod。 这些文件使用 YAML 来描述要部署的一个或多个 Pod 的预期状态。

什么是 Pod 模板?

使用 Pod 模板可以定义要部署的 Pod 的配置。 该模板包含容器映像的名称等信息,容器注册表使用这些信息来获取映像。 该模板也包含运行时配置信息,例如要使用的端口。 模板是使用 YAML,按照创建 Docker 文件的方式定义的。

你可以使用模板手动部署 Pod。 但是,手动部署的 Pod 在失败、删除或终止后不会重新启动。 若要管理 Pod 的生命周期,你需要创建更高级别的 Kubernetes 对象。

什么是复制控制器?

复制控制器使用 Pod 模板,并定义必须运行的指定数量的 Pod。 该控制器有助于运行同一个 Pod 的多个实例,并确保 Pod 始终在群集中的一个或多个节点上运行。 控制器替换运行的 Pod 的方式是:如果它们失败、被删除或终止,将它们替换为新的 Pod。

例如,假设你部署了无人机跟踪前端网站,并且用户开始访问该网站。 如果由于某种原因,所有 Pod 都失败了,则用户无法访问该网站,除非启动新的 Pod。 复制控制器有助于确保用户始终能访问网站。

什么是副本集?

副本集替代复制控制器,成为部署副本的首选方法。 副本集包含与复制控制器相同的功能,但它有一个额外的配置选项,可以包含选择器值。

选择器使副本集能够识别在它下面运行的所有 Pod。 使用此功能,你可以管理标有选择器值的 Pod,但无法管理使用复制集创建的 Pod。

什么是部署?

部署创建的管理对象比副本集创建的高一级,并使你能够在群集中部署和管理 Pod 的更新。

假设你的群集中部署了五个应用实例。 有 5 个 Pod 在运行 1.0.0 版应用。

Diagram that shows five pods running on a node with the same pod version.

如果决定手动更新应用,可移除所有 Pod,然后启动运行 2.0.0 版应用的新 Pod。 采用此策略,应用将出现停机。

你转而需要执行滚动更新,在此过程中,先使用新版应用启动 Pod,再移除运行更低应用版本的 Pod。 滚动更新一次启动一个 Pod,而不是一次性关闭所有旧的 Pod。 部署遵循在描述副本集相关信息的部分中配置的副本数。 这将在使用新 Pod 替换旧 Pod 时维持副本集中指定的 Pod 数量。

Diagram that shows five pods, two pods set as version 1 and 3 pods set as version 2.

默认情况下,部署提供用于更新 Pod 的滚动更新策略。 你还可以使用重新创建策略。 在启动新的 Pod 之前,此策略将终止 Pod。

部署还提供了可使用 kubectl 执行的回滚策略。

部署利用基于 YAML 的定义文件,便于管理部署。 请记住,部署允许将任何更改应用到群集。 例如,可以部署新版的应用、更新标签,以及运行 Pod 的其他副本。

使用 kubectl run 命令部署 Pod 时,kubectl 有简洁的语法用于自动创建部署。 此命令创建具有所需副本集和 Pod 的部署。 但该命令不会创建定义文件。 最佳做法是使用部署定义文件管理所有部署,并使用版本控制系统来跟踪更改。

部署注意事项

对于如何为群集配置网络和存储,Kubernetes 有特定的要求。 网络和存储的配置方式会影响你决定以何种方式在群集网络上公开应用以及存储数据。

例如,无人机跟踪应用中的每项服务在用户访问、进程间网络访问以及数据存储方面都有特定的要求。 接下来,我们将探讨 Kubernetes 群集的这些方面,以及它们对应用部署的影响。

Kubernetes 网络

假设你的群集有一个控制平面和两个节点。 将节点添加到 Kubernetes 时,IP 地址会被自动分配到内部专用网络范围内的每个节点。 例如,假设本地网络范围为 192.168.1.0/24。

Diagram of nodes with assigned IP addresses in a cluster.

部署的每个 Pod 将分配获得 IP 地址池中的一个 IP。 例如,假设你的配置使用的网络范围是 10.32.0.0/12,如下图所示。

Diagram of nodes and pods with assigned IP addresses in a cluster.

默认情况下,使用不同 IP 地址范围的 Pod 和节点不能互相通信。

若要进一步复杂化,请记住,Pod 是暂时性的。 Pod 的 IP 地址是临时的,不能用于重新连接到新创建的 Pod。 此配置会影响应用与其内部组件通信的方式,以及你和服务与其进行外部交互的方式。

为了简化通信,Kubernetes 要求以如下方式配置网络:

  • 在没有网络地址转换 (NAT) 的情况下,Pod 之间可以进行跨节点的通信。
  • 即使没有 NAT,节点也能与所有 Pod 相互通信。
  • 节点上的代理可以与所有节点和 Pod 通信。

Kubernetes 提供了几个网络选项,在安装后可用于配置网络, 例如 Antrea、Cisco Application Centric Infrastructure (ACI)、Cilium、Flannel、Kubenet、VMware NSX-T 和 Weave Net。

云服务提供商也会提供他们自己的网络解决方案。 例如,Azure Kubernetes 服务 (AKS) 支持 Azure 虚拟网络容器网络接口 (CNI)、Kubenet、Flannel、Cilium 和 Antrea。

Kubernetes 服务

Kubernetes 服务是为 Pod 提供稳定网络的 Kubernetes 对象。 使用 Kubernetes 服务可以实现节点间、Pod 间以及群集内外应用用户间的相互通信。

Kubernetes 在服务创建时会为其分配 IP 地址,就像节点或 Pod 一样。 这些地址是从服务群集的 IP 范围中分配的,例如 10.96.0.0/12。 服务还会分配获得一个基于服务名称的 DNS 名称和一个 IP 端口。

在无人机跟踪应用中,网络通信如下所示:

  • 网站和 RESTful API 可供群集外的用户访问。

  • 前端和 RESTful API 可以分别访问内存中缓存和消息队列服务,但外部用户不能访问。

  • 消息队列需要访问数据处理服务,但不需要访问外部用户。

  • 内存中缓存和数据处理服务可以访问 NoSQL 数据库,但是外部用户不能访问。

为了支持这些场景,可以配置三种类型的服务用于公开应用组件。

服务 说明
ClusterIP 这是分配给服务的地址,让群集内的一组服务可以访问该服务。 例如,应用的前端和后端组件之间的通信。
NodePort 这是 Kubernetes 控制平面分配给服务的节点端口,介于 30000 和 32767 之间,例如 clusters01 上的 192.169.1.11。 然后,使用要公开的 Pod 上的目标端口配置该服务。 例如,在其中一个前端上运行的 Pod 上配置端口 80。 现在可以通过节点 IP 和端口地址访问前端。
LoadBalancer 此负载均衡器可实现在运行应用并向公用网络访问公开 Pod 的节点间分配负载。 使用云服务提供商时,通常会配置负载均衡器。 在这种情况下,来自外部负载均衡器的流量会定向到运行应用的 Pod。

在无人机跟踪应用中,你可能会决定使用 LoadBalancer 来公开跟踪网站和 RESTful API,使用 ClusterIP 来公开数据处理服务。

如何对 Pod 进行分组

按 IP 地址管理 Pod 并不实际。 控制器重新创建 Pod IP 地址时,这些地址会更改,并且运行的 Pod 数量不受限制。

Diagram of a service with selector labels.

利用服务对象,可以使用选择器标签来锁定和管理群集中的特定 Pod。 在服务定义中设置选择器标签,以匹配 Pod 定义文件中定义的 Pod 标签。

例如,假设正在运行多个 Pod。 只有几个 Pod 位于前端,并且你想要设置仅面向前端 Pod 的 LoadBalancer 服务。 通过将 Pod 标签作为服务定义文件中的选择器值引用,可以应用服务以公开这些 Pod。 服务会仅将与标签匹配的 Pod 分组。 如果删除并重新创建了某个 Pod,则新的 Pod 会通过其匹配标签自动加入服务组。

Kubernetes 存储

Kubernetes 采用与 Docker 一样的存储卷概念。 Docker 卷所受的管理比 Kubernetes 卷少,因为 Docker 卷生存期不受管理。 Kubernetes 卷的生存期是与 Pod 生存期匹配的显式生存期。 这种生存期上的匹配意味着卷的生存期比 Pod 中运行的容器要长。 不过当 Pod 被删除时,卷也会被删除。

Diagram of a service with selector labels again.

Kubernetes 提供了使用 PersistentVolumes 预配持久存储的选项。 你还可以通过使用 PersistentVolumeClaims 来请求 Pod 的特定存储。

在部署需要持久存储的应用组件(如消息队列和数据库)时需要考虑这两个选项。

云集成注意事项

Kubernetes 并未规定在云原生应用中使用的技术堆栈。 在 Azure 之类的云环境中,可以在 Kubernetes 群集之外使用多种服务。

回想一下前面的内容,Kubernetes 不提供下面的任何一项服务:

  • 中间件
  • 数据处理框架
  • 数据库
  • 缓存
  • 群集存储系统

在此无人机跟踪解决方案中,有三种提供中间件功能的服务:NoSQL 数据库、内存中缓存服务和消息队列。 你可以选择使用 MongoDB Atlas 来实现 NoSQL 解决方案,使用 Redis 来管理内存中缓存,根据消息队列需求使用 RabbitMQ 或 Kafka。

使用类似 Azure 这样的云环境时,最好是在 Kubernetes 群集之外使用服务。 这样做可简化群集的配置和管理工作。 例如,可以将 Azure Cache for Redis 用于内存中缓存服务,将 Azure 服务总线消息传送用于消息队列,并将 Azure Cosmos DB 用于 NoSQL 数据库。