初识容器之云虚拟化与容器

634 阅读9分钟

前言

        容器化也被称为操作系统层虚拟化,是一种虚拟化技术,这种技术将操作系统内核虚拟化,可以允许用户空间软件实例(instances)被分割成几个独立的单元,在内核中运行,而不是只有一个单一实例运行。

        目前作者组内正在进行服务容器化改造,而使用一个技术最好是要知其所以然,本篇文章基于自身对于容器与云虚拟化技术的认知,对比两种技术的相关实现,并且介绍容器的一些基础知识,来认识容器。

正文

云服务及虚拟化

        一个对于云计算服务的官话解释:是一种基于互联网、将分散的各种IT资源集中起来形成共享资源池,并且以动态、弹性的方式为用户提供大规模计算、存储服务的计算模式和商业模式。各个企业都在上云,云到底提供的什么层次的服务?

旧服务架设

        在使用云服务之前,我们的应用服务由下及上多层都需要自己来建设。从硬件设备购买、服务器内核操作系统搭建,服务部署等都需要自行解决。

非云服务.jpg

三层不同的云服务

        云计算概念引入后,大概可分为三种层次模型提供相应IT服务,如下图所示: 三层云服务.jpg

  1. 第一种最为基础,是叫做基础设施即服务IaaS(Infrastructure-as-a-Service),这种提供最基础层次的云服务较为常见,我们个人或企业在XX云上购买的各种虚机服务器就是提供的Iaas服务,在购买服务时我们仅需要对机器硬件配置做出选择,无需考虑高昂的维护成本,在购买完虚拟机后自行选择安装机器内核与操作系统。

        前几年比较火的开源IaaS框架OpenStack就是基于IaaS做的,其基本原理为:在各个宿主机上启用虚拟化服务,将宿主物理机的计算资源、内存资源、存储资源、网络资源等通过虚拟化的方式构建出一个大的资源池,然后IaaS服务再基于这个大池子做出对应的资源分配,比如分配出一台50硬盘、4核、8G的虚拟机。

  1. 平台即服务PaaS(Platform-as-a-Service)相对IaaS忽略了硬件与内测相关的细节,只是提供了一个应用运行的基本平台,而我们在构建自身服务时仅需要关注最外层的操作系统层面即可,这层也是对应的我们的容器服务层。

  2. 软件即服务SaaS(Software-as-a-Service)则是直接提供了从上到下的整个业务解决方案,无需关注各个层面的架构搭建、数据存储等问题,仅需要对于自身业务进行个性化配置即可。这种服务更多的出现在to B的业务场景中,投票、点餐系统比比皆是。

        这三层服务的抽象程度递增,需要业务研发人员关注的点递减,可以解放更多的人力。但对于繁多的业务场景来说,对应的统一抽象的内容越多,可复用或者定制化程度会变的越低,这也是需要我们在去选型时需要权衡的问题。

容器技术

        前面提到三层的云服务模型,其中PaaS与容器化服务是对应的,构建容器服务时我们无需关心底层硬件以及内核版本,可以把精力更多的放在应用上。

容器操作系统虚拟化

        容器需要通过构建出基础镜像来启动,基础镜像中的内容主要包括操作系统、对应应用软件,乍一看上去跟虚拟机(IaaS服务核心)挺像的,都是通过镜像启动,构建出一个独立隔离的空间,然后在内部运行服务。但是容器还是与虚拟机有着本质的区别,如下图所示,虚拟机是基于宿主机的虚拟化能力,完全构建出来了对应的虚拟化硬件,又基于硬件搭建内核、操作系统等,是一个相当重量级的虚拟化实现;而容器技术则只是对于操作系统进行封装,与对应宿主机共用内核、硬件,相当的轻量级,镜像中无需包含内核实现,在启动速度上也有一个明显的差异,虚拟机启动是在分钟级,而搭载了应用的容器服务在秒级就能启动。 虚拟机与容器对比.jpg

