Kubernetes 容器编排

从控制平面、核心对象到与 Docker 和 Compose 的边界,系统理解 Kubernetes 如何管理容器化应用

Posted by Ekko on November 27, 2025

这篇笔记的目标是把 Kubernetes 放回完整的容器体系中重新理解:容器解决的是应用打包与运行一致性,Kubernetes 解决的是容器进入集群之后,如何被调度、发布、暴露服务、扩缩容和恢复。

文章重点不放在零散名词记忆,而放在几个核心问题上:为什么 Kubernetes 不直接管理容器而是管理 PodDeploymentService 分别解决哪一层问题,标签与选择器怎样把这些对象关联起来,探针和资源声明为什么会直接影响发布质量,以及它和 DockerDocker Compose 的边界分别是什么。

参考资料:

Kubernetes 官方文档:Kubernetes DocumentationOverviewCluster ArchitecturePodsDeploymentsServiceIngressIngress ControllersLabels and SelectorsLiveness, Readiness, and Startup Probes

工作负载与运行时资料:StatefulSetDaemonSetJobsContainer Runtime Interface

Docker 官方文档:Docker OverviewWhat is a ContainerWhat is an Image

站内前文:/2025/11/27/Docker容器基础//2025/11/27/DockerCompose与Kubernetes关系/

[TOC]


1. 最短答案:Kubernetes 是什么

Kubernetes 可以概括为:

一个面向容器化应用的集群编排平台。它并不关心某个容器“能不能在一台机器上跑起来”,而更关心一组容器怎样在多台机器上长期稳定运行。

如果进一步拆开看,它主要负责四类事情:

  • 把容器化应用调度到合适的节点
  • 按声明维持副本数和健康状态
  • 为动态变化的实例提供稳定访问入口
  • 让发布、扩缩容、回滚和配置管理变成标准化流程

因此它和 Docker 的关系并不是谁替代谁,而是职责层次不同:

  • Docker 更靠近镜像构建与容器运行
  • Kubernetes 更靠近集群调度与服务治理

2. 为什么有了容器,还需要容器编排

容器化只解决了第一层问题:

  • 应用和依赖如何被标准化打包
  • 应用怎样在不同机器上以相对一致的方式运行

但进入多实例、多节点、频繁发布的环境后,新的问题才真正开始出现:

生产问题 只靠单机容器为什么不够 Kubernetes 的处理方式
实例挂掉怎么办 需要人工重启,或依赖额外脚本 控制器持续补齐副本
多实例如何接流量 实例地址变化频繁,入口不稳定 Service 提供稳定服务入口
新版本如何上线 容易停机或切换粗糙 Deployment 支持滚动更新与回滚
哪台机器有资源 需要人工判断或自写调度逻辑 调度器按资源和约束自动分配
配置和密钥如何注入 配置易散落在脚本和机器中 ConfigMapSecret 统一注入
节点故障如何处理 手工迁移成本高 平台按目标状态自动恢复

这也是容器平台化的关键分界线:

  • 容器化解决“应用怎样被打包和运行”
  • 编排层解决“应用怎样在集群里被持续管理”

3. Docker、Docker Compose、Kubernetes 分别在哪一层

把容器体系粗略拆开,可以看到 3 层不同的问题域:

1
2
3
4
应用代码与依赖
    -> 镜像构建与容器运行
    -> 单机多容器组织
    -> 集群级调度与治理

对应关系大致如下:

层次 主要工具 主要解决的问题
镜像构建与容器运行 Docker 镜像、容器、网络、挂载、分发
单机多容器组织 Docker Compose 在一台机器上描述并启动一组协同容器
集群级调度与治理 Kubernetes 多节点调度、服务发现、扩缩容、自愈、滚动发布

其中最容易混淆的点有两个:

  1. Kubernetes 不是一组更高级的 docker 命令,它是集群平台
  2. Kubernetes 也不是“生产版 Compose”,两者的抽象目标并不完全相同

更准确的理解方式是:

  • Docker 解决“容器怎么来”
  • Docker Compose 解决“单机上一组容器怎么一起跑”
  • Kubernetes 解决“这组容器怎样在集群里长期稳定运行”

4. Kubernetes 的核心思想:声明式和控制回路

理解 Kubernetes 时,真正需要先抓住的不是对象名,而是它的工作方式。

声明式

在传统脚本式部署里,常见思路是:

  • 执行一串命令
  • 期待命令把系统带到目标状态

