- Deptool adalah alat deployment yang dibuat untuk mengoperasikan konfigurasi DNS dan web server sendiri, dengan terlebih dahulu menampilkan rencana perubahan lalu menerapkannya ke host target setelah dikonfirmasi
- Seluruh konfigurasi klaster dirender lebih dulu dan dikelola dengan Git, lalu setiap host memiliki direktori per commit di bawah
/var/lib/deptool, dan versi diganti secara atomik dengan mengubah tautan simbolis current
- Sebelum deployment, setiap host dikunci dan commit yang diketahui secara lokal dibandingkan dengan status deployment aktual untuk membatalkan rencana yang stale, dan proses hanya berjalan jika kunci untuk semua host yang terdampak berhasil diperoleh
- Layanan dijalankan sebagai unit systemd dan direstart saat konfigurasi berubah; jika gagal start, tautan dikembalikan ke versi known-good sebelumnya lalu direstart lagi untuk melakukan rollback otomatis dalam hitungan milidetik
- Eksekusi jarak jauh menggunakan pendekatan agen statis yang memakai SSH hanya sebagai lapisan transport, dan dapat dipasang otomatis hanya dengan coreutils bahkan di lingkungan seperti Flatcar Linux yang tidak memiliki Python dan package manager
Latar belakang pembuatan Deptool
- Berawal dari pemindahan blog ke Eropa untuk menghindari kontradiksi mempublikasikan tulisan tentang kedaulatan digital Eropa di atas hosting AS dan hyperscaler yang dikendalikan AS
- Karena DNS juga masih bergantung pada Cloudflare, muncul kebutuhan untuk menjalankan server DNS sendiri
- Web server yang ada sebelumnya berjalan di VM kecil dengan Nginx dan Lego untuk pembaruan sertifikat, sementara konfigurasi Nginx dibuat dengan Nix lalu disalin ke server menggunakan skrip Python kecil dan Nginx direstart
- Untuk menjalankan server DNS dibutuhkan setidaknya dua server, lebih banyak unit systemd, file konfigurasi, dan zonefile, sehingga skrip lama tidak lagi memadai
- Ada opsi beralih ke NixOS, tetapi diputuskan untuk mempertahankan pendekatan saat ini—OS dasar minimal dan layanan berjalan dalam chroot read-only hanya dengan biner yang diperlukan—serta membuat alat deployment baru
Seperti apa penggunaan Deptool
- Deptool terlebih dahulu menampilkan rencana perubahan konfigurasi klaster, lalu menerapkannya ke host target setelah mendapat konfirmasi
- Contoh pembaruan record DNS menunjukkan bahwa setelah menjalankan
deptool deploy, rencana akan menampilkan perubahan file konfigurasi nsd dan restart nsd.service di s4.ruuda.nl dan s5.ruuda.nl
- Saat deployment gagal, rollback otomatis diterapkan; pada contoh, setelah konfirmasi untuk menerapkan ke 2 host di klaster
prod, proses berhasil dalam 0,99 detik
- Output memisahkan host target, aplikasi yang berubah, file yang berubah, dan unit systemd yang akan direstart, sehingga pekerjaan yang benar-benar akan dilakukan dapat diperiksa sebelum deployment
Syarat alat deployment yang diinginkan
-
Cepat
- Pembaruan konfigurasi harus memakan waktu kurang dari 1 detik, dan karena ping melintasi Atlantik pun sekitar 100 ms, tidak ada alasan mendasar mengapa proses ini harus lebih lambat
-
Dapat diprediksi
- Alat harus menampilkan lebih dulu apa yang akan dilakukan lalu menjalankannya persis seperti itu
- Diinginkan pendekatan pemisahan tahap plan dan apply seperti OpenTofu
- Check mode Ansible dianggap kurang dapat dipercaya karena perubahan berantai baru bisa terlihat setelah langkah imperatif dijalankan, dan perubahan status host di antara check dan eksekusi nyata juga tidak dapat dicegah
-
Aman
- Bahkan jika konfigurasi Nginx rusak, alat harus bisa melakukan rollback otomatis dalam hitungan milidetik agar web server tidak mati selama beberapa menit
-
Sederhana
- Yang dibutuhkan hanyalah menyalin file konfigurasi dari laptop ke server dan merestart beberapa unit systemd
- Tidak perlu menyelesaikan semua masalah deployment atau menyediakan control flow maupun eksekusi kode arbitrer
- Pemrosesan template file konfigurasi bisa dilakukan oleh alat terpisah; masalah template YAML dipisahkan ke generate dan alat pembuat file terpisah
-
Harus deklaratif
- Jika file atau aplikasi dihapus dari konfigurasi, maka itu juga harus dihapus dari server
- Tidak perlu menambahkan langkah pembersihan eksplisit, dan tidak boleh ada drift atau file sisa karena terlupa dibersihkan
-
Tidak boleh ada setup awal
- Host harus bisa dikelola segera setelah selesai diprovisikan
- Jika perlu prosedur untuk memasang agen, daemon, dependensi, atau mendaftarkan host secara manual, maka muncul lagi masalah untuk mengotomatisasi prosedur itu sendiri
Pemisahan antara pembuatan konfigurasi dan deployment
- Gagasan intinya adalah memisahkan pembuatan konfigurasi dan deployment
- Unsible buatan David di kantor tidak mengeksekusi playbook Ansible langkah demi langkah, melainkan membuat tarball secara lokal lalu mengirimkannya ke host untuk menempatkan file
- Skrip deployment sederhana yang sudah ada sebelumnya juga membangun konfigurasi di luar, dan skripnya sendiri berperan hampir seperti penyalinan file
- NixOS juga dapat dipandang sebagai penerapan ide ini pada sistem lokal, dan hal yang bisa dipelajari dari Nix adalah menyimpan artefak yang dihasilkan di lokasi tempat beberapa versi dapat hidup berdampingan, lalu membatasi bagian imperatif dari administrasi sistem ke tahap aktivasi kecil berupa perubahan beberapa tautan simbolis
- Desain ini cocok baik untuk package management maupun konfigurasi sistem
Cara kerja Deptool
-
Merender seluruh konfigurasi klaster lebih dulu
- File konfigurasi untuk seluruh klaster dibuat terlebih dahulu dan disimpan dalam direktori di disk
- Pohon direktori memiliki kedalaman dua tingkat: tingkat teratas berisi direktori per host target, dan di bawahnya terdapat direktori per aplikasi
-
Menaruhnya ke repositori Git
- Dengan menaruh direktori konfigurasi ke repositori Git, perbedaan antarversi dapat dibandingkan dan perubahan di seluruh klaster bisa dilihat
- diffstat menunjukkan host yang terdampak dan aplikasi yang berubah, dan diff yang tepat untuk setiap file konfigurasi dapat dilihat
-
Mewujudkan file di direktori host yang terisolasi
- Semua file ditempatkan di bawah
/var/lib/deptool agar tidak saling mengganggu dengan elemen lain
- Karena direktori dibuat dengan nama commit yang akan dideploy, beberapa versi dapat berdampingan di disk
- Tautan simbolis
current menunjuk ke versi yang dideploy sehingga versi dapat diganti secara atomik
- File yang dihapus tidak diwujudkan pada versi berikutnya, sehingga tidak menimbulkan file sisa
- Untuk aplikasi yang memerlukan file di lokasi tertentu, dapat dibuat tautan simbolis dari lokasi yang dibutuhkan di filesystem menuju
/var/lib/deptool
- Pembuatan dan penghapusan tautan simbolis tidak atomik, tetapi hanya diperlukan saat menambah atau menghapus tautan, bukan saat memodifikasi isi file
- Jika tautan simbolis itu tidak lagi disertakan pada versi deployment berikutnya, diff akan menunjukkan bahwa tautan tersebut harus dihapus sehingga file tidak tertinggal
-
Mencatat status deployment dengan remote-tracking ref
- Laptop operator melacak commit yang telah dideploy ke masing-masing host
- Status deployment bukan properti seluruh klaster, melainkan properti per host
- Jika suatu perubahan tidak memengaruhi host tertentu, maka tidak perlu mendeploy commit baru ke host itu
- Dengan informasi ini, diff klaster dapat dihitung secara offline, dan diff tersebut menjadi rencana deployment yang bisa ditampilkan dalam hitungan milidetik
-
Mengambil lock pada host target sebelum deployment
- Koneksi dilakukan lewat SSH dan permintaan lock dikirimkan, termasuk commit yang diyakini telah dideploy ke host tersebut
- Jika lock berhasil didapatkan, berarti rencana valid, dan selama lock belum dilepas, tidak ada deployment lain yang bisa berjalan di host itu sehingga rencana tetap valid
- Deployment hanya berjalan jika lock untuk semua host yang terdampak berhasil dipegang
- Jika ref sudah usang dan sesuatu yang lain telah dideploy ke host itu, maka rencana berstatus stale dan dibatalkan
- Setelah ref lokal diperbarui, eksekusi berikutnya akan menampilkan rencana terbaru
-
Merestart unit systemd
- Semua layanan berjalan sebagai unit systemd dan start dengan cepat, sehingga saat ragu lebih baik direstart
- Jika konfigurasi aplikasi berubah, unit systemd yang terdampak akan direstart
- Jika start unit gagal, tautan simbolis dikembalikan ke versi known-good sebelumnya lalu direstart lagi, sehingga rollback otomatis dalam hitungan milidetik menjadi memungkinkan
Model konkurensi optimistis
- Deployment Deptool memiliki unsur konkurensi optimistis
- Rencana dibuat dengan asumsi bahwa status klaster saat ini sudah diketahui, dan jika asumsi itu salah maka proses harus diulang
- Saat tidak ada contention, pendekatan ini sangat cepat, seperti pada infrastruktur pribadi ketika satu orang melakukan deployment dari laptop yang sama
- Di lingkungan tempat banyak orang terus mencoba deployment, hanya satu yang akan berhasil dan sisanya harus mencoba lagi, sehingga performanya bisa memburuk drastis
- Model ini mirip
git push; memang tidak akan menskalakan ke ratusan orang atau ribuan server, tetapi sudah cukup untuk kebutuhan infrastruktur pribadi
- Dengan membuat alat sendiri, alat itu bisa dioptimalkan persis untuk use case yang dibutuhkan
Membangun agen
-
Flatcar Linux dan keterbatasan host awal
- Web server berjalan di Flatcar Linux
- Flatcar Linux adalah OS berbasis image dengan userspace yang sangat kecil; ada coreutils dan Bash, tetapi tidak ada package manager maupun Python
- Ini bagus untuk mengurangi attack surface, tetapi kurang menguntungkan jika ingin memasang sesuatu
- Jika alat membutuhkan sesuatu untuk dipasang terlebih dahulu agar bisa bekerja, maka muncul masalah baru untuk mengotomatisasi proses instalasi itu
-
Menggunakan SSH hanya sebagai lapisan transport
- Karena host baru harus dikelola dari luar, SSH dan passwordless sudo dapat digunakan
- Menjalankan perintah langsung lewat SSH bukan hanya lambat karena handshake, tetapi juga karena argv tidak melintasi batas SSH dengan aman, dan harus menghadapi masalah word splitting serta escaping pada shell-over-SSH
- Deptool menjalankan satu program tanpa argumen di lokasi yang dapat diprediksi, dan menggunakan program ini sebagai agen
- Agen membaca pesan dari stdin dan mengirim respons ke stdout
- SSH dipakai murni sebagai sarana transport seperti socket, sehingga input yang dikendalikan pengguna tidak pernah masuk ke perintah SSH atau shell dan masalah escaping pun dapat dihindari
-
Menggunakan biner statis
- Agen dibangun sebagai biner statis
- Tidak mengasumsikan ada apa pun selain kernel, dan juga tidak memerlukan interpreter yang harus mem-parsing beberapa MB kode sebelum bisa melakukan pekerjaan berguna
- Ansible, bahkan setelah mitigate cacat terburuknya, masih mengirim beberapa MB modul Python setiap kali terkoneksi, dan Flatcar bahkan tidak punya Python
-
Menaruh biner pada path berbasis commit
- Biner agen disimpan pada path yang mencakup commit tempat ia dibangun
- Ini menjamin bahwa kedua ujung koneksi menjalankan versi yang sama sehingga tidak timbul masalah kompatibilitas protokol
- Path-nya berbentuk
/var/lib/deptool/bin/deptool-<version>-<commit>
-
Mula-mula mengasumsikan biner sudah ada
- Karena handshake SSH mahal, tidak ada pemborosan untuk probe atau langkah instalasi idempoten
- Biner agen berukuran sekitar 1,6 MB; memang tidak terlalu besar sampai terlarang untuk ditransfer, tetapi juga tidak gratis
- Perubahan konfigurasi klaster terjadi jauh lebih sering daripada pembaruan Deptool, sehingga biasanya diasumsikan binernya sudah ada
-
Jika eksekusi gagal, pasang binernya
- Jika agen gagal dijalankan, instalasi dilakukan lewat koneksi SSH kedua
- Perintah eksekusinya adalah sebagai berikut
uname -sm
&& sudo mkdir -p /var/lib/deptool/{bin,apps,store}
&& sudo dd status=none of=<remote_bin_path>
&& sudo chmod +x <remote_bin_path>
&& sudo sha256sum <remote_bin_path>
- Pertama, satu baris dibaca dari stdout untuk mendapatkan output
uname, lalu dari sana OS dan arsitektur CPU dapat diketahui sehingga biner agen yang sesuai platform bisa dikirim
- Biner ditulis ke stdin, dan
dd di sisi remote akan menuliskannya ke disk
- Terakhir, satu baris lagi dibaca dari stdout untuk memeriksa shasum yang dihitung di sisi remote dan memverifikasi apakah transfer berhasil
- Proses ini hanya bergantung pada program coreutils yang terstandarisasi
- Setelah itu, percobaan menjalankan agen lagi seharusnya berhasil, dan agen akan membersihkan versi lama agar disk tidak penuh
Dampak dan biaya pendekatan agen
- Pendekatan ini menghasilkan cara untuk menjalankan dan berkomunikasi dengan agen di host remote
- Instalasi otomatis dimungkinkan tanpa persyaratan apa pun di host remote selain coreutils
- Karena kedua sisi menjalankan versi yang sama, kompatibilitas protokol dijamin secara struktural
- Input yang dikendalikan pengguna hanya dikirim melalui socket berbasis SSH dan tidak pernah masuk ke perintah SSH atau shell, sehingga masalah escaping dan batas panjang dapat dihindari
- Dalam kasus umum, hanya dibutuhkan satu handshake SSH sehingga latensinya kecil
- Pada kasus yang lebih jarang, seperti deployment ke mesin baru atau setelah pembaruan alat, diperlukan 2 koneksi tambahan dan transfer satu kali sebesar 1,6 MB
- Dengan
ControlMaster, sebagian besar overhead koneksi berikutnya dapat dilewati, sehingga total biayanya menjadi dalam kisaran beberapa detik
- Dalam kasus itu memang bukan deployment kurang dari 1 detik, tetapi tetap dianggap lebih baik daripada Ansible
- Dalam alur kerja deploy konfigurasi, mengubah sedikit, lalu deploy lagi, SSH dapat mempertahankan koneksi dasar sehingga deployment terasa seketika
Hasil penggunaan dan publikasi
- Deptool telah digunakan selama sebulan terakhir untuk mengelola infrastruktur pribadi
- Mampu langsung melihat rencana yang tepat sebelum terkoneksi dan adanya rollback otomatis adalah hal yang bagus, tetapi perubahan terbesar adalah deployment kurang dari 1 detik
- Jika deployment yang benar memakan waktu beberapa menit, orang cenderung ingin mengedit file langsung di server untuk mempersingkat feedback loop, tetapi dengan Deptool lebih cepat mengubah secara lokal lalu mendeploy daripada masuk ke server lewat SSH dan membuka editor
- Cara dengan friksi paling rendah menjadi cara yang benar, dan semua perubahan yang diterapkan tercatat dalam riwayat Git
- Jika sesuatu rusak, Deptool akan rollback bahkan sebelum sempat disadari bahwa ada yang rusak
- Deptool dibuat untuk menyelesaikan masalah pribadi ini secara tepat, dan justru karena tidak mencoba menyelesaikan semua masalah deployment untuk semua orang, alat ini menonjol dalam use case tersebut
- Ini bisa sangat berguna khususnya pada sistem operasi berbasis image, dan telah dipublikasikan di Codeberg dan GitHub, dengan manual yang juga tersedia
1 komentar
Komentar Lobste.rs
Saya sangat senang mereka secara terbuka menyatakan tidak memasukkan teks hasil generasi LLM ke proyek ini: not putting LLM-generated text anywhere near this
Alatnya sendiri juga tampak dipoles dengan baik dan desainnya bagus, tapi untuk sementara saya sepertinya akan tetap memakai NixOS
Saya pasti akan mencobanya. Ini terlihat seperti versi yang lebih matang dari sistem buatan saya sendiri untuk mendeploy layanan berbasis systemd
Dari tutorialnya kelihatannya bagus, tapi saya penasaran bagaimana sebaiknya menangani state lokal. Misalnya, saya tidak menemukan di dokumentasi di mana database sqlite aplikasi seharusnya disimpan
Saya juga penasaran apakah ada cara untuk mengirim biner aplikasi ke server agar bisa dipakai oleh unit systemd. Kalau tidak ada, saya ingin tahu bagaimana deployment biner biasanya ditangani
/var/lib/<yourapp>Jika aplikasinya dijalankan sebagai unit systemd, Anda bisa memakai
StateDirectory=agar systemd membuat direktori itu dengan kepemilikan pengguna yang benarAplikasi yang saya operasikan dibangun menjadi image EROFS kecil dengan skrip berbasis Nix ini, dan skrip itu juga mencakup fungsi untuk mendorong image ke server. Dulu ini langkah terpisah, tapi sekarang build dan push digabung jadi satu langkah, lalu masuk ke direktori unik sehingga beberapa versi bisa hidup berdampingan
Hasil build juga menyertakan JSON berisi path file, yang kemudian saya impor ke konfigurasi klaster, dirender menjadi unit systemd, lalu dideploy dengan Deptool. Jadi satu alat menangani deployment image, dan Deptool menangani aktivasi
Kalau memakai container, biasanya image didorong ke registry, dan di server hanya ada file konfigurasi yang menentukan apa yang harus diambil, jadi bagian itu bisa dikelola hanya dengan Deptool
Pendekatan lain yang juga cukup bagus adalah memakai bootable containers
Yang masih kurang adalah belum ada sesuatu yang benar-benar menjalankan
bootc update --applypada host yang tepat. Ada mekanisme auto-update, tapi tidak terkoordinasi, jadi itu bukan cara yang diinginkan untuk klasterSaat ini saya masih melakukannya secara manual, tapi pada akhirnya yang perlu dijalankan hanya satu perintah bootc, jadi sepertinya nanti mudah untuk dijadikan skrip
Setiap kali ada alat deployment baru, saya cenderung agak skeptis, tapi yang ini tampaknya dirancang dengan baik dan dipoles rapi
Memakai perintah
sshsecara langsung juga tampak sebagai pilihan yang tepat. Pengguna tahu bahwasshyang mereka miliki benar-benar berfungsi, dan bisa saja mereka memakai konfigurasi yang sangat khusus atau biner ssh yang sudah dipatchAlat yang mencoba mengimplementasikan ssh sendiri lewat library eksternal kemungkinan besar akan mengganggu sebagian pengguna
Saya ingin tahu lebih detail bagaimana dan mengapa EROFS dipakai
Flatcar tidak punya package manager, jadi perangkat lunak dan dependensinya harus diunggah sendiri dengan suatu cara, dan image filesystem yang mandiri adalah salah satu caranya
Image OCI mengharuskan alat terpisah seperti Podman atau Docker untuk mengekstrak tar ke suatu tempat dan menyusun stack mount overlay, tetapi kalau sudah berupa image filesystem, itu bisa langsung dijalankan dari unit systemd dengan
RootImage=Saya membangun image dengan Nix sehingga isinya benar-benar minimal. Hanya ada biner Nginx, LibreSSL, libc, dan beberapa shared library, bahkan tidak ada Bash
Ini adalah bagian dari defense in depth. Bahkan jika ada kerentanan remote code execution di Nginx, penyerang akan berjalan di dalam namespace filesystem yang hampir tidak menyediakan bahan untuk membuat eksploit tahap berikutnya, dan seluruh filesystem bersifat read-only. Bukan hanya karena dimount read-only, tetapi karena EROFS memang tidak memiliki kemampuan tulis
Dulu saya memakai Squashfs dan itu bekerja baik, tetapi filesystem itu dirancang berdasarkan era live CD. EROFS mengambil kompromi yang lebih cocok untuk sistem masa kini, meski sejujurnya untuk use case saya sepertinya tidak ada perbedaan yang terukur
Image-nya memang lebih kecil, tetapi itu karena pengaturan kompresinya berbeda. Secara teori, EROFS juga lebih cocok untuk content-defined chunking jika ingin memakai ulang data di antara image dengan versi berbeda, tetapi saya belum benar-benar memakainya untuk transfer image
Kebetulan tulisan ini muncul saat saya sedang berdiskusi dengan seorang teman tentang strategi deployment yang sederhana, dan ini cukup dekat dengan kesimpulan yang sedang kami capai
Namun, saya penasaran bagaimana pengelolaan secret dilakukan dalam setup seperti ini
Judulnya “Prompting the deployment tool I wish I had”, tapi
https://codeberg.org/ruuda/deptool/…
Dalam arti tertentu, cukup mengesankan bahwa bilangan floating-point berhasil membujuk Rust untuk dipakai
Dalam arti yang positif, Rust adalah bahasa yang “disiplin”, dengan konvensi dan tooling yang kuat. Keduanya membantu LLM
Anehnya, setidaknya jika diberi sedikit arahan, LLM cenderung menghasilkan program yang lebih pendek dalam Rust dibanding beberapa bahasa lain. Karena saya memang berniat membaca dan mengedit semua kodenya, versi yang lebih pendek lebih baik bagi saya
Saya penasaran bagaimana secret ditangani di sini. Apakah ada alur kerja yang lebih disukai, apakah dimasukkan ke image EROFS atau diinjeksi lewat systemd
Direktori itu dimount read-write untuk unit Lego, dan dimount read-only untuk unit Nginx