图片及内容均来源于小林coding公众号:面试官:Docker 和 k8s 之间是什么关系?
物理服务器
一台看得见摸得着的机器,其实就是云厂商页面里提到的物理服务器或物理机。不同厂商叫法不同,有的厂商叫它独立服务器。
vps 和 ecs
VPS(Virtual Private Server,虚拟专用服务器)。云厂商一般会将一台物理服务器分割成多个虚拟机。它跟我们在 windows 用 VMware
, VirtualBox
建的虚拟机其实是一回事。每个虚拟机都拥有独立的操作系统、资源(比如 CPU、内存、存储空间)和公网 IP 地址。然后对外出售。
缺点:不支持用户自主升降级,它的资源是预先分配的,不易动态调整。
ECS(Elastic Compute Service,弹性计算服务)。用户可以根据需要随时调整 CPU、内存、磁盘和带宽,主打一个弹性。
Docker容器
只把软件和系统依赖库加配置打包。然后将这部分系统文件挂到 ecs 的操作系统下,利用一个叫 Namespace 的能力让它看起来就像是一个独立操作系统一样。再利用一个叫 Cgroup 的能力限制它能使用的计算资源。这就省掉了一层笨重的操作系统,同时还让软件轻松跑在各类操作系统上。这就是我们常说的 Docker 容器技术。
Namespace: 让docker容器看起来就像是一个独立操作系统一样。
Cgroup: 限制容器能使用的计算资源。
总的来说就是,物理服务器上跑 ecs,ecs 跑 Docker 容器。多个 Docker 容器共享一个 ecs 实例 操作系统内核。
Docker详解
不同软件依赖不同,在软件与操作系统中间添加一层,即Docker
程序是跑在操作系统上的,而操作系统上又装了各种不同版本的依赖库和配置,这些被程序所依赖的信息,我们统称为"环境"。
Docker 是一款可以将程序和环境打包并运行的工具软件。
基础镜像: 选中一个基础操作系统和语言后,我们将它们对应的文件系统,依赖库,配置等放一起打包成一个类似压缩包的文件,这就是所谓的基础镜像(Base Image)。
Dockerfile
我们可以将要做的事情以命令行的形式一行行列出来。就像一份 todo list。意思是要求在基础镜像的基础上按着 todo list 挨个执行命令。
像这样一份列清楚了,从操作系统到应用服务启动,需要做哪些事情的清单文件(todo list),就是所谓的 Dockerfile。
容器镜像
注意 Dockerfile 只是描述了要做哪些事情,并没有真正开始做。当我们用命令行执行 docker build 的时候,Docker 软件就会按着 Dockerfile 的说明,一行行构建环境+应用程序。最终将这个环境+程序,打包成一个类似"压缩包"的东西,我们叫它容器镜像(container image)。
Registry
弄一个镜像仓库,通过 docker push 将镜像推到仓库,有需要的时候再通过 docker pull 将镜像拉到机器上。这个负责管理镜像仓库推拉能力的服务,就叫 Docker Registry。
容器
我们可以跑到目的服务器上,执行 docker pull 拿到容器镜像。然后执行 docker run 命令,将这个类似"压缩包"的容器镜像给"解压缩",获得一个独立的环境和应用程序并运行起来。这样一个独立的环境和应用程序,就是所谓的容器(container)。我们可以在一个操作系统上同时跑多个容器。且这些容器之间都是互相独立,互相隔离的。
Docker 和虚拟机
这个容器是不是很像我们用 vmware 或 kvm 整出来的传统虚拟机?但不同的是,传统虚拟机自带一个完整操作系统,而容器本身不带完整操作系统,容器的基础镜像实际上只包含了操作系统的核心依赖库和配置文件等必要组件。它利用一个叫 Namespace 的能力让它看起来就像是一个独立操作系统一样。再利用一个叫 Cgroup 的能力限制它能使用的计算资源。
所以说,容器本质上只是个自带独立运行环境的特殊进程,底层用的其实是宿主机的操作系统内核。
Docker的架构原理
C/S架构
docker-cli解析输入的cmd命令->docker server将任务分发到Engine层-> Engine层负责创建Job-> job实际执行各种工作。
不同的 Docker 命令会执行不同类型的 Job 任务。
docker build
如果你执行的是 docker build 命令,Job 则会根据 Dockerfile 指令,像包洋葱皮似的一层层构建容器镜像文件。
docker pull/push
如果你执行的是 docker pull 或 push 之类的镜像推拉操作,Job 则会跟外部的 Docker Registry
交互,将镜像上传或下载。
docker run
如果你执行的是 docker run 命令,Job 就会基于镜像文件调用 containerd 组件,驱使 runC 组件创建和运行容器。
Docker Compose
部署多个容器,通过以后个yaml文件规定部署的容器有哪些,部署顺序是怎么样的,以及这些容器占用的 cpu 和内存等信息。
然后,通过一行Docker-compose up
命令,开始解析 YAML 文件,将容器们一键按顺序部署,就完成一整套服务的部署。这其实就是 Docker Compose 干的事情
Docker Swarm
将一套docker服务部署到多台服务器上
Docker 解决的是一个容器的部署。Docker Compose 解决的是多个容器组成的一整套服务的部署。那 Docker Swarm 就更高维度了,它解决的其实是这一整套服务在多台服务器上的集群部署问题。比如在 A 服务器坏了,就将服务在 B 服务器上重新部署一套,实现迁移,还能根据需要对服务做扩缩容。
还记得之前的文章里提到的 k8s 吗?它会在多台 Node 服务器上调度 Pod,进行部署和扩缩容。
k8s的node内部
每个 Pod 内部可以含有多个 container,每个 container 本质上就是一个服务进程。
pod内部
是不是感觉k8s跟 Docker Swarm 做的事情很像?没错,其实 Docker Swarm 是 k8s 的竞品,既然是竞品,那它们做的事情其实区别就不大了。现在回过头来看 Docker 容器和 k8s 之间的关系,思路就清晰了。Docker 部署的容器,其实就是 k8s 调度的 Pod 里的 container,它们都叫容器,其实是一回事。只不过 k8s 除了支持 Docker 的容器外,还支持别人家的容器。Docker Compose 基于多个 container 创建的一整套服务,其实就是 k8s 里的 pod。而 Docker Swarm 做的事情和 k8s 一样,本质上就是在调度 pod。回过头来看下 k8s 的官方定义,叫容器编排引擎,将它理解为,以 API 编程的方式管理安排各个容器的引擎,是不是就特别精辟。
容器编排引擎的含义
现在,我们再回过头来看下 Docker 的图标,是一个个集装箱,放在一艘船上,这一个个集装箱指的就是互相隔离的容器,而 k8s 的图标,则是一个轮船上的方向盘,意思是 k8s 控制着轮船的航向,其实指的就是调度容器。这波联想就非常形象了。
总结
-
Docker 本质上就是一个将程序和环境打包并运行的工具软件,而 Docker 容器本质上只是个自带独立运行环境的特殊进程,底层用的其实是宿主机的操作系统内核。
-
• Docker 软件 通过 Dockerfile 描述环境和应用程序的依赖关系, docker build 构建镜像, docker pull/push 跟 Docker Registry 交互实现存储和分发镜像,docker run 命令基于镜像启动容器,基于容器技术运行程序和它对应的环境,从而解决环境依赖导致的各种问题。
-
• Docker 解决的是一个容器的部署问题,Docker Compose 解决的是多个容器组成的一套服务的部署问题,Docker Swarm 解决的是多个容器组成的一套服务在多台服务器上的部署问题,k8s 则是 Docker Swarm 的竞品,在更高维度上兼容了 Docker 容器,实现了容器编排调度。