而在 Kubernetes 里,更核心的做法是:

  • 声明“系统应该是什么样子”
  • 由控制器不断把当前状态拉回目标状态

例如一个无状态服务通常会声明:

  • 使用哪个镜像版本
  • 需要几个副本
  • 使用哪些配置和密钥
  • 健康检查怎么做
  • 暴露哪个端口

平台并不依赖“一次命令执行结束就算完成”,而是持续观察和纠正。

控制回路

这个过程可以概括成:

1
2
3
4
5
6
7
提交期望状态
    -> API Server 接收并校验对象
    -> etcd 持久化资源状态
    -> Controller 观察差异
    -> Scheduler 选择节点
    -> kubelet 在节点上落实容器运行
    -> 平台持续检查并纠正偏差

这也是 Kubernetes 和传统部署脚本的根本差异:

  • 脚本关注“做过什么动作”
  • Kubernetes 关注“当前状态是否符合声明”

5. Kubernetes 集群由哪些部分构成

整体结构

Kubernetes 集群通常可以拆成两部分:

  • 控制平面 Control Plane
  • 工作节点 Node
graph TB
    A[用户/CI] --> B[API Server]
    B --> C[etcd]
    B --> D[Scheduler]
    B --> E[Controller Manager]
    D --> F[Node 1]
    D --> G[Node 2]
    F --> H[kubelet]
    F --> I[Container Runtime]
    G --> J[kubelet]
    G --> K[Container Runtime]

控制平面负责什么

组件 作用 关键价值
API Server 集群统一入口 所有对象读写都经由它完成
etcd 保存集群状态 记录声明状态和当前资源数据
Scheduler 为未绑定节点的 Pod 选择节点 解决“放到哪台机器”
Controller Manager 运行各种控制器 持续把实际状态拉回目标状态

可以把控制平面理解为:

  • 接收声明
  • 保存状态
  • 判断差异
  • 发起收敛动作

工作节点负责什么

组件 作用
kubelet 接收调度结果并确保 Pod 在节点上运行
Container Runtime 实际拉镜像、启动容器、停止容器
kube-proxy 或相关网络组件 处理服务访问和转发规则

这一层更靠近真实运行现场,因此更关注:

  • 镜像拉取
  • 容器启动
  • 健康状态反馈
  • 节点上的网络和数据面能力

6. Pod 是什么,为什么 Kubernetes 不直接管理容器

PodKubernetes 的最小部署单元,这一点必须单独理解清楚。

Pod 的本质

Pod 不是单纯给容器换了个名字,它表达的是:

一组需要共同调度、共享网络命名空间、共享部分存储上下文的容器运行单元。

一个 Pod 里可以只有一个主容器,也可以有多个紧密配合的容器,例如:

  • 主业务容器
  • 日志收集或代理容器
  • 初始化容器 initContainers

为什么不是直接调度单个容器

如果平台只调度单个容器,会遇到两个问题:

  1. 某些容器天然需要作为一个整体被放到同一台机器
  2. 某些辅助能力并不应该和主应用拆成独立服务去部署

因此 Pod 这个抽象承担了“共同命运共同体”的职责:

  • 一起被调度
  • 共享 IP 和端口空间
  • 一起挂载卷
  • 一起被销毁或重建

Pod 的关键特性

维度 Pod 的表现 含义
网络 同一个 Pod 内共享一个 IP 容器间可通过 localhost 通信
存储 可挂载同一组 Volume 便于共享临时文件或配置
生命周期 Pod 死亡后通常重建新实例 Pod 本身不是稳定身份
调度 调度器调度的是 Pod 容器运行受 Pod 约束

Pod 的边界

Pod 很重要,但它并不适合直接承担完整的应用发布职责,因为:

  • 单个 Pod 失败后需要额外机制补齐
  • 副本扩缩容不能靠手工维护多个 Pod
  • 版本升级和回滚不能依赖直接改单个 Pod

因此 Pod 是运行载体,而不是应用治理入口。


7. Deployment 是什么,为什么发布通常围绕它展开

Deployment 的职责

DeploymentKubernetes 里管理无状态长运行应用最常见的对象。它不直接运行容器,而是通过 ReplicaSet 管理一组同模板的 Pod

它主要关心:

  • 需要几个副本
  • 使用什么 Pod Template
  • 版本如何滚动升级
  • 回滚时如何回到旧版本

为什么需要 Deployment

