Masalah pembersihan gambar container secara “cerdas” dan solusinya di werf

Masalah pembersihan gambar container secara “cerdas” dan solusinya di werf

Artikel ini membahas masalah pembersihan image yang terakumulasi dalam container registry (Docker Registry dan analognya) dalam realitas pipeline CI/CD modern untuk aplikasi cloud native yang dikirimkan ke Kubernetes. Kriteria utama untuk relevansi gambar dan kesulitan yang diakibatkannya dalam mengotomatiskan pembersihan, menghemat ruang, dan memenuhi kebutuhan tim diberikan. Terakhir, dengan menggunakan contoh proyek Open Source tertentu, kami akan memberi tahu Anda bagaimana kesulitan ini dapat diatasi.

pengenalan

Jumlah gambar dalam registri kontainer dapat bertambah dengan cepat, menghabiskan lebih banyak ruang penyimpanan dan dengan demikian meningkatkan biayanya secara signifikan. Untuk mengontrol, membatasi, atau mempertahankan pertumbuhan ruang yang dapat diterima dalam registri, hal berikut dapat dilakukan:

  1. gunakan sejumlah tag tetap untuk gambar;
  2. bersihkan gambar dengan cara tertentu.


Batasan pertama terkadang dapat diterima untuk tim kecil. Jika pengembang memiliki tag permanen yang cukup (latest, main, test, boris dll.), ukuran registri tidak akan membengkak dan untuk waktu yang lama Anda tidak perlu berpikir untuk membersihkannya sama sekali. Lagi pula, semua gambar yang tidak relevan akan terhapus, dan tidak ada pekerjaan tersisa untuk dibersihkan (semuanya dilakukan oleh pemulung biasa).

Namun, pendekatan ini sangat membatasi pengembangan dan jarang diterapkan pada proyek CI/CD modern. Bagian integral dari pembangunan adalah otomatisasi, yang memungkinkan Anda menguji, menerapkan, dan memberikan fungsionalitas baru kepada pengguna dengan lebih cepat. Misalnya, di semua proyek kami, pipeline CI secara otomatis dibuat dengan setiap penerapan. Di dalamnya, gambar dirakit, diuji, diluncurkan ke berbagai sirkuit Kubernetes untuk debugging dan pemeriksaan selanjutnya, dan jika semuanya baik-baik saja, perubahan akan sampai ke pengguna akhir. Dan ini bukan lagi ilmu roket, tetapi kejadian sehari-hari bagi banyak orang - kemungkinan besar bagi Anda, karena Anda membaca artikel ini.

Karena perbaikan bug dan pengembangan fungsionalitas baru dilakukan secara paralel, dan rilis dapat dilakukan beberapa kali sehari, jelas bahwa proses pengembangan disertai dengan sejumlah besar komitmen, yang berarti sejumlah besar gambar di registri. Akibatnya, muncul pertanyaan tentang pengorganisasian pembersihan registri yang efektif, mis. menghapus gambar yang tidak relevan.

Namun bagaimana Anda menentukan apakah suatu gambar relevan?

Kriteria relevansi gambar

Dalam sebagian besar kasus, kriteria utamanya adalah:

1. Yang pertama (yang paling jelas dan paling kritis) adalah gambar itu saat ini digunakan di Kubernetes. Menghapus gambar-gambar ini dapat mengakibatkan biaya waktu henti produksi yang signifikan (misalnya, gambar mungkin diperlukan untuk replikasi) atau meniadakan upaya tim melakukan debug pada loop mana pun. (Untuk alasan ini kami bahkan membuat yang spesial Eksportir Prometheus, yang melacak tidak adanya gambar tersebut di cluster Kubernetes mana pun.)

2. Kedua (kurang jelas, tetapi juga sangat penting dan sekali lagi berkaitan dengan eksploitasi) - gambar itu diperlukan untuk rollback jika ditemukan masalah serius dalam versi saat ini. Misalnya, dalam kasus Helm, ini adalah gambar yang digunakan dalam versi rilis yang disimpan. (Omong-omong, secara default di Helm, batasnya adalah 256 revisi, tetapi sepertinya tidak ada orang yang benar-benar perlu menyimpan seperti itu sejumlah besar versi?..) Lagi pula, kami, khususnya, menyimpan versi sehingga kami dapat menggunakannya nanti, mis. "putar kembali" ke mereka jika perlu.

