前言

之前我给大家介绍过如何在 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 仓库进行编译了:

$ git clone https://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 “Virtualization requires the “com.apple.security.virtualization” entitlement” UserInfo={NSDebugDescription=Virtualization requires the “com.apple.security.virtualization” entitlement}

这是因为编译完成后需要对二进制文件进行签名,而签名是需要授权的,所以需要创建一个自签名证书。打开钥匙串访问,依次选择 证书助理 --> 创建证书

百度网盘再次回收免费空间!21日前赶紧登录下!网友评:想钱想疯了?

选择证书类型为 代码签名,名字随便写,然后点击创建:

从 HTTP 到 HTTP/3 的发展简史

然后利用新建的自签名证书对二进制文件进行签名:

$ codesign --entitlements vftool/vftool/vftool.entitlements -s "<NAME ON CERTIFICATE>" /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

创建数据盘:

$ dd if=/dev/zero of=data.img bs=1m count=51200

3. 修改虚拟机网段

如果你想自定义虚拟机的网段,可以直接修改文件 /Library/Preferences/SystemConfiguration/com.apple.vmnet.plist。例如修改为:

        <key>Shared_Net_Address</key>
        <string>192.168.64.1</string>
        <key>Shared_Net_Mask</key>
        <string>255.255.255.0</string>

3. 创建虚拟机

直接通过 vftool 创建虚拟机:

$ vftool \
  -k vmlinux \
  -i initrd \
  -c focal-server-cloudimg-amd64.img \
  -d data.img \
  -m 2048 \
  -a "console=hvc0"

2021-01-14 13:27:08.223 vftool[66147:839169] vftool (v0.3 10/12/2020) starting
2021-01-14 13:27:08.223 vftool[66147:839169] +++ kernel at vmlinux, initrd at initrd, cmdline 'console=hvc0', 1 cpus, 2048MB memory
2021-01-14 13:27:08.224 vftool[66147:839169] +++ fd 3 connected to /dev/ttys000
2021-01-14 13:27:08.224 vftool[66147:839169] +++ Waiting for connection to:  /dev/ttys000

从日志信息可以看到该虚拟机连接的 TTY,我这里是 /dev/ttys000。打开一个新的终端窗口,连接该 TTY,然后执行一系列命令来进行初始化操作:

$ screen /dev/ttys000
<LOTS OF OUTPUT>
(initramfs) dd if=/dev/vda of=/dev/vdb bs=1024k &
(initramfs) mkdir /mnt
(initramfs) mount /dev/vdb /mnt
(initramfs) chroot /mnt

root@(none):/# touch /etc/cloud/cloud-init.disabled
root@(none):/# echo 'root:root' | chpasswd
root@(none):/# echo "podman" >/etc/hostname
root@(none):/# ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
root@(none):/# ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa
root@(none):/# ssh-keygen -f /etc/ssh/ssh_host_ed25519_key -N '' -t ed25519
root@(none):/# cat <<EOF > /etc/netplan/01-dhcp.yaml
network:
    renderer: networkd
    ethernets:
        enp0s1:
            dhcp4: no
            addresses: [192.168.64.2/24]
            gateway4: 192.168.64.1
            nameservers:
                addresses: [114.114.114.114]
    version: 2
EOF

root@(none):/# echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
root@(none):/# sed -i "/^PasswordAuthentication/ c PasswordAuthentication yes" /etc/ssh/sshd_config

root@(none):/# exit
(initramfs) umount /dev/vda

上面的步骤总共干了这么几件事:

  • 挂载硬盘

  • 禁用 cloud-init

  • 设置主机名和 ssh 秘钥

  • 设置网络

  • 设置 ssh 允许使用 root 用户和密码登录

然后在运行 vftool 命令的窗口中按 CTRL-C 来关闭虚拟机。

接着使用新的硬盘来启动虚拟机:

$ vftool \
  -k vmlinux \
  -i initrd \
  -d data.img \
  -m 2048 \
  -a "console=hvc0 root=/dev/vda" \
  -t 0

打开一个新的终端窗口,通过 ssh 连接虚拟机,调整硬盘容量,移除不必要的组件:

$ ssh root@192.168.64.2
# login as root
root@podman:~# systemctl disable --now snapd.service snapd.socket
root@podman:~# resize2fs /dev/vda
root@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"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>ubuntu</string>
    <key>ProgramArguments</key>
    <array>
      <string>/bin/bash</string>
      <string>-c</string>
      <string>$HOME/bin/vm/start.sh</string>
    </array>
    <key>StandardOutPath</key>
    <string>/var/log/vftool.ubuntu.stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/vftool.ubuntu.stderr.log</string>
    <key>KeepAlive</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
  </dict>
</plist>

创建启动脚本:

$ cd ~/bin/vm
$ cat <<EOF > start.sh
#!/bin/bash

/usr/local/bin/vftool \
  -k $HOME/bin/vm/vmlinux \
  -i $HOME/bin/vm/initrd \
  -d $HOME/bin/vm/data.img \
  -m 2048 \
  -a "console=hvc0 root=/dev/vda" \
  -t 0
EOF
$ chmod +x start.sh

创建日志文件:

$ 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

听过云原生玩家都关注了他

后台回复◉k8s◉获取史上最方便快捷的 Kubernetes 高可用部署工具

只需一条命令,连 ssh 都不需要!

往期推荐

百度网盘再次回收免费空间!21日前赶紧登录下!网友评:想钱想疯了?

从 HTTP 到 HTTP/3 的发展简史

他总在逆风翻盘,绝地反击!最不爱钱却成了最有钱的人...

开发文件上传功能稍不注意就会引发安全漏洞

IDEA不能一个窗口管理多个项目?那是你不会用!

Nacos 惊爆安全漏洞,可绕过身份验证(附修复建议)


Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