Bagian konsep ini membantu kamu belajar tentang bagian-bagian sistem serta abstraksi
yang digunakan Kubernetes untuk merepresentasikan klaster kamu, serta membantu
kamu belajar lebih dalam bagaimana cara kerja Kubernetes.
Ikhtisar
Untuk menggunakan Kubernetes, kamu menggunakan objek-objek Kubernetes API untuk merepresentasikan
state yang diinginkan: apa yang aplikasi atau workload lain yang ingin kamu
jalankan, image kontainer yang digunakan, jaringan atau resource disk apa yang ingin
kamu sediakan, dan lain sebagainya. Kamu membuat state yang diinginkan dengan cara membuat
objek dengan menggunakan API Kubernetes, dan biasanya menggunakan command-line interface, yaitu kubectl.
Kamu juga dapat secara langsung berinteraksi dengan klaster untuk membuat atau mengubah
state yang kamu inginkan.
Setelah kamu membuat state yang kamu inginkan, Control Plane Kubernetes
menggunakan Pod Lifecycle Event Generator (PLEG) untuk mengubah
state yang ada saat ini supaya sama dengan state yang diinginkan.
Untuk melakukan hal tersebut, Kubernetes melakukan berbagai task secara otomatis,
misalnya dengan mekanisme start atau stop kontainer, melakukan scale replika dari
suatu aplikasi, dan lain sebagainya. Control Plane Kubernetes terdiri dari sekumpulan
process yang dijalankan di klaster:
Kubernetes Master terdiri dari tiga buah process yang dijalankan pada sebuah node di klaster kamu, node ini disebut sebagai master, yang terdiri kube-apiserver, kube-controller-manager dan kube-scheduler.
Setiap node non-master pada klaster kamu menjalankan dua buah process:
kubelet, yang menjadi perantara komunikasi dengan master.
kube-proxy, sebuah proxy yang merupakan representasi jaringan yang ada pada setiap node.
Objek Kubernetes
Kubernetes memiliki beberapa abstraksi yang merepresentasikan state dari sistem kamu:
apa yang aplikasi atau workload lain yang ingin kamu jalankan, jaringan atau resource disk apa yang ingin
kamu sediakan, serta beberapa informasi lain terkait apa yang sedang klaster kamu lakukan.
Abstraksi ini direpresentasikan oleh objek yang tersedia di API Kubernetes;
lihat ikhtisar objek-objek Kubernetes
untuk penjelasan yang lebih mendetail.
Sebagai tambahan, Kubernetes memiliki beberapa abstraksi yang lebih tinggi yang disebut kontroler.
Kontroler merupakan objek mendasar dengan fungsi tambahan, contoh dari kontroler ini adalah:
Berbagai bagian Control Plane Kubernetes, seperti master dan process-process kubelet,
mengatur bagaimana Kubernetes berkomunikasi dengan klaster kamu. Control Plane
menjaga seluruh record dari objek Kubernetes serta terus menjalankan
iterasi untuk melakukan manajemen state objek. Control Plane akan memberikan respon
apabila terdapat perubahan pada klaster kamu dan mengubah state saat ini agar sesuai
dengan state yang diinginkan.
Contohnya, ketika kamu menggunakan API Kubernetes untuk membuat sebuah Deployment,
kamu memberikan sebuah state baru yang harus dipenuhi oleh sistem. Control Plane
kemudian akan mencatat objek apa saja yang dibuat, serta menjalankan instruksi yang kamu berikan
dengan cara melakukan start aplikasi dan melakukan scheduling aplikasi tersebut
pada node, dengan kata lain mengubah state saat ini agar sesuai dengan state yang diinginkan.
Master
Master Kubernetes bertanggung jawab untuk memelihara state yang diinginkan pada klaster kamu.
Ketika kamu berinteraksi dengan Kubernetes, misalnya saja menggunakan perangkat kubectl,
kamu berkomunikasi dengan master klaster Kubernetes kamu.
Node di dalam klaster Kubernetes adalah mesin (mesin virtual maupun fisik) yang
menjalankan aplikasi kamu. Master mengontrol setiap node; kamu akan jarang berinteraksi
dengan node secara langsung.
Jika kamu ingin menulis halaman konsep, perhatikan
cara penggunaan template pada laman
untuk informasi mengenai konsep tipe halaman dan template konsep.
1 - Ikhtisar
1.1 - Apa itu Kubernetes?
Kubernetes merupakan platform open-source yang digunakan untuk melakukan manajemen workloads aplikasi yang dikontainerisasi, serta menyediakan konfigurasi dan otomatisasi secara deklaratif. Kubernetes berada di dalam ekosistem yang besar dan berkembang cepat. Service, support, dan perkakas Kubernetes tersedia secara meluas. Kubernetes merupakan platform open-source yang digunakan untuk melakukan manajemen workloads aplikasi yang dikontainerisasi, serta menyediakan konfigurasi dan otomatisasi secara deklaratif. Kubernetes berada di dalam ekosistem yang besar dan berkembang cepat. Service, support, dan perkakas Kubernetes tersedia secara meluas.
Laman ini merupakan ikhtisar Kubernetes.
Kubernetes merupakan platform open-source yang digunakan untuk melakukan
manajemen workloads aplikasi yang dikontainerisasi, serta menyediakan
konfigurasi dan otomatisasi secara deklaratif. Kubernetes berada di dalam ekosistem
yang besar dan berkembang cepat. Service, support, dan perkakas
Kubernetes tersedia secara meluas.
Mengapa Kubernetes dan hal apa saja yang dapat dilakukan oleh Kubernetes?
Kubernetes memiliki sejumlah fitur yang dapat dijabarkan sebagai berikut:
platform kontainer
platform microservices
platform cloud yang tidak mudah dipindahkan
Kubernetes menyediakan manajemen environment yang berpusat pada kontainer.
Kubernetes melakukan orkestrasi terhadap computing, networking,
dan inftrastruktur penyimpanan. Fitur inilah yang kemudian membuat konsep Platform as a Service (PaaS)
menjadi lebih sederhana dilengkapi dengan fleksibilitas yang dimiliki oleh Infrastructure as a Service (IaaS).
Lalu apa yang menyebabkan Kubernetes disebut sebagai sebuah platform?
Meskipun Kubernetes menyediakan banyak fungsionalitas, selalu ada keadaan dimana
hal tersebut membutuhkan fitur baru. Workflow spesifik yang terkait dengan
proses pengembangan aplikasi dapat ditambahkan pada streamline untuk meningkatkan
produktivitas developer. Orkestrasi ad-hoc yang dapat diterima biasanya membutuhkan desain
otomatisasi yang kokoh agar bersifat scalable. Hal inilah yang membuat
Kubernetes juga didesain sebagai platform untuk membangun ekosistem komponen dan
dan perkakas untuk memudahkan proses deployment, scale, dan juga manajemen
aplikasi.
Labels memudahkan pengguna mengkategorisasikan resources yang mereka miliki
sesuai dengan kebutuhan. Annotations memungkinkan pengguna untuk menambahkan informasi
tambahan pada resource yang dimiliki.
Selain itu, Kubernetes control plane dibuat berdasarkan
API yang tersedia bagi pengguna dan developer. Pengguna
dapat mengimplementasikan kontroler sesuai dengan kebutuhan mereka, contohnya adalah
schedulers,
dengan API kustom yang mereka miliki, kontroler kustom ini kemudian dapat digunakan
pada command-line
tool generik yang ada.
Desain
inilah yang memungkinkan beberapa sistem lain untuk dapat dibangun di atas Kubernetes.
Lalu hal apakah yang tidak termasuk di dalam Kubernetes?
Kubernetes bukanlah sebuah PaaS (Platform as a
Service) yang biasanya. Meskipun Kubernetes dijalankan pada tingkatan kontainer
dan bukan pada tingkatan perangkat keras, Kubernetes menyediakan beberapa fitur
yang biasanya disediakan oleh Paas, seperti deployment, scaling,
load balancing, logging, dan monitoring. Akan tetapi,
Kubernetes bukanlah sistem monolitik, melainkan suatu sistem yang bersifat sebagai
bulding block dan pluggable yang dapat digunakan untuk membangun sebuah
platform yang dibutuhkan oleh developer dengan tetap mengutamakan konsep fleksibilitas.
Kubernetes:
Tidak melakukan limitasi terhadap aplikasi yang di-support. Kubernetes bertujuan
untuk mendukung berbagai variasi workloads, termasuk
stateless, stateful, dan data-processing. Jika sebuah
aplikasi dapat dijalankan di atas kontainer, maka aplikasi tersebut juga dapat
dijalankan di atas Kubernetes.
Tidak menyediakan mekanisme untuk melakukan deploy kode sumber
maupun mekanisme build sebuah aplikasi. Continuous Integration, Delivery, and Deployment
(CI/CD) workflows ditentukan oleh preferensi serta kebutuhan teknis organisasi.
Tidak menyediakan application-level services, seperti middleware
(e.g., message buses), data-processing frameworks (for example,
Spark), databases (e.g., mysql), caches, maupun cluster storage systems (e.g.,
Ceph) sebagai suatu built-in services. Komponen tersebut dapat dijalankan di atas Kubernetes, dan/atau
dapat diakses oleh aplikasi yang dijalankan di atas Kubernetes melalui sebuah mekanisme tidak mudah dipindahkan
misalnya saja Open Service Broker.
Tidak membatasi penyedia layanan logging, monitoring, maupun alerting yang digunakan.
Kubernetes menyediakan proof of concept dan mekanisme integrasi yang dapat digunakan
untuk mengumpulkan serta mengekspor metriks yang ada.
Tidak menyediakan atau mengharuskan penggunaan configuration language/system (e.g.,
jsonnet). Kubernetes menyediakan suatu API deklaratif
yang dapat digunakan oleh berbagai jenis spesifikasi deklaratif.
Tidak menyediakan atau mengadaptasi sebuah konfigurasi, maintenance, manajemen, atau
self-healing mesin dengan spesifikasi khusus.
Sebagai tambahan, Kubernetes bukanlah sebuah sitem orkestrasi biasa. Bahkan pada kenyataannya,
Kubernetes menghilangkan kebutuhan untuk melakukan orkestrasi. Definisi teknis dari
orkestrasi merupakan eksekusi dari sebuah workflow yang sudah didefinisikan sebelumnya: pertama kerjakan A, kemudian B,
dan terakhir C. Sebaliknya, Kubernetes disusun oleh seperangkat
proses kontrol yang dapat idekomposisi yang selalu menjalankan state yang ada
saat ini hingga sesuai dengan state yang dinginkan.
Kita tidak perlu peduli proses apa saja yang perlu dilakukan untuk melakukan A hingga C.
Mekanisme kontrol yang tersentralisasi juga tidak dibutuhkan. Dengan demikian, sistem yang
dihasilkan lebih mudah digunakan lebih kokoh, serta lebih extensible.
Mengapa kontainer?
Mencari alasan kenapa kita harus menggunakan kontainer?
Cara Lama untuk melakukan mekanisme deploy suatu aplikasi
adalah dengan cara instalasi aplikasi tersebut pada sebuah mesin
dengan menggunakan package manager yang dimiliki oleh sistem operasi
mesin tersebut. Hal ini menciptakan suatu ketergantungan antara executables,
konfigurasi, serta ketergantungan lain yang dibutuhkan aplikasi dengan sistem operasi
yang digunakan oleh mesin. Untuk mengatasi hal ini, tentunya bisa saja kita melakukan
mekanisme build suatu image VM yang immutable untuk mendapatkan
mekanisme rollouts dan rollback yang dapat diprediksi.
Meskipun demikian, VM masih dianggap "berat" dan tidak tidak mudah dipindahkan.
Cara Baru adalah dengan melakukan mekanisme deploy kontainer pada tingkatan
virtualisasi di level sistem operasi (OS) bukan pada tingkatan virtualisasi perangkat keras.
Kontainer ini berada dalam lingkungan yang terisolasi satu sama lain serta terisolasi dengan
mesin dimana kontainer ini berada. Kontainer ini memiliki filesystems masing-masing.
Selain itu, setiap kontainer tidak dapat "melihat" process yang sedang dijalankan di
kontainer lain. Selain itu resource komputasi yang digunakan oleh kontainer
ini juga dapat dibatasi. Kontainer juga dapat dengan lebih mudah di-build jika
dibandingkan dengan VM, karena kontainer tidak bergantung pada filesystem
yang dimiliki mesin, serta dengan mudah dapat didistribusikan.
Karena kontainer ukurannya kecil dan lebih cepat, sebuah aplikasi dapat dibangun di setiap
image kontainer. Mekanisme pemetaan satu-satu antara kontainer dan aplikasi
inilah yang membuka keuntungan secara meyeluruh yang dapat diberikan oleh kontainer.
Dengan menggunakan kontainer, image kontainer dapat dibuat diwaktu rilis aplikasi.
Pembuatan image ini memungkinkan aplikasi secara konsisten dirilis pada
environmentdevelopment maupun production. Selain itu,
kontainer juga memiliki transparasi yang lebih tinggi dibandingkan dengan VM. Maksudnya,
infrastruktur punya tugas untuk mengatur lifecycle seluruh process yang ada di dalam kontainer. Ini bukanlah lagi tugas sebuah supervisor process yang tersembunyi di dalam kontainer.
Secara garis besar, penggunaan kontainer memiliki keuntungan sebagai berikut:
Mekanisme pembuatan aplikasi serta proses deployment yang lebih efektif:
Kontainer dapat meningkatkan kemudahan dan efisiensi jika dibandingkan dengan penggunaan VM.
Continuous development, integration, and deployment:
Digunakan untuk melakukan proses build dan deploy yang sering dilakukan
serta kemudahan mekanisme rollback karena image yang ada sifatnya immutable.
Pemisahan kepentingan antara Dev dan Ops:
Pembuatan image container dilakukan pada saat rilis dan bukan pada saat deploy
mengurangi ketergantungan aplikasi dan infrastruktur.
Observabilitas
Tidak hanya informasi dan metriks pada level OS, tapi juga kesehatan aplikasi dan signal lain.
Konsistensi environment pada masa pengembangan , testing, dan production:
Memiliki perilaku yang sama baik ketika dijalankan di mesin lokal maupun penyedia layanan cloud.
Portabilitas antar penyedia layanan cloud maupun distribusi OS:
Dapat dijalankan pada Ubuntu, RHEL, CoreOS, on-prem, Google Kubernetes Engine, dan dimanapun.
Manajemen yang bersifat Aplikasi sentris:
Meningkatkan level abstraksi dari proses menjalankan OS pada perangkat keras virtual
ke proses menjalankan aplikasi pada sebuah OS dengan menggunakan resource logis.
Mikroservis yang renggang (loosely coupled), terdistribusi, elastis, dan terliberasi:
Aplikasi dapat dipecah menjadi komponen yang lebih kecil yang independen dan dapat
di-deploy dan diatur secara dinamis -- bukan sebuah sistem monolitik yang dijalankan pada
sebuah mesin yang hanya punya satu tujuan.
Isolasi resource:
Performa aplikasi yang bisa diprediksi.
Utilisasi resource:
Efisiensi yang tinggi
Apakah arti Kubernetes? K8s?
Nama Kubernetes berasal dari Bahasa Yunani, yang berarti juru mudi atau
pilot, dan merupakan asal kata gubernur dan
cybernetic. K8s
merupakan sebuah singkatan yang didapat dengan mengganti 8 huruf "ubernete" dengan
"8".
Sebuah klaster Kubernetes terdiri dari komponen yang merepresentasikan bidang kontrol dan sepasang mesin yaitu nodes.
Dokumen ini merupakan ikhtisar yang mencakup berbagai komponen
yang dibutuhkan agar klaster Kubernetes dapat berjalan secara fungsional.
Komponen Master
Komponen master menyediakan control plane bagi klaster.
Komponen ini berperan dalam proses pengambilan secara global
pada klaster (contohnya, mekanisme schedule), serta berperan dalam proses
deteksi serta pemberian respons terhadap events yang berlangsung di dalam klaster
(contohnya, penjadwalan pod baru apabila jumlah replika yang ada pada
replication controller tidak terpenuhi).
Komponen master dapat dijalankan di mesin manapun yang ada di klaster. Meski begitu,
untuk memudahkan proses yang ada, script inisiasi awal yang dijalankan
biasanya memulai komponen master pada mesin yang sama, serta tidak menjalankan
kontainer bagi pengguna di mesin ini. Contoh konfigurasi multi-master VM
dapat dilihat di modul [Membangun Klaster HA] (/docs/admin/high-availability/).
kube-apiserver
Komponen control plane yang mengekspos API Kubernetes. Merupakan front-end dari control plane Kubernetes.
Komponen ini didesain agar dapat diskalakan secara horizontal. Lihat Membangun Klaster HA.
etcd
Penyimpanan key value konsisten yang digunakan sebagai penyimpanan data klaster Kubernetes.
Selalu perhatikan mekanisme untuk mem-backup data etcd pada klaster Kubernetes kamu. Untuk informasi lebih lanjut tentang etcd, lihat dokumentasi etcd.
kube-scheduler
Komponen control plane yang bertugas mengamati Pod baru yang belum ditempatkan di node manapun dan kemudian memilihkan Node di mana Pod baru tersebut akan dijalankan.
Faktor-faktor yang dipertimbangkan untuk keputusan penjadwalan termasuk: kebutuhan sumber daya secara individual dan kolektif, batasan perangkat keras/perangkat lunak/peraturan, spesifikasi afinitas dan nonafinitas, lokalisasi data, interferensi antar beban kerja dan tenggat waktu.
kube-controller-manager
Komponen control plane yang menjalankan pengontrol.
Secara logis, setiap pengontrol adalah sebuah proses yang berbeda, tetapi untuk mengurangi kompleksitas, kesemuanya dikompilasi menjadi sebuah biner (binary) yang dijalankan sebagai satu proses.
Kontroler-kontroler ini meliputi:
Kontroler Node : Bertanggung jawab untuk mengamati dan memberikan
respons apabila jumlah node berkurang.
Kontroler Replikasi : Bertanggung jawab untuk menjaga jumlah pod agar
jumlahnya sesuai dengan kebutuhan setiap objek kontroler replikasi yang ada di sistem.
Kontroler Endpoints : Menginisiasi objek Endpoints
(yang merupakan gabungan Pods dan Services).
Kontroler Service Account & Token: Membuat akun dan
akses token API standar untuk setiap namespaces yang dibuat.
cloud-controller-manager
Cloud-controller-manager merupakan kontroler yang berinteraksi dengan penyedia layanan cloud.
Kontroler ini merupakat fitur alfa yang diperkenalkan pada Kubernetes versi 1.6.
Cloud-controller-manager hanya menjalankan iterasi kontroler cloud-provider-specific .
Kamu harus menonaktifkan iterasi kontroler ini pada kube-controller-manager.
Kamu dapat menonaktifka iterasi kontroler ini dengan mengubah nilai argumen --cloud-provider dengan external
ketika menginisiasi kube-controller-manager.
Adanya cloud-controller-manager memungkinkan kode yang dimiliki oleh penyedia layanan cloud
dan kode yang ada pada Kubernetes saling tidak bergantung selama masa development.
Pada versi sebelumnya, Kubernetes bergantung pada fungsionalitas spesifik yang disediakan oleh
penyedia layanan cloud. Di masa mendatang, kode yang secara spesifik dimiliki oleh
penyedia layanan cloud akan dipelihara oleh penyedia layanan cloud itu sendiri,
kode ini selanjutnya akan dihubungkan dengan cloud-controller-manager ketika Kubernetes dijalankan.
Kontroler berikut ini memiliki keterkaitan dengan penyedia layanan cloud:
Kontroler Node : Melakukan pengecekan pada penyedia layanan cloud ketika menentukan apakah sebuah node telah dihapus pada cloud apabila node tersebut berhenti memberikan respons.
Kontroler Route : Melakukan pengaturan awal route yang ada pada penyedia layanan cloud
Kontroler Service : Untuk membuat, memperbaharui, menghapus load balancer yang disediakan oleh penyedia layanan cloud
Kontroler Volume : Untuk membuat, meng-attach, dan melakukan mount volume serta melakukan inetraksi dengan penyedia layanan cloud untuk melakukan orkestrasi volume
Komponen Node
Komponen ini ada pada setiap node, fungsinya adalah melakukan pemeliharaan terhadap pod serta menyediakan environment runtime bagi Kubernetes.
kubelet
Agen yang dijalankan pada setiap node di klaster yang bertugas untuk memastikan kontainer dijalankan di dalam Pod.
kube-proxy
kube-proxy membantu abstraksi service Kubernetes melakukan tugasnya. Hal ini terjadi dengan cara memelihara aturan-aturan jaringan (network rules) serta meneruskan koneksi yang ditujukan pada suatu host.
Addons merupakan pod dan service yang mengimplementasikan fitur-fitur yang diperlukan klaster.
Beberapa addons akan dijelaskan selanjutnya.
DNS
Meskipun tidak semua addons dibutuhkan, semua klaster Kubernetes hendaknya
memiliki DNS klaster. Komponen ini penting karena banyak dibutuhkan oleh komponen
lainnya.
Klaster DNS adalah server DNS, selain beberapa server DNS lain yang sudah ada di
environment kamu, yang berfungsi sebagai catatan DNS bagi Kubernetes services
Kontainer yang dimulai oleh kubernetes secara otomatis akan memasukkan server DNS ini
ke dalam mekanisme pencarian DNS yang dimilikinya.
Web UI (Dasbor)
Dasbor adalah antar muka berbasis web multifungsi yang ada pada klaster Kubernetes.
Dasbor ini memungkinkan user melakukan manajemen dan troubleshooting klaster maupun
aplikasi yang ada pada klaster itu sendiri.
Container Resource Monitoring
Container Resource Monitoring mencatat metrik time-series yang diperoleh
dari kontainer ke dalam basis data serta menyediakan antar muka yang dapat digunakan
untuk melakukan pencarian data yang dibutuhkan.
Cluster-level Logging
Cluster-level logging bertanggung jawab mencatat log kontainer pada
penyimpanan log terpusat dengan antar muka yang dapat digunakan untuk melakukan
pencarian.
1.3 - API Kubernetes
API Kubernetes membuatmu dapat melakukan query dan memanipulasi keadaan objek dalam Kubernetes. Inti dari bidang kontrol Kubernetes adalah server API dan HTTP API yang diekspos. Pengguna, berbagai bagian klastermu, dan komponen eksternal semuanya berkomunikasi satu sama lain melalui server API.
Secara keseluruhan standar yang digunakan untuk API dijelaskan di dalam dokumentasi API standar.
Endpoints API, resource types serta contoh penggunaan dijelaskan di dalam API Reference.
API Kubernetes juga berperan sebagai skema konfigurasi yang deklaratif di dalam sistem.. Sementara itu, kubectl merupakan command-line yang dapat digunakan untuk membuat, menmperbaharui, menghapus, dan mendapatkan obyek API.
Kubernetes menyimpan bentuk terserialisasi dari obyek API yang dimilikinya di dalam etcd.
Kubernetes sendiri dibagi menjadi beberapa komponen yang saling dapat saling interaksi melalui API.
Perubahan API
Berdasarkan pengalaman kami, semua sistem yang berhasil memerlukan kebutuhan
untuk terus tumbuh dan berkembang seiring dengan bertambahnya kebutuhan
yang ada. Dengan demikian, kami berekspektasi bahwa API akan selalu berubah seiring dengan bertambahnya kebutuhan yang ada.
Meski begitu, perubahan yang ada akan selalu kompatibel dengan implementasi sebelumnya, untuk jangka waktu tertentu.
Secara umum, penambahan pada sebuah resource API atau field resource bisa sering terjadi.. Penghapusan resource API atau suatu field, di sisi lain,
diharapkan untuk dapat memenuhi kaidah deprecation API.
Hal-hal apa saja yang perlu diperhatikan untuk menjamin kompatibilitas API
secara rinci dibahas di dalam dokumentasi perubahan API.
Swagger and OpenAPI Definition
Detail mengenai API didokumentasikan dengan menggunakan OpenAPI.
Semenjak Kubernetes versi 1.10, Kubernetes menghadirkan spesifikasi OpenAPI melalui endpoint/openapi/v2.
Format request dapat diterapkan dengan cara menambahkan header HTTP:
Header
Opsi
Accept
application/json, application/com.github.proto-openapi.spec.v2@v1.0+protobuf (content-type standar yang digunakan adalah application/json untuk */*)
Accept-Encoding
gzip
Sebelum versi 1.14, terdapat 4 buah endpoint yang menyediakan spesifikasi OpenAPI
dalam format berbeda yang dapat digunakan (/swagger.json, /swagger-2.0.0.json, /swagger-2.0.0.pb-v1, /swagger-2.0.0.pb-v1.gz).
Endpoint ini bersifat deprecated dan akan dihapus pada Kubernetes versi 1.14.
Kubernetes juga menyediakan alternatif mekanisme serialisasi lain,
yaitu dengan menggunakan Protobuf, yang secara umum digunakan untuk mekanisme komunikasi
intra-klaster, hal ini didokumentasikan di dalam proposal desain
serta berkas IDL sebagai bentuk spesifikasi skema berada dalam package Go
Sebelum Kubernetes versi 1.14, apiserver Kubernetes juga mengekspos API
yang dapat digunakan untuk mendapatkan spesifikasi Swagger v1.2 pada endpoint/swaggerapi.
Endpoint ini akan sudah bersifat deprecated dan akan dihapus pada
Kubernetes versi 1.14.
Pemberian Versi pada API
Untuk memudahkan restrukturisasi field dan resource yang ada,
Kubernetes menyediakan beberapa versi API yang berada pada path yang berbeda,
misalnya /api/v1 atau /apis/extensions/v1beta1.
Kita dapat memilih versi yang akan digunakan pada tingkatan API
dan bukan pada tingkatan field atau resource untuk memastikan
API yang digunakan memperlihatkan gambaran yang jelas serta konsisten
mengenai resoure dan sifat sistem yang ada.
Perhatikan bahwa pemberian versi pada API dan pemberian versi pada API dan perangkat lunak memiliki keterkaitan secara tak langsung.
Proposal API and release
versioning memberikan deskripsi keterkaitan antara
pemberian versi pada API dan pemberian versi pada perangkat lunak.
API dengan versi yang berbeda menunjukan tingkatan kestabilan dan ketersediaan yang diberikan pada versi tersebut.
Kriteria untuk setiap tingkatan dideskripsikan secara lebih detail di dalam
dokumentasi perubahan API. They are summarized here:
Tingkatan Alpha:
Nama dari versi ini mengandung string alpha (misalnya, v1alpha1).
Bisa jadi terdapat bug. Secara default fitur ini tidak diekspos.
Ketersediaan untuk fitur yang ada bisa saja dihilangkan pada suatu waktu tanpa pemberitahuan sebelumnya.
API yang ada mungkin saja berubah tanpa memperhatikan kompatibilitas dengan versi perangkat lunak sebelumnya.
Hanya direkomendasikan untuk klaster yang digunakan untuk tujuan testing.
Tingkatan Beta:
Nama dari versi ini mengandung string beta (misalnya v2beta3).
Kode yang ada sudah melalui mekanisme testing yang cukup baik. Menggunakan fitur ini dianggap cukup aman. Fitur ini diekspos secara default.
Ketersediaan untuk fitur secara menyeluruh tidak akan dihapus, meskipun begitu detail untuk suatu fitur bisa saja berubah.
Skema dan/atau semantik dari suatu obyek mungkin saja berubah tanpa memerhatikan kompatibilitas pada rilis beta selanjutnya.
Jika hal ini terjadi, kami akan menyediakan suatu instruksi untuk melakukan migrasi di versi rilis selanjutnya. hal ini bisa saja terdiri dari penghapusan, pengubahan, ataupun pembuatan
obyek API. Proses pengubahan mungkin saja membutuhkan pemikiran yang matang. Dampak proses ini bisa saja menyebabkan downtime aplikasi yang bergantung pada fitur ini.
Disarankan hanya untuk digunakan untuk penggunaan yang untuk penggunaan yang tidak berdampak langsung pada bisnis kamu.
Kami mohon untuk mencoba versi beta yang kami sediakan dan berikan masukan terhadap fitur yang kamu pakai! Apabila fitur tersebut sudah tidak lagi berada di dalam tingkatan beta perubahan yang kami buat terhadap fitur tersebut bisa jadi tidak lagi dapat digunakan
Tingkatan stabil:
Nama dari versi ini mengandung string vX dimana X merupakan bilangan bulat.
Fitur yang ada pada tingkatan ini akan selalu muncul di rilis berikutnya.
API groups
Untuk memudahkan proses ekstensi suatu API Kubernetes, kami mengimplementasikan API groups.
API group ini dispesifikasikan di dalam pathREST serta di dalam fieldapiVersion dari sebuah obyek yang sudah diserialisasi.
Saat ini, terdapat beberapa API groups yang digunakan:
Kelompok core, seringkali disebut sebagai legacy group, berada pada pathREST/api/v1 serta menggunakan apiVersion: v1.
Named groups berada pada pathREST/apis/$GROUP_NAME/$VERSION, serta menggunakan apiVersion: $GROUP_NAME/$VERSION
(misalnya apiVersion: batch/v1). Daftar menyeluruh mengenai apa saja API groups dapat dilihat di Kubernetes API reference.
Ekstensi API dengan custom resources dapat dilakukan melalui dua buah path:
CustomResourceDefinition
digunakan jika memerlukan seluruh set semantik Kubernetes API, pengguna boleh implementasi apiserver sendiri dengan menggunakan aggregator.
Pengguna yang membutuhkan seperangkat semantik API Kubernetes API dapat mengimplementasikan apiserver mereka sendiri.
dengan menggunakan aggregator
untuk membuat integrasi dengan klien menjadi lebih mudah.
Mengaktifkan API groups
Beberapa resources dan API groups sudah diaktifkan secara default.
Resource dan API groups ini dapat diaktifkan dan dinonaktifkan dengan mengatur penanda --runtime-config
pada apiserver. --runtime-config menerima nilai yang dipisahkan oleh koma. Sebagai contoh: untuk menonaktifkan batch/v1, tetapkan
--runtime-config=batch/v1=false, untuk mengaktifkan batch/v2alpha1, tetapkan --runtime-config=batch/v2alpha1.
Penanda menerima nilai yang dipisahkan oleh pasangan key=value yang mendeskripsikan konfigurasi runtime pada apiserver.
PENTING: Melakukan proses mengaktifkan atau menonaktifkan groups atau resources
membutuhkan mekanisme restartapiserver dan controller-manager
agar apiserver dapat menerima perubahan --runtime-config.
Mengaktifkan resources di dalam groups
DaemonSets, Deployments, HorizontalPodAutoscalers,
Ingresses, Jobs, dan ReplicaSets diaktifkan secara default.
Ekstensi lain dapat diaktifkan penanda --runtime-config pada apiserver. Penanda --runtime-config menerima nilai yang dipisahkan oleh koma.
Sebagai contoh untuk menonaktifkan deployments dan ingress, tetapkan.
--runtime-config=extensions/v1beta1/deployments=false,extensions/v1beta1/ingresses=false
1.4 - Menggunakan Objek-Objek Kubernetes
Objek-objek Kubernetes adalah entitas yang tetap dalam sistem Kubernetes. Kubernetes menggunakan entitas tersebut untuk merepresentasikan keadaan dari klastermu. Pelajari tentang objek model Kubernetes dan bagaimana menggunakan objek tersebut.
1.4.1 - Memahami Konsep Objek-Objek yang ada pada Kubernetes
Laman ini menjelaskan bagaimana objek-objek Kubernetes direpresentasikan di dalam API Kubernetes,
dan bagaimana kamu dapat merepresentasikannya di dalam format .yaml.
Memahami Konsep Objek-Objek yang Ada pada Kubernetes
Objek-objek Kubernetes adalah entitas persisten di dalam sistem Kubernetes.
Kubernetes menggunakan entitas ini untuk merepresentasikan state yang ada pada
klaster kamu. Secara spesifik, hal itu dapat dideskripsikan sebagai:
Aplikasi-aplikasi kontainer apa sajakah yang sedang dijalankan (serta pada node apa aplikasi tersebut dijalankan)
Resource yang tersedia untuk aplikasi tersebut
Policy yang mengatur bagaimana aplikasi tersebut dijalankan, misalnya restart, upgrade, dan fault-tolerance.
Objek Kubernetes merupakan sebuah "record of intent"--yang mana sekali kamu membuat suatu objek,
sistem Kubernetes akan bekerja secara konsisten untuk menjamin
bahwa objek tersebut akan selalu ada. Dengan membuat sebuah objek, secara tak langsung kamu
memberikan informasi pada sistem Kubernetes mengenai perilaku apakah yang kamu inginkan pada workload klaster yang kamu miliki;
dengan kata lain ini merupakan definisi state klaster yang kamu inginkan.
Untuk menggunakan objek-objek Kubernetes--baik membuat, mengubah, atau menghapus objek-objek tersebut--kamu
harus menggunakan API Kubernetes.
Ketika kamu menggunakan perintah kubectl, perintah ini akan melakukan API call untuk perintah
yang kamu berikan. Kamu juga dapat menggunakan API Kubernetes secara langsung pada program yang kamu miliki
menggunakan salah satu library klien yang disediakan.
Spec dan Status Objek
Setiap objek Kubernetes memiliki field berantai yang mengatur konfigurasi sebuah objek:
spec dan status. Spec, merupakan field yang harus kamu sediakan, field ini mendeskripsikan
state yang kamu inginkan untuk objek tersebut--karakteristik dari objek yang kamu miliki.
Status mendeskripsikan state yang sebenarnya dari sebuah objek, dan hal ini disediakan dan selalu diubah oleh
sistem Kubernetes. Setiap saat, Control Plane Kubernetes selalu memantau apakah state aktual sudah sesuai dengan
state yang diinginkan.
Sebagai contoh, Deployment merupakan sebuah objek yang merepresentasikan sebuah aplikasi yang dijalankan di klaster kamu.
Ketika kamu membuat sebuah Deployment, kamu bisa saja memberikan spec bagi Deployment untuk memberikan spesifikasi
berapa banyak replica yang kamu inginkan. Sistem Kubernetes kemudian akan membaca konfigurasi yang kamu berikan
dan mengaktifkan tiga buah instans untuk aplikasi yang kamu inginkan--mengubah status yang ada saat ini agar sesuai dengan apa yang kamu inginkan.
Jika terjadi kegagalan dalam instans yang dibuat, sistem Kubernetes akan memberikan respons bahwa terdapat perbedaan antara spec dan status serta
melakukan penyesuaian dengan cara memberikan instans pengganti.
Informasi lebih lanjut mengenai spec objek, status, dan metadata dapat kamu baca di Konvensi API Kubernetes.
Mendeskripsikan Objek Kubernetes
Ketika kamu membuat sebuah objek di Kubernetes, kamu harus menyediakan spec objek yang
mendeskripsikan state yang diinginkan, serta beberapa informasi tentang objek tersebut (seperti nama).
Ketika kamu menggunakan API Kubernetes untuk membuat objek tersebut (baik secara langsung atau menggunakan perintah
kubectl), request API yang dibuat harus mencakup informasi seperti request body dalam format JSON.
Apabila kamu memberikan informasi dalam bentuk .yaml ketika menggunakan perintah kubectl maka kubectl
akan mengubah informasi yang kamu berikan ke dalam format JSON ketika melakukan request API.
Berikut merupakan contoh file.yaml yang menunjukkan field dan spec objek untuk Deployment:
apiVersion:apps/v1# for versions before 1.9.0 use apps/v1beta2kind:Deploymentmetadata:name:nginx-deploymentspec:selector:matchLabels:app:nginxreplicas:2# tells deployment to run 2 pods matching the templatetemplate:metadata:labels:app:nginxspec:containers:- name:nginximage:nginx:1.7.9ports:- containerPort:80
Salah satu cara untuk membuat Deployment menggunakan file.yaml
seperti yang dijabarkan di atas adalah dengan menggunakan perintah
kubectl apply
pada command-line interfacekubectl kamu menerapkan file.yaml sebagai sebuah argumen.
Berikut merupakan contoh penggunaannya:
Keluaran yang digunakan kurang lebih akan ditampilkan sebagai berikut:
deployment.apps/nginx-deployment created
Field-Field yang dibutuhkan
Pada file.yaml untuk objek Kubernetes yang ingin kamu buat, kamu perlu
menyediakan value untuk field-field berikut:
apiVersion - Version API Kubernetes mana yang kamu gunakan untuk membuat objek tersebut
kind - Objek apakah yang ingin kamu buat
metadata - Data yang dapat kamu gunakan untuk melakukan identifikasi objek termasuk name dalam betuk string, UID, dan namespace yang bersifat opsional
Kamu juga harus menyediakan fieldspec. Format spesifik dari spec sebuah objek akan berbeda bergantung
pada objek apakah yang ingin kamu buat, serta mengandung field berantai yang spesifik bagi objek tersebut.
Referensi API Kubernetes memberikan penjelasan
lebih lanjut mengenai format spec untuk semua objek Kubernetes yang dapat kamu buat. Misalnya saja format spec
untuk Pod dapat kamu temukan di sini,
dan format spec untuk Deployment dapat ditemukan
di sini.
Selanjutnya
Pelajari lebih lanjut mengenai dasar-dasar penting bagi objek Kubernetes, seperti Pod.
1.4.2 - Pengaturan Objek Kubernetes
Perangkat kubectl mendukung beberapa cara untuk membuat dan mengatur objek-objek Kubernetes.
Laman ini menggambarkan berbagai macam metodenya. Baca Kubectl gitbook
untuk penjelasan pengaturan objek dengan Kubectl secara detail.
Metode pengaturan
Peringatan: Sebuah objek Kubernetes hanya boleh diatur dengan menggunakan satu metode saja. Mengkombinasikan
beberapa metode untuk objek yang sama dapat menghasilkan perilaku yang tidak diinginkan.
Metode pengaturan
Dijalankan pada
Environment yang disarankan
Jumlah penulis yang didukung
Tingkat kesulitan mempelajari
Perintah imperatif
Objek live
Proyek pengembangan (dev)
1+
Terendah
Konfigurasi objek imperatif
Berkas individu
Proyek produksi (prod)
1
Sedang
Konfigurasi objek deklaratif
Direktori berkas
Proyek produksi (prod)
1+
Tertinggi
Perintah imperatif
Ketika menggunakan perintah-perintah imperatif, seorang pengguna menjalankan operasi secara langsung
pada objek-objek live dalam sebuah klaster. Pengguna menjalankan operasi tersebut melalui
argumen atau flag pada perintah kubectl.
Ini merupakan cara yang paling mudah untuk memulai atau menjalankan tugas "sekali jalan" pada sebuah klaster.
Karena metode ini dijalankan secara langsung pada objek live, tidak ada history yang menjelaskan konfigurasi-konfigurasi terkait sebelumnya.
Contoh
Menjalankan sebuah instans Container nginx dengan membuat suatu objek Deployment:
kubectl run nginx --image nginx
Melakukan hal yang sama menggunakan sintaks yang berbeda:
kubectl create deployment nginx --image nginx
Kelebihan dan kekurangan
Beberapa kelebihan metode ini dibandingkan metode konfigurasi objek:
Sederhana, mudah dipelajari dan diingat.
Hanya memerlukan satu langkah untuk membuat perubahan pada klaster.
Beberapa kekurangan metode ini dibandingkan metode konfigurasi objek:
Tidak terintegrasi dengan proses peninjauan (review) perubahan.
Tidak menyediakan jejak audit yang terkait dengan perubahan.
Tidak menyediakan sumber record kecuali dari apa yang live terlihat.
Tidak menyediakan templat untuk membuat objek-objek baru.
Konfigurasi objek imperatif
Pada konfigurasi objek imperatif, perintah kubectl menetapkan jenis operasi
(create, replace, etc.), flag-flag pilihan dan minimal satu nama berkas.
Berkas ini harus berisi definisi lengkap dari objek tersebut
dalam bentuk YAML atau JSON.
Lihat referensi API
untuk info lebih detail mengenai definisi objek.
Peringatan: Perintah imperatif replace menggantikan spek yang sudah ada dengan spek yang baru,
membuang semua perubahan terhadap objek tersebut yang tidak didefinisikan pada berkas konfigurasi.
Metode ini sebaiknya tidak dilakukan pada tipe sumber daya yang spek-nya diperbarui
secara independen di luar berkas konfigurasi. Service dengan tipe LoadBalancer, sebagai contoh,
memiliki fieldexternalIPs yang diperbarui secara independen di luar konfigurasi, dilakukan
oleh klaster.
Contoh
Membuat objek yang didefinisikan pada sebuah berkas konfigurasi:
kubectl create -f nginx.yaml
Menghapus objek-objek yang didefinisikan pada dua berkas konfigurasi:
kubectl delete -f nginx.yaml -f redis.yaml
Memperbarui objek yang didefinisikan pada sebuah berkas konfigurasi dengan
menimpa konfigurasi live:
kubectl replace -f nginx.yaml
Kelebihan dan kekurangan
Beberapa kelebihan dibandingkan metode perintah imperatif:
Konfigurasi objek dapat disimpan pada suatu sistem kontrol kode seperti Git.
Konfigurasi objek dapat diintegrasikan dengan proses-proses, misalnya peninjauan (review) perubahan sebelum push dan jejak audit.
Konfigurasi objek dapat menyediakan templat untuk membuat objek-objek baru.
Beberapa kekurangan dibandingkan metode perintah imperatif:
Konfigurasi objek memerlukan pemahaman yang mendasar soal skema objek.
Konfigurasi objek memerlukan langkah tambahan untuk menulis berkas YAML.
Beberapa kelebihan dibandingkan metode konfigurasi objek deklaratif:
Konfigurasi objek imperatif memiliki perilaku yang lebih sederhana dan mudah dimengerti.
Sejak Kubernetes versi 1.5, konfigurasi objek imperatif sudah lebih stabil.
Beberapa kekurangan dibandingkan metode konfigurasi objek deklaratif:
Konfigurasi objek imperatif bekerja dengan baik untuk berkas-berkas, namun tidak untuk direktori.
Pembaruan untuk objek-objek live harus diterapkan pada berkas-berkas konfigurasi, jika tidak, hasil perubahan akan hilang pada penggantian berikutnya.
Konfigurasi objek deklaratif
Ketika menggunakan konfigurasi objek deklaratif, seorang pengguna beroperasi pada berkas-berkas
konfigurasi objek yang disimpan secara lokal, namun pengguna tidak mendefinisikan operasi
yang akan dilakukan pada berkas-berkas tersebut. Operasi create, update, dan delete
akan dideteksi secara otomatis per-objek dengan kubectl. Hal ini memungkinkan penerapan
melalui direktori, dimana operasi yang berbeda mungkin diperlukan untuk objek-objek yang berbeda.
Catatan: Konfigurasi objek deklaratif mempertahankan perubahan yang dibuat oleh penulis lainnya, bahkan
jika perubahan tidak digabungkan (merge) kembali pada berkas konfigurasi objek. Hal ini
bisa terjadi dengan menggunakan operasi API patch supaya hanya perbedaannya saja yang ditulis,
daripada menggunakan operasi API replace untuk menggantikan seluruh konfigurasi objek.
Contoh
Melakukan pemrosesan pada semua berkas konfigurasi objek di direktori configs, dan melakukan
create atau patch untuk objek-objek live. Kamu dapat terlebih dahulu melakukan diff untuk
melihat perubahan-perubahan apa saja yang akan dilakukan, dan kemudian terapkan:
Beberapa kelebihan dibandingkan konfigurasi objek imperatif:
Perubahan-perubahan yang dilakukan secara langsung pada objek-objek live akan dipertahankan, bahkan jika perubahan tersebut tidak digabungkan kembali pada berkas-berkas konfigurasi.
Konfigurasi objek deklaratif memiliki dukungan yang lebih baik dalam mengoperasikan direktori dan secara otomatis mendeteksi tipe operasi (create, patch, delete) per-objek.
Beberapa kekurangan dibandingkan konfigurasi objek imperatif:
Konfigurasi objek deklaratif lebih sulit untuk di-debug dan hasilnya lebih sulit dimengerti untuk perilaku yang tidak diinginkan.
Pembaruan sebagian menggunakan diff menghasilkan operasi merge dan patch yang rumit.
Seluruh objek di dalam REST API Kubernetes secara jelas ditandai dengan nama dan UID.
Apabila pengguna ingin memberikan atribut tidak unik, Kubernetes menyediakan label dan anotasi.
Bacalah dokumentasi desain penanda agar kamu dapat memahami lebih lanjut sintaks yang digunakan untuk Nama dan UID.
Nama
String yang dihasilkan oleh klien yang mengacu pada sebuah objek dalam suatu URL resource, seperti /api/v1/pods/some-name.
Sebuah objek dengan kind yang sama tidak boleh memiliki nama yang sama pada suatu waktu tertentu. Meskipun begitu, apabila kamu menghapus sebuah objek, kamu membuat sebuah objek baru (yang memiliki kind yang sama) dengan nama yang sama dengan objek yang kamu hapus sebelumnya.
Berdasarkan ketentuan, nama dari resources Kubernetes memiliki panjang maksimum 253 karakter yang terdiri dari karakter alfanumerik huruf kecil, -, dan ., tetapi resources tertentu punya lebih banyak batasan yang spesifik
UID
String yang dihasilkan oleh sistem Kubernetes untuk mengidentifikasi objek secara unik.
Setiap objek yang ada pada klaster Kubernetes memiliki UID yang unik. Hal ini dilakukan untuk membedakan keberadaan historis suatu entitas dengan kind dan nama yang serupa.
1.4.4 - Namespace
Kubernetes mendukung banyak klaster virtual di dalam satu klaster fisik. Klaster virtual tersebut disebut dengan namespace.
Kapan menggunakan banyak Namespace
Namespace dibuat untuk digunakan di environment dengan banyak pengguna yang berada di dalam banyak tim ataupun proyek. Untuk sebuah klaster dengan beberapa pengguna saja, kamu tidak harus membuat ataupun memikirkan tentang namespace. Mulai gunakan namespace saat kamu membutuhkan fitur dari namespace itu sendiri.
Namespace menyediakan ruang untuk nama objek. Nama dari resource atau objek harus berbeda di dalam sebuah namespace, tetapi boleh sama jika berbeda namespace. Namespace tidak bisa dibuat di dalam namespace lain dan setiap resource atau objek Kubernetes hanya dapat berada di dalam satu namespace.
Namespace merupakan cara yang digunakan untuk memisahkan resource klaster untuk beberapa pengguna (dengan resource quota).
Dalam versi Kubernetes yang akan datang, objek di dalam satu namespace akan mempunyai access control policies yang sama secara default.
Tidak perlu menggunakan banyak namespace hanya untuk memisahkan sedikit perbedaan pada resource, seperti perbedaan versi dari perangkat lunak yang sama: gunakan label untuk membedakan resource di dalam namespace yang sama.
Kamu dapat melihat daftar namespace di dalam klaster menggunakan:
kubectl get namespace
NAME STATUS AGE
default Active 1d
kube-system Active 1d
kube-public Active 1d
Kubernetes berjalan dengan tiga namespace awal:
default, namespace default untuk objek yang dibuat tanpa mencantumkan namespace pada spesifikasinya.
kube-system, namespace yang digunakan untuk objek yang dibuat oleh sistem Kubernetes.
kube-public, namespace ini dibuat secara otomatis dan dapat diakses oleh semua pengguna (termasuk yang tidak diautentikasi). Namespace ini disediakan untuk penggunaan klaster, jika beberapa resouce harus terlihat dan dapat dibaca secara publik di seluruh klaster. Aspek publik dari namespace ini hanya sebuah konvensi, bukan persyaratan.
Mengkonfigurasi namespace untuk request
Untuk mengkonfigurasi sementara request untuk menggunakan namespace tertentu, gunakan --namespaceflag.
Sebagai contoh:
kubectl --namespace=<insert-namespace-name-here> run nginx --image=nginx
kubectl --namespace=<insert-namespace-name-here> get pods
Mengkonfigurasi preferensi namespace
Kamu dapat menyimpan konfigurasi namespace untuk semua perintah kubectl dengan perintah:
Saat kamu membuat sebuah Service, Kubernetes membuat Entri DNS untuk service tersebut. Entri DNS ini berformat <service-name>.<namespace-name>.svc.cluster.local, yang berarti jika sebuah kontainer hanya menggunakan <service-name>, kontainer tersebut akan berkomunikasi dengan service yang berada di dalam satu namespace. Ini berguna untuk menggunakan konfigurasi yang sama di beberapa namespace seperti Development, Staging, dan Production. Jika kamu ingin berkomunikasi antar namespace, kamu harus menggunakan seluruh fully qualified domain name (FQDN).
Tidak semua objek di dalam Namespace
Kebanyakan resource di Kubernetes (contohnya pod, service, replication controller, dan yang lain) ada di dalam namespace. Namun resource namespace sendiri tidak berada di dalam namespace. Dan low-level resource seperti node dan persistentVolume tidak berada di namespace manapun.
Untuk melihat resource di dalam kubernetes yang berada di dalam namespace ataupun tidak:
# Di dalam namespacekubectl api-resources --namespaced=true# Tidak di dalam namespacekubectl api-resources --namespaced=false
1.4.5 - Label dan Selektor
Label merupakan pasangan key/value yang melekat pada objek-objek, misalnya pada Pod.
Label digunakan untuk menentukan atribut identitas dari objek agar memiliki arti dan relevan bagi para pengguna, namun tidak secara langsung memiliki makna terhadap sistem inti.
Label dapat digunakan untuk mengatur dan memilih sebagian dari banyak objek. Label-label dapat ditempelkan ke objek-objek pada saat dibuatnya objek-objek tersebut dan kemudian ditambahkan atau diubah kapan saja setelahnya.
Setiap objek dapat memiliki satu set label key/value. Setiap Key harus unik untuk objek tersebut.
Label memungkinkan untuk menjalankan kueri dan pengamatan dengan efisien, serta ideal untuk digunakan pada UI dan CLI. Informasi yang tidak digunakan untuk identifikasi sebaiknya menggunakan anotasi.
Motivasi
Label memungkinkan pengguna untuk memetakan struktur organisasi mereka ke dalam objek-objek sistem yang tidak terikat secara erat, tanpa harus mewajibkan klien untuk menyimpan pemetaan tersebut.
Service deployments dan batch processing pipelines sering menjadi entitas yang berdimensi ganda (contohnya partisi berganda atau deployment, jalur rilis berganda, tingkatan berganda, micro-services berganda per tingkatan). Manajemen seringkali membutuhkan operasi lintas tim, yang menyebabkan putusnya enkapsulasi dari representasi hierarki yang ketat, khususnya pada hierarki-hierarki kaku yang justru ditentukan oleh infrastruktur, bukan oleh pengguna.
Ini hanya contoh label yang biasa digunakan; kamu bebas mengembangkan caramu sendiri. Perlu diingat bahwa Key dari label harus unik untuk objek tersebut.
Sintaksis dan set karakter
Label merupakan pasangan key/value. Key-key dari Label yang valid memiliki dua segmen: sebuah prefiks dan nama yang opsional, yang dipisahkan oleh garis miring (/). Segmen nama wajib diisi dan tidak boleh lebih dari 63, dimulai dan diakhiri dengan karakter alfanumerik ([a-z0-9A-Z]) dengan tanda pisah (-), garis bawah (_), titik (.), dan alfanumerik di antaranya. Sedangkan prefiks bersifat opsional. Jika ditentukan, prefiks harus berupa subdomain DNS: rangkaian label DNS yang dipisahkan oleh titik (.), dengan total tidak lebih dari 253 karakter, yang diikuti oleh garis miring (/).
Jika prefiks dihilangkan, Key dari label diasumsikan privat bagi pengguna. Komponen sistem otomatis (contoh kube-scheduler, kube-controller-manager, kube-apiserver, kubectl, atau otomasi pihak ketiga lainnya) yang akan menambah label ke objek-objek milik pengguna akhir harus menentukan prefiks.
Prefiks kubernetes.io/ dan k8s.io/ dikhususkan untuk komponen inti Kubernetes.
Nilai label yang valid tidak boleh lebih dari 63 karakter dan harus kosong atau diawali dan diakhiri dengan karakter alfanumerik ([a-z0-9A-Z]) dengan tanda pisah (-), garis bawah (_), titik (.), dan alfanumerik di antaranya.
Contoh di bawah ini merupakan berkas konfigurasi untuk Pod yang memiliki dua label environment: production dan app: nginx :
Tidak seperti nama dan UID, label tidak memberikan keunikan. Secara umum, kami memperkirakan bahwa banyak objek yang akan memiliki label yang sama.
Menggunakan sebuah label selector, klien/pengguna dapat mengidentifikasi suatu kumpulan objek. Selektor label merupakan alat/cara pengelompokan utama pada Kubernetes.
Saat ini API mendukung dua jenis selektor: equality-based dan set-based.
Sebuah selektor label dapat dibuat dari kondisi berganda yang dipisahkan oleh koma. Pada kasus kondisi berganda, semua kondisi harus dipenuhi sehingga separator koma dapat bertindak sebagai operator logika AND (&&).
Makna dari selektor yang kosong atau tidak diisi tergantung dari konteks, dan tipe API yang menggunakan selektor harus mendokumentasikan keabsahan dan arti dari selektor yang kosong tersebut.
Catatan: Untuk beberapa tipe API, seperti ReplicaSet, selektor label untuk dua objek tidak boleh tumpang tindih dengan Namespace, jika tidak maka controller akan melihatnya sebagai instruksi yang menyebabkan konflik dan akan gagal menentukan berapa banyak replika yang seharusnya tersedia.
Perhatian: Untuk kedua kondisi equality-based dan set-based tidak ada logika operator OR (||). Pastikan struktur pernyataan filter kamu ikut disesuaikan.
Kondisi Equality-based
Kondisi Equality-based atau inequality-based memungkinkan untuk melakukan filter dengan menggunakan key dan value dari label. Objek yang cocok harus memenuhi semua batasan label yang telah ditentukan, meskipun mereka dapat memiliki label tambahan lainnya.
Terdapat tiga jenis operator yang didukung yaitu =,==,!=. Dua operator pertama menyatakan kesamaan (keduanya hanyalah sinonim), sementara operator terakhir menyatakan ketidaksamaan. Contoh:
environment = production
tier != frontend
Kondisi pertama akan memilih semua sumber daya dengan keyenvironment dan nilai keyproduction.
Kondisi berikutnya akan memilih semua sumber daya dengan keytier dan nilai key selain frontend, dan semua sumber daya yang tidak memiliki label dengan keytier.
Kamu juga dapat memfilter sumber daya dalam production selain frontend dengan menggunakan operator koma: environment=production,tier!=frontend
Salah satu skenario penggunaan label dengan kondisi equality-based yaitu untuk kriteria pemilihan Node untuk Pod-Pod. Sebagai contoh, Pod percontohan di bawah ini akan memilih Node dengan label "accelerator=nvidia-tesla-p100".
Kondisi label Set-based memungkinkan memfilter key terhadap suatu kumpulan nilai. Terdapat tiga jenis operator yang didukung, yaitu: in,notin, dan exists (hanya key-nya saja). Contoh:
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
Contoh pertama akan memilih semua sumber daya dengan keyenvironment dan nilai production atau qa.
Contoh kedua akan memilih semua sumber daya dengan keytier dan nilai selain frontend dan backend, serta semua sumber daya yang tidak memiliki label dengan keytier.
Contoh ketiga akan memilih semua sumber daya yang memiliki key dari labelpartition; nilainya tidak diperiksa.
Sedangkan contoh keempat akan memilih semua sumber daya yang tidak memiliki label dengan keypartition; nilainya tidak diperiksa.
Secara serupa, operator koma bertindak sebagai operator AND. Sehingga penyaringan sumber daya dengan keypartition (tidak peduli nilai dari key) dan environment yang tidak sama dengan qa dapat dicapai dengan partition,environment notin (qa).
Selektor label set-based merupakan bentuk umum persamaan karena environment=production sama dengan environment in (production); demikian pula != dan notin.
Kondisi Set-based dapat digabungkan dengan kondisi equality-based. Contoh: partition in (customerA, customerB),environment!=qa.
API
Penyaringan LIST dan WATCH
Operasi LIST dan WATCH dapat menentukan selektor label untuk memfilter suatu kumpulan objek yang didapat dengan menggunakan parameter kueri. Kedua jenis kondisi diperbolehkan (ditampilkan sebagai berikut, sama seperti saat tampil pada string kueri di URL):
Kondisi equality-based: ?labelSelector=environment%3Dproduction,tier%3Dfrontend
Kondisi set-based: ?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29
Kedua jenis selektor label dapat digunakan untuk menampilkan (list) dan mengamati (watch) sumber daya melalui klien REST. Contohnya, menargetkan apiserver dengan kubectl dan menggunakan equality-based kamu dapat menuliskan:
kubectl get pods -l environment=production,tier=frontend
atau menggunakan kondisi set-based:
kubectl get pods -l 'environment in (production),tier in (frontend)'
Seperti yang telah disebutkan sebelumnya, kondisi set-based lebih ekspresif. Sebagai contoh, mereka dapat digunakan untuk mengimplementasi operator OR pada nilai:
kubectl get pods -l 'environment in (production, qa)'
atau membatasi pencocokan negatif dengan operator exists:
kubectl get pods -l 'environment,environment notin (frontend)'
Mengatur referensi pada objek API
Pada beberapa objek Kubernetes, seperti Service dan ReplicationController, juga menggunakan selektor label untuk menentukan kumpulan dari sumber daya lain, seperti Pod.
Service dan ReplicationController
Kumpulan Pod yang ditargetkan oleh sebuah service ditentukan dengan selektor label. Demikian pula kumpulan Pod yang harus ditangani oleh replicationcontroller juga ditentukan dengan selektor label.
Selektor label untuk kedua objek tersebut ditentukan dalam berkas json atau yaml menggunakan maps, dan hanya mendukung kondisi equality-based:
"selector": {
"component" : "redis",
}
atau
selector:component:redis
selektor ini (baik dalam bentuk json atau yaml) sama dengan component=redis atau component in (redis).
matchLabels merupakan pemetaan dari pasangan {key,value}. Sebuah {key,value} pada pemetaan matchLabels adalah sama dengan elemen dari matchExpressions, yang nilai key nya adalah "key", dengan operator "In", dan arrayvalues hanya berisi "value". matchExpressions merupakan daftar kondisi untuk selektor Pod. Operator yang valid termasuk In, NotIn, Exists, dan DoesNotExist. Kumpulan nilai ini tidak boleh kosong pada kasus In dan NotIn. Semua kondisi, baik dari matchLabels dan matchExpressions di-AND secara sekaligus -- mereka harus memenuhi semua kondisi agar cocok.
Memilih kumpulan Node
Salah satu contoh penggunaan pemilihan dengan menggunakan label yaitu untuk membatasi suatu kumpulan Node tertentu yang dapat digunakan oleh Pod.
Lihat dokumentasi pada pemilihan Node untuk informasi lebih lanjut.
1.4.6 - Anotasi
Kamu dapat menggunakan fitur anotasi dari Kubernetes untuk menempelkan sembarang
metadata tanpa identitas pada suatu objek. Klien, seperti perangkat dan library,
dapat memperoleh metadata tersebut.
Mengaitkan metadata pada objek
Kamu dapat menggunakan label maupun anotasi untuk menempelkan metadata pada suatu
objek Kubernetes. Label dapat digunakan untuk memilih objek dan mencari sekumpulan
objek yang memenuhi kondisi tertentu. Sebaliknya, anotasi tidak digunakan untuk
mengenali atau memilih objek. Metadata dalam sebuah anotasi bisa berukuran kecil atau besar,
terstruktur atau tidak terstruktur, dan dapat berisikan karakter-karakter yang tidak
diperbolehkan oleh label.
Anotasi, seperti label, merupakan pemetaan key/value:
Berikut merupakan beberapa contoh informasi yang dapat dicatat dengan menggunakan anotasi:
Field-field yang dikelola secara deklaratif oleh layer konfigurasi. Menempelkan
field-field tersebut sebagai anotasi membedakan mereka dari nilai default yang
ditetapkan oleh klien ataupun server, dari field-field yang otomatis di-generate, serta
dari field-field yang ditetapkan oleh sistem auto-sizing atau auto-scaling.
Informasi mengenai build, rilis, atau image, seperti timestamp, rilis ID, git branch,
nomor PR, hash suatu image, dan alamat registri.
Penanda untuk logging, monitoring, analytics, ataupun repositori audit.
Informasi mengenai library klien atau perangkat yang dapat digunakan untuk debugging:
misalnya, informasi nama, versi, dan build.
Informasi yang berhubungan dengan pengguna atau perangkat/sistem, seperti URL objek yang terkait
dengan komponen dari ekosistem lain.
Metadata untuk perangkat rollout yang ringan (lightweight): contohnya, untuk
konfigurasi atau penanda (checkpoint).
Nomor telepon atau pager dari orang yang bertanggung jawab, atau entri direktori
yang berisi informasi lebih lanjut, seperti website sebuah tim.
Arahan dari pengguna (end-user) untuk melakukan implementasi, perubahan perilaku,
ataupun untuk interaksi dengan fitur-fitur non-standar.
Tanpa menggunakan anotasi, kamu dapat saja menyimpan informasi-informasi dengan tipe
di atas pada suatu basis data atau direktori eksternal, namun hal ini sangat mempersulit
pembuatan library klien dan perangkat yang bisa digunakan sama-sama (shared) untuk melakukan
deploy, pengelolaan, introspeksi, dan semacamnya.
Sintaksis dan sekumpulan karakter
Anotasi merupakan key/value pair. Key dari sebuah anotasi yang valid memiliki dua segmen: segmen prefiks yang opsional dan segmen nama, dipisahkan
oleh sebuah garis miring (/). Segmen nama bersifat wajib dan harus terdiri dari 63 karakter atau kurang, dimulai dan diakhiri dengan karakter alfanumerik ([a-z0-9A-Z]) dengan tanda minus (-), garis bawah (_), titik (.), dan alfanumerik di tengahnya. Jika terdapat prefiks,
prefiks haruslah berupa subdomain DNS: urutan dari label DNS yang dipisahkan oleh titik (.), totalnya tidak melebihi 253 karakter,
diikuti dengan garis miring (/).
Jika tidak terdapat prefiks, maka key dari anotasi diasumsikan hanya bisa dilihat oleh pengguna (privat). Komponen sistem otomasi
(seperti kube-scheduler, kube-controller-manager, kube-apiserver, kubectl, ataupun otomasi pihak ketiga) yang menambahkan anotasi
pada objek-objek pengguna harus memiliki sebuah prefiks.
Prefiks kubernetes.io/ dan k8s.io/ merupakan reservasi dari komponen inti Kubernetes.
Selektor field memungkinkan kamu untuk memilih (select) resource Kubernetes berdasarkan
nilai dari satu atau banyak field resource. Di bawah ini merupakan contoh dari beberapa query selektor field:
metadata.name=my-service
metadata.namespace!=default
status.phase=Pending
Perintah kubectl di bawah ini memilih semua Pod dengan fieldstatus.phase yang bernilai
Running:
kubectl get pods --field-selector status.phase=Running
Catatan:
Pada dasarnya, selektor field merupakan filter dari resource. Secara default, tidak ada selektor/filter apapun yang diterapkan. Artinya,
semua resource dengan tipe apapun akan terpilih. Akibatnya, query dengan perintah kubectl di bawah ini akan memberikan hasil yang sama:
kubectl get pods
kubectl get pods --field-selector ""
Field yang didukung
Selektor-selektor field yang didukung oleh Kubernetes bervariasi tergantung dari tipe resource. Semua tipe resource mendukung fieldmetadata.name dan metadata.namespace. Jika kamu menggunakan selektor field yang tidak didukung, maka akan terjadi error. Contohnya:
kubectl get ingress --field-selector foo.bar=baz
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"
Operator yang didukung
Kamu dapat menggunakan operator =, ==, dan != pada selektor field (= dan == punya arti yang sama). Sebagai contoh, perintah kubectl ini
memilih semua Kubernetes Service yang tidak terdapat pada namespacedefault:
kubectl get services --field-selector metadata.namespace!=default
Selektor berantai
Seperti halnya label dan selektor-selektor lainnya, kamu dapat membuat selektor field berantai
(chained) dengan list yang dipisahkan oleh koma. Perintah kubectl di bawah ini memilih semua Pod dengan status.phase tidak sama dengan
Running dan fieldspec.restartPolicy sama dengan Always:
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always
Resource dengan beberapa tipe
Kamu dapat menggunakan selektor-selektor field dengan beberapa tipe resource sekaligus. Perintah kubectl di bawah ini memilih semua Statefulset
dan Service yang tidak terdapat pada namespacedefault:
kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default
1.4.8 - Label yang Disarankan
Kamu dapat melakukan visualisasi dan mengatur objek Kubernetes dengan lebih banyak tools
dibandingkan dengan perintah kubectl dan dasbor. Sekumpulan label mengizinkan tools
untuk bekerja dengan interoperabilitas, mendeskripsikan objek dengan cara yang umum yang dapat
dipahami semua tools.
Sebagai tambahan bagi tooling tambahan, label yang disarankan ini mendeskripsikan
aplikasi sehingga informasi yang ada diapat di-query.
Metadata ini diorganisasi berbasis konsep dari sebuah aplikasi. Kubernetes bukan merupakan
sebuah platform sebagai sebuah service (platform as a service/PaaS) dan tidak
mewajibkan sebuah gagasan formal dari sebuah aplikasi.
Sebagai gantinya, aplikasi merupakan suatu hal informal yang dideskripsikan melalui metadata.
Definisi yang dimiliki oleh sebuah aplikasi merupakan sebuah hal yang cukup longgar.
Catatan: Berikut merupakan label yang disarankan. Label ini mempermudah
proses manajemen aplikasi tetapi tidak dibutuhkan untuk tooling utama apa pun.
Label yang digunakan secara umum serta anotasi memiliki prefiks yang serupa: app.kubernetes.io. Label
tanpa sebuah prefiks bersifat privat khusus pengguna saja. Prefiks yang digunakan secara umum tadi
menjamin bahwa label tadi tidak akan mengganggu label custom yang diberikan oleh pengguna.
Label
Untuk mendapatkan keuntungan menyeluruh dari penggunaan label ini,
label harus digunakan pada seluruh objek sumber daya.
Key
Deskripsi
Contoh
Tipe
app.kubernetes.io/name
Nama aplikasi
mysql
string
app.kubernetes.io/instance
Nama unik yang bersifat sebagai pengidentifikasi dari sebuah instans aplikasi
wordpress-abcxzy
string
app.kubernetes.io/version
Versi saat ini dari aplikasi (misalnya sebuah versi semantik, hash revisi, etc.)
5.7.21
string
app.kubernetes.io/component
Komponen yang ada pada arsitektur
database
string
app.kubernetes.io/part-of
Nama dari komponen lebih tinggi dari aplikasi yang mencakup bagian ini
wordpress
string
app.kubernetes.io/managed-by
Alat yang digunakan untuk mengatur operasi pada aplikasi
helm
string
Untuk memberikan ilustrasi dari penggunaan label, bayangkan sebuah objek StatefulSet yang didefinisikan sebagai berikut:
Sebuah aplikasi dapat diinstal sekali atau beberapa kali di dalam klaster Kubernetes dan,
pada beberapa kasus, di dalam sebuah namespace yang sama. Misalnya, wordpress dapat
diinstal lebih dari satu kali dimana situs web yang berbeda merupakan hasil instalasi yang berbeda.
Nama dari sebuah aplikasi dan nama instans akan dicatat secara terpisah. Sebagai contoh,
WordPress memiliki wordpress sebagai nilai dari app.kubernetes.io/name dimana
nama instans yang digunakan adalah wordpress-abcxzy yang merupakan nilai dari app.kubernetes.io/instance.
Hal ini memungkinkan aplikasi dan instans aplikasi untuk dapat diidentifikasi. Setiap instans dari aplikasi
haruslah memiliki nama yang unik.
Contoh
Untuk memberikan ilustrasi dengan cara yang berbeda pada penggunaan label, contoh di bawah ini
memiliki tingkat kompleksitas yang cukup beragam.
Sebuah Aplikasi Stateless Sederhana
Bayangkan sebuah kasus dimana sebuah aplikasi stateless di-deploy
menggunakan Deployment dan Service. Di bawah ini merupakan
contoh kutipan yang merepresentasikan bagaimana
label dapat digunakan secara sederhana.
Deployment digunakan untuk memastikan Pod dijalankan untuk aplikasi itu sendiri.
Bayangkan sebuah aplikasi yang lebih kompleks: sebuah aplikasi web (WordPress)
yang menggunakan basis data (MySQL), yang diinstal menggunakan Helm.
Kutipan berikut merepresentasikan objek yang di-deploy untuk aplikasi ini.
Berikut merupakan konfigurasi Deployment yang digunakan untuk WordPress:
Dengan StatefulSet MySQL dan Service kamu dapat mengetahui informasi yang ada pada MySQL dan Wordpress.
2 - Arsitektur Kubernetes
2.1 - Node
Node merupakan sebuah mesin worker di dalam Kubernetes, yang sebelumnya dinamakan minion.
Sebuah node bisa berupa VM ataupun mesin fisik, tergantung dari klaster-nya.
Masing-masing node berisi beberapa servis yang berguna untuk menjalankan banyak pod dan diatur oleh komponen-komponen yang dimiliki oleh master.
Servis-servis di dalam sebuah node terdiri dari runtime kontainer, kubelet dan kube-proxy.
Untuk lebih detail, lihat dokumentasi desain arsitektur pada Node Kubernetes.
Status Node
Sebuah status node berisikan informasi sebagai berikut:
Masing-masing bagian dijelaskan secara rinci di bawah ini.
Addresses
Penggunaan field-field ini bergantung pada penyedia layanan cloud ataupun konfigurasi bare metal yang kamu punya.
HostName: Merupakan hostname yang dilaporkan oleh kernel node. Dapat diganti melalui parameter --hostname-override pada kubelet.
ExternalIP: Biasanya merupakan alamat IP pada node yang punya route eksternal (bisa diakses dari luar klaster).
InternalIP: Biasanya merupakan alamat IP pada node yang hanya punya route di dalam klaster.
Condition
Fieldconditions menjelaskan tentang status dari semua node yang sedang berjalan (Running).
Kondisi Node
Penjelasan
OutOfDisk
True jika node sudah tidak punya cukup kapasitas disk untuk menjalankan pod baru, False jika sebaliknya
Ready
True jika node sehat (healthy) dan siap untuk menerima pod, False jika node tidak lagi sehat (unhealthy) dan tidak siap menerima pod, serta Unknown jika kontroler node tidak menerima pesan di dalam node-monitor-grace-period (standarnya 40 detik)
MemoryPressure
True jika memori pada node terkena tekanan (pressure) -- maksudnya, jika kapasitas memori node sudah di titik rendah; False untuk sebaliknya
PIDPressure
True jika process-process mengalami tekanan (pressure) -- maksudnya, jika node menjalankan terlalu banyak process; False untuk sebaliknya
DiskPressure
True jika ukuran disk mengalami tekanan (pressure) -- maksudnya, jika kapasitas disk sudah di titik rendah; False untuk sebaliknya
NetworkUnavailable
True jika jaringan untuk node tidak dikonfigurasi dengan benar, False untuk sebaliknya
Condition pada node direpresentasikan oleh suatu obyek JSON. Sebagai contoh, respon berikut ini menggambarkan node yang sedang sehat (healthy).
Jika status untuk Ready condition bernilai Unknown atau False untuk waktu yang lebih dari pod-eviction-timeout, tergantung bagaimana kube-controller-manager dikonfigurasi, semua pod yang dijalankan pada node tersebut akan dihilangkan oleh Kontroler Node.
Durasi eviction timeout yang standar adalah lima menit.
Pada kasus tertentu ketika node terputus jaringannya, apiserver tidak dapat berkomunikasi dengan kubelet yang ada pada node.
Keputusan untuk menghilangkan pod tidak dapat diberitahukan pada kubelet, sampai komunikasi dengan apiserver terhubung kembali.
Sementara itu, pod-pod akan terus berjalan pada node yang sudah terputus, walaupun mendapati schedule untuk dihilangkan.
Pada versi Kubernetes sebelum 1.5, kontroler node dapat menghilangkan dengan paksa (force delete) pod-pod yang terputus dari apiserver.
Namun, pada versi 1.5 dan seterusnya, kontroler node tidak menghilangkan pod dengan paksa, sampai ada konfirmasi bahwa pod tersebut sudah berhenti jalan di dalam klaster.
Pada kasus dimana Kubernetes tidak bisa menarik kesimpulan bahwa ada node yang telah meninggalkan klaster, admin klaster mungkin perlu untuk menghilangkan node secara manual.
Menghilangkan obyek node dari Kubernetes akan membuat semua pod yang berjalan pada node tersebut dihilangkan oleh apiserver, dan membebaskan nama-namanya agar bisa digunakan kembali.
Pada versi 1.12, fitur TaintNodesByCondition telah dipromosikan ke beta, sehingga kontroler lifecycle node secara otomatis membuat taints yang merepresentasikan conditions.
Akibatnya, scheduler menghiraukan conditions ketika mempertimbangkan sebuah Node; scheduler akan melihat pada taints sebuah Node dan tolerations sebuah Pod.
Sekarang, para pengguna dapat memilih antara model scheduling yang lama dan model scheduling yang lebih fleksibel.
Pada model yang lama, sebuah pod tidak memiliki tolerations apapun sampai mendapat giliran schedule. Namun, pod dapat dijalankan pada Node tertentu, dimana pod melakukan toleransi terhadap taints yang dimiliki oleh Node tersebut.
Perhatian: Mengaktifkan fitur ini menambahkan delay sedikit antara waktu saat suatu condition terlihat dan saat suatu taint dibuat. Delay ini biasanya kurang dari satu detik, tapi dapat menambahkan jumlah yang telah berhasil mendapat schedule, namun ditolak oleh kubelet untuk dijalankan.
Capacity
Menjelaskan tentang resource-resource yang ada pada node: CPU, memori, dan jumlah pod secara maksimal yang dapat dijalankan pada suatu node.
Info
Informasi secara umum pada suatu node, seperti versi kernel, versi Kubernetes (versi kubelet dan kube-proxy), versi Docker (jika digunakan), nama OS.
Informasi ini dikumpulkan oleh Kubelet di dalam node.
Manajemen
Tidak seperti pod dan service, sebuah node tidaklah dibuat dan dikonfigurasi oleh Kubernetes: tapi node dibuat di luar klaster oleh penyedia layanan cloud, seperti Google Compute Engine, atau pool mesin fisik ataupun virtual (VM) yang kamu punya.
Jadi ketika Kubernetes membuat sebuah node, obyek yang merepresentasikan node tersebut akan dibuat.
Setelah pembuatan, Kubernetes memeriksa apakah node tersebut valid atau tidak.
Contohnya, jika kamu mencoba untuk membuat node dari konten berikut:
Kubernetes membuat sebuah obyek node secara internal (representasinya), dan melakukan validasi terhadap node. Validasi dilakukan dengan memeriksa kondisi kesehatan node (health checking), berdasarkan fieldmetadata.name. Jika node valid -- terjadi saat semua servis yang diperlukan sudah jalan -- maka node diperbolehkan untuk menjalankan sebuah pod.
Namun jika tidak valid, node tersebut akan dihiraukan untuk aktivitas apapun yang berhubungan dengan klaster, sampai telah menjadi valid.
Catatan: Kubernetes tetap menyimpan obyek untuk node yang tidak valid, dan terus memeriksa apakah node telah menjadi valid atau belum.
Kamu harus secara eksplisit menghilangkan obyek Node tersebut untuk menghilangkan proses ini.
Saat ini, ada tiga komponen yang berinteraksi dengan antarmuka node di Kubernetes: kontroler node, kubelet, dan kubectl.
Kontroler Node
Kontroler node adalah komponen master Kubernetes yang berfungsi untuk mengatur berbagai aspek dari node.
Kontroler node memiliki berbagai peran (role) dalam sebuah lifecycle node.
Pertama, menetapkan blok CIDR pada node tersebut saat registrasi (jika CIDR assignment diaktifkan).
Kedua, terus memperbarui daftar internal node di dalam kontroler node, sesuai dengan daftar mesin yang tersedia di dalam penyedia layanan cloud.
Ketika berjalan di dalam environment cloud, kapanpun saat sebuah node tidak lagi sehat (unhealthy), kontroler node bertanya pada penyedia cloud, apakah VM untuk node tersebut masihkah tersedia atau tidak.
Jika sudah tidak tersedia, kontroler node menghilangkan node tersebut dari daftar node.
Ketiga, melakukan monitor terhadap kondisi kesehatan (health) node.
Kontroler node bertanggung jawab untuk mengubah status NodeReady condition pada NodeStatus menjadi ConditionUnknown, ketika sebuah node terputus jaringannya (kontroler node tidak lagi mendapat heartbeat karena suatu hal, contohnya karena node tidak hidup), dan saat kemudian melakukan eviction terhadap semua pod yang ada pada node tersebut (melalui terminasi halus -- graceful) jika node masih terus terputus. (Timeout standar adalah 40 detik untuk mulai melaporkan ConditionUnknown dan 5 menit setelah itu untuk mulai melakukan eviction terhadap pod.)
Kontroler node memeriksa state masing-masing node untuk durasi yang ditentukan oleh argumen --node-monitor-period.
Pada versi Kubernetes sebelum 1.13, NodeStatus adalah heartbeat yang diberikan oleh node.
Setelah versi 1.13, fitur node lease diperkenalkan sebagai fitur alpha (fitur gate NodeLease,
KEP-0009).
Ketika fitur node lease diaktifasi, setiap node terhubung dengan obyek Lease di dalam namespacekube-node-lease yang terus diperbarui secara berkala.
Kemudian, NodeStatus dan node lease keduanya dijadikan sebagai heartbeat dari node.
Semua node lease diperbarui sesering mungkin, sedangkan NodeStatus dilaporkan dari node untuk master hanya ketika ada perubahan atau telah melewati periode waktu tertentu (default-nya 1 menit, lebih lama daripada default timeout node-node yang terputus jaringannya).
Karena node lease jauh lebih ringan daripada NodeStatus, fitur ini membuat heartbeat dari node jauh lebih murah secara signifikan dari sudut pandang skalabilitas dan performa.
Di Kubernetes 1.4, kami telah memperbarui logic dari kontroler node supaya lebih baik dalam menangani kasus saat banyak sekali node yang tidak bisa terhubung dengan master (contohnya, karena master punya masalah jaringan).
Mulai dari 1.4, kontroler node melihat state dari semua node di dalam klaster, saat memutuskan untuk melakukan eviction pada pod.
Pada kasus kebanyakan, kontroler node membatasi rate eviction menjadi --node-eviction-rate (default-nya 0.1) per detik.
Artinya, kontroler node tidak akan melakukan eviction pada pod lebih dari 1 node per 10 detik.
Perlakuan eviction pada node berubah ketika sebuah node menjadi tidak sehat (unhealthy) di dalam suatu zona availability.
Kontroler node memeriksa berapa persentase node di dalam zona tersebut yang tidak sehat (saat NodeReady condition menjadi ConditionUnknown atau ConditionFalse) pada saat yang bersamaan.
Jika persentase node yang tidak sehat bernilai --unhealthy-zone-threshold (default-nya 0.55), maka rate eviction berkurang: untuk ukuran klaster yang kecil (saat jumlahnya lebih kecil atau sama dengan jumlah node --large-cluster-size-threshold - default-nya 50), maka eviction akan berhenti dilakukan.
Jika masih besar jumlahnya, rate eviction dikurangi menjadi --secondary-node-eviction-rate (default-nya 0.01) per detik.
Alasan kenapa hal ini diimplementasi untuk setiap zona availability adalah karena satu zona bisa saja terputus dari master, saat yang lainnya masih terhubung.
Jika klaster tidak menjangkau banyak zona availability yang disediakan oleh penyedia cloud, maka hanya ada satu zona (untuk semua node di dalam klaster).
Alasan utama untuk menyebarkan node pada banyak zona availability adalah supaya workload dapat dipindahkan ke zona sehat (healthy) saat suatu zona mati secara menyeluruh.
Kemudian, jika semua node di dalam suatu zona menjadi tidak sehat (unhealthy), maka kontroler node melakukan eviction pada rate normal --node-eviction-rate.
Kasus khusus, ketika seluruh zona tidak ada satupun sehat (tidak ada node yang sehat satupun di dalam klaster).
Pada kasus ini, kontroler node berasumsi ada masalah pada jaringan master, dan menghentikan semua eviction sampai jaringan terhubung kembali.
Mulai dari Kubernetes 1.6, kontroler node juga bertanggung jawab untuk melakukan eviction pada pod-pod yang berjalan di atas node dengan taintsNoExecute, ketika pod-pod tersebut sudah tidak lagi tolerate terhadap taints.
Sebagai tambahan, hal ini di-nonaktifkan secara default pada fitur alpha, kontroler node bertanggung jawab untuk menambahkan taints yang berhubungan dengan masalah pada node, seperti terputus atau NotReady.
Lihat dokumentasi ini untuk bahasan detail tentang taintsNoExecute dan fitur alpha.
Mulai dari versi 1.8, kontroler node bisa diatur untuk bertanggung jawab pada pembuatan taints yang merepresentasikan node condition.
Ini merupakan fitur alpha untuk versi 1.8.
Self-Registration untuk Node
Ketika argumen --register-node pada kubelet bernilai true (default-nya), kubelet akan berusaha untuk registrasi dirinya melalui API server.
Ini merupakan pattern yang disukai, digunakan oleh kebanyakan distros.
Kubelet memulai registrasi diri (self-registration) dengan opsi-opsi berikut:
--kubeconfig - Path berisi kredensial-kredensial yang digunakan untuk registrasi diri pada apiserver.
--cloud-provider - Cara berbicara pada sebuah penyedia layanan cloud, baca tentang metadata-nya.
--register-node - Registrasi secara otomatis pada API server.
--register-with-taints - Registrasi node dengan daftar taints (dipisahkan oleh koma <key>=<value>:<effect>). No-op jika register-node bernilai false.
--node-ip - Alamat IP dari node dimana kubelet berjalan.
--node-labels - Label-label untuk ditambahkan saat melakukan registrasi untuk node di dalam klaster (lihat label yang dibatasi secara paksa oleh NodeRestriction admission plugin untuk 1.13+).
--node-status-update-frequency - Menentukan seberapa sering kubelet melaporkan status pada master.
Seorang admin klaster dapat membuat dan memodifikasi obyek node.
Jika admin ingin untuk membuat obyek node secara manual, atur argument --register-node=false pada kubelet.
Admin dapat memodifikasi resource-resource node (terlepas dari --register-node).
Modifikasi terdiri dari pengaturan label pada node dan membuat node tidak dapat di-schedule.
Label-label pada node digunakan oleh selector node untuk mengatur proses schedule untuk pod, misalnya, membatasi sebuah pod hanya boleh dijalankan pada node-node tertentu.
Menandai sebuah node untuk tidak dapat di-schedule mencegah pod baru untuk tidak di-schedule pada node, tanpa mempengaruhi pod-pod yang sudah berjalan pada node tersebut.
Ini berguna sebagai langkah persiapan untuk melakukan reboote pada node.
Sebagai contoh, untuk menandai sebuah node untuk tidak dapat di-schedule, jalankan perintah berikut:
kubectl cordon $NODENAME
Catatan: Pod-pod yang dibuat oleh suatu kontroler DaemonSet menghiraukan scheduler Kubernetes dan mengabaikan tanda unschedulable pada node.
Hal ini mengasumsikan bahwa daemons dimiliki oleh mesin, walaupun telah dilakukan drain pada aplikasi, saat melakukan persaiapan reboot.
Kapasitas Node
Kapasitas node (jumlah CPU dan memori) adalah bagian dari obyek node.
Pada umumnya, node-node melakukan registrasi diri dan melaporkan kapasitasnya saat obyek node dibuat.
Jika kamu melakukan administrasi node manual, maka kamu perlu mengatur kapasitas node saat menambahkan node baru.
Scheduler Kubernetes memastikan kalau ada resource yang cukup untuk menjalankan semua pod di dalam sebuah node.
Kubernetes memeriksa jumlah semua request untuk kontainer pada sebuah node tidak lebih besar daripada kapasitas node.
Hal ini termasuk semua kontainer yang dijalankan oleh kubelet. Namun, ini tidak termasuk kontainer-kontainer yang dijalankan secara langsung oleh runtime kontainer ataupun process yang ada di luar kontainer.
Node adalah tingkatan tertinggi dari resource di dalam Kubernetes REST API.
Penjelasan lebih detail tentang obyek API dapat dilihat pada: Obyek Node API.
2.2 - Komunikasi antara Control Plane dan Node
Dokumen ini menjelaskan tentang jalur-jalur komunikasi di antara klaster Kubernetes dan control plane yang sebenarnya hanya berhubungan dengan apiserver saja.
Kenapa ada dokumen ini? Supaya kamu, para pengguna Kubernetes, punya gambaran bagaimana mengatur instalasi untuk memperketat konfigurasi jaringan di dalam klaster.
Hal ini cukup penting, karena klaster bisa saja berjalan pada jaringan tak terpercaya (untrusted network), ataupun melalui alamat-alamat IP publik pada penyedia cloud.
Node Menuju Control Plane
Kubernetes memiliki sebuah pola API "hub-and-spoke". Semua penggunaan API dari Node (atau Pod dimana Pod-Pod tersebut dijalankan) akan diterminasi pada apiserver (tidak ada satu komponen control plane apa pun yang didesain untuk diekspos pada servis remote).
Apiserver dikonfigurasi untuk mendengarkan koneksi aman remote yang pada umumnya terdapat pada porta HTTPS (443) dengan satu atau lebih bentuk autentikasi klien yang dipasang.
Sebaiknya, satu atau beberapa metode otorisasi juga dipasang, terutama jika kamu memperbolehkan permintaan anonim (anonymous request) ataupun service account token.
Jika diperlukan, Pod-Pod dapat terhubung pada apiserver secara aman dengan menggunakan ServiceAccount.
Dengan ini, Kubernetes memasukkan public root certificate dan bearer token yang valid ke dalam Pod, secara otomatis saat Pod mulai dijalankan.
Kubernetes Service (di dalam semua Namespace) diatur dengan sebuah alamat IP virtual. Semua yang mengakses alamat IP ini akan dialihkan (melalui kube-proxy) menuju endpoint HTTPS dari apiserver.
Komponen-komponen juga melakukan koneksi pada apiserver klaster melalui porta yang aman.
Akibatnya, untuk konfigurasi yang umum dan standar, semua koneksi dari klaster (node-node dan pod-pod yang berjalan di atas node tersebut) menujucontrol planesudah terhubung dengan aman.
Dan juga, klaster dancontrol planebisa terhubung melalui jaringan publik dan/atau yang tak terpercaya (untrusted).
Control Plane menuju Node
Ada dua jalur komunikasi utama dari control plane (apiserver) menuju klaster. Pertama, dari apiserver ke proses kubelet yang berjalan pada setiap Node di dalam klaster. Kedua, dari apiserver ke setiap Node, Pod, ataupun Service melalui fungsi proksi pada apiserver
Apiserver menuju kubelet
Koneksi dari apiserver menuju kubelet bertujuan untuk:
Melihat log dari pod-pod.
Masuk ke dalam pod-pod yang sedang berjalan (attach).
Menyediakan fungsi port-forward dari kubelet.
Semua koneksi ini diterminasi pada endpoint HTTPS dari kubelet.
Secara default, apiserver tidak melakukan verifikasi serving certificate dari kubelet, yang membuat koneksi terekspos pada serangan man-in-the-middle, dan juga tidak aman untuk terhubung melalui jaringan tak terpercaya (untrusted) dan/atau publik.
Untuk melakukan verifikasi koneksi ini, berikan root certificate pada apiserver melalui tanda --kubelet-certificate-authority, sehingga apiserver dapat memverifikasi serving certificate dari kubelet.
Cara lainnya, gunakan tunnel SSH antara apiserver dan kubelet jika diperlukan, untuk menghindari komunikasi melalui jaringan tak terpercaya (untrusted) atau publik.
Secara default, koneksi apiserver menuju node, pod atau service hanyalah melalui HTTP polos (plain), sehingga tidak ada autentikasi maupun enkripsi.
Koneksi tersebut bisa diamankan melalui HTTPS dengan menambahkan https: pada URL API dengan nama dari node, pod, atau service.
Namun, koneksi tidak tervalidasi dengan certificate yang disediakan oleh endpoint HTTPS maupun kredensial client, sehingga walaupun koneksi sudah terenkripsi, tidak ada yang menjamin integritasnya.
Koneksi ini tidak aman untuk dilalui pada jaringan publik dan/atau tak terpercaya untrusted.
Tunnel SSH
Kubernetes menyediakan tunnel SSH untuk mengamankan jalur komunikasi control plane -> Klaster.
Dengan ini, apiserver menginisiasi sebuah tunnel SSH untuk setiap node di dalam klaster (terhubung ke server SSH di port 22) dan membuat semua trafik menuju kubelet, node, pod, atau service dilewatkan melalui tunnel tesebut.
Tunnel ini memastikan trafik tidak terekspos keluar jaringan dimana node-node berada.
Tunnel SSH saat ini sudah usang (deprecated), jadi sebaiknya jangan digunakan, kecuali kamu tahu pasti apa yang kamu lakukan.
Sebuah desain baru untuk mengganti kanal komunikasi ini sedang disiapkan.
2.3 - Controller
Dalam bidang robotika dan otomatisasi, control loop atau kontrol tertutup adalah
lingkaran tertutup yang mengatur keadaan suatu sistem.
Berikut adalah salah satu contoh kontrol tertutup: termostat di sebuah ruangan.
Ketika kamu mengatur suhunya, itu mengisyaratkan ke termostat
tentang keadaan yang kamu inginkan. Sedangkan suhu kamar yang sebenarnya
adalah keadaan saat ini. Termostat berfungsi untuk membawa keadaan saat ini
mendekati ke keadaan yang diinginkan, dengan menghidupkan atau mematikan
perangkat.
Di Kubernetes, controller adalah kontrol tertutup yang mengawasi keadaan klaster
klaster kamu, lalu membuat atau meminta
perubahan jika diperlukan. Setiap controller mencoba untuk memindahkan status
klaster saat ini mendekati keadaan yang diinginkan.
Di Kubernetes, pengontrol adalah kontrol tertutup yang mengawasi kondisi klaster, lalu membuat atau meminta perubahan jika diperlukan. Setiap pengontrol mencoba untuk memindahkan status klaster saat ini lebih dekat ke kondisi yang diinginkan.
Pola controller
Sebuah controller melacak sekurang-kurangnya satu jenis sumber daya dari
Kubernetes.
objek-objek ini
memiliki spec field yang merepresentasikan keadaan yang diinginkan. Satu atau
lebih controller untuk resource tersebut bertanggung jawab untuk membuat
keadaan sekarang mendekati keadaan yang diinginkan.
Controller mungkin saja melakukan tindakan itu sendiri; namun secara umum, di
Kubernetes, controller akan mengirim pesan ke
API server yang
mempunyai efek samping yang bermanfaat. Kamu bisa melihat contoh-contoh
di bawah ini.
Kontrol melalui server API
ControllerJob adalah contoh dari controller
bawaan dari Kubernetes. Controller bawaan tersebut mengelola status melalui
interaksi dengan server API dari suatu klaster.
Job adalah sumber daya dalam Kubernetes yang menjalankan a
Pod, atau mungkin beberapa Pod sekaligus,
untuk melakukan sebuah pekerjaan dan kemudian berhenti.
(Setelah dijadwalkan, objek Pod
akan menjadi bagian dari keadaan yang diinginkan oleh kubelet).
Ketika controller job melihat tugas baru, maka controller itu memastikan bahwa,
di suatu tempat pada klaster kamu, kubelet dalam sekumpulan Node menjalankan
Pod-Pod dengan jumlah yang benar untuk menyelesaikan pekerjaan. Controller job
tidak menjalankan sejumlah Pod atau kontainer apa pun untuk dirinya sendiri.
Namun, controller job mengisyaratkan kepada server API untuk membuat atau
menghapus Pod. Komponen-komponen lain dalam
control plane
bekerja berdasarkan informasi baru (adakah Pod-Pod baru untuk menjadwalkan dan
menjalankan pekerjan), dan pada akhirnya pekerjaan itu selesai.
Setelah kamu membuat Job baru, status yang diharapkan adalah bagaimana
pekerjaan itu bisa selesai. Controller job membuat status pekerjaan saat ini
agar mendekati dengan keadaan yang kamu inginkan: membuat Pod yang melakukan
pekerjaan yang kamu inginkan untuk Job tersebut, sehingga Job hampir
terselesaikan.
Controller juga memperbarui objek yang mengkonfigurasinya. Misalnya: setelah
pekerjaan dilakukan untuk Job tersebut, controller job memperbarui objek Job
dengan menandainya Finished.
(Ini hampir sama dengan bagaimana beberapa termostat mematikan lampu untuk
mengindikasikan bahwa kamar kamu sekarang sudah berada pada suhu yang kamu
inginkan).
Kontrol Langsung
Berbeda dengan sebuah Job, beberapa dari controller perlu melakukan perubahan
sesuatu di luar dari klaster kamu.
Sebagai contoh, jika kamu menggunakan kontrol tertutup untuk memastikan apakah
cukup Node
dalam kluster kamu, maka controller memerlukan sesuatu di luar klaster saat ini
untuk mengatur Node-Node baru apabila dibutuhkan.
controller yang berinteraksi dengan keadaan eksternal dapat menemukan keadaan
yang diinginkannya melalui server API, dan kemudian berkomunikasi langsung
dengan sistem eksternal untuk membawa keadaan saat ini mendekat keadaan yang
diinginkan.
(Sebenarnya ada sebuah controller yang melakukan penskalaan node secara
horizontal dalam klaster kamu.
Status sekarang berbanding status yang diinginkan
Kubernetes mengambil pandangan sistem secara cloud-native, dan mampu menangani
perubahan yang konstan.
Klaster kamu dapat mengalami perubahan kapan saja pada saat pekerjaan sedang
berlangsung dan kontrol tertutup secara otomatis memperbaiki setiap kegagalan.
Hal ini berarti bahwa, secara potensi, klaster kamu tidak akan pernah mencapai
kondisi stabil.
Selama controller dari klaster kamu berjalan dan mampu membuat perubahan yang
bermanfaat, tidak masalah apabila keadaan keseluruhan stabil atau tidak.
Perancangan
Sebagai prinsip dasar perancangan, Kubernetes menggunakan banyak controller yang
masing-masing mengelola aspek tertentu dari keadaan klaster. Yang paling umum,
kontrol tertutup tertentu menggunakan salah satu jenis sumber daya
sebagai suatu keadaan yang diinginkan, dan memiliki jenis sumber daya yang
berbeda untuk dikelola dalam rangka membuat keadaan yang diinginkan terjadi.
Sangat penting untuk memiliki beberapa controller sederhana daripada hanya satu
controller saja, dimana satu kumpulan monolitik kontrol tertutup saling
berkaitan satu sama lain. Karena controller bisa saja gagal, sehingga Kubernetes
dirancang untuk memungkinkan hal tersebut.
Misalnya: controller pekerjaan melacak objek pekerjaan (untuk menemukan
adanya pekerjaan baru) dan objek Pod (untuk menjalankan pekerjaan tersebut dan
kemudian melihat lagi ketika pekerjaan itu sudah selesai). Dalam hal ini yang
lain membuat pekerjaan, sedangkan controller pekerjaan membuat Pod-Pod.
Catatan:
Ada kemungkinan beberapa controller membuat atau memperbarui jenis objek yang
sama. Namun di belakang layar, controller Kubernetes memastikan bahwa mereka
hanya memperhatikan sumbr daya yang terkait dengan sumber daya yang mereka
kendalikan.
Misalnya, kamu dapat memiliki Deployment dan Job; dimana keduanya akan membuat
Pod. Controller Job tidak akan menghapus Pod yang dibuat oleh Deployment kamu,
karena ada informasi (labels)
yang dapat oleh controller untuk membedakan Pod-Pod tersebut.
Berbagai cara menjalankan beberapa controller
Kubernetes hadir dengan seperangkat controller bawaan yang berjalan di dalam
kube-controller-manager. Beberapa controller
bawaan memberikan perilaku inti yang sangat penting.
Controller Deployment dan controller Job adalah contoh dari controller yang
hadir sebagai bagian dari Kubernetes itu sendiri (controller "bawaan").
Kubernetes memungkinkan kamu menjalankan control plane yang tangguh, sehingga
jika ada controller bawaan yang gagal, maka bagian lain dari control plane akan
mengambil alih pekerjaan.
Kamu juga dapat menemukan pengontrol yang berjalan di luar control plane, untuk
mengembangkan lebih jauh Kubernetes. Atau, jika mau, kamu bisa membuat
controller baru sendiri. Kamu dapat menjalankan controller kamu sendiri sebagai
satu kumpulan dari beberapa Pod, atau bisa juga sebagai bagian eksternal dari
Kubernetes. Manakah yang paling sesuai akan tergantung pada apa yang controller
khusus itu lakukan.
Apabila kamu ingin membuat controller sendiri, silakan lihat pola perluasan dalam memperluas Kubernetes.
2.4 - Konsep-konsep di balik Controller Manager
Konsep Cloud Controller Manager/CCM (jangan tertukar dengan program biner kube-controller-manager) awalnya dibuat untuk memungkinkan kode vendor cloud spesifik dan kode inti Kubernetes untuk berkembang secara independen satu sama lainnya. CCM berjalan bersama dengan komponen Master lainnya seperti Kubernetes Controller Manager, API Server, dan Scheduler. CCM juga dapat dijalankan sebagai Kubernetes Addon (tambahan fungsi terhadap Kubernetes), yang akan berjalan di atas klaster Kubernetes.
Desain CCM didasarkan pada mekanisme plugin yang memungkinkan penyedia layanan cloud untuk berintegrasi dengan Kubernetes dengan mudah dengan menggunakan plugin. Sudah ada rencana untuk pengenalan penyedia layanan cloud baru pada Kubernetes, dan memindahkan penyedia layanan cloud yang sudah ada dari model yang lama ke model CCM.
Dokumen ini mendiskusikan konsep di balik CCM dan mendetail fungsi-fungsinya.
Berikut adalah arsitektur sebuah klaster Kubernetes tanpa CCM:
Desain
Pada diagram sebelumnya, Kubernetes dan penyedia layanan cloud diintegrasikan melalui beberapa komponen berbeda:
Kubelet
Kubernetes Controller Manager
Kubernetes API server
CCM menggabungkan semua logika yang bergantung pada cloud dari dalam tiga komponen tersebut ke dalam sebuah titik integrasi dengan cloud. Arsitektur baru di dalam model CCM adalah sebagai berikut:
Komponen-komponen CCM
CCM memisahkan beberapa fungsi Kubernetes Controller Manager (KCM) dan menjalankannya sebagai proses yang berbeda. Secara spesifik, CCM memisahkan pengendali-pengendali (controller) di dalam KCM yang bergantung terhadap penyedia layanan cloud. KCM memiliki beberapa komponen pengendali yang bergantung pada cloud sebagai berikut:
Node Controller
Volume Controller
Route Controller
Service Controller
Pada versi 1.9, CCM menjalankan pengendali-pengendali dari daftar sebelumnya sebagai berikut:
Node Controller
Route Controller
Service Controller
Catatan: Volume Controller secara sengaja tidak dipilih sebagai bagian dari CCM. Hal ini adalah karena kerumitan untuk melakukannya, dan mempertimbangkan usaha-usaha yang sedang berlangsung untuk memisahkan logika volume yang spesifik vendor dari KCM, sehingga diputuskan bahwa Volume Contoller tidak akan dipisahkan dari KCM ke CCM.
Rencana awal untuk mendukung volume menggunakan CCM adalah dengan menggunakan FlexVolume untuk mendukung penambahan volume secara pluggable. Namun, ada sebuah usaha lain yang diberi nama Container Storage Interface (CSI) yang sedang berlangsung untuk menggantikan FlexVolume.
Mempertimbangkan dinamika tersebut, kami memutuskan untuk mengambil tindakan sementara hingga CSI siap digunakan.
Fungsi-fungsi CCM
Fungsi-fungsi CCM diwarisi oleh komponen-komponen Kubernetes yang bergantung pada penyedia layanan cloud. Bagian ini disusun berdasarkan komponen-komponen tersebut.
1. Kubernetes Controller Manager
Kebanyakan fungsi CCM diturunkan dari KCM. Seperti yang telah disebutkan pada bagian sebelumnya, CCM menjalankan komponen-komponen pengendali sebagai berikut:
Node Controller
Route Controller
Service Controller
Node Controller
Node Controller bertugas untuk menyiapkan sebuah node dengan cara mengambil informasi node-node yang berjalan di dalam klaster dari penyedia layanan cloud. Node Controller melakukan fungsi-fungsi berikut:
Menyiapkan sebuah node dengan memberi label zone/region yang spesifik pada cloud.
Menyiapkan sebuah node dengan informasi instance yang spesifik cloud , misalnya tipe dan ukurannya.
Mendapatkan alamat jaringan dan hostname milik node tersebut.
Dalam hal sebuah node menjadi tidak responsif, memeriksa cloud untuk melihat apakah node tersebut telah dihapus dari cloud. Juga, menghapus objek Node tersebut dari klaster Kubernetes, jika node tersebut telah dihapus dari cloud.
Route Controller
Route Controller bertugas mengkonfigurasi rute jaringan di dalam cloud secara sesuai agar Container pada node-node yang berbeda di dalam klaster Kubernetes dapat berkomunikasi satu sama lain. Route Controller hanya berlaku untuk klaster yang berjalan pada Google Compute Engine (GCE) di penyedia layanan cloud GCP.
Service Controller
Service Controller bertugas memantau terjadinya operasi create, update, dan delete pada Service. Berdasarkan keadaan terkini Service-service pada klaster Kubernetes, Service Controller mengkonfigurasi load balancer spesifik cloud (seperti ELB, Google LB, atau Oracle Cloud Infrastructure LB) agar sesuai dengan keadaan Service-service pada klaster Kubernetes. Sebagai tambahan, Service Controller juga memastikan bahwa service backend (target dari load balancer yang bersangkutan) dari load balancer cloud tersebut berada dalam kondisi terkini.
2. Kubelet
Node Controller berisi fungsi Kubelet yang bergantung pada cloud. Sebelum CCM, Kubelet bertugas untuk menyiapkan node dengan informasi spesifik cloud seperti alamat IP, label zone/region, dan tipe instance. Setelah diperkenalkannya CCM, tugas tersebut telah dipindahkan dari Kubelet ke dalam CCM.
Pada model baru ini, Kubelet menyiapkan sebuah node tanpa informasi spesifik cloud. Namun, Kubelet menambahkan sebuah Taint pada node yang baru dibuat yang menjadikan node tersebut tidak dapat dijadwalkan (sehingga tidak ada Pod yang dapat dijadwalkan ke node tersebut) hingga CCM menyiapkan node tersebut dengan informasi spesifik cloud. Setelah itu, Kubelet menghapus Taint tersebut.
Mekanisme Plugin
CCM menggunakan interface Go untuk memungkinkan implementasi dari cloud apapun untuk ditambahkan. Secara spesifik, CCM menggunakan CloudProvider Interface yang didefinisikan di sini
Implementasi dari empat kontroler-kontroler yang disorot di atas, dan beberapa kerangka kerja, bersama dengan CloudProvider Interface, akan tetap berada pada kode inti Kubernetes. Implementasi spesifik penyedia layanan cloud akan dibuat di luar kode inti dan menggunakan CloudProvider Interface yang didefinisikan di kode inti.
Bagian ini memerinci akses yang dibutuhkan oleh CCM terhadap berbagai objek API untuk melakukan tugas-tugasnya.
Akses untuk Node Controller
Node Controller hanya berinteraksi dengan objek-objek Node. Node Controller membutuhkan akses penuh untuk operasi get, list, create, update, patch, watch, dan delete terhadap objek-objek Node.
v1/Node:
Get
List
Create
Update
Patch
Watch
Delete
Akses untuk Route Controller
Route Controller memantau pembuatan objek Node dan mengkonfigurasi rute jaringan secara sesuai. Route Controller membutuhkan akses untuk operasi get terhadap objek-objek Node.
v1/Node:
Get
Akses untuk Service Controller
Service Controller memantau terjadinya operasi create, update dan delete, kemudian mengkonfigurasi Endpoint untuk Service-service tersebut secara sesuai.
Untuk mengakses Service-service, Service Controller membutuhkan akses untuk operasi list dan watch. Untuk memperbarui Service-service, dibutuhkan akses untuk operasi patch dan update.
Untuk menyiapkan Endpoint bagi untuk Service-service, dibutuhkan akses untuk operasi create, list, get, watch, dan update.
v1/Service:
List
Get
Watch
Patch
Update
Akses Lainnya
Implementasi dari inti CCM membutuhkan akses untuk membuat Event, dan untuk memastikan operasi yang aman, dibutuhkan akses untuk membuat ServiceAccount.
v1/Event:
Create
Patch
Update
v1/ServiceAccount:
Create
Detail RBAC dari ClusterRole untuk CCM adalah sebagai berikut:
Petunjuk lengkap untuk mengkonfigurasi dan menjalankan CCM disediakan di sini.
3 - Kontainer
3.1 - Ikhtisar Kontainer
Kontainer adalah teknologi untuk mengemas kode (yang telah dikompilasi) menjadi
suatu aplikasi beserta dengan dependensi-dependensi yang dibutuhkannya pada saat
dijalankan. Setiap kontainer yang Anda jalankan dapat diulang; standardisasi
dengan menyertakan dependensinya berarti Anda akan mendapatkan perilaku yang
sama di mana pun Anda menjalankannya.
Kontainer memisahkan aplikasi dari infrastruktur host yang ada dibawahnya. Hal
ini membuat penyebaran lebih mudah di lingkungan cloud atau OS yang berbeda.
Image-Image Kontainer
Kontainer image meruapakan paket perangkat lunak
yang siap dijalankan, mengandung semua yang diperlukan untuk menjalankan
sebuah aplikasi: kode dan setiap runtime yang dibutuhkan, library dari
aplikasi dan sistem, dan nilai default untuk penganturan yang penting.
Secara desain, kontainer tidak bisa berubah: Anda tidak dapat mengubah kode
dalam kontainer yang sedang berjalan. Jika Anda memiliki aplikasi yang
terkontainerisasi dan ingin melakukan perubahan, maka Anda perlu membuat
kontainer baru dengan menyertakan perubahannya, kemudian membuat ulang kontainer
dengan memulai dari image yang sudah diubah.
Kamu membuat Docker image dan mengunduhnya ke sebuah registri sebelum digunakan di dalam Kubernetes Pod.
Properti image dari sebuah Container mendukung sintaksis yang sama seperti perintah docker, termasuk registri privat dan tag.
Memperbarui Image
Kebijakan pull default adalah IfNotPresent yang membuat Kubelet tidak
lagi mengunduh (pull) sebuah image jika sudah ada terlebih dahulu. Jika kamu ingin agar
selalu diunduh, kamu bisa melakukan salah satu dari berikut:
mengatur imagePullPolicy dari Container menjadi Always.
buang imagePullPolicy dan gunakan :latesttag untuk image yang digunakan.
Harap diingat kamu sebaiknya hindari penggunaan tag:latest, lihat panduan konfigurasi untuk informasi lebih lanjut.
Membuat Image Multi-arsitektur dengan Manifest
Docker CLI saat ini mendukung perintah docker manifest dengan anak perintah create, annotate, dan push. Perintah-perintah ini dapat digunakan
untuk membuat (build) dan mengunggah (push) manifes. Kamu dapat menggunakan perintah docker manifest inspect untuk membaca manifes.
Perintah-perintah ini bergantung pada Docker CLI, dan diimplementasi hanya di sisi CLI. Kamu harus mengubah $HOME/.docker/config.json dan mengatur keyexperimental untuk mengaktifkan
atau cukup dengan mengatur DOCKER_CLI_EXPERIMENTAL variabel environment menjadi enabled ketika memanggil perintah-perintah CLI.
Catatan: Gunakan Docker 18.06 ke atas, versi-versi di bawahnya memiliki bug ataupun tidak mendukung perintah eksperimental. Contohnya https://github.com/docker/cli/issues/1135 yang menyebabkan masalah di bawah containerd.
Kalau kamu terkena masalah ketika mengunggah manifes-manifes yang rusak, cukup bersihkan manifes-manifes yang lama di $HOME/.docker/manifests untuk memulai dari awal.
Untuk Kubernetes, kami biasanya menggunakan image-image dengan sufiks -$(ARCH). Untuk kompatibilitas (backward compatibility), lakukan generate image-image yang lama dengan sufiks. Idenya adalah men-generate, misalnya pause image yang memiliki manifes untuk semua arsitektur dan misalnya pause-amd64 yang punya kompatibilitas terhadap konfigurasi-konfigurasi lama atau berkas-berkas YAML yang bisa saja punya image-image bersufiks yang di-hardcode.
Menggunakan Registri Privat (Private Registry)
Biasanya kita memerlukan key untuk membaca image-image yang tersedia pada suatu registri privat.
Kredensial ini dapat disediakan melalui beberapa cara:
Menggunakan Google Container Registry
per-klaster
konfigurasi secara otomatis pada Google Compute Engine atau Google Kubernetes Engine
semua Pod dapat membaca registri privat yang ada di dalam proyek
Menggunakan Amazon Elastic Container Registry (ECR)
menggunakan IAM role dan policy untuk mengontrol akses ke repositori ECR
secara otomatis refresh kredensial login ECR
Menggunakan Oracle Cloud Infrastructure Registry (OCIR)
menggunakan IAM role dan policy untuk mengontrol akses ke repositori OCIR
Menggunakan Azure Container Registry (ACR)
Menggunakan IBM Cloud Container Registry
menggunakan IAM role dan policy untuk memberikan akses ke IBM Cloud Container Registry
Konfigurasi Node untuk otentikasi registri privat
semua Pod dapat membaca registri privat manapun
memerlukan konfigurasi Node oleh admin klaster
Pra-unduh image
semua Pod dapat menggunakan image apapun yang di-cached di dalam sebuah Node
memerlukan akses root ke dalam semua Node untuk pengaturannya
Mengatur ImagePullSecrets dalam sebuah Pod
hanya Pod-Pod yang menyediakan key sendiri yang dapat mengakses registri privat
Masing-masing opsi dijelaskan lebih lanjut di bawah ini.
Menggunakan Google Container Registry
Kubernetes memiliki dukungan native untuk Google Container
Registry (GCR), ketika dijalankan pada
Google Compute Engine (GCE). Jika kamu menjalankan klaster pada GCE atau Google Kubernetes Engine,
cukup gunakan nama panjang image (misalnya gcr.io/my_project/image:tag).
Semua Pod di dalam klaster akan memiliki akses baca image di registri ini.
Kubelet akan melakukan otentikasi GCR menggunakan service account yang dimiliki
instance Google. Service acccount pada instance akan memiliki sebuah https://www.googleapis.com/auth/devstorage.read_only,
sehingga dapat mengunduh dari GCR di proyek yang sama, tapi tidak untuk unggah.
Cukup gunakan nama panjang image (misalnya ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag) di dalam definisi Pod.
Semua pengguna klaster yang dapat membuat Pod akan bisa menjalankan Pod yang dapat menggunakan
image-image di dalam registri ECR.
Kubelet akan mengambil dan secara periodik memperbarui kredensial ECR, yang memerlukan permission sebagai berikut:
ecr:GetAuthorizationToken
ecr:BatchCheckLayerAvailability
ecr:GetDownloadUrlForLayer
ecr:GetRepositoryPolicy
ecr:DescribeRepositories
ecr:ListImages
ecr:BatchGetImage
Persyaratan:
Kamu harus menggunakan versi kubelet v1.2.0 atau lebih (misal jalankan /usr/bin/kubelet --version=true).
Jika Node yang kamu miliki ada di region A dan registri kamu ada di region yang berbeda misalnya B, kamu perlu versi v1.3.0 atau lebih.
ECR harus tersedia di region kamu.
Cara troubleshoot:
Verifikasi semua persyaratan di atas.
Dapatkan kredensial $REGION (misalnya us-west-2) pada workstation kamu. Lakukan SSH ke dalam host dan jalankan Docker secara manual menggunakan kredensial tersebut. Apakah berhasil?
Tambahkan verbositas level log kubelet paling tidak 3 dan periksa log kubelet (misal journalctl -u kubelet) di baris-baris yang seperti ini:
aws_credentials.go:109] unable to get ECR credentials from cache, checking ECR API
aws_credentials.go:116] Got ECR credentials from ECR API for <AWS account ID for ECR>.dkr.ecr.<AWS region>.amazonaws.com
Menggunakan Azure Container Registry (ACR)
Ketika menggunakan Azure Container Registry
kamu dapat melakukan otentikasi menggunakan pengguna admin maupun sebuah service principal.
Untuk keduanya, otentikasi dilakukan melalui proses otentikasi Docker standar. Instruksi-instruksi ini
menggunakan perangkat azure-cli.
Kamu pertama perlu membuat sebuah registri dan men-generate kredensial, dokumentasi yang lengkap tentang hal ini
dapat dilihat pada dokumentasi Azure container registry.
Setelah kamu membuat registri, kamu akan menggunakan kredensial berikut untuk login:
DOCKER_USER : service principal, atau pengguna admin
DOCKER_PASSWORD: kata sandi dari service principal, atau kata sandi dari pengguna admin
IBM Cloud Container Registry menyediakan sebuah registri image privat yang multi-tenant, dapat kamu gunakan untuk menyimpan dan membagikan image-image secara aman. Secara default, image-image di dalam registri privat kamu akan dipindai (scan) oleh Vulnerability Advisor terintegrasi untuk deteksi isu
keamanan dan kerentanan (vulnerability) yang berpotensi. Para pengguna di dalam akun IBM Cloud kamu dapat mengakses image, atau kamu dapat menggunakan IAM
role dan policy untuk memberikan akses ke namespace di IBM Cloud Container Registry.
Konfigurasi Node untuk Otentikasi ke sebuah Registri Privat
Catatan: Jika kamu jalan di Google Kubernetes Engine, akan ada .dockercfg pada setiap Node dengan kredensial untuk Google Container Registry. Kamu tidak bisa menggunakan cara ini.
Catatan: Jika kamu jalan di AWS EC2 dan menggunakan EC2 Container Registry (ECR), kubelet pada setiap Node akan dapat
mengatur dan memperbarui kredensial login ECR. Kamu tidak bisa menggunakan cara ini.
Catatan: Cara ini cocok jika kamu dapat mengontrol konfigurasi Node. Cara ini tidak akan bekerja dengan baik pada GCE,
dan penyedia layanan cloud lainnya yang tidak melakukan penggantian Node secara otomatis.
Catatan: Kubernetes pada saat ini hanya mendukung bagian auths dan HttpHeaders dari konfigurasi docker. Hal ini berarti bantuan kredensial (credHelpers atau credsStore) tidak didukung.
Docker menyimpan key untuk registri privat pada $HOME/.dockercfg atau berkas $HOME/.docker/config.json. Jika kamu menempatkan berkas yang sama
pada daftar jalur pencarian (search path) berikut, kubelet menggunakannya sebagai penyedia kredensial saat mengunduh image.
{--root-dir:-/var/lib/kubelet}/config.json
{cwd of kubelet}/config.json
${HOME}/.docker/config.json
/.docker/config.json
{--root-dir:-/var/lib/kubelet}/.dockercfg
{cwd of kubelet}/.dockercfg
${HOME}/.dockercfg
/.dockercfg
Catatan: Kamu mungkin harus mengatur HOME=/root secara eksplisit pada berkas environment kamu untuk kubelet.
Berikut langkah-langkah yang direkomendasikan untuk mengkonfigurasi Node kamu supaya bisa menggunakan registri privat.
Pada contoh ini, coba jalankan pada desktop/laptop kamu:
Jalankan docker login [server] untuk setiap set kredensial yang ingin kamu gunakan. Ini akan memperbarui $HOME/.docker/config.json.
Lihat $HOME/.docker/config.json menggunakan editor untuk memastikan sudah berisi kredensial yang ingin kamu gunakan.
Dapatkan daftar Node, contohnya:
jika kamu ingin mendapatkan nama: nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')
jika kamu ingin mendapatkan IP: nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')
Salin .docker/config.json yang ada di lokal kamu pada salah satu jalur pencarian di atas.
contohnya: for n in $nodes; do scp ~/.docker/config.json root@$n:/var/lib/kubelet/config.json; done
Verifikasi dengana membuat sebuah Pod yanag menggunakan image privat, contohnya:
Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found
Kamu harus memastikan semua Node di dalam klaster memiliki .docker/config.json yang sama. Jika tidak, Pod-Pod
akan jalan pada beberapa Node saja dan gagal di Node lainnya. Contohnya, jika kamu menggunakan Node autoscaling, maka
setiap templat instance perlu untuk mempunyai .docker/config.json atau mount sebuah penyimpanan yang berisi berkas tersebut.
Semua Pod memiliki akses baca (read) untuk image-image di registri privat manapun ketika
key registri privat ditambahkan pada .docker/config.json.
Image Pra-unduh
Catatan: Jika kamu jalan di Google Kubernetes Engine, maka akan ada .dockercfg pada setiap Node dengan kredensial untuk Google Container Registry. Kamu dapat menggunakan cara ini.
Catatan: Cara ini cocok jika kamu dapat mengontrol konfigurasi Node. Cara ini tidak akan
bisa berjalan dengan baik pada GCE, dan penyedia cloud lainnya yang tidak menggantikan
Node secara otomatis.
Secara default, kubelet akan mencoba untuk mengunduh setiap image dari registri yang dispesifikasikan.
Hanya saja, jika properti imagePullPolicy diatur menjadi IfNotPresent atau Never, maka
sebuah image lokal digunakan.
Jika kamu ingin memanfaatkan image pra-unduh sebagai pengganti untuk otentikasi registri,
kamu harus memastikan semua Node di dalam klaster memiliki image pra-unduh yang sama.
Cara ini bisa digunakan untuk memuat image tertentu untuk kecepatan atau sebagai alternatif untuk otentikasi untuk sebuah registri privat.
Semua Pod akan mendapatkan akses baca ke image pra-unduh manapun.
Tentukan ImagePullSecrets pada sebuah Pod
Catatan: Cara ini merupakan cara yang direkomendasikan saat ini untuk Google Kubernetes Engine, GCE, dan penyedia cloud lainnya yang
secara otomatis dapat membuat Node.
Kubernetes mendukung penentuan key registri pada sebuah Pod.
Membuat sebuah Secret dengan Docker Config
Jalankan perintah berikut, ganti nilai huruf besar dengan yang tepat:
Jika kamu sudah memiliki berkas kredensial Docker, daripada menggunakan perintah di atas,
kamu dapat mengimpor berkas kredensial sebagai Kubernetes Secret.
Membuat sebuah Secret berbasiskan pada kredensial Docker yang sudah ada menjelaskan bagaimana mengatur ini.
Cara ini berguna khususnya jika kamu menggunakan beberapa registri kontainer privat,
perintah kubectl create secret docker-registry akan membuat sebuah Secret yang akan
hanya bekerja menggunakan satu registri privat.
Catatan: Pod-Pod hanya dapat mengacu pada imagePullSecrets di dalam namespace,
sehingga proses ini perlu untuk diselesaikan satu kali setiap namespace.
Mengacu pada imagePullSecrets di dalam sebuah Pod
Sekarang, kamu dapat membuat Pod yang mengacu pada Secret dengan menambahkan bagian imagePullSecrets
untuk sebuah definisi Pod.
Kamu dapat menggunakan cara ini bersama .docker/config.json pada setiap Node. Kredensial-kredensial
akan dapat di-merged. Cara ini akan dapat bekerja pada Google Kubernetes Engine.
Kasus-Kasus Penggunaan (Use Case)
Ada beberapa solusi untuk konfigurasi registri privat. Berikut beberapa kasus penggunaan
dan solusi yang disarankan.
Klaster yang hanya menjalankan image non-proprietary (misalnya open-source). Tidak perlu unutuk menyembunyikan image.
Gunakan image publik pada Docker hub.
Tidak ada konfigurasi yang diperlukan.
Pada GCE/Google Kubernetes Engine, sebuah mirror lokal digunakan secara otomatis untuk meningkatkan kecepatan dan ketersediaan.
Klaster yang menjalankan image proprietary yang seharusnya disembunyikan dari luar perusahaan, tetapi bisa terlihat oleh pengguna klaster.
Jalankan sebuah registri privat dimana otorisasi diperlukan.
Men-generate kredensial registri uuntuk setiap tenant, masukkan ke dalam secret uuntuk setiap namespace tenant.
Tenant menambahkan secret pada imagePullSecrets uuntuk setiap namespace.
Jika kamu memiliki akses pada beberapa registri, kamu dapat membuat satu secret untuk setiap registri.
Kubelet akan melakukan mergeimagePullSecrets manapun menjadi sebuah virtual .docker/config.json.
3.3 - Kontainer Environment
Laman ini menjelaskan berbagai resource yang tersedia di dalam Kontainer pada suatu environment.
Environment Kontainer
Environment Kontainer pada Kubernetes menyediakan beberapa resource penting yang tersedia di dalam Kontainer:
Sebuah Filesystem, yang merupakan kombinasi antara image dan satu atau banyak volumes.
Informasi tentang Kontainer tersebut.
Informasi tentang objek-objek lain di dalam klaster.
Informasi tentang Kontainer
Hostname sebuah Kontainer merupakan nama dari Pod dimana Kontainer dijalankan.
Informasi ini tersedia melalui perintah hostname atau panggilan (function call)
gethostname pada libc.
Nama Pod dan namespace tersedia sebagai variabel environment melalui API downward.
Variabel environment yang ditulis pengguna dalam Pod definition juga tersedia di dalam Kontainer,
seperti halnya variabel environment yang ditentukan secara statis di dalam image Docker.
Informasi tentang Klaster
Daftar semua Service yang dijalankan ketika suatu Kontainer dibuat, tersedia di dalam Kontainer tersebut sebagai variabel environment.
Variabel-variabel environment tersebut sesuai dengan sintaksis links dari Docker.
Untuk suatu Service bernama foo yang terkait dengan Kontainer bernama bar,
variabel-variabel di bawah ini tersedia:
FOO_SERVICE_HOST=<host dimana service dijalankan>
FOO_SERVICE_PORT=<port dimana service dijalankan>
Semua Service memiliki alamat-alamat IP yang bisa didapatkan di dalam Kontainer melalui DNS,
jika addon DNS diaktifkan.
Laman ini menjelaskan tentang resource RuntimeClass dan proses pemilihan runtime.
Peringatan: RuntimeClass memiliki breaking change untuk pembaruan ke beta pada v1.14. Jika kamu menggunakan
RuntimeClass sebelum v1.14, lihat Memperbarui RuntimeClass dari Alpha ke Beta.
Runtime Class
RuntimeClass merupakan sebuah fitur untuk memilih konfigurasi runtime kontainer. Konfigurasi
tersebut digunakan untuk menjalankan kontainer-kontainer milik suatu Pod.
Persiapan
Pastikan gerbang fitur (feature gate) RuntimeClass sudah aktif (secara default sudah aktif).
Lihat Gerbang Fitur untuk lebih
jelasnya soal pengaktifan gerbang fitur.
Gerbang fitur RuntimeClass ini harus aktif pada semua apiserver dan kubelet.
Lakukan konfigurasi pada implementasi CRI untuk setiap node (tergantung runtime yang dipilih)
Buat resource RuntimeClass yang terkait
1. Lakukan konfigurasi pada implementasi CRI untuk setiap node
Pilihan konfigurasi yang tersedia melalui RuntimeClass tergantung pada implementasi
Container Runtime Interface (CRI). Lihat bagian (di bawah ini)
soal bagaimana melakukan konfigurasi untuk implementasi CRI yang kamu miliki.
Catatan: Untuk saat ini, RuntimeClass berasumsi bahwa semua node di dalam klaster punya
konfigurasi yang sama (homogen). Jika ada node yang punya konfigurasi berbeda dari
yang lain (heterogen), maka perbedaan ini harus diatur secara independen di luar RuntimeClass
melalui fitur scheduling (lihat Menempatkan Pod pada Node).
Seluruh konfigurasi memiliki nama handler yang terkait, dijadikan referensi oleh RuntimeClass.
Nama handler harus berupa valid label 1123 DNS (alfanumerik + karakter -).
2. Buat resourceRuntimeClass yang terkait
Masing-masing konfigurasi pada langkah no.1 punya nama handler yang merepresentasikan
konfigurasi-konfigurasi tersebut. Untuk masing-masing handler, buatlah sebuah objek RuntimeClass terkait.
Resource RuntimeClass saat ini hanya memiliki 2 field yang penting: nama RuntimeClass tersebut
(metadata.name) dan handler (handler). Definisi objek tersebut terlihat seperti ini:
apiVersion:node.k8s.io/v1beta1 # RuntimeClass didefinisikan pada grup API node.k8s.iokind:RuntimeClassmetadata:name:myclass # Nama dari RuntimeClass yang nantinya akan dijadikan referensi# RuntimeClass merupakan resource tanpa namespacehandler:myconfiguration # Nama dari konfigurasi CRI terkait
Catatan: Sangat disarankan untuk hanya memperbolehkan admin klaster melakukan operasi
write pada RuntimeClass. Biasanya ini sudah jadi default. Lihat Ikhtisar
Autorisasi untuk penjelasan lebih jauh.
Penggunaan
Ketika RuntimeClass sudah dikonfigurasi pada klaster, penggunaannya sangatlah mudah.
Kamu bisa tentukan runtimeClassName di dalam spec sebuah Pod, sebagai contoh:
Kubelet akan mendapat instruksi untuk menggunakan RuntimeClass dengan nama yang sudah ditentukan tersebut
untuk menjalankan Pod ini. Jika RuntimeClass dengan nama tersebut tidak ditemukan, atau CRI tidak dapat
menjalankan handler yang terkait, maka Pod akan memasuki tahapFailed.
Lihat event untuk mengetahui pesan error yang terkait.
Jika tidak ada runtimeClassName yang ditentukan di dalam Pod, maka RuntimeHandler yang default akan digunakan.
Untuk kasus ini, perilaku klaster akan seperti saat fitur RuntimeClass dinonaktifkan.
Konfigurasi CRI
Lihat instalasi CRI untuk lebih detail mengenai pengaturan runtime CRI.
dockershim
Built-in dockershim CRI yang dimiliki Kubernetes tidak mendukung handler runtime.
Fitur Beta pada RuntimeClass memiliki perubahan sebagai berikut:
Grup API resourcenode.k8s.io dan runtimeclasses.node.k8s.io telah dimigrasi ke suatu
API built-in dari CustomResourceDefinition.
Atribut spec telah disederhakan pada definisi RuntimeClass (tidak ada lagi yang namanya
RuntimeClassSpec).
FieldruntimeHandler telah berubah nama menjadi handler.
Fieldhandler sekarang bersifat wajib untuk semua versi API. Artinya, fieldruntimeHandler
pada API Alpha juga bersifat wajib.
Fieldhandler haruslah berupa label DNS valid (RFC 1123),
yang artinya tidak bisa berisi karakter . (pada semua versi). Handler valid harus sesuai dengan
regular expression ini: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$.
Tindakan yang diperlukan: Tindakan-tindaka berikut ini diperlukan untuk melakukan
pembaruan fitur RuntimeClass dari versi alpha ke versi beta:
Resource RuntimeClass harus dibuat ulang setelah diperbarui ke v.1.14, dan
CRD runtimeclasses.node.k8s.io harus dihapus secara manual:
Fitur Alpha pada RuntimeClass akan menjadi tidak valid, jika runtimeHandler tidak ditentukan atau
kosong atau menggunakan karakter . pada handler. Ini harus dimigrasi ke handler dengan
konfigurasi yang valid (lihat petunjuk di atas).
3.5 - Lifecyle Hook pada Kontainer
Laman ini menjelaskan bagaimana semua Kontainer yang diatur kubelet menggunakan framework lifecycle hook
untuk menjalankan kode yang di-trigger oleh event selama lifecycle berlangsung.
Ikhtisar
Kubernetes menyediakan hook untuk lifecycle Kontainer. Hal ini sejalan dengan framework bahasa
pemrograman pada umumnya yang memiliki hook untuk lifecycle komponen, seperti Angular contohnya.
Hook tersebut digunakan Kontainer untuk selalu siap menerima event selama lifecycle dan
menjalankan kode yang diimplementasi pada suatu handler, ketika hook lifecycle terkait telah dieksekusi.
Jenis-jenis hook pada Kontainer
Ada dua jenis hook yang diekspos pada Kontainer:
PostStart
Hook ini dijalankan segera setelah suatu kontainer dibuat.
Hanya saja, tidak ada jaminan bahwa hook akan tereksekusi sebelum ENTRYPOINT dari kontainer.
Tidak ada parameter yang diberikan pada handler.
PreStop
Hook ini akan dipanggil sesaat sebelum kontainer dimatikan, karena suatu request API atau event pengaturan,
contohnya kegagalan pada liveness probe, preemption, perebutan resource, dan lainnya.
Sebuah panggilan untuk hookPreStop akan gagal jika kontainer tersebut telah ada pada state terminate atau complete.
Hal ini bersifat blocking, yang artinya panggilan bersifat sinkron (synchronous), harus menunggu eksekusi selesai, sebelum melakukan panggilan
untuk menghapus kontainer tersebut.
Tidak ada parameter yang diberikan pada handler.
Penjelasan yang lebih rinci tentang proses terminasi dapat dilihat pada Terminasi Pod.
Implementasi handler untuk hook
Kontainer dapat mengakses sebuah hook melalui implementasi dan registrasi sebuah handler untuk hook tersebut.
Ada dua jenis handler untuk hook yang dapat diimplementasikan untuk Kontainer:
Exec - Mengeksekusi sebuah perintah tertentu, contohnya pre-stop.sh, di dalam cgroups dan namespace suatu Kontainer. Resource yang dikonsumsi oleh perintah tersebut dianggap sebagai bagian dari Kontainer.
HTTP - Mengeksekusi sebuah request HTTP untuk endpoint tertentu pada Kontainer tersebut.
Eksekusi handler untuk hook
Ketika manajemen hook untuk suatu lifecycle Kontainer dipanggil, sistem manajemen internal pada Kubernetes
akan mengeksekusi handler di dalam Kontainer yang terdaftar untuk hook tersebut.
Panggilan handler untuk hook semuanya bersifat synchronous di dalam konteks Pod yang
memiliki Kontainer tersebut. Artinya, untuk hookPostStart, Kontainer ENTRYPOINT
dan hook dieksekusi secara asyncrhonous. Akan tetapi, jika hook mengambil waktu terlalu lama,
atau hang, Kontainer tersebut tidak bisa sampai ke staterunning.
Perilaku ini mirip dengan yang terjadi pada hookPreStop.
Jika hook terlalu lama atau hang saat dieksekusi, Pod tersebut tetap ada pada stateTerminating
dan akan dimatikan setelah terminationGracePeriodSeconds Pod selesai.
Jika sebuah hookPostStart atau PreStop gagal dieksekusi, Kontainer akan dimatikan.
Para pengguna sangat disarankan membuat handler untuk hook seringan mungkin (lightweight).
Biar bagaimanapun, ada beberapa kasus yang memang membutuhkan waktu lama untuk mengeksekusi
suatu perintah, misalnya saat proses penyimpanan state sebelum Kontainer dimatikan.
Jaminan pengiriman hook
Proses pengiriman hook akan dilakukan paling tidak satu kali.
Artinya suatu hook boleh dipanggil beberapa kali untuk event yang sama,
seperti dalam PostStart atauPreStop.
Namun begitu, implementasi hook masing-masing harus memastikan bagaimana
menangani kasus ini dengan benar.
Pada umumnya, hanya terjadi satu proses pengiriman.
Jika misalnya sebuah penerima HTTP hook mati atau tidak bisa menerima trafik,
maka tidak ada usaha untuk mengirimkan kembali.
Namun demikian, bisa saja terjadi dua kali proses pengiriman untuk kasus tertentu.
Contohnya, jika kubelet restart saat di tengah proses pengiriman hook,
hook tersebut akan dikirimkan kembali saat kubelet sudah hidup kembali.
Melakukan debughandler untuk hook
Log untuk suatu handler hook tidak terekspos pada event Pod.
Jika handler gagal dieksekusi untuk alasan tertentu, handler akan melakukan broadcast sebuah event.
Untuk PostStart, akan dilakukan broadcast eventFailedPostStartHook,
dan untuk PreStop, akan dilakukan broadcast eventFailedPreStopHook.
Kamu dapat melihat event-event ini dengan menjalankan perintah kubectl describe pod <pod_name>.
Berikut merupakan contoh keluaran event-event setelah perintah tersebut dijalankan.
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {default-scheduler } Normal Scheduled Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulling pulling image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Created Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined]
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulled Successfully pulled image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Started Started container with docker id 5c6a256a2567
38s 38s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1
37s 37s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1
38s 37s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1"
1m 22s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Warning FailedPostStartHook
Halaman ini menyajikan ikhtisar dari Pod, objek terkecil yang dapat di deploy di dalam objek model Kubernetes.
Memahami Pod
Sebuah Pod adalah unit dasar di Kubernetes--unit terkecil dan paling sederhana di dalam objek model Kubernetes yang dapat dibuat dan di deploy. Sebuah Pod merepresentasikan suatu proses yang berjalan di dalam klaster.
Pod membungkus sebuah kontainer (atau, di beberapa kasus, beberapa kontainer), sumber penyimpanan, alamat jaringan IP yang unik, dan opsi yang mengatur bagaimana kontainer harus dijalankan. Pod merupakan representasi dari unit deployment: sebuah instance aplikasi di dalam Kubernetes, yang mungkin terdiri dari satu kontainer atau sekumpulan kontainer yang berbagi resource.
Docker adalah salah satu kontainer runtime yang paling umum digunakan di Kubernetes Pod, tetapi Pod mendukung kontainer runtime lainnya.
Pod di Kubernetes klaster dapat digunakan dengan dua cara:
Pod menjalankan satu kontainer. Model satu kontainer per Pod adalah model yang umum digunakan di Kubernetes; kamu dapat membayangkan sebuah Pod sebagai pembungkus kontainer tersebut, dan Kubernetes tidak mengelola kontainer secara langsung tetapi mengelola Pod tersebut.
Pod menjalankan beberapa kontainer yang perlu berjalan bersamaan. Sebuah Pod dapat membungkus sebuah aplikasi yang terdiri dari beberapa kontainer yang perlu berbagi resource. Kontainer yang ditempatkan di dalam satu Pod ini membentuk sebuah layanan. Sebuah kontainer menyajikan berkas dari sumber penyimpanan ke publik, sedangkan kontainer sidecar yang lain melakukan pembaharuan terhadap berkas tersebut. Pod membungkus semua kontainer dan resource penyimpanan sebagai satu kesatuan yang dapat dikelola.
Kubernetes Blog menyediakan beberapa informasi tambahan terkait penggunaan Pod. Informasi selengkapnya, kunjungi:
Setiap Pod dimaksudkan untuk menjalankan satu instance aplikasi. Jika kamu ingin mengembangkan aplikasi secara horizontal (contoh, banyak instance sekaligus), kamu dapat menggunakan banyak Pod, satu untuk setiap instance. Di Kubernetes, konsep ini umumnya disebut dengan replikasi. Pod yang direplikasi biasanya dibuat dan dikelola sebagai grup oleh objek abstraksi yang disebut kontroler. Lihat Pod dan Kontroler untuk informasi selengkapnya.
Bagaimana Pod mengelola beberapa Kontainer
Pod didesain untuk mendukung banyak proses (sebagai kontainer) yang membentuk sebuah layanan. Kontainer di dalam sebuah Pod akan otomatis ditempatkan bersama di dalam satu mesin fisik atau mesin virtual di dalam klaster. Kontainer tersebut dapat berbagi resource dan dependensi, berkomunikasi satu sama lain, dan berkoordinasi kapan dan bagaimana mereka diterminasi.
Perhatikan bahwa mengelompokan kontainer di dalam satu Pod merupakan kasus lanjutan. Kamu dapat menggunakan pola ini hanya dalam kasus tertentu. Sebagai contoh, kamu memiliki kontainer yang bertindak sebagai web server yang menyajikan berkas dari resource penyimpanan bersama, dan kontainer sidecar melakukan pembaharuan terhadap berkas tersebut dari sumber lain, seperti dalam diagram Pod berikut:
Pod diagram
Pod menyediakan dua jenis resource sebagai penyusun dari kontainer: jaringan dan penyimpanan.
Jaringan
Setiap Pod diberikan sebuah alamat IP unik. Setiap kontainer di dalam Pod berbagi network namespace, termasuk alamat IP dan port jaringan. Setiap kontainer di dalam Pod dapat berkomunikasi satu sama lain menggunakan localhost. Saat para kontainer di dalam Pod berkomunikasi dengan entitas lain di luar Pod, mereka harus berkoordinasi satu sama lain bagaimana mereka menggunakan resource jaringan (seperti Port).
Penyimpanan
Pod dapat menentukan penyimpanan bersama yaitu volumes. Semua kontainer di dalam Pod dapat mengakses volumes ini, mengizinkan kontainer untuk berbagi data. Volumes juga memungkinkan data di Pod untuk bertahan jika salah satu kontainer perlu melakukan proses restart. Lihat Volumes untuk informasi lebih lanjut bagaimana Kubernetes mengimplementasikan penyimpanan di dalam Pod.
Bekerja dengan Pod
Kamu akan jarang membuat Pod secara langsung di Kubernetes. Ini karena Pod dirancang sebagai entitas sesaat. Saat Pod dibuat (baik oleh kamu, atau secara tidak langsung oleh kontroler), Pod ditempatkan dan dijalankan di sebuah Node di dalam klaster. Pod akan tetap di Node tersebut sampai proses dihentikan, Objek Pod dihapus, Pod dihentikan karena kekurangan resource, atau Node tersebut berhenti berjalan.
Catatan: Tidak perlu bingung untuk membedakan antara menjalankan ulang sebuah kontainer di dalam Pod dan menjalankan ulang Pod. Pod itu sendiri tidak berjalan, tetapi Pod adalah environment kontainer itu berjalan dan akan tetap ada sampai dihapus.
Pod tidak melakukan mekanisme penyembuhan diri sendiri. Jika Pod ditempatkan disebuah Node yang gagal, atau proses penempatan Pod itu sendiri gagal, Pod akan dihapus; demikian juga, Pod tidak akan bertahan jika Node tersebut kehabisan resource atau sedang dalam tahap pemeliharaan. Kubernetes menggunakan abstraksi yang disebut kontroler, yang menangani dan mengelola Pod. Jadi, meskipun Pod dapat dipakai secara langsung di Kubernetes, kontroler merupakan cara umum yang digunakan untuk mengelola Pod. Lihat Pod dan kontroler untuk informasi lebih lanjut bagaimana Kubernetes menggunakan kontroler untuk mengimpelentasikan mekanisme penyembuhan diri sendiri dan replikasi pada Pod.
Pod dan Kontroler
Kontroler dapat membuat dan mengelola banyak Pod untuk kamu, menangani replikasi dan menyediakan kemampuan penyembuhan diri sendiri pada lingkup klaster. Sebagai contoh, jika sebuah Node gagal, kontroler akan otomatis mengganti Pod tersebut dengan menempatkan Pod yang identik di Node yang lain.
Beberapa contoh kontroler yang berisi satu atau lebih Pod meliputi:
Secara umum, kontroler menggunakan templat Pod yang kamu sediakan untuk membuat Pod.
Templat Pod
Templat Pod adalah spesifikasi dari Pod yang termasuk di dalam objek lain seperti
Replication Controllers, Jobs, dan DaemonSets. Kontroler menggunakan templat Pod untuk membuat Pod.
Contoh di bawah merupakan manifestasi sederhana untuk Pod yang berisi kontainer yang membuat sebuah pesan.
Perubahan yang terjadi pada templat atau berganti ke templat yang baru tidak memiliki efek langsung pada Pod yang sudah dibuat. Pod yang dibuat oleh replication controller dapat diperbarui secara langsung.
Pod adalah unit komputasi terkecil yang bisa di-deploy dan dibuat serta dikelola dalam Kubernetes.
Apa Itu Pod?
Sebuah Pod (seperti pod pada paus atau kacang polong) adalah sebuah kelompok yang
terdiri dari satu atau lebih kontainer
(misalnya kontainer Docker), dengan ruang penyimpanan ataupun jaringan yang dipakai bersama,
dan sebuah spesifikasi mengenai bagaimana menjalankan kontainer. Isi dari Pod akan
selalu diletakkan dan dijadwalkan bersama, serta berjalan dalam konteks yang sama.
Sebuah Pod memodelkan "logical host" yang spesifik terhadap aplikasi. Ini mengandung
lebih dari satu kontainer aplikasi yang secara relatif saling terhubung erat. Sebelum
masa kontainer, menjalankan aplikasi dalam mesin fisik atau virtual berarti
menjalankan dalam logical host yang sama.
Walaupun Kubernetes mendukung lebih banyak runtime kontainer selain Docker,
namun Docker adalah yang paling umum diketahui dan ini membantu dalam menjelaskan
Pod dengan istilah pada Docker.
Konteks bersama dalam sebuah Pod adalah kumpulan Linux namespace, cgroup dan
kemungkinan segi isolasi lain, hal yang sama yang mengisolasi kontainer Docker.
Dalam sebuah konteks pada Pod, setiap aplikasi bisa menerapkan sub-isolasi lebih lanjut.
Semua kontainer dalam suatu Pod akan berbagi alamat IP dan port yang sama,
dan bisa saling berkomunikasi melalui localhost. Komunikasi tersebut mengunakan
standar inter-process communications (IPC) seperti SystemV semaphores
atau POSIX shared memory. Kontainer pada Pod yang berbeda memiliki alamat IP
yang berbeda dan tidak dapat berkomunikasi menggunakan IPC tanpa
pengaturan khusus. Kontainer ini
biasa berkomunikasi dengan yang lain menggunakan alamat IP setiap Pod.
Aplikasi dalam suatu Pod juga memiliki akses ke ruang penyimpanan bersama,
yang didefinisikan sebagai bagian dari Pod dan dibuat bisa diikatkan ke masing-masing
filesystem pada aplikasi.
Dalam istilah konsep Docker, sebuah Pod dimodelkan sebagai
gabungan dari kontainer Docker yang berbagi namespace dan ruang penyimpanan filesystem.
Layaknya aplikasi dengan kontainer, Pod dianggap sebagai entitas yang relatif tidak kekal
(tidak bertahan lama). Seperti yang didiskusikan dalam
siklus hidup Pod, Pod dibuat, diberikan
ID unik (UID), dan dijadwalkan pada suatu mesin dan akan tetap disana hingga dihentikan
(bergantung pada aturan restart) atau dihapus. Jika mesin
mati, maka semua Pod pada mesin tersebut akan dijadwalkan untuk dihapus, namun setelah
suatu batas waktu. Suatu Pod tertentu (sesuai dengan ID unik) tidak akan dijadwalkan ulang
ke mesin baru, namun akan digantikan oleh Pod yang identik, bahkan jika dibutuhkan bisa
dengan nama yang sama, tapi dengan ID unik yang baru
(baca replication controller
untuk info lebih lanjut)
Ketika sesuatu dikatakan memiliki umur yang sama dengan Pod, misalnya saja ruang penyimpanan,
maka itu berarti akan tetap ada selama Pod tersebut masih ada. Jika Pod dihapus dengan
alasan apapun, sekalipun Pod pengganti yang identik telah dibuat, semua yang berhubungan
(misalnya ruang penyimpanan) akan dihapus dan dibuat ulang.
Pod diagram
Sebuah Pod dengan banyak kontainer, yaitu File Puller dan Web Server yang menggunakan
ruang penyimpanan persisten untuk berbagi ruang penyimpanan bersama antara kontainer.
Motivasi suatu Pods
Pengelolaan
Pod adalah suatu model dari pola beberapa proses yang bekerja sama dan membentuk
suatu unit layanan yang kohesif. Menyederhanakan proses melakukan deploy dan
pengelolaan aplikasi dengan menyediakan abstraksi tingkat yang lebih tinggi
daripada konstituen aplikasinya. Pod melayani sebagai unit dari deployment,
penskalaan horizontal, dan replikasi. Colocation (co-scheduling), berbagi nasib
(misalnya dimatikan), replikasi terkoordinasi, berbagi sumber daya dan
pengelolaan ketergantungan akan ditangani otomatis untuk kontainer dalam suatu Pod.
Berbagi sumber daya dan komunikasi
Pod memungkinkan berbagi data dan komunikasi diantara konstituennya.
Semua aplikasi dalam suatu Pod menggunakan namespace jaringan yang sama
(alamat IP dan port yang sama), dan menjadikan bisa saling mencari dan berkomunikasi
dengan menggunakan localhost. Oleh karena itu, aplikasi dalam Pod harus
berkoordinasi mengenai penggunaan port. Setiap Pod memiliki alamat IP
dalam satu jaringan bersama yang bisa berkomunikasi dengan komputer lain
dan Pod lain dalam jaringan yang sama.
Kontainer dalam suatu Pod melihat hostname sistem sebagai sesuatu yang sama
dengan konfigurasi name pada Pod. Informasi lebih lanjut terdapat dibagian
jaringan.
Sebagai tambahan dalam mendefinisikan kontainer aplikasi yang berjalan dalam Pod,
Pod memberikan sepaket sistem penyimpanan bersama. Sistem penyimpanan memungkinkan
data untuk bertahan saat kontainer dijalankan ulang dan dibagikan kepada semua
aplikasi dalam Pod tersebut.
Penggunaan Pod
Pod dapat digunakan untuk menjalankan beberapa aplikasi yang terintegrasi
secara vertikal (misalnya LAMP), namun motivasi utamanya adalah untuk mendukung
berlokasi bersama, mengelola program pembantu, diantaranya adalah:
sistem pengelolaan konten, pemuat berkas dan data, manajer cache lokal, dll.
catatan dan checkpoint cadangan, kompresi, rotasi, dll.
pengamat perubahan data, pengintip catatan, adapter pencatatan dan pemantauan,
penerbit peristiwa, dll.
proksi, jembatan dan adaptor.
pengontrol, manajer, konfigurasi dan pembaharu.
Secara umum, masing-masing Pod tidak dimaksudkan untuk menjalankan beberapa
aplikasi yang sama.
Kenapa tidak menjalankan banyak program dalam satu kontainer (Docker)?
Transparansi. Membuat kontainer dalam suatu Pod menjadi terlihat dari infrastruktur,
memungkinkan infrastruktur menyediakan servis ke kontainer tersebut, misalnya saja
pengelolaan proses dan pemantauan sumber daya. Ini memfasilitasi sejumlah
kenyamanan untuk pengguna.
Pemisahan ketergantungan perangkat lunak. Setiap kontainer mungkin memiliki
versi, dibuat dan dijalankan ulang secara independen. Kubernetes mungkin mendukung
pembaharuan secara langsung terhadap suatu kontainer, suatu saat nanti.
Mudah digunakan. Penguna tidak diharuskan menjalankan manajer prosesnya sendiri,
khawatir dengan sinyal dan propagasi exit-code, dan lain sebagainya.
Efisiensi. Karena infrastruktur memegang lebih banyak tanggung jawab, kontainer
bisa lebih ringan.
Kenapa tidak mendukung penjadwalan kontainer berdasarkan affinity?
Cara itu bisa menyediakan lokasi yang sama, namun tidak memberikan banyak
keuntungan dari Pod, misalnya saja berbagi sumber daya, IPC, jaminan berbagi nasib
dan kemudahan manajemen.
Ketahanan suatu Pod (atau kekurangan)
Pod tidak dimaksudkan untuk diperlakukan sebagai entitas yang tahan lama.
Mereka tidak akan bertahan dengan kegagalan penjadwalan, kegagalan mesin,
atau eviction (pengusiran), misalnya karena kurangnya sumber daya atau dalam suatu
kasus mesin sedang dalam pemeliharaan.
Secara umum, pengguna tidak seharusnya butuh membuat Pod secara langsung. Mereka
seharusnya selalu menggunakan pengontrol, sekalipun untuk yang tunggal, misalnya,
Deployment. Pengontrol
menyediakan penyembuhan diri dengan ruang lingkup kelompok, begitu juga dengan
pengelolaan replikasi dan penluncuran.
Pengontrol seperti StatefulSet
bisa memberikan dukungan terhadap Pod yang stateful.
Penggunaan API kolektif sebagai user-facing primitive utama adalah hal yang
relatif umum diantara sistem penjadwalan kluster, seperti
Pod diekspose sebagai primitive untuk memfasilitasi hal berikut:
penjadwalan dan pengontrol sifat pluggability
mendukung operasi pada level Pod tanpa perlu melakukan proksi melalui API pengontrol
pemisahan antara umur suatu Pod dan pengontrol, seperti misalnya bootstrapping.
pemisahan antara pengontrol dan servis, pengontrol endpoint hanya memperhatikan Pod
komposisi yang bersih antara fungsionalitas dilevel Kubelet dan klaster. Kubelet
secara efektif adalah pengontrol Pod.
aplikasi dengan ketersediaan tinggi, yang akan mengharapkan Pod akan digantikan
sebelum dihentikan dan tentu saja sebelum dihapus, seperti dalam kasus penggusuran
yang direncanakan atau pengambilan gambar.
Penghentian Pod
Karena Pod merepresentasikan proses yang berjalan pada mesin didalam klaster, sangat
penting untuk memperbolehkan proses ini berhenti secara normal ketika sudah tidak
dibutuhkan (dibandingkan dengan dihentikan paksa dengan sinyal KILL dan tidak memiliki
waktu untuk dibersihkan). Pengguna seharusnya dapat meminta untuk menghapus dan tahu
proses penghentiannya, serta dapat memastikan penghentian berjalan sempurna. Ketika
pengguna meminta menghapus Pod, sistem akan mencatat masa tenggang untuk penghentian
secara normal sebelum Pod dipaksa untuk dihentikan, dan sinyal TERM akan dikirim ke
proses utama dalam setiap kontainer. Setelah masa tenggang terlewati, sinyal KILL
akan dikirim ke setiap proses dan Pod akan dihapus dari API server. Jika Kubelet
atau kontainer manajer dijalankan ulang ketika menunggu suatu proses dihentikan,
penghentian tersebut akan diulang dengan mengembalikan masa tenggang senilai semula.
Contohnya sebagai berikut:
Pengguna mengirim perintah untuk menghapus Pod, dengan masa tenggang (30 detik)
Pod dalam API server akan diperbarui dengan waktu dimana Pod dianggap "mati"
bersama dengan masa tenggang.
Pod ditampilkan dalam status "Terminating" ketika tercantum dalam perintah klien
(bersamaan dengan poin 3) Ketika Kubelet melihat Pod sudah ditandai sebagai
"Terminating" karena waktu pada poin 2 sudah diatur, ini memulai proses penghentian Pod
Jika salah satu kontainer pada Pod memiliki
preStop hook,
maka akan dipanggil di dalam kontainer. Jika preStophook masih berjalan
setelah masa tenggang habis, langkah 2 akan dipanggil dengan tambahan masa tenggang
yang sedikit, 2 detik.
Semua kontainer akan diberikan sinyal TERM. Sebagai catatan, tidak semua kontainer
akan menerima sinyal TERM dalam waktu yang sama dan mungkin butuh waktu untuk
menjalankan preStophook jika bergantung pada urutan penghentiannya.
(bersamaan dengan poin 3) Pod akan dihapus dari daftar endpoint untuk servis dan
tidak lagi dianggap sebagai bagian dari Pod yang berjalan dalam replication controllers.
Pod yang dihentikan, secara perlahan tidak akan melayani permintaan karena load balancer
(seperti servis proksi) menghapus mereka dari daftar rotasi.
Ketika masa tenggang sudah lewat, semua proses yang masih berjalan dalam Pod
akan dihentikan dengan sinyal SIGKILL.
Kubelet akan selesai menghapus Pod dalam API server dengan mengatur masa tenggang
menjadi 0 (langsung menghapus). Pod akan menghilang dari API dan tidak lagi terlihat
oleh klien.
Secara default, semua penghapusan akan berjalan normal selama 30 detik. Perintah
kubectl delete mendukung opsi --grace-period=<waktu dalam detik> yang akan
memperbolehkan pengguna untuk menimpa nilai awal dan memberikan nilai sesuai keinginan
pengguna. Nilai 0 akan membuat Pod
dihapus paksa.
Kamu harus memberikan opsi tambahan --force bersamaan dengan --grace-period=0
untuk melakukan penghapusan paksa.
Penghapusan paksa sebuah Pod
Penghapusan paksa dari sebuah Pod didefinisikan sebagai penghapusan Pod dari state
klaster dan etcd secara langsung. Ketika penghapusan paksa dilakukan, API server tidak
akan menunggu konfirmasi dari kubelet bahwa Pod sudah dihentikan pada mesin ia berjalan.
Ini menghapus Pod secara langsung dari API, sehingga Pod baru bisa dibuat dengan nama
yang sama. Dalam mesin, Pod yang dihentikan paksa akan tetap diberikan sedikit masa
tenggang sebelum dihentikan paksa.
Penghentian paksa dapat menyebabkan hal berbahaya pada beberapa Pod dan seharusnya
dilakukan dengan perhatian lebih. Dalam kasus StatefulSet Pods, silakan melihat
dokumentasi untuk penghentian Pod dari StatefulSet.
Hak istimewa untuk kontainer pada Pod
Setiap kontainer dalam Pod dapat mengaktifkan hak istimewa (mode privileged), dengan menggunakan tanda
privileged pada konteks keamanan
pada spesifikasi kontainer. Ini akan berguna untuk kontainer yang ingin menggunakan
kapabilitas Linux seperti memanipulasi jaringan dan mengakses perangkat. Proses dalam
kontainer mendapatkan hak istimewa yang hampir sama dengan proses di luar kontainer.
Dengan hak istimerwa, seharusnya lebih mudah untuk menulis pada jaringan dan plugin
ruang penyimpanan sebagai Pod berbeda yang tidak perlu dikompilasi ke dalam kubelet.
Catatan:Runtime kontainer kamu harus mendukung konsep hak istimewa kontainer untuk membuat
pengaturan ini menjadi relevan.
API Object
Pod adalah sumber daya tingkat tinggi dalam Kubernetes REST API.
Definisi Objek Pod API menjelaskan mengenai objek secara lengkap.
4.1.3 - Siklus Hidup Pod
Halaman ini menjelaskan siklus hidup sebuah Pod
Fase Pod
Fieldstatus dari sebuah Pod merupakan sebuah objek PodStatus, yang memiliki sebuah fieldphase.
Fase dari sebuah Pod adalah sesuatu yang sederhana, ringkasan yang lebih tinggi tentang Pod dalam siklus hidupnya. Fase ini tidak ditujukan sebagai sebuah kesimpulan yang luas dari observasi suatu kontainer atau state suatu Pod, serta tidak ditujukan sebagai state machine yang luas.
Jumlah dan arti dari nilai-nilai fase Pod dijaga ketat. Selain yang ada dalam dokumentasi ini, tidak perlu berasumsi mengenai Pod telah diberikan nilai phase.
Berikut adalah nilai yang mungkin diberikan untuk suatu phase:
Nilai
Deskripsi
Pending
Pod telah disetujui oleh sistem Kubernetes, tapi ada satu atau lebih image kontainer yang belum terbuat. Ini termasuk saat sebelum dijadwalkan dan juga saat mengunduh image melalui jaringan, yang mungkin butuh beberapa waktu.
Running
Pod telah terikat ke suatu node, dan semua kontainer telah terbuat. Setidaknya ada 1 kontainer yang masih berjalan, atau dalam proses memulai atau restart.
Succeeded
Semua kontainer di dalam Pod sudah berhasil dihentikan, dan tidak akan dilakukan restart.
Failed
Semua kontainer dalan suatu Pod telah dihentikan, dan setidaknya ada satu kontainer yang terhenti karena kegagalan. Itu merupakan kontainer yang keluar dengan kode status bukan 0 atau dihentikan oleh sistem.
Unknown
State suatu Pod tidak dapat diperoleh karena suatu alasan, biasanya karena kesalahan dalam komunikasi dengan host yang digunakan Pod tersebut.
Kondisi Pod
Suatu Pod memiliki sebuah PodStatus, yang merupakan array dari PodConditions yang telah atau belum dilewati oleh Pod. Setiap elemen dari array PodConditions mungkin memiliki enam field berikut:
FieldlastProbeTime memberikan nilai timestamp yang menandakan kapan terakhir kali kondisi kondisi Pod diperiksa.
FieldlastTransitionTime memberikan nilai timestamp yang menandakan kapan terakhir kali Pod berubah status ke status lain.
Fieldmessage adalah pesan yang bisa dibaca manusia yang mengidikasikan detail dari suatu transisi.
Fieldreason adalah suatu alasan yang unik, satu kata, ditulis secara CamelCase untuk kondisi transisi terakhir.
Fieldstatus adalah sebuah kata dengan kemungkinan nilainya berupa "True", "False", dan "Unknown".
Fieldtype adalah sebuah kata yang memiliki kemungkinan nilai sebagai berikut:
PodScheduled: Pod telah dijadwalkan masuk ke node;
Ready: Pod sudah mampu menerima request masuk dan seharusnya sudah ditambahkan ke daftar pembagian beban kerja untuk servis yang sama;
Unschedulable: scheduler belum dapat menjadwalkan Pod saat ini, sebagai contoh karena kekurangan resources atau ada batasan-batasan lain.
ContainersReady: Semua kontainer di dalam Pod telah siap.
Pemeriksaan Kontainer
Sebuah Probe adalah sebuah diagnosa yang dilakukan secara berkala oleh kubelet dalam suatu kontainer. Untuk melakukan diagnosa, kubelet memanggil sebuah Handler yang diimplementasikan oleh kontainer. Ada 3 tipe Handler yang tersedia, yaitu:
ExecAction: Mengeksekusi perintah tertentu di dalam kontainer. Diagnosa dikatakan berhasil jika perintah selesai dengan kode status 0.
TCPSocketAction: Melakukan pengecekan TCP terhadap alamat IP kontainer dengan port tertentu. Diagnosa dikatakan berhasil jika port tersebut terbuka.
HTTPGetAction: Melakukan sebuah request HTTP Get terhadap alamat IP kontainer dengan port dan path tertentu. Diagnosa dikatakan berhasil jika responnya memiliki kode status lebih besar atau sama dengan 200 dan kurang dari 400.
Setiap pemeriksaan akan menghasilkan salah satu dari tiga hasil berikut:
Success: Kontainer berhasil melakukan diagnosa.
Failure: Kontainer gagal melakukan diagnosa.
Unknown: Gagal melakukan diagnosa, sehingga tidak ada aksi yang harus dilakukan.
Kubelet dapat secara optimal melakukan dan bereaksi terhadap dua jenis pemeriksaan yang sedang berjalan pada kontainer, yaitu:
livenessProbe: Ini menunjukkan apakah kontainer sedang berjalan. Jika tidak berhasil melakukan pemeriksaan terhadap liveness dari kontainer, maka kubelet akan mematikan kontainer, dan kontainer akan mengikuti aturan dari restart policy. Jika kontainer tidak menyediakan pemeriksaan terhadap liveness, maka nilai dari state adalah Success.
readinessProbe: Ini menunjukan apakah kontainer sudah siap melayani request. Jika tidak berhasil melakukan pemeriksaan terhadap kesiapan dari kontainer, maka endpoints controller akan menghapus alamat IP Pod dari daftar semua endpoint untuk servis yang sama dengan Pod. Nilai awal state sebelum jeda awal adalah Failure. Jika kontainer tidak menyediakan pemeriksaan terhadap readiness, maka nilai awal state adalah Success.
Kapan sebaiknya menggunakan pemeriksaan terhadap liveness atau readiness?
Jika proses dalam kontainer mungkin gagal yang dikarenakan menghadapi suatu masalah
atau menjadi tidak sehat, maka pemeriksaan terhadap liveness tidak diperlukan.
Kubelet akan secara otomatis melakukan aksi yang tepat mengikuti restartPolicy dari Pod.
Jika kamu ingin kontainer bisa dimatikan dan dijalankan ulang ketika gagal melakukan
pemeriksaan, maka tentukan pemeriksaan liveness dan tentukan nilai restartPolicy sebagai Always atau OnFailure.
Jika kamu ingin mulai mengirim traffic ke Pod hanya ketika pemeriksaan berhasil,
maka tentukan pemeriksaan readiness. Dalam kasus ini, pemeriksaan readiness mungkin
akan sama dengan pemeriksaan liveness, tapi keberadaan pemeriksaan readiness dalam
spec berarti Pod akan tetap dijalankan tanpa menerima traffic apapun dan akan
mulai menerima traffic ketika pemeriksaan yang dilakukan mulai berhasil.
Jika kontainermu dibutuhkan untuk tetap berjalan ketika loading data yang besar,
file konfigurasi, atau melakukan migrasi ketika startup, maka tentukanlah pemeriksaan readiness.
Jika kamu ingin kontainermu dalam mematikan dirinya sendiri, kamu dapat menentukan
suatu pemeriksaan readiness yang melakukan pengecekan terhadap endpoint untuk readiness.
endpoint tersebut berbeda dengan endpoint untuk pengecekan liveness.
Perlu dicatat, jika kamu hanya ingin bisa menutup request ketika Pod sedang dihapus
maka kamu tidak perlu menggunakan pemeriksaan readiness. Dalam penghapusan, Pod akan
secara otomatis mengubah state dirinya menjadi unready tanpa peduli apakah terdapat
pemeriksaan readiness atau tidak. Pod tetap ada pada state unready selama menunggu
kontainer dalam Pod berhenti.
Untuk informasi lebih mendalam mengenai status Pod dan kontainer, silakan lihat
PodStatus
dan
ContainerStatus.
Mohon diperhatikan, informasi tentang status Pod bergantung pada
ContainerState.
State Kontainer
Ketika Pod sudah ditempatkan pada suatu node oleh scheduler, kubelet mulai membuat kontainer menggunakan runtime kontainer.
Ada tiga kemungkinan state untuk suatu kontainer, yaitu Waiting, Running, dan Terminated.
Untuk mengecek state suatu kontainer, kamu bisa menggunakan perintah kubectl describe pod [NAMA_POD].
State akan ditampilkan untuk masing-masing kontainer dalam Pod tersebut.
Waiting: Merupakan state default dari kontainer. Jika state kontainer bukan Running atau Terminated, berarti dalam Wating state.
Suatu kontainer dalam Waiting state akan tetap menjalan operasi-operasi yang dibutuhkan, misalnya mengunduh images, mengaplikasikan Secrets, dsb.
Bersamaan dengan state ini, sebuah pesan dan alasan tentang state akan ditampilkan untuk memberi informasi lebih.
...State:WaitingReason:ErrImagePull...
Running: Menandakan kontainer telah berjalan tanpa masalah. Setelah kontainer masuk ke state Running, jika terdapat hookpostStart maka akan dijalankan. State ini juga menampilkan waktu ketika kontainer masuk ke state Running.
...State:RunningStarted:Wed, 30 Jan 2019 16:46:38 +0530...
Terminated: Menandakan kontainer telah menyelesaikan "tugasnya". Kontainer akan menjadi state ini ketika telah menyelesaikan eksekusi atau terjadi kesalahan. Terlepas dari itu, sebuah alasan dan exit code akan ditampilkan, bersama dengan waktu kontainer mulai dijalankan dan waktu berhenti. Sebelum kontainer masuk ke state Terminated, jika terdapat preStophook maka akan dijalankan.
...State:TerminatedReason:CompletedExit Code:0Started:Wed, 30 Jan 2019 11:45:26 +0530Finished:Wed, 30 Jan 2019 11:45:26 +0530...
Pod readiness gate
FEATURE STATE:Kubernetes v1.14 [stable]
Dalam rangka menambahkan ekstensibilitas terhadap kesiapan Pod dengan menggunakan
injeksi umpan balik tambahan atau sinyal ke dalam PodStatus,
Kubernetes 1.11 memperkenalkan sebuah fitur bernama Pod ready++.
Kamu dapat menggunakan field baru ReadinessGate dalam sebuah PodSpec untuk
menunjukan kondisi tambahan yang akan dievaluasi untuk kesiapan Pod. Jika Kubernetes
tidak dapat menemukan kondisi pada fieldstatus.conditions dalam suatu Pod,
maka statusnya akan secara otomatis menjadi False. Berikut adalah contoh pemakaiannya:
Kind:Pod...spec:readinessGates:- conditionType:"www.example.com/feature-1"status:conditions:- type:Ready # ini adalah PodCondition yang telah tersediastatus:"False"lastProbeTime:nulllastTransitionTime:2018-01-01T00:00:00Z- type:"www.example.com/feature-1"# sebuah PodCondition tambahanstatus:"False"lastProbeTime:nulllastTransitionTime:2018-01-01T00:00:00ZcontainerStatuses:- containerID:docker://abcd...ready:true...
Kondisi Pod yang baru harus memenuhi format label pada Kubernetes.
Sejak perintah kubectl patch belum mendukung perubahan status objek, kondisi Pod yang baru harus mengubah melalui aksi PATCH dengan menggunakan
salah satu dari KubeClient libraries.
Dengan diperkenalkannya kondisi Pod yang baru, sebuah Pod akan dianggap siap hanya jika memenuhi dua syarat berikut:
Semua kontainer dalam Pod telah siap.
Semua kontainer yang diatur dalam ReadinessGates bernilai "True".
Untuk memfasilitasi perubahan tersebut terhadap evaluasi kesiapan Pod, dibuatkan sebuah kondisi Pod baru yaitu ContainerReady,
untuk dapat menangani kondisi Pod Ready yang sudah ada.
Dalam K8s 1.12, fitur tersebut sudah diaktifkan dari awal.
Aturan Menjalankan Ulang
Sebuah PodSpec memiliki fieldrestartPolicy dengan kemungkinan nilai berupa Always, OnFailure, dan Never.
Nilai awalnya berupa Always. restartPolicy akan berlaku untuk semua kontainer dalam Pod.
Kontainer yang mati dan dijalankan ulang oleh kubelet akan dijalankan ulang dengan jeda waktu yang ekponensial (10s, 20s, 40s, ...)
dengan batas atas senilai lima menit. Jeda waktu ini akan diatur ulang setelah sukses berjalan selama 10 menit.
Sesuai dengan diskusi pada dokumen Pod,
setelah masuk ke suatu node, sebuah Pod tidak akan pindah ke node lain.
Umur Pod
Secara umum, Pod tidak hilang sampai ada yang menghapusnya. Ini mungkin dihapus oleh orang atau pengontrol.
Satu pengecualian untuk aturan ini adalah Pod dengan phase bernilai Succeeded atau Failed untuk waktu
beberapa lama yang akan berakhir dan secara otomatis akan dihapus.
(diatur dalam terminated-pod-gc-threshold pada master)
Tiga tipe pengontrol yang tersedia yaitu:
Menggunakan sebuah Job untuk Pod yang diharapkan akan berakhir,
sebagai contoh, penghitungan dalam jumlah banyak. Jobs hanyak cocok untuk Pod dengan restartPolicy yang
bernilai OnFailure atau Never.
Menggunakan sebuah ReplicationController,
ReplicaSet, atau
Deployment untuk Pod yang tidak diharapkan untuk berakhir,
sebagai contoh, web servers. ReplicationControllers hanya cocok digunakan pada Pod dengan restartPolicy
yang bernilai Always.
Menggunakan sebuah DaemonSet untuk Pod yang akan berjalan
hanya satu untuk setiap mesin, karena menyediakan servis yang spesifik untuk suatu mesin.
Ketiga tipe pengontrol ini memiliki sebuah PodTemplate. Direkomdasikan untuk membuat
pengontrol yang sesuai dan membiarkan ini membuat Pod, daripada membuat Pod sendiri secara langsung.
Karena Pod itu sendiri tidak tahan terhadap gagalnya suatu mesin, namun pengontrol tahan.
Jika node mati atau sambungannya terputus dari klaster, Kubernetes mengatur
phase dari semua Pod pada node yang mati untuk menjadi Failed.
Contoh
Contoh Liveness Probe tingkat lanjut
Liveness probe dieksekusi oleh kubelet, jadi semua permintaan akan dilakukan
di dalam namespace jaringan kubelet.
apiVersion:v1kind:Podmetadata:labels:test:livenessname:liveness-httpspec:containers:- args:- /serverimage:k8s.gcr.io/livenesslivenessProbe:httpGet:# ketika "host" tidak ditentukan, "PodIP" akan digunakan# host: my-host# ketika "scheme" tidak ditentukan, _scheme_ "HTTP" akan digunakan. Hanya "HTTP" and "HTTPS" yang diperbolehkan# scheme: HTTPSpath:/healthzport:8080httpHeaders:- name:X-Custom-Headervalue:AwesomeinitialDelaySeconds:15timeoutSeconds:1name:liveness
Contoh State
Pod sedang berjalan dan memiliki sebuah kontainer. Kontainer berhenti dengan sukses.
Mencatat event penyelesaian.
Jika nilai restartPolicy adalah:
Always: Jalankan ulang kontainer; nilai phase Pod akan tetap Running.
OnFailure: nilai phase Pod akan berubah menjadi Succeeded.
Never: nilai phase Pod akan berubah menjadi Succeeded.
Pod sedang berjalan dan memiliki sebuah kontainer. Kontainer berhenti dengan kegagalan.
Mencatat event kegagalan.
Jika nilai restartPolicy adalah:
Always: Jalankan ulang kontainer, nilai phase Pod akan tetap Running.
OnFailure: Jalankan ulang kontainer, nilai phase Pod akan tetap Running.
Never: nilai phase Pod akan menjadi Failed.
Pod sedang berjalan dan memiliki dua kontainer. Kontainer pertama berhenti dengan kegagalan.
Mencatat event kegagalan.
Jika nilai restartPolicy adalah:
Always: Jalankan ulang kontainer, nilai phase Pod akan tetap Running.
OnFailure: Jalankan ulang kontainer, nilai phase Pod akan tetap Running.
Never: Tidak akan menjalankan ulang kontainer, nilai phase Pod akan tetap Running.
Jika kontainer pertama tidak berjalan dan kontainer kedua berhenti:
Mencatat event kegagalan.
Jika nilai restartPolicy adalah:
Always: Jalankan ulang kontainer, nilai phase Pod akan tetap Running.
OnFailure: Jalankan ulang kontainer, nilai phase Pod akan tetap Running.
Never: nilai phase Pod akan menjadi Failed.
Pod sedang berjalan dan memiliki satu kontainer. Kontainer berhenti karena kehabisan memory.
Kontainer diberhentikan dengan kegagalan.
Mencatat kejadian kehabisan memory (OOM)
Jika nilai restartPolicy adalah:
Always: Jalankan ulang kontainer, nilai phase Pod akan tetap Running.
OnFailure: Jalankan ulang kontainer, nilai phase Pod akan tetap Running.
Never: Mencatat kejadian kegagalan, nilai phase Pod akan menjadi Failed.
Pod sedang berjalan dan sebuah disk mati.
Menghentikan semua kontainer.
Mencatat kejadian yang sesuai.
Nilai phase Pod menjadi Failed.
Jika berjalan menggunakan pengontrol, maka Pod akan dibuat ulang di tempat lain.
Pod sedang berjalan, dan node mengalami segmented out.
Node pengontrol menunggu sampai suatu batas waktu.
Node pengontrol mengisi nilai phase Pod menjadi Failed.
Jika berjalan menggunakan pengontrol, maka Pod akan dibuat ulang di tempat lain.
Halaman ini menyediakan ikhtisar untuk Init Container, yaitu Container khusus yang dijalankan sebelum Container aplikasi dan berisi skrip peralatan atau setup yang tidak tersedia di dalam image dari Container aplikasi.
Fitur ini telah keluar dari trek Beta sejak versi 1.6. Init Container dapat dispesifikasikan di dalam PodSpec bersama dengan arraycontainers aplikasi. Nilai anotasi beta akan tetap diperhitungkan dan akan menimpa nilai pada PodSpec, tetapi telah ditandai sebagai kedaluarsa pada versi 1.6 dan 1.7. Pada versi 1.8, anotasi beta tidak didukung lagi dan harus diganti menjadi nilai pada PodSpec.
Memahami Init Container
Sebuah Pod dapat memiliki beberapa Container yang berjalan di dalamnya, dan dapat juga memiliki satu atau lebih Init Container, yang akan berjalan sebelum Container aplikasi dijalankan.
Init Container sama saja seperti Container biasa, kecuali:
Mereka selalu berjalan hingga selesai.
Setiap Init Container harus selesai secara sukses sebelum Init Container berikutnya dijalankan.
Jika sebuah Init Container tidak selesai secara sukses untuk sebuah Pod, Kubernetes akan mengulang kembali Pod tersebut secara terus menerus hingga Init Container selesai secara sukses. Tetapi, jika Pod tersebut memiliki nilai restartPolicy berupa Never, Pod tersebut tidak akan diulang kembali.
Untuk menspesifikasikan sebuah Container sebagai Init Container, tambahkan kolom initContainers pada PodSpec sebagai sebuah array JSON yang berisi objek dengan tipe Container, berdampingan dengan array containers aplikasi.
Status-status dari Init Container dikembalikan di kolom .status.initContainerStatuses sebagai sebuah array dari status-status Container (mirip seperti kolom status.containerStatuses)
Perbedaan dengan Container biasa
Init Container mendukung semua kolom dan fitur dari Container aplikasi, termasuk konfigurasi limit sumber daya, volume, dan keamanan. Tetapi, request dan limit sumber daya dari sebuah Init Container ditangani dengan cara yang sedikit berbeda, yang didokumentasikan di bagian Sumber Daya di bawah. Juga, Init Container tidak mendukung readiness probe karena mereka harus berjalan hingga selesai sebelum Pod dapat siap.
Jika beberapa Init Container dispesifikasikan untuk sebuah Pod, Container-container tersebut akan dijalankan satu per satu secara berurutan. Setiap Init Container harus selesai secara sukses sebelum yang berikutnya dapat berjalan.
Saat semua Init Container telah berjalan hingga selesai, Kubernetes akan menginisialisasi Pod dan menjalankan Container aplikasi seperti biasa.
Apa kegunaan Init Container?
Karena Init Container memiliki image yang berbeda dengan Container aplikasi, mereka memiliki beberapa kelebihan untuk kode yang berhubungan dengan dimulainya Init Container:
Mereka dapat berisi dan menjalankan skrip peralatan yang tidak diinginkan untuk berada di dalam image Container aplikasi karena alasan keamanan.
Mereka dapat berisi skrip peralatan atau setup yang tidak tersedia di dalam image aplikasi. Misalnya, kita tidak perlu membuat image dengan instruksi FROM dari image lainnya hanya untuk menggunakan peralatan seperti sed, awk, python, atau dig pada saat setup.
Peran builder atau deployer dari image dapat bekerja secara independen tanpa harus digabung untuk membuat satu image aplikasi.
Mereka menggunakan namespace Linux, sehingga mereka dapat memiliki sudut pandang filesystem yang berbeda dengan Container aplikasi. Oleh karenanya, mereka dapat diberikan akses terhadap Secret yang tidak boleh diakses oleh Container aplikasi.
Mereka berjalan hingga selesai sebelum Container aplikasi manapun dimulai, sedangkan Container aplikasi dijalankan secara paralel, sehingga Init Container menyediakan cara yang mudah untuk menunda dijalankannya Container aplikasi hingga ketentuan-ketentuan yang diinginkan dipenuhi.
Contoh-contoh
Berikut beberapa contoh kasus penggunaan Init Container:
Menunggu sebuah Service untuk dibuat dengan perintah shell seperti:
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
Mendaftarkan suatu Pod ke sebuah peladen terpisah dari downward API dengan perintah seperti:
`curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'`
Menunggu beberapa waktu sebelum menjalankan Container aplikasi dengan perintah seperti sleep 60.
Mengklon sebuah git repository ke dalam sebuah volume.
Menaruh nilai-nilai tertentu ke dalam sebuah file konfigurasi dan menjalankan peralatan template untuk membuat file konfigurasi secara dinamis untuk Container aplikasi utama. Misalnya, untuk menaruh nilai POD_IP ke dalam sebuah konfigurasi dan membuat konfigurasi aplikasi utama menggunakan Jinja.
File YAML untuk Kubernetes 1.5 berikut menguraikan sebuah Pod sederhana yang memiliki dua buah Init Container.
Pod pertama menunggu myservice dan yang kedua menunggu mydb. Saat kedua Init Container tersebut sudah selesai, Podnya akan dijalankan.
apiVersion:v1kind:Podmetadata:name:myapp-podlabels:app:myappannotations:pod.beta.kubernetes.io/init-containers:'[
{
"name": "init-myservice",
"image": "busybox:1.28",
"command": ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]},{"name": "init-mydb","image": "busybox:1.28","command": ['sh','-c',"until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]}]'
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
Ada sintaksis baru pada Kubernetes 1.6, walaupun sintaksis anotasi yang lama tetap akan bekerja untuk versi 1.6 dan 1.7. Sintaksis yang baru harus digunakan untuk versi 1.8 ke atas. Deklarasi Init Container dipindahkan ke dalam spec:
apiVersion:v1kind:Podmetadata:name:myapp-podlabels:app:myappspec:containers:- name:myapp-containerimage:busybox:1.28command:['sh','-c','echo The app is running! && sleep 3600']initContainers:- name:init-myserviceimage:busybox:1.28command:['sh','-c','until nslookup myservice; do echo waiting for myservice; sleep 2; done;']- name:init-mydbimage:busybox:1.28command:['sh','-c','until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
Sintaksis versi 1.5 tetap akan bekerja pada versi 1.6 dan 1.7, tetapi kami menyarankan untuk menggunakan sintaksis versi 1.6. Pada Kubernetes 1.6, Init Container dijadikan sebagai sebuah kolom di dalam API Kubernetes. Anotasi beta tetap akan diperhitungkan pada versi 1.6 dan 1.7, tetapi tidak didukung lagi pada versi 1.8 ke atas.
File YAML di bawah menguraikan Service mydb dan myservice.
Saat kita menjalankan Service mydb dan myservice, kita dapat melihat Init Container telah selesai dan myapp-pod pun dibuat:
kubectl apply -f services.yaml
service/myservice created
service/mydb created
kubectl get -f myapp.yaml
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
Contoh ini sangat sederhana, tetapi dapat memberikan sedikit petunjuk bagi kamu untuk membuat Init Container sendiri.
Perilaku mendetail
Saat dimulainya sebuah Pod, Init Container dijalankan secara berurutan, setelah jaringan dan volume telah diinisialisasi. Setiap Init Container harus selesai dan keluar secara berhasil sebelum yang berikutnya dijalankan. Jika ada Init Container yang gagal dijalankan atau keluar secara gagal, dia akan diulang kembali sesuai dengan restartPolicy yang dimiliki Pod. Tetapi, jika restartPolicy Pod disetel dengan nilai Always, Init Container akan menggunakan strategi RestartPolicyOnFailure.
Sebuah Pod tidak dapat masuk ke status Ready hingga semua Init Container berhasil selesai. Port di sebuah Init Container tidak diagregasikan di dalam sebuah Service. Sebuah Pod yang sedang diinisalisasikan akan masuk ke dalam status Pending, tetapi akan memiliki kondisi Initialized yang disetel menjadi true.
Jika sebuah Pod diulang kembali, semua Init Container harus dijalankan kembali.
Perubahan pada spesifikasi Init Container dibatasi hanya pada kolom image pada Init Container. Mengganti kolom image sebuah Init Container sama dengan mengulang kembali Pod tersebut.
Karena Init Container dapat diulang kembali, dicoba ulang, atau dijalankan ulang, Init Container sebaiknya bersifat idempotent. Khususnya, kode yang menulis ke dalam file pada EmptyDir sebaiknya dipersiapkan untuk menangani kemungkinan jika file keluaran yang diharapkan sudah ada di dalam EmptyDir tersebut.
Init Container memiliki semua kolom yang dimiliki oleh Container aplikasi. Tetapi, Kubernetes melarang penggunaan readinessProbe karena Init Container tidak dapat mendefinisikan/menggunakan readiness probe setelah selesai/keluar secara berhasil. Hal ini dipaksakan saat proses validasi.
Gunakan activeDeadlineSeconds pada Pod dan livenessProbe pada Container untuk mencegah Init Container gagal terus menerus. Nilai activeDeadlineSeconds berlaku juga terhadap Init Container.
Nama setiap Container aplikasi dan Init Container pada sebuah Pod haruslah unik; Kesalahan validasi akan terjadi jika ada Container atau Init Container yang memiliki nama yang sama.
Sumber Daya
Karena eksekusi Init Container yang berurutan, aturan-aturan untuk sumber daya berlaku sebagai berikut:
Yang tertinggi antara request atau limit sumber daya yang didefinisikan pada semua Init Container adalah request/limit inisialisasi yang berlaku.
request/limit sumber daya Pod yang berlaku adalah yang paling besar diantara:
Jumah request/limit semua Container aplikasi untuk suatu sumber daya.
request/limit inisialisasi yang berlaku untuk suatu sumber daya.
Penjadwalan dilakukan berdasarkan request/limit (Pod) yang berlaku, yang berarti bahwa Init Container dapat mengambil sumber daya inisialisasi yang tidak digunakan selama umur Pod tersebut.
Tingkat QoS yang berlaku milik Pod adalah sama dengan tingkat QoS untuk Init Container dan Container aplikasi.
ResourceQuota dan limitedResources diberlakukan berdasarkan request dan limit Pod yang berlaku.
Cgroup pada tingat Pod didasarkan pada request dan limit Pod yang berlaku, sama dengan scheduler.
Alasan Pod diulang kembali
Pod dapat diulang kembali, yang berakibat pada diulangnya eksekusi Init Container, diakibatkan oleh beberapa alasan berikut:
Seorang pengguna memperbarui PodSpec, mengakibatkan image Init Container berubah. Perubahan apapun pada image Init Container akan mengulang kembali Pod tersebut. Perubahan pada image Container aplikasi hanya mengulang kembali Container aplikasi yang bersangkutan.
Infrastruktur Container Pod diulang kembali. Hal ini jarang terjadi, dan hanya dapat dilakukan oleh seseorang yang memiliki akses root pada node yang bersangkutan.
Semua Container di dalam Pod diterminasi, dengan nilai restartPolicy yang disetel sebagai Always, memaksa pengulangan kembali, dan catatan selesainya Init Container telah hilang karena garbage collection.
Dukungan dan kompatibilitas
Sebuah klaster dengan versi Apiserver 1.6.0 ke atas mendukung Init Container melalui kolom .spec.initContainers. Versi-versi sebelumnya mendukung Init Container melalui anotasi alpha atau beta. Kolom .spec.initContainers juga diduplikasikan dalam bentuk anotasi alpha dan beta agar Kubelet versi 1.3.0 ke atas dapat menjalankan Init Container, dan agar Apiserver versi 1.6 dapat dengan aman dikembalikan ke versi 1.5.x tanpa kehilangan fungsionalitas Pod-pod yang telah dibuat sebelumnya.
Pada Apiserver dan Kubelet versi 1.8.0 ke atas, dukungan untuk anotasi alpha dan beta telah dihapus, sehingga dibutuhkan konversi (manual) dari anotasi yang telah kedaluwarsa tersebut ke dalam bentuk kolom .spec.initContainers.
Kamu dapat menggunakan batasan perseberan topologi (topology spread constraints)
untuk mengatur bagaimana Pod akan disebarkan
pada klaster yang ditetapkan sebagai failure-domains, seperti wilayah, zona, Node dan domain
topologi yang ditentukan oleh pengguna. Ini akan membantu untuk mencapai ketersediaan yang tinggi
dan juga penggunaan sumber daya yang efisien.
Batasan persebaran topologi bergantung dengan label pada Node untuk menentukan
domain topologi yang memenuhi untuk semua Node. Misalnya saja, sebuah Node bisa memiliki
label sebagai berikut: node=node1,zone=us-east-1a,region=us-east-1
Misalkan kamu memiliki klaster dengan 4 Node dengan label sebagai berikut:
NAME STATUS ROLES AGE VERSION LABELS
node1 Ready <none> 4m26s v1.16.0 node=node1,zone=zoneA
node2 Ready <none> 3m58s v1.16.0 node=node2,zone=zoneA
node3 Ready <none> 3m17s v1.16.0 node=node3,zone=zoneB
node4 Ready <none> 2m43s v1.16.0 node=node4,zone=zoneB
Maka klaster tersebut secara logika akan dilihat sebagai berikut:
Tanpa harus memberi label secara manual, kamu dapat menggunakan [label ternama]
(/docs/reference/kubernetes-api/labels-annotations-taints/) yang terbuat dan terkumpulkan
secara otomatis pada kebanyakan klaster.
Batasan Persebaran untuk Pod
API
Fieldpod.spec.topologySpreadConstraints diperkenalkan pada versi 1.16 sebagai berikut:
Kamu dapat mendefinisikan satu atau lebih topologySpreadConstraint untuk menginstruksikan
kube-scheduler mengenai cara peletakan tiap Pod baru dengan menggunakan kondisi Pod yang
sudah ada dalam klaster kamu. Field yang ada adalah:
maxSkew menentukan batasan yang menandakan Pod tidak tersebar secara merata.
Ini merupakan nilai maksimal dari selisih jumlah Pod yang sama untuk setiap 2 domain topologi
yang sama. Nilai ini harus lebih dari 0.
topologyKey adalah kunci dari label Node. Jika terdapat dua Node memiliki label dengan
kunci ini dan memiliki nilai yang identik untuk label tersebut, maka penjadwal akan menganggap
kedua Noode dalam topologi yang sama. Penjadwal akan mencoba untuk menyeimbangkan jumlah Pod
dalam setiap domain topologi.
whenUnsatisfiable mengindikasikan cara menangani Pod yang tidak memenuhi batasan persebaran:
DoNotSchedule (default) memberitahukan penjadwal untuk tidak menjadwalkan Pod tersebut.
ScheduleAnyway memberitahukan penjadwal untuk tetap menjadwalkan Pod namun tetap menjaga ketidakseimbangan Node sekecil mungkin.
labelSelector digunakan untuk mencari Pod yang sesuai. Pod dengan label yang sama dengan ini akan dihitung untuk menentukan jumlah Pod dalam domain topologi yang sesuai. Silakan baca Label dan Selector untuk lebih detailnya.
Kamu juga bisa membaca lebih detail mengenai field ini dengan menjalankan perintah
kubectl explain Pod.spec.topologySpreadConstraints.
Contoh: Satu TopologySpreadConstraint
Misalkan kamu memiliki klaster dengan 4 Node dimana 3 Pod berlabel foo:bar terdapat pada node1,
node2 dan node3 (P merepresentasikan Pod):
+---------------+---------------+
| zoneA | zoneB |
+-------+-------+-------+-------+
| node1 | node2 | node3 | node4 |
+-------+-------+-------+-------+
| P | P | P | |
+-------+-------+-------+-------+
Jika kita ingin Pod baru akan disebar secara merata berdasarkan Pod yang telah ada pada semua zona,
maka spec bernilai sebagai berikut:
topologyKey: zone berarti persebaran merata hanya akan digunakan pada Node dengan pasangan label
"zone: ". whenUnsatisfiable: DoNotSchedule memberitahukan penjadwal untuk membiarkan
tetap ditunda jika Pod yang baru tidak memenuhi batasan yang diterapkan.
Jika penjadwal menempatkan Pod baru pada "zoneA", persebaran Pod akan menjadi [3, 1], menjadikan
ketidakseimbangan menjadi bernilai 2 (3 - 1), yang mana akan melanggar batasan maxSkew: 1.
Dalam contoh ini, Pod baru hanya dapat ditempatkan pada "zoneB":
+---------------+---------------+ +---------------+---------------+
| zoneA | zoneB | | zoneA | zoneB |
+-------+-------+-------+-------+ +-------+-------+-------+-------+
| node1 | node2 | node3 | node4 | OR | node1 | node2 | node3 | node4 |
+-------+-------+-------+-------+ +-------+-------+-------+-------+
| P | P | P | P | | P | P | P P | |
+-------+-------+-------+-------+ +-------+-------+-------+-------+
Kamu dapat mengatur spesifikasi Pod untuk memenuhi beberapa persyaratan berikut:
Ubah nilai maxSkew menjadi lebih besar, misal "2", sehingga Pod baru dapat ditempatkan pada "zoneA".
Ubah nilai topologyKey menjadi "node" agar Pod disebarkan secara merata pada semua Node, bukan zona. Pada contoh di atas, jika maxSkew tetap bernilai "1", maka Pod baru hanya akan ditempatkan pada "node4".
Ubah nilai whenUnsatisfiable: DoNotSchedule menjadi whenUnsatisfiable: ScheduleAnyway untuk
menjamin agar semua Pod baru akan tetap dijadwalkan (misalkan saja API penjadwalan lain tetap
terpenuhi). Namun, ini lebih suka ditempatkan pada domain topologi yang memiliki lebih sedikit
Pod yang sesuai. (Harap diperhatikan bahwa preferensi ini digabungkan bersama dengan prioritas
penjadwalan internal yang lain, seperti rasio penggunaan sumber daya, dan lain sebagainya.)
Contoh: Beberapa TopologySpreadConstraint
Ini dibuat berdasarkan contoh sebelumnya. Misalkan kamu memiliki klaster dengan 4 Node dengan
3 Pod berlabel foo:bar yang ditempatkan pada node1, node2 dan node3. (P merepresentasikan Pod):
+---------------+---------------+
| zoneA | zoneB |
+-------+-------+-------+-------+
| node1 | node2 | node3 | node4 |
+-------+-------+-------+-------+
| P | P | P | |
+-------+-------+-------+-------+
Kamu dapat menggunakan 2 TopologySpreadConstraint untuk mengatur persebaran Pod pada zona dan Node:
Dalam contoh ini, untuk memenuhi batasan pertama, Pod yang baru hanya akan ditempatkan pada "zoneB",
sedangkan untuk batasan kedua, Pod yang baru hanya akan ditempatkan pada "node4". Maka hasil dari
2 batasan ini akan digunakan (AND), sehingga opsi untuk menempatkan Pod hanya pada "node4".
Beberapa batasan dapat berujung pada konflik. Misalnya saja kamu memiliki klaster dengan 3 Node
pada 2 zona berbeda:
+---------------+-------+
| zoneA | zoneB |
+-------+-------+-------+
| node1 | node2 | node3 |
+-------+-------+-------+
| P P | P | P P |
+-------+-------+-------+
Jika kamu menerapkan "two-constraints.yaml" pada klaster ini, kamu akan mendapatkan "mypod" tetap
dalam kondisi Pending. Ini dikarenakan oleh: untuk memenuhi batasan pertama, "mypod" hanya dapat
ditempatkan pada "zoneB", sedangkan untuk batasan kedua, "mypod" hanya dapat ditempatkan pada
"node2". Tidak ada hasil penggabungan dari "zoneB" dan "node2".
Untuk mengatasi situasi ini, kamu bisa menambahkan nilai maxSkew atau mengubah salah satu dari
batasan untuk menggunakan whenUnsatisfiable: ScheduleAnyway.
Konvensi
Ada beberapa konvensi implisit yang perlu diperhatikan di sini:
Hanya Pod dengan Namespace yang sama dengan Pod baru yang bisa menjadi kandidat yang cocok.
Node tanpa memiliki topologySpreadConstraints[*].topologyKey akan dilewatkan. Ini berarti:
Pod yang ditempatkan pada Node tersebut tidak berpengaruh pada perhitungan maxSkew. Dalam contoh di atas, misalkan "node1" tidak memiliki label "zone", maka kedua Pod tidak diperhitungkan dan menyebabkan Pod yang baru akan dijadwalkan masuk ke "zoneA".
Pod yang baru tidak memiliki kesempatan untuk dijadwalkan ke Node tersebut, pada contoh di atas, misalkan terdapat "node5" dengan label {zone-typo: zoneC} bergabung dalam klaster, Node ini akan dilewatkan karena tidak memiliki label dengan kunci "zone".
Harap diperhatikan mengenai hal yang terjadi jika nilai topologySpreadConstraints[*].labelSelector pada Pod yang baru tidak sesuai dengan labelnya.
Pada contoh di atas, jika kita menghapus label pada Pod yang baru, maka Pod akan tetap ditempatkan
pada "zoneB" karena batasan yang ada masih terpenuhi. Namun, setelah ditempatkan, nilai
ketidakseimbangan pada klaster masih tetap tidak berubah, zoneA tetap memiliki 2 Pod dengan label
{foo:bar} dan zoneB memiliki 1 Pod dengan label {foo:bar}. Jadi jika ini tidak yang kamu harapkan,
kami menyarankan nilai dari topologySpreadConstraints[*].labelSelector disamakan dengan labelnya.
Jika Pod yang baru memiliki spec.nodeSelector atau spec.affinity.nodeAffinity, Node yang tidak
sesuai dengan nilai tersebut akan dilewatkan.
Misalkan kamu memiliki klaster dengan 5 Node dari zoneA sampai zoneC:
dan kamu mengetahui bahwa "zoneC" harus tidak diperhitungkan. Dalam kasus ini, kamu dapat membuat
berkas yaml seperti di bawah, jadi "mypod" akan ditempatkan pada "zoneB", bukan "zoneC".
Demikian juga spec.nodeSelector akan digunakan.
Ini memungkinkan untuk mengatur batasan persebaran topologi bawaan untuk klaster.
Batasan persebaran topologi bawaan akan digunakan pada Pod jika dan hanya jika:
Hal ini tidak mendefinisikan batasan apapun pada .spec.topologySpreadConstraints.
Hal ini milik sebuah Service, ReplicationController, ReplicaSet atau StatefulSet.
Batasan bawaan akan diatur sebagai bagian dari argumen pada pluginPodTopologySpread
di dalam sebuah profil penjadwalan.
Batasan dispesifikasikan dengan API yang sama dengan di atas, kecuali bagian labelSelector
harus kosong. selector akan dihitung dari Service, ReplicationController, ReplicaSet atau
StatefulSet yang dimiliki oleh Pod tersebut.
Catatan: Nilai yang dihasilkan oleh batasan penjadwalan bawaan mungkin akan konflik dengan
nilai yang dihasilkan oleh
DefaultPodTopologySpread plugin.
Direkomendasikan untuk kamu menonaktifkan plugin ini dalam profil penjadwalan ketika
menggunakan batasan default untuk PodTopologySpread.
Perbandingan dengan PodAffinity/PodAntiAffinity
Di Kubernetes, arahan yang terkait dengan "Afinitas" mengontrol bagaimana Pod dijadwalkan -
lebih terkumpul atau lebih tersebar.
Untuk PodAffinity, kamu dapat mencoba mengumpulkan beberapa Pod ke dalam suatu
domain topologi yang memenuhi syarat.
Untuk PodAntiAffinity, hanya satu Pod yang dalam dijadwalkan pada sebuah domain topologi.
Fitur "EvenPodsSpread" memberikan opsi fleksibilas untuk mendistribusikan Pod secara merata
pada domain topologi yang berbeda, untuk meraih ketersediaan yang tinggi atau menghemat biaya.
Ini juga dapat membantu saat perbaruan bergilir dan menaikan jumlah replika dengan lancar.
Silakan baca motivasi untuk lebih detail.
Limitasi yang diketahui
Pada versi 1.18, dimana fitur ini masih Beta, beberapa limitasi yang sudah diketahui:
Pengurangan jumlah Deployment akan membuat ketidakseimbangan pada persebaran Pod.
Pod yang cocok pada tainted Node akan dihargai. Lihat Issue 80921
4.1.6 - Pod Preset
Halaman ini menyajikan gambaran umum tentang PodPreset, yang merupakan objek untuk memasukkan informasi tertentu ke dalam Pod pada saat waktu penciptaan. Informasi dapat berupa secret, volume, volume mount, dan variabel environment.
Memahami Pod Preset
Sebuah Pod Preset adalah sebuah resource API untuk memasukkan kebutuhan runtime tambahan ke dalam sebuah Pod pada saat waktu penciptaan. Kamu akan menggunakan label selector untuk menunjuk Pod dimana Pod Preset diterapkan.
Menggunakan sebuah Pod Preset memungkinkan pembuat templat pod untuk tidak menyediakan secara eksplisit semua informasi untuk setiap pod. Dengan demikian, pembuat templat pod yang mengkonsumsi sebuah service spesifik tidak perlu tahu semua detail-detail tentang service tersebut.
Kubernetes menyediakan sebuah admission controller (PodPreset) dimana, ketika diaktifkan, PodPreset diterapkan kepada permintaan penciptaan Pod yang akan datang. Ketika sebuah penciptaan Pod terjadi, sistem melakukan hal-hal berikut:
Mengambil semua PodPreset yang tersedia untuk digunakan.
Cek jika label selector dari salah satu PodPreset cocok dengan label pada pod yang sedang diciptakan.
Usaha untuk menggabungkan berbagai resource didefinisikan oleh PodPreset ke dalam Pod yang sedang diciptakan.
Ketika terjadi galat, lempar sebuah event yang mendokumentasikan galat penggabungan dalam pod, dan membuat pod tanpa salah satu resource dari PodPreset.
Anotasikan hasil spesifikasi Pod yang telah dimodifikasi untuk menunjukkan bahwa Pod telah dimodifikasi oleh sebuah PodPreset. Anotasi berupa podpreset.admission.kubernetes.io/podpreset-<nama pod-preset>: "<versi resource>".
Tiap Pod akan bisa dipasangkan oleh nol atau lebih PodPreset; dan tiap PodPreset bisa diterapkan ke nol atau lebih Pod. Ketika sebuah PodPreset diterapkan ke satu atau lebih Pod, Kubernetes memodifikasi Pod Spec. Untuk perubahan terhadap Env,EnvFrom, dan VolumeMount, Kubernetes memodifikasi spesifikasi kontainer untuk semua kontainer di dalam Pod; Untuk perubahan terhadap Volume, Kubernetes memodifikasi Pod Spec.
Catatan: Sebuah Pod Preset mampu memodifikasi kolom .spec.containers pada sebuah Pod Spec jika sesuai. Tidak ada definisi resource dari Pod Preset yang akan diterapkan kepada kolom initContainer.
Menonaktifkan Pod Preset untuk sebuah Pod Spesifik
Mungkin akan ada keadaan dimana kamu menginginkan sebuah Pod tidak bisa diubah oleh sebuah mutasi PodPreset. Pada kasus ini, kamu bisa menambahkan sebuah anotasi pada Pod Spec dalam bentuk: podpreset.admission.kubernetes.io/exclude: "true".
Mengaktifkan Pod Preset
Dalam rangka untuk menggunakan Pod Preset di dalam klaster kamu, kamu harus memastikan hal berikut:
Kamu telah mengaktifkan tipe API settings.k8s.io/v1alpha1/podpreset. Sebagai contoh, ini bisa dilakukan dengan menambahkan settings.k8s.io/v1alpha1=true di dalam opsi --runtime-config untuk API server. Dalam minikube tambahkan argumen berikut --extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=true saat menginisialisasi klaster.
Kamu telah mengaktifkan admission controller dari PodPreset. Salah satu cara untuk melakukannya adalah dengan menambahkan PodPreset di dalam nilai opsi --enable-admission-plugins yang dispesifikasikan untuk API server. Dalam minikube tambahkan argumen berikut
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
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 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:
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.
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.
Halaman ini memberikan gambaran umum tentang kontainer sementara: satu jenis
kontainer khusus yang berjalan sementara pada Pod
yang sudah ada untuk melakukan tindakan yang diinisiasi oleh pengguna seperti
dalam pemecahan masalah. Kamu menggunakan kontainer sementara untuk memeriksa
layanan bukan untuk membangun aplikasi.
Peringatan: Kontainer sementara masih berada dalam fase alpha dan tidak cocok untuk
klaster produksi. Kamu harus mengharapkan adanya suatu fitur yang tidak akan
berfungsi dalam beberapa situasi tertentu, seperti saat menargetkan namespace
dari suatu kontainer. Sesuai dengan Kubernetes
Deprecation Policy, fitur alpha
ini dapat berubah secara signifikan di masa depan atau akan dihapus seluruhnya.
Memahami Kontainer Sementara
Pod adalah blok pembangun
fundamental dalam aplikasi Kubernetes. Karena Pod diharapkan digunakan hanya
sekali dan dapat diganti, sehingga kamu tidak dapat menambahkan kontainer ke
dalam Pod setelah Pod tersebut dibuat. Sebaliknya, kamu biasanya menghapus dan
mengganti beberapa Pod dengan cara yang terkontrol melalui
Deployment.
Namun, kadang-kadang perlu juga untuk memeriksa keadaan Pod yang telah ada,
sebagai contoh untuk memecahkan masalah bug yang sulit direproduksi. Dalam
kasus ini, kamu dapat menjalankan sebuah kontainer sementara di dalam suatu Pod
yang sudah ada untuk memeriksa statusnya dan menjalankannya segala macam
perintah.
Apa itu Kontainer Sementara?
Kontainer sementara berbeda dengan kontainer lainnya karena tidak memiliki
jaminan sumber daya maupun akan eksekusi, dan mereka tidak akan pernah secara
otomatis melakukan restart, jadi mereka tidak sesuai untuk membangun aplikasi.
Kontainer sementara dideskripsikan dengan menggunakan ContainerSpec yang sama
dengan kontainer biasa, tetapi banyak bagian yang tidak kompatibel dan tidak
diperbolehkan untuk kontainer sementara.
Kontainer sementara mungkin tidak memiliki port, sehingga bagian seperti
port, livenessProbe, readinessProbe tidak diperbolehkan.
Alokasi sumber daya untuk Pod tidak dapat diubah, sehingga pengaturan
sumber daya tidak diperbolehkan.
Kontainer sementara dibuat dengan menggunakan handler khusus
EphemeralContainers dalam API tanpa menambahkannya langsung ke pod.spec,
sehingga tidak memungkinan untuk menambahkan kontainer sementara dengan
menggunakan kubectl edit.
Seperti dengan kontainer biasa, kamu tidak dapat mengubah atau menghapus
kontainer sementara setelah kamu memasukkannya ke dalam sebuah Pod.
Penggunaan Kontainer Sementara
Kontainer sementara berguna untuk pemecahan masalah secara interaktif pada saat
kubectl exec tidak mencukupi karena sebuah kontainer telah hancur atau
kontainer image tidak memiliki utilitas untuk debugging.
Khususnya, untuk images_distroless
memungkinkan kamu untuk menyebarkan kontainer image minimal yang mengurangi
surface attack dan paparan bug dan vulnerability. Karena
image distroless tidak mempunyai sebuah shell atau utilitas debugging apa
pun, sehingga sulit untuk memecahkan masalah image distroless dengan
menggunakan kubectl exec saja.
Saat menggunakan kontainer sementara, akan sangat membantu untuk mengaktifkan
process namespace sharing
sehingga kamu dapat melihat proses pada kontainer lain.
Contoh
Catatan: Contoh-contoh pada bagian ini membutuhkan EphemeralContainersfeature
gate untuk
diaktifkan, dan membutuhkan Kubernetes klien dan server versi v1.16 atau
yang lebih baru.
Contoh-contoh pada bagian ini menunjukkan bagaimana kontainer sementara muncul
dalam API. Kamu biasanya dapat menggunakan plugin kubectl untuk mengatasi
masalah untuk mengotomatiskan langkah-langkah ini.
Kontainer sementara dibuat menggunakan subresourceephemeralcontainers
Pod, yang dapat didemonstrasikan menggunakan kubectl --raw. Pertama-tama
deskripsikan kontainer sementara untuk ditambahkan dalam daftar
EphemeralContainers:
Kamu dapat mengakses kontainer sementara yang baru menggunakan
kubectl attach:
kubectl attach -it example-pod -c debugger
Jika proses berbagi namespace diaktifkan, kamu dapat melihat proses dari semua
kontainer dalam Pod tersebut. Misalnya, setelah mengakses, kamu jalankan
ps di kontainer debugger:
# Jalankan ini pada _shell_ dalam _debugger_ dari kontainer sementaraps auxww
Hasilnya akan seperti ini:
PID USER TIME COMMAND
1 root 0:00 /pause
6 root 0:00 nginx: master process nginx -g daemon off;
11 101 0:00 nginx: worker process
12 101 0:00 nginx: worker process
13 101 0:00 nginx: worker process
14 101 0:00 nginx: worker process
15 101 0:00 nginx: worker process
16 101 0:00 nginx: worker process
17 101 0:00 nginx: worker process
18 101 0:00 nginx: worker process
19 root 0:00 /pause
24 root 0:00 sh
29 root 0:00 ps auxww
4.2 - Controllers
4.2.1 - ReplicaSet
Tujuan dari ReplicaSet adalah untuk memelihara himpunan stabil dari replika Pod yang sedang berjalan pada satu waktu tertentu. Maka dari itu, ReplicaSet seringkali digunakan untuk menjamin ketersediaan dari beberapa Pod identik dalam jumlah tertentu.
Cara kerja ReplicaSet
Sebuah ReplicaSet didefinisikan dengan beberapa field termasuk selektor yang menentukan bagaimana mengidentifikasi Pod yang dapat diakuisisi, jumlah replika yang mengindikasi berapa jumlah Pod yang harus dikelola, dan sebuah templat pod yang menentukan data dari berbagai Pod baru yang harus dibuat untuk memenuhi kriteria jumlah replika. Sebuah ReplicaSet selanjutnya akan memenuhi tujuannya dengan membuat dan menghapus Pod sesuai dengan kebutuhan untuk mencapai jumlah yang diinginkan. Ketika ReplicaSet butuh untuk membuat Pod baru, templat Pod akan digunakan.
Tautan dari sebuah ReplicaSet terhadap Pod yang dimiliki adalah melalui fieldmetadata.ownerReferences pada Pod, yang menentukan sumber daya yang dimiliki oleh objek saat ini. Semua Pod yang diakuisisi oleh sebuah ReplicaSet masing-masing memiliki informasi yang mengidentifikasi ReplicaSet dalam field ownerReferences. Melalui tautan ini ReplicaSet dapat mengetahui keadaan dari Pod yang sedang dikelola dan melakukan perencanaan yang sesuai.
Sebuah ReplicaSet mengidentifikasi Pod baru untuk diakuisisi menggunakan selektornya. Jika terdapat sebuah Pod yang tidak memiliki OwnerReference atau OwnerReference yang dimiliki bukanlah sebuah Controller dan sesuai dengan selektor dari ReplicaSet, maka Pod akan langsung diakuisisi oleh ReplicaSet tersebut.
Kapan menggunakan ReplicaSet
Sebuah ReplicaSet memastikan replika-replika pod dalam jumlah yang ditentukan berjalan pada satu waktu tertentu. Namun demikian, sebuah Deployment adalah konsep dengan tingkatan yang lebih tinggi yang mengatur ReplicaSet dan mengubah Pod secara deklaratif serta berbagai fitur bermanfaat lainnya. Maka dari itu, kami merekomendasikan untuk menggunakan Deployment alih-alih menggunakan ReplicaSet secara langsung, kecuali jika kamu membutuhkan orkestrasi pembaruan yang khusus atau tidak membutuhkan pembaruan sama sekali.
Hal ini berarti kamu boleh jadi tidak akan membutuhkan manipulasi objek ReplicaSet: Gunakan Deployment dan definisikan aplikasi kamu pada bagian spec.
apiVersion:apps/v1kind:ReplicaSetmetadata:name:frontendlabels:app:guestbooktier:frontendspec:# modify replicas according to your casereplicas:3selector:matchLabels:tier:frontendtemplate:metadata:labels:tier:frontendspec:containers:- name:php-redisimage:gcr.io/google_samples/gb-frontend:v3
Menyimpan manifest ini dalam frontend.yaml dan mengirimkannya ke klaster Kubernetes akan membuat ReplicaSet yang telah didefinisikan beserta dengan Pod yang dikelola.
Selanjutnya kamu bisa mendapatkan ReplicaSet yang sedang di-deploy:
kubectl get rs
Dan melihat frontend yang telah dibuat:
NAME DESIRED CURRENT READY AGE
frontend 333 6s
Kamu juga dapat memeriksa kondisi dari ReplicaSet:
kubectl describe rs/frontend
Dan kamu akan melihat keluaran yang serupa dengan:
Name: frontend
Namespace: default
Selector: tier=frontend,tier in (frontend)Labels: app=guestbook
tier=frontend
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=guestbook
tier=frontend
Containers:
php-redis:
Image: gcr.io/google_samples/gb-frontend:v3
Port: 80/TCP
Requests:
cpu: 100m
memory: 100Mi
Environment:
GET_HOSTS_FROM: dns
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1{replicaset-controller } Normal SuccessfulCreate Created pod: frontend-qhloh
1m 1m 1{replicaset-controller } Normal SuccessfulCreate Created pod: frontend-dnjpy
1m 1m 1{replicaset-controller } Normal SuccessfulCreate Created pod: frontend-9si5l
Terakhir, kamu dapat memeriksa Pod yang dibawa:
kubectl get Pods
Kamu akan melihat informasi Pod yang serupa dengan:
NAME READY STATUS RESTARTS AGE
frontend-9si5l 1/1 Running 0 1m
frontend-dnjpy 1/1 Running 0 1m
frontend-qhloh 1/1 Running 0 1m
Kamu juga dapat memastikan bahwa referensi pemilik dari pod-pod ini telah disesuaikan terhadap ReplicaSet frontend.
Untuk melakukannya, yaml dari Pod yang sedang berjalan bisa didapatkan dengan:
kubectl get pods frontend-9si5l -o yaml
Keluarannya akan terlihat serupa dengan contoh berikut ini, dengan informasi ReplicaSet frontend yang ditentukan pada field ownerReferences pada bagian metadata:
Walaupun kamu bisa membuat Pod biasa tanpa masalah, sangat direkomendasikan untuk memastikan Pod tersebut tidak memiliki label yang sama dengan selektor dari salah satu ReplicaSet yang kamu miliki. Hal in disebabkan sebuah ReplicaSet tidak dibatasi untuk memilki Pod sesuai dengan templatnya -- ReplicaSet dapat mengakuisisi Pod lain dengan cara yang telah dijelaskan pada bagian sebelumnya.
Mengambil contoh ReplicaSet frontend sebelumnya, dan Pod yang ditentukan pada manifest berikut:
Karena Pod tersebut tidak memiliki Controller (atau objek lain) sebagai referensi pemilik yang sesuai dengan selektor dari ReplicaSet frontend, Pod tersebut akan langsung diakuisisi oleh ReplicaSet.
Misalkan kamu membuat Pod tersebut setelah ReplicaSet frontend telah di-deploy dan telah mengkonfigurasi replika Pod awal untuk memenuhi kebutuhan jumlah replika:
Kamu akan melihat bahwa ReplicaSet telah mengakuisisi Pod dan hanya membuat Pod yang baru sesuai dengan spec yang ditentukan hingga jumlah dari Pod yang baru dan yang orisinil sesuai dengan jumlah yang diinginkan. Dengan memperoleh Pod:
kubectl get Pods
Akan diperlihatkan pada keluarannya:
NAME READY STATUS RESTARTS AGE
frontend-pxj4r 1/1 Running 0 5s
pod1 1/1 Running 0 13s
pod2 1/1 Running 0 13s
Dengan cara ini, sebuah ReplicaSet dapat memiliki himpunan berbagai Pod yang tidak homogen.
Menulis manifest ReplicaSet
Seperti objek API Kubernetes lainnya, sebuah ReplicaSet membutuhkan fieldapiVersion, kind, dan metadata. Untuk ReplicaSet, nilai dari kind yang memungkinkan hanyalah ReplicaSet. Pada Kubernetes 1.9 versi API apps/v1 pada kind ReplicaSet adalah versi saat ini dan diaktifkan secara default. Versi API apps/v1beta2 telah dideprekasi. Lihat baris-baris awal pada contoh frontend.yaml untuk petunjuk.
.spec.template adalah sebuah templat pod yang juga dibutuhkan untuk mempunyai label. Pada contoh frontend.yaml kita memiliki satu label: tier: frontend.
Hati-hati agar tidak tumpang tindih dengan selektor dari controller lain, agar mereka tidak mencoba untuk mengadopsi Pod ini.
Untuk fieldrestart policy dari templat, .spec.template.spec.restartPolicy, nilai yang diperbolehkan hanyalah Always, yang merupakan nilai default.
Selektor Pod
Field.spec.selector adalah sebuah selektor labe. Seperti yang telah dibahas sebelumnya, field ini adalah label yang digunakan untuk mengidentifikasi Pod yang memungkinkan untuk diakuisisi. Pada contoh frontend.yaml, selektornya adalah:
matchLabels:
tier: frontend
Pada ReplicaSet, .spec.template.metadata.labels harus memiliki nilai yang sama dengan spec.selector, atau akan ditolak oleh API.
Catatan: Untuk 2 ReplicaSet dengan nilai .spec.selector yang sama tetapi memiliki nilai yang berbeda pada field.spec.template.metadata.labels dan .spec.template.spec, setiap ReplicaSet akan mengabaikan Pod yang dibuat oleh ReplicaSet lain.
Replika
Kamu dapat menentukan jumlah Pod yang seharusnya berjalan secara konkuren dengan mengatur nilai dari .spec.replicas. ReplicaSet akan membuat/menghapus Pod-nya hingga jumlahnya sesuai dengan field ini.
Jika nilai .spec.replicas tidak ditentukan maka akan diatur ke nilai default 1.
Menggunakan ReplicaSet
Menghapus ReplicaSet dan Pod-nya
Untuk menghapus sebuah ReplicaSet beserta dengan Pod-nya, gunakan kubectl delete. Garbage collector secara otomatis akan menghapus semua Pod dependen secara default.
Ketika menggunakan REST API atau libraryclient-go, kamu harus mengatur nilai propagationPolicy menjadi Background atau Foreground pada opsi -d.
Sebagai contoh:
Kamu dapat menghapus ReplicaSet tanpa memengaruhi Pod-nya menggunakan kubectl delete dengan menggunakan opsi --cascade=false.
Ketika menggunakan REST API atau libraryclient-go, kamu harus mengatur nilai propagationPolicy menjadi Orphan.
Sebagai contoh:
Ketika ReplicaSet yang asli telah dihapus, kamu dapat membuat ReplicaSet baru untuk menggantikannya. Selama field.spec.selector yang lama dan baru memilki nilai yang sama, maka ReplicaSet baru akan mengadopsi Pod lama namun tidak serta merta membuat Pod yang sudah ada sama dan sesuai dengan templat Pod yang baru.
Untuk memperbarui Pod dengan spec baru dapat menggunakan Deployment karena ReplicaSet tidak mendukung pembaruan secara langsung.
Mengisolasi Pod dari ReplicaSet
Kamu dapat menghapus Pod dari ReplicaSet dengan mengubah nilai labelnya. Cara ini dapat digunakan untuk menghapus Pod dari servis untuk keperluan debugging, data recovery, dan lainnya. Pod yang dihapus dengan cara ini akan digantikan seecara otomatis (dengan asumsi jumlah replika juga tidak berubah).
Mengatur jumlah Pod pada ReplicaSet
Jumlah Pod pada ReplicaSet dapat diatur dengan mengubah nilai dari field.spec.replicas. Pengatur ReplicaSet akan memastikan Pod dengan jumlah yang telah ditentukan dan dengan nilai selektor yang sama sedang dalam keadaan berjalan.
Pengaturan jumlah Pod pada ReplicaSet menggunakan Horizontal Pod Autoscaler
Pengaturan jumlah Pod pada ReplicaSet juga dapat dilakukan mengunakan Horizontal Pod Autoscalers (HPA). Berikut adalah contoh HPA terhadap ReplicaSet yang telah dibuat pada contoh sebelumnya.
Menyimpan manifest ini dalam hpa-rs.yaml dan mengirimkannya ke klaster Kubernetes akan membuat HPA tersebut yang akan mengatur jumlah Pod pada ReplicaSet yang telah didefinisikan bergantung terhadap penggunaan CPU dari Pod yang direplikasi.
Opsi lainnya adalah dengan menggunakan perintah kubectl autoscale untuk tujuan yang sama.
kubectl autoscale rs frontend --max=10
Alternatif selain ReplicaSet
Deployment (direkomendasikan)
Deployment adalah sebuah objek yang bisa memiliki ReplicaSet dan memperbarui ReplicaSet dan Pod-nya melalui rolling update deklaratif dan server-side.
Walaupun ReplicaSet dapat digunakan secara independen, seringkali ReplicaSet digunakan oleh Deployments sebagai mekanisme untuk mengorkestrasi pembuatan, penghapusan dan pembaruan Pod. Ketika kamu menggunakan Deployments kamu tidak perlu khawatir akan pengaturan dari ReplicaSet yang dibuat. Deployments memiliki dan mengatur ReplicaSet-nya sendiri.
Maka dari itu penggunaan Deployments direkomendasikan jika kamu menginginkan ReplicaSet.
Pod sederhana
Tidak seperti pada kasus ketika pengguna secara langsung membuat Pod, ReplicaSet akan menggantikan Pod yang dihapus atau diterminasi dengan alasan apapun, seperti pada kasus dimana terjadi kegagalan node atau pemeliharaan node yang disruptif, seperti pada kasus upgrade kernel. Karena alasan ini kami merekomendasikan kamu untuk menggunakan ReplicaSet walaupun jika aplikasimu membutuhkan hanya satu Pod. Hal ini mirip dengan pengawas proses, hanya saja pada kasus ini mengawasi banyak Pod pada berbagai node alih-alih berbagai proses individu pada sebuah node. ReplicaSet mendelegasikan proses pengulangan kembali dari kontainer lokal kepada agen yang terdapat di node (sebagai contoh, Kubelet atau Docker).
Job
Gunakan Job alih-alih ReplicaSet untuk Pod yang diharapkan untuk diterminasi secara sendirinya.
DaemonSet
Gunakan DaemonSet alih-alih ReplicaSet untuk Pod yang menyediakan fungsi pada level mesin, seperti monitoring mesin atau logging mesin. Pod ini memiliki waktu hidup yang bergantung terhadap waktu hidup mesin: Pod perlu untuk berjalan pada mesin sebelum Pod lain dijalankan, dan aman untuk diterminasi ketika mesin siap untuk di-reboot atau dimatikan.
ReplicationController
ReplicaSet adalah suksesor dari ReplicationControllers. Keduanya memenuhi tujuan yang sama dan memiliki perilaku yang serupa, kecuali bahwa ReplicationController tidak mendukung kebutuhan selektor set-based seperti yang dijelaskan pada panduan penggunaan label. Pada kasus tersebut, ReplicaSet lebih direkomendasikan dibandingkan ReplicationController.
4.2.2 - ReplicationController
Catatan:Deployment yang mengonfigurasi ReplicaSet sekarang menjadi cara yang direkomendasikan untuk melakukan replikasi.
Sebuah ReplicationController memastikan bahwa terdapat sejumlah Pod yang sedang berjalan dalam suatu waktu tertentu. Dengan kata lain, ReplicationController memastikan bahwa sebuah Pod atau sebuah kumpulan Pod yang homogen selalu berjalan dan tersedia.
Bagaimana ReplicationController Bekerja
Jika terdapat terlalu banyak Pod, maka ReplicationController akan membatasi dan mematikan Pod-Pod yang berlebih. Jika terdapat terlalu sedikit, maka ReplicationController akan memulai dan menjalankan Pod-Pod baru lainnya. Tidak seperti Pod yang dibuat secara manual, Pod-Pod yang diatur oleh sebuah ReplicationController akan secara otomatis diganti jika mereka gagal, dihapus, ataupun dimatikan.
Sebagai contoh, Pod-Pod yang kamu miliki akan dibuat ulang dalam sebuah Node setelah terjadi proses pemeliharaan seperti pembaruan kernel. Untuk alasan ini, maka kamu sebaiknya memiliki sebuah ReplicationController bahkan ketika aplikasimu hanya membutuhkan satu buah Pod saja. Sebuah ReplicationController memiliki kemiripan dengan sebuah pengawas proses, tetapi alih-alih mengawasi sebuah proses individu pada sebuah Node, ReplicationController banyak Pod yang terdapat pada beberapa Node.
ReplicationController seringkali disingkat sebagai "rc" dalam diskusi, dan sebagai shortcut dalam perintah kubectl.
Sebuah contoh sederhana adalah membuat sebuah objek ReplicationController untuk menjalankan sebuah instance Pod secara berkelanjutan. Contoh pemakaian lainnya adalah untuk menjalankan beberapa replika identik dari sebuah servis yang direplikasi, seperti peladen web.
Menjalankan Sebuah Contoh ReplicationController
Contoh ReplicationController ini mengonfigurasi tiga salinan dari peladen web nginx.
Periksa status dari ReplicationController menggunakan perintah ini:
kubectl describe replicationcontrollers/nginx
Name: nginx
Namespace: default
Selector: app=nginx
Labels: app=nginx
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 0 Running / 3 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- ---- ------ -------
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-qrm3m
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-3ntk0
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-4ok8v
Tiga Pod telah dibuat namun belum ada yang berjalan, kemungkinan karena image yang sedang di-pull.
Beberapa waktu kemudian, perintah yang sama akan menunjukkan:
Untuk melihat semua Pod yang dibuat oleh ReplicationController dalam bentuk yang lebih mudah dibaca mesin, kamu dapat menggunakan perintah seperti ini:
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})echo$pods
nginx-3ntk0 nginx-4ok8v nginx-qrm3m
Pada perintah di atas, selektor yang dimaksud adalah selektor yang sama dengan yang terdapat pada ReplicationController (yang dapat dilihat pada keluaran kubectl describe), dan dalam bentuk yang berbeda dengan yang terdapat pada replication.yaml. Opsi --output=jsonpath menentukan perintah untuh mendapatkan hanya nama dari setiap Pod yang ada pada daftar hasil.
Menulis Spesifikasi ReplicationController
Seperti semua konfigurasi Kubernetes lainnya, sebuah ReplicationController membutuhkan fieldapiVersion, kind, dan metadata.
Untuk informasi umum mengenai berkas konfigurasi, kamu dapat melihat pengaturan objek.
Sebuah ReplicationController juga membutuhkan bagian .spec.
Templat Pod
.spec.template adalah satu-satunya field yang diwajibkan pada .spec.
.spec.template adalah sebuah templat Pod. Ia memiliki skema yang sama persis dengan sebuah Pod, namun dapat berbentuk nested dan tidak memiliki fieldapiVersion ataupun kind.
Selain field-field yang diwajibkan untuk sebuah Pod, templat Pod pada ReplicationController harus menentukan label dan kebijakan pengulangan kembali yang tepat. Untuk label, pastikan untuk tidak tumpang tindih dengan kontroler lain. Lihat selektor pod.
Untuk pengulangan kembali dari sebuah kontainer lokal, ReplicationController mendelegasikannya ke agen pada Node, contohnya Kubelet atau Docker.
Label pada ReplicationController
ReplicationController itu sendiri dapat memiliki label (.metadata.labels). Biasanya, kamu akan mengaturnya untuk memiliki nilai yang sama dengan .spec.template.metadata.labels; jika .metadata.labels tidak ditentukan maka akan menggunakan nilai bawaan yaitu .spec.template.metadata.labels. Namun begitu, kedua label ini diperbolehkan untuk memiliki nilai yang berbeda, dan .metadata.labels tidak akan memengaruhi perilaku dari ReplicationController.
Selektor Pod
Field.spec.selector adalah sebuah selektor label. Sebuah ReplicationController mengatur semua Pod dengan label yang sesuai dengan nilai selektor tersebut. Ia tidak membedakan antara Pod yang ia buat atau hapus atau Pod yang dibuat atau dihapus oleh orang atau proses lain. Hal ini memungkinkan ReplicationController untuk digantikan tanpa memengaruhi Pod-Pod yang sedang berjalan.
Jika ditentukan, .spec.template.metadata.labels harus memiliki nilai yang sama dengan .spec.selector, atau akan ditolak oleh API. Jika .spec.selector tidak ditentukan, maka akan menggunakan nilai bawaan yaitu .spec.template.metadata.labels.
Selain itu, kamu juga sebaiknya tidak membuat Pod dengan label yang cocok dengan selektor ini, baik secara langsung, dengan menggunakan ReplicationController lain, ataupun menggunakan kontroler lain seperti Job. Jika kamu melakukannya, ReplicationController akan menganggap bahwa ia telah membuat Pod-Pod lainnya. Kubernetes tidak akan menghentikan kamu untuk melakukan aksi ini.
Jika kamu pada akhirnya memiliki beberapa kontroler dengan selektor-selektor yang tumpang tindih, kamu harus mengatur penghapusannya sendiri (lihat di bawah).
Beberapa Replika
Kamu dapat menentukan jumlah Pod yang seharusnya berjalan secara bersamaan dengan mengatur nilai .spec.replicas dengan jumlah Pod yang kamu inginkan untuk berjalan secara bersamaan. Jumlah yang berjalan dalam satu satuan waktu dapat lebih tinggi ataupun lebih rendah, seperti jika replika-replika tersebut melewati proses penambahan atau pengurangan, atau jika sebuah Pod melalui proses graceful shutdown, dan penggantinya telah dijalankan terlebih dahulu.
Jika kamu tidak menentukan nilai dari .spec.replicas, maka akan digunakan nilai bawaan 1.
Bekerja dengan ReplicationController
Menghapus Sebuah ReplicationController dan Pod-nya
Untuk menghapus sebuah ReplicationController dan Pod-Pod yang berhubungan dengannya, gunakan perintah kubectl delete. Kubectl akan mengatur ReplicationController ke nol dan menunggunya untuk menghapus setiap Pod sebelum menghapus ReplicationController itu sendiri. Jika perintah kubectl ini terhenti, maka dapat diulang kembali.
Ketika menggunakan REST API atau library klien go, maka kamu perlu melakukan langkah-langkahnya secara eksplisit (mengatur replika-replika ke 0, menunggu penghapusan Pod, dan barulah menghapus ReplicationController).
Menghapus Hanya ReplicationController
Kamu dapat menghapus ReplicationController tanpa memengaruhi Pod-Pod yang berhubungan dengannya.
Dengan menggunakan kubectl, tentukan opsi --cascade=false ke kubectl delete.
Ketika menggunakan REST API atau library klien go, cukup hapus objek ReplicationController.
Ketika ReplicationController yang asli telah dihapus, kamu dapat membuat ReplicationController yang baru sebagai penggantinya. Selama .spec.selector yang lama dan baru memiliki nilai yang sama, maka ReplicationController baru akan mengadopsi Pod-Pod yang lama.
Walaupun begitu, ia tidak akan melakukan usaha apapun untuk membuat Pod-Pod yang telah ada sebelumnya untuk sesuai dengan templat Pod yang baru dan berbeda.
Untuk memperbarui Pod-Pod ke spesifikasi yang baru dengan cara yang terkontrol, gunakan pembaruan bergulir.
Mengisolasi Pod dari ReplicationController
Pod-Pod dapat dihapus dari kumpulan target sebuah ReplicationController dengan mengganti nilai dari labelnya. Teknik ini dapat digunakan untuk mencopot Pod-Pod dari servis untuk keperluan pengawakutuan (debugging), pemulihan data, dan lainnya. Pod-Pod yang dicopot dengan cara ini dapat digantikan secara otomatis (dengan asumsi bahwa jumlah replika juga tidak berubah).
Pola penggunaan umum
Penjadwalan ulang
Seperti yang telah disebutkan sebelumnya, baik kamu memiliki hanya 1 Pod untuk tetap dijalankan, ataupun 1000, ReplicationController akan memastikan tersedianya jumlah Pod yang telat ditentukan, bahkan ketika terjadi kegagalan Node atau terminasi Pod (sebagai contoh karena adanya tindakan dari agen kontrol lain).
Penskalaan
ReplicationController memudahkan penskalaan jumlah replika, baik meningkatkan ataupun mengurangi, secara manual ataupun dengan agen kontrol penskalaan otomatis, dengan hanya mengubah nilai dari fieldreplicas.
Pembaruan bergulir
ReplicationController didesain untuk memfasilitasi pembaruan bergulir untuk sebuah servis dengan mengganti Pod-Pod satu per satu.
Seperti yang telah dijelaskan di #1353, pendekatan yang direkomendasikan adalah dengan membuat ReplicationController baru dengan 1 replika, skala kontroler yang baru (+1) atau yang lama (-1) satu per satu, dan kemudian hapus kontroler lama setelah menyentuh angka 0 replika. Hal ini memungkinkan pembaruan dilakukan dengan dapat diprediksi terlepas dari adanya kegagalan yang tak terduga.
Idealnya, kontroler pembaruan bergulir akan memperhitungkan kesiapan dari aplikasi, dan memastikan cukupnya jumlah Pod yang secara produktif meladen kapanpun.
Dua ReplicationController diharuskan untuk memiliki setidaknya satu label yang berbeda, seperti tagimage dari kontainer utama dari Pod, karena pembaruan bergulir biasanya dilakukan karena adanya pembaruan image.
Selain menjalankan beberapa rilis dari sebuah aplikasi ketika proses pembaruan bergulir sedang berjalan, adalah hal yang awam untuk menjalankan beberapa rilis untuk suatu periode waktu tertentu, atau bahkan secara kontinu, menggunakan operasi rilis majemuk. Operasi-operasi ini akan dibedakan menggunakan label.
Sebagai contoh, sebuah servis dapat menyasar semua Pod dengan tier in (frontend), environment in (prod). Anggap kamu memiliki 10 Pod tiruan yang membangun tier ini tetapi kamu ingin bisa menggunakan 'canary' terhadap versi baru dari komponen ini. Kamu dapat mengatur sebuah ReplicationController dengan nilai replicas 9 untuk replika-replikanya, dengan label tier=frontend, environment=prod, track=stable, dan ReplicationController lainnya dengan nilai replicas 1 untuk canary, dengan label tier=frontend, environment=prod, track=canary. Sekarang servis sudah mencakup baik canary maupun Pod-Pod yang bukan canary. Kamu juga dapat mencoba-coba ReplicationController secara terpisah untuk melakukan pengujian, mengamati hasilnya, dan lainnya.
Menggunakan ReplicationController dengan Service
Beberapa ReplicationController dapat berada di belakang sebuah Service, sedemikian sehingga, sebagai contoh, sebagian traffic dapat ditujukan ke versi lama, dan sebagian lainnya ke versi yang baru.
Sebuah ReplicationController tidak akan berhenti dengan sendirinya, namun ia tidak diekspektasikan untuk berjalan selama Service-Service yang ada. Service dapat terdiri dari berbagai Pod yang dikontrol beberapa ReplicationController, dan terdapat kemungkinan bahwa beberapa ReplicationController untuk dibuat dan dimatikan dalam jangka waktu hidup Service (contohnya adalah untuk melakukan pembaruan Pod-Pod yang menjalankan Service). Baik Service itu sendiri dan kliennya harus tetap dalam keadaan tidak mempunyai pengetahuan terhadap ReplicationController yang memelihara Pod-Pod dari Service tersebut.
Menulis program untuk Replikasi
Pod-Pod yang dibuat oleh ReplicationController ditujukan untuk dapat sepadan dan memiliki semantik yang identik, walaupun konfigurasi mereka dapat berbeda seiring keberjalanan waktunya. Ini adalah contoh yang cocok untuk peladen stateless, namun ReplicationController juga dapat digunakan untuk memelihara ketersediaan dari aplikasi-aplikasi yang master-elected, sharded, worker-pool. Aplikasi-aplikasi seperti itu sebaiknya menggunakan mekanisme penetapan kerja yang dinamis, seperti antrian kerja RabbitMQ, berlainan dengan pengubahan statis/satu kali dari konfigurasi setiap Pod, yang dipandang sebagai sebuah anti-pattern. Pengubahan apapun yang dilakukan terhadap Pod, seperti auto-sizing vertikal dari sumber daya (misalnya cpu atau memori), sebaiknya dilakukan oleh proses kontroller luring lainnya, dan bukan oleh ReplicationController itu sendiri.
Tanggung Jawab ReplicationController
ReplicationController hanya memastikan ketersediaan dari sejumlah Pod yang cocok dengan selektor label dan berjalan dengan baik. Saat ini, hanya Pod yang diterminasi yang dijadikan pengecualian dari penghitungan. Kedepannya, kesiapan dan informasi yang ada lainnya dari sistem dapat menjadi pertimbangan, kami dapat meningkatkan kontrol terhadap kebijakan penggantian, dan kami berencana untuk menginformasikan kejadian (event) yang dapat digunakan klien eksternal untuk implementasi penggantian yang sesuai dan/atau kebijakan pengurangan.
ReplicationController akan selalu dibatasi terhadap tanggung jawab spesifik ini. Ia tidak akan melakukan probe kesiapan atau keaktifan. Daripada melakukan auto-scaling, ia ditujukan untuk dikontrol oleh auto-scaler eksternal (seperti yang didiskusikan pada #492), yang akan mengganti fieldreplicas. Kami tidak akan menambahkan kebijakan penjadwalan (contohnya spreading) untuk ReplicationController. Ia juga tidak seharusnya melakukan verifikasi terhadap Pod-Pod yang sedang dikontrol yang cocok dengan spesifikasi templat saat ini, karena hal itu dapat menghambat auto-sizing dan proses otomatis lainnya. Demikian pula batas waktu penyelesaian, pengurutan dependencies, ekspansi konfigurasi, dan fitur-fitur lain yang seharusnya berada di komponen lain. Kami juga bahkan berencana untuk mengeluarkan mekanisme pembuatan Pod secara serentak (#170).
ReplicationController ditujukan untuk menjadi primitif komponen yang dapat dibangun untuk berbagai kebutuhan. Kami menargetkan API dengan tingkatan yang lebih tinggi dan/atau perkakas-perkakas untuk dibangun di atasnya dan primitif tambahan lainnya untuk kenyamanan pengguna kedepannya. Operasi-operasi makro yang sudah didukung oleh kubectl (run, scale, rolling-update) adalah contoh proof-of-concept dari konsep ini. Sebagai contohnya, kita dapat menganggap sesuatu seperti Asgard yang mengatur beberapa ReplicationController, auto-scaler, servis, kebijakan penjadwalan, canary, dan yang lainnya.
Objek API
ReplicationController adalah sebuah sumber daya top-level pada REST API Kubernetes. Detil dari objek API dapat ditemukan di: objek API ReplicationController.
Alternatif untuk ReplicationController
ReplicaSet
ReplicaSet adalah kelanjutan dari ReplicationController yang mendukung selektor selektor label set-based yang baru. Umumnya digunakan oleh Deployment sebagai mekanisme untuk mengorkestrasi pembuatan, penghapusan, dan pembaruan Pod.
Perhatikan bahwa kami merekomendasikan untuk menggunakan Deployment sebagai ganti dari menggunakan ReplicaSet secara langsung, kecuali jika kamu membutuhkan orkestrasi pembaruan khusus atau tidak membutuhkan pembaruan sama sekali.
Deployment (Direkomendasikan)
Deployment adalah objek API tingkat tinggi yang memperbarui ReplicaSet dan Pod-Pod di bawahnya yang mirip dengan cara kerja kubectl rolling-update. Deployment direkomendasikan jika kamu menginginkan fungsionalitas dari pembaruan bergulir ini, karena tidak seperti kubectl rolling-update, Deployment memiliki sifat deklaratif, server-side, dan memiliki beberapa fitur tambahan lainnya.
Pod sederhana
Tidak seperti pada kasus ketika pengguna secara langsung membuat Pod, ReplicationController menggantikan Pod-Pod yang dihapus atau dimatikan untuk alasan apapun, seperti pada kasus kegagalan Node atau pemeliharaan Node yang disruptif, seperti pembaruan kernel. Untuk alasan ini, kami merekomendasikan kamu untuk menggunakan ReplicationController bahkan ketika aplikasimu hanya membutuhkan satu Pod saja. Anggap hal ini mirip dengan pengawas proses, hanya pada kasus ini mengawasi banyak Pod yang terdapat pada berbagai Node dan bukan proses-proses tunggal pada satu Node. ReplicationController mendelegasikan pengulangan kontainer lokal ke agen yang terdapat dalam Node (contohnya Kubelet atau Docker).
Job
Gunakan Job sebagai ganti ReplicationController untuk Pod-Pod yang diharapkan diterminasi dengan sendirinya (seperti batch jobs).
DaemonSet
Gunakan DaemonSet sebagai ganti ReplicationController untuk Pod-Pod yang menyediakan fungsi pada level mesin, seperti pengamatan mesin atau pencatatan mesin. Pod-Pod ini memiliki waktu hidup yang bergantung dengan waktu hidup mesin: Pod butuh untuk dijalankan di mesin sebelum Pod-Pod lainnya dimulai, dan aman untuk diterminasi ketika mesin sudah siap untuk dinyalakan ulang atau dimatikan.
Deployment menyediakan pembaruan Pods dan
ReplicaSets secara deklaratif.
Kamu mendeskripsikan sebuah state yang diinginkan dalam Deployment, kemudian Deployment Pengontrol mengubah state sekarang menjadi seperti pada deskripsi secara bertahap. Kamu dapat mendefinisikan Deployment untuk membuat ReplicaSets baru atau untuk menghapus Deployment yang sudah ada dan mengadopsi semua resourcenya untuk Deployment baru.
Catatan: Jangan mengganti ReplicaSets milik Deployment. Pertimbangkan untuk membuat isu pada repositori utama Kubernetes jika kasusmu tidak diatasi semua kasus di bawah.
Penggunaan
Berikut adalah penggunaan yang umum pada Deployment:
Mendeklarasikan state baru dari Pods dengan membarui PodTemplateSpec milik Deployment. ReplicaSet baru akan dibuat dan Deployment mengatur perpindahan Pod secara teratur dari ReplicaSet lama ke ReplicaSet baru. Tiap ReplicaSet baru akan mengganti revisi Deployment.
Deployment baru akan dibuat dengan nama nginx-deployment, tertulis pada kolom .metadata.name.
Deployment membuat tiga Pod yang direplikasi, ditandai dengan kolom replicas.
Kolom selector mendefinisikan bagaimana Deployment menemukan Pod yang diatur.
Dalam kasus ini, kamu hanya perlu memilih sebuah label yang didefinisikan pada templat Pod (app: nginx).
Namun, aturan pemilihan yang lebih canggih mungkin dilakukan asal templat Pod-nya memenuhi aturan.
Catatan: Kolom matchLabels berbentuk pasangan {key,value}. Sebuah {key,value} dalam mapmatchLabels ekuivalen dengan
elemen pada matchExpressions, yang mana kolom key adalah "key", operator adalah "In", dan larik values hanya berisi "value".
Semua prasyarat dari matchLabels maupun matchExpressions harus dipenuhi agar dapat dicocokkan.
Kolom template berisi sub kolom berikut:
Pod dilabeli app: nginx dengan kolom labels.
Spesifikasi templat Pod atau kolom .template.spec menandakan bahwa Pod mennjalankan satu kontainer nginx,
yang menjalankan image nginxDocker Hub dengan versi 1.7.9.
Membuat satu kontainer bernama nginx sesuai kolom name.
Ikuti langkah-langkah berikut untuk membuat Deployment di atas:
Sebelum memulai, pastikan klaster Kubernetes sedang menyala dan bekerja.
Buat Deployment dengan menjalankan perintah berikut:
Catatan: Kamu dapat menambahkan argument --record untuk menulis perintah yang dijalankan pada anotasi sumber daya kubernetes.io/change-cause. Ini berguna untuk pemeriksaan di masa depan.
Contohnya yaitu untuk melihat perintah yang dijalankan pada tiap revisi Deployment.
Jalankan kubectl get deployments untuk mengecek apakah Deployment telah dibuat. Jika Deployment masih sedang pembuatan, keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3000 1s
Ketika kamu memeriksa Deployments pada klastermu, kolom berikut akan tampil:
* `NAME` menampilkan daftar nama Deployment pada klaster.
* `DESIRED` menampilkan jumlah replika aplikasi yang diinginkan sesuai yang didefinisikan saat pembuatan Deployment. Ini adalah _state_ yang diinginkan.
* `CURRENT` menampilkan berapa jumlah replika yang sedang berjalan.
* `UP-TO-DATE` menampilkan jumlah replika yang diperbarui agar sesuai state yang diinginkan.
* `AVAILABLE` menampilkan jumlah replika aplikasi yang dapat diakses pengguna.
* `AGE` menampilkan lama waktu aplikasi telah berjalan.
Perhatikan bahwa jumlah replika yang diinginkan adalah tiga sesuai kolom .spec.replicas.
Untuk melihat status rilis Deployment, jalankan kubectl rollout status deployment.v1.apps/nginx-deployment. Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out
Jalankan kubectl get deployments lagi beberapa saat kemudian. Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3333 18s
Perhatikan bahwa Deployment telah membuat ketiga replika dan semua replika sudah merupakan yang terbaru (mereka mengandung pembaruan terakhir templat Pod) dan dapat diakses.
Untuk melihat ReplicaSet (rs) yang dibuat Deployment, jalankan kubectl get rs. Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE
nginx-deployment-75675f5897 333 18s
Perhatikan bahwa nama ReplicaSet selalu dalam format [NAMA-DEPLOYMENT]-[KATA-ACAK]. Kata acak dibangkitkan secara acak dan menggunakan pod-template-hash sebagai benih.
Untuk melihat label yang dibangkitkan secara otomatis untuk tiap Pod, jalankan kubectl get pods --show-labels. Perintah akan menghasilkan keluaran berikut:
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-75675f5897-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453nginx-deployment-75675f5897-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453nginx-deployment-75675f5897-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453
ReplicaSet yang dibuat menjamin bahwa ada tiga Pod nginx.
Catatan: Kamu harus memasukkan selektor dan label templat Pod yang benar pada Deployment (dalam kasus ini, app: nginx).
Jangan membuat label atau selektor yang beririsan dengan kontroler lain (termasuk Deployment dan StatefulSet lainnya). Kubernetes tidak akan mencegah adanya label yang beririsan.
Namun, jika beberapa kontroler memiliki selektor yang beririsan, kontroler itu mungkin akan konflik dan berjalan dengan tidak semestinya.
Label pod-template-hash
Catatan: Jangan ubah label ini.
Label pod-template-hash ditambahkan oleh Deployment kontroler pada tiap ReplicaSet yang dibuat atau diadopsi Deployment.
Label ini menjamin anak-anak ReplicaSet milik Deployment tidak tumpang tindih. Dia dibangkitkan dengan melakukan hash pada PodTemplate milik ReplicaSet dan memakainya sebagai label untuk ditambahkan ke selektor ReplicaSet, label templat Pod, dan Pod apapun yang ReplicaSet miliki.
Membarui Deployment
Catatan: Rilis Deployment hanya dapat dipicu oleh perubahan templat Pod Deployment (yaitu, .spec.template), contohnya perubahan kolom label atau image container. Yang lain, seperti replika, tidak akan memicu rilis.
Ikuti langkah-langkah berikut untuk membarui Deployment:
Ganti Pod nginx menjadi image nginx:1.9.1 dari image nginx:1.7.9.
kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment image updated
Alternatif lainnya, kamu dapat edit Deployment dan mengganti .spec.template.spec.containers[0].image dari nginx:1.7.9 ke nginx:1.9.1:
kubectl edit deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment edited
Untuk melihat status rilis, jalankan:
kubectl rollout status deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
atau
deployment "nginx-deployment" successfully rolled out
Untuk menampilkan detail lain dari Deployment yang terbaru:
Setelah rilis sukses, kamu dapat melihat Deployment dengan menjalankan kubectl get deployments.
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 36s
Jalankan kubectl get rs to see that the Deployment updated the Pods dengan membuat ReplicaSet baru dan
menggandakannya menjadi 3 replika, sembari menghapus ReplicaSet menjadi 0 replika.
kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 3 6s
nginx-deployment-2035384211 0 0 0 36s
Menjalankan get pods sekarang hanya akan menampilkan Pod baru:
kubectl get pods
Keluaran akan tampil seperti berikut:
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-khku8 1/1 Running 0 14s
nginx-deployment-1564180365-nacti 1/1 Running 0 14s
nginx-deployment-1564180365-z9gth 1/1 Running 0 14s
Selanjutnya ketika ingin membarui Pod, kamu hanya perlu mengganti templat Pod Deployment lagi.
Deployment memastikan hanya ada beberapa Pod yang mati saat pembaruan berlangsung. Umumnya,
dia memastikan paling sedikit ada 75% jumlah Pod yang diinginkan menyala (25% maksimal tidak dapat diakses).
Deployment juga memastikan hanya ada beberapa Pod yang dibuat melebihi jumlah Pod yang diinginkan.
Umumnya, dia memastikan paling banyak ada 125% jumlah Pod yang diinginkan menyala (25% tambahan maksimal).
Misalnya, jika kamu lihat Deployment diatas lebih jauh, kamu akan melihat bahwa pertama-tama dia membuat Pod baru,
kemudian menghapus beberapa Pod lama, dan membuat yang baru. Dia tidak akan menghapus Pod lama sampai ada cukup
Pod baru menyala, dan pula tidak membuat Pod baru sampai ada cukup Pod lama telah mati.
Dia memastikan paling sedikit 2 Pod menyala dan paling banyak total 4 Pod menyala.
Melihat detil Deployment:
kubectl describe deployments
Keluaran akan tampil seperti berikut:
Name: nginx-deployment
Namespace: default
CreationTimestamp: Thu, 30 Nov 2017 10:56:25 +0000
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision=2
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.9.1
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-1564180365 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 2m deployment-controller Scaled up replica set nginx-deployment-2035384211 to 3
Normal ScalingReplicaSet 24s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 1
Normal ScalingReplicaSet 22s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 2
Normal ScalingReplicaSet 22s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 2
Normal ScalingReplicaSet 19s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 1
Normal ScalingReplicaSet 19s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 3
Normal ScalingReplicaSet 14s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 0
Disini bisa dilihat ketika pertama Deployment dibuat, dia membuat ReplicaSet (nginx-deployment-2035384211)
dan langsung menggandakannya menjadi 3 replika. Saat Deployment diperbarui, dia membuat ReplicaSet baru
(nginx-deployment-1564180365) dan menambah 1 replika kemudian mengecilkan ReplicaSet lama menjadi 2,
sehingga paling sedikit 2 Pod menyala dan paling banyak 4 Pod dibuat setiap saat. Dia kemudian lanjut menaik-turunkan
ReplicaSet baru dan ReplicaSet lama, dengan strategi pembaruan rolling yang sama.
Terakhir, kamu akan dapat 3 replika di ReplicaSet baru telah menyala, dan ReplicaSet lama akan hilang (berisi 0).
Perpanjangan (alias banyak pembaruan secara langsung)
Setiap kali Deployment baru is teramati oleh Deployment kontroler, ReplicaSet dibuat untuk membangkitkan Pod sesuai keinginan.
Jika Deployment diperbarui, ReplicaSet yang terkait Pod dengan label .spec.selector yang cocok,
namun kolom .spec.template pada templat tidak cocok akan dihapus. Kemudian, ReplicaSet baru akan
digandakan sebanyak .spec.replicas dan semua ReplicaSet lama dihapus.
Jika kamu mengubah Deployment saat rilis sedang berjalan, Deployment akan membuat ReplicaSet baru
tiap perubahan dan memulai penggandaan. Lalu, dia akan mengganti ReplicaSet yang dibuat sebelumnya
-- mereka ditambahkan ke dalam daftar ReplicaSet lama dan akan mulai dihapus.
Contohnya, ketika kamu membuat Deployment untuk membangkitkan 5 replika nginx:1.7.9,
kemudian membarui Deployment dengan versi nginx:1.9.1 ketika ada 3 replika nginx:1.7.9 yang dibuat.
Dalam kasus ini, Deployment akan segera menghapus 3 replika Pod nginx:1.7.9 yang telah dibuat, dan mulai membuat
Pod nginx:1.9.1. Dia tidak akan menunggu kelima replika nginx:1.7.9 selesai baru menjalankan perubahan.
Mengubah selektor label
Umumnya, sekali dibuat, selektor label tidak boleh diubah. Sehingga disarankan untuk direncanakan dengan hati-hati sebelumnya.
Bagaimanapun, jika kamu perlu mengganti selektor label, lakukan dengan seksama dan pastikan kamu tahu segala konsekuensinya.
Catatan: Pada versi API apps/v1, selektor label Deployment tidak bisa diubah ketika selesai dibuat.
Penambahan selektor mensyaratkan label templat Pod di spek Deployment untuk diganti dengan label baru juga.
Jika tidak, galat validasi akan muncul. Perubahan haruslah tidak tumpang-tindih, dengan kata lain selektor baru tidak mencakup ReplicaSet dan Pod yang dibuat dengan selektor lama. Sehingga, semua ReplicaSet lama akan menggantung sedangkan ReplicaSet baru tetap dibuat.
Pengubahan selektor mengubah nilai pada kunci selektor -- menghasilkan perilaku yang sama dengan penambahan.
Penghapusan selektor menghilangkan kunci yang ada pada selektor Deployment -- tidak mensyaratkan perubahan apapun pada label templat Pod.
ReplicaSet yang ada tidak menggantung dan ReplicaSet baru tidak dibuat.
Tapi perhatikan bahwa label yang dihapus masih ada pada Pod dan ReplicaSet masing-masing.
Membalikkan Deployment
Kadang, kamu mau membalikkan Deployment; misalnya, saat Deployment tidak stabil, seperti crash looping.
Umumnya, semua riwayat rilis Deployment disimpan oleh sistem sehingga kamu dapat kembali kapanpun kamu mau
(kamu dapat mengubahnya dengan mengubah batas riwayat revisi).
Catatan: Revisi Deployment dibuat saat rilis Deployment dipicu. Ini berarti revisi baru dibuat jika dan hanya jika
templat Pod Deployment (.spec.template) berubah, misalnya jika kamu membarui label atau image kontainer pada templat.
Pembaruan lain, seperti penggantian skala Deployment, tidak membuat revisi Deployment, jadi kamu dapat memfasilitasi
penggantian skala secara manual atau otomatis secara simultan. Artinya saat kamu membalikkan ke versi sebelumnya,
hanya bagian templat Pod Deployment yang dibalikkan.
Misal kamu membuat saltik saat mengganti Deployment, dengan memberi nama image dengan nginx:1.91 alih-alih nginx:1.9.1:
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment image updated
Rilis akan tersendat. Kamu dapat memeriksanya dengan melihat status rilis:
kubectl rollout status deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
Tekan Ctrl-C untuk menghentikan pemeriksaan status rilis di atas. Untuk info lebih lanjut
tentang rilis tersendat, baca disini.
Kamu lihat bahwa jumlah replika lama (nginx-deployment-1564180365 dan nginx-deployment-2035384211) adalah 2, dan replika baru (nginx-deployment-3066724191) adalah 1.
kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 3 25s
nginx-deployment-2035384211 0 0 0 36s
nginx-deployment-3066724191 1 1 0 6s
Lihat pada Pod yang dibuat. Akan ada 1 Pod dibuat dari ReplicaSet baru tersendat loop(?) ketika penarikan image.
kubectl get pods
Keluaran akan tampil seperti berikut:
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-70iae 1/1 Running 0 25s
nginx-deployment-1564180365-jbqqo 1/1 Running 0 25s
nginx-deployment-1564180365-hysrc 1/1 Running 0 25s
nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s
Catatan: Controller Deployment menghentikan rilis yang buruk secara otomatis dan juga berhenti meningkatkan ReplicaSet baru.
Ini tergantung pada parameter rollingUpdate (secara khusus maxUnavailable) yang dimasukkan.
Kubernetes umumnya mengatur jumlahnya menjadi 25%.
Tampilkan deskripsi Deployment:
kubectl describe deployment
Keluaran akan tampil seperti berikut:
Name: nginx-deployment
Namespace: default
CreationTimestamp: Tue, 15 Mar 2016 14:48:04 -0700
Labels: app=nginx
Selector: app=nginx
Replicas: 3 desired | 1 updated | 4 total | 3 available | 1 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.91
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True ReplicaSetUpdated
OldReplicaSets: nginx-deployment-1564180365 (3/3 replicas created)
NewReplicaSet: nginx-deployment-3066724191 (1/1 replicas created)
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 1
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1
Untuk memperbaikinya, kamu harus kembali ke revisi Deployment yang sebelumnya stabil.
Mengecek Riwayat Rilis Deployment
Ikuti langkah-langkah berikut untuk mengecek riwayat rilis:
Pertama, cek revisi Deployment sekarang:
kubectl rollout history deployment.v1.apps/nginx-deployment
Untuk detil lebih lanjut perintah terkait rilis, baca rilis kubectl.
Deployment sekarang dikembalikan ke revisi stabil sebelumnya. Seperti terlihat, ada event DeploymentRollback
yang dibentuk oleh kontroler Deployment untuk pembalikan ke revisi 2.
Cek apakah rilis telah sukses dan Deployment berjalan seharusnya, jalankan:
kubectl get deployment nginx-deployment
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 30m
Tampilkan deskripsi Deployment:
kubectl describe deployment nginx-deployment
Keluaran akan tampil seperti berikut:
Name: nginx-deployment
Namespace: default
CreationTimestamp: Sun, 02 Sep 2018 18:17:55 -0500
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision=4
kubernetes.io/change-cause=kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record=true
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.9.1
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-c4747d96c (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set nginx-deployment-75675f5897 to 3
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 1
Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 2
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 2
Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 1
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 3
Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 0
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-595696685f to 1
Normal DeploymentRollback 15s deployment-controller Rolled back deployment "nginx-deployment" to revision 2
Normal ScalingReplicaSet 15s deployment-controller Scaled down replica set nginx-deployment-595696685f to 0
Mengatur Skala Deployment
Kamu dapat mengatur skala Deployment dengan perintah berikut:
Dengan asumsi horizontal Pod autoscaling dalam klaster dinyalakan,
kamu dapat mengatur autoscaler untuk Deployment-mu dan memilih jumlah minimal dan maksimal Pod yang mau dijalankan berdasarkan penggunaan CPU
dari Pod.
Deployment RollingUpdate mendukung beberapa versi aplikasi berjalan secara bersamaan. Ketika kamu atau autoscaler
mengubah skala Deployment RollingUpdate yang ada di tengah rilis (yang sedang berjalan maupun terjeda),
kontroler Deployment menyeimbangkan replika tambahan dalam ReplicaSet aktif (ReplicaSet dengan Pod) untuk mencegah resiko.
Ini disebut pengaturan skala proporsional.
Sebagai contoh, kamu menjalankan Deployment dengan 10 replika, maxSurge=3, dan maxUnavailable=2.
Pastikan ada 10 replica di Deployment-mu yang berjalan.
kubectl get deploy
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 10 10 10 10 50s
Ganti ke image baru yang kebetulan tidak bisa ditemukan dari dalam klaster.
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:sometag
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment image updated
Penggantian image akan memulai rilis baru dengan ReplicaSet nginx-deployment-1989198191, namun dicegah karena
persyaratan maxUnavailable yang disebut di atas. Cek status rilis:
kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 5 5 0 9s
nginx-deployment-618515232 8 8 8 1m
Kemudian, permintaan peningkatan untuk Deployment akan masuk. Autoscaler menambah replika Deployment
menjadi 15. Controller Deployment perlu menentukan dimana 5 replika ini ditambahkan. Jika kamu memakai
pengaturan skala proporsional, kelima replika akan ditambahkan ke ReplicaSet baru. Dengan pengaturan skala proporsional,
kamu menyebarkan replika tambahan ke semua ReplicaSet. Proporsi terbesar ada pada ReplicaSet dengan
replika terbanyak dan proporsi yang lebih kecil untuk replika dengan ReplicaSet yang lebih sedikit.
Sisanya akan diberikan ReplicaSet dengan replika terbanyak. ReplicaSet tanpa replika tidak akan ditingkatkan.
Dalam kasus kita di atas, 3 replika ditambahkan ke ReplicaSet lama dan 2 replika ditambahkan ke ReplicaSet baru.
Proses rilis akan segera memindahkan semua ReplicaSet baru, dengan asumsi semua replika dalam kondisi sehat.
Untuk memastikannya, jalankan:
kubectl get deploy
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
Status rilis mengkonfirmasi bagaimana replika ditambahkan ke tiap ReplicaSet.
kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
Menjeda dan Melanjutkan Deployment
Kamu dapat menjeda Deployment sebelum memicu satu atau lebih pembaruan kemudian meneruskannya.
Hal ini memungkinkanmu menerapkan beberapa perbaikan selama selang jeda tanpa melakukan rilis yang tidak perlu.
Sebagai contoh, Deployment yang baru dibuat:
Lihat detil Deployment:
kubectl get deploy
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 3 3 3 3 1m
Lihat status rilis:
kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE
nginx-2142116321 3 3 3 1m
The state awal Deployment sebelum jeda akan melanjutkan fungsinya, tapi perubahan
Deployment tidak akan berefek apapun selama Deployment masih terjeda.
Kemudian, mulai kembali Deployment dan perhatikan ReplicaSet baru akan muncul dengan semua perubahan baru:
Deployment menurunkan kapasitas ReplicaSet yang lebih lama.
Pod baru menjadi siap atau dapat diakses (siap selama setidaknya MinReadySeconds).
Kamu dapat mengawasi perkembangan Deployment dengan kubectl rollout status.
Deployment Selesai
Kubernetes menandai Deployment sebagai complete saat memiliki karakteristik berikut:
Semua replika terkait Deployment telah diperbarui ke versi terbaru yang dispecify, artinya semua pembaruan yang kamu inginkan telah selesai.
Semua replika terkait Deployment dapat diakses.
Tidak ada replika lama untuk Deployment yang berjalan.
Kamu dapat mengecek apakah Deployment telah selesai dengan kubectl rollout status.
Jika rilis selesai, kubectl rollout status akan mengembalikan nilai balik nol.
kubectl rollout status deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out
$ echo $?
0
Deployment Gagal
Deployment-mu bisa saja terhenti saat mencoba deploy ReplicaSet terbaru tanpa pernah selesai.
Ini dapat terjadi karena faktor berikut:
Kuota tidak mencukupi
Kegagalan pengecekan kesiapan
Galat saat mengunduh image
Tidak memiliki ijin
Limit ranges
Konfigurasi runtime aplikasi yang salah
Salah satu cara untuk mendeteksi kondisi ini adalah untuk menjelaskan parameter tenggat pada spesifikasi Deployment:
(.spec.progressDeadlineSeconds). .spec.progressDeadlineSeconds menyatakan
lama kontroler Deployment menunggu sebelum mengindikasikan (pada status Deployment) bahwa kemajuan Deployment
tersendat dalam detik.
Perintah kubectl berikut menetapkan spek dengan progressDeadlineSeconds untuk membuat kontroler
melaporkan kemajuan Deployment yang sedikit setelah 10 menit:
Catatan: Kubernetes tidak melakukan apapun pada Deployment yang tersendat selain melaporkannya sebagai Reason=ProgressDeadlineExceeded.
Orkestrator yang lebih tinggi dapat memanfaatkannya untuk melakukan tindak lanjut. Misalnya, mengembalikan Deployment ke versi sebelumnya.
Catatan: Jika Deployment terjeda, Kubernetes tidak akan mengecek kemajuan pada selang itu.
Kamu dapat menjeda Deployment di tengah rilis dan melanjutkannya dengan aman tanpa memicu kondisi saat tenggat telah lewat.
Kamu dapat mengalami galat sejenak pada Deployment disebabkan timeout yang dipasang terlalu kecil atau
hal-hal lain yang terjadi sementara. Misalnya, kamu punya kuota yang tidak mencukupi. Jika kamu mendeskripsikan Deployment
kamu akan menjumpai pada bagian ini:
kubectl describe deployment nginx-deployment
Keluaran akan tampil seperti berikut:
<...>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True ReplicaSetUpdated
ReplicaFailure True FailedCreate
<...>
Jika kamu menjalankan kubectl get deployment nginx-deployment -o yaml, Deployment status akan muncul seperti berikut:
Begitu tenggat kemajuan Deployment terlewat, Kubernetes membarui status dan alasan untuk kondisi Progressing:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate
Kamu dapat menangani isu keterbatasan kuota dengan menurunkan jumlah Deployment, bisa dengan menghapus kontrolers
yang sedang berjalan, atau dengan meningkatkan kuota pada namespace. Jika kuota tersedia, kemudian kontroler Deployment
akan dapat menyelesaikan rilis Deployment. Kamu akan melihat bahwa status Deployment berubah menjadi kondisi sukses (Status=True dan Reason=NewReplicaSetAvailable).
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
Type=Available dengan Status=True artinya Deployment-mu punya ketersediaan minimum. Ketersediaan minimum diatur
oleh parameter yang dibuat pada strategi deployment. Type=Progressing dengan Status=True berarti Deployment
sedang dalam rilis dan masih berjalan atau sudah selesai berjalan dan jumlah minimum replika tersedia
(lihat bagian Alasan untuk kondisi tertentu - dalam kasus ini Reason=NewReplicaSetAvailable berarti Deployment telah selesai).
Kamu dapat mengecek apakah Deployment gagal berkembang dengan perintah kubectl rollout status. kubectl rollout status
mengembalikan nilai selain nol jika Deployment telah melewati tenggat kemajuan.
kubectl rollout status deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline
$ echo $?
1
Menindak Deployment yang gagal
Semua aksi yang dapat diterapkan pada Deployment yang selesai berjalan juga pada Deployment gagal. Kamu dapat menaik/turunkan replika, membalikkan ke versi sebelumnya, atau menjedanya jika kamu perlu menerapkan beberapa perbaikan pada templat Pod Deployment.
Kebijakan Pembersihan
Kamu dapat mengisi kolom .spec.revisionHistoryLimit di Deployment untuk menentukan banyak ReplicaSet
pada Deployment yang ingin dipertahankan. Sisanya akan di garbage-collected di balik layar. Umumnya, nilai kolom berisi 10.
Catatan: Mengisi secara eksplisit dengan nilai 0 akan membuat pembersihan semua riwayat rilis Deployment
sehingga Deployment tidak akan dapat dikembalikan.
Deployment Canary
Jika kamu ingin merilis ke sebagian pengguna atau server menggunakan Deployment,
kamu dapat membuat beberapa Deployment, satu tiap rilis, dengan mengikuti pola canary yang didesripsikan pada
mengelola sumber daya.
Menulis Spesifikasi Deployment
Sebagaimana konfigurasi Kubernetes lainnya, Deployment memerlukan kolom apiVersion, kind, dan metadata.
Untuk informasi umum tentang penggunaan berkas konfigurasi, lihat dokumen deploy aplikasi,
mengatur kontainer, dan memakai kubectl untuk mengatur sumber daya.
Dalam .spec hanya ada kolom .spec.template dan .spec.selector yang wajib diisi.
.spec.template adalah templat Pod. Dia memiliki skema yang sama dengan Pod. Bedanya dia bersarang dan tidak punya apiVersion atau kind.
Selain kolom wajib untuk Pod, templat Pod pada Deployment harus menentukan label dan aturan menjalankan ulang yang tepat.
Untuk label, pastikaan tidak bertumpang tindih dengan kontroler lainnya. Lihat selektor).
.spec.replicas adalah kolom opsional yang mengatur jumlah Pod yang diinginkan. Setelan bawaannya berisi 1.
Selektor
.spec.selector adalah kolom wajib yang mengatur selektor label
untuk Pod yang dituju oleh Deployment ini.
.spec.selector harus sesuai .spec.template.metadata.labels, atau akan ditolak oleh API.
Di versi API apps/v1, .spec.selector dan .metadata.labels tidak berisi .spec.template.metadata.labels jika tidak disetel.
Jadi mereka harus disetel secara eksplisit. Perhatikan juga .spec.selector tidak dapat diubah setelah Deployment dibuat pada apps/v1.
Deployment dapat mematikan Pod yang labelnya cocok dengan selektor jika templatnya berbeda
dari .spec.template atau total jumlah Pod melebihi .spec.replicas. Dia akan membuat Pod baru
dengan .spec.template jika jumlah Pod kurang dari yang diinginkan.
Catatan: Kamu sebaiknya tidak membuat Pod lain yang labelnya cocok dengan selektor ini, baik secara langsung,
melalui Deployment lain, atau membuat kontroler lain seperti ReplicaSet atau ReplicationController.
Kalau kamu melakukannya, Deployment pertama akan mengira dia yang membuat Pod-pod ini.
Kubernetes tidak akan mencegahmu melakukannya.
Jika kamu punya beberapa kontroler dengan selektor bertindihan, mereka akan saling bertikai
dan tidak akan berjalan semestinya.
Strategi
.spec.strategy mengatur strategi yang dipakai untuk mengganti Pod lama dengan yang baru.
.spec.strategy.type dapat berisi "Recreate" atau "RollingUpdate". Nilai bawaannya adalah "RollingUpdate".
Membuat Ulang Deployment
Semua Pod yang ada dimatikan sebelum yang baru dibuat ketika nilai .spec.strategy.type==Recreate.
Membarui Deployment secara Bergulir
Deployment membarui Pod secara bergulir
saat .spec.strategy.type==RollingUpdate. Kamu dapat menentukan maxUnavailable dan maxSurge untuk mengatur
proses pembaruan bergulir.
Ketidaktersediaan Maksimum
.spec.strategy.rollingUpdate.maxUnavailable adalah kolom opsional yang mengatur jumlah Pod maksimal
yang tidak tersedia selama proses pembaruan. Nilainya bisa berupa angka mutlak (contohnya 5)
atau persentase dari Pod yang diinginkan (contohnya 10%). Angka mutlak dihitung berdasarkan persentase
dengan pembulatan ke bawah. Nilai tidak bisa nol jika .spec.strategy.rollingUpdate.maxSurge juga nol.
Nilai bawaannya yaitu 25%.
Sebagai contoh, ketika nilai berisi 30%, ReplicaSet lama dapat segera diperkecil menjadi 70% dari Pod
yang diinginkan saat pembaruan bergulir dimulai. Seketika Pod baru siap, ReplicaSet lama dapat lebih diperkecil lagi,
diikuti dengan pembesaran ReplicaSet, menjamin total jumlah Pod yang siap kapanpun ketika pembaruan
paling sedikit 70% dari Pod yang diinginkan.
Kelebihan Maksimum
.spec.strategy.rollingUpdate.maxSurge adalah kolom opsional yang mengatur jumlah Pod maksimal yang
dapat dibuat melebihi jumlah Pod yang diinginkan. Nilainya bisa berupa angka mutlak (contohnya 5) atau persentase
dari Pod yang diinginkan (contohnya 10%). Nilai tidak bisa nol jika MaxUnavailable juga nol. Angka mutlak
dihitung berdasarkan persentase dengan pembulatan ke bawah. Nilai bawaannya yaitu 25%.
Sebagai contoh, ketika nilai berisi 30%, ReplicaSet baru dapat segera diperbesar saat pembaruan bergulir dimulai,
sehingga total jumlah Pod yang baru dan lama tidak melebihi 130% dari Pod yang diinginkan.
Saat Pod lama dimatikan, ReplicaSet baru dapat lebih diperbesar lagi, menjamin total jumlah Pod yang siap
kapanpun ketika pembaruan paling banyak 130% dari Pod yang diinginkan.
Tenggat Kemajuan dalam Detik
.spec.progressDeadlineSeconds adalah kolom opsional yang mengatur lama tunggu dalam dalam detik untuk Deployment-mu berjalan
sebelum sistem melaporkan lagi bahwa Deployment gagal - ditunjukkan dengan kondisi Type=Progressing, Status=False,
dan Reason=ProgressDeadlineExceeded pada status sumber daya. Controller Deployment akan tetap mencoba ulang Deployment.
Nantinya begitu pengembalian otomatis diimplementasikan, kontroler Deployment akan membalikkan Deployment segera
saat dia menjumpai kondisi tersebut.
Jika ditentukan, kolom ini harus lebih besar dari .spec.minReadySeconds.
Lama Minimum untuk Siap dalam Detik
.spec.minReadySeconds adalah kolom opsional yang mengatur lama minimal sebuah Pod yang baru dibuat
seharusnya siap tanpa ada kontainer yang rusak, untuk dianggap tersedia, dalam detik.
Nilai bawaannya yaitu 0 (Pod akan dianggap tersedia segera ketika siap). Untuk mempelajari lebih lanjut
kapan Pod dianggap siap, lihat Pemeriksaan Kontainer.
Kembali Ke
Kolom .spec.rollbackTo telah ditinggalkan pada versi API extensions/v1beta1 dan apps/v1beta1, dan sudah tidak didukung mulai versi API apps/v1beta2.
Sebagai gantinya, disarankan untuk menggunakan kubectl rollout undo sebagaimana diperkenalkan dalam Kembali ke Revisi Sebelumnya.
Batas Riwayat Revisi
Riwayat revisi Deployment disimpan dalam ReplicaSet yang dia kendalikan.
.spec.revisionHistoryLimit adalah kolom opsional yang mengatur jumlah ReplicaSet lama yang dipertahankan
untuk memungkinkan pengembalian. ReplicaSet lama ini mengambil sumber daya dari etcd dan memunculkan keluaran
dari kubectl get rs. Konfigurasi tiap revisi Deployment disimpan pada ReplicaSet-nya; sehingga, begitu ReplicaSet lama dihapus,
kamu tidak mampu lagi membalikkan revisi Deployment-nya. Umumnya, 10 ReplicaSet lama akan dipertahankan,
namun nilai idealnya tergantung pada frekuensi dan stabilitas Deployment-deployment baru.
Lebih spesifik, mengisi kolom dengan nol berarti semua ReplicaSet lama dengan 0 replika akan dibersihkan.
Dalam kasus ini, rilis Deployment baru tidak dapat dibalikkan, sebab riwayat revisinya telah dibersihkan.
Terjeda
.spec.paused adalah kolom boolean opsional untuk menjeda dan melanjutkan Deployment. Perbedaan antara Deployment yang terjeda
dan yang tidak hanyalah perubahan apapun pada PodTemplateSpec Deployment terjeda tidak akan memicu rilis baru selama masih terjeda.
Deployment umumnya tidak terjeda saat dibuat.
Alternatif untuk Deployment
kubectl rolling update
kubectl rolling update membarui Pod dan ReplicationController
dengan cara yang serupa. Namun, Deployments lebih disarankan karena deklaratif, berjalan di sisi server, dan punya fitur tambahan,
seperti pembalikkan ke revisi manapun sebelumnya bahkan setelah pembaruan rolling selesais.
4.2.4 - StatefulSet
StatefulSet merupakan salah satu objek API workload yang digunakan untuk aplikasi stateful.
Catatan: StatefulSet merupakan fitur stabil (GA) sejak versi 1.9.
Melakukan proses manajemen deployment dan scaling dari sebuah set Pods, serta menjamin mekanisme ordering dan keunikan dari Pod ini.
Seperti halnya Deployment, sebuah StatefulSet akan melakukan proses manajemen Pod yang didasarkan pada spec container identik. Meskipun begitu tidak seperti sebuah Deployment, sebuah StatefulSet akan menjamin identitas setiap Pod yang ada. Pod ini akan dibuat berdasarkan spec yang sama, tetapi tidak dapat digantikan satu sama lainnya: setiap Pod memiliki identifier persisten yang akan di-maintain meskipun pod tersebut di (re)schedule.
Sebuah StatefulSet beroperasi dengan pola yang sama dengan Kontroler lainnya. Kamu dapat mendefinisikan state yang diinginkan pada objek StatefulSet, dan kontroler StatefulSet akan membuat update yang dibutuhkan dari state saat ini.
Menggunakan StatefulSet
StatefulSet akan sangat bermanfaat apabila digunakan untuk aplikasi
yang membutuhkan salah satu atau beberapa fungsi berikut.
Memiliki identitas jaringan unik yang stabil.
Penyimpanan persisten yang stabil.
Mekanisme scaling dan deployment yang graceful tertara berdasarkan urutan.
Mekanisme rolling update yang otomatis berdasarkan urutan.
Stabil dalam poin-poin di atas memiliki arti yang sama dengan persisten pada
Pod saat dilakukan (re)scheduling. Jika suatu aplikasi tidak membutuhkan
identitas yang stabil atau deployment yang memiliki urutan, penghapusan, atau
mekanisme scaling, kamu harus melakukan deploy aplikasi dengan controller yang menyediakan
replika stateless. Controller seperti Deployment atau
ReplicaSet akan lebih sesuai dengan kebutuhan kamu.
Keterbatasan
StatefulSet merupakan sumber daya beta sebelum 1.9 dan tidak tersedia
pada Kubernetes rilis sebelum versi 1.5.
Penyimpanan untuk sebuah Pod harus terlebih dahulu di-provision dengan menggunakan sebuah Provisioner PersistentVolume berdasarkan storage class yang dispesifikasikan, atau sudah ditentukan sebelumnya oleh administrator.
Menghapus dan/atau scaling sebuah StatefulSet tidak akan menghapus volume yang berkaitan dengan StatefulSet tersebut. Hal ini dilakukan untuk menjamin data yang disimpan, yang secara umum dinilai lebih berhaga dibandingkan dengan mekanisme penghapusan data secara otomatis pada sumber daya terkait.
StatefulSet saat ini membutuhkan sebuah Headless Service yang nantinya akan bertanggung jawab terhadap pada identitas jaringan pada Pod. Kamulah yang bertanggung jawab untuk membuat Service tersebut.
StatefulSet tidak menjamin terminasi Pod ketika sebuah StatefulSet dihapus. Untuk mendapatkan terminasi Pod yang terurut dan graceful pada StatefulSet, kita dapat melakukan scale down Pod ke 0 sebelum penghapusan.
Contoh di bawah ini akna menunjukkan komponen-komponen penyusun StatefulSet.
Sebuah Service Headless, dengan nama nginx, digunakan untuk mengontrol domain jaringan.
StatefulSet, dengan nama web, memiliki Spek yang mengindikasikan terdapat 3 replika Container yang akan dihidupkan pada Pod yang unik.
FieldvolumeClaimTemplates akan menyediakan penyimpanan stabil menggunakan PersistentVolume yang di-provision oleh sebuah Provisioner PersistentVolume.
apiVersion:v1kind:Servicemetadata:name:nginxlabels:app:nginxspec:ports:- port:80name:webclusterIP:Noneselector:app:nginx---apiVersion:apps/v1kind:StatefulSetmetadata:name:webspec:selector:matchLabels:app:nginx# harus sesuai dengan .spec.template.metadata.labelsserviceName:"nginx"replicas:3# nilai default-nya adalah 1template:metadata:labels:app:nginx# harus sesuai dengan .spec.selector.matchLabelsspec:terminationGracePeriodSeconds:10containers:- name:nginximage:k8s.gcr.io/nginx-slim:0.8ports:- containerPort:80name:webvolumeMounts:- name:wwwmountPath:/usr/share/nginx/htmlvolumeClaimTemplates:- metadata:name:wwwspec:accessModes:["ReadWriteOnce"]storageClassName:"my-storage-class"resources:requests:storage:1Gi
Selector Pod
Kamu harus menspesifikasikan field.spec.selector dari sebuah StatefulSet untuk menyesuaikan dengan label yang ada pada .spec.template.metadata.labels. Sebelum Kubernetes 1.8, field.spec.selector dapat diabaikan. Sejak versi 1.8 dan versi selanjutnya, apabila tidak terdapat selector Pod yang sesuai maka akan menghasilkan eror pada validasi pembuatan StatefulSet.
Identitas Pod
Pod pada StatefulSet memiliki identitas unik yang tersusun berdasarkan skala ordinal, sebuah
identitas jaringan yang stabil, serta penyimpanan yang stabil. Identitas yang ada pada Pod
ini akan tetap melekat, meskipun Pod tersebut dilakukan (re)schedule pada Node yang berbeda.
Indeks Ordinal
Untuk sebuah StatefulSet dengan N buah replika, setiap Pod di dalam StatefulSet akan
diberi nama pada suatu indeks ordinal tertentu, dari 0 hingga N-1, yang unik pada Set ini.
ID Jaringan yang Stabil
Setiap Pod di dalam StatefulSet memiliki hostname diturunkan dari nama SatetulSet tersebut
serta ordinal Pod tersebut. Pola pada hostname yang terbentuk adalah
$(statefulset name)-$(ordinal). Contoh di atas akan menghasilkan tiga Pod
dengan nama web-0,web-1,web-2.
Sebuah StatefulSet dapat menggunakan sebuah Service Headless
untuk mengontrol domain dari Pod yang ada. Domain yang diatur oleh Service ini memiliki format:
$(service name).$(namespace).svc.cluster.local, dimana "cluster.local" merupakan
domain klaster.
Seiring dibuatnya setiap Pod, Pod tersebut akan memiliki subdomain DNS-nya sendiri, yang memiliki format:
$(podname).$(governing service domain), dimana Service yang mengatur didefinisikan oleh
fieldserviceName pada StatefulSet.
Seperti sudah disebutkan di dalam bagian keterbatasan, kamulah yang bertanggung jawab
untuk membuat Service Headless
yang bertanggung jawab terhadap identitas jaringan pada Pod.
Di sini terdapat beberapa contoh penggunaan Domain Klaster, nama Service,
nama StatefulSet, dan bagaimana hal tersebut berdampak pada nama DNS dari Pod StatefulSet.
Domain Klaster
Service (ns/nama)
StatefulSet (ns/nama)
Domain StatefulSet
DNS Pod
Hostname Pod
cluster.local
default/nginx
default/web
nginx.default.svc.cluster.local
web-{0..N-1}.nginx.default.svc.cluster.local
web-{0..N-1}
cluster.local
foo/nginx
foo/web
nginx.foo.svc.cluster.local
web-{0..N-1}.nginx.foo.svc.cluster.local
web-{0..N-1}
kube.local
foo/nginx
foo/web
nginx.foo.svc.kube.local
web-{0..N-1}.nginx.foo.svc.kube.local
web-{0..N-1}
Catatan: Domain klaster akan diatur menjadi cluster.local kecuali
nilainya dikonfigurasi.
Penyimpanan Stabil
Kubernetes membuat sebuah PersistentVolume untuk setiap
VolumeClaimTemplate. Pada contoh nginx di atas, setiap Pod akan menerima sebuah PersistentVolume
dengan StorageClass my-storage-class dan penyimpanan senilai 1 Gib yang sudah di-provisioning. Jika tidak ada StorageClass
yang dispesifikasikan, maka StorageClass default akan digunakan. Ketika sebuah Pod dilakukan (re)schedule
pada sebuah Node, volumeMounts akan me-mount PersistentVolumes yang terkait dengan
PersistentVolume Claim-nya. Perhatikan bahwa, PersistentVolume yang terkait dengan
PersistentVolumeClaim dari Pod tidak akan dihapus ketika Pod, atau StatefulSet dihapus.
Penghapusan ini harus dilakukan secara manual.
Label Pod Name
Ketika sebuah controller StatefulSet membuat sebuah Pod, controller ini akan menambahkan label, statefulset.kubernetes.io/pod-name,
yang akan diaktifkan pada nama Pod. Label ini akan mengizinkan kamu untuk meng-attach sebuah Service pada Pod spesifik tertentu.
di StatefulSet.
Jaminan Deployment dan Mekanisme Scaling
Untuk sebuah StatefulSet dengan N buah replika, ketika Pod di-deploy, Pod tersebut akan dibuat secara berurutan dengan urutan nilai {0..N-1}.
Ketika Pod dihapus, Pod tersebut akan dihentikan dengan urutan terbalik, yaitu {N-1..0}.
Sebelum operasi scaling diaplikasikan pada sebuah Pod, semua Pod sebelum Pod tersebut haruslah sudah dalam status Running dan Ready.
Sebelum sebuah Pod dihentikan, semua Pod setelah Pod tersebut haruslah sudah terlebih dahulu dihentikan.
StatefulSet tidak boleh menspesifikasikan nilai dari pod.Spec.TerminationGracePeriodSeconds menjadi 0. Hal ini tidaklah aman dan tidak disarankan. Untuk penjelasan lebih lanjut, silakan lihat penghapusan paksa Pod pada StatefulSet.
Ketika contoh nginx di atas dibuat, tiga Pod akan di-deploy dengan urutan
web-0, web-1, web-2. web-1 tidak akan di-deploy sebelum web-0 berada dalam status
Running dan Ready, dan web-2 tidak akan di-deploy sebelum
web-1 berada dalam status Running dan Ready. Jika web-0 gagal, setelah web-1 berada dalam status Running and Ready,
tapi sebelum web-2 dibuat, maka web-2 tidak akan dibuat hingga web-0 sukses dibuat ulang dan
berada dalam status Running dan Ready.
Jika seorang pengguna akan melakukan mekanisme scale pada contoh di atas dengan cara melakukan patch,
pada StatefulSet sehingga replicas=1, maka web-2 akan dihentikan terlebih dahulu.
web-1 tidak akan dihentikan hingga web-2 benar-benar berhenti dan dihapus.
Jika web-0 gagal setelah web-2 diterminasi dan berada dalam status mati,
tetapi sebelum web-1 dihentikan, maka web-1 tidak akan dihentikan hingga
web-0 berada dalam status Running dan Ready.
Kebijakan Manajemen Pod
Pada Kubernetes versi 1.7 dan setelahnya, StatefulSet mengizinkan kamu untuk
melakukan mekanisme urutan tadi menjadi lebih fleksibel dengan tetap
menjamin keunikan dan identitas yang ada melalui field.spec.podManagementPolicy.
Manajemen OrderedReady pada Pod
Manajemen OrderedReady pada Pod merupakan nilai default dari StatefulSet.
Hal ini akan mengimplementasikan perilaku yang dijelaskan di atas.
Manajemen Pod secara Paralel
Manajemen Pod secara paralel akan menyebabkan kontroler StatefulSet untuk
memulai atau menghentikan semua Pod yang ada secara paralel, dan tidak
menunggu Pod berada dalam status Running dan Ready atau sudah dihentikan secara menyeluruh
sebelum me-launch atau menghentikan Pod yang lain. Opsi ini hanya akan memengaruhi operasi
scaling. Operasi pembaruan tidak akan terpengaruh.
Strategi Update
Pada Kubernetes versi 1.7 dan setelahnya, field.spec.updateStrategy pada StatefulSet
memungkinkan-mu untuk melakukan konfigurasi dan menonaktifkan otomatisasi
rolling updates untuk container, label, resource request/limits, dan
annotation pada Pod yang ada di dalam sebuah StatefulSet.
Mekanisme Strategi Update On Delete
Mekanisme strategi update OnDelete mengimplementasikan perilaku legasi (versi 1.6 dan sebelumnya).
Ketika sebuah field.spec.updateStrategy.type pada StatefulSet diubah menjadi OnDelete
maka kontroler StatefulSet tidak akan secara otomatis melakukan update
pada Pod yang ada di dalam StatefulSet tersebut. Pengguna haruslah secara manual
melakukan penghapusan Pod agar kontroler membuat Pod baru yang mengandung modifikasi
yang dibuat pada field.spec.template StatefulSet.
Mekanisme Strategi Update Rolling Updates
Mekanisme strategi update RollingUpdate mengimplementasikan otomatisasi rolling update
untuk Pod yang ada pada StatefulSet. Strategi inilah yang diterapkan ketika .spec.updateStrategy tidak dispesifikasikan.
Ketika field.spec.updateStrategy.type diubah nilainya menjadi RollingUpdate, maka
kontroler StatefulSet akan menghapus dan membuat setiap Pod di dalam StatefulSet. Kemudian
hal ini akan diterapkan dengan urutan yang sama dengan mekanisme terminasi Pod (dari nilai ordinal terbesar ke terkecil),
yang kemudian akan melakukan update Pod satu per satu. Mekanisme ini akan memastikan sebuah Pod yang di-update
berada dalam status Running dan Ready sebelum meng-update Pod dengan nilai ordinal lebih rendah.
Mekanisme Strategi Update dengan Partisi
Mekanisme strategi update RollingUpdate dapat dipartisi, dengan cara menspesifikasikan nilai
dari .spec.updateStrategy.rollingUpdate.partition. Jika nilai dari field ini dispesifikasikan,
maka semua Pod dengan nilai ordinal yang lebih besar atau sama dengan nilai partisi akan diupdate ketika
nilai .spec.template pada StatefulSet diubah. Semua Pod dengan nilai ordinal yang lebih kecil
dari partisi tidak akan diupdate, dan, bahkan setelah Pod tersebut dihapus, Pod ini akan digantikan
dengan Pod versi sebelumnya. Jika nilai .spec.updateStrategy.rollingUpdate.partition lebih besar dari
nilai .spec.replicas, update pada .spec.template tidak akan dipropagasi pada Pod-Pod-nya.
Pada sebagian besar kasus, kamu tidak akan perlu menggunakan partisi, tapi hal tersebut
akan sangat berguna apabila kamu ingin mekakukan mekanisme update canary.
Mekanisme Strategi Update yang Dipaksa (Forced Rollback)
Ketika menggunakan strategi update Rolling Updates dengan nilai default
Kebijakan Manajemen Pod (OrderedReady),
hal ini memungkinkan adanya kondisi broken yang membutuhkan intervensi secara manual
agar kondisi ini dapat diperbaiki.
Jika kamu melakukan update pada template Pod untuk konfigurasi
yang tidak pernah berada dalam status Running dan Ready (sebagai contohnya, apabila terdapat kode binary yang buruk atau error pada konfigurasi di level aplikasi),
maka StatefulSet akan menghentikan proses rollout dan berada dalam status wait.
Dalam kondisi ini, maka templat Pod tidak akan diubah secara otomatis pada konfigurasi sebelumnya
Hal ini terjadi karena adanya isu,
StatefulSet akan tetap berada dalam kondisi wait untuk menunggu Pod yang bermasalah untuk menjadi Ready
(yang tidak akan terjadi) dan sebelum StatefulSet ini berusaha untuk melakukan revert pada konfigurasi sebelumnya.
Setelah melakukan mekanisme revert templat, kamu juga harus menghapus semua Pod di dalam
StatefulSet tersebut yang telah berusaha untuk menggunakan konfigurasi yang broken.
StatefulSet akan mulai membuat Pod dengan templat konfigurasi yang sudah di-revert.
DaemonSet memastikan semua atau sebagian Node memiliki salinan sebuah Pod.
Ketika Node baru ditambahkan ke klaster, Pod ditambahkan ke Node tersebut.
Ketika Node dihapus dari klaster, Pod akan dibersihkan oleh garbage collector.
Menghapus DaemonSet akan menghapus semua Pod yang ia buat.
Beberapa penggunaan umum DaemonSet, yaitu:
menjalankan daemon penyimpanan di klaster, seperti glusterd, ceph, di
setiap Node.
menjalankan daemon pengumpulan log di semua Node, seperti fluentd atau
logstash.
Dalam kasus sederhana, satu DaemonSet, mencakup semua Node, akan digunakan untuk
setiap jenis daemon. Pengaturan yang lebih rumit bisa saja menggunakan lebih
dari satu DaemonSet untuk satu jenis daemon, tapi dengan flag dan/atau
permintaan cpu/memori yang berbeda untuk jenis hardware yang berbeda.
Menulis Spek DaemonSet
Buat DaemonSet
Kamu bisa definisikan DaemonSet dalam berkas YAML. Contohnya, berkas
daemonset.yaml di bawah mendefinisikan DaemonSet yang menjalankan image Docker
fluentd-elasticsearch:
.spec.template adalah salah satu field wajib di dalam .spec.
.spec.template adalah sebuah templat Pod. Skemanya benar-benar sama dengan Pod, kecuali bagian bahwa ia bersarang/nested dan tidak memiliki apiVersion atau kind.
Selain field wajib untuk Pod, templat Pod di DaemonSet harus
menspesifikasikan label yang sesuai (lihat selektor Pod).
Templat Pod di DaemonSet harus memiliki RestartPolicy
yang bernilai Always, atau tidak dispesifikasikan, sehingga default menjadi Always.
DaemonSet dengan nilai Always membuat Pod akan selalu di-restart saat kontainer
keluar/berhenti atau terjadi crash.
Selektor Pod
Field.spec.selector adalah selektor Pod. Cara kerjanya sama dengan .spec.selector pada Job.
Pada Kubernetes 1.8, kamu harus menspesifikasikan selektor Pod yang cocok dengan label pada .spec.template.
Selektor Pod tidak akan lagi diberi nilai default ketika dibiarkan kosong. Nilai default selektor tidak
cocok dengan kubectl apply. Juga, sesudah DaemonSet dibuat, .spec.selector tidak dapat diubah.
Mengubah selektor Pod dapat menyebabkan Pod orphan yang tidak disengaja, dan membingungkan pengguna.
matchExpressions - bisa digunakan untuk membuat selektor yang lebih canggih
dengan mendefinisikan key, daftar value dan operator yang menyatakan
hubungan antara key dan value.
Ketika keduanya dispesifikasikan hasilnya diperoleh dari operasi AND.
Jika .spec.selector dispesifikasikan, nilainya harus cocok dengan .spec.template.metadata.labels. Konfigurasi yang tidak cocok akan ditolak oleh API.
Selain itu kamu tidak seharusnya membuat Pod apapun yang labelnya cocok dengan
selektor tersebut, entah secara langsung, via DaemonSet lain, atau via workload resource lain seperti ReplicaSet.
Jika kamu coba buat, Pengontrol DaemonSet akan
berpikir bahwa Pod tersebut dibuat olehnya. Kubernetes tidak akan menghentikan
kamu melakukannya. Contoh kasus di mana kamu mungkin melakukan ini dengan
membuat Pod dengan nilai yang berbeda di sebuah Node untuk testing.
Menjalankan Pod di Sebagian Node
Jika kamu menspesifikasikan .spec.template.spec.nodeSelector, maka controller DaemonSet akan
membuat Pod pada Node yang cocok dengan selektor
Node. Demikian juga, jika kamu menspesifikasikan .spec.template.spec.affinity,
maka controller DaemonSet akan membuat Pod pada Node yang cocok dengan Node affinity.
Jika kamu tidak menspesifikasikan sama sekali, maka controller DaemonSet akan
membuat Pod pada semua Node.
Bagaimana Pod Daemon Dijadwalkan
Dijadwalkan oleh default scheduler
FEATURE STATE:Kubernetes 1.17 [stable]
DaemonSet memastikan bahwa semua Node yang memenuhi syarat menjalankan salinan
Pod. Normalnya, Node yang menjalankan Pod dipilih oleh scheduler Kubernetes.
Namun, Pod DaemonSet dibuat dan dijadwalkan oleh controller DaemonSet. Hal ini
mendatangkan masalah-masalah berikut:
Inkonsistensi perilaku Pod: Pod normal yang menunggu dijadwalkan akan dibuat
dalam keadaan Pending, tapi Pod DaemonSet tidak seperti itu. Ini
membingungkan untuk pengguna.
Pod preemption
ditangani oleh default scheduler. Ketika preemption dinyalakan,
controller DaemonSet akan membuat keputusan penjadwalan tanpa
memperhitungkan prioritas Pod dan preemption.
ScheduleDaemonSetPods mengizinkan kamu untuk menjadwalkan DaemonSet
menggunakan default scheduler daripada controller DaemonSet, dengan
menambahkan syarat NodeAffinity pada Pod DaemonSet daripada syarat
.spec.nodeName. Kemudian, default scheduler digunakan untuk mengikat Pod ke
host target. Jika afinitas Node dari Pod DaemonSet sudah ada, maka ini
akan diganti. Controller DaemonSet hanya akan melakukan operasi-operasi ini
ketika membuat atau mengubah Pod DaemonSet, dan tidak ada perubahan yang terjadi
pada spec.template DaemonSet.
Sebagai tambahan, tolerationnode.kubernetes.io/unschedulable:NoSchedule
ditambahkan secara otomatis pada Pod DaemonSet. Default scheduler akan
mengabaikan Node unschedulable ketika menjadwalkan Pod DaemonSet.
Taint dan Toleration
Meskipun Pod Daemon menghormati
taint dan toleration,
toleration berikut ini akan otomatis ditambahkan ke Pod DaemonSet sesuai
dengan fitur yang bersangkutan.
Toleration Key
Effect
Versi
Deskripsi
node.kubernetes.io/not-ready
NoExecute
1.13+
Pod DaemonSet tidak akan menjadi evicted ketika ada masalah Node seperti partisi jaringan.
node.kubernetes.io/unreachable
NoExecute
1.13+
Pod DaemonSet tidak akan menjadi evicted ketika ada masalah Node seperti partisi jaringan.
node.kubernetes.io/disk-pressure
NoSchedule
1.8+
node.kubernetes.io/memory-pressure
NoSchedule
1.8+
node.kubernetes.io/unschedulable
NoSchedule
1.12+
Pod DaemonSet mentoleransi atribut unschedulabledefault scheduler.
node.kubernetes.io/network-unavailable
NoSchedule
1.12+
Pod DaemonSet yang menggunakan jaringan host mentoleransi atribut network-unavailabledefault scheduler.
Berkomunikasi dengan Pod Daemon
Beberapa pola yang mungkin digunakan untuk berkomunikasi dengan Pod dalam DaemonSet, yaitu:
Push: Pod dalam DaemonSet diatur untuk mengirim pembaruan status ke servis lain,
contohnya stats database. Pod ini tidak memiliki klien.
IP Node dan Konvensi Port: Pod dalam DaemonSet dapat menggunakan hostPort, sehingga Pod dapat diakses menggunakan IP Node. Klien tahu daftar IP Node dengan suatu cara, dan tahu port berdasarkan konvensi.
DNS: Buat headless service dengan Pod selektor yang sama,
dan temukan DaemonSet menggunakan resourceendpoints atau mengambil beberapa A record dari DNS.
Service: Buat Servis dengan Pod selektor yang sama, dan gunakan Servis untuk mengakses daemon pada
Node random. (Tidak ada cara mengakses spesifik Node)
Melakukan Pembaruan DaemonSet
Jika label Node berubah, DaemonSet akan menambahkan Pod ke Node cocok yang baru dan menghapus Pod dari
Node tidak cocok yang baru.
Kamu bisa mengubah Pod yang dibuat DaemonSet. Namun, Pod tidak membolehkan perubahan semua field.
Perlu diingat, controller DaemonSet akan menggunakan templat yang asli di waktu selanjutnya
Node baru (bahkan dengan nama yang sama) dibuat.
Kamu bisa menghapus DaemonSet. Jika kamu spesifikasikan --cascade=false dengan kubectl, maka
Pod akan dibiarkan pada Node. Jika kamu pada waktu kemudian membuat DaemonSet baru dengan selektor
yang sama, DaemonSet yang baru akan mengadopsi Pod yang sudah ada. Jika ada Pod yang perlu diganti,
DaemonSet akan mengganti sesuai dengan updateStrategy.
Kamu mungkin menjalankan proses daemon dengan cara menjalankan mereka langsung pada Node (e.g.
menggunakan init, upstartd, atau systemd). Tidak ada salahnya seperti itu. Namun, ada beberapa
keuntungan menjalankan proses daemon via DaemonSet.
Kemampuan memantau dan mengatur log daemon dengan cara yang sama dengan aplikasi.
Bahasa dan alat Konfigurasi yang sama (e.g. Templat Pod, kubectl) untuk daemon dan aplikasi.
Menjalankan daemon dalam kontainer dengan batasan resource meningkatkan isolasi antar daemon dari
kontainer aplikasi. Namun, hal ini juga bisa didapat dengan menjalankan daemon dalam kontainer tapi
tanpa Pod (e.g. dijalankan langsung via Docker).
Pod Polosan
Dimungkinkan untuk membuat Pod langsung dengan menspesifikasikan Node mana untuk dijalankan. Namun,
DaemonSet akan menggantikan Pod yang untuk suatu alasan dihapus atau dihentikan, seperti pada saat
kerusakan Node atau pemeliharaan Node yang mengganggu seperti pembaruan kernel. Oleh karena itu, kamu
perlu menggunakan DaemonSet daripada membuat Pod satu per satu.
Pod Statis
Dimungkinkan untuk membuat Pod dengan menulis sebuah berkas ke direktori tertentu yang di-watch oleh Kubelet.
Pod ini disebut dengan istilah Pod statis.
Berbeda dengan DaemonSet, Pod statis tidak dapat dikelola menggunakan kubectl atau klien API Kubernetes
yang lain. Pod statis tidak bergantung kepada apiserver, membuat Pod statis berguna pada kasus-kasus
bootstrapping klaster.
Deployment
DaemonSet mirip dengan Deployment sebab mereka
sama-sama membuat Pod, dan Pod yang mereka buat punya proses yang seharusnya tidak berhenti (e.g. peladen web,
peladen penyimpanan)
Gunakan Deployment untuk layanan stateless, seperti frontend, di mana proses scaling naik
dan turun jumlah replika dan rolling update lebih penting daripada mengatur secara tepat di
host mana Pod berjalan. Gunakan DaemonSet ketika penting untuk satu salinan Pod
selalu berjalan di semua atau sebagian host, dan ketika Pod perlu berjalan
sebelum Pod lainnya.
4.2.6 - Garbage Collection
Peran daripada garbage collector Kubernetes adalah untuk menghapus objek tertentu yang sebelumnya mempunyai pemilik, tetapi tidak lagi mempunyai pemilik.
Pemilik dan dependen
Beberapa objek Kubernetes adalah pemilik dari objek lainnya. Sebagai contoh, sebuah ReplicaSet adalah pemilik dari sekumpulan Pod. Objek-objek yang dimiliki disebut dependen dari objek pemilik. Setiap objek dependen memiliki sebuah kolom metadata.ownerReferences yang menunjuk ke objek pemilik.
Terkadang, Kubernetes menentukan nilai dari ownerReference secara otomatis. Sebagai contoh, ketika kamu membuat sebuah ReplicaSet, Kubernetes secara otomatis akan menentukan tiap kolom ownerReference dari tiap Pod di dalam ReplicaSet. Pada versi 1.8, Kubernetes secara otomatis menentukan nilai dari ownerReference untuk objek yang diciptakan atau diadopsi oleh ReplicationController, ReplicaSet, StatefulSet, DaemonSet, Deployment, Job dan CronJob.
Kamu juga bisa menspesifikasikan hubungan antara pemilik dan dependen dengan cara menentukan kolom ownerReference secara manual.
Berikut adalah berkas untuk sebuah ReplicaSet yang memiliki tiga Pod:
Referensi pemilik lintas namespace tidak diperbolehkan oleh desain. Artinya:
Dependen dengan cakupan namespace hanya bisa menspesifikasikan pemilik jika berada di namespace yang sama, dan pemilik memiliki cakupan klaster.
Dependen dengan cakupan klaster hanya bisa menspesifikasikan pemilik yang memiliki cakupan klaster, tetapi tidak berlaku untuk pemilik yang memiliki cakupan klaster.
Ketika kamu menghapus sebuah objek, kamu bisa menspesifikasi apakah dependen objek tersebut juga dihapus secara otomatis. Menghapus dependen secara otomatis disebut cascading deletion. Cascading deletion memiliki dua mode: background dan foreground.
Foreground cascading deletion
Pada foreground cascading deletion, pertama objek utama akan memasuki keadaan "deletion in progress". Pada saat keadaan "deletion in progress", kondisi-kondisi berikut bernilai benar:
Objek masih terlihat via REST API
deletionTimestamp objek telah ditentukan
metadata.finalizers objek memiliki nilai foregroundDeletion.
Ketika dalam keadaan "deletion in progress", garbage collector menghapus dependen dari objek. Ketika garbage collector telah menghapus semua "blocking" dependen (objek dengan ownerReference.blockOwnerDeleteion=true), garbage collector menghapus objek pemilik.
Jika kolom ownerReferences sebuah objek ditentukan oleh sebuah controller (seperti Deployment atau Replicaset), blockOwnerDeletion akan ditentukan secara otomatis dan kamu tidak perlu memodifikasi kolom ini secara manual.
Background cascading deletion
Pada background cascading deletion, Kubernetes segera menghapus objek pemilik dan garbage collector kemudian menghapus dependen pada background.
Mengatur kebijakan cascading deletion
Untuk mengatur kebijakan cascading deletion, tambahkan kolom propagationPolicy pada argumen deleteOptions ketika menghapus sebuah Object. Nilai yang dapat digunakan adalah "Orphan", "Foreground", atau "Background".
Sebelum Kubernetes 1.9, kebijakan default dari garbage collection untuk banyak resource controller adalah orphan. Ini meliputi ReplicationController, ReplicaSet, StatefulSet, DaemonSet, dan Deployment. Untuk jenis pada kelompok versi extensions/v1beta1, apps/v1beta1, dan apps/v1beta2, kecuali kamu menspesifikasikan dengan cara lain, objek dependen adalah orphan secara default. Pada Kubernetes 1.9, untuk semua jenis pada kelompok versi apps/v1, objek dependen dihapus secara default.
Berikut sebuah contoh yang menghapus dependen di background:
kubectl juga mendukung cascading deletion. Untuk menghapus dependen secara otomatis dengan menggunakan kubectl, Ubah nilai --cascade menjadi true. Untuk orphan yang dependen, ubah nilai --cascade menjadi false. Nilai default untuk --cascade adalah true.
Berikut adalah contoh yang membuat dependen ReplicaSet menjadi orphan:
Sebelum versi 1.7, ketika menggunakan cascading delete dengan Deployment, kamu harus menggunakan propagationPolicy: Foreground untuk menghapus tidak hanya ReplicaSet yang telah diciptakan, tetapi juga Pod yang mereka miliki. Jika tipe propagationPolicy tidak digunakan, hanya ReplicaSet yag akan dihapus, dan Pod akan menjadi orphan. Lihat kubeadm/#149 untuk informasi lebih lanjut.
4.2.7 - Pengendali TTL untuk Sumber Daya yang Telah Selesai Digunakan
FEATURE STATE:Kubernetes v1.12 [alpha]
Pengendali TTL menyediakan mekanisme TTL yang membatasi umur dari suatu
objek sumber daya yang telah selesai digunakan. Pengendali TTL untuk saat ini hanya menangani
Jobs,
dan nantinya bisa saja digunakan untuk sumber daya lain yang telah selesai digunakan
misalnya saja Pod atau sumber daya khusus (custom resource) lainnya.
Peringatan Fitur Alpha: fitur ini tergolong datam fitur alpha dan dapat diaktifkan dengan
feature gateTTLAfterFinished.
Pengendali TTL
Pengendali TTL untuk saat ini hanya mendukung Job. Sebuah operator klaster
dapat menggunakan fitur ini untuk membersihkan Job yang telah dieksekusi (baik
Complete atau Failed) secara otomatis dengan menentukan field.spec.ttlSecondsAfterFinished pada Job, seperti yang tertera di
contoh.
Pengendali TTL akan berasumsi bahwa sebuah sumber daya dapat dihapus apabila
TTL dari sumber daya tersebut telah habis. Proses dihapusnya sumber daya ini
dilakukan secara berantai, dimana sumber daya lain yang
berkaitan akan ikut terhapus. Perhatikan bahwa ketika sebuah sumber daya dihapus,
siklus hidup yang ada akan menjaga bahwa finalizer akan tetap dijalankan sebagaimana mestinya.
Waktu TTL dalam detik dapat diatur kapan pun. Terdapat beberapa contoh untuk mengaktifkan field.spec.ttlSecondsAfterFinished pada suatu Job:
Spesifikasikan field ini pada manifest sumber daya, sehingga Job akan
dihapus secara otomatis beberapa saat setelah selesai dieksekusi.
Aktifkan field ini pada sumber daya yang sudah selesai dieksekusi untuk
menerapkan fitur ini.
Gunakan sebuah
mengubah (mutating) _admission)
untuk mengaktifkan field ini secara dinamis pada saat pembuatan sumber daya.
Administrator klaster dapat menggunakan hal ini untuk menjamin kebijakan (policy) TTL pada
sumber daya yang telah selesai digunakan.
Gunakan sebuah
mengubah (mutating) _admission
untuk mengaktifkan field ini secara dinamis setelah sumber daya
selesai digunakan dan TTL didefinisikan sesuai dengan status, label, atau hal lain
yang diinginkan.
Peringatan
Mengubah TTL Detik
Perhatikan bahwa periode TTL, yaitu field.spec.ttlSecondsAfterFinished pada Job,
dapat dimodifikasi baik setelah sumber daya dibuat atau setelah selesai digunakan.
Meskipun begitu, setelah Job dapat dihapus (TTL sudah habis), sistem tidak akan
menjamin Job tersebut akan tetap ada, meskipun nilai TTL berhasil diubah.
Time Skew
Karena pengendali TTL menggunakan cap waktu (timestamp) yang disimpan di sumber daya
Kubernetes untuk menentukan apakah TTL sudah habis atau belum, fitur ini tidak sensitif
terhadap time skew yang ada pada klaster dan bisa saja menghapus objek pada waktu yang salah
bagi objek tersebut akibat adanya time skew.
Pada Kubernetes, NTP haruslah dilakukan pada semua node untuk mecegah adanya time skew
(lihat #6159).
Clock tidak akan selalu tepat, meskipun begitu perbedaan yang ada haruslah diminimalisasi.
Perhatikan bahwa hal ini dapat terjadi apabila TTL diaktifkan dengan nilai selain 0.
Sebuah Job membuat satu atau beberapa Pod dan menjamin bahwa jumlah Pod yang telah dispesifikasikan sebelumnya
berhasil dijalankan. Pada saat Pod telah dihentikan, Job akan menandainya sebagai Job yang sudah berhasil dijalankan.
Ketika jumlah sukses yang dispesifikasikan sebelumnya sudah terpenuhi, maka Job tersebut dianggap selesai.
Menghapus sebuah Job akan menghapus semua Pod yang dibuat oleh Job tersebut.
Sebuah kasus sederhana yang dapat diberikan adalah membuat sebuah objek Job untuk menjamin
sebuah Pod dijalankan hingga selesai. Objek Job ini akan membuat sebuah Pod baru apabila
Pod pertama gagal atau dihapus (salah satu contohnya adalah akibat adanya kegagalan pada
perangkat keras atau terjadinya reboot pada Node).
Kamu juga dapat menggunakan Job untuk menjalankan beberapa Pod secara paralel.
Menjalankan Contoh Job
Berikut merupakan contoh konfigurasi Job. Job ini melakukan komputasi π hingga
digit ke 2000 kemudian memberikan hasilnya sebagai keluaran. Job tersebut memerlukan
waktu 10 detik untuk dapat diselesaikan.
Untuk melihat Pod yang sudah selesai dari sebuah Job, kamu dapat menggunakan perintah kubectl get pods.
Untuk menampilkan semua Pod yang merupakan bagian dari suatu Job di mesin kamu dalam bentuk
yang mudah dipahami, kamu dapat menggunakan perintah berikut ini:
pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath='{.items[*].metadata.name}')echo$pods
pi-aiw0a
Disini, selektor yang ada merupakan selektor yang sama dengan yang ada pada Job.
Opsi --output=jsonpath menspesifikasikan bahwa ekspresi yang hanya
menampilkan nama dari setiap Pod pada list yang dikembalikan.
Untuk melihat keluaran standar dari salah satu pod:
Field.spec.template merupakan satu-satunya field wajib pada .spec.
Field.spec.template merupakan sebuah templat Pod. Field ini memiliki skema yang sama dengan yang ada pada Pod,
kecuali field ini bersifat nested dan tidak memiliki fieldapiVersion atau fieldkind.
Sebagai tambahan dari field wajib pada sebuah Job, sebuah tempat pod pada Job
haruslah menspesifikasikan label yang sesuai (perhatikan selektor pod)
dan sebuah mekanisme restart yang sesuai.
Hanya sebuah RestartPolicy yang sesuai dengan Never atau OnFailure yang bersifat valid.
Selektor Pod
Field.spec.selector bersifat opsional. Dan dalam sebagian besar kasus, kamu tidak perlu memberikan
spesifikasi untuk hal ini. Perhatikan bagian menspesifikasikan selektor Pod kamu sendiri.
Job Paralel
Terdapat tiga jenis utama dari task yang sesuai untuk dijalankan sebagai sebuah Job:
Job non-paralel
secara umum, hanya sebuah Pod yang dimulai, kecuali jika Pod tersebut gagal.
Job akan dianggap sudah selesai dikerjakan apabila Pod dari Job tersebut sudah selesai dijalankan dan mengalami terminasi dengan status sukses.
Job paralel dengan jumlah nilai penyelesaian tetap:
berikan spesifikasi pada .spec.completions dengan nilai non-negatif.
Job yang ada merupakan representasi dari task yang dikerjakan, dan akan dianggap selesai apabila terdapat lebih dari satu Pod yang sukses untuk setiap nilai yang ada dalam jangkauan 1 hingga .spec.completions.
belum diimplementasikan saat ini: Setiap Pod diberikan nilai indeks yang berbeda di dalam jangkauan 1 hingga .spec.completions.
Job paralel dengan sebuah work queue:
jangan berikan spesifikasi pada .spec.completions, nilai default-nya merupakan .spec.parallelism.
Pod yang ada haruslah dapat berkoordinasi satu sama lain atau dengan Service eksternal lain untuk menentukan apa yang setiap Pod tadi perlu lakukan. Sebagai contohnya, sebuah Pod bisa saja melakukan fetch job batch hingga N kali pada work queue
setiap Pod secara independen mampu menentukan apakah Pod lainnya telah menyelesaikan tugasnya dengan baik atau belum, dengan kata lain suatu Job telah dikatakan selesai
ketika Pod mana pun dari sebuah Job berhenti dalam keadaan sukses, maka tidak ada Pod lain yang akan dibuat untuk Job tersebut.
apabila salah satu Pod sudah dihentikan sekali dalam keadaan sukses, maka Job akan ditandai sebagai sukses.
apabila sebuah Pod sudah dihentikan dalam keadaan sukses, tidak boleh ada Pod lain yang mengerjakan task tersebut. Dengan kata lain, semua Pod tersebut haruslah dalam keadaan akan dihentikan.
Untuk sebuah Job yang non-paralel, kamu tidak perlu menspesifikasikan field.spec.completions dan .spec.parallelism. Ketika kedua field tersebut
dalam keadaan tidak dispesifikasikan, maka nilai defult-nya akan diubah menjadi 1.
Untuk sebuah Job dengan jumlah nilai penyelesaian tetap, kamu harus memberikan spesifikasi nilai
dari .spec.completions dengan nilai yang diinginkan. Kamu dapat menspesifikasikan .spec.parallelism,
atau jika kamu tidak melakukannya nilai dari field ini akan memiliki nilai default 1.
Untuk sebuah Job work queue, kamu harus meninggalkan spesifikasi field.spec.completions menjadi kosong, serta
memberikan nilai pada .spec.parallelism menjadi sebuah bilangan bulat non negatif.
Untuk informasi lebih lanjut mengenai bagaimana menggunakan Job dengan jenis yang berbeda, kamu
dapat melihat bagian pola job.
Mengendalikan Paralelisme
Paralelisme yang diminta (.spec.parallelism) dapat diaktifkan dengan cara
memberikan nilai bilangan bulat non-negatif. Jika tidak dispesifikasikan maka nilainya akan
secara default yaitu 1. Jika dispesifikasikan sebagai 0, maka Job akan secara otomatis dihentikan sementara
hingga nilainya dinaikkan.
Paralelisme yang sebenarnya (jumlah Pod yang dijalankan pada satu waktu tertentu)
bisa saja lebih atau kurang dari nilai yang diharapkan karena adanya alasan berikut:
Untuk Job fixed completion count, nilai sebenarnya dari jumlah Pod yang dijalankan secara paralel tidak akan melebihi jumlah completion yang tersisa. Nilai yang lebih tinggi dari .spec.parallelism secara efektif, akan diabaikan.
Untuk Job work queue, tidak akan ada Pod yang dimulai setelah ada Pod yang berhasil -- meskipun begitu, sisa Pod yang ada akan diizinkan untuk menyelesaikan tugasnya.
Jika sebuah Pengontrol Job tidak memiliki waktu untuk memberikan reaksi.
Jika sebuah controller Job gagal membuat Pod dengan alasan apa pun (kurangnya ResourceQuota, kurangnya permission, dkk.),
maka bisa saja terdapat lebih sedikit Pod dari yang diminta.
Jika controller Job melakukan throttle pembuatan Pod karena terdapat gagalnya pembuatan Pod yang berlebihan sebelumnya pada Job yang sama.
Ketika sebuah Pod dihentikan secara graceful, maka Pod tersebut akan membutuhkan waktu untuk berhenti.
Mengatasi Kegagalan Pod dan Container
Sebuah Container pada sebuah Pod bisa saja mengalami kegagalan karena berbagai alasan
yang berbeda, misalnya saja karena proses yang ada di dalamnya berakhir dengan exit code
yang tidak sama dengan nol, atau Container yang ada di-kill karena menyalahi batasan memori, dkk.
Jika hal ini terjadi, dan .spec.template.spec.restartPolicy = "OnFailure", maka Pod
akan tetap ada di dalam node, tetapi Container tersebut akan dijalankan kembali. Dengan demikian,
program kamu harus dapat mengatasi kasus dimana program tersebut di-restart secara lokal, atau jika
tidak maka spesifikasikan .spec.template.spec.restartPolicy = "Never". Perhatikan
lifecycle pod untuk informasi lebih lanjut mengenai restartPolicy.
Sebuah Pod juga dapat gagal secara menyeluruh, untuk beberapa alasan yang mungkin, misalnya saja,
ketika Pod tersebut dipindahkan dari Node (ketika Node diperbarui, di-restart, dihapus, dsb.), atau
jika sebuah Container dalam Pod gagal dan .spec.template.spec.restartPolicy = "Never". Ketika
sebuah Pod gagal, maka controller Job akan membuat sebuah Pod baru. Ini berarti aplikasi kamu haruslah
bisa mengatasi kasus dimana aplikasimu dimulai pada Pod yang baru. Secara khusus apabila aplikasi kamu
berurusan dengan berkas temporer, locks, keluaran yang tak lengkap dan hal-hal terkait dengan
program yang dijalankan sebelumnya.
Perhatikan bahwa bahakan apabila kamu menspesifikasikan .spec.parallelism = 1 dan .spec.completions = 1 dan
.spec.template.spec.restartPolicy = "Never", program yang sama bisa saja tetap dijalankan lebih dari sekali.
Jika kamu menspesifikasikan .spec.parallelism dan .spec.completions dengan nilai yang lebih besar dari 1,
maka bisa saja terdapat keadaan dimana terdapat beberapa Pod yang dijalankan pada waktu yang sama.
Dengan demikian, Pod kamu haruslah fleksibel terhadap adanya konkurensi.
Mekanisme Kebijakan Backoff apabila Terjadi Kegagalan
Terdapat situasi dimana kamu ingin membuat suatu Job gagal
setelah dijalankan mekanisme retry beberapa kali akibat adanya kesalahan pada konfigurasi
dsb. Untuk melakukan hal tersebut, spesifikasikan .spec.backoffLimit dengan nilai retry yang diinginkan
sebelum menerjemahkan Job dalam keadaan gagal. Secara default, nilai dari field tersebut adalah 6.
Pod yang gagal dijalankan dan terkait dengan suatu Job tertentu akan dibuat kembali oleh
controller Job dengan delayback-off eksponensial (10 detik, 20 detik, 40 detik ...)
yang dibatasi pada 6 menit. Penghitungan back-off akan diulang jika tidak terdapat Pod baru yang gagal
sebelum siklus pengecekan status Job selanjutnya.
Catatan: Isu #54870 masih ada untuk versi Kubernetes sebelum 1.12.
Catatan: Jika Job yang kamu miliki memiliki restartPolicy = "OnFailure", perhatikan bahwa Container kamu yang menjalankan
Job tersebut akan dihentikan ketika limit back-off telah dicapai. Hal ini akan membuat proses debugging semakin sulit.
Dengan demikian, kami memberikan saran untuk menspesifikasikan restartPolicy = "Never" ketika melakukan
proses debugging atau menggunakan mekanisme logging untuk menjamin keluaran
dari Job yang gagal agar tidak terus menerus hilang.
Terminasi dan Clean Up Job
Ketika sebuah Job selesai dijalankan, tidak akan ada lagi Pod yang dibuat,
meskipun begitu Pod yang ada juga tidak akan dihapus. Dengan demikian kamu masih bisa mengakses log
yang ada dari Pod yang sudah dalam status complete untuk mengecek apabila terjadi eror, warning, atau hal-hal
yang dapat digunakan untuk proses pelaporan dan identifikasi. Objek Job itu sendiri akan tetap ada,
sehingga kamu tetap bisa melihat statusnya. Penghapusan objek akan diserahkan sepenuhnya pada pengguna
apabila Job tidak lagi digunakan. Penghapusan Job dengan perintah kubectl (misalnya, kubectl delete jobs/pi atau kubectl delete -f ./job.yaml).
Ketika kamu menghapus Job menggunakan perintah kubectl, semua Pod yang terkait dengan Job tersebut akan ikut dihapus.
Secara default, sebuah Job akan dijalankan tanpa adanya interupsi kecuali terdapat Pod yang gagal, (restartPolicy=Never) atau terdapat
Container yang dihentikan dalam kondisi error (restartPolicy=OnFailure), suatu keadaan dimana Job akan dijalankan dengan mekanisme
yang dijelaskan di atas berdasarkan pada .spec.backoffLimit.
Apabila .spec.backoffLimit telah mencapai limit, maka Job akan ditandai sebagai gagal dan Pod yang saat ini sedang dijalankan juga akan dihentikan.
Cara lain untuk menghentikan sebuah Job adalah dengan mengatur deadline aktif.
Untuk melakukannya kamu dapat menspesifikasikan field.spec.activeDeadlineSeconds
dari sebuah Job dengan suatu angka dalam satuan detik. FieldactiveDeadlineSeconds
diterapkan pada durasi dari sebuah Job, tidak peduli seberapa banyak Pod yang dibuat.
Setelah sebuah Job mencapai limit activeDeadlineSeconds, semua Pod yang dijalankan akan dihentikan
dan status dari Job tersebut akan berubah menjadi type: Failed dengan reason: DeadlineExceeded.
Perhatikan bahwa field.spec.activeDeadlineSeconds pada Job memiliki tingkat
presedensi di atas .spec.backoffLimit. Dengan demikian, sebuah Job
yang sedang mencoba melakukan restart pada suatu Pod-nya tidak akan melakukan
pembuatan Pod yang baru apabila Job tersebut telah mencapai limit yang didefinisikan pada
activeDeadlineSeconds, bahkan apabila nilai dari backoffLimit belum tercapai.
Perhatikan bahwa baik spek Job dan spek templat Pod di dalam Job memiliki fieldactiveDeadlineSeconds.
Pastikan kamu telah menspesifikasikan nilai tersebut pada level yang dibutuhkan.
Mekanisme Clean Up Otomatis pada Job yang Sudah Selesai
Job yang sudah selesai biasanya tidak lagi dibutuhkan di dalam sistem. Tetap menjaga keberadaan
objek-objek tersebut di dalam sistem akan memberikan tekanan tambahan pada API server. Jika sebuah Job
yang diatur secara langsung oleh controller dengan level yang lebih tinggi, seperti
CronJob, maka Job ini dapat
di-clean up oleh CronJob berdasarkan policy berbasis kapasitas yang dispesifikasikan.
Mekanisme TTL untuk Job yang Telah Selesai Dijalankan
FEATURE STATE:Kubernetes v1.12 [alpha]
Salah satu cara untuk melakukan clean up Job yang telah selesai dijalankan
(baik dengan status Complete atau Failed) secara otomatis adalah dengan
menerapkan mekanisme TTL yang disediakan oleh
controller TTL untuk
sumber daya yang telah selesai digunakan, dengan cara menspesifikasikan
field.spec.ttlSecondsAfterFinished dari Job tersebut.
Ketika controller TTL melakukan proses clean up pada Job,
maka controller tersebut akan menghapus objek-objek terkait seperti Pod, serta Job itu sendiri.
Perhatikan bahwa ketika suatu Job dihapus, maka lifecycle-nya akan menjamin, mekanisme
finalizer yang ada akan tetap dihargai.
Job pi-with-ttl akan dihapus secara otomatis, dalam jangka waktu 100
detik setelah Job tersebut selesai dijalankan.
Jika field ini dispesifikasikan sebagai 0, maka Job akan secara otomatis dihapus
segera setelah Job tersebut selesai dijalankan. Jika field tersebut tidak dispesifikasikan,
maka Job ini tidak akan dihapus oleh controller TTL setelah Job ini selesai dijalankan.
Perhatikan bahwa mekanisme TTL ini merupakan fitur alpha, dengan gerbang fitur TTLAfterFinished.
Untuk informasi lebih lanjut, kamu dapat membaca dokumentasi untuk
controller TTL untuk
sumber daya yang telah selesai dijalankan.
Pola Job
Sebuah objek Job dapat digunakan untuk mendukung eksekusi paralel yang dapat diandalkan pada Pod.
Objek Job tidak di-desain untuk mendukung proses paralel bersifat closely-communicating,
seperti yang secara umum ditemukan dalam komputasi ilmiah. Meskipun begitu objek ini mendukung
set work item yang independen namun saling terkait satu sama lainnya. Ini termasuk surel yang harus dikirim,
frame yang harus di-render, berkas yang harus di-transcoded, jangkauan key yang ada
di dalam basis data NoSQL, dsb.
Pada suatu sistem yang kompleks, terdapat beberapa set work item yang berbeda.
Di sini, kami hanya mempertimbangkan work item yang ingin digunakan oleh pengguna
untuk melakukan manajemen secara bersamaan — sebuah batch job.
Terdapat beberapa perbedaan pola pada komputasi paralel,
setiap pola memiliki kelebihan dan kekurangannya masing-masing. Kekurangan dan kelebihan ini
dijabarkan sebagai berikut:
Satu objek Job untuk setiap work item, atau sebuah Job untuk semua work item. Pilihan kedua akan lebih baik apabila digunakan untuk jumlah work item yang lebih besar.
Sementara itu, pilihan pertama akan mengakibatkan overhead bagi pengguna dan juga sistem
untuk mengaur jumlah objek Job yang cukup banyak.
Jumlah Pod yang dibuat sesuai dengan jumlah work item atau setiap Pod dapat memproses beberapa work item sekaligus.
Pilihan pertama secara umum memerlukan modifikasi lebih sedikit untuk kode dan Container yang suda ada. Pilihan kedua
akan lebih baik jika digunakan untuk jumlah work item yang lebih banyak, untuk alasan yang sama dengan poin sebelumnya.
Beberapa pendekatan menggunakan prinsip work queue. Hal ini membutuhkan sebuah service queue yang dijalankan,
serta modifikasi untuk program atau Container yang sudah ada untuk mengizinkannya menggunakan working queue.
Pendekatan lain akan lebih mudah untuk digunakan bagi aplikasi yang sudah ada.
Tradeoff yang dirangkum di sini, dengan kolom 2 dan 4 berkaitan dengan tradeoff yang dijelaskan di atas.
Nama dari pola yang ada juga terkait dengan contoh dan deskripsi lebih lanjut.
Ketika kamu menspesifikasikan completion dengan .spec.completions, setiap Pod yang dibuat oleh controller Job
memiliki spec yang identik. Artinya
semua Pod untuk sebuah task akan memiliki perintah yang sama serta image, volume, serta variabel environment yang (hampir) sama.
Pola ini merupakan salah satu cara berbeda yang diterapkan untuk mengatur Pod agar dapat bekerja untuk hal yang berbeda-beda.
Tabel ini menunjukkan pengaturan yang dibutuhkan untuk .spec.parallelism dan .spec.completions bagi setiap pola.
Disini, W merupakan jumlah dari work item.
Secara umum, ketika kamu membuat sebuah objek Job, kamu
tidak menspesifikasikan .spec.selector. Sistem akan memberikan nilai
default pada field ini ketika Job dibuat. Sistem akan memilih nilai dari selektor yang ada
dan memastikan nilainya tidak akan beririsan dengan Job lainnya.
Meskipun demikian, pada beberapa kasus, kamu bisa saja memiliki kebutuhan untuk meng-override
nilai dari selektor ini. Untuk melakukannya, kamu dapat menspesifikasikan .spec.selector
dari Job.
Berhati-hatilah ketika kamu melakukan proses ini. Jika kamu menspesifikasikan sebuah label
selektor yang tidak unik pada Pod yang ada di dalam Job tersebut, serta sesuai dengan Pod yang tidak
terkait dengan Job tadi, maka Pod dari Job yang tidak terkait dengan Job tadi akna dihapus, atau Job ini
akan menghitung completion dari Pod lain sebagai tolak ukur suksesnya Job tersebut, atau bisa saja salah satu
atau kedua Job tidak dapat membuat Pod baru yang digunakan untuk menyelesaikan Job tersebut.
Jika selektor yang tidak unik dipilih, maka controller lain (misalnya ReplicationController) dan Pod
yang ada di dalamnya bisa saja memiliki perilaku yang tidak dapat diprediksi. Kubernetes tidak akan
mencegah kemungkinan terjadinya hal ini ketika kamu menspesifikasikan nilai .spec.selector.
Berikut merupakan contoh skenario dimana kamu ingin menggunakan fitur ini.
Misalnya saja Job dengan nama old sudah dijalankan.
Dan kamu ingin Pod yang sudah dijalankan untuk tetap berada pada state tersebut,
tapi kamu juga ingin Pod selanjutnya yang dibuat untuk menggunakan templat Pod yang berbeda dan agar
Job tersebut memiliki nama yang berbeda. Kamu tidak dapat mengubah Job karena field ini
merupakan nilai yang tidak bisa diubah. Dengan demikian, kamu menghapus Job old
tetapi tetap membiarkan Pod yang ada untuk jalan, menggunakan perintah kubectl delete jobs/old --cascade=false.
Sebelum menghapus Job tadi, kamu mencatat selektor yang digunakan oleh Job tadi:
Kemudian kamu membuat sebuah Job baru dengan nama new
dan kamu secara eksplisit menspesifikasikan selektor yang sama.
Karena Pod dengan selektor yang sama memiliki label controller-uid=a8f3d00d-c6d2-11e5-9f87-42010af00002,
maka Pod-Pod lama tadi dikendalikan juga oleh Job new.
Kamu harus menspesifikasikan manualSelector: true pada Job yang baru
karena kamu tidak menggunakan selektor yang diberikan secara default oleh sistem.
Job yang baru tadi kemudian akan memiliki uid yang berbeda dari a8f3d00d-c6d2-11e5-9f87-42010af00002. Pengaturan
manualSelector: true memberikan perintah pada sistem bahwa kamu mengetahui apa yang kamu lakukan
dan untuk mengizikan ketidaksesuaian ini untuk terjadi.
Alternatif
Pod Polosan
Ketika node dimana Pod dijalankan berada dalam kondisi reboot atau gagal, Pod tadi akan dihentikan
dan tidak akan di-restart. Meskipun demikian, sebuah Job akan membuat Pod baru yang menggantikan
Pod lama yang dihentikan. Untuk alasan inilah, kami memberikan rekomendasi agar kamu menggunakan sebuah Job dibandingkan dengan
Pod yang biasa, bahkan jika aplikasi yang kamu gunakan hanya memerlukan sebuah Pod.
Replication Controller
Job merupakan komplemen dari Replication Controller.
Sebuah Replication Controller mengatur Pod yang diharapkan untuk tidak dihentikan (misalnya, web server), dan sebuah Job
mengatur Pod yang diharapkan untuk berhenti (misalnya, batch task).
Seperti yang sudah dibahas pada Lifecycle Pod, Jobhanya pantas
digunakan untuk Pod dengan RestartPolicy yang sama dengan OnFailure atau Never.
(Perhatikan bahwa: Jika RestartPolicy tidak dispesifikasikan, nilai defaultnya adalah Always.)
Job Tunggal akan menginisiasi Kontroller Pod
Pola lain yang mungkin diterapkan adalah untuk sebuah Job tunggal untuk membuat
sebuah Pod yang kemudian akan membuat Pod lainnya, bersifat selayaknya controller kustom
bagi Pod tersebut. Hal ini mengizinkan fleksibilitas optimal, tetapi cukup kompleks untuk digunakan
dan memiliki integrasi terbatas dengan Kubernetes.
Salah satu contoh dari pola ini adalah sebuah Job yang akan menginisiasi sebuah Pod
yang menjalankan script yang kemudian akan
menjalankan controller master Spark (kamu dapat melihatnya di contoh Spark),
yang menjalankan driver Spark, dan kemudian melakukan mekanisme clean up.
Keuntungan dari pendekatan ini adalah proses keseluruhan yang memiliki jaminan completion
dari sebuah Job, tetapi kontrol secara mutlak atas Pod yang dibuat serta tugas yang diberikan pada Pod tersebut.
CronJob
Kamu dapat menggunakan CronJob untuk membuat Job yang akan
dijalankan pada waktu/tanggal yang spesifik, mirip dengan perangkat lunak cron yang ada pada Unix.
4.2.9 - CronJob
Suatu CronJob menciptakan Job yang dijadwalkan berdasarkan waktu tertentu.
Satu objek CronJob sepadan dengan satu baris pada filecrontab (cron table). CronJob tersebut menjalankan suatu pekerjaan secara berkala
pada waktu tertentu, dituliskan dalam format Cron.
Catatan: Seluruh waktu schedule: pada CronJob mengikuti zona waktu dari master di mana Job diinisiasi.
Suatu cron job menciptakan kurang lebih satu objek Job setiap penjadwalan. Istilah yang digunakan adalah "kurang lebih" karena
terdapat beberapa kasus yang menyebabkan dua Job terbuat, atau tidak ada Job sama sekali yang terbuat. Kemungkinan-kemungkinan
seperti itu memang diusahakan untuk tidak sering terjadi, tapi tidak ada jaminan kemungkinan-kemungkinan tersebut tidak akan pernah terjadi.
Oleh karena itu, Job sudah sepantasnya memiliki sifat idempoten.
Jika pengaturan startingDeadlineSeconds menggunakan nilai yang besar atau tidak diatur (menggunakan nilai default)
dan jika pengaturan concurrencyPolicy dijadikan Allow, Job yang terbuat akan dijalankan paling tidak satu kali.
CronJob controller memeriksa berapa banyak jadwal yang terlewatkan sejak waktu terakhir eksekusi hingga saat ini. Jika terdapat lebih dari 100 jadwal yang terlewat, maka CronJob controller tidak memulai Job dan mencatat kesalahan:
Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew.
Perlu diingat bahwa jika pengaturan startingDeadlineSeconds memiliki suatu nilai (bukan nil), CronJob controller akan menghitung berapa banyak Job yang terlewatkan dari sejak startingDeadlineSeconds hingga sekarang dan bukan sejak waktu terakhir eksekusi. Misalnya: Jika startingDeadlineSeconds memiliki nilai 200, CronJob controller akan menghitung berapa banyak Job yang terlewatkan dalam 200 detik terakhir.
Suatu CronJob dianggap terlewat jika ia gagal diciptakan pada waktu yang semestinya. Misalnya: Jika pengaturan concurrencyPolicy dijadikan Forbid
dan suatu CronJob dicoba dijadwalkan saat masih ada penjadwalan sebelumnya yang masih berjalan, maka ia akan dianggap terlewat.
Contoh: Suatu CronJob akan menjadwalkan Job baru tiap satu menit dimulai sejak 08:30:00, dan startingDeadlineSeconds tidak diatur.
Jika CronJob controller tidak aktif dari 08:29:00 sampai 10:21:00, Job tidak akan dijalankan karena jumlah Job yang terlewat
sudah lebih dari 100.
Sebagai ilustrasi lebih lanjut, misalkan suatu CronJob diatur untuk menjadwalkan Job baru setiap satu menit dimulai sejak 08:30:00,
dan startingDeadlineSeconds memiliki nilai 200. Jika CronJob controller tidak aktif seperti pada contoh sebelumnya (08:29:00 sampai 10:21:00),
Job akan tetap dijalankan pada 10:22:00. Hal ini terjadi karena CronJob controller memeriksa banyaknya jadwal yang terlewatkan pada 200 detik terakhir
(dalam kasus ini: 3 jadwal terlewat), dan bukan dari sejak waktu eksekusi terakhir.
CronJob hanya bertanggung-jawab untuk menciptakan Job yang sesuai dengan jadwalnya sendiri,
dan Job tersebut bertanggung jawab terhadap pengelolaan Pod yang direpresentasikan olehnya.
5 - Services, Load Balancing, dan Jaringan
5.1 - Service
Pod pada Kubernetes bersifat mortal.
Artinya apabila pod-pod tersebut dibuat dan kemudian mati, pod-pod tersebut
tidak akan dihidupkan kembali. ReplicaSets secara
khusus bertugas membuat dan menghapus Pod secara dinamis (misalnya, pada proses scaling out atau scaling in).
Meskipun setiap Pod memiliki alamat IP-nya masing-masing, kamu tidak dapat mengandalkan alamat IP
yang diberikan pada pod-pod tersebut, karena alamat IP yang diberikan tidak stabil.
Hal ini kemudian menimbulkan pertanyaan baru: apabila sebuah sekumpulan Pod (yang selanjutnya kita sebut backend)
menyediakan service bagi sebuah sekumpulan Pod lain (yang selanjutnya kita sebut frontend) di dalam
klaster Kubernetes, bagaimana cara frontend menemukan backend mana yang digunakan?
Inilah alasan kenapa Service ada.
Sebuah Service pada Kubernetes adalah sebuah abstraksi yang memberikan definisi
set logis yang terdiri beberapa Pod serta policy bagaimana cara kamu mengakses sekumpulan Pod tadi - seringkali disebut sebagai microservices.
Set Pod yang dirujuk oleh suatu Service (biasanya) ditentukan oleh sebuah Label Selector
(lihat penjelasan di bawah untuk mengetahui alasan kenapa kamu mungkin saja membutuhkan Service tanpa
sebuah selector).
Sebagai contoh, misalnya terdapat sebuah backend yang menyediakan fungsionalitas image-processing
yang memiliki 3 buah replica. Replica-replica tadi sifatnya sepadan - dengan kata lain frontend
tidak peduli backend manakah yang digunakan. Meskipun Pod penyusun sekumpulan backend bisa berubah,
frontend tidak perlu peduli bagaimana proses ini dijalankan atau menyimpan list dari backend-backend
yang ada saat itu. Service memiliki tujuan untuk decouple mekanisme ini.
Untuk aplikasi yang dijalankan di atas Kubernetes, Kubernetes menyediakan API endpoint sederhana
yang terus diubah apabila state sebuah sekumpulan Pod di dalam suatu Service berubah. Untuk
aplikasi non-native, Kubernetes menyediakan bridge yang berbasis virtual-IP bagi Service
yang diarahkan pada Podbackend.
Mendefinisikan sebuah Service
Sebuah Service di Kubernetes adalah sebuah objek REST, layaknya sebuah Pod. Seperti semua
objek REST, definisi Service dapat dikirim dengan method POST pada apiserver untuk membuat
sebuah instans baru. Sebagai contoh, misalnya saja kamu memiliki satu sekumpulan Pod yang mengekspos port
9376 dan memiliki label"app=MyApp".
Spesifikasi ini akan ditranslasikan sebagai sebuah objek Service baru dengan nama "my-service"
dengan target port 9376 pada setiap Pod yang memiliki label"app=MyApp". Service ini
juga akan memiliki alamat IP tersendiri (yang terkadang disebut sebagai "cluster IP"), yang nantinya
akan digunakan oleh service proxy (lihat di bagian bawah). Selector pada Service akan selalu dievaluasi
dan hasilnya akan kembali dikirim dengan menggunakan method POST ke objek Endpoints
yang juga disebut "my-service".
Perhatikan bahwa sebuah Service dapat melakukan pemetaan setiap incoming port pada targetPort
mana pun. Secara default, fieldtargetPort akan memiliki value yang sama dengan value dari fieldport.
Hal menarik lainnya adalah value dari targetPort bisa saja berupa string yang merujuk pada nama
dari port yang didefinisikan pada Podbackend. Nomor port yang diberikan pada port dengan nama
tadi bisa saja memiliki nilai yang berbeda di setiap Podbackend. Hal ini memberikan fleksibilitas
pada saat kamu melakukan deploy atau melakukan perubahan terhadap Service. Misalnya saja suatu saat
kamu ingin mengubah nomor port yang ada pada Podbackend pada rilis selanjutnya tanpa menyebabkan
permasalahan pada sisi klien.
Secara default, protokol yang digunakan pada service adalah TCP, tapi kamu bisa saja menggunakan
protokol yang tersedia. Karena banyak Service memiliki kebutuhan untuk
mengekspos lebih dari sebuah port, Kubernetes menawarkan definisi multipleport pada sebuah objek
Service. Setiap definisi port dapat memiliki protokol yang berbeda.
Service tanpa selector
Secara umum, Service memberikan abstraksi mekanisme yang dilakukan untuk mengakses Pod, tapi
mereka juga melakukan abstraksi bagi backend lainnya. Misalnya saja:
Kamu ingin memiliki sebuah basis data eksternal di environmentproduction tapi pada tahap test,
kamu ingin menggunakan basis datamu sendiri.
Kamu ingin merujuk service kamu pada service lainnya yang berada pada
Namespace yang berbeda atau bahkan klaster yang berbeda.
Kamu melakukan migrasi workloads ke Kubernetes dan beberapa backend yang kamu miliki masih
berada di luar klaster Kubernetes.
Berdasarkan skenario-skenario di atas, kamu dapat membuat sebuah Service tanpa selector:
Karena Service ini tidak memiliki selector, objek Endpoints bagi Service ini tidak akan dibuat.
Dengan demikian, kamu bisa membuat Endpoints yang kamu inginkan:
Catatan: Perhatikan bahwa alamat IP yang kamu buat untuk Endpoints tidak boleh berupa
loopback (127.0.0.0/8), link-local (169.254.0.0/16), atau link-local multicast (224.0.0.0/24).
Alamat IP tersebut juga tidak boleh berupa cluster IP dari Service Kubernetes lainnya,
karena kube-proxy belum menyediakan dukungan IP virtual sebagai destination.
Cara mengakses suatu Service tanpa selector sama saja dengan mengakses suatu Service
dengan selector. Trafik yang ada akan di-route ke Endpoints yang dispesifikasikan oleh
pengguna (dalam contoh kali ini adalah 1.2.3.4:9376).
Sebuah ExternalNameService merupakan kasus spesial dari Service
dimana Service tidak memiliki selector dan menggunakan penamaan DNS. Untuk
informasi lebih lanjut silahkan baca bagian ExternalName.
IP Virtual dan proxyService
Setiap node di klaster Kubernetes menjalankan kube-proxy. kube-proxy
bertanggung jawab terhadap implementasi IP virtual bagi Services dengan tipe
selain ExternalName.
Pada Kubernetes versi v1.0, Services adalah "layer 4" (TCP/UDP pada IP), proxy
yang digunakan murni berada pada userspace. Pada Kubernetes v1.1, API Ingress
ditambahkan untuk merepresentasikan "layer 7"(HTTP), proxyiptables juga ditambahkan
dan menjadi mode operasi default sejak Kubernetes v1.2. Pada Kubernetes v1.8.0-beta.0,
proxyipvs juga ditambahkan.
Mode Proxy: userspace
Pada mode ini, kube-proxy mengamati master Kubernetes apabila terjadi penambahan
atau penghapusan objek Service dan Endpoints. Untuk setiap Service, kube-proxy
akan membuka sebuah port (yang dipilih secara acak) pada node lokal. Koneksi
pada "proxy port" ini akan dihubungkan pada salah satu Podbackend dari Service
(yang tercatat pada Endpoints). Podbackend yang akan digunakan akan diputuskan berdasarkan
SessionAffinity pada Service. Langkah terakhir yang dilakukan oleh kube-proxy
adalah melakukan instalasi rulesiptables yang akan mengarahkan trafik yang ada pada
clusterIP (IP virtual) dan port dari Service serta melakukan redirect trafik ke proxy
yang memproksikan Podbackend. Secara default, mekanisme routing yang dipakai adalah
round robin.
Mode Proxy: iptables
Pada mode ini, kube-proxy mengamati master Kubernetes apabila terjadi penambahan
atau penghapusan objek Service dan Endpoints. Untuk setiap Service,
kube-proxy akan melakukan instalasi rulesiptables yang akan mengarahkan
trafik ke clusterIP (IP virtual) dan port dari Service. Untuk setiap objek Endpoints,
kube-proxy akan melakukan instalasi rulesiptables yang akan memilih satu buah Podbackend. Secara default, pemilihan backend ini dilakukan secara acak.
Tentu saja, iptables yang digunakan tidak boleh melakukan switching
antara userspace dan kernelspace, mekanisme ini harus lebih kokoh dan lebih cepat
dibandingkan dengan userspaceproxy. Meskipun begitu, berbeda dengan mekanisme
proxyuserspace, proxyiptables tidak bisa secara langsung menjalankan mekanisme
retry ke Pod lain apabila Pod yang sudah dipilih sebelumnya tidak memberikan respons,
dengan kata lain hal ini akan sangat bergantung pada
readiness probes.
Mode Proxy: ipvs
FEATURE STATE:Kubernetes v1.9 [beta]
Pada mode ini, kube-proxy mengamati Services dan Endpoints, kemudian memanggil
interfacenetlink untuk membuat rulesipvs yang sesuai serta melakukan sinkronisasi
rulesipvs dengan Services dan Endpoints Kubernetes secara periodik, untuk memastikan
status ipvs konsisten dengan apa yang diharapkan. Ketika sebuah Services diakses,
trafik yang ada akan diarahkan ke salah satu Podbackend.
Sama halnya dengan iptables, ipvs juga berdasarkan pada fungsi hooknetfilter,
bedanya adalah ipvs menggunakan struktur data hash table dan bekerja di kernelspace.
Dengan kata lain ipvs melakukan redirect trafik dengan lebih cepat dan dengan performa yang lebih
baik ketika melakukan sinkronisasi rulesproxy. Selain itu, ipvs juga menyediakan
lebih banyak opsi algoritma load balancing:
rr: round-robin
lc: least connection
dh: destination hashing
sh: source hashing
sed: shortest expected delay
nq: never queue
Catatan: Mode ipvs menggunakan moduleIPVSkernel yang diinstal pada node
sebelum kube-proxy dijalankan. Ketika kube-proxy dijalankan dengan mode proxyipvs,
kube-proxy akan melakukan proses validasi, apakah moduleIPVS sudah diinstal di node,
jika module tersebut belum diinstal, maka kube-proxy akan menggunakan mode iptables.
Dari sekian model proxy yang ada, trafik inbound apa pun yang ada diterima oleh IP:Port pada Service
akan dilanjutkan melalui proxy pada backend yang sesuai, dan klien tidak perlu mengetahui
apa informasi mendetail soal Kubernetes, Service, atau Pod. afinitas session (session affinity) berbasis
Client-IP dapat dipilih dengan cara menerapkan nilai "ClientIP" pada service.spec.sessionAffinity
(nilai default untuk hal ini adalah "None"), kamu juga dapat mengatur nilai maximum sessiontimeout yang ada dengan mengatur opsi service.spec.sessionAffinityConfig.clientIP.timeoutSeconds jika
sebelumnya kamu sudah menerapkan nilai "ClusterIP" pada service.spec.sessionAffinity
(nilai default untuk opsi ini adalah "10800").
Multi-Port Services
Banyak Services dengan kebutuhan untuk mengekspos lebih dari satu port.
Untuk kebutuhan inilah, Kubernetes mendukung multipleportdefinitions pada objek Service.
Ketika menggunakan multipleport, kamu harus memberikan nama pada setiap port yang didefinisikan,
sehingga Endpoint yang dibentuk tidak ambigu. Contoh:
Perhatikan bahwa penamaan port hanya boleh terdiri dari karakter alphanumericlowercase
dan -, serta harus dimulai dan diakhiri dengan karakter alphanumeric, misalnya saja 123-abc dan web
merupakan penamaan yang valid, tapi 123_abc dan -web bukan merupakan penamaan yang valid.
Memilih sendiri alamat IP yang kamu inginkan
Kamu dapat memberikan spesifikasi alamat cluster IP yang kamu inginkan
sebagai bagian dari request pembuatan objek Service. Untuk melakukan hal ini,
kamu harus mengisi fields.spec.clusterIP field. Contoh penggunaannya adalah sebagai berikut,
misalnya saja kamu sudah memiliki entry DNS yang ingin kamu gunakan kembali,
atau sebuah sistem legacy yang sudah diatur pada alamat IP spesifik
dan sulit untuk diubah. Alamat IP yang ingin digunakan pengguna haruslah merupakan alamat IP
yang valid dan berada di dalam rangeCIDRservice-cluster-ip-range yang dispesifikasikan di dalam
penanda yang diberikan apiserver. Jika value yang diberikan tidak valid, apiserver akan
mengembalikan responsecode HTTP 422 yang mengindikasikan value yang diberikan tidak valid.
Mengapa tidak menggunakan DNS round-robin?
Pertanyaan yang selalu muncul adalah kenapa kita menggunakan IP virtual dan bukan
DNS round-robin standar? Terdapat beberapa alasan dibalik semua itu:
Terdapat sejarah panjang dimana library DNS tidak mengikuti TTL DNS dan
melakukan caching hasil dari lookup yang dilakukan.
Banyak aplikasi yang melakukan lookup DNS hanya sekali dan kemudian melakukan cache hasil yang diperoleh.
Bahkan apabila aplikasi dan library melakukan resolusi ulang yang proper, load dari setiap
klien yang melakukan resolusi ulang DNS akan sulit untuk di manage.
Kami berusaha untuk mengurangi ketertarikan pengguna untuk melakukan yang mungkin akan menyusahkan pengguna.
Dengan demikian, apabila terdapat justifikasi yang cukup kuat, kami mungkin saja memberikan implementasi
alternatif yang ada.
Discovering services
Kubernetes mendukung 2 buah mode primer untuk melakukan Service - variabel environment dan DNS.
Variabel Environment
Ketika sebuah Pod dijalankan pada node, kubelet menambahkan seperangkat variabel environment
untuk setiap Service yang aktif. Environment yang didukung adalah Docker links compatible variabel (perhatikan
makeLinkVariables)
dan variabel {SVCNAME}_SERVICE_HOST dan {SVCNAME}_SERVICE_PORT, dinama nama Service akan diubah
menjadi huruf kapital dan tanda minus akan diubah menjadi underscore.
Sebagai contoh, Service"redis-master" yang mengekspos port TCP 6379 serta alamatcluster IP10.0.0.11 akan memiliki environment sebagai berikut:
Hal ini merupakan kebutuhan yang urutannya harus diperhatikan - Service apa pun yang
akan diakses oleh sebuah Pod harus dibuat sebelum Pod tersebut dibuat,
jika tidak variabel environment tidak akan diinisiasi.
Meskipun begitu, DNS tidak memiliki keterbatasan ini.
DNS
Salah satu add-on opsional
(meskipun sangat dianjurkan) adalah server DNS. Server DNS bertugas untuk mengamati apakah
terdapat objek Service baru yang dibuat dan kemudian bertugas menyediakan DNS baru untuk
Service tersebut. Jika DNS ini diaktifkan untuk seluruh klaster, maka semua Pod akan secara otomatis
dapat melakukan resolusi DNS.
Sebagai contoh, apabila kamu memiliki sebuah Service dengan nama "my-service" pada Namespace"my-ns", maka record DNS "my-service.my-ns" akan dibuat. Pod yang berada di dalam
Namespace"my-ns" dapat langsung melakukan lookup dengan hanya menggunakan "my-service".
Sedangkan Pod yang berada di luar Namespacemy-ns" harus menggunakan "my-service.my-ns".
Hasil dari resolusi ini menrupakan cluster IP.
Kubernetes juga menyediakan record DNS SRV (service) untuk named ports. Jika
Service"my-service.my-ns" memiliki port dengan nama "http" dengan protokol TCP,
kamu dapat melakukan query DNS SRV untuk "_http._tcp.my-service.my-ns" untuk mengetahui
nomor port yang digunakan oleh http.
Server DNS Kubernetes adalah satu-satunya cara untuk mengakses
Service dengan tipe ExternalName. Informasi lebih lanjut tersedia di
DNS Pods dan Services.
Serviceheadless
Terkadang kamu tidak membutuhkan mekanisme load-balancing dan sebuah single IP Sevice.
Dalam kasus ini, kamu dapat membuat "headless"Service dengan cara memberikan spesifikasi
None pada cluster IP (.spec.clusterIP).
Opsi ini memungkinkan pengguna mengurangi ketergantungan terhadap sistem Kubernetes
dengan cara memberikan kebebasan untuk mekanisme service discovery. Aplikasi akan
tetap membutuhkan mekanisme self-registration dan adapter service discovery
lain yang dapat digunakan berdasarkan API ini.
Untuk Service"headless" alokasi cluster IP tidak dilakukan dan kube-proxy
tidak me-manageService-Service, serta tidak terdapat mekanisme load balancing
yang dilakukan. Bagaimana konfigurasi otomatis bagi DNS dilakukan bergantung pada
apakah Service tersebut memiliki selector yang dispesifikasikan.
Dengan selector
Untuk Service"headless" dengan selector, kontroler Endpoints akan membuat suatu
recordEndpoints di API, serta melakukan modifikasi konfigurasi DNS untuk mengembalikan
A records (alamat) yang merujuk secara langsung pada Podbackend.
Tanpa selector
Untuk Service"headless" tanpa selector, kontroler Endpoints
tidak akan membuat recordEnpoints. Meskipun demikian,
sistem DNS tetap melakukan konfigurasi salah satu dari:
record untuk semua Endpoints yang memiliki nama Service yang sama, untuk
tipe lainnya.
Mekanisme publishService - jenis-jenis Service
Untuk beberapa bagian dari aplikasi yang kamu miliki (misalnya saja, frontend),
bisa saja kamu memiliki kebutuhan untuk mengekspos Service yang kamu miliki
ke alamat IP eksternal (di luar klaster Kubernetes).
ServiceTypes yang ada pada Kubernetes memungkinkan kamu untuk menentukan
jenis Service apakah yang kamu butuhkan. Secara default, jenis Service
yang diberikan adalah ClusterIP.
Value dan perilaku dari tipe Service dijelaskan sebagai berikut:
ClusterIP: Mengekspos Service ke range alamat IP di dalam klaster. Apabila kamu memilih value ini
Service yang kamu miliki hanya dapat diakses secara internal. tipe ini adalah
defaultvalue dari ServiceType.
NodePort: Mengekspos Service pada setiap IP node pada port statis
atau port yang sama. Sebuah ServiceClusterIP, yang mana ServiceNodePort akan di-route
, dibuat secara otomatis. Kamu dapat mengakses Service dengan tipe ini,
dari luar klaster melalui <NodeIP>:<NodePort>.
LoadBalancer: Mengekspos Service secara eksternal dengan menggunakan LoadBalancer
yang disediakan oleh penyedia layanan cloud. Service dengan tipe NodePort dan ClusterIP,
dimana trafik akan di-route, akan dibuat secara otomatis.
ExternalName: Melakukan pemetaan Service ke konten
dari fieldexternalName (misalnya: foo.bar.example.com), dengan cara mengembalikan
catatan CNAME beserta value-nya. Tidak ada metode proxy apa pun yang diaktifkan. Mekanisme ini
setidaknya membutuhkan kube-dns versi 1.7.
Type NodePort
Jika kamu menerapkan valueNodePort pada fieldtype, master Kubernetes akan mengalokasikan
port dari range yang dispesifikasikan oleh penanda --service-node-port-range (secara default, 30000-32767)
dan setiap Node akan memproksikan port tersebut (setiap Node akan memiliki nomor port yang sama) ke Service
yang kamu miliki. Port tersebut akan dilaporkan pada field.spec.ports[*].nodePort di Service kamu.
Jika kamu ingin memberikan spesifikasi IP tertentu untuk melakukan poxy pada port.
kamu dapat mengatur penanda --nodeport-addresses pada kube-proxy untuk range alamat IP
tertentu (mekanisme ini didukung sejak v1.10). Sebuah daftar yang dipisahkan koma (misalnya, 10.0.0.0/8, 1.2.3.4/32)
digunakan untuk mem-filter alamat IP lokal ke node ini. Misalnya saja kamu memulai kube-proxy dengan penanda
--nodeport-addresses=127.0.0.0/8, maka kube-proxy hanya akan memilih interfaceloopback untuk Service dengan tipe
NodePort. Penanda --nodeport-addresses memiliki nilai default kosong ([]), yang artinya akan memilih semua interface yang ada
dan sesuai dengan perilaku NodePortdefault.
Jika kamu menginginkan nomor port yang berbeda, kamu dapat memberikan spesifikasi
value dari fieldnodePort, dan sistem yang ada akan mengalokasikan port tersebut untuk kamu,
jika port tersebut belum digunakan (perhatikan bahwa jika kamu menggunakan teknik ini, kamu perlu
mempertimbangkan collision yang mungkin terjadi dan bagaimana cara mengatasi hal tersebut)
atau transaksi API yang dilakukan akan gagal.
Hal ini memberikan kebebasan bagi pengembang untuk memilih load balancer yang akan digunakan, terutama apabila
load balancer yang ingin digunakan belum didukung sepenuhnya oleh Kubernetes.
Perhatikan bahwa Service dapat diakses baik dengan menggunakan <NodeIP>:spec.ports[*].nodePort
atau .spec.clusterIP:spec.ports[*].port. (Jika penanda --nodeport-addresses diterapkan, dapat di-filter dengan salah satu atau lebih NodeIP.)
Type LoadBalancer
Pada penyedia layanan cloud yang menyediakan pilihan load balancer eksternal, pengaturan fieldtype
ke LoadBalancer akan secara otomatis melakukan proses provisionload balancer untuk Service yang kamu buat.
Informasi mengenai load balancer yang dibuat akan ditampilkan pada field.status.loadBalancer
pada Service kamu. Contohnya:
Trafik dari load balancer eksternal akan diarahkan pada Podbackend, meskipun mekanisme
bagaimana hal ini dilakukan bergantung pada penyedia layanan cloud. Beberapa penyedia layanan
cloud mengizinkan konfigurasi untuk valueloadBalancerIP. Dalam kasus tersebut, load balancer akan dibuat
dengan loadbalancerIP yang dispesifikasikan. Jika value dari loadBalancerIP tidak dispesifikasikan.
sebuah IP sementara akan diberikan pada loadBalancer. Jika loadBalancerIP dispesifikasikan,
tetapi penyedia layanan cloud tidak mendukung hal ini, maka field yang ada akan diabaikan.
Catatan Khusus untuk Azure: Untuk spesifikasi loadBalancerIP publik yang didefinisikan oleh pengguna,
sebuah alamat IP statis publik akan disediakan terlebih dahulu, dan alamat IP tersebut harus berada di
resource group dari resource yang secara otomatis dibuat oleh klaster. Misalnya saja, MC_myResourceGroup_myAKSCluster_eastus.
Berikan spesifikasi alamat IP sebagai loadBalancerIP. Pastikan kamu sudah melakukan update pada
securityGroupName pada file konfigurasi penyedia layanan cloud.
Untuk informasi lebih lanjut mengenai permission untuk CreatingLoadBalancerFailed kamu dapat membaca troubleshooting untuk
Penggunaan alamat IP statis pada load balancer Azure Kubernetes Service (AKS) atau
CreatingLoadBalancerFailed pada klaster AKS dengan advanced networking.
Catatan: Dukungan untuk SCTP load balancer dari penyedia layanan cloud bergantung pada
implementasi load balancer yang disediakan oleh penyedia layanan cloud tersebut.
Jika SCTP tidak didukung oleh load balancer penyedia layanan publik maka request pembuatan Service
akan tetap diterima, meskipun proses pembuatan load balancer itu sendiri gagal.
Load balancer internal
Di dalam environment, terkadang terdapat kebutuhan untuk melakukan route trafik antar
Service yang berada di dalam satu VPC.
Di dalam environmentsplit-horizon DNS kamu akan membutuhkan dua service yang mampu
melakukan mekanisme route trafik eskternal maupun internal ke endpoints yang kamu miliki.
Hal ini dapat diraih dengan cara menambahkan anotasi berikut untuk service yang disediakan oleh
penyedia layanan cloud.
Gunakan cloud.google.com/load-balancer-type: "internal" untuk master dengan versi 1.7.0 to 1.7.3.
Untuk informasi lebih lanjut, dilahkan baca dokumentasi.
Dukungan parsial untuk SSL bagi klaster yang dijalankan di AWS mulai diterapkan,
mulai versi 1.3 terdapat 3 anotasi yang dapat ditambahkan pada Service dengan tipe
LoadBalancer:
Anotasi pertama memberikan spesifikasi ARN dari sertifikat yang akan digunakan.
Sertifikat yang digunakan bisa saja berasal dari third party yang diunggah ke IAM atau
sertifikat yang dibuat secara langsung dengan menggunakan sertifikat manajer AWS.
Anotasi kedua memberikan spesifikasi bagi protokol yang digunakan oleh Pod untuk saling berkomunikasi.
Untuk HTTPS dan SSL, ELB membutuhkan Pod untuk melakukan autentikasi terhadap dirinya sendiri melalui
koneksi yang dienkripsi.
Protokol HTTP dan HTTPS akan memilih mekanisme proxy di tingkatan ke-7:
ELB akan melakukan terminasi koneksi dengan pengguna, melakukan proses parsingheaders, serta
memasukkan value bagi headerX-Forwarded-For dengan alamat IP pengguna (Pod hanya dapat melihat
alamat IP dari ELB pada akhir koneksi yang diberikan) ketika melakukan forwarding suatu request.
Protokol TCP dan SSL akan memilih mekanisme proxy pada tingkatan 4: ELB akan melakukan forwarding trafik
tanpa melakukan modifikasi headers.
Pada environment campuran dimana beberapa port diamankan sementara port lainnya dalam kondisi tidak dienkripsi,
anotasi-anotasi berikut dapat digunakan:
Pada contoh di atas, jika Service memiliki 3 buah port, yaitu: 80, 443, dan
8443, maka 443 adan 8443 akan menggunakan sertifikat SSL, tetapi 80 hanya akan
di-proxy menggunakan protokol HTTP.
Mulai versi 1.9, Service juga dapat menggunakan predefinedpolicy
untuk HTTPS atau listener SSL. Untuk melihat policy apa saja yang dapat digunakan, kamu dapat menjalankan perintah awscli:
Sejak versi 1.3.0, penggunaan anotasi berlaku untuk semua port yang diproksi oleh ELB
dan tidak dapat diatur sebaliknya.
Akses Log ELB pada AWS
Terdapat beberapa anotasi yang digunakan untuk melakukan manajemen
akses log untuk ELB pada AWS.
Anotasi service.beta.kubernetes.io/aws-load-balancer-access-log-enabled
mengatur akses log mana sajakah yang diaktifkan.
Anotasi service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval
mengatur interval (dalam menit) publikasi akses log. Kamu dapat memberikan spesifikasi interval
diantara range 5-60 menit.
Anotasi service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name
mengatur nama bucket Amazon S3 dimana akses logload balancer disimpan.
Anotasi service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix
memberikan spesifikasi hierarki logis yang kamu buat untuk bucket Amazon S3 yang kamu buat.
metadata:name:my-serviceannotations:service.beta.kubernetes.io/aws-load-balancer-access-log-enabled:"true"# Specifies whether access logs are enabled for the load balancerservice.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval:"60"# The interval for publishing the access logs. You can specify an interval of either 5 or 60 (minutes).service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name:"my-bucket"# The name of the Amazon S3 bucket where the access logs are storedservice.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix:"my-bucket-prefix/prod"# The logical hierarchy you created for your Amazon S3 bucket, for example _my-bucket-prefix/prod_
Mekanisme Draining Koneksi pada AWS
Mekanisme draining untuk ELB klasik dapat dilakukan dengan menggunakan anotasi
service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled serta mengatur
value-nya menjadi "true". Anotasi
service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout juga
dapat digunakan untuk mengatur maximum time (dalam detik), untuk menjaga koneksi yang ada
agar selalu terbuka sebelum melakukan deregisteringinstance.
Terdapat beberapa anotasi lain yang dapat digunakan untuk mengatur ELB klasik
sebagaimana dijelaskan seperti di bawah ini:
metadata:name:my-serviceannotations:service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout:"60"# The time, in seconds, that the connection is allowed to be idle (no data has been sent over the connection) before it is closed by the load balancerservice.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled:"true"# Specifies whether cross-zone load balancing is enabled for the load balancerservice.beta.kubernetes.io/aws-load-balancer-additional-resource-tags:"environment=prod,owner=devops"# A comma-separated list of key-value pairs which will be recorded as# additional tags in the ELB.service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold:""# The number of successive successful health checks required for a backend to# be considered healthy for traffic. Defaults to 2, must be between 2 and 10service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold:"3"# The number of unsuccessful health checks required for a backend to be# considered unhealthy for traffic. Defaults to 6, must be between 2 and 10service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval:"20"# The approximate interval, in seconds, between health checks of an# individual instance. Defaults to 10, must be between 5 and 300service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout:"5"# The amount of time, in seconds, during which no response means a failed# health check. This value must be less than the service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval# value. Defaults to 5, must be between 2 and 60service.beta.kubernetes.io/aws-load-balancer-extra-security-groups:"sg-53fae93f,sg-42efd82e"# A list of additional security groups to be added to ELB
Dukungan Network Load Balancer (NLB) pada AWS [alpha]
Peringatan: Ini merupakan tingkatan alpha dan tidak direkomendasikan untuk digunakan pada environmentproduction.
Sejak versi 1.9.0, Kubernetes mendukung Network Load Balancer (NLB). Untuk
menggunakan NLB pada AWS, gunakan anotasi service.beta.kubernetes.io/aws-load-balancer-type
dan atur value-nya dengan nlb.
Tidak seperti ELB klasik, NLB, melakukan forwarding IP klien melalui node.
Jika field.spec.externalTrafficPolicy diatur value-nya menjadi Cluster, maka
alamat IP klien tidak akan diteruskan pada Pod.
Dengan mengatur value dari field.spec.externalTrafficPolicy ke Local,
alamat IP klien akan diteruskan ke Pod, tapi hal ini bisa menyebabkan distribusi trafik
yang tidak merata. Node yang tidak memiliki Pod untuk Service dengan tipe LoadBalancer
akan menyebabkan kegagalan health checkNLB Target pada tahapan auto-assigned.spec.healthCheckNodePort
dan tidak akan menerima trafik apa pun.
Untuk menghasilkan distribusi trafik yang merata, kamu dapat menggunakan
DaemonSet atau melakukan spesifikasi
pod anti-affinity
agar Pod tidak di-assign ke node yang sama.
Agar trafik klien berhasil mencapai instances dibelakang ELB,
security group dari node akan diberikan rules IP sebagai berikut:
Rule
Protokol
Port
IpRange(s)
Deskripsi IpRange
Health Check
TCP
NodePort(s) (.spec.healthCheckNodePort for .spec.externalTrafficPolicy = Local)
VPC CIDR
kubernetes.io/rule/nlb/health=<loadBalancerName>
Client Traffic
TCP
NodePort(s)
.spec.loadBalancerSourceRanges (defaults to 0.0.0.0/0)
kubernetes.io/rule/nlb/client=<loadBalancerName>
MTU Discovery
ICMP
3,4
.spec.loadBalancerSourceRanges (defaults to 0.0.0.0/0)
kubernetes.io/rule/nlb/mtu=<loadBalancerName>
Perhatikan bahwa jika .spec.loadBalancerSourceRanges tidak dispesifikasikan,
Kubernetes akan mengizinkan trafik dari 0.0.0.0/0 ke Node Security Group.
Jika node memiliki akses publik, maka kamu harus memperhatikan tersebut karena trafik yang tidak berasal
dari NLB juga dapat mengakses semua instance di security group tersebut.
Untuk membatasi klien IP mana yang dapat mengakses NLB,
kamu harus memberikan spesifikasi loadBalancerSourceRanges.
spec:loadBalancerSourceRanges:- "143.231.0.0/16"
Catatan: NLB hanya dapat digunakan dengan beberapa kelas instance tertentu baca dokumentasi AWS
untuk mengetahui lebih lanjut intance apa saja yang didukung.
Tipe ExternalName
Service dengan tipe ExternalName melakukan pemetaan antara Service dan DNS, dan bukan
ke selector seperti my-service atau cassandra. Kamu memberikan spesifikasi spec.externalName
pada Service tersebut.
Definisi Service ini, sebagai contoh, melaukan pemetaan
Servicemy-service pada namespaceprod ke DNS my.database.example.com:
Catatan:ExternalName menerima alamat IPv4 dalam bentuk string,
tapi karena DNS tersusun atas angka dan bukan sebagai alamat IP.
ExternalName yang menyerupai alamat IPv4 tidak bisa di-resolve oleh CoreDNS
atau ingress-nginx karena ExternalName memang ditujukan bagi penamaan canonical DNS.
Untuk melakukan hardcode alamat IP, kamu dapat menggunakan headlessService sebagai alternatif.
Ketika melakukan pencarian hostmy-service.prod.svc.cluster.local,
servis DNS klaster akan mengembalikan recordCNAME dengan valuemy.database.example.com.
Mekanisme akses pada my-service bekerja dengan cara yang sama dengan
Service pada umumnya, perbedaan yang krusial untuk hal ini adalah mekanisme redirection
terjadi pada tingkatan DNS dan bukan melalui proxy forward. Apabila kamu berniat memindahkan basis data
yang kamu pakai ke dalam klaster, kamu hanya perlu mengganti instans basis data kamu dan menjalankannya
di dalam Pod, menambahkan selector atau endpoint yang sesuai, serta mengupah type dari
Service yang kamu gunakan.
Jika terdapat sebuah alamat IP eksternal yang melakukan mekanisme route ke satu atau lebih node yang ada di klaster, Service Kubernetes dapat diekspos
dengan menggunakan externalIP. Trafik yang diarahkan ke klaster dengan IP eksternal
(sebagai destinasi IP), pada portService akan di-route ke salah satu endpointService.
Value dari externalIP tidak diatur oleh Kubernetes dan merupakan tanggung jawab
dari administrator klaster.
Pada ServiceSpec, kamu dapat memberikan spesifikasi externalIP dan ServiceTypes.
Pada contoh di bawah ini. "my-service" dapat diakses oleh klien pada "80.11.12.10:80" (externalIP:port).
Penggunaan proxyuserspace untuk VIP dapat digunakan untuk skala kecil hingga menengah,
meski begitu hal ini tidak scalable untuk klaster yang sangat besar dan memiliki ribuan Service.
Perhatikan Desain proposal orisinil untuk portal untuk informasi
lebih lanjut.
Penggunaan proxyuserspace menghilangkan source-IP dari packet yang mengakses
sebuah Service. Hal ini membuat mekanisme firewall menjadi sulit untuk diterapkan.
Proxyiptables tidak menghilangkan source IP yang berasal dari dalam klaster,
meski begitu, hal ini masih berimbas pada klien yang berasal dari Service dengan tipe
load-balancer atau node-port.
Field tipe didesain sebagai fungsionalitas yang berantai - setiap tingkatan
menambahkan tambahan pada tingkatansebelumnya. Hal ini tidak selalu berlaku bagi
semua penyedia layanan cloud (misalnya saja Google Compute Engine tidak perlu
melakukan alokasi NodePort untuk membuat LoadBalancer bekerja sebagaimana mestinya,
hal ini berbeda dengan AWS yang memerlukan hal ini, setidaknya untuk API yang mereka miliki
saat ini).
Pengerjaan lebih lanjut
Di masa mendatang, kami berencana untuk membuat policyproxy menjadi lebih
bervariasi dan bukan hanya round robin, misalnya saja master-elected atau sharded.
Kami juga berharap bahwa beberapa Service bisa saja memiliki load balancer yang sebenarnya,
suatu kasus dimana VIP akan secara langsung mengantarkan paket.
Kami ingin meningkatkan dukungan lebih lanjut untuk Service dengan tingkatan Service L7(HTTP).
Kami ingin memiliki mode ingress yang lebih fleksibel untuk Service yang
mencakup mode ClusterIP, NodePort, dan LoadBalancer dan banyak lagi.
Detail mendalam mengenai IP virtual
Informasi sebelumnya sudah cukup bagi sebagian orang yang hanya ingin menggunakan
Service. Meskipun begitu, terdapat banyak hal yang sebenarnya terjadi dan akan
sangat bermanfaat untuk dipelajari lebih lanjut.
Menghindari collison
Salah satu filosofi Kubernetes adalah pengguna tidak mungkin menghadapi situasi
dimana apa yang mereka mengalami kegagalan tanpa adanya alasan yang jelas. Dalam kasus ini,
kita akan coba memahami lebih lanjut mengenai network port - pengguna tidak seharusnya memilih
nomor port jika hal itu memungkinkan terjadinya collision dengan pengguna lainnya. Hal ini
merupakan mekanisme isolasi kegagalan.
Agar pengguna dapat menentukan nomor port bagi Service mereka, kita harus
memastikan bahwa tidak ada dua Service yang mengalami collision. Kita melakukan
hal tersebut dengan cara melakukan alokasi alamat IP pada setiap Service.
Untuk memastikan setiap Service memiliki alamat IP yang unik, sebuah allocator
internal akan secara atomik melakukan pemetaan alokasi global di dalam etcd ketika
membuat sebuah Service baru. Pemetaan objek harus tersedia pada registryService
dimana Service akan diberikan sebuah IP, jika tidak, proses pembuatan Service akan gagal
dan sebuah pesan akan memberikan informasi bahwa alamat IP tidak dapat dialokasikan.
Sebuah backgroudcontroller bertanggung jawab terhadap mekanisme pemetaan tersebut (migrasi
dari versi Kubernetes yang digunakan dalam memory locking) sekaligus melakukan pengecekan
terhadap assignment yang tidak valid yang terjadi akibat intervensi administrator dan melakukan
penghapusan daftar IP yang dialokasikan tapi tidak digunakan oleh Service mana pun.
IP dan VIP
Tidak seperti alamat IP Pod, yang akan di route ke destinasi yang "pasti",
IP Service tidak mengarahkan request hanya pada satu host. Sebagai gantinya,
kita mneggunakan iptables (logika pemrosesan paket pada Linux) untuk melakukan definisi
alamat IP virtual yang secara transparan akan diarahkan sesuai kebutuhan. Ketika klien
dihubungkan pada VIP, trafik yang ada akan secara otomatis dialihkan pada endpoint yang sesuai.
Variabel environment dan DNS untuk Service terdiri dalam bentuk VIP dan port.
Kami mendukung tiga jenis mode proxy - userspace, iptables, dan ipvs yang memiliki
perbedaan cara kerja satu sama lainnya.
Userspace
Sebagai contoh, anggaplah kita memiliki aplikasi image processing seperti yang sudah
disebutkan di atas. Ketika Servicebackend dibuat, master Kubernetes akan mengalokasikan
sebuah alamat IP virtual, misalnya 10.0.0.1. Dengan asumsi port dari Service tersebut adalah 1234,
maka Service tersebut akan diamati oleh semua instancekube-proxy yang ada di klaster.
Ketika sebuah proxy mendapati sebuah Service baru, proxy tersebut akan membuka sebuah portacak, menyediakan iptables yang mengarahkan VIP pada port yang baru saja dibuat, dan mulai
koneksi pada port tersebut.
Ketika sebuah klien terhubung ke VIP dan terdapat rulesiptables
yang diterapkan, paket akan diarahkan ke port dari proxyService itu sendiri.
ProxyService akan memilih sebuah backend, dan mulai melakukan mekanisme proxy
trafik dari klien ke backend.
Dengan demikian, pemilik Service dapat memilih port mana pun yang dia inginkan
tanpa adanya kemungkinan terjadinya collision. Klien dapat dengan mudah mengakses IP dan port,
tanpa harus mengetahui Pod mana yang sebenarnya diakses.
Iptables
Kembali, bayangkan apabila kita memiliki aplikasi image processing seperti yang sudah
disebutkan di atas. Ketika Servicebackend dibuat, master Kubernetes akan mengalokasikan
sebuah alamat IP virtual, misalnya 10.0.0.1. Dengan asumsi port dari Service tersebut adalah 1234,
maka Service tersebut akan diamati oleh semua instancekube-proxy yang ada di klaster.
Ketika sebuah proxy mendapati sebuah Service baru, proxy tersebut akan melakukan instalasi
serangkaian rulesiptables yang akan melakukan redirect VIP ke rules tiap Service. Rules
untuk tiap Service ini terkait dengan rules tiap Endpoints yang mengarahkan (destinasi NAT)
ke backend.
Ketika sebuah klien terhubung ke VIP dan terdapat _rules _iptables
yang diterapkan. Sebuah backend akan dipilih (hal ini dapat dilakukan berdasarkan session affinity
maupun secara acak) dan paket-paket yang ada akan diarahkan ke backend. Tidak seperti mekanisme
yang terjadi di userspace, paket-paket yang ada tidak pernah disalin ke userspace, kube-proxy
tidak harus aktif untuk menjamin kerja VIP, serta IP klien juga tidak perlu diubah.
Tahapan yang dijalankan sama dengan tahapan yang dijalankan ketika trafik masuk melalui sebuah node-port
atau load-balancer, meskipun pada dua kasus di atas klien IP tidak akan mengalami perubahan.
Ipvs
Operasi iptables berlangsung secara lambat pada klaster dengan skala besar (lebih dari 10.000 Service).
IPVS didesain untuk mekanisme load balance dan berbasis pada hash tables yang berada di dalam kernel.
Dengan demikian kita dapat mendapatkan performa yang konsisten pada jumlah Service yang cukup besar dengan
menggunakan kube-proxy berbasis ipvs. Sementara itu, kube-proxy berbasis ipvs memiliki algoritma
load balance yang lebih bervariasi (misalnya saja least conns, locality, weighted, persistence).
Objek API
Service merupakan resourcetop-level pada API Kubernetes.
Penjelasan lebih lanjut mengenai objek API dapat ditemukan pada:
objek API Service.
Protokol yang didukung
TCP
FEATURE STATE:Kubernetes v1.0 [stable]
Kamu dapat menggunakan TCP untuk Service dengan type apa pun, dan protokol ini merupakan
protokol default yang digunakan.
UDP
FEATURE STATE:Kubernetes v1.0 [stable]
Kamu dapat menggunakan UDP untuk sebagian besar Service.
Untuk Service dengan type=LoadBalancer, dukungan terhadap UDP
bergantung pada penyedia layanan cloud yang kamu gunakan.
HTTP
FEATURE STATE:Kubernetes v1.1 [stable]
Apabila penyedia layanan cloud yang kamu gunakan mendukung, kamu dapat menggunakan
Service dengan typeLoadBalancer untuk melakukan mekanisme reverseproxy
bagi HTTP/HTTPS, dan melakukan forwarding ke Endpoints dari _Service.
Catatan: Kamu juga dapat menggunakan Ingress sebagai salah satu
alternatif penggunaan Service untuk HTTP/HTTPS.
Protokol PROXY
FEATURE STATE:Kubernetes v1.1 [stable]
Apabila penyedia layanan cloud yang kamu gunakan mendukung, (misalnya saja, AWS),
Service dengan typeLoadBalancer untuk melakukan konfigurasi load balancer
di luar Kubernetes sendiri, serta akan melakukan forwarding koneksi yang memiliki prefiks
protokol PROXY.
Load balancer akan melakukan serangkaian inisiasi octet yang memberikan
deskripsi koneksi yang datang, dengan bentuk yang menyerupai:
PROXY TCP4 192.0.2.202 10.0.42.7 12345 7\r\n
yang kemudian diikuti data dari klien.
SCTP
FEATURE STATE:Kubernetes v1.12 [alpha]
Kubernetes memberikan dukungan bagi SCTP sebagai value dari definition yang ada pada
Service, Endpoints, NetworkPolicy dan Pod sebagai fitur alpha. Untuk mengaktifkan fitur ini,
administrator klaster harus mengaktifkan feature gateSCTPSupport pada apiserver, contohnya
“--feature-gates=SCTPSupport=true,...”. Ketika fature gate ini diaktifkan, pengguna dapat
memberikan value SCTP pada fieldprotocolService, Endpoints, NetworkPolicy dan Pod.
Kubernetes kemudian akan melakukan pengaturan agar jaringan yang digunakan agar jaringan tersebut menggunakan SCTP,
seperti halnya Kubernetes mengatur jaringan agar menggunakan TCP.
Perhatian
Dukungan untuk asoasiasi multihomed SCTP
Dukungan untuk asosiasi multihomed SCTP membutuhkan plugin CNI yang dapat memberikan
pengalokasian multiple interface serta alamat IP pada sebuah Pod.
NAT untuk asosiasi multihomed SCTP membutuhkan logika khusus pada modul kernel terkait.
Service dengan type=LoadBalancer
Sebuah Service dengan typeLoadBalancer dan protokol SCTP dapat dibuat
hanya jika implementasi load balancer penyedia layanan cloud menyediakan dukungan
bagi protokol SCTP. Apabila hal ini tidak terpenuhi, maka request pembuatan Servixe ini akan ditolak.
Load balancer yang disediakan oleh penyedia layanan cloud yang ada saat ini (Azure, AWS, CloudStack, GCE, OpenStack) tidak mendukung SCTP.
Windows
SCTP tidak didukung pada node berbasis Windows.
Kube-proxyuserspace
Kube-proxy tidak mendukung manajemen asosiasi SCTP ketika hal ini dilakukan pada mode
userspace
Topologi Service memungkinkan Service untuk
merutekan lalu lintas jaringan berdasarkan topologi Node dalam klaster. Misalnya, suatu
layanan dapat menentukan lalu lintas jaringan yang lebih diutamakan untuk dirutekan ke
beberapa endpoint yang berada pada Node yang sama dengan klien, atau pada
availability zone yang sama.
Pengantar
Secara bawaan lalu lintas jaringan yang dikirim ke ClusterIP atau NodePort dari Service
dapat dialihkan ke alamat backend untuk Service tersebut. Sejak Kubernetes 1.7
dimungkinkan untuk merutekan lalu lintas jaringan "eksternal" ke Pod yang berjalan di
Node yang menerima lalu lintas jaringan, tetapi fitur ini tidak didukung untuk ClusterIP dari
Service, dan topologi yang lebih kompleks — seperti rute zonasi —
belum memungkinkan. Fitur topologi Service mengatasi kekurangan ini dengan
mengizinkan pembuat layanan untuk mendefinisikan kebijakan dalam merutekan lalu lintas jaringan
berdasarkan label Node untuk Node-Node asal dan tujuan.
Dengan menggunakan label Node yang sesuai antara asal dan tujuan, operator dapat
menunjuk kelompok Node mana yang "lebih dekat" dan mana yang "lebih jauh" antara satu sama lain,
dengan menggunakan metrik apa pun yang masuk akal untuk memenuhi persyaratan
dari operator itu. Untuk sebagian besar operator di publik cloud, misalnya, ada
preferensi untuk menjaga layanan lalu lintas jaringan dalam zona yang sama, karena lalu lintas jaringan
antar zona memiliki biaya yang dibebankan, sementara lalu lintas jaringan
dalam zona yang sama tidak ada biaya. Kebutuhan umum lainnya termasuk kemampuan untuk merutekan
lalu lintas jaringan ke Pod lokal yang dikelola oleh sebuah DaemonSet, atau menjaga lalu lintas jaringan ke
Node yang terhubung ke top-of-rack switch yang sama untuk mendapatkan
latensi yang terendah.
Menggunakan Topologi Service
Jika klaster kamu mengaktifkan topologi Service kamu dapat mengontrol rute lalu lintas jaringan Service
dengan mengatur bagian topologyKeys pada spesifikasi Service. Bagian ini
adalah daftar urutan label-label Node yang akan digunakan untuk mengurutkan endpoint
saat mengakses Service ini. Lalu lintas jaringan akan diarahkan ke Node yang nilai
label pertamanya cocok dengan nilai dari Node asal untuk label yang sama. Jika
tidak ada backend untuk Service pada Node yang sesuai, maka label kedua akan
dipertimbangkan, dan seterusnya, sampai tidak ada label yang tersisa.
Jika tidak ditemukan kecocokan, lalu lintas jaringan akan ditolak, sama seperti jika tidak ada
sama sekali backend untuk Service tersebut. Artinya, endpoint dipilih
berdasarkan kunci topologi yang pertama yang tersedia pada backend. Jika dalam
bagian ini ditentukan dan semua entri tidak memiliki backend yang sesuai dengan
topologi klien, maka Service tidak memiliki backend untuk klien dan koneksi harus
digagalkan. Nilai khusus "*" dapat digunakan untuk mengartikan "topologi
apa saja". Nilai catch-all ini, jika digunakan, maka hanya sebagai
nilai terakhir dalam daftar.
Jika topologyKeys tidak ditentukan atau kosong, tidak ada batasan topologi
yang akan diterapkan.
Seandainya sebuah klaster dengan Node yang dilabeli dengan nama host ,
nama zona, dan nama wilayah mereka, maka kamu dapat mengatur nilai
topologyKeys dari sebuah Service untuk mengarahkan lalu lintas jaringan seperti berikut ini.
Hanya ke endpoint dalam Node yang sama, gagal jika tidak ada endpoint pada Node: ["kubernetes.io/hostname"].
Lebih memilih ke endpoint dalam Node yang sama, jika tidak ditemukan maka ke endpoint pada zona yang sama, diikuti oleh wilayah yang sama, dan selain itu akan gagal: ["kubernetes.io/hostname ", "topology.kubernetes.io/zone", "topology.kubernetes.io/region"]. Ini mungkin berguna, misalnya, dalam kasus di mana lokalitas data sangatlah penting.
Lebih memilih ke endpoint dalam zona yang sama, tetapi memilih endpoint mana saja yang tersedia apabila tidak ada yang tersedia dalam zona ini: ["topology.kubernetes.io/zone ","*"].
Batasan
Topologi Service tidak kompatibel dengan externalTrafficPolicy=Local, dan karena itu Service tidak dapat menggunakan kedua fitur ini sekaligus. Dimungkinkan untuk menggunakan kedua fitur pada klaster yang sama untuk Service yang berbeda, bukan untuk Service yang sama.
Untuk saat ini kunci topologi yang valid hanya terbatas pada kubernetes.io/hostname, topology.kubernetes.io/zone, dan topology.kubernetes.io/region, tetapi akan digeneralisasikan ke label Node yang lain di masa depan.
Kunci topologi harus merupakan kunci label yang valid dan paling banyak hanya 16 kunci yang dapat ditentukan.
Nilai catch-all, "*", harus menjadi nilai terakhir pada kunci topologi, jika nilai itu digunakan.
Contoh
Berikut ini adalah contoh umum penggunaan fitur topologi Service.
Hanya pada endpoint pada Node lokal
Service yang hanya merutekan ke endpoint pada Node lokal. Jika tidak ada endpoint pada Node, lalu lintas jaringan akan dihentikan:
Hanya untuk endpoint pada zona atau wilayah yang sama
Service yang lebih memilih endpoint dalam zona yang sama daripada wilayah yang sama. Jika tidak ada endpoint pada keduanya, maka lalu lintas jaringan akan dihentikan.
Lebih memilih endpoint pada Node lokal, zona yang sama, dan kemudian wilayah yang sama
Service yang lebih memilih endpoint pada Node lokal, zona yang sama, dan kemudian baru wilayah yang sama,
namun jika tetap tidak ditemukan maka akan memilih endpoint diseluruh klaster.
EndpointSlice menyediakan sebuah cara yang mudah untuk melacak endpoint jaringan dalam sebuah
klaster Kubernetes. EndpointSlice memberikan alternatif yang lebih scalable dan lebih dapat diperluas dibandingkan dengan Endpoints.
Motivasi
Endpoints API telah menyediakan sebuah cara yang mudah dan sederhana untuk
melacak endpoint jaringan pada Kubernetes. Sayangnya, seiring dengan besarnya klaster Kubernetes
dan Service, batasan-batasan yang dimiliki API tersebut semakin terlihat.
Terutama, hal tersebut termasuk kendala-kendala mengenai proses scalingendpoint jaringan
dalam jumlah yang besar.
Karena semua endpoint jaringan untuk sebuah Service disimpan dalam satu sumber daya
Endpoints, sumber daya tersebut dapat menjadi cukup besar. Hal itu dapat mempengaruhi kinerja
dari komponen-komponen Kubernetes (terutama master control plane) dan menyebabkan
lalu lintas jaringan dan pemrosesan yang cukup besar ketika Endpoints berubah.
EndpointSlice membantu kamu menghindari masalah-masalah tersebut dan juga menyediakan platform
yang dapat diperluas untuk fitur-fitur tambahan seperti topological routing.
Sumber daya EndpointSlice
Pada Kubernetes, sebuah EndpointSlice memiliki referensi-referensi terhadap sekumpulan endpoint
jaringan. Controller EndpointSlice secara otomatis membuat EndpointSlice
untuk sebuah Service Kubernetes ketika sebuah selektor dituliskan. EndpointSlice tersebut akan memiliki
referensi-referensi menuju Pod manapun yang cocok dengan selektor pada Service tersebut. EndpointSlice mengelompokkan
endpoint jaringan berdasarkan kombinasi Service dan Port yang unik.
Nama dari sebuah objek EndpointSlice haruslah berupa
nama subdomain DNS yang sah.
Sebagai contoh, berikut merupakan sampel sumber daya EndpointSlice untuk sebuah Service Kubernetes
yang bernama example.
Secara bawaan, setiap EndpointSlice yang dikelola oleh controller EndpointSlice tidak akan memiliki
lebih dari 100 endpoint. Di bawah skala tersebut, EndpointSlice akan memetakan 1:1
dengan Endpoints dan Service dan akan memiliki kinerja yang sama.
EndpointSlice dapat bertindak sebagai sumber kebenaran untuk kube-proxy sebagai acuan mengenai
bagaimana cara untuk merutekan lalu lintas jaringan internal. Ketika diaktifkan, EndpointSlice semestinya memberikan peningkatan
kinerja untuk Service yang memiliki Endpoints dalam jumlah besar.
Tipe-tipe Alamat
EndpointSlice mendukung tiga tipe alamat:
IPv4
IPv6
FQDN (Fully Qualified Domain Name)
Topologi
Setiap endpoint pada EndpointSlice dapat memiliki informasi topologi yang relevan.
Hal ini digunakan untuk mengindikasikan di mana endpoint berada, berisi informasi mengenai
Node yang bersangkutan, zona, dan wilayah. Ketika nilai-nilai tersebut tersedia,
label-label Topology berikut akan ditambahkan oleh controller EndpointSlice:
kubernetes.io/hostname - Nama dari Node tempat endpoint berada.
topology.kubernetes.io/zone - Zona tempat endpoint berada.
topology.kubernetes.io/region - Region tempat endpoint berada.
Nilai-nilai dari label-label berikut berasal dari sumber daya yang diasosiasikan dengan tiap
endpoint pada sebuah slice. Label hostname merepresentasikan nilai dari kolom NodeName
pada Pod yang bersangkutan. Label zona dan wilayah merepresentasikan nilai
dari label-label dengan nama yang sama pada Node yang bersangkutan.
Pengelolaan
Secara bawaan, EndpointSlice dibuat dan dikelola oleh controller
EndpointSlice. Ada berbagai macam kasus lain untuk EndpointSlice, seperti
implementasi service mesh, yang memungkinkan adanya entitas atau controller lain
yang dapat mengelola beberapa EndpointSlice sekaligus. Untuk memastikan beberapa entitas dapat
mengelola EndpointSlice tanpa mengganggu satu sama lain, sebuah
label endpointslice.kubernetes.io/managed-by digunakan untuk mengindikasikan entitas
yang mengelola sebuah EndpointSlice. Controller EndpointSlice akan menambahkan
endpointslice-controller.k8s.io sebagai nilai dari label tersebut pada seluruh
EndpointSlice yang dikelolanya. Entitas lain yang mengelola EndpointSlice juga diharuskan untuk
menambahkan nilai yang unik untuk label tersebut.
Kepemilikan
Pada kebanyakan kasus, EndpointSlice akan dimiliki oleh Service yang diikutinya. Hal ini diindikasikan dengan referensi pemilik pada tiap EndpointSlice dan
juga label kubernetes.io/service-name yang memudahkan pencarian seluruh
EndpointSlice yang dimiliki oleh sebuah Service.
Controller EndpointSlice
Controller EndpointSlice mengamati Service dan Pod untuk memastikan EndpointSlice
yang bersangkutan berada dalam kondisi terkini. Controller EndpointSlice akan mengelola EndpointSlice untuk
setiap Service yang memiliki selektor. Ini akan merepresentasikan IP dari Pod
yang cocok dengan selektor dari Service tersebut.
Ukuran EndpointSlice
Secara bawaan, jumlah endpoint yang dapat dimiliki tiap EndpointSlice dibatasi sebanyak 100 endpoint. Kamu dapat
mengaturnya melalui opsi --max-endpoints-per-slicekube-controller-manager sampai dengan
jumlah maksimum sebanyak 1000 endpoint.
Distribusi EndpointSlice
Tiap EndpointSlice memiliki sekumpulan port yang berlaku untuk seluruh endpoint dalam sebuah sumber daya. Ketika nama port digunakan untuk sebuah Service, Pod mungkin mendapatkan
nomor target port yang berbeda-beda untuk nama port yang sama, sehingga membutuhkan
EndpointSlice yang berbeda. Hal ini mirip dengan logika mengenai bagaimana subset dikelompokkan
dengan Endpoints.
Controller EndpointSlice akan mencoba untuk mengisi EndpointSlice sebanyak mungkin, tetapi tidak
secara aktif melakukan rebalance terhadap EndpointSlice tersebut. Logika dari controller cukup sederhana:
Melakukan iterasi terhadap EndpointSlice yang sudah ada, menghapus endpoint yang sudah tidak lagi
dibutuhkan dan memperbarui endpoint yang sesuai yang mungkin telah berubah.
Melakukan iterasi terhadap EndpointSlice yang sudah dimodifikasi pada langkah pertama dan
mengisinya dengan endpoint baru yang dibutuhkan.
Jika masih tersisa endpoint baru untuk ditambahkan, mencoba untuk menambahkannya pada
slice yang tidak berubah sebelumnya dan/atau membuat slice yang baru.
Terlebih penting, langkah ketiga memprioritaskan untuk membatasi pembaruan EndpointSlice terhadap
distribusi dari EndpointSlice yang benar-benar penuh. Sebagai contoh, jika ada 10
endpoint baru untuk ditambahkan dan ada 2 EndpointSlice yang masing-masing memiliki ruang untuk 5 endpoint baru,
pendekatan ini akan membuat sebuah EndpointSlice baru daripada mengisi 2
EndpointSlice yang sudah ada. Dengan kata lain, pembuatan sebuah EndpointSlice
lebih diutamakan daripada pembaruan beberapa EndpointSlice.
Dengan kube-proxy yang berjalan pada tiap Node dan mengamati EndpointSlice, setiap perubahan
pada sebuah EndpointSlice menjadi sangat mahal karena hal tersebut akan dikirimkan ke
setiap Node dalam klaster. Pendekatan ini ditujukan untuk membatasi jumlah
perubahan yang perlu dikirimkan ke setiap Node, meskipun hal tersebut berdampak pada banyaknya
EndpointSlice yang tidak penuh.
Pada praktiknya, distribusi yang kurang ideal seperti ini akan jarang ditemukan. Kebanyakan perubahan yang diproses oleh controller EndpointSlice akan cukup kecil untuk dapat masuk pada
EndpointSlice yang sudah ada, dan jika tidak, cepat atau lambat sebuah EndpointSlice baru
akan segera dibutuhkan. Pembaruan bertahap (rolling update) dari Deployment juga menyediakan sebuah proses
pengemasan ulang EndpointSlice yang natural seiring dengan digantikannya seluruh Pod dan endpoint yang
bersangkutan.
Laman ini menyediakan ikhtisar dari dukungan DNS oleh Kubernetes.
Pendahuluan
Kubernetes DNS melakukan scheduling DNS Pod dan Service yang ada pada klaster, serta
melakukan konfigurasi kubelet untuk memberikan informasi bagi setiap Container
untuk menggunakan DNS Service IP untuk melakukan resolusi DNS.
Apa Sajakah yang Mendapatkan Nama DNS?
Setiap Service yang didefinisikan di dalam klaster (termasuk server DNS itu sendiri)
memiliki nama DNS. Secara default, sebuah list pencarian DNS pada Pod klien
akan mencantumkan namespace Pod itu sendiri serta domain default klaster. Hal ini dapat diilustrasikan
dengan contoh berikut:
Asumsikan sebuah Service dengan nama foo pada Kubernetes dengan namespacebar.
Sebuah Pod yang dijalankan di namespacebar dapat melakukan resolusi
terhadap Service ini dengan melakukan query DNS
untuk foo. Sebuah Pod yang dijalankan pada namespace quux dapat melakukan
resolusi Service ini dengan melakukan query DNS untuk foo.bar.
Bagian di bawah ini akan menampilkan detail tipe rekaman serta layout yang didukung.
Layout atau nama query lain yang dapat digunakan dianggap sebagai detail implementasi
yang bisa saja berubah tanpa adanya pemberitahuan sebelumnya. Untuk informasi spesifikasi
terbaru kamu dapat membaca Service Discovery pada Kubernetes berbasis DNS.
Service
A record
Service "Normal" (bukan headless) akan diberikan sebuah A record untuk sebuah nama dalam bentuk
my-svc.my-namespace.svc.cluster-domain.example. Inilah yang kemudian digunakan untuk melakukan
resolusi IP klaster dari Service tersebut.
Service "Headless" (tanpa IP klaster) juga memiliki sebuah A record DNS dengan format
my-svc.my-namespace.svc.cluster-domain.example. Tidak seperti halnya Service normal,
DNS ini akan melakukan resolusi pada serangkauan IP dari Pod yang dipilih oleh Service tadi.
Klien diharapkan untuk mengkonsumsi serangkaian IP ini atau cara lain yang digunakan adalah pemilihan
menggunakan penjadwalan Round-Robin dari set yang ada.
SRV record
SRV record dibuat untuk port bernama yang merupakan bagian dari Service normal maupun Headless
Services.
Untuk setiap port bernama, SRV record akan memiliki format
_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example.
Untuk sebuah Service normal, ini akan melakukan resolusi pada nomor port dan
nama domain: my-svc.my-namespace.svc.cluster-domain.example.
Untuk Service headless, ini akan melakukan resolusi pada serangkaian Pod yang merupakan backend dari Service
tersebut yang memiliki format: auto-generated-name.my-svc.my-namespace.svc.cluster-domain.example.
Pod
Hostname Pod dan Field Subdomain
Saat ini ketika sebuah Pod dibuat, hostname-nya adalah nilai dari metadata.name.
Spek Pod memiliki field opsional hostname, yang dapat digunakan untuk menspesifikasikan
hostname Pod. Ketika dispesifikasikan, maka nama ini akan didahulukan di atas nama Pod .
Misalnya, sebuah Pod dengan hostname yang diberikan nilai "my-host", maka hostname Pod tersebut akan menjadi "my-host".
Spek Pod juga memiliki field opsional subdomain yang dapat digunakan untuk menspesifikasikan
subdomain Pod tersebut. Misalnya saja sebuah Pod dengan hostname yang diberi nilai "foo", dan subdomain
yang diberi nilai "bar", pada namespace "my-namespace", akan memiliki fully qualified
domain name (FQDN) "foo.bar.my-namespace.svc.cluster-domain.example".
Contoh:
apiVersion:v1kind:Servicemetadata:name:default-subdomainspec:selector:name:busyboxclusterIP:Noneports:- name:foo# Actually, no port is needed.port:1234targetPort:1234---apiVersion:v1kind:Podmetadata:name:busybox1labels:name:busyboxspec:hostname:busybox-1subdomain:default-subdomaincontainers:- image:busybox:1.28command:- sleep- "3600"name:busybox---apiVersion:v1kind:Podmetadata:name:busybox2labels:name:busyboxspec:hostname:busybox-2subdomain:default-subdomaincontainers:- image:busybox:1.28command:- sleep- "3600"name:busybox
Jika terdapat sebuah Service headless memiliki nama yang sama dengan
subdomain dari suatu Pod pada namespace yang sama, server KubeDNS klaster akan mengembalikan
A record untuk FQDN Pod.
Sebagai contoh, misalnya terdapat sebuah Pod dengan hostname "busybox-1" dan
subdomain "default-subdomain", serta sebuah Service headless dengan nama "default-subdomain" berada pada suatu namespace yang sama, maka Pod tersebut akan menerima FQDN dirinya sendiri
sebagai "busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example". DNS mengembalikan
A record pada nama tersebut dan mengarahkannya pada IP Pod. Baik Pod "busybox1" dan
"busybox2" bisa saja memiliki A record yang berbeda.
Objek Endpoint dapat menspesifikasikan hostname untuk alamat endpoint manapun
beserta dengan alamat IP-nya.
Catatan: Karena A record tidak dibuat untuk sebuah Pod, maka hostname diperlukan
agar sebuah Pod memiliki A record. Sebuah Pod yang tidak memiliki hostname
tetapi memiliki subdomain hanya akan membuat sebuah A record untuk Service headless
(default-subdomain.my-namespace.svc.cluster-domain.example), yang merujuk pada IP dari
Pod tersebut. Pod juga harus dalam status ready agar dapat memiliki A record kecuali
fieldpublishNotReadyAddresses=True diaktifkan pada Service.
Kebijakan DNS Pod
Kebijakan DNS dapat diaktifkan untuk setiap Pod. Kubernetes saat ini mendukung
kebijakan DNS spesifik Pod (pod-specific DNS policies). Kebijakan ini
dispesifikasikan pada fielddnsPolicy yang ada pada spek Pod.
"Default": Pod akan mewarisi konfigurasi resolusi yang berasal dari Node
dimana Pod tersebut dijalankan.
Silakan baca diskusi terkait
untuk detailnya.
"ClusterFirst": Query DNS apa pun yang tidak sesuai dengan sufiks domain klaster yang sudah dikonfigurasi
misalnya "www.kubernetes.io", akan di-forward ke nameserverupstream yang diwarisi dari Node.
Administrator klaster bisa saja memiliki stub-domain atau DNS usptream lain yang sudah dikonfigurasi.
Silakan lihat diskusi terkait
untuk detail lebih lanjut mengenai bagaimana query DNS melakukan hal tersebut.
"ClusterFirstWithHostNet": Untuk Pod yang dijalankan dengan menggunakan hostNetwork, kamu harus
secara eksplisit mengaktifkan kebijakan DNS-nya menjadi "ClusterFirstWithHostNet".
"None": Hal ini mengisikan sebuah Pod untuk mengabaikan konfigurasi DNS dari environment Kubernetes
Semua pengaturan DNS disediakan menngunakan fielddnsConfig yang ada pada spek Pod.
Silakan lihat konfigurasi DNS Pod di bawah.
Catatan: "Default" bukan merupakan nilai default kebijakan DNS.
Jika dnsPolicy tidak secara eksplisit dispesifikasikan, maka “ClusterFirst” akan digunakan.
Contoh di bawah ini menunjukkan sebuah Pod dengan kebijakan
DNS yang diubah menjadi "ClusterFirstWithHostNet" karena fieldhostNetwork
diubah menjadi true.
Konfigurasi DNS Pod mengizinkan pengguna untuk memiliki
lebih banyak kontrol terhadap pengaturan DNS pada Pod.
FielddnsConfig bersifat opsional dan dapat digunakan dengan
pengaturan dnsPolicy apa pun.
Meskipun begitu, ketika fielddnsPolicy pada sebuah Pod diubah menjadi "None",
maka fielddnsConfig harus dispesifikasikan.
Berikut merupakan properti yang dapat dispesifikasikan oleh pengguna
pada fielddnsConfig:
nameservers: serangkaian alamat IP yang akan digunakan sebagai server DNS bagi Pod.
Jumlah maksimum dari IP yang dapat didaftarkan pada field ini adalah tiga buah IP.
Ketika sebuah dnsPolicy pada Pod diubah menjadi "None", maka list ini setidaknya
harus mengandung sebuah alamat IP, selain kasus tersebut properti ini bersifat opsional.
Server yang didaftarkan akan digabungkan di dalam nameserver dasar yang dihasilkan dari
kebijakan DNS yang dispesifikasikan, apabila terdapat duplikat terhadap alamat yang didaftarkan
maka alamat tersebut akan dihapus.
searches: merupakan serangkaian domain pencarian DNS yang digunakan untuk proses lookup pada Pod.
Properti ini bersifat opsional. Ketika dispesifikasikan, list yang disediakan akan digabungkan dengan
nama domain pencarian dasar yang dihasilkan dari kebijakan DNS yang dipilih. Alamat yang duplikat akan dihapus.
Nilai maksimum domain pencarian yang dapat didaftarkan adalah 6 domain.
options: merupakan sebuah list opsional yang berisikan objek dimana setiap objek
bisa saja memiliki properti name (yang bersifat wajib). Isi dari properti ini
akan digabungkan dengan opsi yang dihasilkan kebijakan DNS yang digunakan.
Alamat yang duplikat akan dihapus.
Di bawah ini merupakan contoh sebuah Pod dengan pengaturan DNS kustom:
Sekarang kamu memiliki aplikasi yang telah direplikasi, kamu dapat mengeksposnya di jaringan. Sebelum membahas pendekatan jaringan di Kubernetes, akan lebih baik jika kamu paham bagaimana jaringan bekerja di dalam Docker.
Secara default, Docker menggunakan jaringan host, jadi kontainer dapat berkomunikasi dengan kontainer lainnya jika mereka berada di dalam node yang sama. Agar kontainer Docker dapat berkomunikasi antar node, masing-masing kontainer tersebut harus diberikan port yang berbeda di alamat IP node tersebut, yang akan diteruskan (proxied) ke dalam kontainer. Artinya adalah para kontainer di dalam sebuah node harus berkoordinasi port mana yang akan digunakan atau dialokasikan secara otomatis.
Akan sulit untuk mengkoordinasikan port yang digunakan oleh banyak pengembang. Kubernetes mengasumsikan bahwa Pod dapat berkomunikasi dengan Pod lain, terlepas di Node mana Pod tersebut di deploy. Kubernetes memberikan setiap Pod alamat ClusterIP sehingga kamu tidak perlu secara explisit membuat jalur antara Pod ataupun memetakan port kontainer ke dalam port di dalam Node tersebut. Ini berarti kontainer di dalam sebuah Pod dapat berkomunikasi dengan localhost via port, dan setiap Pod di dalam klaster dapat berkomunikasi tanpa NAT. Panduan ini akan membahas bagaimana kamu dapat menjalankan sebuah layanan atau aplikasi di dalam model jaringan di atas.
Panduan ini menggunakan server nginx sederhana untuk mendemonstrasikan konsepnya. Konsep yang sama juga ditulis lebih lengkap di Aplikasi Jenkins CI.
Mengekspos Pod ke dalam klaster
Kita melakukan ini di beberapa contoh sebelumnya, tetapi mari kita lakukan sekali lagi dan berfokus pada prespektif jaringannya. Buat sebuah nginx Pod, dan perhatikan bahwa templat tersebut mempunyai spesifikasi port kontainer:
Kamu dapat melakukan akses dengan ssh ke dalam node di dalam klaster dan mengakses IP Pod tersebut menggunakan curl. Perlu dicatat bahwa kontainer tersebut tidak menggunakan port 80 di dalam node, atau aturan NAT khusus untuk merutekan trafik ke dalam Pod. Ini berarti kamu dapat menjalankan banyak nginx Pod di node yang sama dimana setiap Pod dapat menggunakan containerPort yang sama, kamu dapat mengakses semua itu dari Pod lain ataupun dari node di dalam klaster menggunakan IP. Seperti Docker, port masih dapat di publikasi ke dalam * interface node*, tetapi kebutuhan seperti ini sudah berkurang karena model jaringannya.
Kita mempunyai Pod yang menjalankan nginx di dalam klaster. Teorinya, kamu dapat berkomunikasi ke Pod tersebut secara langsung, tapi apa yang terjadi jika sebuah node mati? Pod di dalam node tersebut ikut mati, dan Deployment akan membuat Pod baru, dengan IP yang berbeda. Ini adalah masalah yang Service selesaikan.
Service Kubernetes adalah sebuah abstraksi yang mendefinisikan sekumpulan Pod yang menyediakan fungsi yang sama dan berjalan di dalam klaster. Saat dibuat, setiap Service diberikan sebuah alamat IP (disebut juga ClusterIP). Alamat ini akan terus ada, dan tidak akan pernah berubah selama Service hidup. Pod dapat berkomunikasi dengan Service dan trafik yang menuju Service tersebut akan otomatis dilakukan mekanisme load balancing ke Pod yang merupakan anggota dari Service tersebut.
Kamu dapat membuat Service untuk replika 2 nginx dengan kubectl explose:
kubectl expose deployment/my-nginx
service/my-nginx exposed
Perintah di atas sama dengan kubectl apply -f dengan yaml sebagai berikut:
Spesifikasi ini akan membuat Service yang membuka TCP port 80 di setiap Pod dengan label run: my-nginx dan mengeksposnya ke dalam port Service (targetPort: adalah port kontainer yang menerima trafik, port adalah service port yang dapat berupa port apapun yang digunakan Pod lain untuk mengakses Service).
Lihat Service
objek API untuk melihat daftar field apa saja yang didukung di definisi Service. Cek Service kamu:
kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 <none> 80/TCP 21s
Seperti yang disebutkan sebelumnya, sebuah Service berisi sekumpulan Pod. Pod diekspos melalui endpoints. Service selector akan mengecek Pod secara terus-menerus dan hasilnya akan dikirim (POSTed) ke objek endpoint yang bernama my-nginx. Saat sebuah Pod mati, IP Pod di dalam endpoint tersebut akan otomatis dihapus, dan Pod baru yang sesuai dengan Service selector akan otomatis ditambahkan ke dalam endpoint. Cek endpoint dan perhatikan bahwa IP sama dengan Pod yang dibuat di langkah pertama:
NAME ENDPOINTS AGE
my-nginx 10.244.2.5:80,10.244.3.4:80 1m
Kamu sekarang dapat melakukan curl ke dalam nginx Service di <CLUSTER-IP>:<PORT> dari node manapun di klaster. Perlu dicatat bahwa Service IP adalah IP virtual, IP tersebut tidak pernah ada di interface node manapun. Jika kamu penasaran bagaimana konsep ini bekerja, kamu dapat membaca lebih lanjut tentang service proxy.
Mengakses Service
Kubernetes mendukung 2 mode utama untuk menemukan sebuah Service - variabel environment dan DNS.
DNS membutuhkan tambahan CoreDNS di dalam klaster.
Variabel Environment
Saat sebuah Pod berjalan di Node, kubelet akan menambahkan variabel environment untuk setiap Service yang aktif ke dalam Pod. Ini menimbulkan beberapa masalah. Untuk melihatnya, periksa environment dari Pod nginx yang telah kamu buat (nama Pod-mu akan berbeda-beda):
kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
Perlu dicatat tidak ada variabel environment yang menunjukan Service yang kamu buat. Ini terjadi karena kamu membuat replika terlebih dahulu sebelum membuat Service. Kerugian lain ditimbulkan adalah bahwa komponen scheduler mungkin saja bisa menempatkan semua Pod di dalam satu Node, yang akan membuat keseluruhan Service mati jika Node tersebut mati. Kita dapat menyelesaikan masalah ini dengan menghapus 2 Pod tersebut dan menunggu Deployment untuk membuat Pod kembali. Kali ini Service ada sebelum replika Pod tersebut ada. Ini akan memberikan kamu scheduler-level Service (jika semua Node kamu mempunyai kapasitas yang sama), serta variabel environment yang benar:
Kubernetes menawarkan sebuah layanan DNS klaster tambahan yang secara otomatis memberikan sebuah nama dns pada Service. Kamu dapat mengecek jika DNS berjalan di dalam klaster Kubernetes:
kubectl get services kube-dns --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.0.0.10 <none> 53/UDP,53/TCP 8m
Sisa panduan ini mengasumsikan kamu mempunyai Service dengan IP (my-nginx), dan sebuah server DNS yang memberikan nama ke dalam IP tersebut (CoreDNS klaster), jadi kamu dapat berkomunikasi dengan Service dari Pod lain di dalam klaster menggunakan metode standar (contohnya gethostbyname). Jalankan aplikasi curl lain untuk melakukan pengujian ini:
kubectl run curl --image=radial/busyboxplus:curl -i --tty
Waiting for pod default/curl-131556218-9fnch to be running, status is Pending, pod ready: false
Hit enter for command prompt
Hingga sekarang kita hanya mengakses nginx server dari dalam klaster. Sebelum mengekspos Service ke internet, kamu harus memastikan bahwa kanal komunikasi aman. Untuk melakukan hal tersebut, kamu membutuhkan:
Self signed certificates untuk https (kecuali jika kamu sudah mempunyai identity certificate)
Sebuah server nginx yang terkonfigurasi untuk menggunakan certificate tersebut
Sebuah secret yang membuat setifikat tersebut dapat diakses oleh pod
Kamu dapat melihat semua itu di contoh nginx https. Contoh ini mengaharuskan kamu melakukan instalasi go dan make. Jika kamu tidak ingin melakukan instalasi tersebut, ikuti langkah-langkah manualnya nanti, singkatnya:
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret Opaque 2 1m
Berikut ini adalah langkah-langkah manual yang harus diikuti jika kamu mengalami masalah menjalankan make (pada windows contohnya):
#membuat sebuah key-pair public privateopenssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /d/tmp/nginx.key -out /d/tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"#rubah key tersebut ke dalam pengkodean base64cat /d/tmp/nginx.crt | base64
cat /d/tmp/nginx.key | base64
Gunakan hasil keluaran dari perintah sebelumnya untuk membuat sebuah file yaml seperti berikut. Nilai yang dikodekan base64 harus berada di dalam satu baris.
kubectl apply -f nginxsecrets.yaml
kubectl get secrets
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret Opaque 2 1m
Sekarang modifikasi replika nginx untuk menjalankan server https menggunakan certificate di dalam secret dan Service untuk mengekspos semua port (80 dan 443):
Pada tahapan ini, kamu dapat berkomunikasi dengan server nginx dari node manapun.
kubectl get pods -o yaml | grep -i podip
podIP: 10.244.3.5
node $ curl -k https://10.244.3.5
...
<h1>Welcome to nginx!</h1>
Perlu dicatat bahwa kita menggunakan parameter -k saat menggunakan curl, ini karena kita tidak tau apapun tentang Pod yang menjalankan nginx saat pembuatan seritifikat, jadi kita harus memberitahu curl untuk mengabaikan ketidakcocokan CName. Dengan membuat Service, kita menghubungkan CName yang digunakan pada certificate dengan nama pada DNS yang digunakan Pod. Lakukan pengujian dari sebuah Pod (secret yang sama digunakan untuk agar mudah, Pod tersebut hanya membutuhkan nginx.crt untuk mengakses Service)
Kamu mungkin ingin mengekspos Service ke alamat IP eksternal. Kubernetes mendukung dua cara untuk melakukan ini: NodePort dan LoadBalancer. Service yang dibuat tadi sudah menggunakan NodePort, jadi replika nginx sudah siap untuk menerima trafik dari internet jika Node kamu mempunyai IP publik.
Mari coba membuat ulang Service menggunakan cloud load balancer, ubah saja typeServicemy-nginx dari NodePort ke LoadBalancer:
kubectl edit svc my-nginx
kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 162.222.184.144 80/TCP,81/TCP,82/TCP 21s
curl https://<EXTERNAL-IP> -k
...
<title>Welcome to nginx!</title>
IP address pada kolom EXTERNAL-IP menunjukan IP yang tersedia di internet. Sedangkan kolom CLUSTER-IP merupakan IP yang hanya tersedia di dalam klaster kamu (IP private).
Perhatikan pada AWS, tipe LoadBalancer membuat sebuah ELB, yang menggunakan hostname yang panjang, bukan IP. Karena tidak semua keluar pada standar keluaran kubectl get svc. Jadi kamu harus menggunakan kubectl describe service my-nginx untuk melihatnya. Kamu akan melihat seperti ini:
kubectl describe service my-nginx
...
LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
...
Selanjutnya
Kubernetes juga mendukung Federated Service, yang bisa mempengaruhi banyak klaster dan penyedia layanan cloud, untuk meningkatkan ketersediaan, peningkatan toleransi kesalahan, dan pengembangan dari Service kamu. Lihat Panduan Federated Service untuk informasi lebih lanjut.
5.6 - Ingress
Sebuah obyek API yang mengatur akses eksternal terhadap Service yang ada di dalam klaster, biasanya dalam bentuk request HTTP.
Ingress juga menyediakan load balancing, terminasi SSL, serta name-based virtual hosting.
Terminologi
Untuk memudahkan, di awal akan dijelaskan beberapa terminologi yang sering dipakai:
Node: Sebuah mesin fisik atau virtual yang berada di dalam klaster Kubernetes.
Klaster: Sekelompok node yang merupakan resource komputasi primer yang diatur oleh Kubernetes, biasanya diproteksi dari internet dengan menggunakan firewall.
Edge router: Sebuah router mengatur policy firewall pada klaster kamu. Router ini bisa saja berupa gateway yang diatur oleh penyedia layanan cloud maupun perangkat keras.
Jaringan klaster: Seperangkat links baik logis maupus fisik, yang memfasilitasi komunikasi di dalam klaster berdasarkan model jaringan Kubernetes.
Service: Sebuah Service yang mengidentifikasi beberapa Pod dengan menggunakan selector label. Secara umum, semua Service diasumsikan hanya memiliki IP virtual yang hanya dapat diakses dari dalam jaringan klaster.
Apakah Ingress itu?
Ingress ditambahkan sejak Kubernetes v1.1, mengekspos rute HTTP dan HTTPS ke berbagai
services di dalam klaster.
Mekanisme routing trafik dikendalikan oleh aturan-aturan yang didefinisikan pada Ingress.
internet
|
[ Ingress ]
--|-----|--
[ Services ]
Sebuah Ingress dapat dikonfigurasi agar berbagai Service memiliki URL yang dapat diakses dari eksternal (luar klaster), melakukan load balance pada trafik, terminasi SSL, serta Virtual Host berbasis Nama.
Sebuah kontroler Ingress bertanggung jawab untuk menjalankan fungsi Ingress yaitu sebagai loadbalancer, meskipun dapat juga digunakan untuk mengatur edge router atau frontend tambahan untuk menerima trafik.
Sebuah Ingress tidak mengekspos sembarang port atau protokol. Mengekspos Service untuk protokol selain HTTP ke HTTPS internet biasanya dilakukan dengan menggunakan
service dengan tipe Service.Type=NodePort atau
Service.Type=LoadBalancer.
Prasyarat
FEATURE STATE:Kubernetes v1.1 [beta]
Sebelum kamu mulai menggunakan Ingress, ada beberapa hal yang perlu kamu ketahui sebelumnya. Ingress merupakan resource dengan tipe beta.
Catatan: Kamu harus terlebih dahulu memiliki kontroler Ingress untuk dapat memenuhi Ingress. Membuat sebuah Ingress tanpa adanya kontroler Ingres tidak akan berdampak apa pun.
GCE/Google Kubernetes Engine melakukan deploy kontroler Ingress pada master. Perhatikan laman berikut
keterbatasan versi beta
kontroler ini jika kamu menggunakan GCE/GKE.
Secara ideal, semua kontroler Ingress harus memenuhi spesifikasi ini, tetapi beberapa
kontroler beroperasi sedikit berbeda satu sama lain.
Catatan: Pastikan kamu sudah terlebih dahulu memahami dokumentasi kontroler Ingress yang akan kamu pakai sebelum memutuskan untuk memakai kontroler tersebut.
Resource Ingress
Berikut ini merupakan salah satu contoh konfigurasi Ingress yang minimum:
Seperti layaknya resource Kubernetes yang lain, sebuah Ingress membutuhkan fieldapiVersion, kind, dan metadata.
Untuk informasi umum soal bagaimana cara bekerja dengan menggunakan berkas konfigurasi, silahkan merujuk pada melakukan deploy aplikasi, konfigurasi kontainer, mengatur resource.
Ingress seringkali menggunakan anotasi untuk melakukan konfigurasi beberapa opsi yang ada bergantung pada kontroler Ingress yang digunakan, sebagai contohnya
adalah anotasi rewrite-target.
Kontroler Ingress yang berbeda memiliki jenis anotasi yang berbeda. Pastikan kamu sudah terlebih dahulu memahami dokumentasi
kontroler Ingress yang akan kamu pakai untuk mengetahui jenis anotasi apa sajakah yang disediakan.
Spesifikasi Ingress
memiliki segala informasi yang dibutuhkan untuk melakukan proses konfigurasi loadbalancer atau server proxy. Hal yang terpenting adalah
bagian inilah yang mengandung semua rules yang nantinya akan digunakan untuk menyesuaikan trafik yang masuk. Resource Ingress hanya menyediakan
fitur rules untuk mengarahkan trafik dengan protokol HTTP.
Rule Ingress
Setiap rule HTTP mengandung informasi berikut:
Host opsional. Di dalam contoh ini, tidak ada host yang diberikan, dengan kata lain, semua rules berlaku untuk inbound
trafik HTTP bagi alamat IP yang dispesifikasikan. JIka sebuah host dispesifikasikan (misalnya saja,
foo.bar.com), maka rules yang ada akan berlaku bagi host tersebut.
Sederetan path (misalnya, /testpath), setiap path ini akan memiliki pasangan berupa sebuah backend yang didefinisikan dengan serviceName
dan servicePort. Baik host dan path harus sesuai dengan konten dari request yang masuk sebelum
loadbalancer akan mengarahkan trafik pada service yang sesuai.
Suatu backend adalah kombinasi service dan port seperti yang dideskripsikan di
dokumentasi Service. Request HTTP (dan HTTPS) yang sesuai dengan
host dan path yang ada pada rule akan diteruskan pada backend terkait.
Backend default seringkali dikonfigurasi pada kontroler kontroler Ingress, tugas backend default ini adalah
mengarahkan request yang tidak sesuai dengan path yang tersedia pada spesifikasi.
Backend Default
Sebuah Ingress yang tidak memiliki rules akan mengarahkan semua trafik pada sebuah backend default. Backend default inilah yang
biasanya bisa dimasukkan sebagai salah satu opsi konfigurasi dari kontroler Ingress dan tidak dimasukkan dalam spesifikasi resource Ingress.
Jika tidak ada host atau path yang sesuai dengan request HTTP pada objek Ingress, maka trafik tersebut
akan diarahkan pada backend default.
Jenis Ingress
Ingress dengan satu Service
Terdapat konsep Kubernetes yang memungkinkan kamu untuk mengekspos sebuah Service, lihat alternatif lain.
Kamu juga bisa membuat spesifikasi Ingress dengan backend default yang tidak memiliki rules.
Jika kamu menggunakan kubectl apply -f kamu dapat melihat:
kubectl get ingress test-ingress
NAME HOSTS ADDRESS PORTS AGE
test-ingress * 107.178.254.228 80 59s
Dimana 107.178.254.228 merupakan alamat IP yang dialokasikan oleh kontroler Ingress untuk
memenuhi Ingress ini.
Catatan: Kontroler Ingress dan load balancer membutuhkan waktu sekitar satu hingga dua menit untuk mengalokasikan alamat IP.
Hingga alamat IP berhasil dialokasikan, kamu akan melihat tampilan kolom ADDRESS sebagai <pending>.
Fanout sederhana
Sebuah konfigurasi fanout akan melakukan route trafik dari sebuah alamat IP ke banyak Service,
berdasarkan URI HTTP yang diberikan. Sebuah Ingress memungkinkan kamu untuk memiliki jumlah loadbalancer minimum.
Contohnya, konfigurasi seperti di bawah ini:
foo.bar.com -> 178.91.123.132 -> / foo service1:4200
/ bar service2:8080
Kontroler Ingress akan menyediakan loadbalancer (implementasinya tergantung dari jenis Ingress yang digunakan), selama service-service yang didefinisikan (s1, s2) ada.
Apabila Ingress selesai dibuat, maka kamu dapat melihat alamat IP dari berbagai loadbalancer
pada kolom address.
Catatan: Kamu mungkin saja membutuhkan konfigurasi default-http-backend Service
bergantung pada kontroler Ingress yang kamu pakai.
Virtual Host berbasis Nama
Virtual Host berbasis Nama memungkinkan mekanisme routing berdasarkan trafik HTTP ke beberapa host name dengan alamat IP yang sama.
Jika kamu membuat sebuah Ingress tanpa mendefinisikan host apa pun, maka
trafik web ke alamat IP dari kontroler Ingress tetap dapat dilakukan tanpa harus
menyesuaikan aturan name based virtual host. Sebagai contoh,
resource Ingress di bawah ini akan melakukan pemetaan trafik
dari first.bar.com ke service1, second.foo.com ke service2, dan trafik lain
ke alamat IP tanpa host name yang didefinisikan di dalam request (yang tidak memiliki request header) ke service3.
Kamu dapat mengamankan Ingress yang kamu miliki dengan memberikan spesifikasi secret
yang mengandung private key dan sertifikat TLS. Saat ini, Ingress hanya
memiliki fitur untuk melakukan konfigurasi single TLS port, yaitu 443, serta melakukan terminasi TLS.
Jika section TLS pada Ingress memiliki spesifikasi host yang berbeda,
rules yang ada akan dimultiplekskan pada port yang sama berdasarkan
hostname yang dispesifikasikan melalui ekstensi TLS SNI. Secret TLS harus memiliki
key bernama tls.crt dan tls.key yang mengandung private key dan sertifikat TLS, contohnya:
Ketika kamu menambahkan secret pada Ingress maka kontroler Ingress akan memberikan perintah untuk
memproteksi channel dari klien ke loadbalancer menggunakan TLS.
Kamu harus memastikan secret TLS yang digunakan memiliki sertifikat yang mengandung
CN untuk sslexample.foo.com.
Catatan: Terdapat perbedaan di antara beberapa fitur TLS
yang disediakan oleh berbagai kontroler Ingress. Perhatikan dokumentasi
nginx,
GCE, atau
kontroler Ingress spesifik platform lainnya untuk memahami cara kerja TLS
pada environment yang kamu miliki.
Loadbalancing
Sebuah kontroler Ingress sudah dibekali dengan beberapa policy terkait mekanisme load balance
yang nantinya akan diterapkan pada semua Ingress, misalnya saja algoritma load balancing, backend
weight scheme, dan lain sebagainya. Beberapa konsep load balance yang lebih advance
(misalnya saja persistent sessions, dynamic weights) belum diekspos melalui Ingress.
Meskipun begitu, kamu masih bisa menggunakan fitur ini melalui
loadbalancer service.
Perlu diketahui bahwa meskipun health check tidak diekspos secara langsung
melalui Ingress, terdapat beberapa konsep di Kubernetes yang sejalan dengan hal ini, misalnya
readiness probes
yang memungkinkan kamu untuk memperoleh hasil yang sama. Silahkan pelajari lebih lanjut dokumentasi
kontroler yang kamu pakai untuk mengetahui bagaimana implementasi health checks pada kontroler yang kamu pilih (nginx,
GCE).
Mengubah Ingress
Untuk mengubah Ingress yang sudah ada dan menambahkan host baru, kamu dapat mengubahnya dengan mode edit:
kubectl describe ingress test
Name: testNamespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo s1:80 (10.8.0.90:80)Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 35s loadbalancer-controller default/test
kubectl edit ingress test
Sebuah editor akan muncul dan menampilkan konfigurasi Ingress kamu
dalam format YAML apabila kamu telah menjalankan perintah di atas.
Ubah untuk menambahkan host:
Menyimpan konfigurasi dalam bentuk YAML ini akan mengubah resource pada API server,
yang kemudian akan memberi tahu kontroler Ingress untuk mengubah konfigurasi loadbalancer.
Kamu juga dapat mengubah Ingress dengan menggunakan perintah kubectl replace -f pada berkas konfigurasi
Ingress yang ingin diubah.
Mekanisme failing pada beberapa zona availability
Teknik untuk menyeimbangkan persebaran trafik pada failure domain berbeda antar penyedia layanan cloud.
Kamu dapat mempelajari dokumentasi yang relevan bagi kontoler Ingress
untuk informasi yang lebih detail. Kamu juga dapat mempelajari dokumentasi federasi
untuk informasi lebih detail soal bagaimana melakukan deploy untuk federasi klaster.
Pengembangan selanjutnya
Silahkan amati SIG Network
untuk detail lebih lanjut mengenai perubahan Ingress dan resource terkait lainnya. Kamu juga bisa melihat
repositori Ingress untuk informasi yang lebih detail
soal perubahan berbagai kontroler.
Alternatif lain
Kamu dapat mengekspos sebuah Service dalam berbagai cara, tanpa harus menggunakan resource Ingress, dengan menggunakan:
Agar Ingress dapat bekerja sebagaimana mestinya,
sebuah klaster harus memiliki paling tidak sebuah kontroler Ingress.
Berbeda dengan kontroler-kontroler lainnya yang dijalankan
sebagai bagian dari binarykube-controller-manager, kontroler Ingress
tidak secara otomatis dijalankan di dalam klaster. Kamu bisa menggunakan
laman ini untuk memilih implementasi kontroler Ingress yang kamu pikir
paling sesuai dengan kebutuhan kamu.
Kubernetes sebagai sebuah proyek, saat ini, mendukung dan memaintain kontroler-kontroler GCE dan
nginx.
Gloo adalah sebuah proyek kontroler Ingress open source berbasis Envoy yang menawarkan fungsionalitas API Gateway dengan dukungan enterprise dari solo.io.
Traefik adalah sebuah kontroler Ingress yang menyediakan semua fitur secara lengkap (fully featured)
(Let's Encrypt, secrets, http2, websocket), dengan tambahan dukungan
komersial oleh Containous.
Menggunakan beberapa jenis kontroler Ingress sekaligus
Kamu dapat melakukan deployberapa pun banyaknya kontroler Ingress
dalam sebuah klaster. Jika kamu ingin membuat Ingress, kamu tinggal memberikan anotasi setiap Ingress sesuai dengan
ingress.class
yang sesuai untuk menandai kontroler Ingress mana yang digunakan jika terdapat lebih dari satu kontroler Ingress yang ada di
klaster kamu.
Apabila kamu tidak mendefinisikan class yang dipakai, penyedia layanan cloud kamu akan menggunakan kontroler Ingress default yang mereka miliki.
Idealnya, semua ingress harus memenuhi spesifikasi ini, tetapi berbagai jenis
kontroler Ingress bisa saja memiliki sedikit perbedaan cara kerja.
Catatan: Pastikan kamu sudah terlebih dahulu memahami dokumentasi kontroler Ingress yang akan kamu pakai sebelum memutuskan untuk memakai kontroler tersebut.
Sebuah NetworkPolicy adalah spesifikasi dari sekelompok Pod atau endpoint yang diizinkan untuk saling berkomunikasi.
NetworkPolicy menggunakan label untuk memilih Pod serta mendefinisikan serangkaian rule yang digunakan
untuk mendefinisikan trafik yang diizinkan untuk suatu Pod tertentu.
Prasyarat
NetworkPolicy diimplementasikan dengan menggunakan plugin jaringan,
dengan demikian kamu harus memiliki penyedia jaringan yang mendukung NetworkPolicy -
membuat resource tanpa adanya controller tidak akan berdampak apa pun.
Pod yang terisolasi dan tidak terisolasi
Secara default, Pod bersifat tidak terisolasi; Pod-Pod tersebut
menerima trafik dari resource apa pun.
Pod menjadi terisolasi apabila terdapat NetworkPolicy yang dikenakan pada Pod-Pod tersebut.
Apabila terdapat NetworkPolicy di dalam namespace yang dikenakan pada suatu Pod, Pod tersebut
akan menolak koneksi yang tidak diizinkan NetworkPolicy. (Pod lain dalam namespace
yang tidak dikenakan NetworkPolicy akan tetap menerima trafik dari semua resource.)
ResourceNetworkPolicy
Lihat NetworkPolicy untuk definisi lengkap resource.
Sebuah contoh NetworkPolicy akan terlihat seperti berikut:
Mengirimkan ini ke API server dengan metode POST tidak akan berdampak apa pun
kecuali penyedia jaringan mendukung network policy.
Field-field yang bersifat wajib: Sama dengan seluruh config Kubernetes lainnya, sebuah NetworkPolicy
membutuhkan field-fieldapiVersion, kind, dan metadata. Informasi generik mengenai
bagaimana bekerja dengan fileconfig, dapat dilihat di
Konfigurasi Kontainer menggunakan ConfigMap,
serta Manajemen Objek.
spec: NetworkPolicyspec memiliki semua informasi yang harus diberikan untuk memberikan definisi network policy yang ada pada namespace tertentu.
podSelector: Setiap NetworkPolicy memiliki sebuah podSelector yang bertugas memfilter Pod-Pod yang dikenai policy tersebut. Contoh yang ada memfilter Pod dengan label "role=db". Sebuah podSelector yang empty akan memilih semua Pod yang ada di dalam namespace.
policyTypes: Setiap NetworkPolicy memiliki sebuah daftar policyTypes yang dapat berupa Ingress, Egress, atau keduanya. FieldpolicyTypes mengindikasikan apakah suatu policy diberikan pada trafik ingress, egress, atau camputan ingress dan egress pada Pod tertentu. Jika tidak ada policyTypes tyang diberikan pada NetworkPolicy maka Ingressdefault akan diterapkan dan Egress akan diterapkan apabila policy tersebut memberikan spesifikasi egress.
ingress: Setiap NetworkPolicy bisa saja memberikan serangkaian whitelist rule-ruleingress. Setiap rule mengizinkan trafik yang sesuai dengan sectionfrom dan ports. Contoh policy yang diberikan memiliki sebuah rule, yang sesuai dengan trafik pada sebuah portsingle, bagian pertama dispesifikasikan melalui ipBlock, yang kedua melalui namespaceSelector dan yang ketiga melalui podSelector.
egress: Setiap NetworkPolicy bisa saja meliputi serangkaian whitelistrule-ruleegress. Setiap rule mengizinkan trafik yang sesuai dengan sectionto dan ports. Contoh policy yang diberikan memiliki sebuah rule, yang sesuai dengan portsingle pada destinasi 10.0.0.0/24.
Pada contoh, NetworkPolicy melakukan hal berikut:
Mengisolasi Pod-Pod dengan label "role=db" pada namespace"default" baik untuk ingress atau egress.
(RuleIngress) mengizinkan koneksi ke semua Pod pada namespace“default” dengan label “role=db” untuk protokol TCP port6379 dari:
semua Pod pada namespace"default" dengan label "role=frontend"
semua Pod dalam sebuah namespace dengan label "project=myproject"
alamat IP pada range172.17.0.0–172.17.0.255 dan 172.17.2.0–172.17.255.255 (yaitu, semua 172.17.0.0/16 kecuali 172.17.1.0/24)
(Rule Egress) mengizinkan koneksi dari semua Pod pada namespace"default" dengan label "role=db" ke CIDR 10.0.0.0/24 untuk protokol TCP pada port5978
Terdapat empat jenis selektor yang dapat dispesifikasikan dalam sectioningressfrom atau sectionegressto:
podSelector: Ini digunakan untuk memfilter Pod tertentu pada namespace dimana NetworkPolicy berada yang akan mengatur destinasi ingress atau egress.
namespaceSelector: Ini digunakan untuk memfilter namespace tertentu dimana semua Pod diperbolehkan sebagai sourceingress atau destinasi egress.
namespaceSelectorandpodSelector: Sebuah entri to/from yang memberikan spesifikasi namespaceSelector dan podSelector serta memilih Pod-Pod tertentu yang ada di dalam namespace. Pastikan kamu menggunakan sintaks YAML yang tepat; policy ini:
mengandung sebuah elemen from yang mengizinkan koneksi dari Pod-Pod dengan label role=client di namespace dengan label user=alice. Akan tetapi, policyini:
mengandung dua elemen pada arrayfrom, dan mengizinkan koneksi dari Pod pada Namespace lokal dengan label
role=client, atau dari Pod di namespace apa pun dengan label user=alice.
Ketika kamu merasa ragu, gunakan kubectl describe untuk melihat bagaimana Kubernetes
menginterpretasikan policy tersebut.
ipBlock: Ini digunakan untuk memilih range IP CIDR tertentu untuk berperan sebagai
sourceingress atau destinasi egress. Alamat yang digunakan harus merupakan
alamat IP eksternal klaster, karena alamat IP Pod bersifat ephemeral dan tidak dapat ditebak.
Mekanisme ingress dan egress klaster seringkali membutuhkan mekanisme rewrite alamat IP source dan destinasi
paket. Pada kasus-kasus dimana hal ini, tidak dapat dipastikan bahwa apakah hal ini
terjadi sebelum atau setelah pemrosesan NetworkPolicy, dan perilaku yang ada mungkin saja berbeda
untuk kombinasi plugin jaringan, penyedia layanan cloud, serta implementasi Service yang berbeda.
Pada ingress, artinya bisa saja kamu melakukan filter paket yang masuk berdasarkan source IP,
sementara di kasus lain "source IP" yang digunakan oleh Network Policy adalah alamat IP LoadBalancer,
node dimana Pod berada, dsb.
Pada egress, bisa saja sebuah koneksi dari Pod ke IP Service di-rewrite ke IP eksternal klaster
atau bahkan tidak termasuk di dalam ipBlockpolicy.
PolicyDefault
Secara default, jika tidak ada policy yang ada dalam suatu namespace, maka semua trafik ingress dan egress yang diizinkan ke atau dari Pod dalam namespace.
Contoh di bawah ini akan memberikan gambaran bagaimana kamu dapat mengubah perilaku default pada sebuah namespace.
Default: tolak semua trafik ingress
Kamu dapat membuat policy isolasi "default" untuk sebuah namespace
dengan membuat sebuah NetworkPolicy yang memilih semua Pod tapi tidak mengizinkan
trafik ingress masuk ke Pod-Pod tersebut.
Hal ini menjamin bahwa bahkan Pod yang tidak dipilih oleh NetworkPolicy lain masih terisolasi.
Policy ini tidak mengubah perilaku default dari egress.
Default: izinkan semua trafik ingress
Jika kamu ingin mengizinkan semua trafik ingress pada semua Pod dalam sebuah namespace
(bahkan jika policy ditambahkan dan menyebabkan beberapa Pod menjadi terisolasi), kamu
dapat secara eksplisit mengizinkan semua trafik bagi namespace tersebut.
Kamu dapat membuat policy isolasi "default" untuk sebuah namespace
dengan membuat sebuah NetworkPolicy yang memilih semua Pod tapi tidak mengizinkan
trafik egress keluar dari Pod-Pod tersebut.
Hal ini menjamin bahwa bahkan Pod yang tidak dipilih oleh NetworkPolicy lain masih terisolasi.
Policy ini tidak mengubah perilaku default dari ingress.
Default: izinkan semua trafik egress
Jika kamu ingin mengizinkan semua trafik egress pada semua Pod dalam sebuah namespace
(bahkan jika policy ditambahkan dan menyebabkan beberapa Pod menjadi terisolasi), kamu
dapat secara eksplisit mengizinkan semua trafik bagi namespace tersebut.
Hal ini menjamin bahwa bahkan Pod yang tidak dipilih oleh NetworkPolicy tidak akan mengizinkan trafik ingress atau egress.
Dukungan terhadap SCTP
FEATURE STATE:Kubernetes v1.12 [alpha]
Kubernetes mendukung SCTP sebagai valueprotocol pada definisi NetworkPolicy sebagai fitur alpha. Untuk mengaktifkan fitur ini, administrator klaster harus mengaktifkan gerbang fitur SCTPSupport pada apiserver, contohnya “--feature-gates=SCTPSupport=true,...”. Ketika gerbang fitur ini diaktifkan, pengguna dapat menerapkan value dari fieldprotocol pada NetworkPolicy menjadi SCTP. Kubernetes akan mengatur jaringan sesuai dengan SCTP, seperti halnya koneksi TCP.
Plugin CNI harus mendukung SCTP sebagai value dari protocol pada NetworkPolicy.
Baca lebih lanjut soal panduan bagi skenario generik resourceNetworkPolicy.
5.9 - Menambahkan Entry pada /etc/hosts Pod dengan HostAliases
Menambahkan entri pada berkas /etc/hosts Pod akan melakukan override
resolusi hostname pada level Pod ketika DNS dan opsi lainnya tidak tersedia.
Pada versi 1.7, pengguna dapat menambahkan entri yang diinginkan beserta field HostAliases
pada PodSpec.
Modifikasi yang dilakukan tanpa menggunakan HostAliases tidaklah disarankan
karena berkas ini diatur oleh Kubelet dan dapat di-override ketika Pod dibuat/di-restart.
Isi Default pada Berkas Hosts
Misalnya saja kamu mempunyai sebuah Pod Nginx yang memiliki sebuah IP Pod:
kubectl run nginx --image nginx --generator=run-pod/v1
pod/nginx created
Perhatikan IP Pod tersebut:
kubectl get pods --output=wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
Secara default, berkas hosts hanya berisikan boilerplate alamat IP IPv4 and IPv6 seperti
localhost dan hostname dari Pod itu sendiri.
Menambahkan Entri Tambahan dengan HostAliases
Selain boilerplate default, kita dapat menambahkan entri pada berkas
hosts untuk melakukan resolusi foo.local, bar.local pada 127.0.0.1 dan foo.remote,
bar.remote pada 10.1.2.3, kita dapat melakukannya dengan cara menambahkan
HostAliases pada Pod di bawah field.spec.hostAliases:
Dengan tambahan entri yang telah dispesifikasikan sebelumnya.
Kenapa Kubelet Melakukan Mekanisme Manajemen Berkas Hosts?
Kubelet melakukan proses manajemen
berkas hosts untuk setiap container yang ada pada Pod untuk mencegah Docker melakukan
modifikasi pada berkas tersebut
setelah kontainer dihidupkan.
Karena sifat dari berkas tersebut yang secara otomatis di-manage,
semua hal yang didefinisikan oleh pengguna akan ditimpa (overwrite) ketika berkas
hosts di-mount kembali oleh Kubelet ketika ada kontainer yang di-restart
atau Pod di-schedule ulang. Dengan demikian tidak dianjurkan untuk
memodifikasi berkas tersebut secara langsung.
5.10 - Dual-stack IPv4/IPv6
FEATURE STATE:Kubernetes v1.16 [alpha]
Dual-stack IPv4/IPv6 memungkinkan pengalokasian alamat IPv4 dan IPv6 untuk
Pod dan Service.
Jika kamu mengaktifkan jaringan dual-stack IPv4/IPv6 untuk klaster Kubernetes
kamu, klaster akan mendukung pengalokasian kedua alamat IPv4 dan IPv6 secara
bersamaan.
Fitur-fitur yang didukung
Mengaktifkan dual-stack IPv4 / IPv6 pada klaster Kubernetes kamu untuk
menyediakan fitur-fitur berikut ini:
Jaringan Pod dual-stack (pengalokasian sebuah alamat IPv4 dan IPv6 untuk setiap Pod)
Service yang mendukung IPv4 dan IPv6 (setiap Service hanya untuk satu keluarga alamat)
Perutean Pod ke luar klaster (misalnya Internet) melalui antarmuka IPv4 dan IPv6
Prasyarat
Prasyarat berikut diperlukan untuk menggunakan dual-stack IPv4/IPv6 pada
klaster Kubernetes :
Kubernetes versi 1.16 atau yang lebih baru
Dukungan dari penyedia layanan untuk jaringan dual-stack (Penyedia layanan cloud atau yang lainnya harus dapat menyediakan antarmuka jaringan IPv4/IPv6 yang dapat dirutekan) untuk Node Kubernetes
Sebuah plugin jaringan yang mendukung dual-stack (seperti Kubenet atau Calico)
Kube-proxy yang berjalan dalam mode IPVS
Mengaktifkan dual-stack IPv4/IPv6
Untuk mengaktifkan dual-stack IPv4/IPv6, aktifkan gerbang fitur (feature gate)IPv6DualStack
untuk komponen-komponen yang relevan dari klaster kamu, dan tetapkan jaringan
dual-stack pada klaster:
kube-controller-manager:
--feature-gates="IPv6DualStack=true"
--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR> misalnya --cluster-cidr=10.244.0.0/16,fc00::/24
--node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6 nilai bawaannya adalah /24
untuk IPv4 dan /64 untuk IPv6
kubelet:
--feature-gates="IPv6DualStack=true"
kube-proxy:
--proxy-mode=ipvs
--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>
--feature-gates="IPv6DualStack=true"
Perhatian: Jika kamu menentukan blok alamat IPv6 yang lebih besar dari /24 melalui
--cluster-cidr pada baris perintah, maka penetapan tersebut akan gagal.
Service
Jika klaster kamu mengaktifkan jaringan dual-stack IPv4/IPv6, maka kamu dapat
membuat Service dengan
alamat IPv4 atau IPv6. Kamu dapat memilih keluarga alamat untuk clusterIP Service kamu dengan mengatur bagian, .spec.ipFamily, pada Service tersebut.
Kamu hanya dapat mengatur bagian ini saat membuat Service baru. Mengatur bagian
.spec.ipFamily bersifat opsional dan hanya boleh digunakan jika kamu berencana
untuk mengaktifkan Service
dan Ingress IPv4 dan IPv6
pada klaster kamu. Konfigurasi bagian ini bukanlah syarat untuk lalu lintas
[egress] (#lalu-lintas-egress).
Catatan: Keluarga alamat bawaan untuk klaster kamu adalah keluarga alamat dari rentang
clusterIP Service pertama yang dikonfigurasi melalui opsi
--service-cluster-ip-range pada kube-controller-manager.
Kamu dapat mengatur .spec.ipFamily menjadi salah satu dari:
IPv4: Dimana server API akan mengalokasikan IP dari service-cluster-ip-range yaitu ipv4
IPv6: Dimana server API akan mengalokasikan IP dari service-cluster-ip-range yaitu ipv6
Spesifikasi Service berikut ini tidak memasukkan bagian ipFamily.
Kubernetes akan mengalokasikan alamat IP (atau yang dikenal juga sebagai
"cluster IP") dari service-cluster-ip-range yang dikonfigurasi pertama kali
untuk Service ini.
Spesifikasi Service berikut memasukkan bagian ipFamily. Sehingga Kubernetes
akan mengalokasikan alamat IPv6 (atau yang dikenal juga sebagai "cluster IP")
dari service-cluster-ip-range yang dikonfigurasi untuk Service ini.
Sebagai perbandingan, spesifikasi Service berikut ini akan dialokasikan sebuah alamat
IPv4 (atau yang dikenal juga sebagai "cluster IP") dari service-cluster-ip-range
yang dikonfigurasi untuk Service ini.
Penyedia layanan cloud yang mendukung IPv6 untuk pengaturan beban eksternal,
Mengatur bagian type menjadi LoadBalancer sebagai tambahan terhadap mengatur bagian
ipFamily menjadi IPv6 menyediakan sebuah cloud load balancer untuk Service kamu.
Lalu lintas egress
Penggunaan blok alamat IPv6 yang dapat dirutekan dan yang tidak dapat dirutekan
secara publik diperbolehkan selama CNI
dari penyedia layanan dapat mengimplementasikan transportasinya. Jika kamu memiliki
Pod yang menggunakan IPv6 yang dapat dirutekan secara publik dan ingin agar Pod
mencapai tujuan di luar klaster (misalnya Internet publik), kamu harus mengatur
IP samaran untuk lalu lintas keluar dan balasannya. ip-masq-agent
bersifat dual-stack aware, jadi kamu bisa menggunakan ip-masq-agent untuk
masquerading IP dari klaster dual-stack.
Masalah-masalah yang diketahui
Kubenet memaksa pelaporan posisi IP untuk IPv4,IPv6 IP (--cluster-cidr)
Berkas-berkas yang disimpan di disk di dalam Container bersifat tidak permanen (akan terhapus seiring dengan dihapusnya Container/Pod), yang menimbulkan beberapa masalah untuk aplikasi biasa saat berjalan di dalam Container. Pertama, saat sebuah Container mengalami kegagalan, Kubelet akan memulai kembali Container tersebut, tetapi semua berkas di dalamnya akan hilang - Container berjalan dalam kondisi yang bersih. Kedua, saat menjalankan banyak Container bersamaan di dalam sebuah Pod, biasanya diperlukan untuk saling berbagi berkas-berkas di antara Container-container tersebut. Kedua masalah tersebut dipecahkan oleh abstraksi Volume pada Kubernetes.
Docker juga memiliki konsep volume, walaupun konsepnya Docker agak lebih fleksibel dan kurang dikelola. Pada Docker, sebuah volume adalah sesederhana sebuah direktori pada disk atau di dalam Container lainnya. Lifetime tidak dikelola dan hingga baru-baru ini hanya ada volume yang didukung disk lokal. Docker sekarang menyediakan driver untuk volume, namun fungsionalitasnya masih sangat terbatas (misalnya hingga Docker 1.7 hanya ada satu driver volume yang diizinkan untuk setiap Container, dan tidak ada cara untuk menyampaikan parameter kepada volume).
Sebaliknya, sebuah Volume Kubernetes memiliki lifetime yang gamblang - sama dengan lifetime Pod yang berisi Volume tersebut. Oleh karena itu, sebuah Volume bertahan lebih lama dari Container-container yang berjalan di dalam Pod tersebut, dan data di Volum tersebut juga dipertahankan melewati diulangnya Container. Tentu saja, saat sebuah Pod berakhir, Volume tersebut juga akan berakhir/terhapus. Dan mungkin lebih penting lagi, Kubernetes mendukung banyak jenis Volume, dan sebuah Pod dapat menggunakan sebanyak apapun Volume secara bersamaan.
Pada intinya, sebuah volume hanyalah sebuah direktori, dan mungkin berisi data, yang dapat diakses oleh Container-container di dalam Pod. Bagaimana direktori tersebut dibuat, medium yang menyokongnya, dan isinya ditentukan oleh jenis volume yang digunakan.
Untuk menggunakan sebuah volume, sebuah Pod memerinci volume-volume yang akan disediakan untuk Pod tersebut (kolom .spec.volumes) dan di mana volume-volume tersebut akan ditambatkan (di-mount) di dalam Container-container di Pod (kolom .spec.containers.volumeMounts).
Sebuah proses di dalam Container memiliki sudut pandang filesystem yang disusun dari image dan volume Dockernya. Docker Image berada pada bagian teratas hierarki filesystem, dan volume manapun yang ditambatkan pada path yang diperinci di dalam Image tersebut. Volume tidak dapat ditambatkan pada volume lain atau memiliki hard link ke volume lain. Setiap Container di dalam Pod harus secara independen memerinci di mana tiap Volume ditambatkan.
Sebuah Volume awsElasticBlockStore menambatkan sebuah Volume EBS Amazon Web Services (AWS) ke dalam Pod kamu. Hal ini berarti bahwa sebuah Volume EBS dapat sebelumnya diisi terlebih dahulu dengan data, dan data dapat "dipindahkan" diantara banyak Pod.
Perhatian: Kamu harus membuat sebuah volume EBS menggunakan awscli dengan perintah aws ec2 create-volume atau menggunakan AWS API sebelum kamu dapat menggunakannya.
Ada beberapa batasan saat menggunakan Volume awsElasticBlockStore:
Node di mana Pod berjalan haruslah merupakan instance AWS EC2.
Instance tersebut mesti berada pada regiondanavailability-zone yang sama dengan volume EBS.
EBS hanya mendukung penambatan pada satu instance EC2 pada saat yang bersamaan.
Membuat sebuah Volume EBS
Sebelum kamu dapat menggunakan sebuah volume EBS pada sebuah Pod, kamu harus membuatnya pada AWS terlebih dahulu.
Pastikan availability zone yang kamu masukkan sama dengan availability zone klaster kamu. (Dan pastikan juga ukuran dan jenis EBSnya sesuai dengan penggunaan yang kamu butuhkan!)
Contoh Konfigurasi AWS EBS
apiVersion:v1kind:Podmetadata:name:test-ebsspec:containers:- image:k8s.gcr.io/test-webservername:test-containervolumeMounts:- mountPath:/test-ebsname:test-volumevolumes:- name:test-volume# volume EBS ini harus sudah dibuat di AWSawsElasticBlockStore:volumeID:<volume-id>fsType:ext4
Migrasi CSI awsElasticBlocStore
FEATURE STATE:Kubernetes v1.14 [alpha]
Pada saat fitur migrasi CSI (Container Storage Interface) untuk awsElasticBlockStore diaktifkan, fitur ini akan menterjemahkan semua operasi plugin dari plugin yang sudah ada di kode inti Kubernetes ke bentuk Driver CSI ebs.csi.aws.com. Untuk menggunakan fitur ini, Driver CSI AWS EBS harus dinstal di klaster dan fitur Alpha CSIMigration serta CSIMigrationAWS harus diaktifkan.
azureDisk
Sebuah azureDisk digunakan untuk menambatkan sebuah Data Disk Microsoft Azure ke dalam sebuah Pod.
Pada saat fitur migrasi CSI untuk azureDisk diaktifkan, fitur ini akan menterjemahkan semua operasi plugin dari plugin yang sudah ada di kode inti Kubernetes ke bentuk Driver CSI disk.csi.azure.com. Untuk menggunakan fitur ini, Driver CSI Azure Disk harus dinstal di klaster dan fitur Alpha CSIMigration serta CSIMigrationAzureDisk harus diaktifkan.
azureFile
Sebuah azureFile digunakan untuk menambatkan sebuah Microsoft Azure File Volume (SMB 2.1 dan 3.0) ke dalam sebuah Pod.
Pada saat fitur migrasi CSI untuk azureFile diaktifkan, fitur ini akan menterjemahkan semua operasi plugin dari plugin yang sudah ada di kode inti Kubernetes ke bentuk Driver CSI file.csi.azure.com. Untuk menggunakan fitur ini, Driver CSI Azure File harus dinstal di klaster dan fitur Alpha CSIMigration serta CSIMigrationAzureFile harus diaktifkan.
cephfs
Sebuah Volume cephfs memungkinkan sebuah volume CephFS yang sudah ada untuk ditambatkan ke dalam Pod kamu. Berbeda dengan emptyDir, yang juga ikut dihapus saat Pod dihapus, isi data di dalam sebuah volume CephFS akan dipertahankan dan Volume tersebut hanya dilepaskan tambatannya (mount-nya). Hal ini berarti bahwa sebuah Volume CephFS dapat sebelumnya diisi terlebih dahulu dengan data, dan data dapat "dipindahkan" diantara banyak Pod.
Perhatian: Kamu harus memiliki server Ceph sendiri dan mengekspor share-nya sebelum kamu dapat menggunakannya.
Catatan: Prasyarat: Kubernetes dengan penyedia layanan cloud OpenStack yang telah dikonfigurasikan. Untuk konfigurasi penyedia layanan cloud, silahkan lihat penyedia layanan cloud openstack.
cinder digunakan untuk menambatkan Volume Cinder ke dalam Pod kamu.
Contoh Konfigurasi Volume Cinder
apiVersion:v1kind:Podmetadata:name:test-cinderspec:containers:- image:k8s.gcr.io/test-webservername:test-cinder-containervolumeMounts:- mountPath:/test-cindername:test-volumevolumes:- name:test-volume# Volume OpenStack ini harus sudah ada sebelumnya.cinder:volumeID:<volume-id>fsType:ext4
Migrasi CSI Cinder
FEATURE STATE:Kubernetes v1.14 [alpha]
Pada saat fitur migrasi CSI untuk Cinder diaktifkan, fitur ini akan menterjemahkan semua operasi plugin dari plugin yang sudah ada di kode inti Kubernetes ke bentuk Driver CSI cinder.csi.openstack.com. Untuk menggunakan fitur ini, Driver CSI Openstack Cinder harus dinstal di klaster dan fitur Alpha CSIMigration serta CSIMigrationOpenStack harus diaktifkan.
configMap
Sumber daya configMap memungkinkan kamu untuk menyuntikkan data konfigurasi ke dalam Pod.
Data yang ditaruh di dalam sebuah objek ConfigMap dapat dirujuk dalam sebuah Volume dengan tipe configMap dan kemudian digunakan oleh aplikasi/container yang berjalan di dalam sebuah Pod.
Saat mereferensikan sebuah objek configMap, kamu tinggal memasukkan nama ConfigMap tersebut ke dalam rincian Volume yang bersangkutan. Kamu juga dapat mengganti path spesifik yang akan digunakan pada ConfigMap. Misalnya, untuk menambatkan ConfigMap log-config pada Pod yang diberi nama configmap-pod, kamu dapat menggunakan YAML ini:
ConfigMap log-config ditambatkan sebagai sebuah Volume, dan semua isinya yang ditaruh di dalam entri log_level-nya ditambatkan dalam Pod tersebut pada path "/etc/config/log_level".
Perlu dicatat bahwa path tersebut berasal dari isian mountPath pada Volume, dan path yang ditunjuk dengan key bernama log_level.
Perhatian: Kamu harus membuat sebuah ConfigMap sebelum kamu dapat menggunakannya.
Catatan: Sebuah Container yang menggunakan sebuah ConfigMap sebagai tambatan Volume subPath tidak akan menerima pembaruan ConfigMap.
downwardAPI
Sebuah Volume downwardAPI digunakan untuk menyediakan data downward API kepada aplikasi.
Volume ini menambatkan sebuah direktori dan menulis data yang diminta pada berkas-berkas teks biasa.
Catatan: Sebuah Container yang menggunakan Downward API sebagai tambatan Volume subPath tidak akan menerima pembaruan Downward API.
Sebuah Volume emptyDir pertama kali dibuat saat sebuah Pod dimasukkan ke dalam sebuah Node, dan akan terus ada selama Pod tersebut berjalan di Node tersebut. Sesuai dengan namanya, Volume ini awalnya kosong. Container-container di dalam Pod dapat membaca dan menulis berkas-berkas yang sama di dalam Volume emptyDir, walaupun Volume tersebut dapat ditambatkan pada path yang sama maupun berbeda pada setiap Container. Saat sebuah Pod dihapus dari sebuah Node untuk alasan apapun, data di dalam emptyDir tersebut dihapus untuk selamanya.
Catatan: Sebuah Container yang gagal TIDAK AKAN menghapus sebuah Pod dari sebuah Node, sehingga data di dalam sebuah emptyDir akan aman jika Container di dalam Podnya gagal.
Beberapa kegunaan emptyDir adalah sebagai berikut:
Scratch space, misalnya untuk merge sort menggunakan berkas-berkas di disk
Checkpointing untuk komputasi panjang yang dipulihkan dari proses yang sebelumnya mengalami kegagalan
Menyimpan berkas-berkas yang diambil oleh Container aplikasi Content Manager saat sebuah peladen web melayani data tersebut
Secara bawaan, emptyDir ditaruh pada media penyimpanan apapun yang menyokong Node yang bersangkuta - mungkin sebuah disk atau SSD atau penyimpanan berbasis jaringan, tergantung lingkungan Node yang kamu miliki. Tetapi, kamu juga dapat menyetel bagian emptyDir.medium menjadi "Memory" untuk memberitahukan pada Kubernetes untuk menggunakan sebuah tmpfs (filesystem berbasis RAM) sebagai gantinya. tmpfs memang sangan cepat, tetapi kamu harus sadar bahwa ia tidak seperti disk, data di tmpfs akan terhapus saat Node tersebut diulang kembali. Selain itu, berkas apapun yang kamu tulis akan dihitung terhadap limitmemory milik Container kamu.
Sebuah Volume fc memunginkan sebuah volumefibre channel yang sudah ada untuk ditambatkan ke sebuah Pod.
Kamu dapat menentukan satu atau banyak target World Wide Names menggunakan parameter targetWWNs pada konfigurasi Volume kamu. Jika banyak WWN ditentukan, maka targetWWNs mengharapkan bahwa WWN tersebut berasal dari koneksi multi-path.
Perhatian: Sebelumnya, kamu harus mengkonfigurasikan FC SAN Zoning untuk mengalokasikan dan melakukan masking terhadap LUN (volume) tersebut terhadap target WWN sehingga Node-node Kubernetes dapat mengakses mereka.
Flocker adalah sebuah proyek open-source yg berfungsi sebagai pengatur volume data Container yang diklasterkan. Flocker menyediakan pengelolaan dan orkestrasi volume yang disokong oleh banyak jenis media penyimpanan.
Sebuah Volume flockere memungkinkan sebuah dataset Flocker untuk ditambatkan ke dalam sebuah Pod. Jika dataset tersebut belum ada di dalam Flocker, maka ia harus dibuat terlebih dahulu dengan menggunakan Flocker CLI atau menggunakan Flocker API. Jika dataset tersebut sudah ada, ia akan ditambatkan kembali oleh Flocker ke Node di mana Pod tersebut dijadwalkan. Hal ini berarti data dapat dioper diantara Pod-pod sesuai dengan kebutuhan.
Perhatian: Kamu harus memiliki instalasi Flocker yang sudah berjalan sebelum kamu dapat menggunakannya.
Sebuah volumegcePersistentDisk menambatkan sebuah PersistentDisk Google Compute Engine (GCE) ke dalam Pod kamu. Tidak seperti emptyDir yang ikut dihapus saat Pod dihapus, isi dari sebuah PD dipertahankan dan volume-nya hanya dilepaskan tambatannya. Hal ini berarti sebuah PD dapat diisi terlebih dahulu dengan data, dan data tersebut dapat "dioper" diantara Pod-pod.