Perbandingan yang Tepat antara Penerapan, Penggantian, dan Patch Kubernetes

Kubernetes memiliki beberapa opsi untuk memperbarui sumber daya: menerapkan, mengedit, menambal, dan mengganti. Ada kebingungan tentang apa yang dilakukan masing-masing perangkat dan kapan menggunakannya. Mari kita cari tahu.

Perbandingan yang Tepat antara Penerapan, Penggantian, dan Patch Kubernetes

Jika cari di Google frasa "kubernetes apply vs replace" berada membalas StackOverflow, yang tidak benar. Saat mencari "kubernetes apply vs patch" tautan pertama adalah dokumentasinya kubectl patch, yang tidak termasuk perbandingan apply и patch. Artikel ini akan membahas berbagai opsi, serta penggunaan yang tepat dari masing-masing opsi.

Selama siklus hidup sumber daya Kubernetes (layanan, penerapan, ingress, dll.), terkadang Anda perlu mengubah, menambah, atau menghapus beberapa properti sumber daya ini. Misalnya menambah catatan, menambah atau mengurangi jumlah replika.

CLI Kubernetes

Jika Anda sudah bekerja dengan cluster Kubernetes melalui CLI, Anda sudah familiar dengannya apply и edit. Tim apply membaca spesifikasi sumber daya dari file dan membuat "upsert" ke cluster Kubernetes, mis. membuat sumber daya jika tidak ada dan memperbaruinya jika ada. Tim edit membaca sumber daya melalui API, lalu menulis spesifikasi sumber daya ke file lokal, yang kemudian dibuka di editor teks. Setelah Anda mengedit dan menyimpan file, kubectl akan mengirimkan kembali perubahan yang dilakukan melalui API, yang akan menerapkan perubahan ini dengan hati-hati ke sumber daya.

Tidak semua orang mengetahui perintahnya patch и replace. Tim patch memungkinkan Anda mengubah sebagian spesifikasi sumber daya, hanya menyediakan bagian yang diubah pada baris perintah. Tim replace bekerja sama dengan edit, tetapi semuanya perlu dilakukan secara manual: Anda perlu mengunduh versi spesifikasi sumber daya saat ini, misalnya menggunakan kubectl get -o yaml, edit, lalu gunakan replace untuk memperbarui sumber daya sesuai dengan spesifikasi yang diubah. Tim replace tidak akan berfungsi jika ada perubahan yang terjadi antara membaca dan mengganti sumber daya.

API Kubernetes

Anda mungkin sudah familiar dengan metodenya CoreV1().Pods().Update(), replaceNamespacedService или patch_namespaced_deployment, jika Anda bekerja dengan cluster melalui perpustakaan klien untuk API Kubernetes menggunakan beberapa bahasa pemrograman. Pustaka menangani metode ini melalui permintaan HTTP menggunakan metode PUT и PATCH... Di mana update и replace menggunakan PUTDan patch, betapapun sepelenya, tetap berguna PATCH.

Perlu dicatat bahwa kubectl juga bekerja dengan cluster melalui API. Dengan kata lain, kubectladalah pembungkus di atas pustaka klien untuk bahasa Go, yang sebagian besar menyediakan kemampuan untuk menyediakan subperintah dalam bentuk yang lebih ringkas dan mudah dibaca selain kemampuan API standar. Misalnya, seperti yang mungkin sudah Anda ketahui, metodenya apply tidak disebutkan di atas pada paragraf sebelumnya. Saat ini (Mei 2020, kira-kira Penerjemah) semua logika kubectl apply, yaitu. membuat sumber daya yang tidak ada dan memperbarui sumber daya yang sudah ada, bekerja sepenuhnya di sisi kode kubectl. Upaya sedang dilakukan pada transfer logika apply ke sisi API, tapi masih dalam versi beta. Lebih lengkapnya akan saya tuliskan dibawah ini.

Tambalan secara default

Paling baik digunakan patch, jika Anda ingin memperbarui sumber daya. Beginilah cara kedua perpustakaan klien bekerja di atas API Kubernetes dan kubectl (tidak mengherankan, karena ini adalah pembungkus perpustakaan klien, kira-kira Penerjemah).

Bekerja secara strategis