3. Ketiga - kebutuhan pengembang: Semua gambar yang berhubungan dengan pekerjaannya saat ini. Misalnya, jika kita sedang mempertimbangkan PR, maka masuk akal untuk meninggalkan gambar yang sesuai dengan komit terakhir dan, katakanlah, komit sebelumnya: dengan cara ini pengembang dapat dengan cepat kembali ke tugas apa pun dan bekerja dengan perubahan terbaru.

4. Keempat - gambar itu sesuai dengan versi aplikasi kita, yaitu. adalah produk akhir: v1.0.0, 20.04.01/XNUMX/XNUMX, sierra, dll.

NB: Kriteria yang ditentukan di sini dirumuskan berdasarkan pengalaman berinteraksi dengan puluhan tim pengembangan dari berbagai perusahaan. Namun, tentu saja, tergantung pada proses pengembangan spesifik dan infrastruktur yang digunakan (misalnya, Kubernetes tidak digunakan), kriteria ini mungkin berbeda.

Kelayakan dan solusi yang ada

Layanan populer dengan pendaftar kontainer, biasanya, menawarkan kebijakan pembersihan gambarnya sendiri: di dalamnya Anda dapat menentukan kondisi di mana tag dihapus dari registri. Namun, ketentuan ini dibatasi oleh parameter seperti nama, waktu pembuatan, dan jumlah tag*.

* Tergantung pada implementasi registri kontainer tertentu. Kami mempertimbangkan kemungkinan solusi berikut: Azure CR, Docker Hub, ECR, GCR, GitHub Packages, GitLab Container Registry, Harbour Registry, JFrog Artifactory, Quay.io - mulai September 2020.

Kumpulan parameter ini cukup untuk memenuhi kriteria keempat - yaitu, untuk memilih gambar yang sesuai dengan versinya. Namun, untuk semua kriteria lainnya, kita harus memilih solusi kompromi (kebijakan yang lebih ketat atau, sebaliknya, lebih lunak) - tergantung pada ekspektasi dan kemampuan finansial.

Misalnya, kriteria ketiga - terkait dengan kebutuhan pengembang - dapat diselesaikan dengan mengatur proses dalam tim: penamaan gambar tertentu, memelihara daftar izin khusus, dan perjanjian internal. Namun pada akhirnya masih perlu diotomatisasi. Dan jika kemampuan solusi yang sudah jadi tidak cukup, Anda harus melakukan sesuatu sendiri.

Situasi dengan dua kriteria pertama serupa: kriteria tersebut tidak dapat dipenuhi tanpa menerima data dari sistem eksternal - sistem tempat aplikasi diterapkan (dalam kasus kami, Kubernetes).

Ilustrasi alur kerja di Git

Katakanlah Anda sedang mengerjakan sesuatu seperti ini di Git:

Masalah pembersihan gambar container secara “cerdas” dan solusinya di werf

Ikon dengan kepala pada diagram menunjukkan gambar container yang saat ini diterapkan di Kubernetes untuk semua pengguna (pengguna akhir, penguji, manajer, dll.) atau digunakan oleh pengembang untuk debugging dan tujuan serupa.

Apa yang terjadi jika kebijakan pembersihan hanya memperbolehkan gambar dipertahankan (tidak dihapus) dengan nama tag yang diberikan?

Masalah pembersihan gambar container secara “cerdas” dan solusinya di werf

Tentu saja skenario seperti itu tidak akan membuat siapa pun bahagia.

Apa yang akan berubah jika kebijakan mengizinkan gambar untuk tidak dihapus? sesuai dengan interval waktu tertentu/jumlah komitmen terakhir?

Masalah pembersihan gambar container secara “cerdas” dan solusinya di werf

Hasilnya sudah jauh lebih baik, namun masih jauh dari ideal. Lagi pula, kami masih memiliki pengembang yang membutuhkan gambar di registri (atau bahkan diterapkan di K8) untuk men-debug bug...

Untuk meringkas situasi pasar saat ini: fungsi yang tersedia dalam pendaftar kontainer tidak menawarkan fleksibilitas yang cukup saat membersihkan, dan alasan utamanya adalah tidak ada cara untuk berinteraksi dengan dunia luar. Ternyata tim yang memerlukan fleksibilitas seperti itu terpaksa menerapkan penghapusan gambar “dari luar” secara mandiri, menggunakan Docker Registry API (atau API asli dari implementasi terkait).

