一, 虚拟化概述及简介
通俗的说, 虚拟化就是把物理资源转变为逻辑上可以管理的资源, 以打破物理结构间的壁垒, 计算元件运行在虚拟的基础上而不是真实的基础上, 可以扩大硬件的容量, 简化软件的重新配置过程.
允许一个平台同时运行多个操作系统, 并且应用程序都可以在相互独立的空间内运行而互不影响, 从而显著提高计算机的工作效率, 是一个为了简化管理, 优化资源的解决方案.
目前主流的虚拟化技术主要有: KVM,Xen,VMware,VirtualBox,Docker, 虚拟化技术也越来越广泛的应用在企业中, 例如 Taobao,Google 等.
虚拟化原理: 虚拟化解决方案的底部是要进行虚拟化的物理机器. 这台机器可能直接支持虚拟化, 也可能不会直接支持虚拟化; 那么就需要系统管理程序层的支持. 系统管理程序(Virtual machine monitor), 或称为 VMM, 可以看作是平台硬件和操作系统的抽象化. 在某些情况中, 这个系统管理程序就是一个操作系统; 此时, 它就称为主机操作系统.
图 1. 虚拟化的分层抽象
完全拟化技术实际上是通过软件实现对操作系统的资源再分配, 比较成熟, 例如我们的 KVM,VirtualBox;
而半虚拟化技术则是通过代码修改已有的系统, 形成一种新的可虚拟化的系统, 调用硬件资源去安装多个系统, 整体速度上相对高一点, 代表产品有 Xen.
二, Docker 入门简介
Docker 是一个开源的应用容器引擎, 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中, 然后发布到任何流行的 Linux 机器上, 也可以实现虚拟化.
容器是完全使用沙箱机制, 相互之间不会有任何接口(类似 iPhone 的 App). 几乎没有性能开销, 可以很容易地在机器和数据中心中运行. 最重要的是, 他们不依赖于任何语言, 框架或包括系统.
"Docker" 应该是 2014 年最火爆的技术之一, 如果没有听说过, 那么你就 out 了, 2015 年将开启新的跨越.
Docker 自开源后受到广泛的关注和讨论, 以至于 dotCloud 公司后来都改名为 Docker Inc.RedHat 已经在其 RHEL6.5 中集中支持 Docker;Google 也在其 PaaS 产品中广泛应用.
Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案. Docker 的基础是 Linux 容器 (LXC) 等技术.
在 LXC 的基础上 Docker 进行了进一步的封装, 让用户不需要去关心容器的管理, 使得操作更为简便. 用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单.
下面对比了 Docker 和传统虚拟化 (KVM,XEN 等) 方式的不同之处, Docker 容器是在操作系统层面上实现虚拟化, 直接复用本地主机的操作系统, 而传统方式则是在硬件的基础上, 虚拟出自己的系统, 再在系统上部署相关的 App 应用.
虚拟化要运行一下 Nginx 软件
下图为传统虚拟化方案:
如下为 Docker 虚拟化方案:
三, Docker 虚拟化有三个概念需要理解, 分别镜像, 容器, 仓库.
镜像: docker 的镜像其实就是模板, 跟我们常见的 ISO 镜像类似, 是一个样板.
容器: 使用镜像常见的应用或者系统, 我们称之为一个容器.
仓库: 仓库是存放镜像的地方, 分为公开仓库 (Public) 和私有仓库 (Private) 两种形式.
Docker LXC 及 Cgroup
Docker 最早为 LXC+AUFS 组合, Docker0.9.0 版本开始引入 libcontainer, 可以视作 LXC 的替代品). 其中 LXC 负责资源管理, AUFS 负责镜像管理; 而 LXC 包括 cgroup,namespace,chroot 等组件, 并通过 cgroup 进行资源管理.
从资源管理来看, Docker,LXC,Cgroup 三者的关系是: Cgroup 在最底层落实资源管理, LXC 在 cgroup 上封装了一层, Docker 又在 LXC 封装了一层, 要想学好 Docker, 需要了解负责资源管理的 CGroup 和 LXC.
Cgroups 是 control groups 的缩写, 是 Linux 内核提供的一种可以限制, 记录, 隔离进程组 (process groups) 所使用的物理资源 (如: CPU, Memory, IO 等) 的机制.
最初由 Google 的工程师提出, 后来被整合进 Linux 内核. Cgroups 也是 LXC 为实现虚拟化所使用的资源管理手段, 可以说没有 Cgroups 就没有 LXC, 也就没有 Docker.
Cgroups 最初的目标是为资源管理提供的一个统一的框架, 既整合现有的 Cpuset 等子系统, 也为未来开发新的子系统提供接口. 现在的 Cgroups 适用于多种应用场景, 从单个进程的资源控制, 到实现操作系统层次的虚拟化(OS Level Virtualization).
LinuxContainer 容器可以提供轻量级的虚拟化, 以便隔离进程和资源, 而且不需要提供指令解释机制以及全虚拟化的其他复杂性. 容器有效地将由单个操作系统管理的资源划分到孤立的组中, 以更好地在孤立的组之间平衡有冲突的资源使用需求.
LXC 建立在 CGroup 基础上, 我们可以粗略的认为 LXC = Cgroup+ namespace + Chroot + veth + 用户态控制脚本. LXC 利用内核的新特性 (CGroup) 来提供用户空间的对象, 用来保证资源的隔离和对于应用或者系统的资源控制.
典型的 Linux 文件系统由 bootfs 和 rootfs 两部分组成, bootfs(boot file system)主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel, 当 kernel 被加载到内存中后 bootfs 就被 umount.rootfs (root file system) 包含的就是典型 Linux 系统中的 / dev,/proc,/bin,/etc 等标准目录和文件.
Docker 容器的文件系统最早是建立在 Aufs 基础上的, Aufs(Another Union File System)是一种 Union FS, 简单来说就是支持将不同的目录挂载到同一个虚拟文件系统下, 并实现一种 layer 的概念.
由于 Aufs 未能加入到 Linux 内核, 考虑到兼容性问题, 加入了 Devicemapper 的支持. Docker 目前默认运行在 Devicemapper 基础上.
Aufs 将挂载到同一虚拟文件系统下的多个目录分别设置成 read-only,read-write 以及 whiteout-able 权限, 对 read-only 目录只能读, 而写操作只能实施在 read-write 目录中. 重点在于, 写操作是在 read-only 上的一种增量操作, 不影响 read-only 目录. 当挂载目录的时候要严格按照各目录之间的这种增量关系, 将被增量操作的目录优先于在它基础上增量操作的目录挂载, 待所有目录挂载结束了, 继续挂载一个 read-write 目录, 如此便形成了一种层次结构.
传统的 Linux 加载 bootfs 时会先将 rootfs 设为 read-only, 然后在系统自检之后将 rootfs 从 read-only 改为 read-write, 然后我们就可以在 rootfs 上进行写和读的操作了. 但 Docker 的镜像却不是这样, 它在 bootfs 自检完毕之后并不会把 rootfs 的 read-only 改为 read-write. 而是利用 union mount(UnionFS 的一种挂载机制)将一个或多个 read-only 的 rootfs 加载到之前的 read-only 的 rootfs 层之上.
在加载了这么多层的 rootfs 之后, 仍然让它看起来只像是一个文件系统, 在 Docker 的体系里把 union mount 的这些 read-only 的 rootfs 叫做 Docker 的镜像. 但是, 此时的每一层 rootfs 都是 read-only 的, 我们此时还不能对其进行操作. 当我们创建一个容器, 也就是将 Docker 镜像进行实例化, 系统会在一层或是多层 read-only 的 rootfs 之上分配一层空的 read-write 的 rootfs.
Device Mapper 是 Linux2.6 内核中支持逻辑卷管理的通用设备映射机制, 它为实现用于存储资源管理的块设备驱动提供了一个高度模块化的内核架构, Device Mapper 的内核体系架构:
在内核中它通过一个一个模块化的 target driver 插件实现对 IO 请求的过滤或者重新定向等工作, 当前已经实现的 target driver 插件包括软 raid, 软加密, 逻辑卷条带, 多路径, 镜像, 快照等, 图中 linear,mirror,snapshot,multipath 表示的就是这些 target driver.Device mapper 进一步体现了在 Linux 内核设计中策略和机制分离的原则, 将所有与策略相关的工作放到用户空间完成, 内核中主要提供完成这些策略所需要的机制.
Device mapper 用户空间相关部分主要负责配置具体的策略和控制逻辑, 比如逻辑设备和哪些物理设备建立映射, 怎么建立这些映射关系等等, 而具体过滤和重定向 IO 请求的工作由内核中相关代码完成. 因此整个 device mapper 机制由两部分组成 -- 内核空间的 device mapper 驱动, 用户空间的 device mapper 库以及它提供的 dmsetup 工具.
四, Docker 虚拟化特点
跟传统 VM 比较具有如下优点:
操作启动快
运行时的性能可以获取极大提升, 管理操作(启动, 停止, 开始, 重启等等) 都是以秒或毫秒为单位的.
轻量级虚拟化
你会拥有足够的 "操作系统", 仅需添加或减小镜像即可. 在一台服务器上可以布署 100~1000 个 Containers 容器. 但是传统虚拟化, 你虚拟 10-20 个虚拟机就不错了.
开源免费
开源的, 免费的, 低成本的. 由现代 Linux 内核支持并驱动. 注 * 轻量的 Container 必定可以在一个物理机上开启更多 "容器", 注定比 VMs 要便宜.
前景及云支持
正在越来越受欢迎, 包括各大主流公司都在推动 docker 的快速发展, 性能有很大的优势.
跟传统 VM 比较具有如下缺点:
目前知道的人比较少;
相关的技术资料欠缺;
Go 语言还没完全成熟.
五, 为什么使用 Docker
Docker 在如下几个方面具有较大的优势:
更快速的交付和部署
Docker 在整个开发周期都可以完美的辅助你实现快速交付. Docker 允许开发者在装有应用和服务本地容器做开发. 可以直接集成到可持续开发流程中.
开发者可以使用一个标准的镜像来构建一套开发容器, 开发完成之后, 运维人员可以直接使用这个容器来部署代码. Docker 可以快速创建容器, 快速迭代应用程序, 并让整个过程全程可见, 使团队中的其他成员更容易理解应用程序是如何创建和工作的. Docker 容器很轻很快! 容器的启动时间是秒级的, 大量地节约开发, 测试, 部署的时间.
高效的部署和扩容
Docker 容器几乎可以在任意的平台上运行, 包括物理机, 虚拟机, 公有云, 私有云, 个人电脑, 服务器等. 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个.
Docker 的兼容性和轻量特性可以很轻松的实现负载的动态管理. 你可以快速扩容或方便的下线的你的应用和服务, 这种速度趋近实时.
更高的资源利用率
Docker 对系统资源的利用率很高, 一台主机上可以同时运行数千个 Docker 容器. 容器除了运行其中应用外, 基本不消耗额外的系统资源, 使得应用的性能很高, 同时系统的开销尽量小. 传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机, 而 Docker 只需要启动 10 个隔离的应用即可.
更简单的管理
使用 Docker, 只需要小小的修改, 就可以替代以往大量的更新工作. 所有的修改都以增量的方式被分发和更新, 从而实现自动化并且高效的管理.
Docker 引擎架构
docker 引擎是一个 C/S 结构的应用, 组件如图所示:
Server 是一个常驻进程;
REST API 实现了 client 和 server 间的交互协议;
CLI 实现容器和镜像的管理, 为用户提供统一的操作界面.
Docker 使用 C/S 架构, Client 通过接口与 Server 进程通信实现容器的构建, 运行和发布. client 和 server 可以运行在同一台集群, 也可以通过跨主机实现远程通信, 架构如图所示:
实战操作如下:
六, Docker 安装配置
系统环境: Centos7.4(docker 官方文档说要求 Linux kernel 至少 3.8 以上), 执行以下命令
[root@localhost ~]# yum -y install docker
安装完后:
启动 docker 进程: systemctl start docker.service
查看 docker 进程: ps -ef | grep docker
Docker 简单使用
要使用 docker 虚拟化, 首先我们需要去下载一个镜像, 然后使用 docker 命令启动
1)下载镜像
- [root@localhost ~]# docker search CentOS
- [root@localhost ~]# docker pull CentOS
2)启动 Docker 容器
3)进入容器
[root@localhost ~]# docker exec -it f48a681da213 /bin/bash
七, Docker 常用命令讲解
- docker version #查看版本
- docker search CentOS #搜索可用 docker 镜像
- docker images #查看当前 docker 所有镜像
- docker pull CentOS #下载镜像
- cat CentOS.tar | docker import - centos6_newname #Docker 导入镜像
docker export 容器_id> cenos6.tar #Docker 导出镜像
- docker run CentOS echo "hello word" #在 docker 容器中运行 hello world!
- docker run CentOS yum install ntpdate #在容器中安装 ntpdate 的程序
- docker ps -l #命令获得最后一个容器的 id
- docker ps -a #查看所有的容器.
运行 docker commit 提交刚修改的容器, 例如:
docker commit 2313132 CentOS:v1
docker run -i -t -d CentOS /bin/bash 在容器里启动一个 / bin/bash shell 环境, 可以登录进入操作, 其中 - t 表示打开一个终端的意思,-i 表示可以交互输入.
docker run -d CentOS:v1 /bin/bash ,-d 表示在后台启动, 以 daemon 方式启动.
- Docker stop id #关闭容器
- Docker start id #启动某个容器
- docker rm id #删除容器
- docker rmi images #删除镜像
docker run -d -p 80:80 -p 8022:22 CentOS:v2, 解析:-p 指定容器启动后 docker 上运行的端口映射及容器里运行的端口, 80:80, 第一个 80 表示 docker 系统上的 80, 第二个 80 表示 docker 虚拟机里面的端口. 用户默认访问本机 80 端口, 自动映射到容器里面的 80 端口.
docker exec -it id /bin/bash #进入容器
来源: http://virtual.51cto.com/art/201905/597108.htm