1. 基于容器的虚拟化技术

0 概述

0.1 操作系统的挑战

OS领域一直以来面临的一个主要挑战来自 应用间存在的相互独立性资源互操作性 之间的矛盾, 即每个应用程序都希望能运行在一个相对独立的系统环境下, 不受其他程序的干扰, 同时又能以方便快捷的方式与其他程序交换和共享系统资源.

虚拟化技术因其具有同时运行多个相对独立操作系统的能力而被用来克服上面挑战. VMware和Xen等虚拟化主流产品均采用Hypervisor模型. 该模型通过将应用程序运行在多个不同虚拟机内, 实现对上层应用程序的隔离. 但由于Hypervisor模型更倾向于每个虚拟机都拥有一套相对独立的系统资源, 提供相对完全的独立性支持, 这种策略造成处于不同虚拟机内应用程序间实现相互操作非常困难. 例如, 同一台物理机不同虚拟机, 应用程序之间仍然只能通过网络进行数据交换, 而非共享内存或文件.

Hypervisor模型这种强独立性保障策略在一定程度上牺牲系统的执行效率. 对于高性能计算、Web服务、数据库、游戏平台和分布式系统等很多应用领域, 提供高效的资源互操作性和保持程序间的独立性具有同等重要的意义. 针对这种需求, 学术界提出了一种基于资源与安全容器概念的虚拟化技术. 应用容器模型的虚拟机化产品Solaris 10和Linux-Vsever, 能够满足基本的独立性需求的同时提供高效的系统资源共享支持.

1 容器技术的基本概念和发展背景

容器技术主要涉及两个方面: 资源容器安全容器.

1.1 资源容器

1.1.1 资源主体与资源消费者: 资源的统计和控制很难

当前比较流行的 高性能服务器程序!!! 通常是 一个资源主体 对应多个资源消费者的模式, 如事件触发模式(Event-Driven), 或者是多个资源主体对应多个资源消费者的模式, 如CGI程序.

这造成准确估算单个资源消费者所使用的资源量变的很困难, 从而无法很好地进行资源管理和控制.

例如, 在多线程服务器上, 一个应用实例对应一个可以执行多种独立行为的进程, 这个进程拥有所有属于它的资源. 但在使用线程完成单个任务时, 其所使用的资源往往只是这个进程所属资源的一个子集. 由于对 资源的控制粒度!!! 只能细化到 进程级别!!!, 因此不可能对单个线程进行独立的资源控制. 而对需要多线程协作完成的任务进行资源的统计和控制就更加难以实现.

其它主要的限制来自于资源控制范围线程调度策略任务涉及线程差异等在内的多个方面. 例如, 系统很少网络资源的使用进行控制, 必然造成对涉及网络使用的进程的资源统计数据的变差, 进而造成资源调度的不准确. 同样的, 线程调度中的中断抢占机制会导致计算线程运行时间的偏差, 也会引发类似问题.

1.1.2 延时处理机制: 进程与资源绑定

学术界提出了延时处理机制(Lazy Receiver Processing), 将 进程!!! 视为完成某个任务的核心. 将网络等资源的使用进程联系起来, 从而提高了资源统计的精确度.

但该机制仍然无法彻底解决线程不是资源控制和统计单元(unit of resource)的问题.

1.1.3 资源容器: 资源容器与任务对应

资源容器概念最早在1999年提出, 主要为了提高应用程序对系统资源的的控制和管理能力. 基于资源容器的系统可以将系统中资源主体(resource principal)从运行主体(即进程)中剥离(process abstraction)出来, 从而达到对系统资源进行更精确和高效控制的目的.

作为抽象的操作系统载体, 资源容器可以拥有一个或多个进程在完成某个任务过程中所使用的所有资源. 因此, 资源主体不再静态地绑定到进程. 进程及其产生的线程与资源主体的关系是动态的、可调整的. 甚至来自多个不同进程的线程也可以同时属于一个资源容器.

资源容器任务相对应!!!, 记录下任务在执行过程中所消耗的所有资源, 包括CPU、内存和网络等. 这样就可以根据这些信息实现对资源的合理调度和控制. 资源容器通过引入子资源容器概念可以将任务分解并归类容器组进行管理, 子资源依照一定规则实现资源共享, 提高灵活性.

1.1.4 基于容器的虚拟化技术: 资源主体和运行主体剥离

基于容器的虚拟化技术通过借鉴资源容器的核心思想, 将系统中的资源主体运行主体(即虚拟机)中剥离, 从而达到在虚拟化技术上系统资源进行精确和高效控制的目的. 虚拟机监控器负责对 系统中所有资源容器!!! 进行管理和控制, 根据用户配置以及系统资源使用的实际情况进行合理分配和回收, 实现跨虚拟机的进程间资源共享!!!.

但这样的资源控制机制仍然存在安全隐患.

1.2 安全容器

克服资源共享带来的安全隐患的有效方法, 是采用一套可靠的访问控制机制来防止非法的资源共享.

强制访问控制(Mandatory Access Controller, MAC)是早期的访问控制机制, 它通过在所有的系统对象上添加有管理员制定的安全策略来限制正在执行的程序的访问权限, 从而阻止恶意程序破坏的传播.

该方法存在很多限制,

  • 首先由于采用了基于安全分级安全机制, 因此只能实现一些普遍的安全策略, 无法针对单个程序提出不同的安全策略;
  • 其次, 它对数据和程序的完整性, 以及程序的职能范围无法进行有效地控制.

在此基础上, 研究者提出一种名为FlaskMAC架构, 实现了将安全策略逻辑安全机制分离, 从而能够提供更便捷的安全策略设置和调整, 以满足不同程序对安全策略的要求.

