<<the architecture of open source applications>> 中关于虚拟机复制与迁移(下)

来源:互联网 发布:张予曦淘宝店质量 编辑:程序博客网 时间:2024/06/05 15:55

18.6克隆端组件

克隆在从架构描述器创建时是空心弹,和我们一样,他们需要从父母那里获得很大的帮助才能长大:子虚拟机们迁出时要立即给家里打电话,他们发现很多需要的东西缺失,要求他们的父母马上发送。

18.6.1 memtap进程

memtap进程连接到每个创建后的克隆,是一个克隆的生命线。它映射到克隆的所有内存并按需加载。通过Xenhypervisor,它登记了一些关键的数据位:访问克隆内存的权限被关闭,由第一次访问一个内存页造成的硬件故障由hypervisor路由到memtap进程。

在其最简单的化身中,memtap进程只需简单地要求内存的服务器处理错误内存页,但也有更复杂的情况。首先,memtap助手使用了mcdist。这意味着,在任何时间点,任何页面可以凭借已被另一个克隆的异步预取请求到达克隆。第二,我们允许SnowFlock虚拟机是多处理器的虚拟机。这就不那么有趣了。这意味着,在并行处理时存在同一页的多个故障需要。第三,在以后的版本中,memtap助手可以明确地预取批量的内存页,在缺乏保证情况下,以任何次序从mcdist服务器到达克隆。这些因素可能导致并发噩梦,我们遇到了所有这些问题。

内存页位图是整个memtap的设计中心。当处理架构描述器创建克隆虚拟机时,创建和初始化该位图。该位图是一个比特数组,其大小由虚拟机内存可容纳的内存页数量决定。英特尔处理器有方便的原子位互斥指令:设置了一个比特,或做一个测试和设置,可以保证原子发生与其他处理器在同一个盒子里。这使得我们在大多数情况下,从而提供不同的实体,在不同的保护域的访问位图以避免锁:Xen管理程序,memtap进程,以及guest内核本身的克隆。

Xen的处理由第一次访问页面产生的硬件页错误时,它使用内存页位图来决定是否需要提醒 memtap。它还使用该位图依赖于不在同一页的多个虚拟处理器来队列化memtap缓冲页。当其缓冲区是满的,或到达一个明确请求的内存页时暂停虚拟机,位图被用来丢弃那些已经到达的任何重复的已经存在内存页。所需的任何剩余内存页被复制到虚拟机的内存,并设置适当的位图比特。

18.6.2 明智的克隆,避免不必要的提取

我们刚刚提到,运行于克隆内核的该内存页位图是可见的,并没有锁,需要修改。这给克隆提供了一个强大的启蒙工具:它们可以防止通过修改位图和假装已经存在的是当前内存页的抓取。这是非常有用的性能,在内存页没有完全覆盖之前,他们都可以被安全使用。

恰好是一个非常普遍的情况,当发生这种情况,并获取可避免。在内核中的所有内存分配(虚拟机alloc使用 kzallocget_free_page,用户空间的BRK,等等)最终处理内核页分配器。内存页通常由中间开始分配,管理细粒度块要求是:slab分配器,glibc在一个用户空间进程的malloc分配,等等。然而,无论是显式或隐式的分配,一个关键的语法含义始终正确:没有人关注内存页中包含的内容,因为它的内容将随时被覆盖。为什么取这样一个内存页呢?没有任何理由这样做,实际经验表明,避免这种获取方式是极其有利的。

18.7虚拟机克隆的应用程序接口

到目前为止,我们都集中一个虚拟机有效克隆的内部机制。作为服务系统非常有趣,所以我们需要把注意力放在谁将使用这样的系统:应用。

18.7.1API实现

