1.对容器技术的理解
(1)容器=CGroup+Namespaces+Rootfs+容器引擎
任何一组进程都是容器化的
/proc/PID/cgroup 保存了进程所在的控制组
/proc/PID/status 保存了进程的控制信息
/proc/PID/ns 保存了进程的命名空间
(2)容器运行时
实现容器生命周期管理的工具(给容器提供资源的)
-
容器运行时分为低层(Low-Level)运行时和高层(High-Level)运行时。
-
低层运行时负责调整资源限制、安全限制和命名空间,并启动一组受限的进程。典型代表是 runC。
-
高层运行时(容器引擎)建立在低层运行时之上,提供 Web API、镜像管理、容器生命周期管理等功能。典型代表包括 Containerd(以及基于 Containerd 实现的 Docker)、Podman、CRI-O。

核心流程步骤
整个流程是自上而下的,分为以下几个关键层级:
-
KUBELET (K8s 节点代理)
- 角色: 它是 Kubernetes 集群中每个节点上的主要"节点代理"。
- 动作: 当 Kubelet 接收到启动一个 Pod(K8s 的最小部署单元)的指令时,它会调用容器运行时接口。
- 图注解释: 左侧文字说明"Kubelet 请求启动一个 Pod,因此它会调用容器运行时接口"。
-
CONTAINER RUNTIME INTERFACE (CRI)
- 角色: 这是一个插件接口,旨在让 Kubelet 能够独立于具体的容器运行时实现(如 Docker, containerd, CRI-O 等)工作。
- 动作: 它作为中间层,接收 Kubelet 的请求,并将其转发给实际配置的容器运行时服务。
- 图注解释: 左侧文字提到"这个 Kubernetes 实例被配置为使用 CRI-O,所以它会调用 CRI-O 守护进程"。
-
CRI-O DAEMON (containerd-shim)
- 角色: 这是实际的容器运行时实现。CRI-O 是专门为 Kubernetes 设计的轻量级容器运行时。
- 动作:
- 它接收来自 CRI 的请求。
- 它负责管理镜像和存储。
- 图注解释:
- 左侧: CRI-O 使用
/container/image库来拉取容器镜像,使用/container/storage库来管理磁盘存储。 - 右侧: CRI-O 守护进程启动一个与开放容器倡议 兼容的运行时(即
runc)来运行容器进程。
- 左侧: CRI-O 使用
-
镜像与存储库 (Libraries)
- /container/image Library: 负责与镜像仓库交互,拉取
Container Image。 - /container/storage Library: 负责管理镜像在磁盘上的存储和解压。
- /container/image Library: 负责与镜像仓库交互,拉取
-
runc (OCI 运行时)
- 角色:
runc是一个命令行工具,用于根据 OCI 规范创建和运行容器。它是实际与操作系统内核交互的底层工具。 - 动作: CRI-O 调用
runc,runc利用 Linux 内核的特性(如 Namespace 和 Cgroups)来隔离进程,从而创建容器。 - 图注解释: 右下角文字说明"runc 使用容器镜像中包含的文件来启动容器,并通过告知 Linux 内核在合适的命名空间、控制组上下文等环境中启动相应进程"。
- 角色:
-
Container Image -> Container
- 过程: 静态的镜像文件被
runc加载,结合内核特性,转变为一个正在运行的容器。
- 过程: 静态的镜像文件被
-
LINUX KERNEL
- 角色: 最底层的操作系统核心。
- 作用: 提供 Namespace(命名空间,用于隔离)和 Cgroups(控制组,用于资源限制)等核心功能,支撑容器的运行。
(3)容器镜像
容器镜像是一个分层存储的归档文件(通常为 Tar格式),包含运行容器所需的所有静态文件和元数据。其核心设计遵循开放容器倡议(OCI)标准,主要包含以下两部分:
-
文件系统层(Rootfs):提供容器的根文件系统(rootfs),与宿主机的文件系统隔离,是容器内进程看到的文件系统视图。
-
配置元数据(JSON 文件):定义容器的运行时行为,包括进程配置、安全权限、环境变量等。关键文件(OCI 标准)有 config.json,包含容器运行时配置;manifest.json,描述镜像的层级结构和配置文件的路径;layer.tar,每个文件系统层对应的压缩包,存储实际文件内容。
配置元数据 (JSON 文件)
-
是什么 :这是一套"使用说明书",告诉容器引擎(如Docker、containerd)应该如何运行这个镜像。
-
关键文件解析:
-
config.json:核心指令集。它定义了:-
进程配置 :容器启动时默认运行什么命令(如
nginx -g "daemon off;"),以及它的参数、工作目录。 -
安全权限 :以哪个用户运行(root还是普通用户)、哪些Linux Capabilities(如
CAP_NET_ADMIN)可以被使用、是否使用seccomp或AppArmor安全策略。 -
环境变量 :设置
PATH,HOME等。
-
-
manifest.json:镜像的目录索引。它不直接配置运行时行为,而是描述了这个镜像文件的内部结构,包括:-
一共有多少个文件系统层 (
layer.tar)。 -
每个层的
tar文件叫什么名字。 -
哪个
config.json文件是配置入口。
-
-
layer.tar:实际的数据 。每个layer.tar就是一个具体的层 ,里面是真实的文件和目录。比如,基础层会包含bin/,etc/,lib/等;应用层可能只包含app.jar或index.html。
-
为什么要用容器?
| 传统部署方式 | 容器化部署方式 | |
|---|---|---|
| 难易程度 | 取决于项目 | 相对较为简单 |
| 部署速度 | 慢 | 敏捷 |
| 扩展性 | 差 | 好 |
| 系统扩展性 | 扩展性差 | 扩展性好 |
| 技术栈多样性 | 单一、封闭 | 多样、开放 |
| 运维 | 简单 | 运维复杂 |
| 架构复杂度 | 较小 | 复杂度高 |
| 查错 | 简单 | 定位问题困难 |
| 管理成本 | 开发成本 | 服务治理、运维 |