SELinux则是在MAC机制在Linux上的实现, 它涵盖了对进程文件套接字在内的多种系统资源访问控制. 通过引入域、角色和类型等概念实现对安全策略的细化和精确定制.

虚拟化技术因其卓越的进程和系统资源隔离能力在发展初期就被用来实现对应用程序的访问控制. 将应用程序置于相对独立的运行环境中, 由虚拟机监控器依照制定的策略实现程序间的访问控制.

上面的访问控制机制的实现, 往往依赖OS本身的基于保障机密性和完整性的信息隔离机制. 但是, 这种信息隔离机制却可能被不法程序通过特殊手段绕过, 使得访问控制机制形同虚设, 而直接对上层应用程序进行篡改和攻击. 造成这种潜在威胁的根源在于访问控制机制未能从操作系统中剥离出来.

通过对资源容器的借鉴, 学术界提出安全容器概念. 核心思想在于将访问控制机制从OS中剥离出来独立于运行环境, 依据不同的安全策略形成虚拟的安全容器. 在资源容器的基础上, 对包括系统进程文件系统网络和进程间通信等在内的系统资源进行访问控制. 例如, Sun的Solaris系统中, 提供了这样的访问控制支持(Solaris Zones). 每个应用程序被置于一个独立的运行环境中, 各自拥有自己独立的文件系统(整个文件系统的一个子集), 网络和设备则根据需要虚拟出来, 进程间通信也被严格控制. 各个程序就像运行在一个安全的容器里面, 具有较强的访问控制能力.

基于容器的虚拟化技术借鉴了安全容器的思想, 在使用资源容器实现资源共享的基础上通过安全容器技术实现对共享资源的有效访问控制. 按不同的安全对象, 例如域、应用程序和虚拟机等分配不同的可访问资源形成虚拟的安全容器, 防止其他对象对其资源进行恶意的、未授权的访问.

2 基于容器的虚拟化技术

基于容器的系统需要一个共享的虚拟操作系统镜像. 镜像中包括一个唯一的根文件系统, 一系列可执行的系统文件和库文件, 以及其它建立虚拟机所需要的资源. 任意一个虚拟机都可以像单机的OS一样进行重启、关机等操作.

如图9-1, 基于容器的系统架构由两个平台组成: 宿主平台虚拟平台.

宿主平台主要由一个共享的操作系统镜像一个特权级虚拟机组成. 管理员通过特权级虚拟机对客户虚拟机进行管理.

虚拟平台若干客户虚拟机组成, 在客户虚拟机平台上运行的程序与直接运行在物理机上的程序在行为上没有本质差别.

上面所述的一些基于容器的系统特性和Hypervisor模型下的虚拟机的系统特性类似, 而它们的主要区别在于实现程序独立性的方法. 图9-2给出了两者在安全独立性和资源独立性上的不同结构.

基于容器的系统在实现安全独立性直接使用了操作系统的内部对象(如PID、UID等). 如何安全使用这些对象需要遵循以下两个要点: 命名空间的分开; 控制访问(如使用过滤器).

在实现"命名空间分开"上, 全局的标识符保存在完全不同的空间内, 并且各自的空间不存在指针引用其他空间的对象. 这样一来, 全局的标识符就变成各自虚拟机空间独立的标识符.

对于"控制访问"的实现, 主要依靠对虚拟机访问内核对象权限进行动态检查.

Hypervisor系统中安全独立性的实现也是通过命名空间和访问控制来实现的, 但更多的是基于包括虚拟内存空间、PCI总线地址和特权指令在内的硬件层. 基于容器的系统和基于Hypervisor模型的系统在资源独立性的实现上大致一致, 都需要将诸如CPU周期、I/O带宽等物力资源进行虚拟产生多份虚拟资源.Hypervisor系统比较有代表性的Xen虚拟机监控器系统和基于容器系统的Linux-VServer系统都是通过苏主虚拟机来管理网络和硬盘I/O的, 两个系统的差别仅仅在于如何映射资源.

1. 基于容器的虚拟化技术

1. 基于容器的虚拟化技术

下面以Linux-VServer为例, 具体介绍资源独立性和安全独立性等问题

2.1 资源独立性

资源的独立性主要由CPU分配I/O分配储存分配三部分组成。无论哪种资源的分配, 公平性总是首先被考虑的, 这是资源独立性的核心. 当然, 如何高效利用资源避免浪费也是一个需要考虑的因素. 不同的系统会有不同的实现, 但是其遵循的原则是类似的.

Linux-Vserver的CPU分配、I/O分配和储存分配根据以下原则实现。

2.1.1 CPU分配

Linux-Vserver的CPU分配是在优先级的基础上公平分配CPU资源. 具体方法是在标准Linux调度器上添加标记过滤器(Token Bucket Filter, TBF), 然后为每个虚拟机设定运行级别来限定其占用的事件, 即标记(Token), 级别高的标记值就相对较高. 当虚拟机占用CPU运行该虚拟机上的进程时, 它所拥有的标记值就会持续减少. 当某个虚拟机的标记值降为0时, 它的进程就会从可执行队列里面去除, 直到它再次获得足够的标记量以重返可执行队列. 每个虚拟机

2.1.2 I/O资源

Linux-Vserver同样也用基于标记的方法来分配I/O资源. 在网络I/O资源的使用上, 每个虚拟机的标记同样需要设定"预定"和共享"剩余I/O资源"两个属性. 遵循类似于

2.1.3 硬盘和内存资源

2.2 安全独立性