如果只保留若干个裸 Pod,会有明显问题:

  • 某个 Pod 挂掉后,谁来补
  • 想从 3 个副本扩到 6 个副本,谁来统一维护
  • 发布新镜像时,怎么保证不是一次性全部中断

Deployment 的价值就在于:

  • 把“应用应该维持怎样一组 Pod”这件事对象化
  • 把“升级”和“回滚”变成平台能力

Deployment 的工作过程

graph LR
    A[修改 Deployment] --> B[生成新 ReplicaSet]
    B --> C[逐步创建新 Pod]
    C --> D[旧 Pod 逐步缩减]
    D --> E[完成滚动发布]

滚动更新的核心不是简单地“删旧起新”,而是:

  • 先创建一部分新副本
  • 等待新副本通过健康检查
  • 再逐步缩减旧副本

因此发布能力与健康检查、资源容量、启动速度都会直接相关。

Deployment 和 Pod 的关系

可以简单概括为:

  • Pod 是运行单元
  • Deployment 是无状态应用的生命周期管理者

这也是 Kubernetes 学习里非常关键的一步:

平台最终运行的是 Pod,但日常发布和扩缩容通常操作的是 Deployment

Deployment 不是所有工作负载的统一答案

很多入门文章会把 Deployment 讲成“应用发布对象”,这在无状态 Web 服务场景里基本成立,但它并不能覆盖全部工作负载。

常见工作负载对象可以这样区分:

对象 更适合的场景 核心特征
Deployment 无状态服务、API、Web 应用 副本无固定身份,强调滚动更新和回滚
StatefulSet 数据库、消息队列、有序副本服务 副本有稳定网络标识和持久化绑定
DaemonSet 日志采集、节点监控、网络组件 期望每个节点或每类节点运行一个副本
Job / CronJob 一次性任务、定时批处理 关注任务完成,而不是长期常驻

因此围绕 Deployment 学习 Kubernetes 是合理起点,但不能把它误认为所有应用形态的唯一抽象。


8. Service 是什么,为什么 Kubernetes 里必须有它

问题背景

Pod 是会变化的:

  • Pod 重建后 IP 可能变化
  • 副本扩缩容后,实例集合也会变化
  • 节点故障后,实例可能迁移到其他节点

如果业务直接依赖 Pod IP,服务访问会非常脆弱。

Service 的职责

Service 解决的是:

给一组动态变化的 Pod 提供一个稳定的访问入口和服务发现抽象。

这意味着调用方不需要关心:

  • 当前后端一共有几个 Pod
  • 这些 Pod 分布在哪些节点
  • 某个实例是否刚刚重建

Service 的几种常见类型

类型 典型用途 访问范围
ClusterIP 集群内服务访问 仅集群内部
NodePort 暴露到节点端口 可从节点地址访问
LoadBalancer 对接云厂商负载均衡 对外提供统一入口

需要额外区分的是:

  • Service 解决的是四层或基础服务入口抽象
  • Ingress 更偏七层 HTTP/HTTPS 路由管理
  • Ingress 本身只定义路由规则,真正处理流量通常还需要 Ingress Controller

Service 和 Deployment 的关系

常见链路是:

1
2
3
Deployment 管理 Pod 副本
    -> Service 通过标签选择这一组 Pod
    -> 调用方通过 Service 访问

因此三者职责可以一句话拆开:

  • Pod 负责跑
  • Deployment 负责管
  • Service 负责连

更准确地说,Service 并不是“连到 Deployment 上”,而是通过 label selector 找到符合条件的 Pod。只是这些 Pod 往往恰好由某个 Deployment 创建和维护。


9. Label 和 Selector:这些对象是怎样关联起来的

Kubernetes 里很多对象之间并不是直接写死引用关系,而是通过标签 Label 和选择器 Selector 关联。

Label 是对象身上的元数据

Label 本质上是一组键值对,例如:

  • app: checkout
  • tier: backend
  • version: v1

它的作用不是给人看说明文,而是让平台和其他对象可以按条件筛选资源。

Selector 决定“谁属于谁”

常见关联关系如下:

关系 选择器做的事 结果
Deployment -> Pod 识别哪些 Pod 属于当前副本集 控制器才能补副本、缩副本、滚动升级
Service -> Pod 找到可接流量的后端实例 调用方获得稳定入口

这也是为什么 DeploymentServicePod 看似是三种对象,实际上却能组合成一条完整链路。

