Logo
Section 1 / 6

Kubernetes 概览

了解 Kubernetes 并掌握其架构。

导入

Kubernetes 概览

了解 Kubernetes 并掌握其架构。

Kubernetes 概览

Kubernetes 是一个容器编排平台,能够帮助更好地管理分布式环境中的容器化应用。它具备以下能力:

  • 声明式 API
  • 零停机部署
  • 多种策略的动态调度
  • 自动扩缩容
  • 无缝发布
  • 以容器为中心的基础设施

它显著降低了在分布式系统中维护应用所需的工作量,使团队能够专注于核心业务,即应用程序本身。

  • Kubernetes 彻底改变了应用的构建与部署方式。它提供了关键的抽象机制,隐藏了管理容器的复杂性,使我们能够构建更复杂、更具可靠性、可扩展性和弹性的应用。如今,它是云原生应用开发的事实标准,带来了前所未有的速度和效率。

  • Kubernetes 具有良好的可移植性和供应商无关性,可在多种基础设施上运行,包括物理机、虚拟机以及公有云或私有云平台。甚至可以在我们的树莓派上运行。

  • Kubernetes 的采用已真正进入主流。全球各类规模的组织都在广泛使用。Kubernetes 的下一个发展重点不再是普及,而是扩展与定制。

  • Kubernetes 是一个设计精良且影响深远的项目,能够帮助用户轻松运行可扩展且高可用的容器化工作负载。它提供了大量高度抽象的对象和 API,有助于用户高效地设计和开发容器化服务。

设计原则

尽管 Kubernetes 的架构、概念和组件初看可能令人望而生畏,但它提供了无与伦比且强大的功能集。理解 Kubernetes 的基本构建模块,有助于我们充分挖掘其能力,实现可扩展且高可用的工作负载运行。

在深入探讨 Kubernetes 架构之前,先花些时间了解其设计原则。这些原则不仅有助于我们更好地理解 Kubernetes 的架构,还能在尝试扩展和定制时提供重要指导。

声明式 API

Kubernetes 最重要且最具特色的设计原则是 声明式 API,可以简单理解为系统的期望状态。Kubernetes 确保每个声明式对象都反映并匹配其期望状态。我们只需定义系统在期望状态下的样子,其余工作交由 Kubernetes 完成。这使得系统具备自愈能力和高可用性,无需人工干预。

Kubernetes 中的所有控制器都会对声明式对象进行协调,检测当前状态与期望状态之间的差异,并执行必要的操作,将对象恢复到期望状态。这是我们在实现自定义控制器时必须遵循的原则,后续课程将深入讨论。

以 kubelet 为例,kubelet 中的 PLEG(Pod 生命周期事件生成器)控制器会定期重新列出所有容器,发现配置不一致的情况并生成 Pod 事件。随后,kubelet 会采取必要措施,将这些容器恢复到期望状态。

...
PLEG in the kubelet

自愈能力

Kubernetes 是一个自愈系统。虽然这一点可归入上述声明式 API 的范畴,但自愈能力值得作为另一项核心设计原则。这也是任何外部控制器或 Operator 必须遵循的原则。

一方面,Kubernetes 本身具备自愈能力。借助 informers,Kubernetes 内部所有组件都会维护一些状态或缓存,并定期刷新。这些缓存也减轻了 kube-apiserver 的负担。即使某个事件被遗漏或网络出现短暂中断,系统也能迅速恢复正常。

另一方面,Kubernetes 会持续采取行动,确保对象始终处于期望状态,包括防范各种故障和异常、自动水平扩缩容等。这有助于提升系统的稳定性、可用性和可靠性。例如,若我们声明了一个包含三个副本的应用,Kubernetes 将持续确保恰好有三个健康副本在运行,不多不少。如果有人手动删除了一个副本,Kubernetes 会自动创建一个新的,使其回到期望状态。同样,它也会移除多余的副本。

抽象与解耦

Kubernetes 被设计为一个松散耦合的分布式系统,其组件独立运行。同时,它提供了多种抽象,允许使用不同的实现方式。例如,在 AWS 上运行 Kubernetes 时,可以使用 ELB(弹性负载均衡)作为外部服务的负载均衡器。由于这些抽象的存在,我们可以轻松地根据需求定制和扩展 Kubernetes。这正是 Kubernetes 强大的原因。