Semua tim kubectl apply, edit и patch gunakan metode tersebut PATCH dalam permintaan HTTP untuk memperbarui sumber daya yang ada. Jika Anda mempelajari implementasi perintah secara lebih rinci, maka semuanya menggunakan pendekatan ini patching penggabungan strategis untuk memperbarui sumber daya, meskipun perintah patch dapat menggunakan pendekatan lain (lebih lanjut tentang ini di bawah). Pendekatan patching penggabungan strategis berupaya untuk "melakukannya dengan benar" dengan menggabungkan spesifikasi yang disediakan dengan spesifikasi yang ada. Lebih khusus lagi, ia mencoba menggabungkan objek dan array, yang berarti perubahannya cenderung bersifat aditif. Misalnya menjalankan perintah patch dengan adanya variabel lingkungan baru dalam spesifikasi kontainer pod, menyebabkan variabel lingkungan tersebut ditambahkan ke variabel lingkungan yang ada daripada menimpanya. Untuk menghapus menggunakan pendekatan ini, Anda harus memaksa nilai parameter ke null dalam spesifikasi yang disediakan. Tim yang mana kubectl Apakah yang terbaik digunakan untuk memperbarui?

Jika Anda membuat dan mengelola sumber daya menggunakan kubectl apply, saat update lebih baik selalu gunakan kubectl applyuntuk kubectl dapat mengelola konfigurasi dan melacak perubahan yang diminta dengan benar dari satu aplikasi ke aplikasi lainnya. Keuntungan selalu digunakan apply adalah ia melacak spesifikasi yang diterapkan sebelumnya, memungkinkannya mengetahui kapan properti spesifikasi dan elemen array dihapus secara eksplisit. Ini memungkinkan Anda untuk menggunakan apply untuk menghapus properti dan elemen array, sementara penggabungan strategis normal tidak akan berfungsi. Tim edit и patch jangan perbarui catatan itu kubectl apply digunakan untuk melacak perubahannya, jadi setiap perubahan yang dilacak dan dilakukan melalui API Kubernetes, tetapi dilakukan melalui perintah edit и patch, tidak terlihat oleh perintah berikutnya applyitu adalah apply tidak menghapusnya meskipun tidak muncul dalam spesifikasi masukan apply (Dokumentasi mengatakan itu edit и patch melakukan pembaruan pada catatan yang digunakan apply, tetapi dalam praktiknya - tidak).

Jika Anda tidak menggunakan perintah apply, dapat digunakan sebagai editDan patch, memilih perintah yang paling sesuai dengan perubahan yang dilakukan. Saat menambahkan dan mengubah properti BOM, kedua pendekatan tersebut kurang lebih sama. Saat menghapus properti spesifikasi atau elemen array edit berperilaku seperti peluncuran satu kali apply, termasuk melacak spesifikasi sebelum dan sesudah diedit, sehingga Anda dapat secara eksplisit menghapus properti dan elemen array dari sumber daya. Anda perlu secara eksplisit menyetel nilai properti ke null dalam spesifikasinya patchuntuk menghapusnya dari sumber daya. Menghapus elemen array menggunakan patching penggabungan strategis lebih rumit karena memerlukan penggunaan arahan penggabungan. Lihat pendekatan peningkatan lainnya di bawah untuk alternatif yang lebih layak.

Untuk menerapkan metode pembaruan di perpustakaan klien yang berperilaku serupa dengan perintah di atas kubectl, harus diatur dalam permintaan content-type в application/strategic-merge-patch+json. Jika Anda ingin menghapus properti dalam suatu spesifikasi, Anda perlu menyetel nilainya secara eksplisit ke null dengan cara yang sama kubectl patch. Jika Anda perlu menghapus elemen array, Anda harus menyertakan arahan penggabungan dalam spesifikasi pembaruan atau menggunakan pendekatan berbeda untuk pembaruan.

Pendekatan lain terhadap pembaruan

Kubernetes mendukung dua pendekatan pembaruan lainnya: tambalan penggabungan JSON и tambalan JSON. Pendekatan patch penggabungan JSON menggunakan sebagian spesifikasi Kubernetes sebagai masukan dan mendukung penggabungan objek yang serupa dengan pendekatan patching penggabungan strategis. Perbedaan keduanya adalah hanya mendukung penggantian array, termasuk array container pada spesifikasi pod. Artinya, saat menggunakan patch penggabungan JSON, Anda perlu memberikan spesifikasi lengkap untuk semua container jika ada properti container yang berubah. Jadi pendekatan ini berguna untuk menghapus elemen dari array di BOM. Pada baris perintah Anda dapat memilih menggunakan patch penggabungan JSON kubectl patch --type=merge. Saat bekerja dengan API Kubernetes, Anda harus menggunakan metode permintaan PATCH dan instalasi content-type в application/merge-patch+json.

