0 Docker历史
0.1 虚拟化技术
概述
虚拟化技术是一种资源管理技术,是将计算机的各种[实体资源]"CPU"、"内存"、"磁盘空间"、"网络适配器"等)予以抽象、转换后呈现出来并可供分割、组合为一个或多个电脑配置环境。由此,打破实体结构间的不可切割的障碍,使用户可以比原本的配置更好的方式来应用这些电脑硬件资源。这些资源的新虚拟部分是不受现有资源的 架设方式,地域或物理配置所限制的。一般所指的虚拟化资源包括计算能力和数据存储。
为什么需要这种技术?
- 节省成本:一台物理机上可同时运行多个虚拟机或多个容器,硬件资源利用率显然能得到提高。
- 减少宕机时间,提升服务弹性:这一点也很好理解,虚拟机或者容器是可以被迁移的。
- 提高交付速度:我们能在不影响生产环境的情况下,很快复制出一套环境来进行测试验证,提高交付速度。
- 灵活性:虚拟机或者容器的资源都是可以动态调整配置的。
虚拟化技术分类
当下,虚拟化技术主要分为三类,其中前两类都属于硬件虚拟化:
- Type 1 Hypervisor
- Type 2 Hypervisor
- 容器化
Type 1 Hypervisor:VMM 直接安装在物理机上,多个虚拟机在VMM上运行。Xen 和 VMWare 的 ESXi 都属于这个类型。
而Type 2 Hypervisor,我们平常使用过的 KVM、VirtualBox 和 VMWare Workstation 都属于这个类型。和Type 1 不同的是,VMM是直接安装在操作系统上的。
第三类容器化技术和前两类不一样,它是操作系统级别的虚拟化。也就是说只需要对操作系统进行抽象,与Host主机共享内核和部分操作系统,轻量。比如,LXC(Linux Container)和 Docker。
虚拟化技术诞生的背景
Docker的诞生与云计算的兴起密不可分。2009年云计算兴起后,软件开发更趋向于组件安装,把合适的服务集合装配在一起、构建出应用、并部署到各个云平台上。就硬件问题来说,云计算平台通过抽象硬件实现了按量供给,而软件的依赖、部署、管理问题依然存在:
- 环境管理复杂:操作系统、库的安装、不同服务之间复杂的依赖关系,导致整个搭建时间很长且还容易出错。
- 更为轻量的虚拟化需求:正如前面说的,已有的虚拟化技术都太“重”了,无论从节省成本还是从启动效率的角度来说,开发者都希望出现更为轻量的虚拟技术。
- 可移植性的需求:已有的容器方案如LXC,并不是为云计算环境设计的,可移植性做得不好,且很难配置。
基于以上这类问题,开发者继续一种像集装箱一样的容器来装配、运输软件应用,实现快速部署应用。于是乎,Docker就诞生了。
0.2 硬件虚拟化技术演变历程
陷阱 & 模拟技术(Trap and Emulate)
为了区分操作系统代码和用户定义代码的执行,操作系统有两种独立的操作模式:
- 用户模式(user mode)
- 特权模式(privileged mode)
正常情况下,虚拟机的代码指令会直接放到物理CPU上执行。 但如果在用户模式下是没法执行特权指令(如I/O操作、停止CPU工作、清理内存等)的。 怎么解决用户模式下执行特权指令的情况呢? 这就是陷阱 & 模拟技术(Trap and Emulate)所要解决的问题。
当在用户模式下执行特权指令时,会触发异常,并以trap(陷阱)的形式通知VMM。 VMM收到通知后,就会emulate(模拟)这些指令的行为,但并不会实际执行。
全虚拟化
全虚拟化的代表有VMware。 具体来讲就是,对于用户代码还是会直接在CPU上执行; 而对于敏感指令,将其翻译为能在宿主机上执行的指令。
这种方案通过翻译解决了敏感指令的问题,但性能却有很大问题,因为它是完全用纯软件的形式去“模拟”出一台计算机的,翻译转换的成本十分高。
半虚拟化技术
既然翻译转换成本很高,那能不能把操作系统中所有执行敏感指令的地方都改掉呢? 来看看半虚拟化技术。 半虚拟化的代表是一个叫做 Xen 的开源项目,具体做法是将执行敏感指令的地方改成接口调用(HyperCall)。 由于不用捕获和模拟硬件,性能也能得到大幅度提升。
半虚拟化与全虚拟化不同的地方在于:
- 全虚拟化,VMM会完全“模拟”一台计算机,而半虚拟化只提供API给虚拟机调用。
- 全虚拟化使用二进制翻译技术,而半虚拟化使用接口调用(hypercall)
- 半虚拟化需要虚拟机代码更改,这样才能调用hypercall; 而全虚拟化无需虚拟机代码更改
- 半虚拟化更快
- 半虚拟化不强制依赖于VMM
上面这几种方案,无论是全虚拟化还是半虚拟化,其实都没有从根本上解决问题,要想从根本上解决问题,还是得让CPU支持虚拟化。
硬件辅助虚拟化(Hardware-assisted Virtualization)
Intel的VT系列技术和AMD的AMD-v系列技术就实现了CPU对虚拟化的支持。有了CPU对虚拟化的支持,VMM就不需要花费高昂的成本去模拟了,性能也就得到了巨大提升。 伴随硬件辅助虚拟化技术而来的是KVM和QEMU。
KVM(全称for Kernel-based Virtual Machine),意为基于内核的虚拟机。 和前面提到的VMware不同的是,KVM不是安装在操作系统上的,而是集成到 Linux 内核里的(如下图所示)。 但KVM也仅仅实现了CPU和和内存的虚拟化,外部设备的虚拟化需要引入另一项技术——QEMU。
容器虚拟化技术
上面的技术都是在模拟整台计算机,但如果仅仅想要的是一个隔离的独立环境来构建云原生应用、封装微服务等,其实是不需要耗费那么大的成本的,这也是容器化技术的出现所要解决的问题。
容器虚拟化是操作系统级别的虚拟化。容器化技术比较有代表性的就是LXC、Docker和最近出现的超轻虚拟化技术。 LXC(Linux Container)是基于Linux内核的 Cgroups 技术和 namespace 技术来实现的,而早期的 Docker 也是直接基于LXC 封装的,后期推出了lib container。 要说LXC和Docker不一样的地方,我觉得本质上两个是不同类型的容器,LXC是一个系统容器(可包含Linux发行版的操作系统 ),而 Docker 是一个应用程序容器。(区别见下图)
容器化虽然对比虚拟机来说有轻量、可移植的特点,但是安全性不如虚拟机高。 由于容器和宿主机共用同个操作系统内核,一旦利用内核漏洞发起攻击,可能会危及宿主机。那能不能结合虚拟机的强隔离性和容器技术的轻量性呢?
这就是超轻虚拟化(Lightweight Virtualization)要解决的问题。 它提出了一个microVM的概念,底层通过KVM来实现各个microVM的强隔离,而隔离的microVM中运行的是专为容器设计的微型OS。 这门技术的代表有AWS的firecracker、谷歌的gVisor和Intel主导的NEMU。
1 Docker的优缺点
Docker的优点
- Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 “这段代码在我机器上没问题啊” 这类问题;——一致的运行环境
- 可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。——更快速的启动时间
- 避免公用的服务器,资源会容易受到其他用户的影响。——隔离性
- 善于处理集中爆发的服务器使用压力;——弹性伸缩,快速扩展
- 可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。——迁移方便
- 使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。——持续交付和部署
- Docker 引擎统一了程序打包(装箱)的方式,例如 java 程序,go 程序,python 程序等等
- Docker 引擎统一了程序部署(运行)方式,例如 java 的部署运行方式为
java -jar...
,或者 python 的部署运行python manage.py runserver
,go 的部署运行go run ...
使用 Docker 容器化封装应用程序的缺点:
- Docker 是单机使用的,无法有效集群
- 随着容器数量的上升,管理的成本也越来越高
- 没有有效的容灾或者自愈机制
- 没有预设编排模板,无法实现快速,大规模容器调度
- 没有统一的配置管理中心
- 没有容器生命周期的管理工具
- 没有图形化运维工具 等等
2 Dockerfile
Dockerfile
是由一系列命令和参数构成的脚本,是用来构建 docker 镜像的文件,一个Dockerfile
里面包含了构建整个image
的完整命令。Docker通过docker build
执行Dockerfile
中的一系列命令自动构建image
。dockerfile 是面向开发的,在做项目的时候,是直接发布一个镜像,交付的是一个镜像,即DockerImages:通过 DockerFile 构建生产的镜像,最终发布和运行的产品;所以就需要编写 DockerFile 文件。
一般 docker 镜像的构建步骤:
- 1、编写一个 dockerfile 文件
- 2、docker build 构建成为一个镜像
- 3、docker run 运行镜像
- 4、docker push 发布镜像(可以发布到 DockerHub,也可以发布到阿里云上面)
Dockerfile 中常见的指令
- FROM:构建镜像基于哪个镜像
- MAINTAINER:镜像维护者姓名或邮箱地址
- RUN:构建镜像时运行的指令
- CMD:运行容器时执行的shell环境
- VOLUME:指定容器挂载点到宿主机自动生成的目录或其他容器
- USER:为RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户
- WORKDIR:为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录
- HEALTHCHECH:健康检查
- ARG:构建时指定的一些参数
- EXPOSE:声明容器的服务端口(仅仅是声明)
- ENV:设置容器环境变量
- ADD:拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压
- COPY:拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能
- ENTRYPOINT:运行容器时执行的shell命令
-
- 每一个指令都会创建提交一个新的镜像层,并提交。镜像是一层一层的。
3 Docker 如何集群部署(不使用 k8s 的话)
docker compose 是单机部署的,Docker 在进行多服务部署和管理时通常会使用Docker Stack来解决大规模部署管理问题。Docker引擎在1.12 版本集成了Docker Swarm, 内置新的容器编排工具docker stack,通过提供期望状态、滚动升级、简单易用、扩缩容、健康检查等特性简化了应用的管理。
Docker Stack 与 Docker Compose的区别
- docker stack 是swarm mode的一部分, 即使是单机使用, 也需要一个 swarm 节点
- docker stack 强化了service的概念
服务可理解为发布到生产环境时某组容器的预期状态 ,以及强化了( 复制集、 容器重启策略、回滚策略、服务更新策略 )等生产特性。总得来说,docker stack 适用于生产环境的编排工具,而 docker-compose 更适合被定义为单机容器编排的工具。
- docker stack 不支持 build 指令 ,而 docker compose 不支持 deploy 指令;
- docker stack几乎能做 docker-compose 所有的事情,后续统一还是使用 kubernetes ;
4 Kubernetes 基本介绍
kubernetes 重要的作用? kubernetes 是一个开源的容器编排框架工具,有着极其丰富的生态资源;
学习 kubernetes 的意义? 解决单机裸跑 docker 的若干痛点;
kubernetes 有什么优势?
- 可自动装箱,可水平扩展,可自我修复
- 有服务发现和负载均衡
- 可集中化配置管理和秘钥管理
- 可存储编排
- 可任务批处理运行
- 可自动发布和回滚 等等
(blog.51cto.com/hadoop2/527…) (zhuanlan.zhihu.com/p/363922044…)