通过简单的SnowFlock API(如18.1所示),应用程序可以利用虚拟机克隆。利用克隆的方式基本上是一个两阶段的过程。你第一次请求分配一个克隆实例,虽然依赖于系统策略的影响,分配的实例可能会小于所请求的内容。第二,你可以使用分配给你的虚拟机克隆。一个关键的假设是你的重点聚焦于虚拟机上一个操作。虚拟机克隆是适用于单一应用的虚拟机,如Web服务器或一个渲染工厂组件。如果你在一百多个桌面环境进程中的多个应用程序同时调用虚拟机克隆,你就头大了。

sf_request_ticketN

请求分配n个克隆。返回一个分配M≤N 克隆的ticket。 

sf_cloneticket

使用的ticket分配克隆。返回克隆ID0≤ID <M 

sf_checkpoint_parent()

准备一个检查点ç不可改变的父虚拟机,可用于以后任意创建克隆。

sf_create_clonesC,门票)

sf_clone相同,只是使用检查点ç。在哪个对应点开始执行sf_checkpoint_parent()时调用克隆。

sf_exit()

 终止子克隆1≤ID <M

sf_jointicket

父节点使用ID = 0,块,直到所有使用ticket的子节点调用sf_exit前一直处于阻塞状态。在这一时间点上,所有的子节点都被终止和ticket被弃用。

sf_killticket

家长弃用ticket,并立即杀死所有相关的子节点进程。

18.1SnowFlock虚拟机克隆API

API简化了编组消息,同时传递给XenStoreXen通过共享内存的低吞吐量接口来控制平面交易。在hypervisor上运行的一个SnowFlock本地守护进程(SFLD)执行监听这样的请求,包括消息解组,执行,并要求回调。

通过API,程序可以直接控制虚拟机的克隆。API编程语言包括CC + +PythonJava。我们既可以使用shell脚本执行程序,也可以使用所提供的命令行脚本。并行框架(如MPI)可以嵌入到API中:MPI程序就可以使用SnowFlock了,且并不需要修改源代码。置于Web服务器或应用服务器前的负载平衡器可以使用API​​克隆他们所管理的服务器。

SFLDs协调虚拟机克的隆执行请求。他们创建和传输架构描述器,创建克隆的虚拟机,启动磁盘和内存的服务器,并启动memtap辅助进程。他们是分布在一个物理集群系统上负责管理虚拟机的一个微型发布系统。

SFLDs推迟分配的决策给一个集中SnowFlock的主守护进程(SFMD)。SFMD使用相应的集群管理软件简化了接口。我们没有看到任何需求需要推倒重来,包括资源分配,配额,策略等,例如Sun的网格引擎或平台的EGO等都是适合的。

18.7.2必要的突变

克隆后,大多数克隆的虚拟机进程不再是父节点,而且他们现在运行在一个副本上。在大多数情况下,这是正常的,没有问题。毕竟,操作系统的主要任务是从低层次的细节(如网络标识)隔离应用程序。然而,平稳过渡需要一套有效的机制。如果管理在克隆的网络身份以避免冲突和混乱,我们就必须引入在克隆过程中的轻微突变。此外,因为这些调整可能需要更高级别的权限,所以允许用户配置一个钩子程序来插入到任何必要的任务中,例如依靠克隆的身份安装网络文件系统,。

克隆的产生有可能是不必要的。尽管父虚拟机可能是由DHCP服务器管理的网络的一部分,或系统管理员通过其他各种途径能够做到克隆的IP地址分配。为了保持灵活的应用场景,我们将父节点和所有克隆置于虚拟的私有网络中。从同一父节点的克隆都分配一个唯一的ID,他们的IP地址在这个私有网络中被自动设置后,克隆的ID生效。这保证了不需要系统管理员的干预参与,而且没有IP地址冲突。

我们通过一个钩子程序在虚拟的网络驱动程序直接对IP进行重新配置。然而,我们也催动驱动程序自动生成合成的DHCP响应。因此,无论你如何分发,虚拟的网络接口将确保正确的IP地址传播到客户机操作系统,甚至当你重新启动主机是都可以。