Label 设计直接影响治理效果

标签如果设计混乱,会直接带来治理问题:

  • Service 可能误选到不该接流量的 Pod
  • 新旧版本发布时,选择范围可能过宽
  • 运维和观测系统难以按应用、版本、环境聚合资源

因此在实践里,标签通常至少会覆盖:

  • 应用名
  • 组件层级
  • 版本
  • 环境或发布批次

这部分看起来像元数据细节,实际上是 Kubernetes 对象组织方式的主干。


10. Pod、Deployment、Service 三者如何配合

这是理解 Kubernetes 的主干。

graph LR
    A[Deployment] --> B[Pod 1]
    A --> C[Pod 2]
    A --> D[Pod 3]
    E[Service] --> B
    E --> C
    E --> D
    F[Ingress / Client] --> E

如果把一个无状态 Web 服务放进 Kubernetes,通常是这样工作的:

  1. Deployment 声明“需要 3 个同版本 Pod
  2. 调度器把这些 Pod 放到合适节点
  3. Service 通过标签选择这些 Pod
  4. 内外部流量通过 ServiceIngress 进入这组实例
  5. 某个 Pod 挂掉后,控制器补一个新的
  6. 发布新版本时,Deployment 逐步替换旧 Pod

因此三者虽然经常同时出现,但并不重复:

对象 核心问题 不能替代它的原因
Pod 应用实际在哪里运行 没有它就没有运行载体
Deployment 一组 Pod 怎样持续维持和升级 Pod 缺乏副本治理和发布能力
Service 调用方怎样稳定访问动态实例 Pod IP 不稳定,不适合作为服务入口

11. 一个典型的 Kubernetes 发布链路

只看对象名称容易碎片化,把完整链路串起来会更清楚:

graph LR
    A[业务代码] --> B[Docker Build]
    B --> C[镜像仓库]
    C --> D[Deployment]
    D --> E[Pod 副本]
    E --> F[Service]
    F --> G[Ingress / LoadBalancer]
    G --> H[外部流量]

这条链路体现了容器体系里的分工:

镜像构建

应用代码先通过 Dockerfile 构建为镜像。

镜像分发

镜像被推送到镜像仓库,供集群拉取。

集群部署

Kubernetes 根据 Deployment 期望状态创建 Pod,并由调度器决定落点。

服务暴露

集群内通过 Service 访问,集群外通过 IngressLoadBalancer 暴露。

这样再回头看两者关系就比较清楚:

  • Docker 更偏构建、打包、分发
  • Kubernetes 更偏部署、治理、服务抽象

12. 为什么发布能力离不开探针和资源声明

很多时候会把滚动发布理解成“新 Pod 起起来,旧 Pod 删下去”。但在真实集群里,发布质量很大程度取决于探针和资源声明是否合理。

探针决定流量何时可以进入实例

Kubernetes 常见探针有三类:

探针 主要用途 典型影响
readinessProbe 判断实例是否可以接收流量 未就绪实例不会进入 Service 后端
livenessProbe 判断实例是否已经失效 失败后可能触发容器重启
startupProbe 给慢启动应用更宽松的启动窗口 避免应用还没启动完就被误判失败

对发布来说,最关键的通常是 readinessProbe。如果就绪判断过早,流量可能在应用尚未真正可用时就进入新实例,结果表现为发布过程中出现短暂错误。

资源声明决定调度和稳定性

requestslimits 虽然经常被放到“资源治理”章节,但它们同样会反过来影响发布:

字段 作用 发布相关影响
requests 告诉调度器最低需要多少资源 影响 Pod 能否被顺利调度到节点
limits 限定容器最多可以使用多少资源 设置不当可能导致性能抖动甚至 OOMKilled

如果资源申请明显偏低,实例即使“启动成功”,也可能在真实流量进入后立刻变得不稳定;如果申请过高,则可能导致滚动发布期间新副本迟迟无法调度。

发布不是单一对象的能力

因此所谓“Deployment 支持滚动更新”,背后实际上依赖多种因素共同成立:

  • Deployment 负责控制更新节奏
  • Pod 模板决定容器如何启动
  • 探针决定何时接流量、何时重启
  • 资源声明决定调度是否顺利、运行是否稳定

这也是为什么 Kubernetes 的发布问题往往不能只盯着 Deployment 一个对象看。


13. Kubernetes 还包含哪些关键对象和平台能力

