
目录Docker 简介什么是虚拟化、容器化为什么要虚拟化、容器化容器虚拟化实现容器虚拟化实现原理容器虚拟化基础之 NameSpace什么是 Namespace(命名空间空间隔离实战基础知识dd 命令详解mkfs 命令详解df 命令详解mount 命令详解unshare命令详解Docker 简介什么是虚拟化、容器化物理机实际的服务器或者计算机。相对于虚拟机而言的对实体计算机的称呼。物理机提供给虚拟机以硬件环境有时也称为“寄主”或“宿主”。虚拟化是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机每个逻辑计算机可运行不同的操作系统并且应用程序都可以在相互独立的空间内运行而互不影响从而显著提高计算机的工作效率。容器化容器化是一种虚拟化技术又称操作系统层虚拟化Operating system level virtualization这种技术将操作系统内核虚拟化可以允许用户空间软件实例instances被分割成几个独立的单元在内核中运行而不是只有一个单一实例运行。这个软件实例也被称为是一个容器containers。对每个实例的拥有者与用户来说他们使用的服务器程序看起来就像是自己专用的。容器技术是虚拟化的一种。docker 是现今容器技术的事实标准。为什么要虚拟化、容器化我们从上面的历史发展来看虚拟化和容器化的最主要目的就是资源隔离随着资源隔离的实现逐渐也带来了更大的收益。资源利用率高将利用率较低的服务器资源进行整合用更少硬件资源运行更多业务降低 IT 支出和运维管理成本。环境标准化一次构建随处执行。实现执行环境的标准化发布部署和运维。开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致导致有些bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境确保了应用运行环境一致性从而不会再出现「这段代码在我机器上没问题啊」这类问题。资源弹性伸缩根据业务情况动态调整计算、存储、网络等硬件及软件资源差异化环境提供同时提供多套差异化的执行环境限制环境使用资源。比如我的服务一个以来 Ubuntu 操作系统一个服务依赖 CentOS 操作系统但是没有预算购买两个物理机这个时候容器化就能很好的提供多种不同的环境。沙箱安全为避免不安全或不稳定软件对系统安全性、稳定性造成影响可使用虚拟化技术构建虚拟执行环境。比如我在容器里面执行 rm -rf /* 不会把整个服务器搞死也不影响其他人部署的程序使用。容器对比虚拟机更轻量启动更快传统的虚拟机技术启动应用服务往往需要数分钟而 Docker 容器应用由于直接运行于宿主内核无需启动完整的操作系统因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。docker 不需要虚拟内核所以启动可以更快相当于 windows 的开机时间省去了。维护和扩展容易Docker 使用的分层存储以及镜像的技术使得应用重复部分的复用更为容易也使得应用的维护更新更加简单基于基础镜像进一步扩展镜像也变得非常简单。此外Docker 团队同各个开源项目团队一起维护了一大批高质量的官方镜像既可以直接在生产环境使用又可以作为基础进一步定制大大的降低了应用服务的镜像制作成本。比如 docker hub 提供了很多镜像各个系统的一个命令就可以拿到了研发也可以自己定制镜像分享给各个产品容器虚拟化实现容器虚拟化实现原理容器虚拟化有别于主机虚拟化是操作系统层的虚拟化。通过 namespace 进行各程序的隔离加上 cgroups 进行资源的控制以此来进行虚拟化。容器虚拟化基础之 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可以使用 | (按位或)组合这些参数举例说明三年一班的小明和三年二班的小明虽说他们名字是一样的但是所在班级不一样那么在全年级排行榜上面即使出现两个名字一样的小明也会通过各自的学号来区分。对于学校来说每个班级就相当于是一个命名空间这个空间的名称是班级号。班级号用于描述逻辑上的学生分组信息至于什么学生分配到 1 班什么学生分配到2 班那就由学校层面来统一调度。namespace系统调用参数被隔离的全局资源IPCCLONE_NEWIPC进程间通信MountCLONE_NEWNS文件系统挂载点UTSCLONE_NEWUTS主机名域名PIDCLONE_NEWPID进程编号NetworkCLONE_NEWNET网络设备UserCLONE_NEWUSER用户以上命名空间在容器环境下的隔离效果UTS每个容器能看到自己的 hostname拥有独立的主机名和域名。IPC同一个 IPC namespace 的进程之间能互相通讯不同的 IPC namespace 之间不能通信。PID每个 PID namespace 中的进程可以有其独立的 PID每个容器可以有其 PID 为1 的 root 进程。Network每个容器用有其独立的网络设备IP 地址IP 路由表/proc/net 目录端口号。Mount每个容器能看到不同的文件系统层次结构。User每个 container 可以有不同的 user 和 group id空间隔离实战我需要知道隔离的能力其实并不是Docker实现的而是我们的操作系统实现的基础知识dd 命令详解语法dd option参数if文件名输入文件名默认为标准输入。即指定源文件。of文件名输出文件名默认为标准输出。即指定目的文件。ibsbytes一次读入 bytes 个字节即指定一个块大小为 bytes 个字节。obsbytes一次输出 bytes 个字节即指定一个块大小为 bytes 个字节。bsbytes同时设置读入/输出的块大小为 bytes 个字节。cbsbytes一次转换 bytes 个字节即指定转换缓冲区大小。skipblocks从输入文件开头跳过 blocks 个块后再开始复制。seekblocks从输出文件开头跳过 blocks 个块后再开始复制。countblocks仅拷贝 blocks 个块块大小等于 ibs 指定的字节数。conv关键字关键字可以有以下 11 种conversion用指定的参数转换文件。ascii转换 ebcdic 为 asciiebcdic转换 ascii 为 ebcdicibm转换 ascii 为 alternate ebcdicblock把每一行转换为长度为 cbs不足部分用空格填充unblock使每一行的长度都为 cbs不足部分用空格填充lcase把大写字符转换为小写字符ucase把小写字符转换为大写字符swap交换输入的每对字节noerror出错时不停止notrunc不截短输出文件sync将每个输入块填充到 ibs 个字节不足部分用空NUL字符补齐。--help显示帮助信息--version显示版本信息dd命令演示mkfs 命令详解用于在设备上创建 Linux 文件系统,俗称格式化比如我们使用 U 盘的时候可以格式化。语法mkfs [-V] [-t fstype] [fs-options] filesys [blocks]参数-t fstype指定要建立何种文件系统如 ext3ext4filesys 指定要创建的文件系统对应的设备文件名blocks指定文件系统的磁盘块数。-V : 详细显示模式fs-options:传递给具体的文件系统的参数mkfs演示df 命令详解Linux df英文全拼disk free 命令用于显示目前在 Linux 系统上的文件系统磁盘使用情况统计。语法df [OPTION]... [FILE]...参数-a, --all 包含所有的具有 0 Blocks 的文件系统-h, --human-readable 使用人类可读的格式(预设值是不加这个选项的...)-H, --si 很像 -h, 但是用 1000 为单位而不是用 1024-t, --typeTYPE 限制列出文件系统的 TYPE-T, --print-type 显示文件系统的形式df命令演示-Tmount命令详解mount命令用于加载文件系统到指定的加载点。此命令的也常用于挂载光盘使我们可以访问光盘中的数据因为你将光盘插入光驱中Linux并不会自动挂载必须使用Linux mount 命令来手动完成挂载。Linux系统下不同目录可以挂载不同分区和磁盘设备它的目录和磁盘分区是分离的可以自由组合(通过挂载)不同的目录数据可以跨越不同的磁盘分区或者不同的磁盘设备。挂载的实质是为磁盘添加入口挂载点mount常见用法mount [-l]mount [-t vfstype] [-o options] device dir常见参数-l显示已加载的文件系统列表-t:加载文件系统类型支持常见系统类型的ext3,ext4,iso9660,tmpfs,xfs等,大部分情况可以不指定mount可以自己识别-o options主要用来描述设备或档案的挂接方式。loop用来把一个文件当成硬盘分区挂接上系统ro采用只读方式挂接设备rw采用读写方式挂接设备device:要挂接(mount)的设备。dir:挂载点的目录mount命令演示我们将刚刚格式化的test.img文件挂载到我们的testmount文件中用df可以查看我们成功的挂载我们就可以通过在这个目录中进行读写就是对挂载的磁盘或文件进行读写unshare命令详解unshare主要能力是使用与父程序不共享的名称空间运行程序。语法unshare [options] program [arguments]常用参数参数含义-i, --ipc不共享IPC空间-m, --mount不共享Mount空间-n, --net不共享Net空间-p, --pid不共享PID空间-u, --uts不共享UTS空间-U, --user不共享用户-V, --version版本查看--fork执行unshare的进程fork一个新的子进程在子进程里执行 unshare传入的参数。--mount-proc执行子进程前将proc优先挂载过去unshare命令演示1 、PID隔离在主机上执行ps -ef,可以看到进程列表如下其中启动进程PID 1为init进程我们打开另外一个shell执行下面命令创建一个bash进程并且新建一个PIDNamespace--fork新建了一个bash进程是因为如果不建新进程新的namespace会用unshare 的 PID作为新的空间的父进程而这个unshare进程并不在新的namespace中所以会报个错 Cannot allocate memorymount-proc是因为Linux下的每个进程都有一个对应的/proc/PID目录该目录包含了大量的有关当前进程的信息。 对一个 PID namespace而言/proc目录只包含当前namespace 和它所有子孙后代namespace里的进程的信息。创建一个新的PIDnamespace 后如果想让子进程中的top、ps等依赖/proc文件系统的命令工作还需要挂载 /proc文件系统。而文件系统隔离是mount namespace管理的所以linux特意提供了一个选项--mount-proc来解决这个问题。如果不带这个我们看到的进程还是系统的进程信息或者根本看不到系统的相关信息unshare之后unshare之前2、mount隔离我们首先创建一个空白的镜像文件然后执行mount隔离再当前窗口进行mount隔离我们再挂载点中进行写操作我们去另一个bash中查看当前文件下的是否有内容发现并没有内容所以我们的确实完成了mout隔离