Nanos Unikernel入门
2024-04-21
1. Unikernel 概述
1.1. 什么是 Unikernel
Unikernel 是一种专为特定应用构建的轻量级操作系统,将应用程序与操作系统功能紧密集成在一起,形成单一的可执行文件。这种设计可以显著提高性能和安全性,同时减少资源消耗。
-
定义与构成:Unikernel 是从传统的全功能操作系统中剥离出来的,它仅包含运行特定应用程序所必需的最小操作系统组件。这些组件与应用程序代码一起编译,形成一个高度优化和专用的系统映像。
-
性能优化:由于 Unikernel 仅包含必要的操作系统功能,它能够在启动时间、运行效率和响应速度等方面实现显著的性能优势。例如,Unikernel 可以在几毫秒内启动,非常适合需要快速启动和高效运行的环境。
-
安全性提高:Unikernel 的攻击面相对较小,因为它剥离了不必要的代码和服务,从而减少了潜在的安全漏洞。此外,由于每个 Unikernel 都是为特定应用定制的,因此可以实现更细粒度的安全控制。
-
应用场景:
-
云计算:在云平台上,Unikernels 可以提供轻量级、高性能的虚拟机选项,特别适合微服务架构和弹性计算需求。
-
物联网(IoT):对于资源受限的物联网设备,Unikernel 提供了一种有效的方法,可以在保持较低资源消耗的同时,确保设备的响应速度和安全性。
-
边缘计算:在边缘计算场景中,Unikernel 由于其快速启动和低资源消耗的特性,非常适合处理离用户更近的数据处理任务。
-
-
挑战与局限性:
-
兼容性问题:由于 Unikernel 高度专用化,它可能不支持标准的 POSIX 接口,这可能会限制某些应用程序的移植。
-
开发与维护难度:Unikernel 需要针对每个应用定制开发,这可能增加开发和维护的复杂性和成本。
-
1.2. 虚拟机 VS Linux 容器 VS Unikernel
2. Unikernel 现有解决方案及对比
下表是一些仍保持活跃开发的 Unikernel 解决方案
3. Nanos Unikernel
Nanos 是一个 Unikernel 的解决方案,支持较多的编程语言和平台,其主要使用 ops
工具对 Nanos 镜像和实例进行管理和编排,同时还支持 Kibs
插件对其进行扩展。
ops
是一个使用 Go 语言编写的 CLI 工具,地址在 https://github.com/nanovms/ops
3.1. 安装
官方提供了一键安装脚本
curl https://ops.city/get.sh -sSfL | sh
ops version
3.2. 一个最简单的 Demo
这里使用 Node.js 作为编程语言实现
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8083, "0.0.0.0");
console.log('Server running at http://127.0.0.1:8083/');
将上述代码保存为 hi.js
,然后运行
ops pkg load eyberg/node:20.5.0 -p 8083 -f -n -a hi.js
上述命令中各参数含义如下
-
pkg load eyberg/node:20.5.0
: 用于将eyberg/node:20.5.0
作为基础的镜像,可以理解为 Docker 中的基础镜像, -
-p
: 用于映射端口号 -
-f
: 强制从远程拉取最新的镜像 -
-n
: 使用 nightly 通道进行构建 -
-a
: 传递给程序的参数
运行命令后输出:
running local instance
booting /root/.ops/images/node ...
en1: assigned 10.0.2.15
Server running at http://127.0.0.1:8083/
en1: assigned FE80::84D8:EFFF:FEDC:6C5D
3.3. 原理
上述的 Demo 运行过程发生了什么?
首先,我们先将 eyberg/node:20.5.0
这个基础镜像拉取到了本地,它在本地的路径位于 ~/.ops/packages/eyberg/node_20.5.0
,可以查看一下这个目录下有什么内容
# tree
.
├── node
├── package.manifest
├── README.md
└── sysroot
├── lib
│ └── x86_64-linux-gnu
│ ├── libc.so.6
│ ├── libdl.so.2
│ ├── libgcc_s.so.1
│ ├── libm.so.6
│ ├── libpthread.so.0
│ └── libstdc++.so.6
└── lib64
└── ld-linux-x86-64.so.2
4 directories, 10 files
可以看到目录下包含了 node
的二进制文件和其所需要的动态依赖库,其中 sysroot
目录在镜像打包时,会映射到系统的根目录。
而我们上一步运行的程序也会打包成一个二进制文件,使用 ops image list
查看
+------+------------------------+----------+---------------+
| NAME | PATH | SIZE | CREATEDAT |
+------+------------------------+----------+---------------+
| node | /root/.ops/images/node | 114.8 MB | 2 seconds ago |
+------+------------------------+----------+---------------+
可以看到镜像位于 /root/.ops/images/node