evilfactorylabs

Cover image for Isolated Development Environment di Apple Silicon
Rizaldy
Rizaldy

Posted on

Isolated Development Environment di Apple Silicon

Sebagai pembuka, ini perlu banget gue nyebutin chip Apple Silicon (M1) karena jika menggunakan chip Intel harusnya enggak bakal seribet ini.

Sudah lama gue menggunakan remote server sebagai development environment utama gue mengingat spesifikasi PC gue (Intel NUC) sedikit sampah. Sistem operasi utama gue adalah GNU/Linux untuk kebutuhan web app development dan menggunakan Ubuntu karena varian ini yang paling terkenal (dan stabil) sejauh yang gue tau.

Seperti kebanyakan pengembang lain, diri gue sebagai seorang pengembang perangkat lunak pun tidak hanya ketika dari jam 09 sampai 17 aja, di waktu luang ataupun akhir pekan gue terkadang mengembangkan aplikasi juga entah just for fun, pembelajaran, dsb.

Gue lumayan ketat dalam memasang dan menjalankan aplikasi yang ada di komputer gue. Gue rutin memeriksa aplikasi apa saja yang sedang berjalan, apa saja yang membuka koneksi, dan apa saja yang mengirim paket. Disamping itu, kebutuhan penggunaan komputer gue tidak sebatas untuk kepentingan pribadi, melainkan kepentingan pekerjaan juga baik pekerjaan utama ataupun sampingan iseng-iseng berhadiah.

Di tahun 2021 gue berencana melakukan upgrade terhadap mesin tempur yang gue miliki. Sebenarnya tidak terlalu banyak perubahan, hanya core CPU yang sebelumnya 4 menjadi 8, dan arstektur yang tadinya Intel-based menjadi ARM-based jika membandingkan dengan MBA 2015 gue.

Throughput nya? Sangat terasa. I/O speed mesin ini rata-rata nya adalah 2.3 GB/s, berbeda dengan yang sebelumnya (MBA dan NUC) yang hanya ~50% dari yang sekarang. Apple menjanjikan 3.5x peningkatan dalam CPU speed, dan sejujurnya gue kurang yakin apakah benar-benar peningkatan tersebut sebesar 3.5x karena yang gue rasakan hanyalah... cepat.

Karena pertimbangan tersebut gue merasa mubazir bila laptop gue masih dipakai sebatas sebagai SSH client aja, dan juga gue bisa terbebas dari tagihan $22/bulan hanya untuk membuat remote devbox gue berjalan demi mendapatkan mesin dengan 2 vCPU, RAM 4GB, 80GB NVMe SSD, dan alamat IP publik cantik yang beralamat 143.198.198.198.

Tapi sekali lagi, gue tidak ingin mencampur berbagai kepentingan di satu tempat. Dan tentu saja membuat VM adalah jawabannya. Sayangnya, Multipass nya Canonical belum mendukung chip si Apple Silicon ini. Dan Vagrant belum mendukung native support Hypervisor.framework (via xhyve/bhyve) ataupun menggunakan HyperKit nya Docker.

Dan yang paling penting: Gue tidak ingin memasang Docker for Desktop ataupun Virtualbox nya Oracle, no matter what. Tapi kita memiliki Qemu, salah satu swiss army knife untuk virtualization dan emulation yang dibuat oleh lord Fabrice Bellard.

Tapi pengetahuan & pengalaman gue tidak se-dewa itu untuk bisa memahami & menghafal argument-argument penting yang ada di QEMU, dan juga bagian yang paling sulitnya adalah bagaimana membuatnya berjalan dengan baik dan benar.

Lalu gue menemukan UTM versi Mac nya yang gue rasa ini adalah versi GUI dari QEMU karena si UTM ini pada dasarnya menggunakan QEMU, under the hood.

Proses instalasinya mudah, drag-and-drop seperti biasa ke direktori /Application. Dan cara memulainya pun relatif mudah, mari kita membuat VM dengan sistem operasi Ubuntu Server yang menggunakan arsitektur ARM sebagai pembuka topik dari tulisan.

Membuat VM Ubuntu Server

Pertama tentu saja unduh berkas optical disk image nya di halaman ini.

Brengseknya terakhir gue cek belum ada berkas checksum yang disediakan untuk versi si ARM ini, jadi kita tidak bisa memastikan bahwa berkas yang kita unduh dengan berkas yang ada disediakan Canonical adalah berkas yang sama dan tidak rusak. But YOLO, download now.

Kedua, setting VM seperti biasa.

Bagian yang paling penting menurut gue adalah jenis hardware (di bagian System) yang akan di emulasi (pastikan memilih arsitektur arm64), jumlah memory yang ingin ditawarkan (umumnya 50% dari kapasitas yang asli), dan terakhir, seperti biasa, tambahkan 2 drive yang satu sebagai drive utama dan yang dua sebagai ephemeral drive untuk installer si Ubuntu Server kita.

Setting VM

Sisanya, boot dan jalankan proses instalasi seperti biasa. Semuanya harusnya akan berjalan out of the box.

Install Docker

Oke gue bisa aja memasang Postgres, Redis, Traefik, Python, Flask, Node.js, npm, dkk, clone repositori-repositori yang dibutuhkan, switch branch secara manual, dan getting up and running in hard way.

Tidak lupa juga menyesuaikannya dengan lingkungan yang ada, salah satu contohnya adalah mendefinisikan environment variables yang ada.