Namun, kami mencari solusi universal yang akan mengotomatiskan pembersihan gambar untuk tim berbeda menggunakan registri berbeda...

Jalan kami menuju pembersihan citra universal

Dari manakah kebutuhan ini berasal? Faktanya adalah kami bukanlah kelompok pengembang yang terpisah, namun sebuah tim yang melayani banyak pengembang sekaligus, membantu menyelesaikan masalah CI/CD secara komprehensif. Dan alat teknis utama untuk ini adalah utilitas Open Source wer. Keunikannya adalah ia tidak menjalankan satu fungsi saja, namun menyertai proses pengiriman berkelanjutan di semua tahap: mulai dari perakitan hingga penerapan.

Menerbitkan gambar ke registri* (segera setelah dibuat) adalah fungsi yang jelas dari utilitas semacam itu. Dan karena gambar ditempatkan di sana untuk penyimpanan, maka - jika penyimpanan Anda tidak terbatas - Anda harus bertanggung jawab atas pembersihan selanjutnya. Bagaimana kami mencapai kesuksesan dalam hal ini, memenuhi semua kriteria yang ditentukan, akan dibahas lebih lanjut.

* Meskipun registrinya sendiri mungkin berbeda (Docker Registry, GitLab Container Registry, Harbour, dll.), penggunanya menghadapi masalah yang sama. Solusi universal dalam kasus kami tidak bergantung pada implementasi registri, karena berjalan di luar registri itu sendiri dan menawarkan perilaku yang sama untuk semua orang.

Meskipun kami menggunakan werf sebagai contoh implementasi, kami berharap pendekatan yang digunakan dapat bermanfaat bagi tim lain yang menghadapi kesulitan serupa.

Jadi kami sibuk luar implementasi mekanisme untuk membersihkan gambar - alih-alih kemampuan yang sudah ada di dalam register untuk container. Langkah pertama adalah menggunakan Docker Registry API untuk membuat kebijakan primitif yang sama untuk jumlah tag dan waktu pembuatannya (disebutkan di atas). Ditambahkan ke mereka izinkan daftar berdasarkan gambar yang digunakan dalam infrastruktur yang diterapkan, yaitu. Kubernet. Untuk yang terakhir, cukup menggunakan API Kubernetes untuk melakukan iterasi melalui semua sumber daya yang diterapkan dan mendapatkan daftar nilai image.

Solusi sepele ini menyelesaikan masalah paling kritis (kriteria No. 1), namun hanyalah awal dari perjalanan kami untuk meningkatkan mekanisme pembersihan. Langkah selanjutnya – dan yang jauh lebih menarik – adalah keputusan mengasosiasikan gambar yang diterbitkan dengan riwayat Git.

Skema penandaan

Untuk memulainya, kami memilih pendekatan di mana gambar akhir harus menyimpan informasi yang diperlukan untuk pembersihan, dan membangun proses berdasarkan skema penandaan. Saat memublikasikan gambar, pengguna memilih opsi penandaan tertentu (git-branch, git-commit или git-tag) dan menggunakan nilai yang sesuai. Dalam sistem CI, nilai-nilai ini ditetapkan secara otomatis berdasarkan variabel lingkungan. nyatanya gambar terakhir dikaitkan dengan primitif Git tertentu, menyimpan data yang diperlukan untuk pembersihan dalam label.

Pendekatan ini menghasilkan serangkaian kebijakan yang memungkinkan Git digunakan sebagai satu-satunya sumber kebenaran:

  • Saat menghapus cabang/tag di Git, gambar terkait di registri secara otomatis dihapus.
  • Jumlah gambar yang terkait dengan tag Git dan penerapan dapat dikontrol oleh jumlah tag yang digunakan dalam skema yang dipilih dan waktu pembuatan penerapan terkait.