Pendekatan patch JSON, alih-alih menyediakan sebagian spesifikasi sumber daya, menggunakan penyediaan perubahan yang ingin Anda buat pada sumber daya sebagai array, di mana setiap elemen array mewakili deskripsi perubahan yang dilakukan pada sumber daya. Pendekatan ini adalah cara yang lebih fleksibel dan ampuh untuk mengekspresikan perubahan yang dibuat, namun dengan mengorbankan pencatatan perubahan yang dibuat dalam format non-Kubernetes yang terpisah, dibandingkan mengirimkan sebagian spesifikasi sumber daya. DI DALAM kubectl Anda dapat memilih patch JSON menggunakan kubectl patch --type=json. Saat menggunakan API Kubernetes, pendekatan ini bekerja menggunakan metode permintaan PATCH dan instalasi content-type в application/json-patch+json.

Kami membutuhkan kepercayaan diri - gunakan pengganti

Dalam beberapa kasus, Anda perlu memastikan bahwa tidak ada perubahan yang dilakukan pada sumber daya antara saat sumber daya tersebut dibaca dan saat sumber daya tersebut diperbarui. Dengan kata lain, Anda harus memastikan bahwa semua perubahan akan terjadi atom. Dalam hal ini, untuk memperbarui sumber daya yang harus Anda gunakan replace. Misalnya, jika Anda memiliki ConfigMap dengan penghitung yang diperbarui oleh beberapa sumber, Anda harus yakin bahwa dua sumber tidak memperbarui penghitung secara bersamaan, sehingga menyebabkan pembaruan hilang. Untuk mendemonstrasikannya, bayangkan rangkaian peristiwa menggunakan pendekatan tersebut patch:

  • A dan B mendapatkan status sumber daya saat ini dari API
  • Masing-masing memperbarui spesifikasi secara lokal dengan menambah penghitung sebanyak satu dan juga menambahkan "A" atau "B" masing-masing ke catatan "diperbarui oleh"
  • Dan itu memperbarui sumber daya sedikit lebih cepat
  • B memperbarui sumber daya

Akibatnya update A hilang. Operasi terakhir patch menang, penghitung bertambah satu, bukan dua, dan nilai not "diperbarui oleh" diakhiri dengan "B" dan tidak mengandung "A". Mari kita bandingkan hal di atas dengan apa yang terjadi ketika pembaruan dilakukan menggunakan pendekatan ini replace:

  • A dan B mendapatkan status sumber daya saat ini dari API
  • Masing-masing memperbarui spesifikasi secara lokal dengan menambah penghitung sebanyak satu dan juga menambahkan "A" atau "B" masing-masing ke catatan "diperbarui oleh"
  • Dan itu memperbarui sumber daya sedikit lebih cepat
  • B mencoba memperbarui sumber daya, tetapi pembaruan ditolak oleh API karena versi sumber daya ada dalam spesifikasi replace tidak cocok dengan versi sumber daya saat ini di Kubernetes karena versi sumber daya ditingkatkan oleh operasi penggantian A.

Dalam kasus di atas, B harus mengambil kembali sumber daya, membuat perubahan pada status baru, dan mencoba lagi replace. Hal ini akan menyebabkan penghitung bertambah dua dan catatan "diperbarui oleh" menyertakan "AB" di akhir.

Contoh di atas menyiratkan hal itu ketika mengeksekusi replace Seluruh sumber daya diganti sepenuhnya. Spesifikasi yang digunakan untuk replace, tidak boleh sebagian, atau sebagian seperti pada apply, tapi lengkap, termasuk tambahannya resourceVersion ke dalam metadata spesifikasi. Jika Anda belum mengaktifkannya resourceVersion atau versi yang Anda berikan bukan versi terbaru, penggantian akan ditolak. Jadi pendekatan terbaik untuk digunakan adalah replace – baca sumber daya, perbarui dan segera ganti. Menggunakan kubectl, mungkin terlihat seperti ini:

