K8s 和 Docker 的关系与管理逻辑详解
一、先搞懂:Docker 和 K8s 分别是做什么的?
- Docker(容器工具):好比「集装箱工厂」,负责把应用和依赖打包成标准化容器(类似集装箱),让应用能在任何环境中运行(一次打包,到处运行)。
- K8s(Kubernetes,容器编排工具):好比「集装箱码头调度系统」,当有大量集装箱(容器)需要管理时,K8s 负责调度、分配资源、保证容器正常运行,解决单个 Docker 无法处理的「大规模集群管理」问题。
二、K8s 与 Docker 的关系:不是替代,而是「分工合作」
- Docker 是基础,K8s 是上层调度:
- Docker 解决「如何打包和运行单个容器」的问题。
- K8s 解决「如何在集群中管理成千上万个容器」的问题,比如:
- 容器挂了自动重启(自愈);
- 按流量自动增减容器数量(扩缩容);
- 把容器分配到最合适的服务器上(调度);
- 让多个容器之间能互相访问(服务发现)。
三、K8s 如何管理 Docker?核心组件与流程
K8s 不直接管理 Docker,而是通过中间层 Container Runtime Interface(CRI,容器运行时接口) 间接控制。以 Docker 为例,其管理逻辑如下:
1. K8s 的「调度 - 执行」架构
K8s 控制平面(Master) → 工作节点(Worker Node)
├─ 调度容器去哪运行 └─ Docker 负责实际运行容器
- 控制平面(Master):
- API Server:接收用户部署请求(如「运行 3 个 Web 容器」),并转化为标准格式(Pod)。
- Scheduler:根据节点资源(CPU、内存)和容器需求,决定把容器放在哪个节点上。
- Controller Manager:监控容器状态,比如发现容器挂了就通知重新部署。
- 工作节点(Worker Node):
- Kubelet:节点上的「管家」,接收控制平面的指令,通过 CRI 调用 Docker 运行容器。
- Docker Engine:实际创建和运行容器,管理容器的生命周期。
2. CRI:K8s 与 Docker 沟通的「翻译官」
- 为什么需要 CRI?:K8s 设计时希望支持多种容器运行时(如 Docker、Containerd、CRI-O),所以定义了 CRI 接口,让不同运行时按统一标准对接。
- CRI 如何对接 Docker?:
- 早期 K8s 直接调用 Docker API,但后来为了解耦,引入了 containerd-shim 作为中间层:
- Kubelet 通过 CRI 发送请求(如「运行容器」)到 containerd-shim。
- containerd-shim 调用 Docker 的底层组件(containerd)创建容器。
- Docker 负责容器的运行,containerd-shim 负责将状态返回给 Kubelet。
- 早期 K8s 直接调用 Docker API,但后来为了解耦,引入了 containerd-shim 作为中间层:
3. K8s 管理 Docker 的最小单位:Pod
- Pod 是什么?:K8s 中容器的「打包单元」,一个 Pod 可以包含 1 个或多个容器(通常是紧密协作的容器,如 Web 服务 + 日志收集器)。
- Pod 与 Docker 容器的关系:
- 每个 Pod 对应一组 Docker 容器,这些容器共享网络和存储资源(比如同一个 Pod 里的容器可以通过 localhost 互相访问)。
- K8s 部署时,先创建 Pod 对象,Kubelet 再通过 Docker 创建 Pod 里的所有容器。
四、举个生活例子:K8s 如何像「快递站」管理 Docker 容器?
- 场景:你开了一家网店,需要处理大量订单(容器)。
- Docker = 快递盒:把每个订单的商品(应用)打包成独立快递盒(容器),保证商品不受损坏(环境隔离)。
- K8s = 快递站调度系统:
- 接收订单(API Server):用户下单(部署请求),系统记录需要多少个快递盒(容器数量)。
- 分配快递员(Scheduler):根据快递员(节点)的工作量(资源),安排最合适的人去打包(运行容器)。
- 监控快递状态(Controller Manager):如果某个快递员生病(节点故障),调度系统会把订单转给其他快递员(容器迁移)。
- 快递盒打包(Docker):快递员接到任务后,用标准快递盒(Docker)打包商品,确保每个包裹一致。
五、K8s 管理 Docker 的核心功能:不止于「运行」
- 服务发现与负载均衡:
- K8s 为一组容器(如 Web 服务)创建一个「服务(Service)」,自动分配域名和 IP,让其他容器能找到它们,同时分摊流量(负载均衡)。
- 弹性伸缩:
- 当访问量增加时,K8s 自动通知 Docker 创建更多容器;访问量减少时,删除多余容器,避免资源浪费。
- 滚动更新与回滚:
- 升级应用时,K8s 会先启动新容器,再逐步替换旧容器,保证服务不中断;如果升级失败,能一键回滚到旧版本。
- 存储管理:
- K8s 可以为容器分配共享存储(如 NFS、云硬盘),即使容器在节点间迁移,数据也不会丢失。
containerd 和 dockerd 的关系:从 “母子” 到 “独立协作”
1. 技术演进:dockerd 曾是 containerd 的 “包装层”
-
containerd 的本质:它是一个底层容器运行时,负责管理容器的生命周期(创建、运行、停止)、镜像管理、存储和网络接口等核心功能,相当于容器世界的 “基建工程师”。
-
dockerd 的角色:Docker 早期版本中,
dockerd
是用户直接交互的命令行工具(比如docker run
),但它内部依赖containerd
来执行实际的容器操作。可以理解为:dockerd
是给containerd
穿了一层 “用户友好的外套”,让用户不用关心底层复杂逻辑。 -
关系类比:
containerd
像手机的操作系统内核(如 Android 内核),dockerd
像手机的操作界面(如 MIUI/EMUI),用户通过界面(dockerd)操作,但真正干活的是内核(containerd)。
2. 如今:独立组件的协作模式
-
Docker 架构升级:随着容器技术发展,Docker 将
containerd
剥离为独立项目(2017 年捐赠给 CNCF),现在dockerd
和containerd
是两个独立运行的进程,但仍需协作:dockerd
负责接收用户命令(如docker run
),并将请求转发给containerd
;containerd
负责执行容器操作,完成后将结果返回给dockerd
,再由dockerd
反馈给用户。
-
类比场景:
点外卖时,用户通过 App(dockerd)下单,App 将订单发给商家后厨(containerd),后厨做好饭菜后交给 App,再由 App 通知用户取餐。
3. 为什么 K8s 更倾向于直接使用 containerd?
- K8s 作为容器编排工具,更关注底层容器运行时的效率和稳定性,而
containerd
比dockerd
更轻量、更标准化(符合 OCI 容器标准)。因此,K8s 从 1.24 版本开始推荐直接使用containerd
作为容器运行时,跳过dockerd
这一层,就像手机用户绕过定制界面直接使用原生系统,减少性能损耗。
参考:
Docker 上 Kubernetes 的入门到进阶指南:构建和管理你的容器化应用_kubernetes docker 先装谁?-CSDN博客
深入理解K8s与Docker的关系:容器化技术的双雄-CSDN博客