Penggabungan 3 arah ke werf: penerapan ke Kubernetes dengan Helm “dengan steroid”

Apa yang telah lama kami (dan bukan hanya kami) tunggu-tunggu telah terjadi: wer, utilitas Sumber Terbuka kami untuk membangun aplikasi dan mengirimkannya ke Kubernetes, kini mendukung penerapan perubahan menggunakan patch penggabungan 3 arah! Selain itu, dimungkinkan untuk mengadopsi sumber daya K8 yang ada ke dalam rilis Helm tanpa membangun kembali sumber daya tersebut.

Penggabungan 3 arah ke werf: penerapan ke Kubernetes dengan Helm “dengan steroid”

Jika sangat pendek, maka kita masukkan WERF_THREE_WAY_MERGE=enabled — kami mendapatkan penerapan “seperti dalam kubectl apply", kompatibel dengan instalasi Helm 2 yang ada dan bahkan lebih banyak lagi.

Tapi mari kita mulai dengan teorinya: apa sebenarnya patch penggabungan 3 arah itu, bagaimana orang-orang menemukan pendekatan untuk menghasilkan patch tersebut, dan mengapa patch tersebut penting dalam proses CI/CD dengan infrastruktur berbasis Kubernetes? Dan setelah itu mari kita lihat apa itu 3-way-merge di werf, mode apa saja yang digunakan secara default dan bagaimana cara mengelolanya.

Apa itu patch penggabungan 3 arah?

Jadi, mari kita mulai dengan tugas meluncurkan sumber daya yang dijelaskan dalam manifes YAML ke dalam Kubernetes.

Untuk bekerja dengan sumber daya, Kubernetes API menawarkan operasi dasar berikut: membuat, menambal, mengganti, dan menghapus. Diasumsikan bahwa dengan bantuan mereka, perlu untuk membangun peluncuran sumber daya yang berkelanjutan dan nyaman ke dalam cluster. Bagaimana?

perintah kubectl imperatif

Pendekatan pertama dalam mengelola objek di Kubernetes adalah dengan menggunakan perintah kubectl imperatif untuk membuat, memodifikasi, dan menghapus objek tersebut. Sederhananya:

  • tim kubectl run Anda 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

Sekilas pendekatan ini mungkin tampak nyaman. Namun ada masalah:

  1. Sulit mengotomatisasikan.
  2. Как mencerminkan konfigurasi di Git? Bagaimana cara meninjau perubahan yang terjadi pada cluster?
  3. Bagaimana cara menyediakannya reproduktifitas konfigurasi saat restart?
  4. ...

Jelas bahwa pendekatan ini tidak cocok dengan penyimpanan aplikasi dan infrastruktur sebagai kode (IaC; atau bahkan GitOps sebagai pilihan yang lebih modern, mendapatkan popularitas di ekosistem Kubernetes). Oleh karena itu, perintah-perintah ini tidak dikembangkan lebih lanjut di kubectl.

Membuat, mendapatkan, mengganti dan menghapus operasi

Dengan primer penciptaan sederhana saja: kirim manifes ke operasi create kube api dan sumber daya telah dibuat. Representasi YAML dari manifes dapat disimpan di Git dan dibuat menggunakan perintah kubectl create -f manifest.yaml.

С menghapus juga sederhana: gantikan yang sama manifest.yaml dari Git ke tim kubectl delete -f manifest.yaml.

Operasi replace memungkinkan Anda mengganti sepenuhnya konfigurasi sumber daya dengan yang baru, tanpa membuat ulang sumber daya. Artinya, sebelum membuat perubahan pada sumber daya, logis untuk menanyakan versi saat ini dengan operasi tersebut get, ubah dan perbarui dengan operasi replace. kube apiserver sudah ada di dalamnya penguncian optimis dan, jika setelah operasi get objek telah berubah, lalu operasi replace tidak akan lulus.

Untuk menyimpan konfigurasi di Git dan memperbaruinya menggunakan penggantian, Anda perlu melakukan operasi get, gabungkan konfigurasi dari Git dengan apa yang kami terima, dan jalankan replace. Secara default, kubectl hanya mengizinkan Anda menggunakan perintah kubectl replace -f manifest.yamlDimana manifest.yaml — manifes yang sudah disiapkan sepenuhnya (dalam kasus kami, digabungkan) yang perlu diinstal. Ternyata pengguna perlu mengimplementasikan manifes gabungan, dan ini bukan masalah sepele...

