第 1 章 容器与云原生基础¶
配套实验手册:本课程所有动手实验见《Kubernetes 实验手册》(manual/ 目录)。本章为基础铺垫,无强制实验;若需温故容器操作,可自行用 Docker 快速体验(见 1.2 节命令)。
学习目标¶
学完本章,你应该能够:
- 解释容器的核心技术原理(命名空间隔离、cgroups 资源限制、镜像分层)
- 说出 Docker 的镜像/容器/仓库三要素及常用操作
- 分析容器化应用在单机场景下的痛点,理解"为什么需要编排器"
- 说明云原生(Cloud Native)的定义与 CNCF 生态定位
- 对比 Kubernetes / Docker Swarm / Mesos,说出 Kubernetes 胜出的核心理由
1.1 容器技术原理¶
1.1.1 从虚拟机到容器¶
| 维度 | 虚拟机(VM) | 容器 |
|---|---|---|
| 隔离级别 | 硬件级(Hypervisor 虚拟整机) | 操作系统级(内核共享) |
| 每个实例 | 完整 Guest OS(GB 级) | 仅应用 + 依赖(MB 级) |
| 启动时间 | 分钟级 | 秒级(进程级启动) |
| 密度 | 低(每台机几十个) | 高(每台机成百上千) |
| 性能 | 有虚拟化开销 | 接近原生 |
为什么容器更快更轻:容器共享宿主机内核,不虚拟硬件和操作系统——它只是宿主上的一组受约束的进程。隔离和限制通过 Linux 内核的两个机制实现。
1.1.2 命名空间(Namespaces):隔离"看得见"¶
命名空间让容器里的进程"以为"自己独占系统资源。每个容器创建时,内核为它建立独立的命名空间视图:
| 命名空间 | 隔离内容 | 容器里看到 |
|---|---|---|
| PID | 进程编号 | 自己是 PID 1,看不到宿主机其他进程 |
| Mount | 文件系统挂载点 | 只看到自己的根文件系统 |
| Network | 网络栈(网卡/IP/路由) | 自己的 IP 和端口 |
| UTS | 主机名 | 自己的 hostname |
| IPC | 进程间通信 | 独立的信号量/消息队列 |
| User | 用户 ID | 独立的 UID 映射(容器内 root ≠ 宿主机 root) |
1.1.3 cgroups:限制"能用多少"¶
cgroups(Control Groups)限制容器能消耗多少资源:
cpu:CPU 份额与配额(如最多用 0.5 核)memory:内存上限(超限触发 OOM Killer)cpuset:绑定特定 CPU 核blkio:磁盘 IO 带宽
教学记忆:命名空间管"看不见"(隔离),cgroups 管"用多少"(限制)——两者结合,容器既安全隔离又可被资源管控。
1.1.4 镜像分层(Layer)¶
镜像不是一个大文件,而是只读层的堆叠:
┌─────────────────────┐
│ 应用层(App) │ ← 可写层(容器运行时在此写)
├─────────────────────┤
│ RUN 指令层 │
├─────────────────────┤
│ apt 安装层 │
├─────────────────────┤
│ 基础镜像层(OS) │
└─────────────────────┘
- 每层只存与上一层的差异(增量)
- 多个容器共享相同底层 → 磁盘占用小、启动快
- 容器运行时的写入发生在最上层可写层——删除容器即可写层消失(这就是"容器无状态"的底层原因,第 4 章讲持久化)
1.1.5 OCI 标准:让"容器"不绑死某一家¶
OCI(Open Container Initiative) 是容器格式与运行时的开放标准(2015 年由 Docker 等发起,现由 Linux 基金会托管),由两个规范组成:
- Image Spec(镜像规范):镜像的打包格式(分层/配置/manifest)——任何符合规范的镜像,任何符合规范的运行时都能跑
- Runtime Spec(运行时规范):容器运行时的行为(进程/命名空间/cgroups 配置、生命周期钩子)
为什么重要(本书的伏笔):
- Docker 构建的镜像(符合 OCI Image Spec)→ containerd(符合 OCI Runtime Spec)直接运行——第 3 章"K8s 用 containerd 替换 Docker"之所以无缝,正是因为大家都遵守 OCI
- 生态不绑死:镜像可以来自 Docker/Podman/Buildah,运行时可以是 containerd/CRI-O——标准是生态互通的基石
核心认知:OCI 是"容器界的 USB 接口"——第 1 章学的镜像分层、第 3 章装的 containerd,都在 OCI 的框架内工作。Docker 只是"最流行的 OCI 实现之一"。
1.2 Docker 快速回顾(镜像 / 容器 / 仓库)¶
本课程不要求精通 Docker,但 K8s 使用 OCI 兼容的容器运行时(containerd),理解 Docker 的三要素有助于后续章节。
1.2.1 三大概念¶
| 概念 | 类比 | 说明 |
|---|---|---|
| 镜像(Image) | 安装包/模板 | 只读的打包产物,包含应用 + 依赖 + 配置 |
| 容器(Container) | 运行中的进程 | 镜像的运行实例,有独立命名空间与 cgroups |
| 仓库(Registry) | 应用商店 | 存放和分发镜像(Docker Hub / 私有仓库) |
1.2.2 常用命令速查¶
docker build -t myapp:v1 . # 构建镜像
docker images # 查看本地镜像
docker pull nginx:latest # 拉取镜像
docker run -d -p 8080:80 nginx # 运行容器(后台、端口映射)
docker ps # 查看运行中容器
docker exec -it <容器> /bin/bash # 进入容器
docker logs <容器> # 查看日志
docker rm -f <容器> # 删除容器
docker rmi <镜像> # 删除镜像
与 Kubernetes 的衔接:K8s 用 containerd(兼容 OCI 镜像)替代 Docker 守护进程作为运行时,但镜像的构建、仓库、分层机制完全一致——实验 01 安装时配置的镜像加速就是针对 Docker Hub 的镜像分发。
1.3 容器化的价值与挑战¶
1.3.1 价值¶
- 可移植性:构建一次,处处运行(开发/测试/生产一致)
- 资源效率:高密度、秒级启动,弹性伸缩的基础
- 一致性:环境差异消失("在我机器上是好的"不再成立)
- 快速交付:镜像即部署产物,CI/CD 流水线化
1.3.2 单机场景的挑战(编排器的需求来源)¶
用 Docker 跑一个容器很简单,但跑一组容器做生产时:
| 挑战 | 具体问题 |
|---|---|
| 单点故障 | 容器崩了谁重启?机器挂了谁迁移? |
| 扩缩容 | 流量大了手动 docker run 复制十份?流量降了呢? |
| 服务发现 | 容器 IP 每次重启都变,前端怎么找到后端? |
| 负载均衡 | 多个副本之间流量怎么分发? |
| 健康检查 | 容器"活着"不代表"能用",谁来探测? |
| 存储 | 容器删了数据没了,数据库怎么办? |
| 配置与密钥 | 几十个容器的环境变量/密码怎么统一管理? |
结论:单机 Docker 解决"如何跑一个容器",编排器解决"如何运维一群容器"——这正是 Kubernetes 的定位(第 2 章)。
1.4 云原生与 CNCF¶
1.4.1 云原生的定义¶
CNCF(Cloud Native Computing Foundation)对云原生的定义:
云原生技术使组织能够在现代动态环境(如公有云、私有云、混合云)中构建和运行可扩展的应用程序。容器、服务网格、微服务、不可变基础设施和声明式 API 是这一方法的典型特征。
核心要素:
- 容器化:应用打包为容器(可移植、隔离)
- 微服务:单体拆分为可独立部署的服务
- 动态编排:Kubernetes 自动调度、扩缩、自愈
- DevOps:开发与运维一体化,CI/CD 自动化
- 声明式:描述"期望状态",系统自行达到(第 2 章核心概念)
1.4.2 CNCF 项目全景(与本课程相关)¶
| 层次 | 代表项目 | 本课程对应 |
|---|---|---|
| 编排 | Kubernetes | 全书 |
| 容器运行时 | containerd / CRI-O | 第 1、3 章 |
| 网络 | Calico / Cilium / Flannel | 第 9 章(实验手册(实验 07)) |
| 存储 | Rook / Longhorn | 第 10 章(实验手册(实验 08)) |
| 可观测性 | Prometheus / Grafana | 第 15 章 |
| 服务网格 | Istio / Linkerd | 进阶(本课程略) |
1.5 容器编排器对比:为什么是 Kubernetes¶
| 能力 | Docker Swarm | Apache Mesos | Kubernetes |
|---|---|---|---|
| 定位 | Docker 原生集群 | 数据中心级资源调度 | 容器编排事实标准 |
| 成熟度 | 简单但功能有限 | 复杂、运维门槛高 | 生态最完整 |
| 服务发现/负载均衡 | 内建(简单) | 需额外组件 | Service + Ingress(第 9 章) |
| 自愈/扩缩容 | 有限 | 有限 | Deployment/HPA(第 5、7 章) |
| 存储/网络插件 | 少 | 少 | 丰富的 CSI/CNI 生态 |
| 社区与生态 | 停滞 | 停滞 | CNCF 最大项目,事实标准 |
Kubernetes 胜出的核心理由:
- 声明式 API + 控制循环:用户描述"期望状态",控制器持续调和——设计优雅,可扩展
- 可扩展性:CRD、Operator、CNI/CSI 插件机制,生态爆炸式增长
- 云厂商背书:AWS/Azure/GCP/阿里云全部提供托管 K8s(EKS/AKS/GKE/ACK)
- CKA 认证体系:人才市场认可(本课程目标)
实验演练指引¶
本章为基础铺垫,无强制实验。若希望热身,可在任意 Linux 机器上:
# 体验容器三要素(需已装 Docker/containerd)
docker run -d --name demo -p 8080:80 nginx
docker exec -it demo bash # 进入容器:ps 看 PID 1、hostname 看隔离
docker rm -f demo # 删除容器:进程消失,镜像还在
目的:直观感受"容器 = 隔离的进程"(PID 1、独立 hostname),为第 2 章"Pod 是 K8s 的最小调度单元"建立直觉。不熟悉 Docker 不影响后续学习,遇到镜像操作照抄实验手册命令即可。
本章小结¶
- 容器 = 命名空间(隔离)+ cgroups(限制) 的受控进程,比虚拟机轻量得多
- 镜像 = 只读分层 + 可写层(容器运行时),共享底层省空间、启动快
- 单机 Docker 的六大痛点(故障/扩缩/发现/均衡/健康/存储)→ 编排器的需求来源
- 云原生 = 容器 + 微服务 + 动态编排 + DevOps + 声明式
- Kubernetes 凭声明式 API + 生态 + 云厂商背书成为容器编排事实标准
衔接:第 2 章将进入 Kubernetes 本身——它的架构、组件与"声明式 API + 控制循环"的核心设计。
思考题¶
- 容器与虚拟机共享内核,那容器内执行
reboot会发生什么?为什么? - 为什么说"容器没有持久化"?镜像分层中哪一层解释了这一点?
- 单机 Docker 的痛点中,你认为哪一个对生产影响最大?Kubernetes 用什么机制解决它(可以提前翻第 2/5 章找答案)?
- 云原生的"声明式"与传统"命令式"运维的区别是什么?举一个生活中的例子。
CKA 考点标注:本章为前置基础,无直接 CKA 考点;但容器原理是理解后续所有章节(尤其第 3 章运行时、第 4 章 Pod)的前提,考试中的排障题常要求理解容器生命周期。