Beberapa bulan yang lalu, saya menulis artikel tentang mempercepat pembuatan container di dalam container. Artikel tersebut berkonsentrasi pada kecepatan menarik gambar container, dan berbagai cara untuk mengisi penyimpanan gambar sebelumnya, menggunakan pemasangan volume dari host dan konsep Buildah tentang "penyimpanan tambahan".
Buildah adalah fitur command-line untuk membuat image yang kompatibel dengan Open Container Initiative (yang berarti kompatibel dengan Docker dan Kubernetes juga) dengan cepat dan mudah. Buildah mudah dimasukkan ke dalam skrip dan pipeline build, dan yang terpenting, buildah tidak memerlukan daemon container yang sedang berjalan untuk membangun image-nya.
Artikel ini akan membahas masalah kedua dengan kecepatan build saat menggunakan dnf
/yum
perintah di dalam container. Perhatikan bahwa dalam artikel ini saya akan menggunakan nama dnf
(yang merupakan nama upstream) dan bukan yang digunakan oleh beberapa downstream (yum
) Komentar ini berlaku untuk dnf
dan yum
.
Kecepatan unduh
Pernahkah Anda memperhatikan bahwa terkadang saat Anda menjalankan dnf -y update
atau dnf -y install
untuk pertama kalinya dalam beberapa saat, perintah dijeda untuk waktu yang lama bahkan sebelum mulai menurunkan RPM? Apa yang terjadi?
Hal pertama yang dnf
lakukan adalah mengunduh file cache yang sangat besar. File-file ini ditulis dalam XML dan berisi setiap paket dalam repositori jarak jauh, termasuk banyak data tentang paket tersebut. Mereka bahkan berisi setiap jalur dalam paket. Data ini diperlukan agar ketika Anda dapat menjalankan sesuatu seperti dnf -y install /usr/bin/httpd
lalu dnf
mengetahui paket yang akan diinstal. Banyak paket berisi perintah seperti (requires: /usr/bin/sendmail
) yang memanfaatkan fitur ini, memungkinkan dnf
untuk menarik paket yang sesuai untuk memenuhi kebutuhan.
Menarik file-file besar ini—dan yang lebih penting, memproses file-file ini—bisa memakan waktu lebih dari satu menit. Data ini digunakan oleh libsolv
, jadi harus dikonversi ke solv
format, yang lambat. Kecepatan bukanlah masalah besar jika Anda hanya melakukannya secara berkala di host Anda, tetapi dalam hal membangun container, ini adalah masalah yang jauh lebih besar.
Sintaks Dockerfile
Meskipun Buildah memungkinkan Anda membuat image container langsung di shell, kebanyakan orang menggunakan Dockerfiles dan Containerfiles untuk membuat container dan menentukan resep gambar yang dapat direproduksi. Buildah default untuk mencari Containerfile
dan Dockerfile
sekarang. Masing-masing memiliki sintaks yang sama, jadi saya akan menggunakan Containerfile
untuk sisa dokumen ini.
Hal yang umum dilakukan di Containerfile
adalah dengan menggunakan sintaks seperti:
FROM ubi8
RUN dnf -y update; dnf -y install nginx; dnf -y clean all
…
RUN dnf -y install jboss; dnf -y clean all
Mari kita periksa dnf
garis. dnf
pertama baris:
(dnf -y update; dnf -y install nginx; dnf -y clean all
):
- Memperbarui semua paket dalam penampung.
- Menginstal paket yang dipilih
nginx
. - Membersihkan semua.
Sejak ubi8
gambar mungkin dibuat beberapa waktu lalu dan /var/cache/dnf
direktori mungkin tidak ada di dalam gambar kontainer, dnf
harus menarik file cache XML dan memprosesnya. Kemudian, dnf
menginstal paket yang sebenarnya sebelum dnf -y clean all
menghapus semua data berlebih yang ditempatkan oleh perintah sebelumnya ke dalam gambar seperti file log dan cache.
Pengguna disarankan untuk menjalankan clean all
untuk menjaga gambar sekecil mungkin. Setiap RUN
perintah membuat layer baru, dan bahkan jika Anda menghapus konten di RUN
later perintah, lapisan awal akan berisi semua konten. Ini berarti bahwa setiap orang yang pernah menarik gambar Anda pada akhirnya akan menarik file log dan cache. Sekarang, jika Containerfile
Anda berisi satu atau lebih dnf
perintah, Anda akan membayar harga berulang kali. Tidak hanya itu tetapi setiap kali Anda membangun kembali gambar ini, Anda akan membayar harga itu lagi. Jika Anda berada di server build, setiap image container yang Anda buat akan mendownload file XML ini berulang kali, membuang banyak sumber daya dan waktu.
Bangun dengan dudukan overlay
Kami melihat masalah yang dijelaskan di atas dan berpikir kami dapat menangani ini dengan cara yang lebih baik. Tidak bisakah kita menarik data XML ke host, memprosesnya di host, dan memasang volume ke dalam container? Mungkin kita bisa mengatur tugas cron atau systemd
timer yang melakukan dnf makecache
sekali untuk setiap versi OS tempat Anda akan membuat gambar penampung? Anda dapat menjalankan tugas ini sekali atau beberapa kali sehari di host, lalu meminta semua volume pembuat penampung memasang cache yang sesuai ke dalam penampung buildah.
Nah, Buildah mendukung direktori pemasangan volume dari host ke dalam wadah. Itu harus menyelesaikan masalah, dan memang begitu. NAMUN, kontainer sering ingin menulis ke direktori ini, jika mereka harus memperbarui cache, maka cache perlu dipasang ke dalam kontainer baca/tulis. Hal ini menyebabkan lubang keamanan yang sangat besar. Bayangkan situasi di mana container build yang tidak bersahabat menulis konten ke cache ini yang dibaca oleh container builder berikutnya. Itu mungkin bisa menipu wadah kedua untuk menginstal perangkat lunak yang diretas. Kami membutuhkan solusi di mana konten dipasang ke dalam wadah, tidak dapat ditulis oleh wadah, namun tetap ditulis dari perspektif wadah. Pada dasarnya inilah titik pemasangan Overlay.
Sistem file overlay memasang lower
direktori dan kemudian melampirkan upper
direktori ke merged
titik pemasangan. Ketika sebuah proses menulis ke file baru ke merged
direktori, file baru akan ditulis ke upper
direktori. Ketika sebuah proses memodifikasi file yang ada di lower
direktori, kernel menyalin file dari lower
direktori ke upper
direktori dan memungkinkan proses untuk memodifikasi file di upper
direktori.
Kami memperkenalkan konsep pemasangan Overlay ke Buildah. Sekarang Anda dapat menjalankan build dengan
buildah bud -v /var/cache/dnf:/var/cache/dnf:O -f /tmp/Containerfile /tmp
Dnf
di dalam wadah masih akan memeriksa untuk melihat apakah ada konten yang lebih baru di repo, dan akan menarik konten ke bawah jika ada. Tapi jika konten di host sudah up to date, maka akan cepat menggunakan cache host. Saya sarankan Anda memperbarui cache host setidaknya sekali sehari.
Satu fitur tambahan yang kami tambahkan untuk pemasangan Buildah Overlay adalah menghancurkan upper
direktori pada setiap RUN
pengarahan. Ingat dalam contoh kita, kita menggunakan beberapa RUN
perintah yang masing-masing menjalankan dnf -y clean all
. dnf -y clean all
perintah menyebabkan upper
direktori untuk menampilkan semua konten dari bawah sebagai dihapus. Jika berikutnya dnf
perintah berbagi bagian atas sebelumnya akan melihat cache kosong dan harus menarik penyimpanan data XML dan memprosesnya. Menghapus upper
direktori berarti bahwa setiap dnf
perintah akan kembali melihat lower
direktori dari host, dan terus berbagi cache host.
Perbedaan kecepatan
Saya akan membuat Containerfile
sederhana berisi dua dnf
menjalankan perintah.
FROM fedora:31
RUN dnf -y install net-utils; dnf -y clean all
RUN dnf -y install iputils; dnf -y clean all
Menjalankan ini secara lokal di kotak Fedora 31 saya
# time -f "Elapsed Time: %E" buildah bud -f Containerfile .
STEP 1: FROM fedora:31
STEP 2: RUN dnf -y install procps-ng; dnf -y clean all
Fedora Modular 31 - x86_64 2.0 MB/s | 5.2 MB 00:02
Fedora Modular 31 - x86_64 - Updates 1.6 MB/s | 4.0 MB 00:02
Fedora 31 - x86_64 - Updates 4.2 MB/s | 19 MB 00:04
Fedora 31 - x86_64 1.8 MB/s | 71 MB 00:39
Last metadata expiration check: 0:00:01 ago on Wed Feb 5 13:55:54 2020.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
procps-ng x86_64 3.3.15-6.fc31 fedora 326 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 326 k
Installed size: 966 k
Downloading Packages:
procps-ng-3.3.15-6.fc31.x86_64.rpm 375 kB/s | 326 kB 00:00
--------------------------------------------------------------------------------
Total 218 kB/s | 326 kB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : procps-ng-3.3.15-6.fc31.x86_64 1/1
Running scriptlet: procps-ng-3.3.15-6.fc31.x86_64 1/1
Verifying : procps-ng-3.3.15-6.fc31.x86_64 1/1
Installed:
procps-ng-3.3.15-6.fc31.x86_64
Complete!
33 files removed
STEP 3: RUN dnf -y install iputils; dnf -y clean all
Fedora Modular 31 - x86_64 741 kB/s | 5.2 MB 00:07
Fedora Modular 31 - x86_64 - Updates 928 kB/s | 4.0 MB 00:04
Fedora 31 - x86_64 - Updates 3.8 MB/s | 19 MB 00:05
Fedora 31 - x86_64 7.9 MB/s | 71 MB 00:08
Last metadata expiration check: 0:00:01 ago on Wed Feb 5 13:57:13 2020.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
iputils x86_64 20190515-3.fc31 fedora 141 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 141 k
Installed size: 387 k
Downloading Packages:
iputils-20190515-3.fc31.x86_64.rpm 252 kB/s | 141 kB 00:00
--------------------------------------------------------------------------------
Total 141 kB/s | 141 kB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : iputils-20190515-3.fc31.x86_64 1/1
Running scriptlet: iputils-20190515-3.fc31.x86_64 1/1
Verifying : iputils-20190515-3.fc31.x86_64 1/1
Installed:
iputils-20190515-3.fc31.x86_64
Complete!
33 files removed
STEP 4: COMMIT
Getting image source signatures
Copying blob ac0b803c5612 skipped: already exists
Copying blob 922380d685bc done
Copying config 566e2afbb4 done
Writing manifest to image destination
Storing signatures
566e2afbb417f0119109578a87950250b566a3b4908868627975a4c7428accfb
566e2afbb417f0119109578a87950250b566a3b4908868627975a4c7428accfb
Elapsed Time: 2:15.00
Proses ini membutuhkan waktu 2 menit 15 detik untuk membuat image container baru dengan dua paket baru.
Sekarang mari kita coba ini dengan mount Overlay dari host.
# dnf -y makecache
# time -f "Elapsed Time: %E" buildah bud -v /var/cache/dnf:/var/cache/dnf:O -f Containerfile .
STEP 1: FROM fedora:31
STEP 2: RUN dnf -y install procps-ng; dnf -y clean all
Last metadata expiration check: 0:02:34 ago on Wed Feb 5 13:51:54 2020.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
procps-ng x86_64 3.3.15-6.fc31 fedora 326 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 326 k
Installed size: 966 k
Downloading Packages:
procps-ng-3.3.15-6.fc31.x86_64.rpm 496 kB/s | 326 kB 00:00
--------------------------------------------------------------------------------
Total 245 kB/s | 326 kB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : procps-ng-3.3.15-6.fc31.x86_64 1/1
Running scriptlet: procps-ng-3.3.15-6.fc31.x86_64 1/1
Verifying : procps-ng-3.3.15-6.fc31.x86_64 1/1
Installed:
procps-ng-3.3.15-6.fc31.x86_64
Complete!
285 files removed
STEP 3: RUN dnf -y install iputils; dnf -y clean all
Last metadata expiration check: 0:02:41 ago on Wed Feb 5 13:51:54 2020.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
iputils x86_64 20190515-3.fc31 fedora 141 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 141 k
Installed size: 387 k
Downloading Packages:
iputils-20190515-3.fc31.x86_64.rpm 556 kB/s | 141 kB 00:00
--------------------------------------------------------------------------------
Total 222 kB/s | 141 kB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : iputils-20190515-3.fc31.x86_64 1/1
Running scriptlet: iputils-20190515-3.fc31.x86_64 1/1
Verifying : iputils-20190515-3.fc31.x86_64 1/1
Installed:
iputils-20190515-3.fc31.x86_64
Complete!
285 files removed
STEP 4: COMMIT
Getting image source signatures
Copying blob ac0b803c5612 skipped: already exists
Copying blob 524bb3b83d61 done
Copying config 0f82aa6064 done
Writing manifest to image destination
Storing signatures
0f82aa6064814ff3dcb603c34c75e516e00817811681b83b8632f3e9b694e518
0f82aa6064814ff3dcb603c34c75e516e00817811681b83b8632f3e9b694e518
Elapsed Time: 0.17.44
Dengan pemasangan Overlay, kami dapat membuat gambar baru dengan dua paket tambahan dalam 17 detik, bukan 2 menit dan 15 detik. Itu hampir 8 kali lebih cepat untuk membuat image container yang sama.
Sekarang ini menunjukkan bahwa jika Anda membuat gambar pada sistem operasi host yang memiliki dnf
metadata pra-cache Anda dapat mempercepat kecepatan instal dengan jumlah yang BESAR. Tetapi bagaimana jika sistem build Anda membuat image untuk versi OS lainnya? Katakanlah Anda ingin membuat gambar untuk Fedora 30 serta Fedora 31. Catatan:ini juga akan bekerja pada sistem RHEL8, di mana Anda mungkin ingin membuat gambar RHEL7 dan bahkan mungkin RHEL6.Dnf
menyertakan fitur keren di mana Anda dapat menentukan rilis berbeda saat menarik konten, menggunakan --releasever
pilihan. Dnf
juga memungkinkan Anda untuk menentukan direktori alternatif untuk menempatkan cachedir, --setopt=cachedir
.
Dalam contoh berikut, saya akan menurunkan dua cache pada host dan kemudian menggunakan Buildah dalam mode baris perintah.
# dnf -y makecache --releasever=31 --setopt=cachedir=/var/cache/dnf/31
# dnf -y makecache --releasever=30 --setopt=cachedir=/var/cache/dnf/30
# ctr31=$(buildah from fedora:31)
# time -f 'Elapsed Time: %E' buildah run -v /var/cache/dnf/31:/var/cache/dnf:O ${ctr31} dnf -y install iputils
Last metadata expiration check: 0:00:15 ago on Wed Feb 5 14:17:41 2020.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
iputils x86_64 20190515-3.fc31 fedora 141 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 141 k
Installed size: 387 k
Downloading Packages:
iputils-20190515-3.fc31.x86_64.rpm 192 kB/s | 141 kB 00:00
--------------------------------------------------------------------------------
Total 107 kB/s | 141 kB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : iputils-20190515-3.fc31.x86_64 1/1
Running scriptlet: iputils-20190515-3.fc31.x86_64 1/1
Verifying : iputils-20190515-3.fc31.x86_64 1/1
Installed:
iputils-20190515-3.fc31.x86_64
Complete!
Elapsed Time: 0:06.85
# ctr30=$(buildah from fedora:30)
# time -f 'Elapsed Time: %E' buildah run -v /var/cache/dnf/30:/var/cache/dnf:O ${ctr30} dnf -y install iputils
Last metadata expiration check: 0:00:15 ago on Wed Feb 5 14:17:47 2020.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
iputils x86_64 20180629-4.fc30 fedora 123 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 123 k
Installed size: 351 k
Downloading Packages:
iputils-20180629-4.fc30.x86_64.rpm 370 kB/s | 123 kB 00:00
--------------------------------------------------------------------------------
Total 138 kB/s | 123 kB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : iputils-20180629-4.fc30.x86_64 1/1
Running scriptlet: iputils-20180629-4.fc30.x86_64 1/1
Verifying : iputils-20180629-4.fc30.x86_64 1/1
Installed:
iputils-20180629-4.fc30.x86_64
Complete!
Elapsed Time: 0:08.88
Seperti yang Anda lihat, kami dapat menjalankan container Buildah menggunakan dnf
cache dari dua rilis Fedora berbeda dari host build yang sama dan container untuk Fedora 31 membutuhkan waktu 6+ detik dan build Fedora 30 membutuhkan waktu 8+ detik.
Catatan:Saya memilih subdirektori /var/cache/dnf
untuk file cache, untuk memastikan label SELinux sudah benar. Hanya menjalankan dnf clean all
tidak akan membersihkan /var/cache/dnf/31
. Anda perlu menjalankan dnf clean all --setopt=cachedir=/var/cache/dnf/31
untuk membersihkan file cache repo dengan benar, tetapi beberapa artefak akan tetap ada (kunci gpg, direktori kosong).
Sekarang hanya untuk melihat berapa lama waktu yang dibutuhkan untuk menjalankan build di Fedora 31 tanpa mount Overlay.
# ctr31=$(buildah from fedora:31)
# time -f 'Elapsed Time: %E' buildah run ${ctr31} dnf -y install iputils
Fedora Modular 31 - x86_64 1.2 MB/s | 5.2 MB 00:04
Fedora Modular 31 - x86_64 - Updates 875 kB/s | 4.0 MB 00:04
Fedora 31 - x86_64 - Updates 2.4 MB/s | 19 MB 00:07
Fedora 31 - x86_64 1.7 MB/s | 71 MB 00:41
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
iputils x86_64 20190515-3.fc31 fedora 141 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 141 k
Installed size: 387 k
Downloading Packages:
iputils-20190515-3.fc31.x86_64.rpm 279 kB/s | 141 kB 00:00
--------------------------------------------------------------------------------
Total 129 kB/s | 141 kB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : iputils-20190515-3.fc31.x86_64 1/1
Running scriptlet: iputils-20190515-3.fc31.x86_64 1/1
Verifying : iputils-20190515-3.fc31.x86_64 1/1
Installed:
iputils-20190515-3.fc31.x86_64
Complete!
Elapsed Time: 1:29.85
Dalam hal ini, butuh hampir 1,5 menit untuk menjalankan wadah yang sama. Buildah dengan mount Overlay berjalan 14 kali lebih cepat.
Wadah Tanpa Root
Semua contoh saya sampai sekarang telah menjalankan build menggunakan Containerfiles
sebagai akar. Tetapi Anda juga dapat melakukan ini dengan wadah tanpa akar. Dalam beberapa contoh berikutnya, saya akan meminta Buildah menjalankan container menggunakan buildah run
sintaks untuk mendemonstrasikan menggunakan cache.
Menjalankan
$ buildah run -v /var/cache/dnf/30:/var/cache/dnf:O ${ctr30} dnf -y install iputils
berfungsi dengan baik. Selama pengguna dapat membaca /var/cache/dnf/30
direktori, lower
direktori dapat dibaca. Tetapi Anda harus mengandalkan sesuatu pada host untuk memperbarui cache secara berkala.
Jika pengguna mau, mereka bahkan dapat menggunakan dnf
untuk membuat cache di direktori home mereka.
$ dnf -y makecache --releasever=30 --setopt=cachedir=$HOME/dnfcache
$ chcon --reference /var/cache/dnf -R $HOME/dnfcache
$ ctr30=$(buildah from fedora:30)
$ buildah run -v $HOME/dnfcache:/var/cache/dnf:O ${ctr30} dnf -y install iputils
Perhatikan saya harus mengubah label SELinux dari $HOME/dnfcache
direktori sehingga SELinux akan memungkinkan wadah untuk membaca lower
direktori untuk pemasangan Overlay.
Kesimpulan
Mempercepat pembuatan container memerlukan pemahaman tentang apa yang terjadi saat Anda menginstal paket. Pra-cache dnf
data di host dan menggunakan pemasangan Overlay untuk memasang cache ke dalam wadah dengan Buildah dapat sangat meningkatkan kecepatan pembangunan dan mengurangi jumlah sumber daya yang diperlukan untuk mendukung kumpulan bangunan.
Buildah sama dengan kesederhanaan tetapi juga memiliki beberapa fitur hebat seperti Overlay mounts
dan additional stores
yang dapat membantu Anda mempercepat pembuatan gambar container.
[ Baru mengenal container? Unduh Containers Primer dan pelajari dasar-dasar container Linux. ]