Disrupsi
Petunjuk ini ditujukan pada pemilik aplikasi yang meninginkan aplikasinya memiliki ketersediaan yang tinggi, sehingga butuh untuk mengerti jenis-jenis Disrupsi yang dapat terjadi pada Pod-pod.
Petunjuk ini juga ditujukan pada administrator klaster yang ingin melakukan berbagai tindakan otomasi pada klaster, seperti pembaruan dan autoscaling klaster.
Disrupsi yang Disengaja dan Tidak Disengaja
Pod-pod tidak akan terhapus sampai sesuatu (orang ataupun pengendali) menghancurkan mereka atau ada kesalahan perangkat keras maupun perangkat lunak yang tidak dapat dihindari.
Kita menyebut kasus-kasus yang tidak dapat dihindari sebagai disrupsi yang tidak disengaja terhadap aplikasi. Beberapa contohnya adalah sebagai berikut:
- Kesalahan perangkat keras pada mesin yang menjalankan Node
- Administrator klaster menghapus virtual machine secara tidak sengaja
- Kesalahan pada penyedia layanan cloud yang mengakibatkan terhapusnya virtual machine
- Sebuah kernel panic
- Node menghilang dari klaster karena partisi jaringan klaster
- Pod mengalami eviction karena Node kehabisan sumber daya
Dengan pengecualian pada kondisi kehabisan sumber daya, kondisi-kondisi tersebut pada umumnya diketahui oleh kebanyakan pengguna karena kondisi-kondisi tersebut tidak spesifik pada Kubernetes saja.
Kita menyebut kasus-kasus lainnya sebagai disrupsi yang disengaja. Hal ini termasuk tindakan yang dilakukan oleh pemilik aplikasi atau yang dilakukan oleh administrator klaster. Pemilik aplikasi umumnya melakukan hal-hal berikut:
- Menghapus Deployment atau pengendali yang mengatur Pod
- Memperbarui templat Pod yang menyebabkan pengulangan kembali/restart
- Menghapus Pod secara langsung
Administrator klaster umumnya melakukan hal-hal berikut:
- Melakukan drain terhadap Node untuk perbaikan atau pembaruan.
- Melakukan drain terhadap sebuah node dari klaster untuk memperkecil ukuran klaster (untuk lebih lanjutnya, pelajari Autoscaling klaster).
- Menghapus sebuah Pod dari node untuk memuat Pod lain ke node tersebut.
Tindakan-tindakan tersebut dapat dilakukan secara langsung oleh administrator klaster, atau oleh alat otomasi yang dijalankan oleh administrator klaster, atau oleh penyedia layanan Kubernetes kamu.
Tanyakan administrator klaster atau penyedia layanan cloud kamu, atau lihatlah dokumentasi penyedia layanan Kubernetes kamu untuk mengetahui bila ada sumber-sumber yang berpotensi mengakibatkan disrupsi yang disengaja yang ada pada klastermu. Jika tidak ada, kamu bisa melewatkan pembuatan PodDisruptionBudget
Perhatian:
Tidak semua disrupsi yang disengaja dibatasi oleh Pod Disruption Budget. Contohnya, menghapus Deployment atau Pod dapat mengabaikan PodDisruptionBudget.Mengatasi Disrupsi
Berikut beberapa cara untuk mengatasi disrupsi yang tidak disengaja:
- Pastikan Pod-pod kamu merinci permintaan sumber daya klaster yang dibutuhkan.
- Replikasikan aplikasimu jika membutuhkan ketersediaan yang tinggi. (Pelajari tentang menjalankan aplikasi stateless dan stateful).
- Untuk mencapai ketersediaan yang bahkan lebih tinggi lagi saat mereplikasikan aplikasi, sebarkanlah Pod-pod kamu di rak-rak pada data center (menggunakan anti-affinity) atau di seluruh zona (jika kamu menggunakan klaster pada beberapa zona).
Frekuensi disrupsi yang disengaja dapat berubah-ubah. Pada klaster Kubernetes yang dasar, tidak ada disrupsi yang disengaja sama sekali. Tetapi, administrator klaster atau penyedia layanan Kubernetes kamu mungkin saja menjalankan beberapa servis tambahan yang dapat mengakibatkan disrupsi yang disengaja. Misalnya, memperbarui perangkat lunak pada node yang dapat mengakibatkan disrupsi yang disengaja. Selain itu, beberapa implementasi autoscaling klaster (atau node) dapat mengakibatkan disrupsi yang disengaja untuk merapikan dan memadatkan node-node pada klaster. Administrator klaster atau penyedia layanan Kubernetes kamu perlu mendokumentasikan tingkatan disrupsi yang disengaja, jika ada disrupsi yang telah diperkirakan.
Kubernetes menawarkan fitur-fitur untuk membantu menjalankan aplikasi-aplikasi dengan ketersediaan tinggi bersamaan dengan seringnya disrupsi yang disengaja, fitur-fitur tersebut dinamai Disruption Budget.
Bagaimana cara kerja Disruption Budget
Pemilik aplikasi dapat membuat objek PodDisruptionBudget
(PDB) untuk setiap aplikasi. Sebuah PDB membatasi jumlah Pod yang boleh mati secara bersamaan pada aplikasi yang direplikasi dikarenakan disrupsi yang disengaja.
Misalnya, sebuah aplikasi yang bekerja secara quorum mau memastikan bahwa jumlah replika yang berjalan tidak jatuh ke bawah yang dibutuhkan untuk membentuk sebuah quorum. Contoh lainnya, sebuah front-end web mungkin perlu memastikan bahwa jumlah replika yang melayani trafik tidak pernah turun ke total persentase yang telah ditentukan.
Administrator klaster dan penyedia layanan Kubernetes sebaiknya menggunakan alat-alat yang menghormati PDB dengan cara berkomunikasi dengan Eviction API dari pada menghapus Pod atau Deployment secara langsung. Contohnya adalah perintah kubectl drain
dan skrip pembaruan Kubernetes-on-GCE (cluster/gce/upgrade.sh
)
Saat seorang administrator klaster ingin melakukan drain terhadap sebuah node, ia akan menggunakan perintah kubectl drain
. Alat tersebut mencoba untuk "mengusir" semua Pod di node tersebut. Permintaan untuk mengusir Pod tersebut mungkin ditolak untuk sementara, dan alat tersebut akan mencoba ulang permintaannya secara periodik hingga semua Pod dihapus, atau hingga batas waktu yang ditentukan telah dicapai.
Sebua PDB merinci jumlah replika yang dapat ditoleransi oleh sebuah aplikasi, relatif terhadap berapa banyak yang seharusnya dimiliki oleh aplikasi tersebut. Sebagai contoh, sebuah Deployment yang memiliki rincian .spec.replicas :5
diharapkan memiliki 5 Pod pada satu waktu. Jika PDB aplikasi tersebut mengizinkan ada 4 replika pada satu waktu, maka Eviction API akan mengizinkan disrupsi yag disengaja sebanyak satu, tapi tidak mengizinkan dua, pada satu waktu.
Sebuah kelompok Pod yang mewakili aplikasi dispesifikasikan menggunakan sebuah label selector yang sama dengan yang digunakan oleh pengatur aplikasi tersebut (Deployment, StatefulSet, dsb.)
Jumlah Pod yang "diharapkan" dihitung dari .spec.replicas
dari pengendali Pod tersebut. Pengendali dari sebuah Pod dapat ditemukan di spesifikasi .metadata.ownerReferences
objek Pod yang bersangkutan.
PDB tidak dapat mencegah disrupsi yang tidak disengaja, tapi disrupsi ini akan dihitung terhadap bujet PDB.
Pod yang dihapus atau tidak tersetia dikarenakan pembaruan bertahap juga dihitung terhadap bujet PDB, tetapi pengendali (seperti Deployment dan StatefulSet) tidak dibatasi oleh PDB ketika melakukan pembaruan bertahap; Penanganan kerusakan saat pembaruan aplikasi dikonfigurasikan pada spesifikasi pengendali. (Pelajari tentang memperbarui sebuah Deployment.)
Saat sebuah Pod diusir menggunakan eviction API, Pod tersebut akan dihapus secara graceful (lihat terminationGracePeriodSeconds
pada PodSpec.))
Contoh PDB
Kita ambil contoh sebuah klaster dengan 3 node, node-1
hingga node-3
.
Klaster tersebut menjalankan beberapa aplikasi. Salah satu dari aplikasi tersebut awalnya memiliki 3 replika, yang akan kita namai Pod-a
, Pod-b
, dan Pod-c
. Sebuah Pod lain yang tidak bersangkutan dan tidak memiliki PDB, dinamai Pod-x
juga terlihat. Awalnya, Pod-pod tersebut berada pada node-node sebagai berikut:
node-1 | node-2 | node-3 |
---|---|---|
Pod-a available | Pod-b available | Pod-c available |
Pod-x available |
3 Pod Pod-a
hingga Pod-c
adalah bagian dari sebuah Deployment, dan mereka secara kolektif memiliki sebuah PDB yang mengharuskan ada setidaknya 2 dari 3 Pod untuk tersedia sepanjang waktu.
Sebagai contoh, asumsikan administrator klaster ingin me-reboot ke dalam versi kernel baru untuk memperbaiki kesalahan di dalam kernel lama. Administator klaster pertama-tama mencoba untuk melakukan drain terhadap node-1
menggunakan perintah kubectl drain
. Perintah tersebut mencoba untuk mengusir Pod-a
dan Pod-x
. Hal ini langsung berhasil. Kedua Pod tersebut masuk ke dalam kondisi terminating
secara bersamaan. Hal ini mengubah kondisi klaster menjadi sebagai berikut:
node-1 draining | node-2 | node-3 |
---|---|---|
Pod-a terminating | Pod-b available | Pod-c available |
Pod-x terminating |
Deployment tersebut melihat bahwa salah satu Pod berada dalam kondisi terminating
, sehingga Deployment mencoba untuk membuat penggantinya, Pod-d
. Sejak node-1
ditutup (karena perintah kubectl-drain
), Pod-d
masuk ke node lainnya. Sesuatu juga membuat Pod-y
sebagai pengganti Pod-x
(Catatan: untuk sebuah StatefulSet, Pod-a
, akan dinamai dengan Pod-1
, harus diterminasi hingga selesai sebelum penggantinya, yang juga dinamai Pod-1
tetapi memiliki UID yang berbeda, akan dibuat. Selain hal ini, seluruh contoh ini juga berlaku untuk StatefulSet.)
Sekarang, klaster berada pada kondisi berikut:
node-1 draining | node-2 | node-3 |
---|---|---|
Pod-a terminating | Pod-b available | Pod-c available |
Pod-x terminating | Pod-d starting | Pod-y |
Pada satu waktu, Pod-pod yang diusir pun selesai diterminasi, dan kondisi klaster menjadi seperti berikut:
node-1 drained | node-2 | node-3 |
---|---|---|
Pod-b available | Pod-c available | |
Pod-d starting | Pod-y |
Pada titik ini, jika seorang administrator klaster yang tidak sabar mencoba untuk melakukan drain terhadap node-2
atau node-3
, perintah untuk melakukan drain terhadap node tersebut akan terhalang, karena hanya ada 2 Pod yang tersedia, dan PDB-nya membutuhkan setidaknya ada 2 Pod tersedia. Setelah beberapa waktu, Pod-d
menjadi tersedia.
Kondisi klaster menjadi seperti berikut:
node-1 drained | node-2 | node-3 |
---|---|---|
Pod-b available | Pod-c available | |
Pod-d available | Pod-y |
Sekarang, administrator klaster mencoba untuk melakukan drain terhadap node-2
. Perintah drain tersebut akan mencoba mengusir Pod-pod tersebut secara berurutan (tidak bersamaan), misalnya Pod-b
yang pertama dan diikuti dengan Pod-d
. Perintah tersebut akan berhasil mengusir Pod-b
. Tetapi, pada saat ia mencoba untuk mengusir Pod-d
, hal tersebut akan ditolak karena hal tersebut akan mengakibatkan hanya satu Pod yang tersedia untuk Deployment yang bersangkutan.
Deployment tersebut membuat pengganti Pod-b
yang dinamai Pod-e
.
Karena tidak ada sumber daya klaster yang cukup untuk mengalokasikan Pod-e
, proses drain akan kembali terhalang.
Klaster mungkin berada pada kondisi berikut:
node-1 drained | node-2 | node-3 | no node |
---|---|---|---|
Pod-b available | Pod-c available | Pod-e pending | |
Pod-d available | Pod-y |
Pada titik ini, administrator klaster mesti menambah sebuah node untuk klaster agar bisa melanjutkan pembaruan klaster.
Kamu dapat melihat bagaimana frekuensi disrupsi dapat berubah-ubah pada Kubernetes, tergantung pada:
- Berapa banyak replika yang dibutuhkan sebuah aplikasi
- Berapa lama waktu yang dibutuhkan untuk mematikan sebuah Pod secara graceful
- Berapa lama waktu yang dibutuhkan untuk memulai sebuah Pod
- Tipe pengendali
- Kapasitas sumber daya klaster
Memisahkan Peran Pemilik Klaster dan Pemilik Aplikasi
Seringkali akan bermanfaat untuk berpikir Administrator Klaster dan Pemilik Aplikasi sebagai peran yang terpisah dan dengan pengetahuan yang terbatas satu sama lainnya. Pemisahan ini dapat dimengerti dalam beberapa skenario berikut:
- Saat ada banyak tim aplikasi yang berbagi pakai sebuah klaster Kubernetes, dan ada pembagian peran yang spesifik
- Saat alat atau servis pihak ketiga digunakan untuk melakukan otomasi manajemen klaster.
PDB mendukung pemisahan peran ini dengan cara menyediakan antarmuka bagi peran-peran tersebut.
Jika kamu tidak memiliki pemisahan peran seperti ini pada organisasimu, kamu mungkin tidak membutuhkan PDB.
Bagaimana cara melakukan Tindakan Disruptif terhadap Klaster
Jika kamu adalah Administrator Klaster, maka kamu mesti melakukan tindakan disruptif pada setiap node di klastermu, seperti melakukan pembaruan perangkat lunak pada node, berikut beberapa opsinya:
- Menerima downtime pada saat pembaruan node
- Melakukan failover ke replika lengkap klaster lain.
- Tanpa downtime, tetapi mungkin lebih mahal, baik ongkos duplikasi node-node dan tenaga yang dibutuhkan untuk melakukan failover.
- Membuat aplikasi yang toleran terhadap disrupsi, dan gunakan PDB.
- Tanpa downtime.
- Duplikasi sumber daya yang minimal.
- Mengizinkan lebih banyak otomasi administrasi klaster.
- Membuat aplikasi yang toleran terhadap disrupsi agak rumit, tetapi usaha yang dilakukan untuk menoleransi disrupsi yang disengaja kebanyakan beririsan dengan usaha untuk mendukung autoscaling dan menoleransi disrupsi yang tidak disengaja.
Selanjutnya
Ikuti langkah-langkah untuk melindungi aplikasimu dengan membuat sebuah PodDisruptionBudget.
Pelajari lebih lanjut mengenai melakukan drain terhadap node.