当前位置: 首页 > news >正文

网站内链检查泗阳网站建设

网站内链检查,泗阳网站建设,wordpress添加随机图片,外包seo服务口碑好文章目录什么是容器#xff1f;容器隔离何为“边界”#xff1f;容器和虚拟机一样吗#xff1f;基于 Linux Namespace 隔离机制的弊端容器限制何为“限制”#xff1f;Cgroups 对资源的限制能力缺陷单进程模型容器镜像容器的诞生容器的一致性何为“层#xff08;layer容器隔离何为“边界”容器和虚拟机一样吗基于 Linux Namespace 隔离机制的弊端容器限制何为“限制”Cgroups 对资源的限制能力缺陷单进程模型容器镜像容器的诞生容器的一致性何为“层layer”什么是容器 容器其实是一种沙盒技术。顾名思义沙盒就是能够像一个集装箱一样把你的应用“装”起来的技术。这样应用与应用之间就因为有了边界而不至于相互干扰而被装进集装箱的应用也可以被方便地搬来搬去这不就是 PaaS 最理想的状态嘛。 容器隔离 何为“边界” 我们知道对于进程来说它的静态表现就是程序平常都安安静静地待在磁盘上而一旦运行起来它就变成了计算机里的数据和状态的总和这就是它的动态表现。而容器技术的核心功能就是通过约束和修改进程的动态表现从而为其创造出一个“边界”。 Docker 容器这个听起来玄而又玄的概念实际上是在创建容器进程时指定了这个进程所需要启用的一组 Namespace 参数。这样容器就只能“看”到当前 Namespace 所限定的资源、文件、设备、状态或者配置而对于宿主机以及其他不相关的程序它就完全看不到了。 比如 PID Namespacelinux中执行 clone() 创建多个新进程时可以指定 CLONE_NEWPID 参数这样就会创建多个 PID Namespace而每个 Namespace 里的应用进程都会认为自己是当前容器里的第 1 号进程它们既看不到宿主机里真正的进程空间也看不到其他 PID Namespace 里的具体情况而在宿主机真实的进程空间里这个进程的 PID 还是真实的数值比如 100。 Linux 操作系统还提供了 Mount、UTS、IPC、Network 和 User 这些 Namespace用来对各种不同的进程上下文进行“障眼法”操作。比如Mount Namespace用于让被隔离进程只看到当前 Namespace 里的挂载点信息Network Namespace用于让被隔离进程看到当前 Namespace 里的网络设备和配置。 容器和虚拟机一样吗 这幅图的左边画出了虚拟机的工作原理。其中名为 Hypervisor 的软件是虚拟机最主要的部分它通过硬件虚拟化功能模拟出了运行一个操作系统需要的各种硬件比如 CPU、内存、I/O 设备等等。然后它在这些虚拟的硬件上安装了一个新的操作系统即 Guest OS。 这样用户的应用进程就可以运行在这个虚拟的机器中它能看到的自然也只有 Guest OS 的文件和目录以及这个机器里的虚拟设备。这就是为什么虚拟机也能起到将不同的应用进程相互隔离的作用。 而这幅图的右边则用一个名为 Docker Engine 的软件替换了 Hypervisor。这也是为什么很多人会把 Docker 项目称为“轻量级”虚拟化技术的原因实际上就是把虚拟机的概念套在了容器上。 在理解了 Namespace 的工作方式之后你就会明白跟真实存在的虚拟机不同在使用 Docker 的时候并没有一个真正的“Docker 容器”运行在宿主机里面。Docker 项目帮助用户启动的还是原来的应用进程只不过在创建这些进程时Docker 为它们加上了各种各样的 Namespace 参数。 这时这些进程就会觉得自己是各自 PID Namespace 里的第 1 号进程只能看到各自 Mount Namespace 里挂载的目录和文件只能访问到各自 Network Namespace 里的网络设备就仿佛运行在一个个“容器”里面与世隔绝。 实际上也不应该把 Docker Engine 或者任何容器管理工具放在跟 Hypervisor 相同的位置因为它们并不像 Hypervisor 那样对应用进程的隔离环境负责也不会创建任何实体的“容器”真正对隔离环境负责的是宿主机操作系统本身。 所以在这个对比图里我们应该把 Docker 画在跟应用同级别并且靠边的位置。这意味着用户运行在容器里的应用进程跟宿主机上的其他进程一样都由宿主机操作系统统一管理只不过这些被隔离的进程拥有额外设置过的 Namespace 参数。而 Docker 项目在这里扮演的角色更多的是旁路式的辅助和管理工作。 这样的架构也解释了为什么 Docker 项目比虚拟机更受欢迎的原因。 这是因为使用虚拟化技术作为应用沙盒就必须要由 Hypervisor 来负责创建虚拟机这个虚拟机是真实存在的并且它里面必须运行一个完整的 Guest OS 才能执行用户的应用进程。这就不可避免地带来了额外的资源消耗和占用。 而相比之下容器化后的用户应用却依然还是一个宿主机上的普通进程这就意味着这些因为虚拟化而带来的性能损耗都是不存在的而另一方面使用 Namespace 作为隔离手段的容器并不需要单独的 Guest OS这就使得容器额外的资源占用几乎可以忽略不计。 所以说“敏捷”和“高性能”是容器相较于虚拟机最大的优势也是它能够在 PaaS 这种更细粒度的资源管理平台上大行其道的重要原因。 基于 Linux Namespace 隔离机制的弊端 首先既然容器只是运行在宿主机上的一种特殊的进程那么多个容器之间使用的就还是同一个宿主机的操作系统内核。 这意味着如果你要在 Windows 宿主机上运行 Linux 容器或者在低版本的 Linux 宿主机上运行高版本的 Linux 容器都是行不通的。而相比之下拥有硬件虚拟化技术和独立 Guest OS 的虚拟机就要方便得多了。最极端的例子是Microsoft 的云计算平台 Azure实际上就是运行在 Windows 服务器集群上的但这并不妨碍你在它上面创建各种 Linux 虚拟机出来。 其次在 Linux 内核中有很多资源和对象是不能被 Namespace 化的最典型的例子就是时间。 这就意味着如果你的容器中的程序使用 settimeofday(2) 系统调用修改了时间整个宿主机的时间都会被随之修改这显然不符合用户的预期。相比于在虚拟机里面可以随便折腾的自由度在容器里部署应用的时候“什么能做什么不能做”就是用户必须考虑的一个问题。 容器限制 在介绍完容器的“隔离”技术之后我们再来研究一下容器的“限制”问题。也许你会好奇不是已经通过 Linux Namespace 创建了一个“容器”吗为什么还需要对容器做“限制”呢还是以 PID Namespace 为例来解释这个问题。 虽然容器内的第 1 号进程在“障眼法”的干扰下只能看到容器里的情况但是宿主机上它作为第 100 号进程与其他所有进程之间依然是平等的竞争关系。这就意味着虽然第 100 号进程表面上被隔离了起来但是它所能够使用到的资源比如 CPU、内存却是可以随时被宿主机上的其他进程或者其他容器占用的。当然这个 100 号进程自己也可能把所有资源吃光。这些情况显然都不是一个“沙盒”应该表现出来的合理行为。 何为“限制” Linux Cgroups 就是 Linux 内核中用来为进程设置资源限制的一个重要功能。Linux Cgroups 的全称是 Linux Control Group。它最主要的作用就是限制一个进程组能够使用的资源上限包括 CPU、内存、磁盘、网络带宽等等。此外Cgroups 还能够对进程进行优先级设置、审计以及将进程挂起和恢复等操作。 除 CPU 子系统外Cgroups 的每一项子系统都有其独有的资源限制能力比如 blkio为​​​块​​​设​​​备​​​设​​​定 ​​​I/O 限​​​制一般用于磁盘等设备cpuset为进程分配单独的 CPU 核和对应的内存节点memory为进程设定内存使用的限制。 Linux Cgroups 的设计还是比较易用的简单粗暴地理解呢它就是一个子系统目录加上一组资源限制文件的组合。而对于 Docker 等 Linux 容器项目来说它们只需要在每个子系统下面为每个容器创建一个控制组即创建一个新目录然后在启动容器进程之后把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。 Cgroups 对资源的限制能力缺陷 众所周知Linux 下的 /proc 目录存储的是记录当前内核运行状态的一系列特殊文件用户可以通过访问这些文件查看系统以及当前正在运行的进程的信息比如 CPU 使用情况、内存占用率等这些文件也是 top 指令查看系统信息的主要数据来源。 但是你如果在容器里执行 top 指令就会发现它显示的信息居然是宿主机的 CPU 和内存数据而不是当前容器的数据。 造成这个问题的原因就是/proc 文件系统并不知道用户通过 Cgroups 给这个容器做了什么样的资源限制即/proc 文件系统不了解 Cgroups 限制的存在。 在生产环境中这个问题必须进行修正否则应用程序在容器里读取到的 CPU 核数、可用内存等信息都是宿主机上的数据这会给应用的运行带来非常大的困惑和风险。这也是在企业中容器化应用碰到的一个常见问题也是容器相较于虚拟机另一个不尽如人意的地方。 单进程模型 通过以上讲述我们就能理解一个正在运行的 Docker 容器其实就是一个启用了多个 Linux Namespace 的应用进程而这个进程能够使用的资源量则受 Cgroups 配置的限制。 这也是容器技术中一个非常重要的概念即容器是一个“单进程”模型。 由于一个容器的本质就是一个进程用户的应用进程实际上就是容器里 PID1 的进程也是其他后续创建的所有进程的父进程。这就意味着在一个容器中你没办法同时运行两个不同的应用除非你能事先找到一个公共的 PID1 的程序来充当两个不同应用的父进程这也是为什么很多人都会用 systemd 或者 supervisord 这样的软件来代替应用本身作为容器的启动进程。但是在后面分享容器设计模式时会有其他更好的解决办法。这是因为容器本身的设计就是希望容器和应用能够同生命周期这个概念对后续的容器编排非常重要。否则一旦出现类似于“容器是正常运行的但是里面的应用早已经挂了”的情况编排系统处理起来就非常麻烦了。 容器镜像 容器的诞生 先看这样一段代码 #define _GNU_SOURCE #include sys/mount.h #include sys/types.h #include sys/wait.h #include stdio.h #include sched.h #include signal.h #include unistd.h #define STACK_SIZE (1024 * 1024) static char container_stack[STACK_SIZE]; char* const container_args[] {/bin/bash,NULL };int container_main(void* arg) { printf(Container - inside the container!\n);execv(container_args[0], container_args);printf(Somethings wrong!\n);return 1; }int main() {printf(Parent - start a container!\n);int container_pid clone(container_main, container_stackSTACK_SIZE, CLONE_NEWNS | SIGCHLD , NULL);waitpid(container_pid, NULL, 0);printf(Parent - container stopped!\n);return 0; }可以看到这里我们通过 clone() 系统调用创建了一个新的子进程 container_main并且声明要为它启用 Mount Namespace即CLONE_NEWNS 标志注Mount Namespace用于让被隔离进程只看到当前 Namespace 里的挂载点信息。这就创建了一个“容器”而这个“容器”里执行的是一个“/bin/bash”程序也就是一个 shell。进入这个“容器”当中如果在“容器”里执行一下 ls 指令的话我们就会发现一个有趣的现象 /tmp 目录下的内容跟宿主机的内容是一样的。 也就是说 即使开启了 Mount Namespace容器进程看到的文件系统也跟宿主机完全一样。 这是怎么回事呢 仔细思考一下会发现这其实并不难理解Mount Namespace 修改的是容器进程对文件系统“挂载点”的认知。但这也就意味着只有在“挂载”这个操作发生之后进程的视图才会被改变而在此之前新创建的容器会直接继承宿主机的各个挂载点。 这时你可能已经想到了一个解决办法创建新进程时除了声明要启用 Mount Namespace 之外我们还可以告诉容器进程有哪些目录需要重新挂载就比如这个 /tmp 目录。可以在容器进程启动之前加上了一句 mount(“none”, “/tmp”, “tmpfs”, 0, “”) 语句。就这样我告诉了容器以 tmpfs内存盘格式重新挂载了 /tmp 目录。 因为我们创建的新进程启用了 Mount Namespace所以这次重新挂载的操作只在容器进程的 Mount Namespace 中有效。如果在宿主机上用 mount -l 来检查一下这个挂载你会发现它是不存在的。 这就是 Mount Namespace 跟其他 Namespace 的使用略有不同的地方它对容器进程视图的改变一定是伴随着挂载操作mount才能生效。 可是作为一个普通用户我希望每当创建一个新容器时容器进程看到的文件系统就是一个独立的隔离环境而不是继承自宿主机的文件系统。怎么才能做到这一点呢 不难想到我们可以在容器进程启动之前重新挂载它的整个根目录“/”。而由于 Mount Namespace 的存在这个挂载对宿主机不可见所以容器进程就可以在里面随便折腾了。 当然为了能够让容器的这个根目录看起来更“真实”我们一般会在这个容器的根目录下挂载一个完整操作系统的文件系统比如 Ubuntu16.04 的 ISO。这样在容器启动之后我们在容器里通过执行 “ls /” 查看根目录下的内容就是 Ubuntu 16.04 的所有目录和文件。 而这个挂载在容器根目录上用来为容器进程提供隔离后执行环境的文件系统就是所谓的“容器镜像”。它还有一个更为专业的名字叫作rootfs根文件系统。 现在你应该可以理解对 Docker 项目来说它最核心的原理实际上就是为待创建的用户进程 启用 Linux Namespace 配置设置指定的 Cgroups 参数切换进程的根目录Change Root。 这样一个完整的容器就诞生了。 需要明确的是rootfs 只是一个操作系统所包含的文件、配置和目录并不包括操作系统内核。在 Linux 操作系统中这两部分是分开存放的操作系统只有在开机启动时才会加载指定版本的内核镜像。 而实际上同一台机器上的所有容器都共享宿主机操作系统的内核。 这就意味着如果你的应用程序需要配置内核参数、加载额外的内核模块以及跟内核进行直接的交互就需要注意了这些操作和依赖的对象都是宿主机操作系统的内核它对于该机器上的所有容器来说是一个“全局变量”牵一发而动全身。 这也是容器相比于虚拟机的主要缺陷之一毕竟后者不仅有模拟出来的硬件机器充当沙盒而且每个沙盒里还运行着一个完整的 Guest OS 给应用随便折腾。 不过正是由于 rootfs 的存在容器才有了一个被反复宣传至今的重要特性一致性。 容器的一致性 在容器出现之前我们知道由于云端与本地服务器环境不同应用的打包过程一直是使用 PaaS 时最“痛苦”的一个步骤。 但有了容器之后更准确地说有了容器镜像即 rootfs之后这个问题被非常优雅地解决了。 由于 rootfs 里打包的不只是应用而是整个操作系统的文件和目录也就意味着应用以及它运行所需要的所有依赖都被封装在了一起。 事实上对于大多数开发者而言他们对应用依赖的理解一直局限在编程语言层面。比如 Golang 的 Godeps.json。但实际上一个一直以来很容易被忽视的事实是对一个应用来说操作系统本身才是它运行所需要的最完整的“依赖库”。 有了容器镜像“打包操作系统”的能力这个最基础的依赖环境也终于变成了应用沙盒的一部分。这就赋予了容器所谓的一致性无论在本地、云端还是在一台任何地方的机器上用户只需要解压打包好的容器镜像那么这个应用运行所需要的完整的执行环境就被重现出来了。 这种深入到操作系统级别的运行环境一致性打通了应用在本地开发和远端执行环境之间难以逾越的鸿沟。 何为“层layer” 在 rootfs 的基础上Docker 公司创新性地提出了使用多个增量 rootfs 联合挂载一个完整 rootfs 的方案这就是容器镜像中“层”的概念。 如上从这个结构可以看出来容器的 rootfs 由图所示的三部分组成 第一部分只读层。 它是这个容器的 rootfs 最下面的五层对应的正是 ubuntu:latest 镜像的五层。可以看到它们的挂载方式都是只读的rowh即 readonlywhiteout至于什么是 whiteout我下面马上会讲到。而这些层都以增量的方式分别包含了 Ubuntu 操作系统的一部分。 第二部分可读写层。 它是这个容器的 rootfs 最上面的一层6e3be5d2ecccae7cc它的挂载方式为rw即 read write。在没有写入文件之前这个目录是空的。而一旦在容器里做了写操作你修改产生的内容就会以增量的方式出现在这个层中。 为了删除只读层里的一个文件AuFS 会在可读写层创建一个 whiteout 文件把只读层里的文件“遮挡”起来。 比如你要删除只读层里一个名叫 foo 的文件那么这个删除操作实际上是在可读写层创建了一个名叫.wh.foo 的文件。这样当这两个层被联合挂载之后foo 文件就会被.wh.foo 文件“遮挡”起来“消失”了。这个功能就是“rowh”的挂载方式即只读 whiteout 的含义。我喜欢把 whiteout 形象地翻译为“白障”。 所以最上面这个可读写层的作用就是专门用来存放你修改 rootfs 后产生的增量无论是增、删、改都发生在这里。而当我们使用完了这个被修改过的容器之后还可以使用 docker commit 和 push 指令保存这个被修改过的可读写层并上传到 Docker Hub 上供其他人使用而与此同时原先的只读层里的内容则不会有任何变化这就是增量 rootfs 的好处。 第三部分Init 层。 它是一个以“-init”结尾的层夹在只读层和读写层之间。Init 层是 Docker 项目单独生成的一个内部层专门用来存放 /etc/hosts、/etc/resolv.conf 等信息。 需要这样一层的原因是这些文件本来属于只读的 Ubuntu 镜像的一部分但是用户往往需要在启动容器时写入一些指定的值比如 hostname所以就需要在可读写层对它们进行修改。 可是这些修改往往只对当前的容器有效我们并不希望执行 docker commit 时把这些信息连同可读写层一起提交掉。 所以Docker 做法是在修改了这些文件之后以一个单独的层挂载了出来。而用户执行 docker commit 只会提交可读写层所以是不包含这些内容的。 最终这 7 个层都被联合挂载到 /var/lib/docker/aufs/mnt 目录下表现为一个完整的 Ubuntu 操作系统供容器使用。 至此 通过“分层镜像”的设计以 Docker 镜像为核心来自不同公司、不同团队的技术人员被紧密地联系在了一起。而且由于容器镜像的操作是增量式的这样每次镜像拉取、推送的内容比原本多个完整的操作系统的大小要小得多而共享层的存在可以使得所有这些容器镜像需要的总空间也比每个镜像的总和要小。这样就使得基于容器镜像的团队协作要比基于动则几个 GB 的虚拟机磁盘镜像的协作要敏捷得多。 更重要的是一旦这个镜像被发布那么你在全世界的任何一个地方下载这个镜像得到的内容都完全一致可以完全复现这个镜像制作者当初的完整环境。这就是容器技术“强一致性”的重要体现。 而这种价值正是支撑 Docker 公司在 2014~2016 年间迅猛发展的核心动力。容器镜像的发明不仅打通了“开发 - 测试 - 部署”流程的每一个环节更重要的是容器镜像将会成为未来软件的主流发布方式。 笔记来源于极客时间《深入剖析Kubernetes》
http://www.w-s-a.com/news/341871/

