(一)容器技术发展史
接下来,我简要的叙述一下关于容器技术的发展史,具体大家有兴趣的可以再去深入了解!!
1、Jail 时代
容器不是一个新概念或者新技术,很早就有了,只是近几年遇到了云计算,整个技术
被彻底引爆了。
1️⃣ 1979 年 贝尔实验室发明 chroot
2️⃣ 2000 年 FreeBSD 4.0 发行 FreeBSD Jail
3️⃣ 2001 年 Linux VServer 发行
4️⃣ 2004 年 Solaris Containers 发行
2、云时代
2006 年,Google 101 计划提出云的概念,对当前的主流开发模式产生深远的影响。也许以后我们会更多考虑如果出现比现在多 1000 倍, 10000 倍的数据量的时候,我们该如何处理?要想让”云”发挥潜能,与此相关的编程和操作就应该与使用互联网一样简单。随后,亚马逊、IBM 等行业巨头也陆续宣布各自的“云”计划,宣告“云”技术时代的来临。
云计算需要处理海量数据、超高并发、快速扩展等问题,此时不仅仅需要隔离还需要能够对资源进行控制和调配。
1️⃣2008 年 LXC 推出
2️⃣ 2011 年 CloudFoundry 推出 Warden
3️⃣ 2013 年 LMCTFY 启动
4️⃣ 2013 年 Docker 推出到风靡全球
3、云原生时代
Google &Docker 竞争
1️⃣ 2013 年 CoreOS 发布和 Docker 由合作终止
2️⃣ 2014 年 6 月 Google 发布开源的容器编排引擎 Kubernetes ( K8S )
3️⃣ 2014 年 12 月 CoreOS 发布开源容器引擎 Rocket(rkt)
4️⃣ 2015 年 Docker 推出容器集群编排组件 Swarm
5️⃣ 2015 年 6 月 Docker 成立 OCI
6️⃣ 2015 年 7 月 Google 带头成立 CNCF
k8s 成为云原生事实标准
1️⃣ 2016 年 发布 CRI 标准
2️⃣ 2016 年 Docker 捐献 containerd
3️⃣ 2016 年 CRI-O 发布
4️⃣ 2017 年 containerd 确定作为标准 CRI
(二)编排与容器的技术演进之路
💨 核心问题:容器哪些技术过时了
1、DockerClient
此时 K8s 只是编排领域的一个选择,而 Docker 此时一家独大,所以 K8s 的客户端只
是作为 Docker 的客户端来调用 Docker 引擎来完成服务。
2、RUNC&Shim
OCI 催生 runc ,剥离 Docker Engine 的一家独大的情况,确保各个厂商都可以搭建自己的容器平台。CRI 标准确立了但是 Docker 并没有接入该标准。此时催生了临时技术shim。
3、CRI-Containerd
containerd 被捐献出来,谷歌开发 cri-containerd 接入 CRI 标准。
4、CRI-O
k8s 已经成为事实的编排标准,促使容器回归云原生本质。
5、Containerd
containerd 实现 CRI,成为 CRI 的事实标准。
那么实际生产的集群采用的什么运行时组件?
以腾讯的 TKE (腾讯商用 K8S 产品 ) 为例,支持选择 containerd 和 docker 两种模式的选择。如何选择呢?
( 1 ) Containerd 调用链更短,组件更少,更稳定,占用节点资源更少。建议选择Containerd。
( 2 )以下情况还是要用 docker:
- 使用 docker build/push/save/load 等命令。
- 调用 docker API
- 需要 docker compose 或 docker swarm。
(三)Docker 简介
1、什么是虚拟化、容器化
物理机 : 实际的服务器或者计算机。相对于虚拟机而言的对实体计算机的称呼。物理机提供给虚拟机以硬件环境,有时也称为“ 寄主 ” 或 “ 宿主 ” 。
虚拟化 :是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。
容器化 :容器化是一种虚拟化技术,又称操作系统层虚拟化( Operating system level
virtualization ),这种技术将操作系统内核虚拟化,可以允许用户空间软件实例(instances )被分割成几个独立的单元,在内核中运行,而不是只有一个单一实例运行。这个软件实例,也被称为是一个容器(containers )。对每个实例的拥有者与用户来说,他们使用的服务器程序,看起来就像是自己专用的。容器技术是虚拟化的一种。docker 是现今容器技术的事实标准。
💨 上面这样文字性的叙述或许太过抽象,接下来 举个生活中的例子:
- 物理机如下,就像一个庄园,独立占用了一块土地,花园都是自己的,其他人无法共享使用:
- 虚拟机相当于开发商的一个楼盘,一栋楼一套房子一户人家,共享一块宅基地,共享小区的花园,共享小区的游乐设施。
- 容器相当于在 1 个房子里面,开辟出来一个又一个的胶囊公寓,共享这套房子的卫生间、共享厨房、共享 WiFi,只有衣服、电脑等私人物品是你自己的。
2、为什么要虚拟化、容器化?
我们从上面的历史发展来看,虚拟化和容器化的最主要目的就是资源隔离,随着资源隔离的实现逐渐也带来了更大的收益。
- 资源利用率高
将利用率较低的服务器资源进行整合,用更少硬件资源运行更多业务,降低 IT 支出和运维管理成本。
比如上图中我们的土地直接复用, 使用这块土地的人多了,但是成本还是庄园那块地 。
- 环境标准化
一次构建,随处执行。实现执行环境的标准化发布,部署和运维。开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「 这段代码在我机器上没问题啊 」 这类问题。
- 资源弹性伸缩
根据业务情况,动态调整计算、存储、网络等硬件及软件资源。比如 遇到双 11 了,把服务扩容 100 个,双 11 过去了, 把扩容的 100 个收回去
- 差异化环境提供
同时提供多套差异化的执行环境,限制环境使用资源。
比如我的服务一个以来 Ubuntu 操作系统,一个服务依赖 CentOS 操作系统,但是没有预算购买两个物理机,这个时候容器化就能很好的提供多种不同的环境。
- 沙箱安全
比如我在容器里面执行 rm -rf /* 不会把整个服务器搞死,也不影响其他人部署的程序使用。
- 容器对比虚拟机更轻量,启动更快
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。
docker 不需要虚拟内核,所以启动可以更快,相当 于 windows 的开机时间省去 了。
- 维护和扩展容易
Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得
应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。比如 docker hub 提供了很多镜像,各个系统的一个命令就可以拿到了,研发也可以自己定制镜像分享给各个产品。
3、虚拟化实现方式
很简单的实现,其实就是应用程序执行环境分层:
硬件层:提供硬件抽象,包括指令集架构、硬件设备及硬件访问接口
操作系统层 :提供系统调用接口,管理硬件资源
程序库层:提供数据结构定义及函数调用接口
4、虚拟化常见类别
虚拟机
- 存在于硬件层和操作系统层间的虚拟化技术。虚拟机通过“伪造”一个硬件抽象接口,将一个操作系统以及操作系统层以上的层嫁接到硬件上,实现和真实物理机几乎一样的功能。比如我们在一台 Windows 系统的电脑上使用 Android 虚拟机,就能够用这台电脑打开 Android 系统上的应用。
容器
- 存在于操作系统层和函数库层之间的虚拟化技术。容器通过“伪造”操作系统的接口,将函数库层以上的功能置于操作系统上。以 Docker 为例,其就是一个基于 Linux 操作系统的Namespace 和 Cgroup 功能实现的隔离容器,可以模拟操作系统的功能。简单来说,如果虚拟机是把整个操作系统封装隔离,从而实现跨平台应用的话,那么容器则是把一个个应用单独封装隔离,从而实现跨平台应用;
- 所以容器体积比虚拟机小很 多,理论上占用资源更少。容器化就是应用程序级别的虚拟化技术。容器提供了将应用程序的代码、运行时、系统工具、系统库和配置打包到一个实例中的标准方法。容器共享一个内核(操作系统),它安装在硬件上。
JVM 之类的虚拟机
- 存在于函数库层和应用程序之间的虚拟化技术。Java 虚拟机同样具有跨平台特性,所谓跨平台特性实际上也就是虚拟化的功劳。我们知道 Java 语言是调用操作系统函数库的,JVM 就是在应用层与函数库层之间建立一个抽象层,对下通过不同的版本适应不同的操作系统函数库,对上提供统一的运行环境交给程序和开发者,使开发者能够调用不同操作系统的函数库。
5、常见虚拟化实现
5.1主机虚拟化(虚拟机)实现
主机虚拟化的原理是通过在物理服务器上安装一个虚拟化层来实现。这个虚拟化层以在物理服务器和客户操作系统之间建立虚拟机,使得它们可以独立运行。
从软件框架的角度上,根据虚拟化层是直接位于硬件之上还是在一个宿主操作系统之上,将虚拟化划分为 Type1 和 Type2.
Type1 类的 Hypervisor(Hypervisor 是一种系统软件,它充当计算机硬件和虚拟机之间的中介,负责有效地分配和利用由各个虚拟机使用的硬件资源,这些虚拟机在物理主机上单独工作,因此,Hypervisor 也称为虚拟机管理器。 ) 直接运行在硬件之上,没有宿主机操作系统,Hypervisor 直接控制硬件资源和客户机。典型框架为 Xen 、 VmwareESX。
Type2 类的 Hypervisor 运行在一个宿主机操作系统之上( Vmware Workstation )或者系统里面,Hypervisor 作为宿主机操作系统中的一个应用程序,客户机就是在宿主机操作系统上的一个进程。
5.2容器虚拟化实现
容器虚拟化实现原理:
- 容器虚拟化,有别于主机虚拟化,是操作系统层的虚拟化。通过 namespace 进行各程序的隔离,加上 cgroups 进行资源的控制,以此来进行虚拟化。
5.2.1容器虚拟化基础之 NameSpace
- 什么是 Namespace(命名空间)
namespace 是 Linux 内核用来隔离内核资源的方式。通过 namespace 可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的资源,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进的相关资源指定在同一个 namespace 中。
Linux namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前namespace 里的进程,对其他 namespace 中的进程没有影响。
Linux 提供了多个 API 用来操作 namespace ,它们是 clone() 、 setns() 和 unshare() 函数,为了确定隔离的到底是哪项 namespace ,在使用这些 API 时,通常需要指定一些调用参数:CLONE_NEWIPC 、 CLONE_NEWNET 、 CLONE_NEWNS 、CLONE_NEWPID、 CLONE_NEWUSER 、 CLONE_NEWUTS 和CLONE_NEWCGROUP。如果要同时隔离多个 namespace ,可以使用 | ( 按位或 ) 组合这些参数。
5.2.2容器虚拟化基础之 cgroups
1. 什么是 cgroups
- cgroups(Control Groups) 是 linux 内核提供的一种机制,这种机制可以根据需求把一系列系统任务及其子任务整合(或分隔)到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。简单说,cgroups 可以限制、记录任务组所使用的物理资源。本质上来说,cgroups 是内核附加在程序上的一系列钩子(hook),通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。
2. 为什么使用 cgroups
- 其可以做到对 cpu,内存等资源实现精细化的控制,目前越来越火的轻量级容器Docker 及 k8s 中的 pod 就使用了 cgroups 提供的资源限制能力来完成 cpu,内存等部分的资源控制。
3. cgroups 的用途
- Resource limitation: 限制资源使用,例:内存使用上限/cpu 的使用限制
- Prioritization: 优先级控制,例:CPU 利用/磁盘 IO 吞吐
- Accounting: 一些审计或一些统计
- Control: 挂起进程/恢复执行进程
5.2.3容器虚拟化基础之 LXC
LXC ( LinuX Containers ) Linux 容器,一种操作系统层虚拟化技术,为 Linux 内核容器功能的一个用户空间接口。它将应用软件系统打包成一个软件容器(Container ),内含应用软件本身的代码,以及所需要的操作系统核心和库。透过统一的名字空间和共享 API 来分配不同软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得 Linux 用户可以容易的创建和管理系统或应用容器。
LXC 是最早一批真正把完整的容器技术用一组简易使用的工具和模板来极大的简化了容器技术使用的一个方案
LXC 虽然极大的简化了容器技术的使用,但比起直接通过内核调用来使用容器技术,其复杂程度其实并没有多大降低,因为我们必须要学会 LXC 的一组命令工具,且由于内核的创建都是通过命令来实现的,通过批量命令实现数据迁移并不容易。其隔离性也没有虚拟机那么强大。
后来就出现了 docker ,所以从一定程度上来说, docker 就是 LXC 的增强版。
(四)Docker 是什么
1、Docker 本质
Docker 本质其实是 LXC 之类的增强版,它本身不是容器,而是容器的易用工具。容器是 linux 内核中的技术, Docker 只是把这种技术在使用上简易普及了。 Docker 在早期的版本其核心就是 LXC 的二次封装发行版。
Docker 作为容器技术的一个实现,或者说让容器技术普及开来的 最成功 的实现。Docker 是基于 Go 语言实现的一个开源项目,它的主要目标是 “Build , Ship andRun Any APP, Anywhere” ,即通过对组件的封装、分发、部署、运行等生命周期的管理,使得用户的应用及其运行环境能够做到“ 一次封装,到处运行 ” 。
2、Docker 的引擎迭代
Docker 早期是基于 LXC 容器管理引擎实现,当后来成熟之后, Docker 自建了一个容器引擎叫 libcontainer ,后来 CNCF 的介入, Docker 又研发了一个工业化标准的容器引擎 runC ,目前所使用的新版 Docker ,所使用的容器引擎就是 RunC 。
3、Docker 和虚拟机的区别
4、Docker 优势
docker 有比虚拟机更少的抽象层。 docker 不需要 Hypervisor 实现硬件资源虚拟化,运行在docker 容器上的程序直接使用的是实际物理机的硬件资源。因此在 cpu 、内存利用率上 docker 将会在效率上有明显的优势。 docker 利用的是宿主机的内核,而不需要Guest OS,节省了 Guest OS 占用的资源。
docker 不需要 Guest OS ,创建一个容器时,不需要和虚拟机一样重新加载一个操作系统内核。从而避免引寻、加载操作系统内核返回时耗时耗资源的过程,当新建一个虚拟机时,虚拟机软件需要加载 Guest OS, 返回新建过程是分钟级别的。而新建一个docker 容器只需要几秒钟。
5、Docker 和 JVM 虚拟化的区别
(五)Docker 版本
Docker 发展过程中衍生了以下版本,目前我们学习和使用提到的版本是 docker-ce 。
lxc :上文中提到, lxc 是最早的 linux 容器技术,早期版本的 docker 直接使用 lxc 来实现容器的底层功能。虽然使用者相对较少,但 lxc 项目仍在持续开发演进中。
libcontainer : docker 从 0.9 版本开始自行开发了 libcontainer 模块来作为 lxc 的替代品实现容器底层特性,并在 1.10 版本彻底去除了 lxc 。在 1.11 版本拆分出 runc 后,libcontainer 也随之成为了 runc 的核心功能模块, runc 后续变成了容器标准。
moby : moby 是 docker 公司发起的开源项目,其中最主要的部分就是同名组件 moby ,事实上这个 moby 就是 dockerd 目前使用的开源项目名称, docker 项目中的 engine(dockerd )仓库现在就是从 moby 仓库 fork 而来的,使用 containerd 作为运行时标准。https://mobyproject.org/
docker-ce : docker 的开源版本, CE 指 Community Edition 。 docker-ce 中的组件来自于 moby 、 containerd 等其他项目。 https://www.docker.com/pricing/
docker-ee : docker 的收费版本, EE 指 Enterprise Edition 。其基础组件来源和docker-ce 是一样的,但附加了一些其他的组件和功能。
最后,附上docker官网链接:https://www.docker.com/
(六)总结
以上便是本期关于docker的基本介绍了,更多知识后续我会为大家持续更新的!!