Docker 与 K8s 原理大纲
这份你不要只背几个名词,而是要真正建立这条主线:
应用为什么要容器化 -> Docker 到底解决了什么 -> 为什么只有 Docker 还不够 -> K8s 为什么会出现 -> 它怎样把大量容器和服务治理起来
如果你之前对这块不熟,这份就按“从零理解到能面试”的节奏来读。
一、总纲
这部分最核心的 10 条主线:
- 为什么应用交付会越来越依赖容器化
- 镜像、容器、Dockerfile 分别是什么
- 容器和虚拟机到底差在哪
- Docker 底层为什么能做隔离和资源限制
- 为什么只有 Docker 还不够
- K8s 的核心思想为什么是期望状态和持续收敛
- Pod / Deployment / Service / Ingress 为什么要拆成不同对象
- 探针、发布、回滚、扩缩容为什么属于治理能力
- 控制面组件各自在做什么
- 这整套东西最后怎样服务你的项目和面试表达
二、先别急着背 Docker,先理解它为什么会出现
1. 传统部署最常见的问题是什么
在没有容器化之前,应用部署经常会遇到这些问题:
- 开发机能跑,测试机跑不起来
- 测试机能跑,线上依赖版本不一样
- 不同服务部署方式不统一
- 回滚很麻烦
- 环境一多,排查越来越痛苦
所以真正的问题不是“程序能不能跑”,而是:
应用如何被稳定、重复、标准化地交付。
2. Docker 解决的核心问题到底是什么
Docker 解决的不是单纯“打包方便”,而是:
- 应用和依赖一起交付
- 运行环境尽量一致
- 启动方式标准化
- 服务边界更清晰
你可以把 Docker 理解成:
把“应用怎么跑”收敛成一个标准交付单元。
3. 为什么这件事对工程特别重要
因为服务越来越多之后,你真正痛苦的往往不是:
- 代码写不出来
而是:
- 部署怎么统一
- 依赖怎么控制
- 发布怎么标准化
- 回滚怎么简单
Docker 先把这层问题解决掉。
三、Docker 到底是什么
1. 一句话理解
Docker 是一套容器化工具链,用来把应用、依赖、运行方式打包成标准化交付单元,并以容器形式运行。
2. 你面试里更稳的说法
Docker 的重点不是一个命令,而是它让应用交付从“手工配环境”变成“基于镜像的标准化运行”。
3. Docker 里最容易混的几个概念
- Image
- Container
- Dockerfile
- Registry
- Volume
- Network
这几个一定要分清。
四、镜像、容器、Dockerfile 分别是什么
1. 镜像是什么
镜像是静态模板。
你可以理解成:
- 一份打包好的应用文件快照
- 加上一套“这个应用该怎么运行”的说明
镜像本身不是真在跑的进程,它更像:
- 可复制、可分发、可复用的运行模板
2. 容器是什么
容器是镜像运行后的实例。
它更像:
- 真正在机器上跑起来的进程环境
所以镜像和容器的关系,可以这样记:
- 镜像像“类”
- 容器像“对象实例”
或者更通俗点:
- 镜像像“模具”
- 容器像“用模具生产出来、正在运行的成品”
3. Dockerfile 是什么
Dockerfile 是构建镜像的脚本。
它定义的是:
- 基础镜像是什么
- 要安装什么依赖
- 代码放到哪里
- 工作目录是什么
- 容器启动时执行什么命令
所以 Dockerfile 的本质不是语法题,而是:
定义“这个应用如何被标准化构建成镜像”。
4. Registry 是什么
Registry 是镜像仓库。
比如:
- 本地构建好镜像
- 推到仓库
- 线上再拉下来运行
所以一条完整交付链路通常是:
代码 -> Dockerfile -> 镜像 -> Registry -> 容器运行
五、镜像为什么要分层
这块是很常见的原理追问。
Docker 镜像不是一个黑盒大压缩包,它通常是分层构建的。
1. 分层有什么好处
- 构建时可以复用缓存
- 分发时可以减少重复传输
- 相同基础层能被多个镜像共享
- 镜像结构更适合工程治理
2. 为什么面试要知道这个
因为它直接影响:
- 构建速度
- 镜像大小
- CI/CD 效率
- 安全扫描成本
3. Dockerfile 层顺序为什么很重要
因为变化少的层应该尽量放前面,比如:
- 基础环境
- 系统依赖
- 包依赖
变化快的层尽量放后面,比如:
- 业务代码
这样缓存更容易命中。
4. 多阶段构建为什么常被推荐
因为构建环境和运行环境往往不是一回事。
比如:
- 构建阶段需要编译工具链
- 运行阶段只需要最终产物
多阶段构建可以把:
- 编译工具
- 临时文件
- 构建依赖
留在前一阶段,不带到最终运行镜像里。
这样做的好处是:
- 镜像更小
- 分发更快
- 启动更快
- 攻击面更小
六、容器和虚拟机到底差在哪
这题特别高频,而且很多人答得太浅。
1. 虚拟机是什么思路
虚拟机更偏硬件虚拟化。
一般会有:
- 虚拟硬件
- 独立操作系统
- 更完整的隔离边界
所以它更像:
- 每个应用都带一台自己的“小电脑”
2. 容器是什么思路
容器更偏操作系统层隔离。
多个容器通常:
- 共享宿主机内核
- 各自有隔离的进程视图、网络视图、挂载视图
所以它更像:
- 很多应用住在同一台楼里,但每个应用有自己的独立房间
3. 为什么容器通常更轻
因为容器不需要每个实例都带完整 OS。
所以通常会表现为:
- 启动更快
- 资源开销更小
- 交付更轻
4. 为什么容器不等于绝对安全隔离
这点说出来会比较加分。
因为容器本质上共享宿主机内核,它不是完整虚拟机级别的完全隔离。
所以容器更适合:
- 标准化交付
- 轻量部署
- 资源利用率优化
但不要把它理解成:
- 天然绝对安全沙箱
七、Docker 底层为什么能做容器
你不一定要背源码,但至少要知道这几个关键词:
namespacecgroupunion filesystem
1. namespace 在干什么
namespace 主要解决的是:
- 看起来彼此隔离
它可以隔离很多视图,比如:
- 进程
- 网络
- 挂载点
- 主机名
这也是为什么容器里的进程会感觉自己像独立运行环境。
2. cgroup 在干什么
cgroup 主要解决的是:
- 资源限制和资源统计
比如:
- CPU
- 内存
- IO
所以它回答的是:
- 这个容器最多能用多少资源
- 这个容器现在用了多少资源
3. union filesystem 在干什么
它主要服务镜像分层和文件系统叠加。
简单理解就是:
- 基础层在下面
- 业务层叠在上面
- 容器运行时还有自己的可写层
这也是为什么镜像可以层层复用。
4. 一句话怎么讲 Docker 底层
容器不是魔法,本质上是 Linux 提供的隔离、资源控制和分层文件系统能力,再加上一套镜像和运行时标准。
八、除了镜像和容器,为什么还要关心 Volume 和 Network
1. Volume 在解决什么
容器本身更像临时运行实例。
如果把重要数据只写在容器内部,可重建时很容易丢。
所以像下面这些内容通常要认真设计持久化:
- 数据库数据
- 上传文件
- 部分日志
- 缓存落盘目录
所以 Volume 的本质是在回答:
- 容器删了,哪些数据还要保留
2. Network 在解决什么
容器不是只会单独运行,它们往往还要互相通信。
Docker Network 主要解决:
- 容器间通信
- 服务名解析
- 网络隔离
比如:
- PHP 调 MySQL
- 应用调 Redis
- 服务调消息队列
这些通信关系通过容器网络被标准化。
九、为什么只有 Docker 还不够
这一步非常关键。
Docker 解决的是:
- 一个容器怎么打包
- 一个容器怎么运行
但当你的服务越来越多,就会出现新的问题:
- 多副本怎么管理
- 机器挂了怎么自动恢复
- 服务之间怎么发现彼此
- 发布怎么滚动进行
- 出问题怎么快速回滚
- 怎么做自动扩缩容
- 集群资源怎么调度
这时候问题已经不再是“容器能不能跑”,而是:
很多容器、很多服务、很多实例,怎么稳定治理。
这就是 K8s 出现的原因。
十、K8s 到底是什么
1. 一句话理解
Kubernetes 是容器编排和治理平台。
2. 更稳的说法
Docker 解决单个容器交付,K8s 解决大量容器实例在集群里的调度、发布、服务发现、故障恢复和扩缩容。
3. 为什么它不是“更高级的 Docker”
这个区分很重要。
Docker 更偏:
- 镜像构建
- 容器运行
- 单机交付
K8s 更偏:
- 集群管理
- 多实例治理
- 声明式运维
- 持续收敛
所以它们解决的问题层次不同。
十一、K8s 的核心思想为什么是“期望状态”
这句话一定要真正听懂:
你告诉它想要什么状态,它持续把实际状态往期望状态拉齐。
1. 这是什么意思
比如你声明:
- 我要 3 个副本
- 镜像版本是 v2
- 对外暴露成一个 Service
- 健康探针通过后才能接流量
K8s 不会只是执行一次命令然后结束,而是会持续盯着:
- 是不是真的有 3 个副本
- 版本是不是 v2
- 挂掉的实例有没有被补起来
- 流量是不是只打到健康实例
2. 为什么这很重要
因为集群环境天然不稳定:
- 节点会挂
- Pod 会崩
- 发布会失败
- 资源会紧张
如果没有“持续收敛”,系统很快就会偏离你原本想要的状态。
3. 这就是 K8s 和“只会起容器”的根本区别
它不是一次性执行工具,而是持续治理系统。
十二、K8s 核心对象到底为什么这样拆
这块别只背名词,要理解职责边界。
1. Pod
Pod 是 K8s 的最小调度单元。
它不是简单等于一个容器,而是:
- 一组协同运行的容器单元
它们通常会:
- 共享网络
- 共享部分存储
- 生命周期绑定
2. 为什么 Pod 不直接等于容器
因为现实里很多时候,一个业务单元不一定只有一个容器。
比如:
- 主业务容器
- sidecar 代理
- 日志采集容器
这些放在同一个 Pod 里更合理。
所以 K8s 管的是:
- 协同运行单元
而不是单纯的容器进程列表。
3. Deployment
Deployment 管的是:
- 我要多少副本
- 用哪个版本
- 怎么滚动更新
- 出问题怎么回滚
它关心的不是“某一个 Pod”,而是:
- 这组无状态服务的期望运行形态
4. Service
Service 主要解决:
- 服务发现
- 稳定访问入口
- 集群内部负载均衡
因为 Pod 自己的 IP 并不稳定。
所以 Service 的意义就是:
- 给一组动态变化的 Pod 一个相对稳定的访问方式
5. Ingress
Ingress 更偏集群外部入口。
主要解决:
- 域名入口
- URL 路由
- TLS
- 外部统一流量入口
你可以把它理解成:
- Service 是内部稳定门牌号
- Ingress 是外部入口总闸
6. ConfigMap / Secret
它们解决的是:
- 配置和镜像解耦
也就是说:
- 镜像只负责应用本体
- 配置在运行时注入
这样才能做到:
- 同一镜像多环境复用
- 改配置不一定重打镜像
- 敏感信息和普通配置分开治理
7. Namespace
Namespace 主要做逻辑隔离。
它常用来区分:
- 团队
- 环境
- 业务域
所以 Namespace 更像:
- 集群里的逻辑分区
十三、为什么 Deployment、探针、发布、回滚这么重要
线上不是“跑起来就结束”,而是:
- 怎么平滑更新
- 怎么避免中断
- 出问题怎么退回
- 怎么判断实例能不能接流量
1. readinessProbe 在解决什么
readiness 负责回答:
- 这个实例现在能不能安全接流量
如果没准备好,就不应该把请求打过去。
2. livenessProbe 在解决什么
liveness 负责回答:
- 这个实例是不是已经坏掉,需要被拉起
3. 为什么这两个不能混
因为:
- readiness 关注的是“能不能接流量”
- liveness 关注的是“要不要重启”
如果混用,很容易出现:
- 服务还没准备好就接请求
- 服务假死却没人拉起
- 发布时流量被打到不稳定实例
4. Deployment 为什么是治理核心之一
它能把:
- 副本数
- 新旧版本替换
- 滚动发布
- 回滚
统一起来。
所以它的价值不在于“多一个 YAML 对象”,而在于:
把发布从手工动作变成持续可控的治理动作。
十四、资源请求、限制和调度到底在解决什么
1. requests 是什么
你可以把 requests 理解成:
- 调度时至少需要多少资源
调度器会看:
- 哪个节点有足够资源容纳它
2. limits 是什么
limits 更像:
- 运行时最多允许吃到多少资源
3. 为什么这不是“随便填两个数字”
因为这会直接影响:
- 调度结果
- 节点资源利用率
- 服务稳定性
如果 requests 配太大:
- 调度会更困难
- 资源利用率可能变差
如果 limits 太松:
- 服务可能把机器吃爆
如果 requests 太小:
- 真实流量一上来就不稳
4. Scheduler 为什么重要
调度器的核心问题其实是:
- 这堆 Pod 到底放到哪台机器更合适
它要考虑的不是一个单点配置,而是:
- 资源是否足够
- 节点约束
- 污点容忍
- 亲和 / 反亲和
- 负载分布
所以 K8s 的调度本质上也是治理能力的一部分。
十五、扩缩容为什么不只是“副本数加一减一”
1. 手动扩缩容
更适合:
- 明确可控场景
- 运维人工介入
2. 自动扩缩容
比如 HPA,适合:
- 负载波动明显
- 指标可观测
- 服务相对无状态
3. 为什么自动扩缩容不是万能药
因为扩出来的不只是副本数,而是一整条链路压力。
还要考虑:
- 下游数据库扛不扛得住
- Redis、MQ、第三方接口会不会成为瓶颈
- 限流和熔断是否到位
所以扩缩容不是“魔法按钮”,而是:
- 在指标、资源和系统瓶颈之间做平衡
十六、K8s 控制面组件怎么理解
你不一定要背源码,但至少要知道这些名字是干什么的。
1. apiserver
它是集群控制入口。
你可以把它理解成:
- 所有声明、查询、变更请求的总入口
2. etcd
它负责保存集群状态数据。
简单理解就是:
- 集群的状态数据库
3. scheduler
它负责决定:
- 新 Pod 应该调度到哪个节点
4. controller-manager
它负责:
- 持续让实际状态逼近期望状态
所以它和“持续收敛”这件事高度相关。
5. kubelet
它是节点上的执行代理。
它负责:
- 接收控制面下发的任务
- 在节点上把 Pod 真正跑起来
- 汇报运行状态
6. kube-proxy
它主要和 Service 的网络转发相关。
简单理解就是:
- 帮 Service 把流量导到后端 Pod
7. 一句话串起来
可以这样记:
- apiserver:入口
- etcd:状态存储
- scheduler:决定放哪
- controller-manager:持续收敛
- kubelet:节点执行
- kube-proxy:服务网络转发
十七、从代码到线上 Pod 的完整链路
这块很适合你面试时讲成一条线。
一条典型链路
- 开发写代码
- 用 Dockerfile 构建镜像
- 镜像推到 Registry
- 发布系统更新 Deployment 的镜像版本
- apiserver 接收这次变更
- controller-manager 发现期望状态变了
- scheduler 给新的 Pod 选择节点
- 节点上的 kubelet 拉镜像并启动容器
- readinessProbe 通过后,Pod 才开始接流量
- Service / Ingress 把流量转发过来
- 如果新版本异常,Deployment 可以暂停、回滚
如果你能把这条链讲顺,Docker 和 K8s 这块就已经不像“只会背名词”了。
十八、常见误区
1. “有 Docker 就等于有 K8s”
不对。
Docker 解决交付,K8s 解决集群治理。
2. “K8s 就是起容器的平台”
太浅了。
它更核心的是:
- 声明式管理
- 发布治理
- 服务发现
- 故障恢复
- 扩缩容
3. “Pod 就等于容器”
不对。
Pod 是调度单元,容器是运行组件。
4. “探针就是随便配个接口”
不对。
探针直接影响:
- 流量是否打进来
- 故障实例是否被拉起
- 发布过程是否稳定
5. “扩容一定能解决性能问题”
不对。
如果瓶颈在:
- 数据库
- 第三方接口
- 锁竞争
- 单线程热点
那单纯扩 Pod 不一定有用。
十九、如果你不是平台 owner,面试里怎么讲最稳
很多人会担心:
- 我不是专门做 K8s 平台的
- 这块会不会讲不深
其实你不需要装成平台专家。
更稳的说法是:
我不是 K8s 平台侧最深的 owner,但我知道 Docker 解决的是应用交付标准化,K8s 解决的是多服务、多副本、多环境下的部署治理。我能讲清镜像、容器、Pod、Deployment、Service、Ingress、探针、扩缩容这些对象分别在解决什么问题,也理解它们最终是为稳定发布、资源利用率和服务治理服务的。
这样既真实,又够面试。
二十、30 秒版怎么答
Docker 解决的是应用和依赖的标准化交付,把代码、环境和启动方式打包成镜像,再以容器运行;K8s 解决的是大量容器在集群里的调度、服务发现、滚动发布、故障恢复和扩缩容。我的理解重点不是背平台名词,而是知道它们分别在解决交付问题和治理问题。
二十一、1 分钟版怎么答
我会把 Docker 和 K8s 分成两层看。Docker 主要解决的是应用交付标准化,比如镜像、容器、Dockerfile、分层构建、环境一致性;它底层依赖 namespace、cgroup 和分层文件系统来实现隔离和资源控制。K8s 则是在 Docker 之上进一步解决多服务、多实例、多环境的治理问题,比如 Pod、Deployment、Service、Ingress、ConfigMap、Secret、探针、扩缩容和回滚。它最核心的思想是期望状态和持续收敛,也就是你声明想要什么状态,系统持续把实际状态往目标状态拉齐。
二十二、3 分钟版怎么答
我理解 Docker 和 K8s 其实是两层不同的问题。Docker 解决的是单个应用怎么被标准化交付,它把应用、依赖、启动方式打包成镜像,再以容器运行。镜像是静态模板,容器是运行实例,Dockerfile 定义构建过程,底层依赖 namespace 做隔离、cgroup 做资源控制、union filesystem 做镜像分层。这样可以让开发、测试、预发、线上环境尽量一致,也让服务发布和回滚更标准。
但只有 Docker 还不够,因为当服务数量和实例数量变多之后,你会遇到调度、服务发现、滚动发布、故障恢复、配置管理、扩缩容这些问题,这就是 K8s 出现的原因。K8s 的核心思想不是“帮你起容器”,而是声明式管理和持续收敛。比如你声明要 3 个副本、某个镜像版本、某个 Service 暴露方式,K8s 会持续维持这个目标状态。
它为什么拆成 Pod、Deployment、Service、Ingress、ConfigMap、Secret 这些对象,也是因为每个对象在解决不同职责:Pod 是最小调度单元,Deployment 管副本和发布回滚,Service 负责内部服务发现,Ingress 负责外部流量入口,ConfigMap 和 Secret 负责配置解耦。再往下还有 readiness/liveness 探针、requests/limits、HPA、scheduler、controller-manager 这些治理能力。
如果把这套东西挂回项目,我会重点讲它们带来的价值不是“平台名词很多”,而是部署更标准、发布更平滑、回滚更可控、资源治理更清晰。即使我不是平台侧最深的 owner,我也能把这些对象在解决什么问题讲清楚。
二十三、继续深挖建议
如果你想把这块再讲得更像做过的人,可以继续看:
那篇会更偏:
- 从零理解
- 从代码到 Pod 的完整链路
- 常见误区
- 面试怎么讲得更自然