Linux memiliki banyak wajah: cara bekerja pada distribusi apa pun



Membuat aplikasi cadangan yang berjalan pada distribusi apa pun bukanlah tugas yang mudah. Untuk memastikan bahwa Veeam Agent untuk Linux berjalan pada distribusi dari RHEL 6 dan Debian 6, openSUSE Leap 15.1 dan Ubuntu 19.04 harus menyelesaikan berbagai masalah, terutama ketika Anda menganggap bahwa modul kernel adalah bagian dari produk perangkat lunak.

Artikel ini didasarkan pada presentasi di konferensi LinuxPiter 2019 .

Linux bukan hanya salah satu OS yang paling populer. Sebenarnya, ini adalah platform yang di atasnya Anda dapat melakukan sesuatu yang unik, sesuatu milik Anda. Karena itu, Linux memiliki banyak distribusi yang berbeda dalam satu set komponen perangkat lunak. Dan di sini muncul masalah: agar produk perangkat lunak berfungsi pada distribusi apa pun, Anda harus memperhitungkan karakteristik masing-masing.

Manajer paket. .deb vs .rpm


Mari kita mulai dengan masalah yang jelas dalam mendistribusikan produk untuk distribusi yang berbeda.
Cara paling umum untuk mendistribusikan produk perangkat lunak adalah dengan meletakkan paket pada repositori sehingga manajer paket yang dibangun ke dalam sistem dapat menginstalnya dari sana.
Namun, kami memiliki dua format paket populer: rpm dan deb . Jadi, semua orang harus mendukung.

Dalam dunia paket deb, tingkat kompatibilitasnya luar biasa. Paket yang sama menginstal dengan baik dan bekerja pada Debian 6 dan Ubuntu 19.04. Standar untuk proses membangun paket dan bekerja dengannya, ditetapkan dalam distribusi Debian lama, tetap relevan dalam Linux Mint dan OS dasar. Oleh karena itu, dalam kasus Veeam Agent untuk Linux, satu paket deb untuk setiap platform perangkat keras sudah cukup.

Namun dalam dunia paket rpm, perbedaannya besar. Pertama, karena ada dua distributor Red Hat dan SUSE yang sepenuhnya independen, yang kompatibilitasnya sama sekali tidak diperlukan. Kedua, distributor ini memiliki distribusi dari mereka. dukungan dan eksperimental. Di antara mereka, kompatibilitas juga tidak diperlukan. Ternyata untuk el6, el7 dan el8 paket mereka sendiri. Paket terpisah untuk Fedora. Paket untuk SLES11 dan 12 dan terpisah untuk openSUSE. Masalah utama adalah dependensi dan nama paket.

Masalah ketergantungan


Sayangnya, paket yang sama sering berakhir dengan nama yang berbeda dalam distribusi yang berbeda. Di bawah ini adalah sebagian daftar dependensi paket veeam.
Untuk EL7:Untuk SLES 12:
  • libblkid
  • libgcc
  • libstdc ++
  • ncurses-libs
  • fuse-libs
  • file-libs
  • veeamsnap = 3.0.2.1185
  • libblkid1
  • libgcc_s1
  • libstdc ++ 6
  • libmagic1
  • libfuse2
  • veeamsnap-kmp = 3.0.2.1185

Akibatnya, daftar dependensi unik untuk distribusi.

Semakin buruk ketika versi yang diperbarui mulai bersembunyi di bawah nama paket lama.

Contoh:

Fedora 24 telah memperbarui paket ncurses dari versi 5 ke versi 6. Produk kami dibuat dengan versi 5 untuk memastikan kompatibilitas dengan distribusi yang lebih lama. Untuk menggunakan perpustakaan versi ke-5 di Fedora 24, saya harus menggunakan paket ncurses-compat-libs .

Akibatnya, dua paket muncul untuk Fedora, dengan dependensi berbeda.

Lebih menarik. Setelah pembaruan berikutnya dari paket distribusi, paket ncurses-compat-libs dengan versi 5 perpustakaan tidak tersedia. Tidak menguntungkan bagi distributor untuk menarik perpustakaan lama ke versi distribusi baru. Setelah beberapa waktu, masalahnya terulang dalam distribusi SUSE.