同时,Kubernetes 通过抽象天然支持解耦的服务运行。Kubernetes 使用 Pod 对象描述一个微服务实例。Service 这一抽象对象用于暴露一组 Pod 上运行的应用;而 Pod 是临时的,随时可能终止并被替换。这种解耦设计有助于追踪健康的 Pod 对象,并自动绑定其 IP 地址。因此,这些微服务可以独立伸缩,因为它们在逻辑上彼此独立。开发者可以以更高的速度将新变更投入生产环境。

不可变基础设施

最后但同样重要的是,Kubernetes 遵循不可变基础设施的原则。

一切都有可能出错,随着时间推移问题不可避免。很多时候,我们浪费大量时间在排查根本原因和调试运行时问题上。大多数情况下,真正的根源是配置错误。

Kubernetes 将 Pod 对象视为不可变基础设施。Pod 是 Kubernetes 的基本构建单元,由一个或多个紧密相关的容器组成。使用不可变基础设施的好处巨大,例如:简化运维(将 Pod 视为牛群而非个体)、减少配置漂移、降低出错概率、保持环境一致性等。通过替换而非维护失败或错误的实例,更容易保障高可用性并满足服务级别协议。此外,一旦发生错误,也能够轻松回滚到之前的稳定状态。

Kubernetes 架构

现在,让我们更深入地了解 Kubernetes 的架构。Kubernetes 运行在一组节点(如物理服务器、虚拟机等)之上,这些节点可分为两类:

  • 控制平面节点(以前称为“主节点”)承载 Kubernetes 控制平面,充当集群的网关。它们通过暴露 REST API 供用户和客户端使用,负责选择候选节点(即调度)、协调其他组件间的通信等。控制平面由多个组件构成,包括 kube-apiserver、kube-scheduler、kube-controller-manager 和 etcd。
  • 工作节点 是实际运行应用程序的地方。在工作节点上部署了 kubelet 和 kube-proxy。

etcd 集群存储整个集群的状态,包括配置信息、声明内容以及所有对象的运行状态。它是 Kubernetes 集群的大脑。因此,通常会部署一个高可用的 etcd 集群,节点数量为奇数,并通过 Raft 算法进行通信。

控制平面提供了 Kubernetes 的大部分核心逻辑。强烈建议配置多个主节点以保证高可用性。即使某个控制平面节点宕机,或某个控制平面组件出现临时故障,整个集群仍能正常运行。

Kubernetes 所有组件之间都是松散耦合的。后续课程将详细讲解这五个核心组件。

...
Kubernetes architecture

控制平面节点与工作节点之间没有本质区别。我们可以在控制平面节点上运行 kubelet。但这并不推荐,因为可能带来安全风险并影响控制平面的稳定性。大多数安装工具(如 kubeadm)默认会在控制平面节点上设置污点(taint)。如果确实需要在这些节点上调度 Pod,可以使用以下命令移除这些污点:

1kubectl taint nodes --all node-role.kubernetes.io/control-plane- node-role.kubernetes.io/master-

输出如下:

1node "node-01" untainted 2node "node-02" untainted 3...

上述命令将从所有节点(包括控制平面节点)移除 node-role.kubernetes.io/control-plane 和 node-role.kubernetes.io/master 污点。从版本 1.25 开始,旧版污点名称 node-role.kubernetes.io/master 已正式移除。

创建集群

创建 Kubernetes 集群的方法有很多。本课程将介绍其中几种。

Kind 方法不推荐,因为它难以配置和定制。

kubeadm 是官方推荐的创建符合最佳实践的最小可行 Kubernetes 集群的方法。在本课程中,我们强烈建议使用 kubeadm 创建集群,原因如下:

  • 我们不需要非常庞大的集群。两个节点的小型集群已足够满足本课程的需求。

  • 操作极其简单直接。仅需两步:kubeadm init 和 kubeadm join 即可完成集群创建。

  • 它能消除复杂的配置,让我们聚焦于核心内容。大多数情况下,默认配置已能满足使用需求。使用简单配置更容易演示我们所做的修改,并进行定制。

  • 当集群出现问题时,可通过 kubeadm reset 方便地清理并重新创建。

  • 可轻松获取任意版本的 Kubernetes 集群。每个 kubeadm 版本都支持特定范围的 Kubernetes 版本。通过选择对应版本的 kubeadm,即可快速搭建所需版本的集群。这对于快速验证自定义配置非常有用。

开始之前

Kubernetes 的核心:kube-apiserver