Perlu juga dicatat bahwa meskipun demikian manifest.yaml dan disimpan di Git, kita tidak dapat mengetahui sebelumnya apakah perlu membuat objek atau memperbaruinya - ini harus dilakukan oleh perangkat lunak pengguna.

Total: bisakah kita membangun peluncuran 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 Anda perlu menerapkan operasi penggabungan manifesto dan semacam pengikatan yang:

  • memeriksa keberadaan suatu objek di cluster,
  • melakukan pembuatan sumber daya awal,
  • memperbarui atau menghapusnya.

Saat memperbarui, harap perhatikan itu sumber daya mungkin telah berubah sejak terakhir get dan secara otomatis menangani kasus penguncian optimis - melakukan upaya pembaruan berulang kali.

Namun, untuk apa menemukan kembali roda ketika kube-apiserver menawarkan cara lain untuk memperbarui sumber daya: operasi patch, yang meringankan pengguna dari beberapa masalah yang dijelaskan?

tambalan

Sekarang kita sampai pada tambalannya.

Patch adalah cara utama untuk menerapkan perubahan pada objek yang ada di Kubernetes. Operasi patch ini berfungsi seperti ini:

  • pengguna kube-apiserver perlu mengirimkan patch dalam bentuk JSON dan menentukan objeknya,
  • dan apiserver sendiri akan menangani keadaan objek saat ini dan membawanya ke bentuk yang diperlukan.

Penguncian optimis tidak diperlukan dalam kasus ini. Operasi ini lebih bersifat deklaratif daripada penggantian, meskipun pada awalnya mungkin terlihat sebaliknya.

Demikian:

  • menggunakan suatu operasi create kita membuat objek sesuai manifes dari Git,
  • melalui delete — hapus jika objek tidak diperlukan lagi,
  • melalui patch — kita mengubah objeknya, membawanya ke bentuk yang dijelaskan di Git.

Namun, untuk melakukan ini, Anda perlu membuatnya tambalan yang benar!

Cara kerja patch di Helm 2: penggabungan 2 arah

Saat Anda pertama kali menginstal rilis, Helm melakukan operasinya create untuk sumber daya bagan.

Saat memperbarui rilis Helm untuk setiap sumber daya:

  • mempertimbangkan patch antara versi sumber daya dari bagan sebelumnya dan versi bagan saat ini,
  • menerapkan tambalan ini.

Kami akan menyebutnya tambalan ini Patch penggabungan 2 arah, karena 2 manifesto terlibat dalam pembuatannya:

  • manifes sumber daya dari rilis sebelumnya,
  • manifes sumber daya dari sumber daya saat ini.

Saat melepas operasi delete di kube apiserver dipanggil untuk sumber daya yang dideklarasikan pada rilis sebelumnya, namun tidak dideklarasikan pada rilis saat ini.

Pendekatan patch penggabungan 2 arah memiliki masalah: mengarah ke tidak sinkron dengan keadaan sebenarnya dari sumber daya di cluster dan manifes di Git.

Ilustrasi masalah beserta contohnya

  • Di Git, bagan menyimpan manifes yang berisi bidang tersebut image Penempatan itu penting ubuntu:18.04.
  • Pengguna melalui kubectl edit mengubah nilai bidang ini menjadi ubuntu:19.04.
  • Saat menerapkan kembali bagan Helm tidak menghasilkan tambalan, karena lapangan image di versi rilis sebelumnya dan di chart saat ini adalah sama.
  • Setelah penempatan ulang image sisa ubuntu:19.04, meskipun bagan menyatakan ubuntu:18.04.

Kami mengalami desinkronisasi dan kehilangan sifat deklaratif.

Apa yang dimaksud dengan sumber daya yang disinkronkan?

Secara umum lengkap Tidak mungkin mendapatkan kecocokan antara manifes sumber daya di klaster yang sedang berjalan dan manifes dari Git. Karena dalam manifes nyata mungkin terdapat anotasi/label layanan, penampung tambahan, dan data lain yang ditambahkan dan dihapus dari sumber daya secara dinamis oleh beberapa pengontrol. Kami tidak dapat dan tidak ingin menyimpan data ini di Git. Namun, kami ingin bidang yang kami tentukan secara eksplisit di Git mengambil nilai yang sesuai saat diluncurkan.

Ternyata sangat umum aturan sumber daya yang disinkronkan: saat meluncurkan sumber daya, Anda hanya dapat mengubah atau menghapus bidang yang secara eksplisit ditentukan dalam manifes dari Git (atau ditentukan dalam versi sebelumnya dan sekarang dihapus).