Akibatnya, untuk beberapa distribusi, saya harus meninggalkan ketergantungan eksplisit pada ncurses-libs , dan memperbaiki produk sehingga dapat bekerja dengan versi perpustakaan apa pun.

Ngomong-ngomong, dalam Red Hat versi ke-8 tidak ada lagi paket meta python yang merujuk pada python 2.7 yang bagus . Ada python2 dan python 3.

Alternatif untuk manajer paket


Masalah dengan ketergantungan sudah lama dan sudah jelas. Hanya ingat neraka Ketergantungan.
Gabungkan berbagai pustaka dan aplikasi sehingga semuanya bekerja secara stabil dan tidak bertentangan - pada kenyataannya, distributor Linux mana pun berusaha menyelesaikan masalah ini.

Manajer paket Canonical, Snappy, mencoba menyelesaikan masalah ini dengan sangat berbeda. Gagasan utama: aplikasi berjalan di kotak pasir yang terisolasi dan dilindungi dari sistem utama. Jika aplikasi membutuhkan pustaka, maka mereka dikirim dengan aplikasi itu sendiri.

Flatpak juga memungkinkan Anda menjalankan aplikasi di kotak pasir menggunakan Linux Containers. Ada juga AppImage , yang memungkinkan Anda membuat gambar program yang portabel.

Solusi ini memungkinkan Anda membuat satu paket untuk distribusi apa pun. Dalam hal Flatpak dan AppImage , instalasi dan peluncuran aplikasi dimungkinkan bahkan tanpa sepengetahuan administrator.

Masalah utama adalah bahwa tidak semua aplikasi dapat berjalan di sandbox dan tanpa hak akses root . Beberapa membutuhkan akses langsung ke platform. Saya tidak berbicara tentang modul kernel, yang sangat tergantung pada kernel dan tidak cocok dengan konsep sandbox.

Masalah kedua adalah bahwa distribusi populer dari Red Hat dan SUSE di lingkungan perusahaan belum mendukung Snappy dan Flatpak.

Dalam hal ini, Veeam Agent untuk Linux tidak ada di snapcraft.io atau di flathub.org .

Di akhir pertanyaan tentang manajer paket, saya perhatikan bahwa ada opsi untuk sepenuhnya mengabaikan manajer paket dengan menggabungkan file biner dan skrip untuk menginstalnya dalam satu paket.

Bundel semacam itu memungkinkan Anda untuk membuat satu paket umum untuk berbagai distribusi dan platform, untuk melakukan proses instalasi interaktif, melakukan penyesuaian yang diperlukan. Saya menemukan paket seperti itu untuk Linux hanya dari VMware.

Perbarui masalah



Bahkan jika semua masalah ketergantungan diselesaikan, program dapat bekerja secara berbeda pada distribusi yang sama. Intinya ada di pembaruan.

Ada 3 strategi peningkatan:

  • Yang termudah adalah tidak pernah memperbarui. Mengkonfigurasi server dan lupa. Mengapa diperbarui jika semuanya berfungsi? Masalah mulai saat pertama kali Anda menghubungi dukungan. Pembuat distribusi hanya mendukung rilis yang diperbarui.
  • Anda dapat mempercayai distributor dan mengatur pembaruan otomatis. Dalam hal ini, panggilan untuk mendukung kemungkinan segera setelah pembaruan yang gagal.
  • Pilihan untuk memperbarui secara manual hanya setelah menjalankannya pada infrastruktur pengujian adalah yang paling setia, tetapi mahal dan memakan waktu. Tidak semua orang mampu membelinya.

Karena pengguna yang berbeda menggunakan strategi pembaruan yang berbeda, Anda perlu mendukung rilis terbaru dan semua yang dirilis sebelumnya. Ini mempersulit proses pengembangan, dan proses pengujian, menambah sakit kepala ke layanan dukungan.

Berbagai platform perangkat keras


Berbagai platform perangkat keras adalah masalah yang sebagian besar khusus untuk kode asli. Minimal, Anda harus mengumpulkan binari untuk setiap platform yang didukung.

Dalam proyek Veeam Agent untuk Linux, kami masih tidak dapat mendukung setidaknya sesuatu seperti RISC.

Saya tidak akan membahas masalah ini secara rinci. Saya hanya akan menguraikan masalah utama: tipe yang bergantung pada platform seperti size_t , perataan struktur, dan urutan byte.