为了防止来自不同父母的克隆碰撞以及隔离彼此的虚拟专用网络,可以防止相互DDoS攻击克隆虚拟网络的以太网(或第二层交换)。我们劫持了以太网MAC OUIs范围3,奉献他们的克隆。OUI将是一个父虚拟机的功能。像通过一个虚拟机的ID确定其IP地址一样,这同样决定了其非OUI的以太网MAC地址。虚拟的网络驱动器具有将虚拟机的MAC地址转换成它所分配虚拟机ID的功能,过滤出所有虚拟专用网络与不同OUI们的流量。这种隔离是通过 ebtables简单实现的。

让彼此克隆间通信可能是有趣的,但不是情趣盎然。有时我们会想让克隆响应来自互联网的HTTP请求,或连接公共数据仓库。我们为虚拟机的任何一套父节点和克隆配备一个专用的路由器。这个路由器的小虚拟机执行从克隆到互联网的防火墙,节流和NAT的功能。这也限制了父虚拟机的接入连接和众所周知的端口。路由器的虚拟机是轻量级的,但代表了网络流量的集中化,从而严重限制了可伸缩性的单点。相同的网络规则,可用于每个克隆虚拟机运行主机的一个分布式环境。我们还没有发布这个实验室补丁。

SFLDs分配了虚拟机ID,并指导虚拟网络驱动程序应该如何配置自己内部的MACIP地址,DHCP指令,路由器虚拟机的坐标,过滤规则,等等。

18.8结论

通过调整Xen hypervisor和延迟转移虚拟机的状态,SnowFlock可以在几秒钟内产生几十个运行中的虚拟机克隆。SnowFlock克隆虚拟机的瞬时性和热加载极大地改善了自动化集群管理的可用性和为应用提供云资源的更大可编程性。SnowFlock也提高了云的灵活性,虚拟机实例加快了20倍,并通过利用他们的父节点内存中的操作系统和应用程序缓存提高了最新创建的虚拟机的性能。SnowFlock高效性能的关键是启发式,避免了不必要的页面抓取,组播系统,让克隆们合作预取它们的状态。它是巧妙应用了一些尝试和真正的技术,一些技巧,以及一些工业界调试的慷慨帮助。

我们认识到整个SnowFlock经历了两个重要的教训。首先是经常被低估的价值KISS定理。我们期待实现复杂的预取技术,以减轻一连串的内存页在克隆启动时会发出的请求。令人惊讶的是这也许没有必要。该系统作为以一个单一原则为基础的许多工作有很好的表现:只是带来了超出需要的内存。简单化的另一个例子是内存页位图。通过一个简单的数据结构和清晰的原子访问语义,这大大简化了由于多个虚拟CPU,页面更新的竞争,通过多播的异步页到达等可能产生的并发性问题。

第二个教训是规模不再是谎言。换句话说,你发现每次你都会碰到准备切换系统和新出现瓶颈的规模性问题。这是紧密联系在一起的教训:随着负载的增加,简单而优雅的解决方案使规模化隐藏了起来。这个原则的一个最好的例子是mcdist系统。在大规模的测试表明,一个以TCP / IP为基础的页面分配机制进行数百克隆时经常惨遭失败。mcdist凭借其极端的分发机制和角色良好定义的获得了成功:客户只关心自己的内存页,服务器只关心维持一个全局的流量控制。保持mcdist优雅简单,使SnowFlock能够扩展得非常好。

如果你有兴趣了解更多,您可以访问网站多伦多大学的网站1获得在GPLv2授权许可下的学术论文和开放源码,GridCentric 4为一个工业化的实现。

脚注

1.      http://sysweb.cs.toronto.edu/projects/1

2.      http://www.gridcentriclabs.com/architecture-of-open-source-applications

3.      OUI的,或组织唯一IDMAC地址分配给供应商的范围。

4.      http://www.gridcentriclabs.com/

0 0