Development On Apple Silicon with Lima
In this article, I'll demonstrate how to provision a Virtual Machine for software development that currently lacks support for Apple silicon. I'll be utilizing Lima VMs to establish development and testing environments specifically tailored for the cri-o project.
Installation #
It's better to install Lima
with brew
, follow the instruction here.
Create VM #
Next step is create a VM:
limactl create crio
INFO[0000] Creating an instance "crio" from template://default (Not from template://crio)
WARN[0000] This form is deprecated. Use `limactl create --name=crio template://default` instead
? Creating an instance "crio" [Use arrows to move, type to filter]
Proceed with the current configuration
> Open an editor to review or modify the current configuration
Choose another template (docker, podman, archlinux, fedora, ...)
Exit
Choose the "Open an editor to review or modify the current configuration" option to review and modify the VM configuration. (Ensure the $EDITOR
variable is declared to utilize this option).
The arch
option:
arch: x86_64
If you choose wrong arch option the following error will be raised:
INFO[0028] Starting the instance "crio" with VM driver "qemu"
INFO[0028] QEMU binary "/opt/homebrew/bin/qemu-system-aarch64" seems properly signed with the "com.apple.security.hypervisor" entitlement
FATA[0023] [skipped to download: "https://cloud-images.ubuntu.com/releases/23.10/release-20240125/ubuntu-23.10-server-cloudimg-amd64.img": unsupported arch: "x86_64"]
As you can see from the lima.yaml
file, the default template is Ubuntu 23.10
on x86_64
.
We'll use unstable artifacts from the kubic repository.
Lets mount the directory with project:
mounts:
# Location of cri-o repository
- location: "~/Documents/dev/opensource/cri-o"
writable: true
Next add provision scripts in order to install all needed runtime dependencies:
Upgrade the instance on boot
upgradePackages: true
The provision
option, this part follows the install.md guide:
provision:
# `system` is executed with the root privilege
- mode: system
script: |
#!/bin/bash
# Install deps
set -eux -o pipefail
export DEBIAN_FRONTEND=noninteractive
export OS=xUbuntu_22.04
export VERSION=1.24
echo "deb [signed-by=/usr/share/keyrings/libcontainers-archive-keyring.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
echo "deb [signed-by=/usr/share/keyrings/libcontainers-crio-archive-keyring.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list
mkdir -p /usr/share/keyrings
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-archive-keyring.gpg
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-crio-archive-keyring.gpg
apt-get update -qq && apt-get install -y \
libbtrfs-dev \
containers-common \
git \
bats \
libassuan-dev \
libdevmapper-dev \
libglib2.0-dev \
libc6-dev \
libgpgme-dev \
libgpg-error-dev \
libseccomp-dev \
libsystemd-dev \
libselinux1-dev \
pkg-config \
go-md2man \
cri-o-runc \
libudev-dev \
software-properties-common \
gcc \
make
# Install golang
wget https://go.dev/dl/go1.21.0.linux-amd64.tar.gz -O go.tar.gz
tar -C /usr/local -xzvf go.tar.gz
rm -rf go
echo 'export GOROOT=/usr/local/go' >> ~/.profile
echo 'export GOPATH=$HOME/go' >> ~/.profile
echo 'export PATH=$GOPATH/bin:$GOROOT/bin:$PATH' >> ~/.profile
# `user` is executed without the root privilege
- mode: user
script: |
#!/bin/bash
set -eux -o pipefail
echo 'export GOROOT=/usr/local/go' >> ~/.bashrc
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export PATH=$GOPATH/bin:$GOROOT/bin:$PATH' >> ~/.bashrc
Now everything is ready to bootstrat our VM, close editor start the VM:
limactl start crio
INFO[0000] Using the existing instance "crio"
INFO[0000] Starting the instance "crio" with VM driver "qemu"
INFO[0000] [hostagent] hostagent socket created at /Users/user/.lima/crio/ha.sock
INFO[0001] [hostagent] Using system firmware ("/opt/homebrew/share/qemu/edk2-x86_64-code.fd")
INFO[0001] [hostagent] Starting QEMU (hint: to watch the boot progress, see "/Users/user/.lima/crio/serial*.log")
INFO[0001] SSH Local Port: 52867
INFO[0001] [hostagent] Waiting for the essential requirement 1 of 4: "ssh"
INFO[0041] [hostagent] Waiting for the essential requirement 1 of 4: "ssh"
INFO[0051] [hostagent] Waiting for the essential requirement 1 of 4: "ssh"
INFO[0061] [hostagent] Waiting for the essential requirement 1 of 4: "ssh"
INFO[0067] [hostagent] The essential requirement 1 of 4 is satisfied
INFO[0067] [hostagent] Waiting for the essential requirement 2 of 4: "user session is ready for ssh"
INFO[0107] [hostagent] Waiting for the essential requirement 2 of 4: "user session is ready for ssh"
INFO[0147] [hostagent] Waiting for the essential requirement 2 of 4: "user session is ready for ssh"
INFO[0188] [hostagent] Waiting for the essential requirement 2 of 4: "user session is ready for ssh"
INFO[0228] [hostagent] Waiting for the essential requirement 2 of 4: "user session is ready for ssh"
INFO[0268] [hostagent] Waiting for the essential requirement 2 of 4: "user session is ready for ssh"
You can check the logs of VM here:
tail -f /Users/user/.lima/crio/serial.log
If everything is functioning properly, after starting the VM, executing the limactl shell crio
command should open a shell and process the last commands.
sudo -i
git clone https://github.com/containers/conmon
cd conmon
env "PATH=$PATH" make
env "PATH=$PATH" make install
# Link runc to tests
ln -s /usr/local/bin/runc /usr/bin/runc
Lets start some tests:
# We need pass PATH variable to the sh shell
sudo -E env "PATH=$PATH" make testunit
Tip 🆒
How to configure lima
and VSCode : Remote - SSH
plugin.
Happy coding!