Statis dan / atau tautan dinamis



Dan di sini ada pertanyaan "Bagaimana menautkan ke perpustakaan - secara dinamis atau statis?" layak didiskusikan.

Biasanya, aplikasi Linux C / C ++ menggunakan tautan dinamis. Ini berfungsi baik jika aplikasi dibangun khusus untuk distribusi tertentu.

Jika tugasnya adalah untuk menutupi berbagai distribusi dengan satu file biner, maka Anda harus fokus pada distribusi tertua yang didukung. Bagi kami, ini Red Hat 6. Ini berisi gcc 4.4, yang bahkan standar C ++ 11 tidak sepenuhnya mendukung.

Kami sedang membangun proyek kami menggunakan gcc 6.3, yang sepenuhnya mendukung C ++ 14. Secara alami, dalam kasus ini di Red Hat 6 libstdc ++ dan boost library harus diseret. Cara termudah untuk menautkannya adalah secara statis.

Namun sayang, tidak semua perpustakaan dapat dihubungkan secara statis.

Pertama, pustaka sistem, seperti libfuse , libblkid, perlu dihubungkan secara dinamis untuk memastikan bahwa mereka kompatibel dengan kernel dan modul-modulnya.

Kedua, ada kehalusan dengan lisensi.

Lisensi GPL pada dasarnya memungkinkan menghubungkan perpustakaan hanya dengan kode opensource. MIT dan BSD memungkinkan tautan statis dan memungkinkan perpustakaan untuk dimasukkan dalam proyek. Tetapi LGPL tampaknya tidak bertentangan dengan tautan statis, tetapi membutuhkan pembagian file yang diperlukan untuk menghubungkan.

Secara umum, penggunaan tautan dinamis akan melindungi terhadap kebutuhan untuk menyediakan sesuatu.

Membangun Aplikasi C / C ++


Untuk membangun aplikasi C / C ++ untuk berbagai platform dan distribusi, cukup memilih atau mengkompilasi versi gcc yang sesuai dan menggunakan lintas-kompiler untuk arsitektur tertentu, untuk mengumpulkan seluruh rangkaian perpustakaan. Pekerjaan ini cukup layak, tetapi agak merepotkan. Dan tidak ada jaminan bahwa kompiler dan perpustakaan yang dipilih akan memberikan opsi yang bisa diterapkan.

Nilai tambah yang jelas: infrastrukturnya sangat disederhanakan, karena seluruh proses perakitan dapat dilakukan pada satu mesin. Selain itu, cukup mengumpulkan satu set file biner untuk satu arsitektur dan Anda dapat mengemasnya ke dalam paket untuk distribusi yang berbeda. Ini adalah bagaimana paket veeam untuk Veeam Agent untuk Linux dibangun.

Berbeda dengan opsi ini, Anda cukup menyiapkan farm build, yaitu, beberapa mesin untuk perakitan. Setiap mesin tersebut akan menyediakan kompilasi aplikasi dan perakitan paket untuk distribusi tertentu dan arsitektur tertentu. Dalam hal ini, kompilasi dilakukan dengan cara yang telah disiapkan distributor. Artinya, tahap persiapan kompiler dan pemilihan perpustakaan tidak lagi diperlukan. Selain itu, proses perakitan dapat dengan mudah diparalelkan.

Namun, ada minus untuk pendekatan ini: untuk setiap distribusi dalam arsitektur yang sama, Anda harus merakit set file biner Anda sendiri. Yang juga minus adalah bahwa begitu banyak mesin perlu dipertahankan, untuk mengalokasikan sejumlah besar ruang disk dan RAM.

Dengan demikian, paket KMOD dari modul kernel veeamsnap untuk distribusi Red Hat dikumpulkan.

Layanan build terbuka


Rekan SUSE mencoba mengimplementasikan jalan tengah sebagai layanan khusus untuk mengompilasi aplikasi dan membangun paket - openbuildservice .

Intinya, ini adalah hypervisor yang menciptakan mesin virtual, menginstal semua paket yang diperlukan di dalamnya, mengkompilasi aplikasi dan mengkompilasi paket dalam lingkungan yang terisolasi ini, setelah itu mesin virtual seperti itu dibebaskan.



