这篇笔记的目标是把
Kubernetes放回完整的容器体系中重新理解:容器解决的是应用打包与运行一致性,Kubernetes解决的是容器进入集群之后,如何被调度、发布、暴露服务、扩缩容和恢复。
文章重点不放在零散名词记忆,而放在几个核心问题上:为什么
Kubernetes不直接管理容器而是管理Pod,Deployment和Service分别解决哪一层问题,标签与选择器怎样把这些对象关联起来,探针和资源声明为什么会直接影响发布质量,以及它和Docker、Docker Compose的边界分别是什么。
参考资料:
Kubernetes 官方文档:Kubernetes Documentation 、 Overview 、 Cluster Architecture 、 Pods 、 Deployments 、 Service 、 Ingress 、 Ingress Controllers 、 Labels and Selectors 、 Liveness, Readiness, and Startup Probes
工作负载与运行时资料:StatefulSet 、 DaemonSet 、 Jobs 、 Container Runtime Interface
Docker 官方文档:Docker Overview 、 What is a Container 、 What is an Image
站内前文:
/2025/11/27/Docker容器基础/、/2025/11/27/DockerCompose与Kubernetes关系/
[TOC]
1. 最短答案:Kubernetes 是什么
Kubernetes 可以概括为:
一个面向容器化应用的集群编排平台。它并不关心某个容器“能不能在一台机器上跑起来”,而更关心一组容器怎样在多台机器上长期稳定运行。
如果进一步拆开看,它主要负责四类事情:
- 把容器化应用调度到合适的节点
- 按声明维持副本数和健康状态
- 为动态变化的实例提供稳定访问入口
- 让发布、扩缩容、回滚和配置管理变成标准化流程
因此它和 Docker 的关系并不是谁替代谁,而是职责层次不同:
Docker更靠近镜像构建与容器运行Kubernetes更靠近集群调度与服务治理
2. 为什么有了容器,还需要容器编排
容器化只解决了第一层问题:
- 应用和依赖如何被标准化打包
- 应用怎样在不同机器上以相对一致的方式运行
但进入多实例、多节点、频繁发布的环境后,新的问题才真正开始出现:
| 生产问题 | 只靠单机容器为什么不够 | Kubernetes 的处理方式 |
|---|---|---|
| 实例挂掉怎么办 | 需要人工重启,或依赖额外脚本 | 控制器持续补齐副本 |
| 多实例如何接流量 | 实例地址变化频繁,入口不稳定 | Service 提供稳定服务入口 |
| 新版本如何上线 | 容易停机或切换粗糙 | Deployment 支持滚动更新与回滚 |
| 哪台机器有资源 | 需要人工判断或自写调度逻辑 | 调度器按资源和约束自动分配 |
| 配置和密钥如何注入 | 配置易散落在脚本和机器中 | ConfigMap、Secret 统一注入 |
| 节点故障如何处理 | 手工迁移成本高 | 平台按目标状态自动恢复 |
这也是容器平台化的关键分界线:
- 容器化解决“应用怎样被打包和运行”
- 编排层解决“应用怎样在集群里被持续管理”
3. Docker、Docker Compose、Kubernetes 分别在哪一层
把容器体系粗略拆开,可以看到 3 层不同的问题域:
1
2
3
4
应用代码与依赖
-> 镜像构建与容器运行
-> 单机多容器组织
-> 集群级调度与治理
对应关系大致如下:
| 层次 | 主要工具 | 主要解决的问题 |
|---|---|---|
| 镜像构建与容器运行 | Docker |
镜像、容器、网络、挂载、分发 |
| 单机多容器组织 | Docker Compose |
在一台机器上描述并启动一组协同容器 |
| 集群级调度与治理 | Kubernetes |
多节点调度、服务发现、扩缩容、自愈、滚动发布 |
其中最容易混淆的点有两个:
Kubernetes不是一组更高级的docker命令,它是集群平台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 不直接管理容器
Pod 是 Kubernetes 的最小部署单元,这一点必须单独理解清楚。
Pod 的本质
Pod 不是单纯给容器换了个名字,它表达的是:
一组需要共同调度、共享网络命名空间、共享部分存储上下文的容器运行单元。
一个 Pod 里可以只有一个主容器,也可以有多个紧密配合的容器,例如:
- 主业务容器
- 日志收集或代理容器
- 初始化容器
initContainers
为什么不是直接调度单个容器
如果平台只调度单个容器,会遇到两个问题:
- 某些容器天然需要作为一个整体被放到同一台机器
- 某些辅助能力并不应该和主应用拆成独立服务去部署
因此 Pod 这个抽象承担了“共同命运共同体”的职责:
- 一起被调度
- 共享
IP和端口空间 - 一起挂载卷
- 一起被销毁或重建
Pod 的关键特性
| 维度 | Pod 的表现 | 含义 |
|---|---|---|
| 网络 | 同一个 Pod 内共享一个 IP |
容器间可通过 localhost 通信 |
| 存储 | 可挂载同一组 Volume |
便于共享临时文件或配置 |
| 生命周期 | Pod 死亡后通常重建新实例 |
Pod 本身不是稳定身份 |
| 调度 | 调度器调度的是 Pod |
容器运行受 Pod 约束 |
Pod 的边界
Pod 很重要,但它并不适合直接承担完整的应用发布职责,因为:
- 单个
Pod失败后需要额外机制补齐 - 副本扩缩容不能靠手工维护多个
Pod - 版本升级和回滚不能依赖直接改单个
Pod
因此 Pod 是运行载体,而不是应用治理入口。
7. Deployment 是什么,为什么发布通常围绕它展开
Deployment 的职责
Deployment 是 Kubernetes 里管理无状态长运行应用最常见的对象。它不直接运行容器,而是通过 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: checkouttier: backendversion: v1
它的作用不是给人看说明文,而是让平台和其他对象可以按条件筛选资源。
Selector 决定“谁属于谁”
常见关联关系如下:
| 关系 | 选择器做的事 | 结果 |
|---|---|---|
Deployment -> Pod |
识别哪些 Pod 属于当前副本集 |
控制器才能补副本、缩副本、滚动升级 |
Service -> Pod |
找到可接流量的后端实例 | 调用方获得稳定入口 |
这也是为什么 Deployment、Service、Pod 看似是三种对象,实际上却能组合成一条完整链路。
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,通常是这样工作的:
Deployment声明“需要 3 个同版本Pod”- 调度器把这些
Pod放到合适节点 Service通过标签选择这些Pod- 内外部流量通过
Service或Ingress进入这组实例 - 某个
Pod挂掉后,控制器补一个新的 - 发布新版本时,
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 访问,集群外通过 Ingress 或 LoadBalancer 暴露。
这样再回头看两者关系就比较清楚:
Docker更偏构建、打包、分发Kubernetes更偏部署、治理、服务抽象
12. 为什么发布能力离不开探针和资源声明
很多时候会把滚动发布理解成“新 Pod 起起来,旧 Pod 删下去”。但在真实集群里,发布质量很大程度取决于探针和资源声明是否合理。
探针决定流量何时可以进入实例
Kubernetes 常见探针有三类:
| 探针 | 主要用途 | 典型影响 |
|---|---|---|
readinessProbe |
判断实例是否可以接收流量 | 未就绪实例不会进入 Service 后端 |
livenessProbe |
判断实例是否已经失效 | 失败后可能触发容器重启 |
startupProbe |
给慢启动应用更宽松的启动窗口 | 避免应用还没启动完就被误判失败 |
对发布来说,最关键的通常是 readinessProbe。如果就绪判断过早,流量可能在应用尚未真正可用时就进入新实例,结果表现为发布过程中出现短暂错误。
资源声明决定调度和稳定性
requests 和 limits 虽然经常被放到“资源治理”章节,但它们同样会反过来影响发布:
| 字段 | 作用 | 发布相关影响 |
|---|---|---|
requests |
告诉调度器最低需要多少资源 | 影响 Pod 能否被顺利调度到节点 |
limits |
限定容器最多可以使用多少资源 | 设置不当可能导致性能抖动甚至 OOMKilled |
如果资源申请明显偏低,实例即使“启动成功”,也可能在真实流量进入后立刻变得不稳定;如果申请过高,则可能导致滚动发布期间新副本迟迟无法调度。
发布不是单一对象的能力
因此所谓“Deployment 支持滚动更新”,背后实际上依赖多种因素共同成立:
Deployment负责控制更新节奏Pod模板决定容器如何启动- 探针决定何时接流量、何时重启
- 资源声明决定调度是否顺利、运行是否稳定
这也是为什么 Kubernetes 的发布问题往往不能只盯着 Deployment 一个对象看。
13. Kubernetes 还包含哪些关键对象和平台能力
除了 Pod、Deployment、Service 这条主链,真实生产环境通常还会依赖下面几类对象或能力:
| 能力 | 典型对象 | 解决的问题 |
|---|---|---|
| 配置管理 | ConfigMap |
让配置与镜像解耦 |
| 敏感信息管理 | Secret |
避免把密钥直接固化在镜像或脚本中 |
| 存储 | Volume、PV、PVC |
让有状态数据不依赖容器可写层 |
| 入口路由 | Ingress + Ingress Controller |
统一域名、路径、证书与七层规则 |
| 资源治理 | requests/limits |
控制资源申请和上限 |
| 弹性扩缩 | HPA |
根据指标自动调整副本数 |
| 资源隔离 | Namespace、Quota |
按团队、环境或项目隔离资源边界 |
这一层体现的是 Kubernetes 的平台属性:
- 它不只是把容器跑起来
- 它还负责把运行环境、访问路径和资源治理标准化
14. 与 Docker 的边界:Kubernetes 不等于 Docker 的升级版
二者不是同一层
| 维度 | Docker | Kubernetes |
|---|---|---|
| 主要关注点 | 镜像构建、容器运行 | 集群编排、调度、治理 |
| 典型工作范围 | 单机、开发机、CI | 测试、预发、生产集群 |
| 核心对象 | Image、Container |
Pod、Deployment、Service |
| 核心动作 | build、run、push |
apply、rollout、scale |
“Kubernetes 不用 Docker 了” 应该怎样理解
这句话容易被误读成:
Docker整体没价值了
更准确的理解是:
Kubernetes不再要求必须通过Docker Engine作为集群运行时- 现在更常见的是通过
CRI对接containerd、CRI-O - 但镜像构建、本地开发、镜像分发依然广泛使用
Docker
因此更合适的表达是:
Kubernetes不绑定Docker Engine- 不等于容器工具链里不再需要
Docker Kubernetes也不负责镜像构建和镜像仓库本身,这些仍然属于更靠近容器工具链和交付流水线的能力
15. 与 Docker Compose 的边界:单机编排不是集群编排
Docker Compose 和 Kubernetes 都会描述“一组服务如何运行”,因此常被并列讨论。
但它们的目标并不一样:
| 维度 | Docker Compose | Kubernetes |
|---|---|---|
| 编排范围 | 单机 | 多节点集群 |
| 目标 | 快速组织本地或轻量环境中的多容器应用 | 长期治理生产级容器平台 |
| 调度能力 | 没有跨节点调度 | 具备调度器和资源约束 |
| 自愈能力 | 很有限 | 控制器持续收敛状态 |
| 服务抽象 | 主要依赖容器名、端口、网络 | Service、Ingress、DNS |
| 发布策略 | 较轻量 | 原生支持滚动更新、回滚、扩缩容 |
更详细的对比已经单独放在站内这篇:
Docker Compose与Kubernetes的关系:/2025/11/27/DockerCompose与Kubernetes关系/
16. 学 Kubernetes 时,更合理的顺序
如果基础还没有完全理顺,比较稳妥的顺序通常是:
- 先理解镜像、容器、仓库、网络、挂载这些
Docker基础 - 再理解单机多容器编排和集群编排不是同一个问题
- 然后重点掌握
Pod、Deployment、Service - 再补
Label、Selector、探针、requests/limits这些把对象真正串起来的机制 - 然后区分
Deployment、StatefulSet、DaemonSet、Job分别适合什么工作负载 - 再补
ConfigMap、Secret、Ingress、存储 - 最后进入调度策略、资源治理、自动扩缩容、可观测性
站内阅读顺序也可以按这个逻辑展开:
- Docker 基础:
/2025/11/27/Docker容器基础/ - Compose 与 Kubernetes 的关系:
/2025/11/27/DockerCompose与Kubernetes关系/ - 再回来看这篇
Kubernetes容器编排总览
17. 小结
这篇笔记最核心的结论有六点:
Kubernetes解决的是容器进入集群之后的编排和治理问题Pod是最小运行单元,但不是完整的应用治理入口Deployment管理一组Pod的副本、升级和回滚Service给动态变化的Pod提供稳定访问入口,而Label/Selector是这些对象真正发生关联的机制- 探针和资源声明会直接影响调度结果、服务可用性和滚动发布质量
Docker、Docker Compose、Kubernetes分别解决容器体系里三层不同的问题
如果后续继续深入,最自然的下一步通常是:
- 进一步拆解
Pod生命周期、调度约束、控制器收敛细节和网络模型 - 进入
Ingress Controller、存储、配置管理与弹性扩缩容 - 再结合一套完整示例,把
Deployment + Service + Ingress的部署链路走通