Secara keseluruhan, implementasi yang dihasilkan memenuhi kebutuhan kami, namun tantangan baru segera menanti kami. Faktanya adalah saat menggunakan skema penandaan berdasarkan primitif Git, kami menemui sejumlah kekurangan. (Karena uraiannya berada di luar cakupan artikel ini, semua orang dapat mengetahui detailnya di sini.) Oleh karena itu, setelah memutuskan untuk beralih ke pendekatan penandaan yang lebih efisien (penandaan berbasis konten), kami harus mempertimbangkan kembali penerapan pembersihan gambar.

Algoritma baru

Mengapa? Dengan penandaan berbasis konten, setiap tag dapat memenuhi banyak komitmen di Git. Saat membersihkan gambar, Anda tidak bisa lagi berasumsi hanya dari komit tempat tag baru ditambahkan ke registri.

Untuk algoritme pembersihan baru, diputuskan untuk beralih dari skema penandaan dan membangun proses meta-gambar, yang masing-masing menyimpan banyak:

  • komit tempat publikasi dilakukan (tidak masalah apakah gambar ditambahkan, diubah, atau tetap sama di registri penampung);
  • dan pengenal internal kami yang sesuai dengan gambar yang dirakit.

Dengan kata lain, hal itu telah disediakan menghubungkan tag yang diterbitkan dengan komitmen di Git.

Konfigurasi akhir dan algoritma umum

Saat mengonfigurasi pembersihan, pengguna kini memiliki akses ke kebijakan yang memilih gambar saat ini. Setiap kebijakan tersebut didefinisikan:

  • banyak referensi, mis. Tag Git atau cabang Git yang digunakan selama pemindaian;
  • dan batas gambar yang dicari untuk setiap referensi dari kumpulan.

Sebagai ilustrasi, seperti inilah konfigurasi kebijakan default:

cleanup:
  keepPolicies:
  - references:
      tag: /.*/
      limit:
        last: 10
  - references:
      branch: /.*/
      limit:
        last: 10
        in: 168h
        operator: And
    imagesPerReference:
      last: 2
      in: 168h
      operator: And
  - references:  
      branch: /^(main|staging|production)$/
    imagesPerReference:
      last: 10

Konfigurasi ini berisi tiga kebijakan yang mematuhi aturan berikut:

  1. Simpan gambar untuk 10 tag Git terakhir (berdasarkan tanggal pembuatan tag).
  2. Simpan tidak lebih dari 2 gambar yang diterbitkan dalam seminggu terakhir untuk tidak lebih dari 10 rangkaian pesan dengan aktivitas dalam seminggu terakhir.
  3. Simpan 10 gambar untuk cabang main, staging и production.

Algoritme terakhir bermuara pada langkah-langkah berikut:

  • Mengambil manifes dari registri kontainer.
  • Tidak termasuk gambar yang digunakan di Kubernetes, karena Kami telah memilihnya terlebih dahulu dengan melakukan polling pada API K8s.
  • Memindai riwayat Git dan mengecualikan gambar berdasarkan kebijakan yang ditentukan.
  • Menghapus gambar yang tersisa.

Kembali ke ilustrasi kita, inilah yang terjadi dengan werf:

Masalah pembersihan gambar container secara “cerdas” dan solusinya di werf

Namun, meskipun Anda tidak menggunakan werf, pendekatan serupa untuk pembersihan gambar tingkat lanjut - dalam satu implementasi atau lainnya (sesuai dengan pendekatan pilihan untuk penandaan gambar) - dapat diterapkan ke sistem/utilitas lain. Untuk melakukan ini, cukup mengingat masalah yang muncul dan menemukan peluang di tumpukan Anda yang memungkinkan Anda mengintegrasikan solusinya semulus mungkin. Kami berharap jalur yang telah kami lalui akan membantu Anda melihat kasus khusus Anda dengan detail dan pemikiran baru.

Kesimpulan

  • Cepat atau lambat, sebagian besar tim menghadapi masalah kelebihan registri.
  • Saat mencari solusi, pertama-tama perlu ditentukan kriteria relevansi gambar.
  • Alat yang ditawarkan oleh layanan registri kontainer populer memungkinkan Anda mengatur pembersihan yang sangat sederhana yang tidak memperhitungkan “dunia luar”: gambar yang digunakan di Kubernetes dan kekhasan alur kerja tim.
  • Algoritme yang fleksibel dan efisien harus memiliki pemahaman tentang proses CI/CD dan beroperasi tidak hanya dengan data image Docker.

PS

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komentar