Penjadwal yang diimplementasikan dalam OpenBuildService akan menentukan berapa banyak mesin virtual yang dapat dijalankan untuk kecepatan pembuatan paket yang optimal. Mekanisme tanda tangan built-in itu sendiri akan menandatangani paket dan menempatkannya di repositori built-in. Sistem kontrol versi bawaan akan menyimpan riwayat perubahan dan rakitan. Tetap menambahkan kode sumber Anda ke sistem ini. Bahkan server itu sendiri tidak perlu dinaikkan, tetapi Anda dapat menggunakan yang terbuka.

Namun, di sini ada masalah: penggabungan seperti itu sulit masuk ke infrastruktur yang ada. Misalnya, kontrol versi tidak diperlukan, kami sudah memiliki sumbernya sendiri. Mekanisme tanda tangan berbeda: server khusus digunakan. Repositori juga tidak diperlukan.

Selain itu, dukungan untuk distribusi lain - misalnya, Red Hat - dilaksanakan agak buruk, yang dapat dimengerti.

Keuntungan dari layanan ini adalah dukungan cepat dari versi distribusi SUSE berikutnya. Sebelum pengumuman rilis resmi, paket yang diperlukan untuk perakitan diunggah ke repositori publik. Yang baru muncul dalam daftar distribusi yang tersedia di OpenBuildService. Kami memberi tanda centang dan ditambahkan ke rencana perakitan. Dengan demikian, menambahkan versi baru distribusi dilakukan di hampir satu klik.

Dalam infrastruktur kami, menggunakan OpenBuildService, kami mengumpulkan seluruh paket KMP dari modul kernel veeamsnap untuk distribusi SUSE.

Lebih lanjut, saya ingin membahas masalah-masalah khusus untuk modul kernel.

kernel ABI


Modul kernel Linux secara historis telah didistribusikan dalam bentuk sumber. Faktanya adalah bahwa pencipta kernel tidak membebani diri mereka sendiri dengan hati-hati memelihara API yang stabil untuk modul-modul kernel, dan terlebih lagi pada tingkat biner, kemudian kABI.

Untuk membangun modul untuk kernel vanilla, header dari kernel khusus ini diperlukan, dan itu hanya akan berfungsi pada core ini.

DKMS memungkinkan Anda untuk mengotomatiskan proses perakitan modul saat memperbarui kernel. Akibatnya, pengguna repositori Debian (dan banyak kerabatnya) menggunakan modul kernel baik dari repositori distributor atau dikumpulkan dari sumber menggunakan DKMS.

Namun, situasi ini tidak terlalu nyaman dengan segmen Enterprise. Distributor kode kepemilikan ingin mendistribusikan produk dalam bentuk binari terkompilasi.

Administrator tidak ingin menyimpan alat pengembangan di server produksi untuk alasan keamanan. Distributor Enterprise Linux - seperti Red Hat dan SUSE - telah memutuskan bahwa mereka dapat mempertahankan kABI yang stabil untuk para penggunanya. Akibatnya, paket KMOD untuk Red Hat dan paket KMP untuk SUSE muncul.

Inti dari solusi ini cukup sederhana. API kernel dibekukan untuk versi distribusi tertentu. Distributor menyatakan bahwa ia menggunakan kernel, misalnya, 3.10, dan hanya membuat perbaikan dan perbaikan yang tidak mempengaruhi antarmuka kernel dengan cara apa pun, dan modul yang dirakit untuk kernel pertama dapat digunakan untuk semua yang berikutnya tanpa kompilasi ulang.

Red Hat mengumumkan kompatibilitas kABI untuk distribusi sepanjang siklus hidup. Artinya, modul yang dirakit untuk rhel 6.0 (rilis November 2010) juga harus berfungsi pada versi 6.10 (rilis Juni 2018). Dan ini hampir 8 tahun. Tentu, tugasnya agak rumit.
Kami mencatat beberapa kasus ketika, karena masalah dengan kompatibilitas KABI, modul veeamsnap berhenti bekerja.

Setelah modul veeamsnap yang dikompilasi untuk RHEL 7.0 ternyata tidak kompatibel dengan kernel dari RHEL 7.5, tetapi itu dimuat dan dijamin untuk menjatuhkan server, kami menolak untuk menggunakan kompatibilitas kABI untuk RHEL 7 secara umum.

