Kubernetes 架构深度解析:从 Borg 到云原生
本文深入探讨了 Kubernetes 的架构设计原则与核心对象模型,追溯其设计灵感来源 Borg,并解析其在云原生时代的关键作用。
1. 云计算的演变:从虚拟机到容器编排
云计算的核心思想是将计算资源(CPU、内存、存储、网络等)池化,通过网络按需提供给用户,无需用户自行建设和维护物理基础设施。其发展大致经历了两个重要阶段:
第一阶段:虚拟化平台 (以 OpenStack 为代表)
- 核心技术: Hypervisor(如 KVM, Xen)将物理服务器分割成多个独立的虚拟机(VM)。每个 VM 拥有自己的操作系统和资源视图。
- 优点: 提高了硬件利用率,实现了初步的资源隔离。
- 缺点:
- 部署流程割裂: VM 创建与应用部署分离,流程繁琐,需要手动配置环境。
- 资源开销大: 每个 VM 都需要运行完整的操作系统,带来额外的 CPU、内存和存储开销。
- 环境一致性难保证: 不同 VM 的底层环境可能存在差异,增加维护复杂性。
- 启动速度慢: VM 启动需要加载整个操作系统。
第二阶段:基于容器的集群管理平台 (以谷歌 Borg 和 Kubernetes 为代表)
- 核心技术: 操作系统级虚拟化(容器),利用 Linux Namespaces 和 Cgroups 实现进程隔离和资源限制。
- 优点:
- 轻量级: 容器共享宿主机内核,资源开销小,启动速度快(秒级甚至毫秒级)。
- 环境一致性: 容器镜像打包了应用及其所有依赖,确保开发、测试、生产环境一致。
- 更高的资源利用率: 可以在同一宿主机上运行更多容器实例。
- 更快的部署与恢复: 应用部署和故障恢复速度显著提升。
- 挑战: 如何高效地管理、调度、扩展和维护大规模容器集群成为新的挑战,催生了 Borg 和 Kubernetes 等容器编排系统。
2. 谷歌 Borg:Kubernetes 的思想源泉与实践基础
Borg 是谷歌内部使用的大规模集群管理系统,运行多年,支撑了包括 Search, Gmail, Maps 在内的众多核心业务。Kubernetes 的许多核心概念和设计思想都源于 Borg 的实践经验。
2.1 Borg 的核心特性
- 极高的资源利用率: 通过混部(co-location)生产和非生产任务,以及精细化的资源超卖和回收机制,最大化硬件价值。
- 高可用性与可靠性: 自动化的故障检测与恢复机制,保证关键服务持续运行。
- 大规模集群管理: 支持管理数万台机器的超大集群(Cell)。
- 灵活的作业调度: 支持不同优先级、资源需求和约束条件的任务调度。
- 声明式配置: 用户描述期望状态,Borg 负责达成。
2.2 Borg 的关键概念
- Workload(工作负载):
- prod (production): 在线服务型任务,对延迟敏感,需要长期运行,高优先级。
- non-prod (non-production): 离线批处理型任务,对延迟不敏感,可容忍抢占,低优先级。
- Cell(单元): 一个 Borg 管理域,通常包含数千到数万台机器,由一个逻辑上中心化的 Borgmaster 和分布在各节点上的 Borglet 组成。用户通常与 Cell 交互,无需关心具体机器。
- Job 和 Task:
- Job: 用户提交的部署单元,描述了一个应用或服务,包含一个或多个 Task。Job 定义了 Task 的属性,如镜像、资源需求、约束等。
- Task: Job 的执行实例,对应一个或多个运行在同一台机器上的 Linux 进程(通常在容器内)。Task 是 Borg 调度的基本单位。
- Alloc Sets 和 Allocs:
- Alloc (Allocation): 预留在机器上的一组资源(CPU, RAM, Disk等),用于运行 Task。可以理解为资源预留的“槽位”。Task 必须运行在 Alloc 内。
- Alloc Set: 逻辑上相关的 Alloc 的集合,通常用于部署需要一起调度的 Task(类似 Kubernetes Pod 的早期概念,但更侧重资源预留)。
- Priority, Quota: 用于控制不同用户和 Job 对资源的访问权限和调度优先级。
- Naming & Service Discovery: 通过 BNS (Borg Name Service) 实现服务发现。Task 的 DNS 名称包含 Cell、用户、Job 名和 Task 序号,例如
50.jfoo.ubar.cc.borg.google.com
。BNS 还集成了基于 Chubby(分布式锁服务)的健康检查信息。
2.3 Borg 的架构
- Borgmaster:
- 逻辑中心控制器: 每个 Cell 有一个逻辑上的 Borgmaster,物理上由 5 个副本组成的高可用集群。
- 状态维护: 通过 Paxos 协议维护集群状态(节点、任务、Alloc 等)的一致性视图,存储在内存中并定期 Checkpoint 到 Ficus。一个副本作为 Leader 处理所有变更请求,其他副本作为热备。
- RPC 接口: 处理来自客户端(命令行工具、其他服务)的 Job 创建、更新、删除、查询等请求。
- 与 Borglet 通信: 向 Borglet 发送指令(启动/停止 Task),接收 Borglet 的状态汇报。
- 调用 Scheduler: 当有 Pending Task 时,调用 Scheduler 进行调度决策。
- Scheduler:
- 调度决策核心: 负责将 Pending Task 分配到满足其资源需求和约束条件的机器(Borglet)上。
- 两阶段调度:
- 可行性检查 (Feasibility Checking): 找到满足 Task 硬性约束(如架构、资源需求、特定标签)的机器子集。
- 评分 (Scoring): 对可行机器进行打分,选择最优机器。评分考虑因素复杂,包括:资源碎片、任务优先级、能耗、故障域分散、用户偏好(如 best-fit vs worst-fit)等。
- 优化策略: 采用缓存、并行化、松弛约束等多种技术提高调度吞吐量和效率。
- Borglet:
- 节点代理: 部署在 Cell 中每台机器上的 Agent 进程。
- 任务管理: 负责启动、停止、重启 Task 内的进程(通常在 Linux 容器内)。
- 资源管理: 管理本地资源(CPU, RAM, Disk, Network),监控资源使用情况。
- 状态汇报: 向 Borgmaster 汇报节点状态和 Task 状态。
- 健康检查: 执行本地健康检查。
- Ficus & Chubby:
- Ficus: 持久化存储,用于 Borgmaster Checkpoint。
- Chubby: 分布式锁服务,用于 Borgmaster Leader 选举和 BNS 服务发现。
2.4 Borg 的高可用性
- 应用高可用:
- 多副本与故障域: Job 通常部署多个 Task 副本,并分散到不同的故障域(机器、机架、电源域)。
- 自动恢复: Borglet 或机器故障时,Borgmaster 会自动在其他可用节点上重新调度失败的 Task。
- 优雅处理 Master/Borglet 故障: 关键原则: 即使 Borgmaster 或 Borglet 短暂失联或重启,也不应主动杀掉正在运行的 Task,保证服务连续性。Borglet 重启后会尝试恢复对本地 Task 的管理。
- 速率限制: 控制节点故障时任务重新调度的速率,防止因网络分区等问题导致大规模误判和任务迁移风暴。
- Borg 系统自身高可用:
- Borgmaster 副本: 5 个副本通过 Paxos 保证状态一致性和 Leader 自动切换。
- 独立 Cell 设计: 每个 Cell 的 Borg 系统(Master, Scheduler)独立部署,故障隔离。
- 简化部署依赖: 使用简单工具部署 Borg 自身,减少外部依赖风险。
2.5 Borg 的资源利用率优化
- 混部 (Co-location): 在同一台机器上混合部署 prod 和 non-prod 任务。
- 资源超卖与抢占: non-prod 任务使用较低优先级,可以使用 prod 任务预留但未使用的资源(可压榨资源,如 CPU)。当 prod 任务需要资源时,可抢占 non-prod 任务的资源,甚至驱逐 non-prod 任务。
- 精细化资源模型: 区分可压榨(CPU)和不可压榨(RAM)资源。内存通常不超卖。
- 资源回收 (Reclamation): Borglet 监控 Task 的实际资源使用量,定期调整其资源预留(Reservation),将未使用的预留资源回收给 Cell,用于调度更多任务。
- Cell Compaction: 通过优化调度策略,将负载集中到部分机器上,允许关闭空闲机器以节省能源。
- 效果显著: 混部和资源回收等机制使得谷歌数据中心的服务器利用率远超传统模式,节省大量成本。
2.6 Borg 的调度原理
graph TD subgraph Machine Resources TotalCapacity --- Reserved TotalCapacity --- Available end subgraph Task Resource Model Request(Reservation) --> Limit(Limit) Request --> ActualUsage(Actual Usage) end Scheduler -- Considers --> Available Scheduler -- Places Task --> Machine Task -- Consumes --> ActualUsage Borglet -- Monitors --> ActualUsage Borglet -- Performs --> Reclamation(Reduces Reservation towards Actual Usage + Headroom) style Request fill:#f9f,stroke:#333,stroke-width:2px style Limit fill:#ccf,stroke:#333,stroke-width:2px style ActualUsage fill:#cfc,stroke:#333,stroke-width:2px
- 调度流程:
- Job 提交,Task 进入 Pending 队列。
- Scheduler 收到调度请求。
- 可行性检查: 过滤掉不满足硬性约束的机器。
- 评分: 对可行机器打分,选择分数最高的机器。评分考虑资源匹配度(best-fit/worst-fit)、优先级、避免资源碎片、分散风险等。
- Borgmaster 将 Task 分配给选定的 Borglet。
- Borglet 启动 Task。
- 资源模型: Task 定义资源请求(Reservation)和限制(Limit)。Reservation 是调度器保证的资源量,Limit 是资源使用的上限。
- 资源回收: Borglet 监控 Task 实际使用量,如果远低于 Reservation,会逐步降低 Reservation(但保留一定 headroom),将差值“回收”给 Cell 的可用资源池。
2.7 Borg 的隔离性
- 安全隔离:
- 早期使用 Chroot jail。
- 后期广泛采用 Linux Namespaces (PID, Net, IPC, Mnt, UTS, User) 实现进程视图隔离。
- 通过 Cgroups 实现资源限制和优先级控制。
- 性能隔离:
- Cgroups: 限制 CPU、内存、I/O 等资源使用。
- 优先级与抢占: Prod 任务优先级高于 non-prod。低优先级任务可能被高优先级任务抢占资源(CPU 时间片)或被驱逐(如果需要回收内存)。
- 资源区分: 可压榨资源(CPU)允许超卖和抢占,不可压榨资源(内存)通常需要严格保证。
2.8 Borg 的局限与 Kubernetes 的改进
尽管 Borg 非常成功,但也存在一些设计上的问题,Kubernetes 在借鉴的同时进行了改进:
- IP 地址共享: Borg 中同一机器上的所有 Task 共享宿主机 IP,通过端口区分服务,易导致端口冲突,管理复杂。Kubernetes 改进: 每个 Pod 拥有独立的 IP 地址(IP-per-Pod 模型),简化了网络模型和应用迁移。
- 紧耦合的对象模型: Borg 的 Job/Task/Alloc 等概念耦合较紧,不够灵活。Kubernetes 改进: 引入更松耦合、可组合的对象(Pod, Service, Deployment, ReplicaSet 等),提高了灵活性和可扩展性。
- 过于强大的“上帝”权限: Borg 为超级用户(SRE)提供了过多直接干预底层状态的接口,增加了系统复杂性和误操作风险。Kubernetes 改进: 强调通过标准的 API 对象和控制器进行管理,减少直接状态操纵。
- 单一集中式 Master: 虽然 Borgmaster 是高可用的,但逻辑上仍是中心化的,可能成为扩展瓶颈。Kubernetes 改进: 控制平面组件(API Server, Scheduler, Controller Manager)可以水平扩展(尽管 etcd 仍是核心瓶颈)。
3. Kubernetes:Borg 设计思想的开源实现与演进
Kubernetes (K8s) 继承了 Borg 的核心理念(如声明式 API、自动化、资源调度),并结合社区实践,发展成为业界标准的容器编排平台。
3.1 K8s 的核心能力
- 自动化部署与扩展: 基于容器的应用部署、维护、滚动更新和回滚。
- 服务发现与负载均衡: 自动化的服务注册、发现和流量分发。
- 存储编排: 支持挂载多种类型的持久化存储。
- 配置与密钥管理: 管理应用的配置信息和敏感数据。
- 自愈能力: 自动替换失败的容器、重新调度 Pod。
- 水平扩展: 根据负载自动调整应用副本数。
- 批处理执行: 支持 Job 和 CronJob。
- 可扩展性: 通过 CRD 和 Operator 机制轻松扩展 API 和功能。
3.2 核心理念:声明式 API 与协调循环
- 命令式 (Imperative) vs 声明式 (Declarative):
- 命令式: 关注“如何做”,用户发出具体的操作指令(如
create server
,configure network
,run process
)。系统按顺序执行。 - 声明式: 关注“做什么”(期望状态),用户提交一个描述最终期望状态的“清单”(Manifest,通常是 YAML 文件),例如“我需要运行 3 个 Nginx 副本,对外暴露 80 端口”。
- 命令式: 关注“如何做”,用户发出具体的操作指令(如
- Kubernetes 的选择:声明式
- 优势:
- 幂等性: 多次提交同一份声明,结果应一致。
- 容错性与自愈: 系统持续监控实际状态,如果与期望状态不符(例如一个 Pod 挂了),会自动采取行动(启动新 Pod)来恢复到期望状态。
- 易于自动化和版本控制: 声明文件可以纳入 Git 等版本控制系统,实现基础设施即代码 (IaC)。
- 优势:
- 协调循环 (Reconciliation Loop) / 控制器模式 (Controller Pattern):
- 这是实现声明式 API 的核心机制。
- 每个控制器 (Controller) 负责监控特定类型的 API 对象(如 Deployment, ReplicaSet, Service)。
- 控制器通过 API Server 获取对象的 期望状态 (Spec) 和 实际状态 (Status)。
- 比较两者差异,如果存在差异,控制器会执行相应的操作(调用 API Server 创建/删除/更新其他对象,或与 Kubelet 交互)来驱动实际状态趋向期望状态。
- 这个
Observe -> Analyze -> Act
的循环持续进行,确保系统状态最终收敛到用户声明的状态。
3.3 Kubernetes 的核心对象 (API Objects)
Kubernetes 将集群中的一切都抽象为 API 对象,用户通过操作这些对象来管理集群和应用。
- Workload (工作负载) 相关:
- Pod: 最核心、最小的部署单元。 包含一个或多个紧密关联的容器,它们共享网络命名空间(同一个 IP 地址和端口空间)、IPC 命名空间和存储卷 (Volumes)。通常代表应用的一个实例。
- ReplicaSet (RS): 确保指定数量的 Pod 副本(由其管理的 Pod Template 定义)在任何时候都处于运行状态。主要由 Deployment 控制。
- Deployment (Deploy): 推荐的应用部署方式。 定义了应用的期望状态(副本数、镜像版本、更新策略等),并通过管理 ReplicaSet 来实现应用的滚动更新和回滚。
- StatefulSet (STS): 用于管理 有状态应用(如数据库、消息队列)。为每个 Pod 提供稳定的、唯一的网络标识符(如
pod-0
,pod-1
)和独立的、持久的存储卷。保证 Pod 按顺序、逐个地部署、更新和删除。 - DaemonSet (DS): 确保 每个(或部分指定的)Node 上都运行一个 Pod 副本。常用于部署集群范围的后台服务,如日志收集器 (Fluentd)、监控 Agent (Node Exporter)、网络插件 Pod 等。
- Job: 用于运行 一次性任务(批处理作业)。确保一个或多个 Pod 成功执行完成。
- CronJob: 用于管理 定时任务,类似 Linux 的 crontab。按预定的时间周期性地创建 Job。
- Service Discovery & Load Balancing 相关:
- Service (Svc): 为一组具有相同标签 (Label) 的 Pod 提供一个 稳定的、统一的访问入口 和负载均衡。Service 有自己的虚拟 IP (ClusterIP) 和 DNS 名称。应用内部可以通过 Service 名称互相访问,无需关心后端 Pod 的 IP 地址变化和数量。
- Ingress: 管理集群外部访问内部 Service 的规则集合,通常用于暴露 HTTP/HTTPS 服务。可以提供基于域名/路径的路由、SSL 终止、负载均衡等功能。需要配合 Ingress Controller(如 Nginx Ingress, Traefik)工作。
- Config & Storage 相关:
- ConfigMap (CM): 用于存储 非机密的配置数据(键值对),并将其注入到 Pod 中(作为环境变量、命令行参数或挂载为文件)。实现配置与镜像分离。
- Secret: 用于存储 敏感信息(如密码、API 密钥、TLS 证书)。数据以 Base64 编码存储(注意:不是加密,需要配合 RBAC 等机制保护),可以像 ConfigMap 一样注入 Pod。
- Volume: Pod 内 容器间共享数据、持久化数据 的机制。支持多种类型,包括:
emptyDir
: Pod 生命周期内的临时存储。hostPath
: 挂载宿主机文件或目录(谨慎使用)。persistentVolumeClaim
: 挂载持久化存储。
- PersistentVolume (PV): 由集群管理员提供的 一块网络存储(如 NFS, Ceph, EBS)。代表实际的存储资源。
- PersistentVolumeClaim (PVC): 用户(Pod)对 存储资源的请求。描述所需的存储大小、访问模式(ReadWriteOnce, ReadOnlyMany, ReadWriteMany)等。PVC 会与满足条件的 PV 绑定。实现存储资源申请与实际存储后端的解耦。
- StorageClass (SC): 定义了 动态创建 PV 的模板。当用户创建 PVC 时,如果指定了 StorageClass,系统会根据 SC 的定义自动创建(Provision)一个匹配的 PV 并与 PVC 绑定。
- Cluster (集群) 相关:
- Node: 集群中的一个 工作节点(物理机或虚拟机),是 Pod 运行的地方。由 Master 组件管理。
- Namespace (NS): 资源隔离的逻辑单元。 用于将一个物理集群划分为多个虚拟集群,适用于多租户、多环境(开发、测试、生产)场景。不同 Namespace 内的对象名称可以重复。资源配额 (ResourceQuota) 和网络策略 (NetworkPolicy) 通常在 Namespace 级别定义。
- Metadata (元数据) 相关:
- Label: 附加到对象上的 键值对标签,用于 识别和选择 对象。例如,Service 通过 Label Selector 找到它要代理的 Pod。一个对象可以有多个 Label。
- Annotation: 附加到对象上的 非识别性元数据(键值对)。用于存储工具、库或用户的额外信息,例如构建版本、日志链接、负责人等。
- OwnerReference: 指明一个对象(如 Pod)是由哪个其他对象(如 ReplicaSet)创建和管理的。用于实现 级联删除(删除 Owner 时自动删除其拥有的对象)。
- Finalizer: 一个特殊的键列表,用于 阻止对象被强制删除,直到相关的清理逻辑完成。例如,在删除 PVC 前确保其绑定的 PV 已按策略处理。
3.4 Kubernetes 的架构:控制平面与数据平面
Kubernetes 集群由 控制平面 (Control Plane) 组件和 工作节点 (Worker Nodes) 组成。
控制平面 (Master Nodes): 集群的大脑,负责管理和决策。通常运行在专用的 Master 节点上(为了高可用,一般至少 3 个 Master 节点)。主要组件包括:
- API Server (kube-apiserver):
- 集群的统一入口: 所有组件(kubectl, Controller Manager, Scheduler, Kubelet)以及用户都通过 API Server 交互。
- 提供 RESTful API: 暴露 Kubernetes API 资源。
- 请求处理: 负责认证 (Authentication)、授权 (Authorization)、准入控制 (Admission Control)。
- 状态存储接口: 是唯一直接与 etcd 交互的组件,负责将对象状态持久化到 etcd 或从 etcd 读取。
- etcd:
- 分布式键值存储: 存储整个集群的所有配置数据和状态信息(API 对象)。是集群的“单一事实来源 (Single Source of Truth)”。
- 高可用与一致性: 通常部署为 3 或 5 个节点的集群,使用 Raft 协议保证数据一致性和高可用性。对 etcd 的性能和稳定性要求极高。
- Scheduler (kube-scheduler):
- Pod 调度器: 监视 API Server 中新创建的、尚未分配节点的 Pod (处于 Pending 状态)。
- 调度决策: 根据 Pod 的资源需求 (requests)、亲和性/反亲和性规则 (affinity/anti-affinity)、污点与容忍 (taints/tolerations)、节点资源可用性等多种因素,为 Pod 选择一个最合适的 Node。
- 调度过程:
- 过滤 (Predicates/Filtering): 筛选出满足 Pod 所有硬性要求的节点。
- 打分 (Priorities/Scoring): 对通过过滤的节点进行评分,选择分数最高的节点。
- 结果: 将选择的 Node 信息更新到 Pod 对象的
spec.nodeName
字段。
- Controller Manager (kube-controller-manager):
- 运行内置控制器: 包含多个核心控制器,每个控制器负责一种特定资源的管理,通过协调循环确保集群状态与期望一致。
- 主要控制器示例:
- ReplicaSet Controller: 监控 ReplicaSet 对象,确保实际 Pod 数量与
spec.replicas
匹配。 - Deployment Controller: 编排滚动更新,管理 ReplicaSet 版本。
- Node Controller: 监控 Node 状态,处理节点故障。
- Service Controller: 根据 Service 类型与云服务商 API 交互(如创建 LoadBalancer)。
- Endpoint Controller: 根据 Service 的 Label Selector 更新 Endpoint 对象(包含 Pod IP 列表)。
- Namespace Controller: 处理 Namespace 删除时的资源清理。
- PersistentVolume Controller: 处理 PV 和 PVC 的绑定。
- ReplicaSet Controller: 监控 ReplicaSet 对象,确保实际 Pod 数量与
- Cloud Controller Manager (cloud-controller-manager): (可选)与特定的云提供商(AWS, GCP, Azure 等)API 交互,管理云相关的资源,如负载均衡器、存储卷、节点等。将云平台相关的逻辑与核心 K8s 代码解耦。
- API Server (kube-apiserver):
工作节点 (Worker Nodes): 运行用户应用程序(Pod)的地方。主要组件包括:
- Kubelet:
- 节点代理: 在每个 Node 上运行,是 Master 与 Node 之间的主要通信桥梁。
- Pod 管理: 监视分配给本节点的 Pod(通过 API Server 或静态文件),确保这些 Pod 中的容器正常运行。
- 与容器运行时交互: 调用容器运行时接口 (CRI) 来创建、启动、停止容器。
- 状态汇报: 向 API Server 汇报 Node 状态和 Pod 状态。
- 健康检查: 执行容器的存活探针 (Liveness Probe) 和就绪探针 (Readiness Probe)。
- 挂载卷: 负责为 Pod 挂载所需的 Volume。
- Kube-proxy:
- 网络代理与负载均衡: 在每个 Node 上运行,负责实现 Kubernetes Service 的网络功能。
- 维护网络规则: 监视 API Server 中 Service 和 Endpoint 对象的变化。
- 流量转发: 根据 Service 定义,在 Node 上配置网络规则(通常使用 iptables 或 IPVS 模式),将访问 Service ClusterIP:Port 的流量转发/负载均衡到后端正确的 Pod IP:Port。
- Container Runtime:
- 容器运行时引擎: 负责实际运行容器的软件,如 Docker, containerd, CRI-O。
- CRI (Container Runtime Interface): Kubelet 通过 CRI 与容器运行时进行通信,这使得 Kubernetes 可以支持多种不同的容器运行时,实现了 Kubelet 与具体运行时的解耦。
- Kubelet:
3.5 Pod 创建流程示例
- 用户/CI/CD 系统 使用
kubectl apply -f pod.yaml
或调用 API 创建一个 Pod 对象。 - kubectl/Client 将请求发送给 API Server。
- API Server 对请求进行认证、授权、准入控制。
- API Server 将 Pod 对象信息(期望状态 Spec)持久化到 etcd。
- API Server 返回成功响应给客户端。
- Scheduler 通过 Watch 机制监听到有一个新的、未绑定的 Pod (
spec.nodeName
为空)。 - Scheduler 执行调度算法(过滤和打分),为 Pod 选择一个合适的 Node。
- Scheduler 通过 API Server 更新 Pod 对象的
spec.nodeName
字段,将其绑定到选定的 Node。 - API Server 将 Pod 的更新信息存储到 etcd。
- Kubelet (运行在被选定 Node 上) 通过 Watch 机制监听到有一个 Pod 被调度到本节点。
- Kubelet 读取 Pod 的 Spec,准备运行环境(如创建目录、拉取镜像)。
- Kubelet 通过 CRI (Container Runtime Interface) 调用 Container Runtime (如 containerd) 创建并启动 Pod 中的容器。
- Kubelet 持续监控 Pod 和容器的状态。
- Kubelet 定期将 Pod 的实际状态 (Status) 和 Node 的状态汇报给 API Server。
- API Server 将更新后的状态存储到 etcd。
- (如果 Pod 属于某个 Service) Kube-proxy 监听到 Pod 的创建和 IP 分配,更新本地的网络规则 (iptables/IPVS),将 Service 流量可以路由到这个新 Pod。
- (如果 Pod 由 ReplicaSet/Deployment 管理) Controller Manager 中的相应控制器会监控 Pod 状态,并在需要时(如 Pod 失败)采取行动(如创建新 Pod)。
3.6 Kubernetes 的常用 Add-ons (附加组件)
Add-ons 是扩展 Kubernetes 功能的 Pod 和 Service,通常部署在 kube-system
Namespace 下。
- DNS (如 CoreDNS): 为集群提供服务发现的 DNS 解析。允许 Pod 通过 Service 名称访问其他服务。必需组件。
- Web UI (Dashboard): 提供图形化界面来管理集群和应用。
- Container Resource Monitoring (如 Metrics Server): 采集集群范围内的容器和节点资源使用指标(CPU, 内存),供 HPA (Horizontal Pod Autoscaler) 和
kubectl top
命令使用。 - Cluster-level Logging (如 EFK/Loki Stack): 负责收集集群中所有容器的日志,并提供存储、查询和可视化能力 (Elasticsearch/Fluentd/Kibana 或 Loki/Promtail/Grafana)。
- Network Policy (如 Calico, Cilium): 提供更精细化的网络隔离策略,控制 Pod 之间的网络访问。需要对应的网络插件支持。
- Ingress Controller (如 Nginx Ingress, Traefik): 实现 Ingress 资源定义的路由规则,管理外部流量入口。
3.7 kubectl:与 Kubernetes 交互的命令行工具
- kubectl: Kubernetes 的主要命令行客户端,允许用户与 API Server 交互,管理集群资源。
- kubeconfig 文件: 存储集群连接信息(API Server 地址、用户凭证、上下文 Context)。默认路径是
~/.kube/config
。kubectl 使用此文件来确定连接哪个集群以及使用什么身份。 - 常用命令范例:
kubectl get <resource_type> [resource_name] [-n namespace] [-o wide|yaml|json]
:获取资源信息。kubectl describe <resource_type> <resource_name> [-n namespace]
:显示资源的详细信息,包括关联事件 (Events),非常适合排错。kubectl apply -f <filename.yaml> | <directory>
:声明式地创建或更新资源。推荐使用。kubectl create <resource_type> <resource_name> --image=...
:命令式地创建资源(不推荐用于生产)。kubectl edit <resource_type> <resource_name>
:直接编辑活动对象的配置。kubectl delete <resource_type> <resource_name> | -f <filename.yaml>
:删除资源。kubectl logs <pod_name> [-c container_name] [-f]
:查看 Pod 日志(-f
持续跟踪)。kubectl exec -it <pod_name> [-c container_name] -- <command>
:在 Pod 的容器内执行命令(-it
进入交互式终端)。kubectl top node|pod
:查看节点或 Pod 的资源使用情况(需 Metrics Server)。kubectl rollout status|history|undo deployment/<deployment_name>
:管理 Deployment 的发布状态。kubectl port-forward <pod_name|service/service_name> <local_port>:<remote_port>
:将本地端口转发到 Pod 或 Service 的端口。
4. 深入理解 Kubernetes 设计哲学
4.1 云计算的传统分类与 Kubernetes 的定位

- IaaS (Infrastructure as a Service): 提供基础计算资源(虚拟机、存储、网络)。用户管理操作系统及以上层。 (如 AWS EC2, OpenStack Nova)
- PaaS (Platform as a Service): 提供应用运行平台(运行时环境、数据库、消息队列)。用户只需关注应用代码和数据。 (如 Heroku, Google App Engine)
- SaaS (Software as a Service): 提供完整的软件服务。用户直接使用。 (如 Gmail, Salesforce)
Kubernetes 的定位: Kubernetes 本身介于 IaaS 和 PaaS 之间。它不直接提供虚拟机(依赖底层 IaaS 或物理机),但它提供了比传统 PaaS 更底层、更灵活的应用部署和管理平台。它管理的是容器,而不是应用代码本身。基于 Kubernetes,可以构建功能更丰富的 PaaS 平台。Kubernetes 常被认为是 CaaS (Container as a Service) 的核心,也是现代 云原生 (Cloud Native) 应用的基石。
4.2 Kubernetes 生态系统

Kubernetes 拥有一个庞大且活跃的生态系统,由 CNCF (Cloud Native Computing Foundation) 维护和推广。围绕 Kubernetes 核心,发展出众多项目,覆盖了可观测性(Prometheus, Grafana)、服务网格(Istio, Linkerd)、存储(Ceph, Rook)、Serverless(Knative)、安全、CI/CD(Argo CD, Jenkins X)等各个方面。
4.3 Kubernetes 核心设计理念
- 声明式而非命令式: 如前所述,关注最终状态,易于自动化和保证系统韧性。
- API 驱动: 所有操作都通过标准化的 REST API 进行,易于集成和扩展。API 是系统的中心。
- 可扩展性 (Extensibility):
- CRD (Custom Resource Definition): 允许用户定义自己的 API 对象类型,扩展 Kubernetes API。
- Operator Pattern: 结合 CRD 和自定义控制器,将特定应用的运维知识(如部署、备份、升级、扩缩容)编码为自动化逻辑,实现复杂有状态应用的无人值守管理。
- 标准接口 (CRI, CNI, CSI): 容器运行时接口 (CRI)、容器网络接口 (CNI)、容器存储接口 (CSI) 定义了标准规范,允许接入不同的底层实现(如多种容器运行时、网络方案、存储系统),提高了灵活性和可移植性。
- Webhook Admission Controllers: 允许在 API 请求持久化之前或之后注入自定义的校验和修改逻辑。
- 高可用性 (High Availability):
- 应用层: 通过 ReplicaSet, StatefulSet 等控制器保证应用副本数,结合 Pod 反亲和性、故障域分布(
topologySpreadConstraints
)提高应用容灾能力。 - 控制平面: API Server, Scheduler, Controller Manager 可以多副本部署实现高可用。etcd 集群本身是高可用的。
- 应用层: 通过 ReplicaSet, StatefulSet 等控制器保证应用副本数,结合 Pod 反亲和性、故障域分布(
- 可移植性 (Portability):
- 跨基础设施: 可以在公有云、私有云、混合云、边缘计算甚至本地开发环境(Minikube, Kind)运行。
- 标准接口: CRI, CNI, CSI 使得底层基础设施的选择更加灵活。
- 自动化 (Automation): 控制器模式、自动伸缩 (HPA, VPA, Cluster Autoscaler)、自动恢复等机制减少了手动运维负担。
- 松耦合 (Loosely Coupled): 各组件职责清晰,通过 API Server 进行通信,降低了系统复杂度,易于独立升级和替换。
4.4 Kubernetes 分层架构视图

- 核心层 (Core Layer): Kubernetes 最基础的部分,提供核心 API 对象(Pod, Node, Namespace 等)和核心功能(API Server, etcd, Scheduler, Controller Manager, Kubelet)。这是构建上层能力的基础。
- 应用层 (Application Layer): 关注应用的部署、运行和路由。包括 Deployment, StatefulSet, DaemonSet, Job, Service, Ingress 等对象和相关控制器。用户主要与这一层交互。
- 管理层 (Management Layer): 提供集群的管理和运维能力,如系统度量 (Metrics Server)、自动化策略 (HPA, NetworkPolicy, ResourceQuota)、审计日志等。
- 接口层 (Interface Layer): 提供与 Kubernetes 交互的接口,包括 kubectl 命令行工具、客户端库 (Client Libraries for Go, Python, Java etc.)、Web UI (Dashboard)。集群联邦 (Federation) 也属于这一层,用于管理多个 K8s 集群。
- 生态系统 (Ecosystem):
- 内部生态: 标准接口 (CRI, CNI, CSI) 和对应的实现插件(containerd, Calico, Ceph CSI Driver 等),以及 Cloud Provider 接口实现。
- 外部生态: 围绕 K8s 构建的各种工具和平台,如监控 (Prometheus)、日志 (EFK)、CI/CD (Argo CD)、服务网格 (Istio)、安全扫描等。
4.5 API 设计原则
Kubernetes 的 API 设计遵循一系列原则,确保其一致性、可组合性和可扩展性:
- 所有 API 都应是声明式的: 用户描述期望状态,系统负责实现。
- API 对象应是彼此互补且可组合的: 通过组合不同的 API 对象(如 Deployment + Service + ConfigMap + Secret)来构建复杂应用。避免设计功能重叠或过于庞大的单一对象。
- 高层 API 应以操作意图为基础设计: 例如,Deployment 代表“部署一个可伸缩的应用并管理其更新”,而不是底层的“创建/删除 Pod”。用户关心的是意图。
- 低层 API 根据高层 API 的控制需要设计: 例如,ReplicaSet 的存在是为了被 Deployment 控制,实现滚动更新等策略。
- 尽量避免简单封装,除非增加了显著价值: 新的 API 对象应该提供新的抽象或能力,而不是仅仅包装现有的对象。
- API 操作复杂度应与对象数量成正比: 避免单个 API 操作引起不可预测的大规模集群变更。
- API 对象状态不能依赖于网络连接状态: 对象应该代表持久化的期望状态或报告的实际状态,而不是临时的连接信息。
- 尽量避免让操作机制依赖于全局状态: 操作应尽可能基于对象自身的 Spec 和 Status,减少对外部或隐藏状态的依赖。
- API 应易于被客户端监听 (Watchable): 所有对象状态的变更都应能通过 Watch 机制被高效地通知给感兴趣的客户端(如控制器、kubectl),这是实现协调循环的基础。
4.6 Kubernetes 对象的组合与关系
graph TD subgraph User Intent A[Deployment] -- Defines --> D(Pod Template) A -- Manages --> C(Replica Count) A -- Defines --> B(Update Strategy) end subgraph Control Plane Logic DeploymentController -- Watches --> A DeploymentController -- Creates/Updates --> E[ReplicaSet] ReplicaSetController -- Watches --> E ReplicaSetController -- Creates/Deletes --> J[Pod] Scheduler -- Watches Unscheduled --> J Scheduler -- Assigns --> I[Node] end subgraph Runtime State E -- Owns --> J E -- Contains --> F(Version Info) E -- Manages --> G(Replica Count) E -- Uses --> H(Pod Template) J -- Runs On --> I J -- Contains --> Containers(Image, Resources) J -- Mounts --> Volumes(ConfigMap, Secret, PVC) J -- Gets IP From --> NetworkPlugin(CNI) I -- Reports --> M(Capacity, Allocatable) I -- Reports --> N(Health Status) Kubelet -- Manages --> J KubeProxy -- Watches --> K & Endpoints end subgraph Networking & Exposure K[Service] -- Selects Pods via Label --> J K -- Defines --> Q(Protocol) & R(Port) K -- Gets ClusterIP --> ClusterNetwork L[Ingress] -- Routes Traffic To --> K L -- Defines --> S(Hostname) & T(Path) IngressController -- Watches --> L IngressController -- Configures --> LoadBalancer end style A fill:#lightblue,stroke:#333,stroke-width:2px style E fill:#lightgrey,stroke:#333,stroke-width:2px style J fill:#lightgreen,stroke:#333,stroke-width:2px style K fill:#orange,stroke:#333,stroke-width:2px style L fill:#yellow,stroke:#333,stroke-width:2px style I fill:#whitesmoke,stroke:#333,stroke-width:1px
- 核心流程: 用户定义
Deployment
(意图),Deployment Controller
创建ReplicaSet
(版本控制),ReplicaSet Controller
创建Pod
(实例),Scheduler
将Pod
分配到Node
,Kubelet
在Node
上运行Pod
中的容器。 - 服务暴露:
Service
通过Label Selector
找到一组Pod
,提供稳定的访问入口。Ingress
(配合Ingress Controller
) 将外部流量路由到Service
。 - 配置与存储:
Pod
可以挂载ConfigMap
,Secret
获取配置,通过PVC
请求PV
获取持久化存储。
4.7 架构设计原则总结
- API Server 中心化: 只有 API Server 可以直接访问 etcd 存储。所有其他组件都通过 API Server 交互,这保证了数据一致性、安全性(认证、授权、准入控制)和可审计性。
- 容错性: 单个 Worker Node 或 Master Node(在 HA 配置下)的故障不应影响集群的整体可用性(正在运行的应用不受影响,新的调度和管理可能会暂停或延迟)。
- 状态内存化与 Watch 机制: 所有需要做决策的组件(Scheduler, Controller Manager, Kubelet, Kube-proxy)都在内存中维护其所需关注对象的状态,并通过 Watch 机制从 API Server 实时获取状态更新,避免了传统轮询带来的高延迟和低效率。
- 最终一致性: 系统通过持续的协调循环,不断驱动实际状态向用户声明的期望状态收敛,允许短暂的不一致。
4.8 引导(Bootstrapping)原则与 Self-Hosting
- Self-hosting (自托管) 是目标: 指将 Kubernetes 的控制平面组件(如 API Server, Scheduler, Controller Manager, CoreDNS)本身也作为 Pod 运行在集群之上(通常使用 DaemonSet 或 Static Pod)。
- 优点: 可以利用 Kubernetes 自身的管理能力(如滚动更新、资源限制、健康检查)来管理控制平面组件。简化集群升级和维护。
- 挑战: 存在“鸡生蛋,蛋生鸡”的引导问题。需要一个初始的、非自托管的控制平面(通常由 kubeadm 或其他安装工具临时启动)来部署自托管的控制平面。
- 减少依赖: 引导过程应尽可能减少对外部系统或复杂配置的依赖。
- 分层管理依赖: 通过明确的层次结构管理组件间的依赖关系。
- 处理循环依赖:
- 允许通过其他方式(如静态文件)输入初始配置。
- 组件状态应可从 API Server 或其他来源恢复或重新发现。
- 支持启动临时的、简化的实例来创建稳态运行所需的状态。
- 依赖自动重启机制(如 Kubelet 对 Static Pod 的管理,或者 systemd 对 Kubelet 的管理)来处理组件异常退出。
4.9 核心技术概念:API 对象详解
API 对象是 Kubernetes 中持久化的实体,代表了集群的状态。每个对象包含四个关键部分:
apiVersion
(TypeMeta - Group/Version): 定义了对象的 API 组和版本。例如apps/v1
,v1
(表示 core v1),batch/v1
。用于 API 的演进和版本管理。kind
(TypeMeta - Kind): 定义了对象的基本类型。例如Deployment
,Pod
,Service
,Namespace
。- GVK (GroupVersionKind): 这三者共同唯一标识一个 API 对象类型。
metadata
(ObjectMeta): 包含对象的元数据,用于唯一标识和组织对象。关键字段包括:name
: 在同一个namespace
下,同一种kind
的对象name
必须唯一。namespace
: 对象所属的命名空间。有些对象是集群级别的,没有namespace
(如 Node, PersistentVolume, Namespace 本身)。uid
: 集群范围内唯一的 ID,由系统生成。labels
: 用于对象选择和组织的键值对。可被 Selector 查询。annotations
: 用于存储任意非识别性的元数据,通常给工具或用户使用。不能被 Selector 查询。ownerReferences
: 指明一个对象(如 Pod)是由哪个其他对象(如 ReplicaSet)创建和管理的。用于实现 级联删除(删除 Owner 时自动删除其拥有的对象)。finalizers
: 字符串列表,阻止对象被强制删除,直到相关的清理逻辑完成。例如,在删除 PVC 前确保其绑定的 PV 已按策略处理。resourceVersion
: 字符串,表示对象在 etcd 中的版本号。用于乐观锁并发控制和 Watch 机制。客户端在更新对象时应提供其读取到的resourceVersion
,如果与 etcd 中当前版本不符,更新会被拒绝。creationTimestamp
,deletionTimestamp
: 对象创建和(标记)删除的时间戳。
spec
(Specification): 用户定义的期望状态。描述了用户希望对象达到的状态,例如 Deployment 的副本数、Pod 的容器镜像、Service 的端口等。这是用户主要配置的部分。status
: 系统报告的实际状态。由 Kubernetes 系统组件(主要是控制器和 Kubelet)填充和更新,描述了对象的当前实际运行状态,例如 Deployment 当前可用的副本数、Pod 的 IP 地址和运行阶段 (Phase)、Node 的健康状况等。用户通常只读status
。
4.10 常用 Kubernetes 对象回顾与补充
- Node: 代表集群中的工作机器。
status
包含节点地址、容量 (Capacity)、可分配资源 (Allocatable)、健康状况 (Conditions) 等。 - Namespace: 逻辑隔离单元。可设置
ResourceQuota
(限制 Namespace 内资源总量) 和LimitRange
(限制 Namespace 内单个对象的资源范围)。 - Pod:
- 生命周期 (Phase): Pending, Running, Succeeded, Failed, Unknown。
- 容器类型:
- App Containers: 运行核心业务逻辑。
- Init Containers: 在 App Containers 启动前按顺序执行,用于初始化环境(如下载配置、等待依赖服务)。
- Ephemeral Containers: 临时加入运行中 Pod 用于调试(
kubectl debug
)。
- 共享资源: 网络 (IP, Port), IPC, UTS, 部分 Volume。PID Namespace 可选共享。
- 探针 (Probes):
- Liveness Probe: 检测容器是否存活,失败则 Kubelet 会重启容器。
- Readiness Probe: 检测容器是否准备好接收流量,失败则 Endpoint Controller 会将该 Pod 从 Service 的 Endpoint 列表中移除。
- Startup Probe: 检测容器是否启动完成,用于启动时间较长的应用,成功前禁用 Liveness/Readiness 探针。
- 资源请求与限制 (Requests & Limits):
- Requests: Pod 调度和运行时保证的最小资源量(CPU, Memory)。调度器基于 Requests 选择节点。
- Limits: Pod 可使用的资源上限。超出 CPU Limit 会被节流,超出 Memory Limit 会被 OOMKilled。
- QoS Classes (服务质量等级): Based on Requests/Limits 设置: Guaranteed, Burstable, BestEffort。影响调度优先级和 OOM 时被杀死的顺序。
- ConfigMap & Secret: 将配置/敏感数据与 Pod 解耦。可通过环境变量或 Volume 文件注入。
- Service Account: 为 Pod 内进程提供访问 Kubernetes API 的身份标识。关联 Secret (Token) 和 RBAC Role/ClusterRole。
- Service:
- 类型 (Type):
ClusterIP
(默认): 分配集群内部虚拟 IP,只能在集群内访问。NodePort
: 在每个 Node 上暴露一个静态端口,外部可通过NodeIP:NodePort
访问。LoadBalancer
: (需要云提供商支持) 创建外部负载均衡器,将流量导向 NodePort 或直接到 Pod。ExternalName
: 将 Service 名称映射到外部 DNS 名称 (CNAME)。
Endpoints
/EndpointSlice
对象: Service Controller (或自定义控制器) 维护,包含 Service 代理的后端 Pod 的实际 IP 和端口列表。Kube-proxy 使用此信息配置转发规则。
- 类型 (Type):
- ReplicaSet: 保证 Pod 副本数。通常不直接使用,由 Deployment 管理。
- Deployment: 管理无状态应用的部署和更新。
- 更新策略 (Strategy):
RollingUpdate
(默认,滚动更新),Recreate
(先删旧再建新)。 - 滚动更新参数:
maxSurge
(允许超出的最大副本数/比例),maxUnavailable
(允许不可用的最大副本数/比例)。
- 更新策略 (Strategy):
- StatefulSet: 管理有状态应用。
- 稳定标识: Pod 名称 (
<sts-name>-<ordinal>
) 和 DNS 名称稳定。 - 有序部署/伸缩/更新: Pod 按序号 0, 1, 2… 顺序操作。
- 独立存储: 每个 Pod 通过
volumeClaimTemplates
获得独立的 PVC。
- 稳定标识: Pod 名称 (
- Job & CronJob: 管理批处理和定时任务。可设置重试次数、并行度、完成数。
- DaemonSet: 在符合条件的 Node 上运行 Pod 副本。
- PV & PVC & StorageClass:
- 访问模式 (Access Modes):
ReadWriteOnce
(RWO, 单节点读写),ReadOnlyMany
(ROX, 多节点只读),ReadWriteMany
(RWX, 多节点读写)。 - 回收策略 (Reclaim Policy):
Retain
(保留 PV),Delete
(删除 PV),Recycle
(已废弃)。 - 绑定 (Binding): PVC 与 PV 的匹配和绑定过程。
- 动态配置 (Dynamic Provisioning): 使用 StorageClass 自动创建 PV。
- 访问模式 (Access Modes):
- CustomResourceDefinition (CRD): 扩展 Kubernetes API 的核心机制。 允许用户定义新的资源类型 (Kind)。创建 CRD 后,就可以像使用内置资源 (Pod, Deployment) 一样创建、获取、更新、删除自定义资源 (Custom Resource, CR)。
- Operator: 结合 CRD 和自定义控制器,实现特定应用或服务的自动化管理。 Operator 持续监控其管理的 CR 的状态,并根据 CR 中定义的期望状态,执行复杂的操作(如数据库集群的创建、备份、故障转移、版本升级)。将领域特定的运维知识代码化。是管理有状态应用和复杂服务的最佳实践。
总结: Kubernetes 通过借鉴 Borg 的经验并进行创新,提供了一个强大的、声明式的、可扩展的容器编排平台。理解其核心对象、架构组件、设计原则以及 API 模型,是有效利用 Kubernetes 构建和管理云原生应用的关键。