容器资源隔离

        既然是需要为每个应用构建出独立隔离的运行环境,资源隔离自然就有内存、cpu、进程、文件系统、网络等,那么虚拟机技术是我们能够想到的正常套路,而容器是如何实现资源隔离的?那么就要从linux内核在某个版本提供的两大特性说起:Cgroup和namespace,这两大特性,分别提供了资源(硬件)控制与资源封装的能力。

       Cgroup(Control group)是Linux内核提供的一个特性,用于限制和隔离一组进程对系统资源的使用。对不同资源的具体管理是由各个子系统分工完成的。对于不同子系统可以限制的Cgroup进程组资源列表如下:

子系统限制资源
cpu限制Cgroup的cpu使用率
memory统计和限制cgroup的内存的使用率,包括swap
devicesCgroup设备访问控制
blkio限制Cgroup io频次
net_prio限制进程网络流量优先级
......

       namespace是将内核的全局资源做封装,使得每个namespace都有一份独立的资源,因此不同的进程在各自的namespace内对同一种资源的使用互不干扰。

namespace资源隔离
Network隔离网络资源
IPC隔离 System V IPC 和 POSIX 消息队列
PID隔离进程ID
User隔离用户及用户组
......

        还有很多Cgroup与namespace一些更具体的系统调用细节,就不展开讲了。

        基于这两个内核特性,我们可以使用linux内核对于某个进程的资源进行隔离与限制,而仅有这两个功能,我们还是无法实现当前容器中独立的文件系统视角(与宿主机隔离的文件系统),另外一个技术就是rootfs(根文件系统),一个rootfs就是对应的容器镜像,包含镜像对应操作系统的基础目录 /bin,/etc,/proc等。而rootfs也分为只读层和可读写层,只读层就是我们的基础镜像文件,而可读写层允许我们基于镜像对文件作出变更,每次的变更都是增量的文件层级累加。

        以上的三个功能我们便实现了容器最基本的能力,资源隔离、限制、独立文件系统。那么docker 引擎则是对于这些能力的一个很好的封装,用户仅需要使用docker的api就能完整的控制一个容器的生命周期。

其他问题

        在学习容器的一些基本原理时,我会有一些疑问,比如:容器与宿主机共用内核,如何解决操作系统及版本不一致问题

  1. centos6 宿主机启动 ubuntu 16镜像的容器         linux基于硬件提供的用户级api其实是划分了两层,linux内核发行版与操作系统发行版,这两个是分离概念,所以我们有时候会遇到linux内核漏洞时,不升级操作系统版本,仅升级内核版本完成最小改动的问题修复。而容器正是利用了这一点,rootfs里就是对应操作系统的发行版,可以在任何满足需求的内核版本上运行。但是当一些内核版本未能支持操作系统新特性时,一般就会报错无法启动了。

  2. windows和mac os生态下的linux系统镜像

        如果说linux内核的基础上启动容器是复用宿主机内核,那么近些年来docker在windows、mac os上也陆续支持了容器特性,是如何实现的?原理就是doker做了差异化实现如下图所示,如果是windows宿主机启动windows镜像,那么会利用windows本身的Windows Server Container技术去隔离和限制进程;如果启动的是linux镜像,则需要宿主机的虚拟化功能了,Hyper-V启动一个linux虚拟机,然后基于此虚拟机提供相应linux基础容器镜像的功能,相当于绕了一圈摒弃了容器的性能但是保留了其跨平台的特性。

docker容器其他概念

        除了镜像,对于docker集群服务来讲,还有podnode的概念。如下图所示,为node、pod、container(容器)的层级关系,node就是宿主机的概念,可以基于node分配划分pod,pod中可以启多个容器,pod中的资源可以共享,因此可以用来辅助做另外一个容器中的中间件功能,比如协助做日志清理,微服务的服务注册发现等(service mesh中的side car)。

结语

        本文基于作者对于容器从零开始学习的过程,学习过程中也对于组内运维老师请教了不少关于隔离与内核版本支持的相关问题,对比了云服务虚拟化与容器的相关实现,其中对于容器中资源隔离、资源限制、根文件系统等实现原理做了分享与概述,希望能够对大家在容器最初认知学习中有所帮助。

参考

docker精简版 容器基本技术namespace Linux Cgroup系列:Cgroup概述