Saat ini, paket KMOD untuk RHEL 7 berisi perakitan untuk setiap versi rilis dan skrip yang menyediakan pemuatan modul.

SUSE mendekati tugas kompatibilitas kABI lebih hati-hati. Mereka menyediakan kompatibilitas kABI hanya dalam satu paket layanan.

Sebagai contoh, rilis SLES 12 terjadi pada bulan September 2014. Dan SLES 12 SP1 sudah pada bulan Desember 2015, yaitu, sedikit lebih dari setahun telah berlalu. Meskipun kedua rilis menggunakan kernel 3,12, mereka tidak kompatibel dengan kABI. Jelas, menjaga kompatibilitas KABI hanya selama satu tahun jauh lebih mudah. Siklus pembaruan modul inti tahunan tidak boleh menyebabkan masalah bagi pembuat modul.

Sebagai akibat dari kebijakan SUSE ini, kami tidak memperbaiki masalah dengan kompatibilitas kABI dalam modul veeamsnap kami. Benar, jumlah paket untuk SUSE hampir merupakan urutan besarnya lebih besar.

Tambalan dan backport


Terlepas dari kenyataan bahwa distributor berusaha untuk memastikan kompatibilitas kABI dan stabilitas kernel, mereka juga berusaha untuk meningkatkan kinerja dan menghilangkan cacat pada kernel stabil ini.

Selain itu, di samping "work on error" mereka sendiri, para pengembang dari kernel perusahaan linux melacak perubahan pada kernel vanilla dan mentransfernya ke yang "stabil".

Terkadang ini menyebabkan kesalahan baru.

Rilis terbaru Red Hat 6 membuat kesalahan dalam salah satu pembaruan kecil. Itu mengarah pada fakta bahwa modul veeamsnap dijamin akan merusak sistem ketika snapshot dirilis. Dengan membandingkan sumber kernel sebelum dan setelah pembaruan, kami menemukan bahwa backport yang harus disalahkan. Perbaikan serupa dibuat di kernel vanilla versi 4.19. Tapi hanya di core vanilla, perbaikan ini bekerja dengan baik, dan ketika mentransfernya ke "stable" 2.6.32, ada masalah dengan spin-lock.

Tentu saja, semua orang selalu memiliki kesalahan, tetapi apakah itu layak menyeret kode dari 4,19 menjadi 2,6,32, mempertaruhkan stabilitas? .. Saya tidak yakin ...

Yang terburuk, ketika pemasaran dikaitkan dengan tarik-menarik "stabilitas" perang <-> "modernisasi". Departemen pemasaran membutuhkan inti dari distribusi yang diperbarui agar stabil, di satu sisi, dan pada saat yang sama menjadi lebih baik dalam kinerja dan memiliki fitur-fitur baru. Ini mengarah pada kompromi aneh.

Ketika saya mencoba membangun modul pada kernel 4.4 dari SLES 12 SP3, saya terkejut menemukan fungsionalitas dari vanilla 4.8 di dalamnya. Menurut pendapat saya, implementasi blok I / O dari kernel 4.4 dari SLES 12 SP3 lebih seperti kernel 4.8 daripada rilis kernel 4.4 yang stabil sebelumnya dari SLES12 SP2. Saya tidak dapat menilai berapa persen kode yang ditransfer dari kernel 4.8 ke SLES 4.4 untuk SP3, tetapi saya masih tidak memiliki kesempatan untuk memanggil kernel dengan stable 4.4 yang sama.

Hal yang paling tidak menyenangkan tentang hal ini adalah ketika menulis modul yang bekerja dengan baik pada core yang berbeda, Anda tidak dapat lagi mengandalkan versi kernel. Kami juga harus memperhitungkan distribusi. Sangat baik bahwa kadang-kadang Anda dapat terlibat dalam definisi yang muncul bersama dengan fungsionalitas baru, tetapi fitur ini tidak selalu muncul.

Akibatnya, kode dikelilingi oleh arahan mewah untuk kompilasi bersyarat.

Ada juga tambalan yang mengubah API kernel yang didokumentasikan.
Saya menemukan kit distribusi KDE neon 5.16 dan sangat terkejut melihat bahwa panggilan lookup_bdev dalam versi kernel ini mengubah daftar parameter input.