除了 PodDeploymentService 这条主链,真实生产环境通常还会依赖下面几类对象或能力:

能力 典型对象 解决的问题
配置管理 ConfigMap 让配置与镜像解耦
敏感信息管理 Secret 避免把密钥直接固化在镜像或脚本中
存储 VolumePVPVC 让有状态数据不依赖容器可写层
入口路由 Ingress + Ingress Controller 统一域名、路径、证书与七层规则
资源治理 requests/limits 控制资源申请和上限
弹性扩缩 HPA 根据指标自动调整副本数
资源隔离 NamespaceQuota 按团队、环境或项目隔离资源边界

这一层体现的是 Kubernetes 的平台属性:

  • 它不只是把容器跑起来
  • 它还负责把运行环境、访问路径和资源治理标准化

14. 与 Docker 的边界:Kubernetes 不等于 Docker 的升级版

二者不是同一层

维度 Docker Kubernetes
主要关注点 镜像构建、容器运行 集群编排、调度、治理
典型工作范围 单机、开发机、CI 测试、预发、生产集群
核心对象 ImageContainer PodDeploymentService
核心动作 buildrunpush applyrolloutscale

“Kubernetes 不用 Docker 了” 应该怎样理解

这句话容易被误读成:

  • Docker 整体没价值了

更准确的理解是:

  • Kubernetes 不再要求必须通过 Docker Engine 作为集群运行时
  • 现在更常见的是通过 CRI 对接 containerdCRI-O
  • 但镜像构建、本地开发、镜像分发依然广泛使用 Docker

因此更合适的表达是:

  • Kubernetes 不绑定 Docker Engine
  • 不等于容器工具链里不再需要 Docker
  • Kubernetes 也不负责镜像构建和镜像仓库本身,这些仍然属于更靠近容器工具链和交付流水线的能力

15. 与 Docker Compose 的边界:单机编排不是集群编排

Docker ComposeKubernetes 都会描述“一组服务如何运行”,因此常被并列讨论。

但它们的目标并不一样:

维度 Docker Compose Kubernetes
编排范围 单机 多节点集群
目标 快速组织本地或轻量环境中的多容器应用 长期治理生产级容器平台
调度能力 没有跨节点调度 具备调度器和资源约束
自愈能力 很有限 控制器持续收敛状态
服务抽象 主要依赖容器名、端口、网络 ServiceIngress、DNS
发布策略 较轻量 原生支持滚动更新、回滚、扩缩容

更详细的对比已经单独放在站内这篇:

  • Docker ComposeKubernetes 的关系:/2025/11/27/DockerCompose与Kubernetes关系/

16. 学 Kubernetes 时,更合理的顺序

如果基础还没有完全理顺,比较稳妥的顺序通常是:

  1. 先理解镜像、容器、仓库、网络、挂载这些 Docker 基础
  2. 再理解单机多容器编排和集群编排不是同一个问题
  3. 然后重点掌握 PodDeploymentService
  4. 再补 LabelSelector、探针、requests/limits 这些把对象真正串起来的机制
  5. 然后区分 DeploymentStatefulSetDaemonSetJob 分别适合什么工作负载
  6. 再补 ConfigMapSecretIngress、存储
  7. 最后进入调度策略、资源治理、自动扩缩容、可观测性

站内阅读顺序也可以按这个逻辑展开:

  • Docker 基础:/2025/11/27/Docker容器基础/
  • Compose 与 Kubernetes 的关系:/2025/11/27/DockerCompose与Kubernetes关系/
  • 再回来看这篇 Kubernetes 容器编排总览

17. 小结

这篇笔记最核心的结论有六点:

  1. Kubernetes 解决的是容器进入集群之后的编排和治理问题
  2. Pod 是最小运行单元,但不是完整的应用治理入口
  3. Deployment 管理一组 Pod 的副本、升级和回滚
  4. Service 给动态变化的 Pod 提供稳定访问入口,而 Label/Selector 是这些对象真正发生关联的机制
  5. 探针和资源声明会直接影响调度结果、服务可用性和滚动发布质量
  6. DockerDocker ComposeKubernetes 分别解决容器体系里三层不同的问题

如果后续继续深入,最自然的下一步通常是:

  • 进一步拆解 Pod 生命周期、调度约束、控制器收敛细节和网络模型
  • 进入 Ingress Controller、存储、配置管理与弹性扩缩容
  • 再结合一套完整示例,把 Deployment + Service + Ingress 的部署链路走通