相关文章:

  • 邯郸城乡建设部网站首页唐山市住房城乡建设部网站主页
  • 慕课联盟网站开发实战六安品牌网站建设电话
  • 制作企业网站首页贵州小程序制作开发
  • 什么是网站后台郑州众志seo
  • 做线上交互的网站分销平台
  • 培训机构网站开发江门cms模板建站
  • 网站描述模板建筑模型网站有哪些
  • 域名注册费用张家界seo
  • 淘宝联盟怎么自己做网站山西省住房与城乡建设厅网站
  • 最新网站建设常见问题使用微信推广的各种方法
  • 购物网站建设课程设计报告做木工的网站
  • 扶沟县网站开发网站建设在哪里进行
  • 查看网站服务器信息网站首页地址 网站域名
  • 网站网站制作网站的ui界面设计案例分析
  • 怎么查网站是否备案成都装修公司联系电话
  • 佛山免费发布信息的网站oa办公系统排行榜
  • 南湖区建设街道办事处网站汕头建设银行各支行电话
  • 复古风格网站网站套餐方案
  • 界面设计做的好的网站旅游商城网站模板
  • 大型电子商务网站 服务器硬件 cpu 内存 硬盘 2014美食网站开发意义
  • 建立网站的目的和意义网站建设寻求
  • 邢台手机网站建设设计师培训心得
  • 营销网站怎么做丽水微信网站建设哪家好
  • 南昌定制网站开发多少钱东阿县城市建设局网站
  • 浙江网站建设公司南昌seo招聘
  • 工业软件有哪些专业seo站长工具全面查询网站
  • 山东兴华建设集团有限公司网站和京东一样做电子产品的网站
  • 网站建设谢辞关于h5的网站模板
  • 网站改版提交WordPress360收录
  • 省级网站 开发建设 资质在国外怎么做网站