Untuk berkumpul, kami harus menambahkan skrip di makefile yang memeriksa apakah fungsi lookup_bdev memiliki parameter mask.

Tanda tangan modul kernel


Namun kembali ke masalah distribusi paket.

Salah satu keuntungan dari stabil kABI adalah bahwa modul kernel dapat ditandatangani sebagai file biner. Dalam hal ini, pengembang dapat memastikan bahwa modul itu tidak sengaja rusak atau sengaja diubah. Anda dapat memeriksa ini dengan perintah modinfo.

Distribusi Red Hat dan SUSE memungkinkan Anda memverifikasi tanda tangan modul dan mengunduhnya hanya jika sertifikat yang sesuai terdaftar dalam sistem. Sertifikat adalah kunci publik tempat modul ditandatangani. Kami mendistribusikannya sebagai paket terpisah.

Masalahnya di sini adalah bahwa sertifikat dapat dibangun ke dalam kernel (mereka digunakan oleh distributor), atau harus ditulis ke memori EFI yang tidak mudah menguap menggunakan utilitas mokutil . Saat memasang sertifikat, utilitas mokutil memerlukan reboot sistem dan bahkan sebelum kernel sistem operasi dimuat, ia menawarkan administrator untuk mengizinkan pengunduhan sertifikat baru.

Jadi, menambahkan sertifikat memerlukan akses fisik administrator ke sistem. Jika mesin terletak di suatu tempat di cloud atau hanya di ruang server jauh dan akses hanya melalui jaringan (misalnya, melalui ssh), maka tidak mungkin untuk menambahkan sertifikat.

EFI di mesin virtual


Terlepas dari kenyataan bahwa EFI telah lama didukung oleh hampir semua pencipta motherboard, ketika menginstal sistem, administrator mungkin tidak memikirkan kebutuhan akan EFI, dan itu dapat dinonaktifkan.

Tidak semua hypervisors mendukung EFI. VMWare vSphere mendukung EFI sejak versi 5.
Microsoft Hyper-V juga menerima dukungan EFI, dimulai dengan Hyper-V untuk Windows Server 2012R2.

Namun, dalam konfigurasi default, fungsi ini dinonaktifkan untuk mesin Linux, yang berarti bahwa sertifikat tidak dapat diinstal.

Di vSphere 6.5, Anda dapat mengatur opsi Boot Aman hanya di versi lama antarmuka web yang bekerja melalui Flash. Web UI pada HTML-5 jauh di belakang.

Distribusi Eksperimental


Dan akhirnya, pertimbangkan masalah distribusi dan distribusi eksperimental tanpa dukungan resmi. Di satu sisi, distribusi seperti itu tidak mungkin ditemukan di server organisasi yang serius. Tidak ada dukungan resmi untuk distribusi semacam itu. Karena itu, untuk menyediakannya. dukungan produk pada distribusi semacam itu tidak dimungkinkan.

Namun, distribusi tersebut menjadi platform yang nyaman untuk menguji solusi eksperimental baru. Misalnya, Fedora, OpenSUSE Tumbleweed, atau versi Debian yang tidak stabil. Mereka cukup stabil. Mereka selalu memiliki versi program baru dan selalu kernel baru. Setelah satu tahun, fungsi eksperimental ini mungkin ada di RHEL, SLES atau Ubuntu yang diperbarui.

Jadi, jika sesuatu tidak berfungsi pada kit distribusi eksperimental, ini adalah kesempatan untuk menyelesaikan masalah dan menyelesaikannya. Anda harus siap dengan kenyataan bahwa fungsi ini akan segera muncul di server produksi pengguna.

Daftar distribusi saat ini yang didukung secara resmi untuk versi 3.0 dapat ditemukan di sini . Tetapi daftar distribusi yang sebenarnya yang dapat digunakan oleh produk kami jauh lebih luas.

Secara pribadi, saya tertarik pada percobaan dengan OS Elbrus. Setelah memperbarui paket veeam, produk kami dipasang dan diterima. Tentang percobaan ini saya menulis di Habré dalam artikel .

Nah, dukungan untuk distribusi baru terus berlanjut. Kami menunggu rilis versi 4.0. Beta akan segera muncul, jadi tetap ikuti perkembangannya !

Source: https://habr.com/ru/post/id471226/


All Articles