Build Terdistribusi

Jika Anda memiliki codebase besar, rantai dependensi dapat menjadi sangat dalam. Bahkan biner sederhana pun sering kali bisa bergantung pada puluhan ribu target versi. Pada skala ini, tidak mungkin untuk menyelesaikan build dalam waktu yang wajar pada satu mesin: tidak ada sistem build yang dapat mengabaikan hukum dasar fisika yang diberlakukan pada hardware mesin. Satu-satunya cara untuk membuatnya berfungsi adalah dengan sistem build yang mendukung build terdistribusi, di mana unit pekerjaan yang dilakukan oleh sistem tersebar di sejumlah mesin yang arbitrer dan skalabel. Dengan asumsi bahwa kita telah memecah pekerjaan sistem menjadi beberapa unit yang cukup kecil (akan dibahas lebih lanjut nanti), proses ini akan memungkinkan kita menyelesaikan build apa pun dalam ukuran apa pun secepat yang bersedia kami bayar. Skalabilitas ini adalah hal penting yang selama ini kami upayakan dengan menentukan sistem build berbasis artefak.

Penyimpanan cache jarak jauh

Jenis build terdistribusi yang paling sederhana adalah build yang hanya memanfaatkan cache jarak jauh, seperti ditunjukkan pada Gambar 1.

Build terdistribusi dengan cache jarak jauh

Gambar 1. Build terdistribusi yang menampilkan cache jarak jauh

Setiap sistem yang menjalankan build, termasuk workstation developer dan sistem continuous integration, berbagi referensi ke layanan cache jarak jauh yang umum. Layanan ini dapat berupa sistem penyimpanan jangka pendek yang cepat dan lokal seperti Redis atau layanan cloud seperti Google Cloud Storage. Setiap kali pengguna perlu membuat artefak, baik secara langsung maupun sebagai dependensi, sistem akan terlebih dahulu memeriksa dengan cache jarak jauh untuk melihat apakah artefak tersebut sudah ada di sana. Jika demikian, Asisten dapat mendownload artefak, bukan mem-build-nya. Jika tidak, sistem akan mem-build artefak itu sendiri dan mengupload hasilnya kembali ke cache. Ini berarti bahwa dependensi tingkat rendah yang tidak sering berubah dapat di-build sekali dan dibagikan kepada pengguna, alih-alih harus dibuat ulang oleh setiap pengguna. Di Google, banyak artefak ditampilkan dari cache, bukan dibuat dari awal, sehingga sangat mengurangi biaya menjalankan sistem build.

Agar sistem cache jarak jauh berfungsi, sistem build harus menjamin bahwa build dapat sepenuhnya direproduksi. Artinya, untuk setiap target build, Anda harus dapat menentukan kumpulan input ke target tersebut sehingga kumpulan input yang sama akan menghasilkan output yang sama persis pada mesin apa pun. Ini adalah satu-satunya cara untuk memastikan bahwa hasil download artefak sama dengan hasil pembuatannya sendiri. Perlu diperhatikan bahwa hal ini mengharuskan setiap artefak dalam cache dikunci pada target dan hash inputnya—dengan begitu, engineer yang berbeda dapat melakukan modifikasi yang berbeda pada target yang sama secara bersamaan, dan cache jarak jauh akan menyimpan semua artefak yang dihasilkan dan menyajikannya dengan tepat tanpa konflik.

Tentu saja, agar ada manfaat dari cache jarak jauh, mendownload artefak harus lebih cepat daripada mem-build-nya. Hal ini tidak selalu terjadi, terutama jika server cache berada jauh dari mesin yang melakukan build. Sistem dan jaringan dan build Google disesuaikan dengan cermat agar dapat membagikan hasil build dengan cepat.

Eksekusi jarak jauh

Cache jarak jauh bukanlah build terdistribusi yang sebenarnya. Jika cache hilang atau jika Anda membuat perubahan tingkat rendah yang mengharuskan semuanya dibangun ulang, Anda masih harus menjalankan seluruh build secara lokal di mesin Anda. Sasaran sebenarnya adalah mendukung eksekusi jarak jauh, yang memungkinkan pekerjaan sebenarnya dalam melakukan build disebarluaskan ke berapa pun pekerja. Gambar 2 menggambarkan sistem eksekusi jarak jauh.

Sistem eksekusi jarak jauh

Gambar 2. Sistem eksekusi jarak jauh

