该文章随时会有校正更新,公众号无法更新,欢迎订阅博客查看最新内容:https://fuckcloudnative.io
前言
之前我给大家介绍过如何在 macOS 上使用 multipass 创建轻量级虚拟机来使用 Podman,众小伙伴纷纷齐说真香。今天我要给大家介绍一个全新的黑科技,利用 macOS Big Sur 引入的全新虚拟化框架Virtualization Kit[1]来创建更加轻量级的虚拟机。准确地说,这个最新的虚拟化框架并不能直接使用,它只是提供了 API,为许多设备类型定义了标准接口,包括网络、存储等设备,且支持 Virtio 标准。要想使用该框架来创建管理虚拟机,需要对其进行封装,构建出一个易于使用的工具,目前最优秀的就是vftool[2]。
下面就来看看如何使用 vftool 来创建 Ubuntu 虚拟机。
1. 编译 vftool
vftool[3]使用的是 Swift 语言,要想成功编译出可执行文件,需要安装 Xcode 命令行工具,你可以通过下面的命令直接安装:
$ xcode-select--install
或者到官方网站下载安装:https://developer.apple.com/download/more/[4]
或者你也可以直接安装 Xcode。
安装好 Xcode 命令行工具后,就可以拉取 vftool 仓库进行编译了:
$gitclonehttps://github.com/evansm7/vftool.git$clang -framework Foundation -framework Virtualization vftool/vftool/main.m -o /usr/local/bin/vftool
后面创建虚拟机的时候,你可能会遇到以下的报错:
Configuration vaildation failure! Error Domain=VZErrorDomain Code=2“Virtualizationrequiresthe “com.apple.security.virtualization” entitlement” UserInfo={NSDebugDescription=Virtualizationrequiresthe “com.apple.security.virtualization” entitlement}
这是因为编译完成后需要对二进制文件进行签名,而签名是需要授权的,所以需要创建一个自签名证书。打开钥匙串访问,依次选择证书助理-->创建证书:
选择证书类型为代码签名,名字随便写,然后点击创建:
然后利用新建的自签名证书对二进制文件进行签名:
$codesign --entitlements vftool/vftool/vftool.entitlements -s""/usr/local/bin/vftool
除了上面的方法之外,还有一种编译方法,直接运行以下命令:
$ xcodebuild$cp build/Release/vftool /usr/local/bin/vftool
现在就可以使用这个二进制文件来创建虚拟机了。
2. 准备镜像文件
需要准备三个文件:
kernel:https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic[5]
initrd:https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-initrd-generic[6]
disk image:https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.tar.gz[7]
下载相关文件:
$ mkdir -p ~/bin/vm$ cd ~/bin/vm$ wget https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic$ wget https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-initrd-generic$ wget https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.tar.gz$ mv ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic vmlinux$ mv ubuntu-20.04-server-cloudimg-amd64-initrd-generic initrd$ tar xvfz ubuntu-20.04-server-cloudimg-amd64.tar.gz
创建数据盘:
$ ddif=/dev/zeroof=data.img bs=1m count=51200
3. 修改虚拟机网段
如果你想自定义虚拟机的网段,可以直接修改文件 /Library/Preferences/SystemConfiguration/com.apple.vmnet.plist。例如修改为:
Shared_Net_Address192.168.64.1Shared_Net_Mask255.255.255.0
3. 创建虚拟机
直接通过 vftool 创建虚拟机:
$vftool\-kvmlinux\-iinitrd\-cfocal-server-cloudimg-amd64.img\-ddata.img\-m2048\-a"console=hvc0"2021-01-1413:27:08.223vftool[66147:839169]vftool(v0.310/12/2020)starting2021-01-1413:27:08.223vftool[66147:839169]+++kernelatvmlinux,initrdatinitrd,cmdline'console=hvc0',1cpus,2048MBmemory2021-01-1413:27:08.224vftool[66147:839169]+++fd3connectedto/dev/ttys0002021-01-1413:27:08.224vftool[66147:839169]+++Waitingforconnectionto:/dev/ttys000
从日志信息可以看到该虚拟机连接的 TTY,我这里是 /dev/ttys000。打开一个新的终端窗口,连接该 TTY,然后执行一系列命令来进行初始化操作:
$ screen /dev/ttys000(initramfs) ddif=/dev/vdaof=/dev/vdbbs=1024k &(initramfs) mkdir /mnt(initramfs) mount /dev/vdb /mnt(initramfs) chroot /mntroot@(none):/# touch /etc/cloud/cloud-init.disabledroot@(none):/# echo 'root:root' | chpasswdroot@(none):/# echo "podman" >/etc/hostnameroot@(none):/# ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsaroot@(none):/# ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsaroot@(none):/# ssh-keygen -f /etc/ssh/ssh_host_ed25519_key -N '' -t ed25519root@(none):/# cat < /etc/netplan/01-dhcp.yamlnetwork:renderer:networkdethernets:enp0s1:dhcp4:noaddresses:[192.168.64.2/24]gateway4:192.168.64.1nameservers:addresses:[114.114.114.114]version:2EOFroot@(none):/# echo "PermitRootLogin yes" >> /etc/ssh/sshd_configroot@(none):/# sed -i "/^PasswordAuthentication/ c PasswordAuthentication yes" /etc/ssh/sshd_configroot@(none):/# exit(initramfs) umount /dev/vda
上面的步骤总共干了这么几件事:
挂载硬盘
禁用 cloud-init
设置主机名和 ssh 秘钥
设置网络
设置 ssh 允许使用 root 用户和密码登录
然后在运行 vftool 命令的窗口中按 CTRL-C 来关闭虚拟机。
接着使用新的硬盘来启动虚拟机:
$ vftool \ -k vmlinux \ -i initrd \ -ddata.img \ -m2048\ -a"console=hvc0 root=/dev/vda"\ -t0
打开一个新的终端窗口,通过 ssh 连接虚拟机,调整硬盘容量,移除不必要的组件:
$ ssh root@192.168.64.2# login as rootroot@podman:~# systemctl disable --now snapd.service snapd.socketroot@podman:~# resize2fs /dev/vdaroot@podman:~# apt remove -y cloud-init cloud-initramfs-copymods cloud-initramfs-dyn-netconf cloud-guest-utils popularity-contest
看看它的内存占用:
果然很香!
4. 开机自启
MacOS 可以使用 launchctl 来管理服务,它可以控制启动计算机时需要开启的服务,也可以设置定时执行特定任务的脚本,就像 Linux crontab 一样, 通过加装 *.plist 文件执行相应命令。Launchd 脚本存储在以下位置, 默认需要自己创建个人的 LaunchAgents 目录:
~/Library/LaunchAgents : 由用户自己定义的任务项
/Library/LaunchAgents : 由管理员为用户定义的任务项
/Library/LaunchDaemons : 由管理员定义的守护进程任务项
/System/Library/LaunchAgents : 由 MacOS 为用户定义的任务项
/System/Library/LaunchDaemons : 由 MacOS 定义的守护进程任务项
我们选择在 ~/Library/LaunchAgents/ 目录下创建 vftool.ubuntu.plist 文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>LabelubuntuProgramArguments/bin/bash-c$HOME/bin/vm/start.shStandardOutPath/var/log/vftool.ubuntu.stdout.logStandardErrorPath/var/log/vftool.ubuntu.stderr.logKeepAliveRunAtLoad
创建启动脚本:
$cd~/bin/vm$ cat
创建日志文件:
$ touch /var/log/vftool.ubuntu.stdout.log$ touch /var/log/vftool.ubuntu.stderr.log$ sudo chmod a+rw /var/log/vftool.ubuntu.stdout.log$ sudo chmod a+rw /var/log/vftool.ubuntu.stderr.log
设置开机自动启动 Ubuntu 虚拟机:
$ launchctl load -w ~/Library/LaunchAgents/vftool.ubuntu.plist
启动服务:
$ launchctl start ubuntu
查看服务:
$ launchctl list ubuntu{"StandardOutPath"="/var/log/vftool.ubuntu.stdout.log";"LimitLoadToSessionType"="Aqua";"StandardErrorPath"="/var/log/vftool.ubuntu.stderr.log";"Label"="ubuntu";"OnDemand"=false;"LastExitStatus"= 256;"PID"= 50797;"Program"="/bin/bash";"ProgramArguments"= ("/bin/bash";"-c";"$HOME/bin/vm/start.sh"; );};
大功告成,现在就可以通过 ssh 连接虚拟机了:
$ ssh root@192.168.64.2
参考
Building x86_64 Docker Containers on Apple Silicon[8]
Containerized the Apple Silicon[9]
Ubuntu Server fails[10]
参考资料
[1]
Virtualization Kit:https://developer.apple.com/documentation/virtualization
[2]
vftool:https://github.com/evansm7/vftool
[3]
vftool:https://github.com/evansm7/vftool
[4]
https://developer.apple.com/download/more/:https://developer.apple.com/download/more/
[5]
https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic:https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic
[6]
https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-initrd-generic:https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-initrd-generic
[7]
https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.tar.gz:https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.tar.gz
[8]
Building x86_64 Docker Containers on Apple Silicon:https://medium.com/swlh/building-x86-64-docker-containers-on-apple-silicon-a6d868a18f37
[9]
Containerized the Apple Silicon:https://bee42.com/de/blog/tutorials/containerized-the-apple-silicon/
[10]
Ubuntu Server fails:https://github.com/evansm7/vftool/issues/2