Dan mungkin tidak masalah selagi lingkungan tersebut sudah ter-isolasi dari lingkungan utama gue. Tapi gue males, dan eventually gue harus memasang docker agar seragam dengan setup yang ada di departemen engineering.

Di sistem operasi non-linux, Docker (docker engine) bejalan didalam VM yang disebut "docker machine". Dan yang paling gue males, dia memakan sumber daya yang tidak sedikit, dan gue tidak peduli sekalipun RAM gue berkapasitas 10TB dengan 69-core CPU.

Karena bagian instalasi Docker (di guest machine) tidak penting, jadi gue skip. Yang paling penting adalah bagaimana membuatnya dapat berkomunikasi dengan host OS (Mac).

Port Forwarding

Port forward di UTM relatif gampang, dan sejujurnya gue masih heran kenapa Docker Desktop belum menawarkan port forward dari host ke container via GUI.

Anyway, gue akan mendemonstrasikan bagaimana mem-forward port 80 di guest machine ke port 8080 di host machine. Via utm kurang lebih seperti ini:

port forward

Dan gue rasa sangat intuitif sekalipun ini hari pertama gue menggunakan UTM. Markicob?

akses port 80 di guest os via port 8080 di host os

Di gambar diatas terlihat bahwa gue mengakses Nginx yang ada di guest OS (Ubuntu) di port 80 via port 8080 yang ada di host OS.

Di bagian port forwarding ini juga bisa untuk melakukan SSH ke guest OS, karena sejauh yang gue tau si UTM ini belum bisa menggunakan bridged network yang mana tidak bisa berkomunikasi dengan jaringan yang ada di si guest machine begitupula sebaliknya.

Throughput

Mari kita cek performance penalty yang ada di VM menggunakan bench.sh

benchmark

Gue rasa ada penalti sekitar -40.59% bila dibandingkan dengan benchmark yang ada di host machine:

benchmark

Dan gue rasa it doesn't matter jika melihat keluaran htop(1) yang dilakukan di host & guest machine dengan perintah htop -p $(ps aux | grep -i qemu-aarch64 | head | awk '{print $2}' dan di guest machine tanpa eksplisit membawa pid yang ingin di monitor:

htop

Look how wild Node.js is.

Downside

PR utamanya adalah—khususnya bila menggunakan Docker—harus memastikan bahwa Docker Image yang ingin digunakan dapat berjalan di arsitektur ARM (ARM64). Ini di pipeline CI bisa menggunakan docker/buildx ketika melakukan build, tapi besar kemungkinan aplikasi populer yang akan kita gunakan sudah mendukung untuk arsitektur arm64 ini.

PR kedua adalah tidak (semoga setidaknya belum) bisa mengakses guest machine IP. Dan berarti mDNS pun tentu saja tidak bisa digunakan. Dan somehow ini bikin frustasi karena misalnya lebih mudah menghafal faultables-raspi.local daripada 192.168.8.69 sekalipun menggunakan static lease di dhcp.

PR ketiga adalah port forwarding hell, thanks to PR kedua. Bayangkan jika ada 5 VM, bila setiap VM ingin meng-expose minimal 3 port, akan ada 20 port (plus SSH) yang harus gue forward dan hafal) dari guest ke host. Mungkin gue bisa setting reverse proxy untuk masalah ini, yang berarti setidaknya cuma ada 10 port (untuk 22 dan 80 di guest) yang harus gue forward, tapi tetap ini annoying & pain.

PR terakhir adalah gue belum menemukan cara untuk menjalankan VM ini di background. Harusnya bisa dengan melakukan "export QEMU command" dan gue bikin simple script misal seperti vm delman start, yang mana delman adalah nama VM nya. Tapi idk, terlalu males buat nyoba.

Penutup

Gue berjanji pada diri sendiri khusus untuk provision VM ini hanya untuk kasus jika development environment harus banget ada docker. Selebihnya gue akan mengusahakan dilakukannya di non-vm dan yang ada di radar gue sejak lama adalah menggunakan NixOS.

Dan juga gue akan mengusahakan untuk menggunakan OS yang mendukung arsitektur arm64 alih-alih harus meng-emulasi CPU ke x86 yang pastinya gue rasa akan memiliki penalti yang lebih besar.

Sebagai penutup, apakah gue puas dengan setup seperti ini? Tentu saja! Tidak memasang Docker Desktop dan VirtualBox adalah sebuah kemenangan untuk gue sekalipun dengan memasangnya pun tidak membunuh diri gue secara perlahan.

Jika gue sudah frustasi banget dengan membuat development environment Mac OS di proses ARM, mungkin gue akan mempertimbangkan menggunakan Asahi Linux dan mengucapkan sayonara untuk kesekian kalinya ke Mac OS (would be great kalau Pop!_OS mendukung arsitektur arm64 natively mengingat Ubuntu sudah mendukungnya juga).

Terakhir, I'm just having fun! Tidak semua pengembang cocok membuat development environment nya ter-isolasi. Tapi jika kamu menggunakan rbenv, pyenv, venv, fnm, nodeenv, jails, lxc, dsb, harusnya kamu sudah mengetahui apakah kamu membutuhkan isolated development environment atau tidak 😉

Discussion (1)

Collapse
faultable profile image
Rizaldy Author

Alternatif UTM: lima-vm/lima. Might try later