Alat build yang berjalan pada setiap mesin pengguna (pengguna adalah engineer manusia atau sistem build otomatis) mengirimkan permintaan ke master build pusat. Master build memecah permintaan ke dalam tindakan komponennya dan menjadwalkan eksekusi tindakan tersebut melalui kumpulan pekerja yang skalabel. Setiap pekerja melakukan tindakan yang diminta dengan input yang ditentukan oleh pengguna dan menulis artefak yang dihasilkan. Artefak ini dibagikan di seluruh mesin lain yang menjalankan tindakan yang memerlukannya hingga output akhir dapat diproduksi dan dikirim ke pengguna.

Bagian tersulit dari penerapan sistem tersebut adalah mengelola komunikasi antara pekerja, master, dan komputer lokal pengguna. Pekerja mungkin bergantung pada artefak perantara yang dihasilkan oleh pekerja lain, dan output akhir harus dikirim kembali ke mesin lokal pengguna. Untuk melakukannya, kita dapat membuat di atas cache terdistribusi yang dijelaskan sebelumnya dengan meminta setiap pekerja menulis hasilnya ke dan membaca dependensinya dari cache. Master memblokir pekerja agar tidak melanjutkan hingga semua yang mereka andalkan selesai, dalam hal ini mereka dapat membaca input dari cache. Produk akhir juga di-cache, sehingga mesin lokal dapat mendownloadnya. Perhatikan bahwa kita juga memerlukan cara terpisah untuk mengekspor perubahan lokal pada hierarki sumber pengguna sehingga pekerja dapat menerapkan perubahan tersebut sebelum mem-build.

Agar berfungsi, semua bagian sistem build berbasis artefak yang dijelaskan sebelumnya harus digabungkan. Lingkungan build harus sepenuhnya mendeskripsikan dirinya sendiri agar kita dapat menggerakkan pekerja tanpa campur tangan manusia. Proses build itu sendiri harus sepenuhnya mandiri karena setiap langkah mungkin dijalankan di mesin yang berbeda. Output harus sepenuhnya deterministik sehingga setiap pekerja dapat memercayai hasil yang diterimanya dari pekerja lain. Jaminan tersebut sangat sulit untuk diberikan oleh sistem berbasis tugas, sehingga sangat tidak mungkin untuk membangun sistem eksekusi jarak jauh yang andal di atas sistem tersebut.

Build terdistribusi di Google

Sejak tahun 2008, Google telah menggunakan sistem build terdistribusi yang menggunakan cache jarak jauh dan eksekusi jarak jauh, seperti yang diilustrasikan dalam Gambar 3.

Sistem build level tinggi

Gambar 3. Sistem build terdistribusi milik Google

Cache jarak jauh Google disebut ObjFS. Layanan ini terdiri atas backend yang menyimpan output build di Bigtable yang didistribusikan di seluruh fleet mesin produksi kami, dan daemon FUSE frontend bernama objfsd yang berjalan di setiap mesin developer. Daemon FUSE memungkinkan engineer untuk menjelajahi output build seolah-olah itu adalah file normal yang disimpan di workstation, tetapi dengan konten file yang didownload secara on demand, hanya untuk beberapa file yang diminta langsung oleh pengguna. Menayangkan konten file sesuai permintaan sangat mengurangi penggunaan jaringan dan disk, dan sistem dapat mem-build dua kali lebih cepat dibandingkan dengan saat kita menyimpan semua output build di disk lokal developer.

Sistem eksekusi jarak jauh Google disebut Forge. Klien Forge di Blaze (yang setara internal Bazel) yang disebut Distributor mengirimkan permintaan untuk setiap tindakan ke tugas yang berjalan di pusat data kami yang disebut Scheduler. Scheduler mempertahankan cache hasil tindakan, sehingga dapat segera menampilkan respons jika tindakan telah dibuat oleh pengguna lain di sistem. Jika tidak, tindakan tersebut akan ditempatkan dalam antrean. Kumpulan besar tugas Executor terus membaca tindakan dari antrean ini, jalankan, dan simpan hasilnya langsung di Bigtable ObjFS. Hasil ini tersedia bagi eksekutor untuk tindakan di masa mendatang, atau untuk didownload oleh pengguna akhir melalui objfsd.

Hasil akhirnya adalah sistem yang dapat diskalakan untuk mendukung semua build yang dijalankan di Google secara efisien. Dan skala build Google benar-benar masif: Google menjalankan jutaan build yang menjalankan jutaan kasus pengujian dan menghasilkan output build petabyte dari miliaran baris kode sumber setiap hari. Sistem semacam itu tidak hanya memungkinkan engineer kami mem-build codebase yang kompleks dengan cepat, tetapi juga memungkinkan kami untuk mengimplementasikan sejumlah besar alat dan sistem otomatis yang mengandalkan build kami.