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.
Jika 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 PUT
и PATCH
... Di mana update
и replace
menggunakan PUT
Dan patch
, betapapun sepelenya, tetap berguna PATCH
.
Perlu dicatat bahwa kubectl
juga bekerja dengan cluster melalui API. Dengan kata lain, kubectl
adalah 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 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 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 apply
untuk 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 apply
itu 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 edit
Dan 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 patch
untuk 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: 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
akanapplication/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.
Sumber: www.habr.com