$ kubectl get deployment my-deployment -o json 
    | jq '.spec.template.spec.containers[0].env[1].value = "new value"' 
    | kubectl replace -f -

Perlu dicatat bahwa dua perintah berikut, yang dijalankan secara berurutan, akan berhasil dijalankan deployment.yaml tidak mengandung properti .metadata.resourceVersion

$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml

Hal ini tampaknya bertentangan dengan apa yang dikatakan di atas, yaitu. "menambahkan resourceVersion ke dalam metadata spesifikasi." Apakah salah mengatakan itu? Tidak, tidak, karena jika kubectl pemberitahuan yang tidak Anda tentukan resourceVersion, ia akan membacanya dari sumber daya dan menambahkannya ke spesifikasi yang Anda tentukan, dan baru kemudian menjalankannya replace. Karena ini berpotensi berbahaya jika Anda mengandalkan atomisitas, keajaiban bekerja sepenuhnya di samping kubectl, Anda tidak boleh mengandalkannya saat menggunakan perpustakaan klien yang bekerja dengan API. Dalam hal ini Anda harus membaca spesifikasi sumber daya saat ini, memperbaruinya, lalu menjalankannya PUT meminta.

Anda tidak dapat melakukan penambalan – kami melakukan penggantian

Terkadang Anda perlu melakukan beberapa perubahan yang tidak dapat ditangani oleh API. Dalam kasus ini, Anda dapat memaksa penggantian sumber daya dengan menghapus dan membuatnya kembali. Ini dilakukan dengan menggunakan kubectl replace --force. Menjalankan perintah akan segera menghapus sumber daya dan kemudian membuatnya kembali dari spesifikasi yang disediakan. Tidak ada pengendali "penggantian paksa" di API, dan untuk melakukannya melalui API, Anda perlu melakukan dua operasi. Pertama, Anda perlu menghapus sumber daya dengan mengaturnya gracePeriodSeconds menjadi nol (0) dan propagationPolicy di “Latar Belakang” lalu buat ulang sumber daya ini dengan spesifikasi yang diinginkan.

Peringatan: Pendekatan ini berpotensi berbahaya dan dapat menyebabkan keadaan tidak terdefinisi.

Terapkan di sisi server

Seperti disebutkan di atas, pengembang Kubernetes sedang berupaya mengimplementasikan logika tersebut apply dari kubectl di API Kubernetes. Logika apply tersedia di Kubernetes 1.18 melalui kubectl apply --server-side atau melalui API menggunakan metode ini PATCH с content-type application/apply-patch+YAML.

Catatan: JSON juga merupakan YAML yang valid, sehingga Anda dapat mengirimkan spesifikasinya sebagai JSON meskipun content-type akan application/apply-patch+yaml.

Selain logika itu kubectl menjadi tersedia untuk semua orang melalui API, apply di sisi server, melacak siapa yang bertanggung jawab atas bidang dalam spesifikasi, sehingga memungkinkan akses ganda yang aman untuk pengeditan bebas konflik. Dengan kata lain, jika apply di sisi server akan menjadi lebih luas, antarmuka manajemen sumber daya aman universal akan muncul untuk klien yang berbeda, misalnya kubectl, Pulumi atau Terraform, GitOps, serta skrip yang ditulis sendiri menggunakan perpustakaan klien.

Hasil

Saya harap ikhtisar singkat tentang berbagai cara memperbarui sumber daya dalam cluster ini bermanfaat bagi Anda. Ada baiknya untuk mengetahui bahwa ini bukan hanya menerapkan versus mengganti; memperbarui sumber daya dapat dilakukan dengan menerapkan, mengedit, menambal, atau mengganti. Memang, pada prinsipnya, setiap pendekatan memiliki cakupannya masing-masing. Untuk perubahan atom, penggantian lebih disukai; jika tidak, Anda harus menggunakan patch penggabungan strategis melalui penerapan. Setidaknya, saya berharap Anda memahami bahwa Anda tidak dapat mempercayai Google atau StackOerflow saat mencari "kubernetes apply vs replace". Setidaknya hingga artikel ini menggantikan jawaban saat ini.

Perbandingan yang Tepat antara Penerapan, Penggantian, dan Patch Kubernetes

Sumber: www.habr.com

Tambah komentar