Patch penggabungan 3 arah

ide sentral Patch penggabungan 3 arah: kami membuat patch antara versi manifes yang terakhir diterapkan dari Git dan versi manifes target dari Git, dengan mempertimbangkan versi manifes saat ini dari cluster yang sedang berjalan. Patch yang dihasilkan harus mematuhi aturan sumber daya yang disinkronkan:

  • bidang baru yang ditambahkan ke versi target ditambahkan menggunakan tambalan;
  • bidang yang ada sebelumnya di versi terakhir yang diterapkan dan tidak ada di versi target diatur ulang menggunakan tambalan;
  • bidang dalam versi objek saat ini yang berbeda dari versi manifes target diperbarui menggunakan patch.

Berdasarkan prinsip inilah ia menghasilkan tambalan kubectl apply:

  • versi manifes yang terakhir diterapkan disimpan dalam anotasi objek itu sendiri,
  • target - diambil dari file YAML yang ditentukan,
  • yang saat ini berasal dari cluster yang sedang berjalan.

Sekarang setelah kami memilah teorinya, sekarang saatnya 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 beralih ke jenis tambalan baru - penggabungan 3 arah - langkah pertama kami memperkenalkan apa yang disebut tambalan perbaikan.

Saat diterapkan, patch penggabungan 2 arah standar digunakan, tetapi werf juga menghasilkan patch yang akan menyinkronkan keadaan sebenarnya dari sumber daya dengan apa yang tertulis di Git (patch tersebut dibuat menggunakan aturan sumber daya tersinkronisasi yang sama seperti yang dijelaskan di atas) .

Jika desinkronisasi terjadi, di akhir penerapan, pengguna menerima PERINGATAN dengan pesan terkait dan patch yang harus diterapkan untuk membawa sumber daya ke bentuk yang disinkronkan. Tambalan ini juga dicatat dalam anotasi khusus werf.io/repair-patch. Diasumsikan bahwa tangan pengguna dirinya sendiri akan menerapkan tambalan ini: werf tidak akan menerapkannya sama sekali.

Membuat patch perbaikan adalah tindakan sementara yang memungkinkan Anda benar-benar menguji pembuatan patch berdasarkan prinsip penggabungan 3 arah, namun tidak secara otomatis menerapkan patch ini. Saat ini, mode operasi ini diaktifkan secara default.

Patch penggabungan 3 arah hanya untuk rilis baru

Mulai 1 Desember 2019, werf versi beta dan alfa dimulai secara default gunakan patch penggabungan 3 arah yang lengkap untuk menerapkan perubahan hanya pada rilis Helm baru yang diluncurkan melalui werf. Rilis yang ada akan terus menggunakan pendekatan penggabungan 2 arah + patch perbaikan.

Mode operasi ini dapat diaktifkan secara eksplisit dengan pengaturan WERF_THREE_WAY_MERGE_MODE=onlyNewReleases sekarang.

Catatan: fitur tersebut muncul di werf selama beberapa rilis: di saluran alfa, fitur tersebut sudah siap dengan versi v1.0.5-alpha.19, dan di saluran beta - dengan v1.0.4-beta.20.

Patch penggabungan 3 arah untuk semua rilis

Mulai 15 Desember 2019, versi beta dan alfa dari werf mulai menggunakan patch penggabungan 3 arah penuh secara default untuk menerapkan perubahan pada semua rilis.

Mode operasi ini dapat diaktifkan secara eksplisit dengan pengaturan WERF_THREE_WAY_MERGE_MODE=enabled sekarang.

Apa yang harus dilakukan dengan penskalaan otomatis sumber daya?

Ada 2 jenis penskalaan otomatis di Kubernetes: HPA (horizontal) dan VPA (vertikal).

Horizontal secara otomatis memilih jumlah replika, vertikal - jumlah sumber daya. Jumlah replika dan kebutuhan sumber daya ditentukan dalam manifes sumber daya (lihat Manifes Sumber Daya). spec.replicas или spec.containers[].resources.limits.cpu, spec.containers[].resources.limits.memory и lain).

Masalah: jika pengguna mengonfigurasi sumber daya dalam bagan sehingga menentukan nilai tertentu untuk sumber daya atau replika dan penskala otomatis diaktifkan untuk sumber daya ini, maka dengan setiap penerapan werf akan mengatur ulang nilai-nilai ini ke apa yang tertulis dalam manifes bagan .

