This is the multi-page printable view of this section. Click here to print.
Kontainer
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.
Kontainer runtime
Kontainer runtime adalah perangkat lunak yang bertanggung jawab untuk menjalankan kontainer. Kubernetes mendukung beberapa kontainer runtime: Docker, containerd, CRI-O, dan semua implementasi dari Kubernetes CRI (Container Runtime Interface).
Selanjutnya
- Baca tentang image-image kontainer
- Baca tentang Pod
2 - Image
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 menjadiAlways
. - buang
imagePullPolicy
dan gunakan:latest
tag untuk image yang digunakan. - buang
imagePullPolicy
dan juga tag untuk image. - aktifkan AlwaysPullImages admission controller.
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.
Lihat dokumentasi docker di sini: https://docs.docker.com/edge/engine/reference/commandline/manifest/
Lihat contoh-contoh bagaimana kami menggunakan ini untuk proses build harness: https://cs.k8s.io/?q=docker%20manifest%20(create%7Cpush%7Cannotate)&i=nope&files=&repos=
Perintah-perintah ini bergantung pada Docker CLI, dan diimplementasi hanya di sisi CLI. Kamu harus mengubah $HOME/.docker/config.json
dan mengatur key experimental
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.
Menggunakan Amazon Elastic Container Registry
Kubernetes memiliki dukungan native untuk Amazon Elastic Container Registry, ketika Node adalah AWS EC2 instance.
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 adminDOCKER_PASSWORD
: kata sandi dari service principal, atau kata sandi dari pengguna adminDOCKER_REGISTRY_SERVER
:${some-registry-name}.azurecr.io
DOCKER_EMAIL
:${some-email-address}
Ketika kamu sudah memiliki variabel-variabel di atas, kamu dapat mengkonfigurasi sebuah Kubernetes Secret dan menggunakannya untuk deploy sebuah Pod.
Menggunakan IBM Cloud Container Registry
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.
Untuk instalasi plugin CLI di IBM Cloud Containerr Registry dan membuat sebuah namespace untuk image-image kamu, lihat Mulai dengan IBM Cloud Container Registry.
Jika kamu menggunakan akun dan wilayah (region) yang sama, kamu dapat melakukan deploy image-image yang disimpan di dalam IBM Cloud Container Registry ke dalam namespace default dari klaster IBM Cloud Kubernetes Service yang kamu miliki tanpa konfigurasi tambahan, lihat Membuat kontainer dari image. Untuk opsi konfigurasi lainnya, lihat Bagaimana cara mengotorasi klaster untuk mengunduh image dari sebuah registri.
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 bagianauths
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 mengaturHOME=/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}')
- jika kamu ingin mendapatkan nama:
- 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
- contohnya:
Verifikasi dengana membuat sebuah Pod yanag menggunakan image privat, contohnya:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: private-image-test-1
spec:
containers:
- name: uses-private-image
image: $PRIVATE_IMAGE_NAME
imagePullPolicy: Always
command: [ "echo", "SUCCESS" ]
EOF
pod/private-image-test-1 created
Jika semuanya berjalan dengan baik, maka setelah beberapa lama, kamu dapat menjalankan:
kubectl logs private-image-test-1
dan lihat pada keluaran perintah:
SUCCESS
Jika kamu mencurigai ada perintah yang gagal, kamu dapat menjalankan:
kubectl describe pods/private-image-test-1 | grep 'Failed'
Pada kasus gagal, keluarannya mirip seperti:
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:
kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
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.
cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
EOF
cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF
Cara ini perlu untuk diselesaikan untuk setiap Pod yang mengguunakan registri privat.
Hanya saja, mengatur field ini dapat diotomasi dengan mengatur imagePullSecrets di dalam sumber daya serviceAccount. Periksa Tambahan ImagePullSecrets untuk sebuah Service Account untuk instruksi yang lebih detail.
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.
- Gunakan image publik pada Docker hub.
- Klaster yang menjalankan image proprietary yang seharusnya disembunyikan dari luar perusahaan, tetapi bisa terlihat oleh pengguna klaster.
- Gunakan sebuah privat registri Docker yang hosted.
- Bisa saja di-host pada Docker Hub, atau lainnya.
- Konfigurasi
.docker/config.json
secara manual pada setiap Node seperti dijelaskan di atas.
- Atau, jalankan sebuah registri privat internal di belakang firewall kamu dengan akses baca terbuka.
- Tidak ada konfigurasi Kubernetes yang diperlukan.
- Atau, ketika pada GCE/Google Kubernetes Engine, menggunakan Google Container Registry yang ada di proyek.
- Hal ini bisa bekerja baik dengan autoscaling klaster dibandingkan konfigurasi Node manual.
- Atau, pada sebuah klaster dimana mengubah konfigurasi Node tidak nyaman, gunakan
imagePullSecrets
.
- Gunakan sebuah privat registri Docker yang hosted.
- Klaster dengan image proprietary, beberapa memerlukan akses kontrol yang lebih ketat.
- Pastikan AlwaysPullImages admission controller aktif. Sebaliknya, semua Pod berpotensi memiliki akses ke semua image.
- Pindahkan data sensitif pada sumber daya "Secret", daripada mengemasnya menjadi sebuah image.
- Sebuah klaster multi-tenant dimana setiap tenant memerlukan registri privatnya masing-masing.
- Pastikan AlwaysPullImages admission controller aktif. Sebaliknya, semua Pod dari semua tenant berpotensi memiliki akses pada semua image.
- 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 merge imagePullSecrets
manapun menjadi sebuah virtual .docker/config.json
.
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.
Selanjutnya
- Pelajari lebih lanjut tentang berbagai hook pada lifecycle Kontainer.
- Dapatkan pengalaman praktis soal memberikan handler untuk event dari lifecycle Kontainer.
4 - Runtime Class
Kubernetes v1.14 [beta]
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 resource RuntimeClass
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.io
kind: RuntimeClass
metadata:
name: myclass # Nama dari RuntimeClass yang nantinya akan dijadikan referensi
# RuntimeClass merupakan resource tanpa namespace
handler: 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:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
runtimeClassName: myclass
# ...
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 tahap Failed
.
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.
containerd
Handler runtime diatur melalui konfigurasi containerd pada /etc/containerd/config.toml
.
Handler yang valid dapat dikonfigurasi pada bagian runtime:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${HANDLER_NAME}]
Lihat dokumentasi konfigurasi containerd untuk lebih detail: https://github.com/containerd/containerd/blob/main/docs/cri/config.md
cri-o
Handler runtime dapat diatur menggunakan konfigurasi cri-o pada /etc/crio/crio.conf
.
Handler yang valid dapat dikonfigurasi pada tabel crio.runtime:
[crio.runtime.runtimes.${HANDLER_NAME}]
runtime_path = "${PATH_TO_BINARY}"
Lihat dokumentasi konfigurasi cri-o untuk lebih detail: https://github.com/kubernetes-sigs/cri-o/blob/master/cmd/crio/config.go
Memperbarui RuntimeClass dari Alpha ke Beta
Fitur Beta pada RuntimeClass memiliki perubahan sebagai berikut:
- Grup API resource
node.k8s.io
danruntimeclasses.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). - Field
runtimeHandler
telah berubah nama menjadihandler
. - Field
handler
sekarang bersifat wajib untuk semua versi API. Artinya, fieldruntimeHandler
pada API Alpha juga bersifat wajib. - Field
handler
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:kubectl delete customresourcedefinitions.apiextensions.k8s.io runtimeclasses.node.k8s.io
- 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).
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 hook PreStop
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 hook PostStart
, Kontainer ENTRYPOINT
dan hook dieksekusi secara asyncrhonous. Akan tetapi, jika hook mengambil waktu terlalu lama,
atau hang, Kontainer tersebut tidak bisa sampai ke state running
.
Perilaku ini mirip dengan yang terjadi pada hook PreStop
.
Jika hook terlalu lama atau hang saat dieksekusi, Pod tersebut tetap ada pada state Terminating
dan akan dimatikan setelah terminationGracePeriodSeconds
Pod selesai.
Jika sebuah hook PostStart
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 debug handler 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 event FailedPostStartHook
,
dan untuk PreStop
, akan dilakukan broadcast event FailedPreStopHook
.
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
Selanjutnya
- Pelajari lebih lanjut tentang environment Kontainer.
- Pelajari bagaimana caranya melakukan attach handler pada event lifecycle sebuah Kontainer.