Apa yang kita (dan bukan hanya kita) telah tunggu-tunggu sejak lama telah terjadi: , utilitas sumber terbuka kami untuk membangun aplikasi dan mengirimkannya ke Kubernetes, kini mendukung penerapan perubahan menggunakan patch penggabungan 3 arah! Selain itu, kini dimungkinkan untuk mengadopsi sumber daya K8s yang ada ke dalam rilis Helm tanpa membuatnya ulang.

Singkatnya, kami menempatkan WERF_THREE_WAY_MERGE=enabled — kita mendapatkan penyebaran “seperti dalam kubectl apply", kompatibel dengan instalasi Helm 2 yang ada dan bahkan lebih dari itu.
Namun, mari kita mulai dengan teorinya: apa itu patch 3-way-merge, bagaimana orang-orang menemukan pendekatan untuk membuatnya, dan mengapa patch ini penting dalam proses CI/CD dengan infrastruktur berbasis Kubernetes? Setelah itu, kita akan membahas apa sebenarnya 3-way-merge di werf, mode apa saja yang digunakan secara default, dan bagaimana cara mengelolanya.
Apa itu patch gabungan 3 arah?
Jadi, mari kita mulai dengan tugas meluncurkan sumber daya yang dijelaskan dalam manifes YAML ke Kubernetes.
API Kubernetes menawarkan operasi dasar berikut untuk bekerja dengan sumber daya: membuat, menambal, mengganti, dan menghapus. Operasi-operasi ini dirancang untuk membangun peluncuran sumber daya yang nyaman dan berkelanjutan ke klaster. Bagaimana caranya?
Perintah kubectl imperatif
Pendekatan pertama untuk mengelola objek di Kubernetes adalah menggunakan perintah imperatif kubectl untuk membuat, mengubah, dan menghapus objek-objek ini. Sederhananya:
- tim
kubectl runAnda dapat menjalankan Deployment atau Job:kubectl run --generator=deployment/apps.v1 DEPLOYMENT_NAME --image=IMAGE - tim
kubectl scale— mengubah jumlah replika:kubectl scale --replicas=3 deployment/mysql - dan lain-lain
Pendekatan ini mungkin tampak praktis pada pandangan pertama. Namun, ada beberapa masalah:
- Sulit baginya mengotomatisasikan.
- Как mencerminkan konfigurasi di Git? Bagaimana cara meninjau perubahan yang dibuat pada klaster?
- Bagaimana cara memastikan reproduktifitas konfigurasi saat restart?
- ...
Jelas bahwa pendekatan ini tidak cocok dengan penyimpanan kode aplikasi dan infrastruktur sebagai kode (IaC; atau bahkan (sebagai opsi yang lebih modern dan semakin populer di ekosistem Kubernetes). Oleh karena itu, perintah-perintah di kubectl ini belum dikembangkan lebih lanjut.
Membuat, mendapatkan, mengganti, dan menghapus operasi
Dengan primer penciptaan Sederhana saja: kami mengirim manifest ke operasi create API dan sumber daya kube telah dibuat. Representasi YAML dari manifes dapat disimpan di Git, dan untuk membuatnya, gunakan perintah kubectl create -f manifest.yaml.
С pemindahan itu juga sederhana: kita mengganti yang sama manifest.yaml dari Git ke tim kubectl delete -f manifest.yaml.
Operasi replace Memungkinkan Anda mengganti konfigurasi sumber daya sepenuhnya dengan yang baru, tanpa membuat ulang sumber daya tersebut. Artinya, sebelum melakukan perubahan pada sumber daya, sebaiknya minta versi saat ini dengan operasi get, ubah dan perbarui dengan operasi replaceKube memiliki apiserver yang terpasang di dalamnya. dan jika setelah operasi get objek telah berubah, maka operasinya replace itu tidak akan berhasil.
Untuk menyimpan konfigurasi di Git dan memperbaruinya menggunakan replace, Anda perlu melakukan operasi get, gabungkan konfigurasi dari Git dengan apa yang kita dapatkan, dan jalankan replaceSecara default, kubectl hanya mengizinkan Anda menggunakan perintah kubectl replace -f manifest.yamlDimana manifest.yaml —manifes yang telah sepenuhnya disiapkan (dalam kasus kami, digabungkan) yang perlu diinstal. Ini berarti pengguna perlu menggabungkan manifes, yang bukan tugas yang mudah…
Perlu juga dicatat bahwa meskipun manifest.yaml dan disimpan di Git, kita tidak dapat mengetahui sebelumnya apakah suatu objek perlu dibuat atau diperbarui—ini harus dilakukan oleh perangkat lunak pengguna.
Total: Bisakah kita membangun peluncuran yang berkelanjutan? hanya menggunakan buat, ganti, dan hapus, memastikan bahwa konfigurasi infrastruktur disimpan di Git bersama dengan kode dan CI/CD yang nyaman?
Pada prinsipnya kita bisa... Untuk ini akan diperlukan untuk menerapkan operasi penggabungan manifesto dan semacam ikatan, yang:
- memeriksa keberadaan suatu objek di dalam cluster,
- melakukan pembuatan awal suatu sumber daya,
- memperbarui atau menghapusnya.
Saat memperbarui, harap diingat bahwa sumber daya mungkin telah berubah sejak terakhir get dan secara otomatis menangani kasus penguncian optimis - lakukan upaya berulang untuk memperbarui.
Namun, mengapa harus menciptakan kembali roda ketika kube-apiserver menawarkan cara lain untuk memperbarui sumber daya: operasi patch, yang membebaskan pengguna dari beberapa masalah yang dijelaskan?
tambalan
Jadi, akhirnya kita sampai pada bagian patch.
Patch adalah cara utama untuk menerapkan perubahan pada objek yang sudah ada di Kubernetes. Operasi patch bekerja sedemikian rupa sehingga:
- Pengguna kube-apiserver perlu mengirim patch dalam format JSON dan menentukan objeknya,
- dan apiserver sendiri akan menangani status objek saat ini dan membawanya ke bentuk yang diperlukan.
Penguncian optimis tidak diperlukan dalam kasus ini. Operasi ini lebih bersifat deklaratif daripada penggantian, meskipun awalnya mungkin tampak sebaliknya.
Demikian:
- melalui pembedahan
createkami membuat objek berdasarkan manifest dari Git, - melalui
delete- hapus jika objek tidak lagi diperlukan, - melalui
patch— kita mengubah objek tersebut, membawanya ke bentuk yang dijelaskan di Git.
Namun, untuk melakukan ini, Anda perlu membuat patch yang benar!
Cara Kerja Patch di Helm 2: Penggabungan 2 Arah
Saat Anda pertama kali memasang rilis, Helm melakukan operasi create untuk sumber daya bagan.
Saat memperbarui rilis Helm untuk setiap sumber daya:
- menghitung patch antara versi sumber daya dari grafik sebelumnya dan versi grafik saat ini,
- menerapkan patch ini.
Kita akan menyebut patch seperti itu Patch penggabungan 2 arah, karena ada dua manifesto yang terlibat dalam pembuatannya:
- manifes sumber daya dari rilis sebelumnya,
- manifes sumber daya dari sumber daya saat ini.
Saat menghapus operasi delete Dalam kube, apiserver dipanggil untuk sumber daya yang dideklarasikan dalam rilis sebelumnya tetapi tidak dideklarasikan dalam rilis saat ini.
Pendekatan penggabungan patch 2 arah memiliki masalah: hal ini menyebabkan desinkronisasi status aktual sumber daya di cluster dan manifes di Git.
Mengilustrasikan masalah dengan sebuah contoh
- Di Git, grafik menyimpan manifes di mana bidang
imagePenerapan memiliki nilaiubuntu:18.04. - Pengguna melalui
kubectl editmengubah nilai bidang ini menjadiubuntu:19.04. - Saat menerapkan ulang bagan Helm tidak menghasilkan patch, karena lapangan
imagedalam versi rilis sebelumnya dan dalam bagan saat ini adalah sama. - Setelah penempatan ulang
imagesisaubuntu:19.04, meskipun grafiknya mengatakanubuntu:18.04.
Kita menjadi tidak sinkron dan kehilangan deklaratif.
Apa itu sumber daya yang disinkronkan?
Secara umum menyelesaikan Mustahil untuk mendapatkan kecocokan antara manifes sumber daya di klaster yang sedang berjalan dan manifes dari Git. Hal ini karena manifes yang sebenarnya mungkin berisi anotasi/label layanan, kontainer tambahan, dan data lain yang ditambahkan dan dihapus secara dinamis dari sumber daya oleh beberapa pengontrol. Kita tidak dapat dan tidak ingin menyimpan data ini di Git. Namun, kita ingin kolom yang kita tentukan secara eksplisit di Git memiliki nilai yang sesuai selama penerapan.
Ternyata itu sangat umum aturan sumber daya yang disinkronkan:Saat meluncurkan sumber daya, Anda hanya dapat mengubah atau menghapus bidang yang secara eksplisit ditentukan dalam manifes Git (atau telah ditentukan dalam versi sebelumnya dan sekarang telah dihapus).
Patch penggabungan 3 arah
ide sentral : Hasilkan patch antara versi manifes Git yang terakhir diterapkan dan versi target manifes Git, dengan mempertimbangkan versi manifes saat ini dari klaster yang sedang berjalan. Patch yang dihasilkan harus mematuhi aturan sumber daya yang disinkronkan:
- bidang baru yang ditambahkan ke versi target ditambahkan melalui patch;
- bidang yang sebelumnya ada dalam versi terakhir yang diterapkan dan bidang yang tidak ada dalam versi target diatur ulang menggunakan patch;
- Bidang dalam versi objek saat ini yang berbeda dari versi target manifes diperbarui menggunakan patch.
Inilah prinsip yang mendasari pembuatan patch. kubectl apply:
- versi terakhir yang diterapkan dari manifes disimpan dalam anotasi objek itu sendiri,
- target - diambil dari file YAML yang ditentukan,
- saat ini - dari kluster yang sedang berjalan.
Sekarang setelah kita membahas teorinya, saatnya untuk memberi tahu Anda apa yang kami lakukan di werf.
Menerapkan perubahan pada werf
Sebelumnya, werf, seperti Helm 2, menggunakan patch penggabungan 2 arah.
Perbaikan tambalan
Untuk berpindah ke jenis patch baru - penggabungan 3 arah - langkah pertama yang kami ambil adalah memperkenalkan apa yang disebut tambalan perbaikan.
Saat menyebarkan, patch penggabungan 2 arah standar digunakan, tetapi werf juga menghasilkan patch yang akan menyinkronkan status sumber daya sebenarnya dengan apa yang tertulis di Git (patch ini dibuat menggunakan aturan sumber daya tersinkronisasi yang sama yang dijelaskan di atas).
Jika terjadi desinkronisasi, di akhir penerapan, pengguna akan menerima pesan PERINGATAN beserta pesan terkait dan patch yang harus diterapkan untuk mengembalikan sinkronisasi sumber daya. Patch ini juga ditulis ke anotasi khusus. werf.io/repair-patchDiasumsikan bahwa pengguna menggunakan tangannya dirinya sendiri akan menerapkan patch ini: werf tidak akan menerapkannya pada prinsipnya.
Pembuatan patch perbaikan adalah tindakan sementara yang memungkinkan Anda menguji proses pembuatan patch gabungan 3 arah, tetapi tidak secara otomatis menerapkan patch tersebut. Mode ini saat ini diaktifkan secara default.
Patch penggabungan 3 arah hanya untuk rilis baru
Mulai 1 Desember 2019, versi beta dan alfa werf akan dimulai secara default Gunakan patch gabungan 3 arah penuh untuk menerapkan perubahan hanya pada rilis Helm baru yang di-deploy melalui werf. Rilis yang sudah ada akan tetap menggunakan pendekatan gabungan 2 arah + patch perbaikan.
Mode operasi ini dapat diaktifkan secara eksplisit dengan mengatur WERF_THREE_WAY_MERGE_MODE=onlyNewReleases sekarang.
Catatan:fitur ini muncul di werf melalui beberapa rilis: di saluran alfa, fitur ini menjadi siap dengan versi , dan di saluran beta - dengan .
Patch penggabungan 3 arah untuk semua rilis
Mulai tanggal 15 Desember 2019, versi beta dan alfa werf akan menggunakan patch gabungan 3 arah penuh secara default untuk menerapkan perubahan untuk semua rilis.
Mode operasi ini dapat diaktifkan secara eksplisit dengan mengatur WERF_THREE_WAY_MERGE_MODE=enabled sekarang.
Bagaimana cara menangani penskalaan sumber daya secara otomatis?
Ada dua jenis penskalaan otomatis di Kubernetes: HPA (horizontal) dan VPA (vertikal).
Yang horizontal secara otomatis memilih jumlah replika, sedangkan yang vertikal memilih jumlah sumber daya. Baik jumlah replika maupun kebutuhan sumber daya ditentukan dalam manifes sumber daya (lihat spec.replicas или spec.containers[].resources.limits.cpu, spec.containers[].resources.limits.memory и ).
Masalah: Jika pengguna mengonfigurasi sumber daya dalam bagan sehingga menentukan nilai tertentu untuk sumber daya atau replika, dan penskalaan otomatis diaktifkan untuk sumber daya ini, maka pada setiap penerapan, werf akan mengatur ulang nilai ini ke apa yang tertulis dalam manifes bagan.
Ada dua solusi untuk masalah ini. Cara terbaik untuk memulai adalah dengan menghindari penentuan nilai penskalaan otomatis secara eksplisit dalam manifes bagan. Jika opsi ini tidak sesuai karena suatu alasan (misalnya, karena lebih mudah untuk menentukan batas sumber daya awal dan jumlah replika dalam bagan), werf menawarkan anotasi berikut:
-
werf.io/set-replicas-only-on-creation=true -
werf.io/set-resources-only-on-creation=true
Dengan anotasi ini, werf tidak akan mengatur ulang nilai terkait pada setiap penerapan, tetapi hanya akan mengaturnya saat sumber daya pertama kali dibuat.
Untuk rincian lebih lanjut, lihat dokumentasi proyek. и .
Nonaktifkan penggunaan patch penggabungan 3 arah
Pengguna saat ini dapat menonaktifkan penggunaan patch baru di werf menggunakan variabel lingkungan. WERF_THREE_WAY_MERGE_MODE=disabledNamun, memulai Larangan ini tidak akan berlaku lagi mulai 1 Maret 2020. dan hanya mungkin untuk menggunakan patch penggabungan 3 arah.
Adopsi sumber daya di werf
Menguasai metode patch penggabungan 3 arah dalam menerapkan perubahan memungkinkan kami untuk segera mengimplementasikan fitur seperti adopsi sumber daya kluster yang ada dalam rilis Helm.
Helm 2 memiliki masalah: Anda tidak dapat menambahkan sumber daya ke manifes bagan yang sudah ada di kluster tanpa membuat ulang sumber daya tersebut dari awal (lihat di bawah). , ). Kami telah mengajarkan werf untuk menerima sumber daya yang ada ke dalam rilis. Untuk melakukannya, Anda perlu memasang anotasi pada versi sumber daya saat ini dari kluster yang sedang berjalan (misalnya, menggunakan kubectl edit):
"werf.io/allow-adoption-by-release": RELEASE_NAMESekarang sumber daya tersebut perlu dijelaskan dalam bagan, dan saat werf berikutnya menerapkan rilis dengan nama yang sesuai, sumber daya yang ada akan diterima ke dalam rilis tersebut dan tetap berada di bawah manajemennya. Lebih lanjut, selama proses penerimaan sumber daya ke dalam rilis, werf akan mengonversi status sumber daya saat ini dari klaster yang sedang berjalan ke status yang dijelaskan dalam bagan, menggunakan patch penggabungan 3 arah yang sama dan aturan sumber daya yang disinkronkan.
Catatan: pengaturan WERF_THREE_WAY_MERGE_MODE tidak memengaruhi adopsi sumber daya - dalam kasus adopsi, patch penggabungan 3 arah selalu digunakan.
Detailnya ada di .
Kesimpulan dan rencana masa depan
Saya harap artikel ini menjelaskan lebih lanjut tentang apa itu patch penggabungan 3 arah dan mengapa patch tersebut dipilih. Dari perspektif praktis untuk proyek werf, implementasinya menandai langkah selanjutnya menuju peningkatan penerapan seperti Helm. Masalah sinkronisasi konfigurasi yang sering muncul dengan Helm 2 kini dapat diatasi. Pada saat yang sama, fitur baru yang bermanfaat telah ditambahkan: mengadopsi sumber daya Kubernetes yang sudah diterapkan ke dalam rilis Helm.
Masih ada beberapa masalah dan tantangan dengan penerapan seperti Helm, seperti penggunaan templat Go, dan kami akan terus mengatasinya.
Informasi tentang metode pembaruan sumber daya dan adopsi juga dapat ditemukan di .
helm 3
Layak disebutkan secara khusus Beberapa hari yang lalu, versi utama Helm yang baru—v3—dirilis, yang juga menggunakan patch penggabungan 3 arah dan menghilangkan Tiller. Versi Helm yang baru ini membutuhkan instalasi yang ada untuk mengubahnya ke format penyimpanan rilis baru.
Werf, pada bagiannya, sekarang telah menyingkirkan penggunaan Tiller, beralih ke penggabungan 3 arah dan menambahkan , sekaligus tetap kompatibel dengan instalasi Helm 2 yang ada (tidak memerlukan skrip migrasi). Oleh karena itu, hingga werf beralih ke Helm 3, pengguna werf tidak akan kehilangan keunggulan utama Helm 3 dibandingkan Helm 2 (werf juga memiliki keunggulan ini).
Namun, transisi werf ke basis kode Helm 3 tidak dapat dihindari dan akan terjadi dalam waktu dekat. Kemungkinan besar, ini akan terjadi pada werf 1.1 atau werf 1.2 (saat ini, versi werf utama adalah 1.0; untuk informasi lebih lanjut tentang versi werf, lihat ). Selama waktu ini, Helm 3 akan punya waktu untuk stabil.
PS
Baca juga di blog kami:
- Serangkaian catatan tentang inovasi di werf:
- «»;
- «»;
- «'.
- «»;
- «»;
- «'.
Sumber: www.habr.com
