从操作系统内核到产品部署(一)

从操作系统内核到产品部署理解

Posted by Jingming on November 12, 2020

这篇主要是整理下从操作系统内核到软件产品部署的理解要点。

一、操作系统内核

操作系统是介于应用程序和硬件的中间的软件层。操作系统内核就是操作系统的核心,也就是操作系统作为中间层该做的事,包括:

文件系统,进程调度,内存管理,网络系统等。非内核的部分,例如UI。

二、容器技术

例如LXC容器技术,其作用是在同一个内核上运行多个应用程序与系统。

理解:例如有两台电脑,两台电脑同样硬件配置,且都安装了同一版本的Ubuntu操作系统。唯一不同的地方是第一台电脑在安装Ubuntu后,安装了应用程序A,并运行A,创建了文件X; 第二台电脑在安装Ubuntu后,安装了应用程序B,并运行B,创建了文件Y。

仔细思考之后发现,这两台电脑之间的差异其实没有那么大。它们只是文件或者安装的应用程序不同而已,而使用的内核程序和硬件是一模一样的。

那么想法来了:为何不对公共的部分进行复用,而对这种较小的差异进行单独的管理呢?这就是容器技术做的事情。

容器技术把操作系统的非内核部分抽象成容器(类似应用程序的东西),操作系统内核通过LXC容器对这种”容器应用程序”进行切换,从而达到看上去是在运行一组操作系统的效果。

PS.

  • 容器如何把不同操作系统的文件和应用程序隔离开?答:文件打上不同命名空间就可以隔离,应用程序隔离可以使用Linux控制组(cgroups)内核功能控制和限制一个进程或多组进程的资源使用。

  • 一个容器怎么理解?一个容器就理解为一个操作系统备份。LXC之上可以运行多个容器。

三、虚拟化技术

虚拟化技术同容器技术一样也是为了共享硬件,达到运行不同操作系统的技术。

与容器不同之处是,虚拟化强调虚拟,也就是使用软件程序虚拟硬件。也就是说,虚拟化技术特点是可以运行不同的操作系统内核,但是需要加入中间层来模拟硬件(也就是虚拟机软件),因此它没有容器轻便(虚拟机软件占内存很多,例如占100M内存的虚拟机中可能只跑了个1M的应用程序),

但是好处是可以运行不同操作系统内核,能做到一种操作系统运行另一种操作系统的效果,甚至可以让应用程序对此毫无感知。

四、Docker

Docker是基于容器技术(LXC)的技术,作用是让开发者快速的部署应用。

部署的痛点,例如某个软件应用被开发出来了,在部署的时候,不仅要部署该软件,也要部署它的依赖:

(1)软件并不是跨平台的,也就是软件是依赖固定版本的操作系统的,例如windows,mac,安卓等品牌中的某个具体版本的系统,安装软件如果不安装特定操作系统,可能会出现不兼容。

(2)软件依赖于操作系统中的其他软件(例如库和组件),往往对依赖软件的版本都有特定需求。

Docker其实也是一个应用程序软件,但是它究竟提供了什么多于LXC的技术呢?

  • 首先,Docker是为了解决快速部署问题服务的,它解决了部署环境依赖痛点,解决方法说白了就是交付软件产品的时候,不仅交代码,而且要交环境。通过把环境依赖打包,以便复用来提升效率。

这种打包其实就是一种操作系统的备份,再结合利用LXC技术进行轻量部署,产生了1+1大于2的效果。Docker带来明显的好处:省硬件资源(一台机器部署多个不同服务)、 安装轻量(不用安装多个操作系统内核)。

  • 另外,Docker不是个单机应用程序;它有着自己的服务器,就像网络游戏一样,安装在客户机器上的docker应用只是一个客户端,它通过网络链接和背后强大的服务器交互。

例如,服务器可以提供仓库服务,里面有着很多的image镜像,也就是一些经典的操作系统备份,或者说是经典部署备份,可以很方便的下载下来使用。

  • 再次,Docker中的一个容器里面往往只放一个应用程序及其对应的依赖,而LXC之上的一个容器里面往往是放多个应用程序。这样好处是对功能进行拆分,减少耦合性。

Docker使用docker container start来启动一个容器。

  • 最后,仔细思考,为什么Docker可以解决跨平台(宿主机内核可以跑任何镜像)难点?我们知道Docker基于LXC,决定了Docker必须使用宿主机(安装客户端的机器)的内核,而镜像里面本身是没有什么精简内核之类的东西的。

答案是镜像并不依赖于具体的内核环境。做到这样需要以下三点:

第一,image本身就需要使用Docker自己提供的功能来创建,而不是使用其他软件打包环境,提交给Docker。

第二,image依赖的其实是一种内核的最基本功能,说白了,这个功能是一定成熟版本的任何linux内核都提供且能跑的,也就是任何宿主机内核都能提供的。

这种基本功能的其中之一就是:bootfs。bootfs在linux中几乎是一致。bootfs包含bootloader和kernel。作用就是Linux启动的时候,

在没有文件系统之前,加载到正确的kernel,并之后将控制权交换给kernel,之后kernel自己加载合适的文件系统rootfs。

由于rootfs不同操作系统差距较大,因此加载了特殊的rootfs之后,可以理解为这个镜像变成了这种特定的操作系统。

理解:假设我现在使用了某版本ubuntu来进行开发,开发完成后,我下载了Docker,并且准备用Docker打包镜像,那么Docker要做的一点就是 把我当前环境ubuntu的rootfs打包到镜像里面,之后这个镜像即使是在CentOS宿主机上面跑,经过前面的介绍知道,这个镜像最终在容器中运行的时候,其实就是加载了该特定rootfs的ubuntu的环境。

第三,客户端安装时候,对宿主机的内核有要求,版本太低的直接不支持。

PS. 1. Docker使用Dockerfile来制作image,里面定义了把当前环境的什么东西进行打包,包括文件以及暴露的端口等。

有了Docker之后,软件产品的交付方式变了,从交代码,交应用,到交镜像。

  1. 镜像是分层的,也就是说,最基本的操作系统环境,很可能是公用的,那么可以做成基本镜像。

  2. 容器内容:代码、运行时、系统工具、配置、系统库。

  3. 一个Dockerfile对应一个容器,但是实际使用的时候,往往是部署多个容器组成的一个服务, 这个时候需要的是使用compose命令来运行一个服务,这个服务配置文件是docker-compose.yml,其使用YAML格式定义。