Ada dua solusi untuk masalah ini. Untuk memulainya, sebaiknya hindari menentukan nilai skala otomatis secara eksplisit dalam manifes bagan. Jika opsi ini tidak cocok karena alasan tertentu (misalnya, karena lebih mudah untuk menetapkan batas sumber daya awal dan jumlah replika dalam bagan), maka werf menawarkan anotasi berikut:

  • werf.io/set-replicas-only-on-creation=true
  • werf.io/set-resources-only-on-creation=true

Jika anotasi seperti itu ada, werf tidak akan menyetel ulang nilai terkait pada setiap penerapan, tetapi hanya akan menyetelnya saat sumber daya pertama kali dibuat.

Untuk detail lebih lanjut, lihat dokumentasi proyek untuk HPA и VPA.

Melarang penggunaan patch penggabungan 3 arah

Pengguna saat ini dapat melarang penggunaan patch baru di werf menggunakan variabel lingkungan WERF_THREE_WAY_MERGE_MODE=disabled. Namun, memulai Mulai 1 Maret 2020, larangan ini tidak berlaku lagi. dan hanya mungkin menggunakan patch penggabungan 3 arah.

Adopsi sumber daya di werf

Menguasai metode penerapan perubahan dengan patch penggabungan 3 arah memungkinkan kami untuk segera mengimplementasikan fitur seperti mengadopsi sumber daya yang ada di cluster ke dalam rilis Helm.

Helm 2 memiliki masalah: Anda tidak dapat menambahkan sumber daya ke manifes bagan yang sudah ada di cluster tanpa membuat ulang sumber daya ini dari awal (lihat. #6031, #3275). Kami mengajari kami untuk menerima sumber daya yang ada untuk dirilis. Untuk melakukan ini, Anda perlu menginstal anotasi pada versi sumber daya saat ini dari cluster yang sedang berjalan (misalnya, menggunakan kubectl edit):

"werf.io/allow-adoption-by-release": RELEASE_NAME

Sekarang sumber daya perlu dijelaskan dalam bagan dan pada saat werf menyebarkan rilis dengan nama yang sesuai, sumber daya yang ada akan diterima dalam rilis ini dan tetap berada di bawah kendalinya. Selain itu, dalam proses penerimaan sumber daya untuk dirilis, werf akan membawa status sumber daya saat ini dari cluster 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 mempengaruhi adopsi sumber daya - dalam kasus adopsi, patch penggabungan 3 arah selalu digunakan.

Detail - masuk dokumentasi.

Kesimpulan dan rencana masa depan

Saya harap setelah artikel ini menjadi lebih jelas apa itu patch penggabungan 3 arah dan mengapa patch tersebut muncul. Dari sudut pandang praktis pengembangan proyek werf, implementasinya merupakan langkah lain menuju peningkatan penerapan mirip Helm. Sekarang Anda bisa melupakan masalah sinkronisasi konfigurasi yang sering muncul saat menggunakan Helm 2. Pada saat yang sama, fitur baru yang berguna untuk mengadopsi sumber daya Kubernetes yang sudah diunduh telah ditambahkan ke rilis Helm.

Masih ada beberapa masalah dan tantangan dalam penerapan Helm-like, seperti penggunaan template Go, yang akan terus kami atasi.

Informasi tentang metode pembaruan sumber daya dan penerapannya juga dapat ditemukan di halaman dokumentasi ini.

helm 3

Layak mendapat catatan khusus dilepaskan beberapa hari yang lalu versi utama baru dari Helm - v3 - yang juga menggunakan patch penggabungan 3 arah dan menghilangkan Tiller. Helm versi baru membutuhkan migrasi instalasi yang ada untuk mengubahnya menjadi format penyimpanan rilis baru.

Werf, pada bagiannya, saat ini telah berhenti menggunakan Tiller, beralih ke penggabungan 3 arah dan menambahkan lebih banyak, namun tetap kompatibel dengan instalasi Helm 2 yang ada (tidak ada skrip migrasi yang perlu dijalankan). Oleh karena itu, hingga werf beralih ke Helm 3, pengguna werf tidak kehilangan keunggulan utama Helm 3 dibandingkan Helm 2 (werf juga memilikinya).

Namun, peralihan werf ke basis kode Helm 3 tidak dapat dihindari dan akan terjadi dalam waktu dekat. Agaknya ini adalah werf 1.1 atau werf 1.2 (saat ini, versi utama werf adalah 1.0; untuk informasi lebih lanjut tentang perangkat versi werf, lihat di sini). Selama waktu ini, Helm 3 akan memiliki waktu untuk stabil.

PS

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komentar