This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Tugas

Bagian dokumentasi Kubernetes ini berisi halaman-halaman yang perlihatkan bagaimana melakukan setiap tugas (task). Halaman tugas menunjukkan cara melakukan satu hal saja, biasanya dengan memberikan urutan langkah pendek.

Antarmuka Pengguna Berbasis Web (Dashboard)

Melakukan deploy dan mengakses dashboard berbasis web untuk membantu kamu mengelola dan memantau aplikasi yang dimasukkan ke dalam container di Kubernetes.

Menggunakan Baris Perintah kubectl

Instalasi dan konfigurasi utilitas baris perintah kubectl yang digunakan untuk mengelola secara langsung klaster Kubernetes.

Mengkonfigurasi Pod dan Container

Melakukan tugas konfigurasi yang umum untuk Pod dan Container.

Menjalankan Aplikasi

Melakukan tugas manajemen aplikasi secara umum, seperti rolling updates, memasukkan informasi ke dalam Pod, dan penskalaan Pod secara horisontal.

Menjalankan Job

Menjalankan Job dengan menggunakan pemrosesan paralel.

Mengakses Aplikasi dalam Klaster

Mengkonfigurasi load balancing, port forwarding, atau membangun firewall atau konfigurasi DNS untuk mengakses aplikasi dalam sebuah klaster.

Monitoring, Logging, dan Debugging

Mengatur monitoring (pemantauan) dan logging (pencatatan) untuk memecahkan masalah klaster atau melakukan debug (pelacakan) aplikasi yang dikontainerisasi.

Mengakses API Kubernetes

Mempelajari berbagai metode untuk mengakses API Kubernetes secara langsung.

Menggunakan TLS

Mengkonfigurasi aplikasi kamu untuk percaya dan menggunakan klaster Certificate Authority (CA).

Mengelola Klaster

Mempelajari tugas umum untuk mengelola klaster.

Mengelola Aplikasi yang Stateful

Melakukan tugas umum untuk mengelola aplikasi yang Stateful, termasuk penskalaan, penghapusan, dan debugging StatefulSets.

Daemon Klaster

Melakukan tugas-tugas umum untuk mengelola DaemonSet, seperti melakukan rolling updates.

Mengelola GPU

Mengkonfigurasi dan menjadwalkan GPU NVIDIA untuk digunakan sebagai sumber daya oleh Node dalam sebuah klaster.

Mengelola HugePages

Mengkonfigurasi dan menjadwalkan HugePages sebagai sumber daya yang dapat dijadwalkan dalam sebuah klaster.

Selanjutnya

Jika kamu ingin menulis halaman tugas (task), silahkan lihat Membuat Dokumentasi Pull Request.

1 - Menginstal Peralatan

Peralatan untuk melakukan instalasi Kubernetes dalam komputer kamu.

kubectl

Perangkat baris perintah Kubernetes, kubectl, memungkinkan kamu untuk menjalankan perintah pada klaster Kubernetes. Kamu dapat menggunakan kubectl untuk menerapkan aplikasi, memeriksa dan mengelola sumber daya klaster, dan melihat log (catatan). Untuk informasi lebih lanjut termasuk daftar lengkap operasi kubectl, lihat referensi dokumentasi kubectl.

kubectl dapat diinstal pada berbagai platform Linux, macOS dan Windows. Pilihlah sistem operasi pilihan kamu di bawah ini.

kind

kind memberikan kamu kemampuan untuk menjalankan Kubernetes pada komputer lokal kamu. Perangkat ini membutuhkan Docker yang sudah diinstal dan terkonfigurasi.

Halaman Memulai Cepat kind memperlihatkan kepada kamu tentang apa yang perlu kamu lakukan untuk kind berjalan dan bekerja.

Melihat Memulai Cepat Kind

minikube

Seperti halnya dengan kind, minikube merupakan perangkat yang memungkinkan kamu untuk menjalankan Kubernetes secara lokal. minikube menjalankan sebuah klaster Kubernetes dengan satu node saja dalam komputer pribadi (termasuk Windows, macOS dan Linux) sehingga kamu dapat mencoba Kubernetes atau untuk pekerjaan pengembangan sehari-hari.

Kamu bisa mengikuti petunjuk resmi Memulai! minikube jika kamu ingin fokus agar perangkat ini terinstal.

Lihat Panduan Memulai! Minikube

Setelah kamu memiliki minikube yang bekerja, kamu bisa menggunakannya untuk menjalankan aplikasi contoh.

kubeadm

Kamu dapat menggunakan kubeadm untuk membuat dan mengatur klaster Kubernetes. kubeadm menjalankan langkah-langkah yang diperlukan untuk mendapatkan klaster dengan kelaikan dan keamanan minimum, aktif dan berjalan dengan cara yang mudah bagi pengguna.

Instalasi kubeadm memperlihatkan tentang bagaimana melakukan instalasi kubeadm. Setelah terinstal, kamu dapat menggunakannya untuk membuat klaster.

Lihat panduan instalasi kubeadm

1.1 - Menginstal dan Menyiapkan kubectl

Kubectl adalah alat baris perintah (command line tool) Kubernetes yang digunakan untuk menjalankan berbagai perintah untuk klaster Kubernetes. Kamu dapat menggunakan kubectl untuk men-deploy aplikasi, mengatur sumber daya klaster, dan melihat log. Daftar operasi kubectl dapat dilihat di Ikhtisar kubectl.

Sebelum kamu memulai

Kamu harus menggunakan kubectl dengan perbedaan maksimal satu versi minor dengan klaster kamu. Misalnya, klien v1.2 masih dapat digunakan dengan master v1.1, v1.2, dan 1.3. Menggunakan versi terbaru kubectl dapat menghindari permasalahan yang tidak terduga.

Menginstal kubectl pada Linux

Menginstal program kubectl menggunakan curl pada Linux

  1. Unduh versi terbarunya dengan perintah:

    curl -LO https://dl.k8s.io/release/`curl -LS https://dl.k8s.io/release/stable.txt`/bin/linux/amd64/kubectl 

    Untuk mengunduh versi spesifik, ganti bagian curl -LS https://dl.k8s.io/release/stable.txt dengan versi yang diinginkan.

    Misalnya, untuk mengunduh versi 1.34.0 di Linux, ketik:

    curl -LO https://dl.k8s.io/release/v1.34.0/bin/linux/amd64/kubectl 
  2. Jadikan program kubectl dapat dieksekusi.

    chmod +x ./kubectl 
  3. Pindahkan ke PATH kamu.

    sudo mv ./kubectl /usr/local/bin/kubectl 
  4. Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:

    kubectl version --client 

Menginstal dengan manajer paket (package manager) bawaan

 sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl gnupg sudo mkdir -p -m 755 /etc/apt/keyrings curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list sudo apt-get update sudo apt-get install -y kubectl 

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/ enabled=1 gpgcheck=1 gpgkey=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/repodata/repomd.xml.key EOF sudo yum install -y kubectl 

Menginstal dengan manajer paket lain

Jika kamu menggunakan Ubuntu atau versi Linux lain yang mendukung manajer paket snap, kubectl tersedia dalam bentuk aplikasi di snap.

snap install kubectl --classic  kubectl version --client 

Jika kamu menggunakan Linux dengan manajer paket Homebrew, kubectl sudah tersedia untuk diinstal di Homebrew.

brew install kubectl  kubectl version --client 

Menginstal kubectl pada macOS

Menginstal program kubectl dengan curl pada macOS

  1. Unduh versi terbarunya dengan perintah:

    curl -LO "https://dl.k8s.io/release/$(curl -LS https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl" 

    Untuk mengunduh versi spesifik, ganti bagian curl -LS https://dl.k8s.io/release/stable.txt dengan versi yang diinginkan.

    Misalnya, untuk mengunduh versi 1.34.0 pada macOS, ketik:

    curl -LO https://dl.k8s.io/release/v1.34.0/bin/darwin/amd64/kubectl 
  2. Buat agar program kubectl dapat dijalankan.

    chmod +x ./kubectl 
  3. Pindahkan ke PATH kamu.

    sudo mv ./kubectl /usr/local/bin/kubectl 
  4. Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:

    kubectl version --client 

Menginstal dengan Homebrew pada macOS

Jika kamu menggunakan macOS dan manajer paket Homebrew, kamu dapat menginstal kubectl langsung dengan Homebrew.

  1. Jalankan perintah:

    brew install kubectl 

    atau

    brew install kubernetes-cli 
  2. Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:

    kubectl version --client 

Menginstal dengan Macports pada macOS

Jika kamu menggunakan macOS dan manajer paket Macports, kamu dapat menginstal kubectl langsung dengan Macports.

  1. Jalankan perintah:

    sudo port selfupdate sudo port install kubectl 
  2. Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:

    kubectl version --client 

Menginstal kubectl pada Windows

Menginstal program kubectl dengan curl pada Windows

  1. Unduh versi terbarunya 1.34.0 dari tautan ini.

    Atau jika sudah ada curl pada mesin kamu, jalankan perintah ini:

    curl -LO https://dl.k8s.io/release/v1.34.0/bin/windows/amd64/kubectl.exe 

    Untuk mendapatkan versi stabil terakhir (misalnya untuk scripting), lihat di https://dl.k8s.io/release/stable.txt.

  2. Tambahkan program yang sudah diunduh tersebut ke PATH kamu.

  3. Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:

    kubectl version --client 

Menginstal dengan Powershell dari PSGallery

Jika kamu menggunakan Windows dan manajer paket Powershell Gallery, kamu dapat menginstal dan melakukan pembaruan kubectl dengan Powershell.

  1. Jalankan perintah berikut (jangan lupa untuk memasukkan DownloadLocation):

    Install-Script -Name install-kubectl -Scope CurrentUser -Force install-kubectl.ps1 [-DownloadLocation <path>] 

    Penginstal akan membuat $HOME/.kube dan membuat berkas konfigurasi

  2. Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:

    kubectl version --client 

Menginstal pada Windows menggunakan Chocolatey atau Scoop

Untuk menginstal kubectl pada Windows, kamu dapat menggunakan manajer paket Chocolatey atau penginstal baris perintah Scoop.

choco install kubernetes-cli 

scoop install kubectl 

  1. Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:

    kubectl version --client 
  2. Pindah ke direktori utama:

    cd %USERPROFILE% 
  3. Buat direktori .kube:

    mkdir .kube 
  4. Pindah ke direktori .kube yang baru saja dibuat:

    cd .kube 
  5. Lakukan konfigurasi kubectl untuk menggunakan klaster Kubernetes remote:

    New-Item config -type file 

Mengunduh sebagai bagian dari Google Cloud SDK

Kamu dapat menginstal kubectl sebagai bagian dari Google Cloud SDK.

  1. Instal Google Cloud SDK.

  2. Jalankan perintah instalasi kubectl:

    gcloud components install kubectl 
  3. Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:

    kubectl version --client 

Memeriksa konfigurasi kubectl

Agar kubectl dapat mengakses klaster Kubernetes, dibutuhkan sebuah berkas kubeconfig, yang akan otomatis dibuat ketika kamu membuat klaster baru menggunakan kube-up.sh atau setelah berhasil men-deploy klaster Minikube. Secara bawaan, konfigurasi kubectl disimpan di ~/.kube/config.

Kamu dapat memeriksa apakah konfigurasi kubectl sudah benar dengan mengambil keadaan klaster:

kubectl cluster-info 

Jika kamu melihat respons berupa URL, maka konfigurasi klaster kubectl sudah benar.

Tetapi, jika kamu melihat pesan seperti di bawah, maka kubectl belum dikonfigurasi dengan benar atau tidak dapat terhubung ke klaster Kubernetes.

The connection to the server <server-name:port> was refused - did you specify the right host or port? 

Selanjutnya, jika kamu ingin menjalankan klaster Kubernetes di laptop (lokal) kamu, kamu memerlukan sebuah perangkat seperti Minikube sebelum menjalankan ulang perintah yang ada di atas.

Jika kubectl cluster-info mengembalikan respons URL tetapi kamu masih belum dapat mengakses klaster, kamu bisa menggunakan perintah di bawah untuk memeriksa apakah klaster sudah dikonfigurasi dengan benar.

kubectl cluster-info dump 

Konfigurasi kubectl opsional

Menyalakan penyelesaian otomatis untuk terminal

kubectl menyediakan fitur penyelesaian otomatis (auto complete) untuk Bash dan Zsh yang dapat memudahkanmu ketika mengetik di terminal.

Ikuti petunjuk di bawah untuk menyalakan penyelesaian otomatis untuk Bash dan Zsh.

Pendahuluan

Skrip penyelesaian (completion script) kubectl untuk Bash dapat dibuat dengan perintah kubectl completion bash. Masukkan skrip tersebut ke dalam terminal sebagai sumber untuk menyalakan penyelesaian otomatis dari kubectl.

Namun, skrip penyelesaian tersebut bergantung pada bash-completion, yang artinya kamu harus menginstal program tersebut terlebih dahulu (kamu dapat memeriksa apakah kamu sudah memiliki bash-completion dengan menjalankan perintah type _init_completion).

Menginstal bash-completion

bash-completion disediakan oleh banyak manajer paket (lihat di sini). Kamu dapat menginstalnya dengan menggunakan perintah apt-get install bash-completion atau yum install bash-completion, dsb.

Perintah di atas akan membuat skrip utama bash-completion di /usr/share/bash-completion/bash_completion. Terkadang kamu juga harus menambahkan skrip tersebut ke dalam berkas ~/.bashrc, tergantung manajer paket yang kamu pakai.

Untuk memastikannya, muat ulang terminalmu dan jalankan type _init_completion. Jika perintah tersebut berhasil, maka instalasi selesai. Jika tidak, tambahkan teks berikut ke dalam berkas ~/.bashrc:

source /usr/share/bash-completion/bash_completion 

Muat ulang terminalmu dan pastikan bash-completion sudah berhasil diinstal dengan menjalankan type _init_completion.

Menyalakan penyelesaian otomatis kubectl

Sekarang kamu harus memastikan bahwa skrip penyelesaian untuk kubectl sudah dimasukkan sebagai sumber penyelesaian otomatis pada semua sesi terminal. Kamu dapat melakukannya dengan dua cara:

  • Masukkan skrip penyelesaian sebagai sumber di berkas ~/.bashrc:

    echo 'source <(kubectl completion bash)' >>~/.bashrc 
  • Tambahkan skrip penyelesaian ke direktori /etc/bash_completion.d:

    kubectl completion bash >/etc/bash_completion.d/kubectl 

Jika kamu menggunakan alias untuk kubectl, kamu masih dapat menggunakan fitur penyelesaian otomatis dengan menjalankan perintah:

```shell echo 'alias k=kubectl' >>~/.bashrc echo 'complete -F __start_kubectl k' >>~/.bashrc ``` 

Kedua cara tersebut sama, kamu bisa memilih salah satunya. Setelah memuat ulang terminal, penyelesaian otomatis dari kubectl seharusnya sudah dapat bekerja.

Pendahuluan

Skrip penyelesaian (completion script) kubectl untuk Bash dapat dibuat dengan perintah kubectl completion bash. Masukkan skrip tersebut ke dalam terminal sebagai sumber untuk menyalakan penyelesaian otomatis dari kubectl.

Namun, skrip penyelesaian tersebut bergantung pada bash-completion, yang artinya kamu harus menginstal program tersebut terlebih dahulu.

Pemutakhiran Bash

Panduan di bawah berasumsi kamu menggunakan Bash 4.1+. Kamu dapat memeriksa versi Bash dengan menjalankan:

echo $BASH_VERSION 

Jika versinya sudah terlalu usang, kamu dapat menginstal/memutakhirkannya dengan menggunakan Homebrew:

brew install bash 

Muat ulang terminalmu dan pastikan versi yang diharapkan sudah dipakai:

echo $BASH_VERSION $SHELL 

Homebrew biasanya akan menginstalnya di /usr/local/bin/bash.

Menginstal bash-completion

Kamu dapat memeriksa apakah kamu sudah memiliki bash-completion v2 dengan perintah type _init_completion. Jika belum, kamu dapat menginstalnya dengan menggunakan Homebrew:

brew install bash-completion@2 

Seperti yang disarankan pada keluaran perintah di atas, tambahkan teks berikut ke berkas ~/.bashrc:

export BASH_COMPLETION_COMPAT_DIR="/usr/local/etc/bash_completion.d" [[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh" 

Muat ulang terminalmu dan pastikan bash-completion v2 sudah terinstal dengan perintah type _init_completion.

Menyalakan penyelesaian otomatis kubectl

Sekarang kamu harus memastikan bahwa skrip penyelesaian untuk kubectl sudah dimasukkan sebagai sumber penyelesaian otomatis di semua sesi terminal. Kamu dapat melakukannya dengan beberapa cara:

  • Masukkan skrip penyelesaian sebagai sumber di berkas ~/.bashrc:

    echo 'source <(kubectl completion bash)' >>~/.bashrc 
  • Menambahkan skrip penyelesaian ke direktori /etc/bash_completion.d:

    kubectl completion bash >/etc/bash_completion.d/kubectl 
  • Jika kamu menggunakan alias untuk kubectl, kamu masih dapat menggunakan fitur penyelesaian otomatis dengan menjalankan perintah:

    echo 'alias k=kubectl' >>~/.bashrc echo 'complete -F __start_kubectl k' >>~/.bashrc 
  • Jika kamu menginstal kubectl dengan Homebrew (seperti yang sudah dijelaskan di atas), maka skrip penyelesaian untuk kubectl sudah berada di /usr/local/etc/bash_completion.d/kubectl. Kamu tidak perlu melakukan apa-apa lagi.

Setelah memuat ulang terminal, penyelesaian otomatis dari kubectl seharusnya sudah dapat bekerja.

Skrip penyelesaian (completion script) kubectl untuk Zsh dapat dibuat dengan perintah kubectl completion zsh. Masukkan skrip tersebut ke dalam terminal sebagai sumber untuk menyalakan penyelesaian otomatis dari kubectl.

Tambahkan baris berikut di berkas ~/.zshrc untuk menyalakan penyelesaian otomatis dari kubectl:

source <(kubectl completion zsh) 

Jika kamu menggunakan alias untuk kubectl, kamu masih dapat menggunakan fitur penyelesaian otomatis dengan menjalankan perintah:

echo 'alias k=kubectl' >>~/.zshrc echo 'compdef __start_kubectl k' >>~/.zshrc 

Setelah memuat ulang terminal, penyelesaian otomatis dari kubectl seharusnya sudah dapat bekerja.

Jika kamu mendapatkan pesan gagal seperti complete:13: command not found: compdef, maka tambahkan teks berikut ke awal berkas ~/.zshrc:

autoload -Uz compinit compinit 

Selanjutnya

2 - Menjalankan Tugas-Tugas Otomatis dengan CronJob

Kamu dapat menggunakan CronJob untuk menjalankan Job yang dijadwalkan berbasis waktu. Job akan berjalan seperti pekerjaan-pekerjaan Cron di Linux atau sistem UNIX.

CronJob sangat berguna untuk membuat pekerjaan yang berjalan secara periodik dan berulang, misalnya menjalankan (backup) atau mengirim email. CronJob juga dapat menjalankan pekerjaan individu pada waktu tertentu, misalnya jika kamu ingin menjadwalkan sebuah pekerjaan dengan periode aktivitas yang rendah.

CronJob memiliki keterbatasan dan kekhasan. Misalnya, dalam keadaan tertentu, sebuah CronJob dapat membuat banyak Job. Karena itu, Job haruslah idempotent.

Untuk informasi lanjut mengenai keterbatasan, lihat CronJob.

Sebelum kamu memulai

  • Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Membuat Sebuah CronJob

CronJob membutuhkan sebuah berkas konfigurasi. Ini adalah contoh dari berkas konfigurasi CronJob .spec yang akan mencetak waktu sekarang dan pesan "hello" setiap menit:

apiVersion: batch/v1 kind: CronJob metadata:  name: hello spec:  schedule: "* * * * *"  jobTemplate:  spec:  template:  spec:  containers:  - name: hello  image: busybox  command:  - /bin/sh  - -c  - date; echo Hello from the Kubernetes cluster  restartPolicy: OnFailure 

Jalankan contoh CronJob menggunakan perintah berikut:

kubectl create -f https://k8s.io/examples/application/job/cronjob.yaml 

Keluaran akan mirip dengan ini:

cronjob.batch/hello created 

Kamu juga dapat menggunakan kubectl run untuk membuat sebuah CronJob tanpa menulis sebuah konfigurasi yang lengkap:

kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster" 

Setelah membuat sebuah CronJob, untuk mengecek statusnya kamu dapat menggunakan perintah berikut:

kubectl get cronjob hello 

Keluaran akan mirip dengan ini:

NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE hello */1 * * * * False 0 <none> 10s 

Seperti yang kamu lihat dari hasil perintah di atas, CronJob belum menjadwalkan atau menjalankan pekerjaan apa pun. Waktu yang biasanya dibutuhkan untuk mengamati Job hingga Job tersebut dibuat akan membutuhkan sekitar satu menit:

kubectl get jobs --watch 

Keluaran akan mirip dengan ini:

NAME COMPLETIONS DURATION AGE hello-4111706356 0/1 0s hello-4111706356 0/1 0s 0s hello-4111706356 1/1 5s 5s 

Sekarang kamu telah melihat satu Job berjalan yang dijadwalkan oleh "hello" CronJob. Kamu dapat berhenti mengamati Job dan melihat CronJob lagi untuk melihat CronJob menjadwalkan sebuah Job:

kubectl get cronjob hello 

Keluaran akan mirip dengan ini:

NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE hello */1 * * * * False 0 50s 75s 

Kamu dapat melihat bahwa CronJob hello berhasil menjadwalkan sebuah Job pada waktu yang ditentukan dalam LAST SCHEDULE. Saat ini ada 0 Job yang aktif, berarti sebuah Job telah selesai atau gagal.

Sekarang, temukan Pod yang dibuat oleh jadwal Job terakhir dan melihat keluaran bawaan dari salah satu Pod.

# Ganti "hello-4111706356" dengan nama Job di sistem kamu pods=$(kubectl get pods --selector=job-name=hello-4111706356 --output=jsonpath={.items[*].metadata.name}) 

Menampilkan log sebuah Pod:

kubectl logs $pods 

Keluaran akan mirip dengan ini:

Fri Feb 22 11:02:09 UTC 2019 Hello from the Kubernetes cluster 

Menghapus sebuah CronJob

Ketika kamu tidak membutuhkan sebuah CronJob lagi, kamu dapat megnhapusnya dengan perintah kubectl delete cronjob <cronjob name>:

kubectl delete cronjob hello 

Menghapus CronJob akan menghapus semua Job dan Pod yang telah terbuat dan menghentikanya dari pembuatan Job tambahan. Kamu dapat membaca lebih lanjut tentang menghapus Job di garbage collection.

Seperti semua konfigurasi Kubernetes, sebuah CronJob membutuhkan field apiVersion, kind, dan metadata. Untuk informasi umum tentang bekerja dengan berkas konfigurasi, lihat dokumentasi men-deploy aplikasi, dan mengunakan kubectl untuk manajemen sumber daya.

Sebuah konfigurasi CronJob juga membutuhkan sebuah bagian .spec.

Penjadwalan

.spec.schedule adalah field yang wajib diisi dari sebuah .spec Dibutuhkan sebuah format string Cron, misalnya 0 * * * * atau @hourly, sebagai jadwal Job untuk dibuat dan dieksekusi.

Format ini juga mencakup nilai langkah "Vixie cron". Seperti penjelasan di FreeBSD manual:

Nilai langkah dapat digunakan bersama dengan rentang. Sebuah rentang diikuti dengan /<number> menentukan lompatan angka melalui rentang. Misalnya, 0-23/2 dapat digunakan dalam jam untuk menentukan perintah akan dieksekusi setiap jam (alternatif dalam bawaan v7 adalah 0,2,4,6,8,10,12,14,16,18,20,22). Langkah-langkah juga diizinkan setelah tanda bintang, jadi jika kamu menginginkan "setiap dua jam", gunakan saja */2.

Templat Job

.spec.JobTemplate adalah templat untuk sebuah Job, dan itu wajib. Templat Job memiliki skema yang sama dengan Job, kecuali jika bersarang dan tidak memiliki sebuah apiVersion atau kind. Untuk informasi lebih lanjut tentang menulis sebuah Job .spec lihat Menulis spesifikasi Job.

Starting Deadline

Field .spec.startingDeadlineSeconds adalah field opsional. Field tersebut berarti batas waktu dalam satuan detik untuk memulai sebuah Job jika Job melewatkan waktu yang telah dijadwalkan karena alasan apapun. Setelah mencapai batas waktu, CronJob tidak akan memulai sebuah Job. Job yang tidak memenuhi batas waktu, dengan cara ini dianggap sebagai Job yang gagal. Jika field ini tidak ditentukan, maka Job tidak memiliki batas waktu.

Controller CronJob menghitung berapa banyak jadwal yang terlewat untuk sebuah CronJob. jika lebih dari 100 jadwal yang terlewat, maka tidak ada lagi CronJob yang akan dijadwalkan. Ketika .spec.startingDeadlineSeconds tidak disetel, CronJob Controller menghitung jadwal yang terlewat dari status.lastScheduleTime hingga sekarang.

Misalnya, sebuah CronJob seharusnya berjalan setiap menit, status.lastScheduleTime CronJob adalah pukul 5:00am, tetapi sekarang pukul 07:00am. Itu berarti ada 120 jadwal yang terlewat, maka tidak ada lagi CronJob yang akan dijadwalkan.

Jika field .spec.startingDeadlineSeconds disetel (tidak kosong), CronJob Controller akah menghitung berapa banyak Job yang terlewat dari nilai .spec.startingDeadlineSeconds hingga sekarang.

Misalnya, jika disetel ke 200, CronJob Controller akan menghitung jadwal yang terlewat dalam 200 detik terakhir. Pada kasus ini, jika terdapat lebih dari 100 jadwal yang terlewat dalam 200 detik terakhir, maka tidak ada lagi CronJob yang akan dijadwalkan.

Kebijakan Concurrency

Field .spec.concurrencyPolicy juga opsional. Field tersebut menentukan bagaimana memperlakukan eksekusi concurrent dari sebuah Job yang dibuat oleh CronJob. Kamu dapat menetapkan hanya satu dari kebijakan concurrency:

  • Allow (bawaan): CronJob mengizinkan Job berjalan secara concurrent
  • Forbid : Job tidak mengizinkan Job berjalan secara concurrent; jika sudah saatnya untuk menjalankan Job baru dan Job sebelumnya belum selesai, maka CronJob akan melewatkan Job baru yang akan berjalan
  • Replace: Jika sudah saatnya untuk menjalankan Job baru dan Job sebelumnya belum selesai, maka CronJob akan mengganti Job yang sedang berjalan dengan Job baru.

Perhatikan bahwa kebijakan concurrency hanya berlaku untuk Job yang dibuat dengan CronJob yang sama. Jika terdapat banyak CronJob, Job akan selalu diizinkan untuk berjalan secara concurrent.

Penangguhan

Field .spec.suspend juga opsional. Jika field tersebut disetel true, semua eksekusi selanjutnya akan ditangguhkan. Konfigurasi ini tidak dapat berlaku untuk eksekusi yang sudah dimulai. Secara bawaan false.

Batas Riwayat Pekerjaan

Field .spec.successfulJobsHistoryLimit dan .spec.failedJobsHistoryLimit juga opsional. Field tersebut menentukan berapa banyak Job yang sudah selesai dan gagal yang harus disimpan. Secara bawaan, masing-masing field tersebut disetel 3 dan 1. Mensetel batas ke 0 untuk menjaga tidak ada Job yang sesuai setelah Job tersebut selesai.

3 - Mengatur Pod dan Kontainer

3.1 - Menetapkan Sumber Daya Memori untuk Container dan Pod

Laman ini menunjukkan bagaimana menetapkan permintaan dan batasan memori untuk Container. Container dijamin memiliki memori sebanyak yang diminta, tetapi tidak diperbolehkan untuk menggunakan memori melebihi batas.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Setiap Node pada klaster kamu harus memiliki memori setidaknya 300 MiB.

Beberapa langkah pada laman ini mengharuskan kamu menjalankan Service metrics-server pada klaster kamu. Jika kamu memiliki metrics-server yang sudah berjalan, kamu dapat melewati langkah-langkah berikut ini.

Jika kamu menjalankan Minikube, jalankan perintah berikut untuk mengaktifkan metrics-server:

minikube addons enable metrics-server 

Untuk melihat apakah metrics-server sudah berjalan, atau penyedia lain dari API metrik sumber daya (metrics.k8s.io), jalankan perintah berikut ini:

kubectl get apiservices 

Jika API metrik sumber daya telah tersedia, keluarannya meliputi seperti acuan pada metrics.k8s.io.

NAME v1beta1.metrics.k8s.io 

Membuat Namespace

Buat Namespace sehingga sumber daya yang kamu buat dalam latihan ini terisolasi dari klaster kamu yang lain.

kubectl create namespace mem-example 

Menentukan permintaan memori dan batasan memori

Untuk menentukan permintaan memori untuk Container, sertakan field resources:requests pada manifes sumber daya dari Container. Untuk menentukan batasan memori, sertakan resources:limits.

Dalam latihan ini, kamu akan membuat Pod yang memiliki satu Container. Container memiliki permintaan memori sebesar 100 MiB dan batasan memori sebesar 200 MiB. Berikut berkas konfigurasi untuk Pod:

apiVersion: v1 kind: Pod metadata:  name: memory-demo  namespace: mem-example spec:  containers:  - name: memory-demo-ctr  image: polinux/stress  resources:  limits:  memory: "200Mi"  requests:  memory: "100Mi"  command: ["stress"]  args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"] 

Bagian args dalam berkas konfigurasi memberikan argumen untuk Container pada saat dimulai. Argumen"--vm-bytes", "150M" memberi tahu Container agar mencoba mengalokasikan memori sebesar 150 MiB.

Buatlah Pod:

kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example 

Verifikasi apakah Container dalam Pod sudah berjalan:

kubectl get pod memory-demo --namespace=mem-example 

Lihat informasi mendetil tentang Pod:

kubectl get pod memory-demo --output=yaml --namespace=mem-example 

Keluarannya menunjukkan bahwa satu Container dalam Pod memiliki permintaan memori sebesar 100 MiB dan batasan memori sebesar 200 MiB.

... resources:  limits:  memory: 200Mi  requests:  memory: 100Mi ... 

Jalankan kubectl top untuk mengambil metrik dari Pod:

kubectl top pod memory-demo --namespace=mem-example 

Keluarannya menunjukkan bahwa Pod menggunakan memori sekitar 162.900.000 byte, dimana sekitar 150 MiB. Ini lebih besar dari permintaannya sebesar 100 MiB Pod, tetapi masih di dalam batasan Pod sebesar 200 MiB.

NAME CPU(cores) MEMORY(bytes) memory-demo <something> 162856960 

Hapuslah Pod:

kubectl delete pod memory-demo --namespace=mem-example 

Melebihi batasan memori dari Container

Container dapat melebihi permintaan memorinya jika Node memiliki memori yang tersedia. Tapi sebuah Container tidak diperbolehkan untuk menggunakan lebih dari batasan memorinya. Jika Container mengalokasikan lebih banyak memori daripada batasannya, Container menjadi kandidat untuk dihentikan. Jika Container terus berlanjut mengkonsumsi memori melebihi batasnya, maka Container akan diakhiri. Jika Container dihentikan dan bisa di mulai ulang, kubelet akan memulai ulang, sama seperti jenis kegagalan runtime yang lainnya.

Dalam latihan ini, kamu membuat Pod yang mencoba mengalokasikan lebih banyak memori dari batasannya. Berikut adalah berkas konfigurasi untuk Pod yang memiliki satu Container dengan berkas permintaan memori sebesar 50 MiB dan batasan memori sebesar 100 MiB:

apiVersion: v1 kind: Pod metadata:  name: memory-demo-2  namespace: mem-example spec:  containers:  - name: memory-demo-2-ctr  image: polinux/stress  resources:  requests:  memory: "50Mi"  limits:  memory: "100Mi"  command: ["stress"]  args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"] 

Dalam bagian args dari berkas konfigurasi, kamu dapat melihat bahwa Container tersebut akan mencoba mengalokasikan memori sebesar 250 MiB, yang jauh di atas batas yaitu 100 MiB.

Buatlah Pod:

kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example 

Lihat informasi mendetail tentang Pod:

kubectl get pod memory-demo-2 --namespace=mem-example 

Sampai sini, Container mungkin sedang berjalan atau dimatikan. Ulangi perintah sebelumnya hingga Container dimatikan:

NAME READY STATUS RESTARTS AGE memory-demo-2 0/1 OOMKilled 1 24s 

Dapatkan tampilan yang lebih mendetail tentang status Container:

kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example 

Keluarannya menunjukkan bahwa Container dimatikan karena kehabisan memori (OOM):

lastState:  terminated:  containerID: docker://65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f  exitCode: 137  finishedAt: 2017-06-20T20:52:19Z  reason: OOMKilled  startedAt: null 

Container dalam latihan ini dapat dimulai ulang, sehingga kubelet akan memulai ulangnya. Ulangi perintah ini beberapa kali untuk melihat bahwa Container berulang kali dimatikan dan dimulai ulang:

kubectl get pod memory-demo-2 --namespace=mem-example 

Keluarannya menunjukkan bahwa Container dimatikan, dimulai ulang, dimatikan lagi, dimulai ulang lagi, dan seterusnya:

kubectl get pod memory-demo-2 --namespace=mem-example NAME READY STATUS RESTARTS AGE memory-demo-2 0/1 OOMKilled 1 37s 
 kubectl get pod memory-demo-2 --namespace=mem-example NAME READY STATUS RESTARTS AGE memory-demo-2 1/1 Running 2 40s 

Lihat informasi mendetail tentang riwayat Pod:

kubectl describe pod memory-demo-2 --namespace=mem-example 

Keluarannya menunjukkan bahwa Container dimulai dan gagal berulang kali:

... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511 ... Warning BackOff Back-off restarting failed container 

Lihat informasi mendetail tentang Node klaster Anda:

kubectl describe nodes 

Keluarannya mencakup rekaman Container yang dimatikan karena kondisi kehabisan memori:

Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child 

Hapus Pod kamu:

kubectl delete pod memory-demo-2 --namespace=mem-example 

Menentukan permintaan memori yang terlalu besar untuk Node kamu

Permintaan dan batasan memori yang dikaitkan dengan Container, berguna untuk berpikir apakah sebuah Pod yang memiliki permintaan dan batasan memori. Permintaan memori untuk Pod tersebut adalah jumlah permintaan memori untuk semua Container dalam Pod. Begitu juga dengan batasan memori untuk Pod adalah jumlah batasan memori dari semua Container di dalam Pod.

Penjadwalan Pod didasarkan pada permintaan. Sebuah Pod dijadwalkan untuk berjalan di sebuah Node hanya jika sebuah Node memiliki cukup memori yang tersedia untuk memenuhi permintaan memori dari Pod tersebut.

Dalam latihan ini, kamu membuat Pod yang memiliki permintaan memori yang sangat besar sehingga melebihi kapasitas dari Node mana pun dalam klaster kamu. Berikut adalah berkas konfigurasi untuk Pod yang memiliki Container dengan permintaan memori 1000 GiB, yang kemungkinan besar melebihi kapasitas dari setiap Node dalam klaster kamu.

apiVersion: v1 kind: Pod metadata:  name: memory-demo-3  namespace: mem-example spec:  containers:  - name: memory-demo-3-ctr  image: polinux/stress  resources:  limits:  memory: "1000Gi"  requests:  memory: "1000Gi"  command: ["stress"]  args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"] 

Buatlah Pod:

kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example 

Lihat status Pod:

kubectl get pod memory-demo-3 --namespace=mem-example 

Keluarannya menunjukkan bahwa status Pod adalah PENDING. Artinya, Pod tidak dijadwalkan untuk berjalan di Node mana pun, dan Pod akan tetap dalam status PENDING tanpa batas waktu:

kubectl get pod memory-demo-3 --namespace=mem-example NAME READY STATUS RESTARTS AGE memory-demo-3 0/1 Pending 0 25s 

Lihat informasi mendetail tentang Pod, termasuk event:

kubectl describe pod memory-demo-3 --namespace=mem-example 

Keluarannya menunjukkan bahwa Container tidak dapat dijadwalkan karena memori yang tidak cukup pada Node:

Events:  ... Reason Message  ------ -------  ... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3). 

Satuan Memori

Sumber daya memori diukur dalam satuan byte. Kamu dapat mengekspresikan memori sebagai bilangan bulat biasa atau bilangan bulan fixed-point dengan salah satu akhiran ini: E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki. Contoh berikut ini mewakili nilai yang kira-kira sama:

128974848, 129e6, 129M , 123Mi 

Hapuslah Pod kamu:

kubectl delete pod memory-demo-3 --namespace=mem-example 

Jika kamu tidak menentukan batasan memori

Jika kamu tidak menentukan batasan memori untuk sebuah Container, salah satu dari situasi berikut ini berlaku:

  • Container tidak memiliki batasan maksimum jumlah memori yang digunakannya. Container dapat menggunakan semua memori yang tersedia dalam Node dimana Container itu berjalan yang pada gilirannya dapat memanggil penyetop OOM (out-of-memory). Lebih lanjut, dalam kasus menghentikan OOM, Container tanpa batas sumber daya akan memiliki peluang lebih besar untuk dihentikan.

  • Container berjalan pada Namespace yang memiliki batasan bawaan memori, dan Container secara otomatis menetapkan batasan bawaan. Administrator klaster dapat menggunakan LimitRange untuk menentukan batasan memori secara bawaan.

Motivasi untuk permintaan dan batasan memori

Dengan mengonfigurasi permintaan dan batasan memori untuk Container yang berjalan pada berkas klaster, kamu dapat menggunakan sumber daya memori yang tersedia pada Node klaster kamu secara efisien. Dengan menjaga permintaan memori pada Pod tetap rendah, kamu memberikan kesempatan yang baik untuk Pod tersebut dijadwalkan. Dengan memiliki batas memori yang lebih besar dari permintaan memori, Anda mencapai dua hal:

  • Pod dapat memiliki aktivitas yang bersifat burst dengan memanfaatkan memori yang kebetulan tersedia.
  • Jumlah memori yang dapat digunakan Pod selama keadaan burst dibatasi pada jumlah yang wajar.

Membersihkan

Hapus Namespace kamu. Ini akan menghapus semua Pod yang kamu buat untuk tugas ini:

kubectl delete namespace mem-example 

Selanjutnya

Untuk pengembang aplikasi

Untuk administrator klaster

3.2 - Konfigurasi Quality of Service untuk Pod

Laman ini menunjukkan bagaimana mengonfigurasi Pod agar ditempatkan pada kelas Quality of Service (QoS) tertentu. Kubernetes menggunakan kelas QoS untuk membuat keputusan tentang penjadwalan dan pengeluaran Pod.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Kelas QoS

Saat membuat Pod, Kubernetes menempatkan salah satu kelas QoS berikut untuknya:

  • Guaranteed
  • Burstable
  • BestEffort

Membuat sebuah Namespace

Buat sebuah Namespace sehingga sumber daya yang kamu buat dalam latihan ini terisolasi dari klaster kamu yang lain.

kubectl create namespace qos-example 

Membuat sebuah Pod yang mendapatkan penempatan kelas QoS Guaranteed

Agar sebuah Pod memiliki kelas QoS Guaranteed:

  • Setiap Container, termasuk Container pemulai, di dalam Pod harus memiliki batasan memori dan permintaan memori dengan nilai yang sama.
  • Setiap Container, termasuk Container pemulai, di dalam Pod harus memiliki batasan CPU dan permintaan CPU dengan nilai yang sama.

Berikut adalah berkas konfigurasi untuk sebuah Pod dengan satu Container. Container tersebut memiliki sebuah batasan memori dan sebuah permintaan memori, keduanya sama dengan 200MiB. Container itu juga mempunyai batasan CPU dan permintaan CPU yang sama sebesar 700 milliCPU:

apiVersion: v1 kind: Pod metadata:  name: qos-demo  namespace: qos-example spec:  containers:  - name: qos-demo-ctr  image: nginx  resources:  limits:  memory: "200Mi"  cpu: "700m"  requests:  memory: "200Mi"  cpu: "700m" 

Buatlah Pod:

kubectl create -f https://k8s.io/examples/pods/qos/qos-pod.yaml --namespace=qos-example 

Tampilkan informasi detail Pod yang telah dibuat:

kubectl get pod qos-demo --namespace=qos-example --output=yaml 

Keluaran dari perintah di atas menunjukkan Kubernetes memberikan kelas QoS Guaranteed pada Pod. Keluaran tersebut juga membuktikan bahwa Container pada Pod memiliki permintaan memori yang sesuai dengan batasan memori dan permintaan CPU yang juga sesuai dengan batasan CPU yang dispesifikasikan.

spec:  containers:  ...  resources:  limits:  cpu: 700m  memory: 200Mi  requests:  cpu: 700m  memory: 200Mi  ... status:  qosClass: Guaranteed 

Hapuslah Pod:

kubectl delete pod qos-demo --namespace=qos-example 

Membuat sebuah Pod yang mendapatkan penempatan kelas Qos Burstable

Sebuah Pod akan mendapatkan kelas QoS Burstable apabila:

  • Pod tidak memenuhi kriteria untuk kelas QoS Guaranteed.
  • Setidaknya ada satu Container di dalam Pod dengan permintaan memori atau CPU.

Berikut adalah berkas konfigurasi untuk Pod dengan satu Container. Container yang dimaksud memiliki batasan memori sebesar 200MiB dan permintaan memori sebesar 100MiB.

apiVersion: v1 kind: Pod metadata:  name: qos-demo-2  namespace: qos-example spec:  containers:  - name: qos-demo-2-ctr  image: nginx  resources:  limits:  memory: "200Mi"  requests:  memory: "100Mi" 

Buatlah Pod:

kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-2.yaml --namespace=qos-example 

Tampilkan informasi detail Pod yang telah dibuat:

kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml 

Keluaran dari perintah di atas menunjukkan Kubernetes memberikan kelas QoS Burstable pada Pod.

spec:  containers:  - image: nginx  imagePullPolicy: Always  name: qos-demo-2-ctr  resources:  limits:  memory: 200Mi  requests:  memory: 100Mi  ... status:  qosClass: Burstable 

Hapuslah Pod:

kubectl delete pod qos-demo-2 --namespace=qos-example 

Membuat sebuah Pod yang mendapatkan penempatan kelas QoS BestEffort

Agar Pod mendapatkan kelas QoS BestEffort, Container dalam pod tidak boleh memiliki batasan atau permintaan memori atau CPU.

Berikut adalah berkas konfigurasi untuk Pod dengan satu Container. Container yang dimaksud tidak memiliki batasan atau permintaan memori atau CPU apapun.

apiVersion: v1 kind: Pod metadata:  name: qos-demo-3  namespace: qos-example spec:  containers:  - name: qos-demo-3-ctr  image: nginx 

Buatlah Pod:

kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-3.yaml --namespace=qos-example 

Tampilkan informasi detail Pod yang telah dibuat:

kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml 

Keluaran dari perintah di atas menunjukkan Kubernetes memberikan kelas QoS BestEffort pada Pod.

spec:  containers:  ...  resources: {}  ... status:  qosClass: BestEffort 

Hapuslah Pod:

kubectl delete pod qos-demo-3 --namespace=qos-example 

Membuat sebuah Pod yang memiliki dua Container

Berikut adalah konfigurasi berkas untuk Pod yang memiliki dua Container. Satu Container menentukan permintaan memori sebesar 200MiB. Container yang lain tidak menentukan permintaan atau batasan apapun.

apiVersion: v1 kind: Pod metadata:  name: qos-demo-4  namespace: qos-example spec:  containers:   - name: qos-demo-4-ctr-1  image: nginx  resources:  requests:  memory: "200Mi"   - name: qos-demo-4-ctr-2  image: redis 

Perhatikan bahwa Pod ini memenuhi kriteria untuk kelas QoS Burstable. Maksudnya, Container tersebut tidak memenuhi kriteria untuk kelas QoS Guaranteed, dan satu dari Container tersebut memiliki permintaan memori.

Buatlah Pod:

kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-4.yaml --namespace=qos-example 

Tampilkan informasi detail Pod yang telah dibuat:

kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml 

Keluaran dari perintah di atas menunjukkan Kubernetes memberikan kelas QoS Burstable pada Pod.

spec:  containers:  ...  name: qos-demo-4-ctr-1  resources:  requests:  memory: 200Mi  ...  name: qos-demo-4-ctr-2  resources: {}  ... status:  qosClass: Burstable 

Hapuslah Pod:

kubectl delete pod qos-demo-4 --namespace=qos-example 

Membersihkan

Hapuslah Namespace:

kubectl delete namespace qos-example 

Selanjutnya

Untuk pengembang aplikasi

Untuk administrator klaster

3.3 - Mengatur Pod untuk Menggunakan Volume sebagai Tempat Penyimpanan

Laman ini menjelaskan bagaimana cara mengatur sebuah Pod untuk menggunakan Volume sebagai tempat penyimpanan.

Filesystem dari sebuah Container hanya hidup selama Container itu juga hidup. Saat Container berakhir dan dimulai ulang, perubahan pada filesystem akan hilang. Untuk penyimpanan konsisten yang independen dari Container, kamu dapat menggunakan Volume. Hal ini penting terutama untuk aplikasi stateful, seperti key-value stores (contohnya Redis) dan database.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Mengatur volume untuk Pod

Pada latihan ini, kamu membuat sebuah Pod yang menjalankan sebuah Container. Pod ini memiliki sebuah Volume dengan tipe emptyDir yang tetap bertahan, meski Container berakhir dan dimulai ulang. Berikut berkas konfigurasi untuk Pod:

apiVersion: v1 kind: Pod metadata:  name: redis spec:  containers:  - name: redis  image: redis  volumeMounts:  - name: redis-storage  mountPath: /data/redis  volumes:  - name: redis-storage  emptyDir: {} 
  1. Membuat Pod:

    kubectl apply -f https://k8s.io/examples/pods/storage/redis.yaml 
  2. Verifikasi apakah Container dari Pod berjalan sukses, lalu mengamati perubahan terhadap Pod:

    kubectl get pod redis --watch 

    Hasil keluaran seperti ini:

    NAME READY STATUS RESTARTS AGE redis 1/1 Running 0 13s 
  3. Pada terminal lain, buka shell untuk masuk ke Container yang sedang berjalan:

    kubectl exec -it redis -- /bin/bash 
  4. Di dalam shell, pergi ke /data/redis, kemudian buat sebuah berkas:

    root@redis:/data# cd /data/redis/ root@redis:/data/redis# echo Hello > test-file 
  5. Di dalam shell, munculkan daftar proses-proses yang sedang berjalan:

    root@redis:/data/redis# apt-get update root@redis:/data/redis# apt-get install procps root@redis:/data/redis# ps aux 

    Keluarannya mirip seperti ini:

    USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND redis 1 0.1 0.1 33308 3828 ? Ssl 00:46 0:00 redis-server *:6379 root 12 0.0 0.0 20228 3020 ? Ss 00:47 0:00 /bin/bash root 15 0.0 0.0 17500 2072 ? R+ 00:48 0:00 ps aux 
  6. Di dalam shell, matikan proses Redis:

    root@redis:/data/redis# kill <pid> 

    dengan <pid> adalah ID proses Redis (PID).

  7. Di dalam terminal awal, amati perubahan terhadap Pod Redis. Sampai akhirnya kamu akan melihat hal seperti ini:

    NAME READY STATUS RESTARTS AGE redis 1/1 Running 0 13s redis 0/1 Completed 0 6m redis 1/1 Running 1 6m 

Sampai di sini, Container telah berakhir dan dimuat ulang. Hal ini karena Pod Redis memiliki restartPolicy dengan nilai Always.

  1. Gunakan shell untuk masuk ke dalam Container yang telah dimuat ulang:

    kubectl exec -it redis -- /bin/bash 
  2. Di dalam shell, pergi ke /data/redis, dan verifikasi apakah test-file masih ada.

    root@redis:/data/redis# cd /data/redis/ root@redis:/data/redis# ls test-file 
  3. Hapus Pod yang kamu buat untuk latihan ini:

    kubectl delete pod redis 

Selanjutnya

  • Lihat Volume.

  • Lihat Pod.

  • Selain penyimpanan pada disk lokal yang di sediakan oleh emptyDir, Kubernetes juga mendukung solusi penyimpanan network-attached, termasuk PD pada GCE dan EBS dari EC2, yang cenderung lebih disukai untuk data sangat penting dan akan menangani urusan detil seperti mounting dan unmounting perangkat pada Node. Lihat Volume untuk informasi detil.

3.4 - Mengatur Pod untuk Penyimpanan dengan PersistentVolume

Laman ini akan menjelaskan bagaimana kamu dapat mengatur sebuah Pod dengan menggunakan PersistentVolumeClaim untuk penyimpanan. Berikut ringkasan prosesnya:

  1. Kamu, sebagai seorang administrator klaster, membuat sebuah PersistentVolume yang didukung oleh penyimpanan fisik. Kamu tidak mengaitkan volume dengan Pod apapun.

  2. Kamu, sekarang mengambil peran sebagai seorang developer / pengguna klaster, membuat sebuah PersistentVolumeClaim yang secara otomatis terikat dengan PersistentVolume yang sesuai.

  3. Kamu membuat sebuah Pod yang menggunakan PersistentVolumeClaim di atas untuk penyimpanan.

Sebelum kamu memulai

  • Kamu membutuhkan sebuah klaster Kubernetes yang hanya memiliki satu Node, dan kubectl alat baris perintah yang sudah diatur untuk berkomunikasi dengan klaster kamu. Jika kamu tidak memiliki sebuah klaster dengan Node tunggal, kamu dapat membuatnya dengan Minikube.

  • Familiar dengan materi di Persistent Volumes.

Membuat sebuah berkas index.html di dalam Node kamu

Buka sebuah shell ke Node tunggal di klaster kamu. Bagaimana kamu membuka sebuah shell tergantung dengan bagaimana kamu mengatur klaster kamu. Contoh, jika kamu menggunakan Minikube, kamu dapat membuka sebuah shell ke Node kamu dengan memasukkan minikube ssh.

Di dalam shell kamu pada Node itu, buat sebuah direktori dengan nama /mnt/data:

# Asumsikan Node kamu menggunakan "sudo" untuk menjalankan perintah # sebagai superuser sudo mkdir /mnt/data 

Di dalam direktori /mnt/data, buat sebuah berkas dengan nama index.html:

# Disini kembali asumsikan bahwa Node kamu menggunakan "sudo" untuk menjalankan perintah # sebagai superuser sudo sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html" 

Menguji bahwa berkas index.html ada:

cat /mnt/data/index.html 

Keluaran akan seperti ini:

Hello from Kubernetes storage 

Sekarang kamu dapat menutup shell di Node kamu.

Membuat sebuah PersistentVolume

Pada latihan ini, kamu akan membuat sebuah hostPath PersistentVolume. Kubernetes mendukung hostPath untuk pengembangan dan pengujian di dalam klaster Node tunggal. Sebuah hostPath PersistentVolume menggunakan berkas atau direktori di dalam Node untuk meniru penyimpanan terhubung jaringan (NAS, network-attached storage).

Di dalam klaster production, kamu tidak dapat menggunakan hostPath. Sebagai gantinya sebuah administrator klaster akan menyediakan sumberdaya jaringan seperti Google Compute Engine persistent disk, NFS share, atau sebuah Amazon Elastic Block Store volume. Administrator klaster juga dapat menggunakan StorageClass untuk mengatur provisioning secara dinamis.

Berikut berkas konfigurasi untuk hostPath PersistentVolume:

apiVersion: v1 kind: PersistentVolume metadata:  name: task-pv-volume  labels:  type: local spec:  storageClassName: manual  capacity:  storage: 10Gi  accessModes:  - ReadWriteOnce  hostPath:  path: "/mnt/data" 

Berkas konfigurasi tersebut menentukan bahwa volume berada di /mnt/data pada klaster Node. Konfigurasi tersebut juga menentukan ukuran dari 10 gibibytes dan mode akses ReadWriteOnce, yang berarti volume dapat di pasang sebagai read-write oleh Node tunggal. Konfigurasi ini menggunakan nama dari StorageClass manual untuk PersistentVolume, yang akan digunakan untuk mengikat permintaan PeristentVolumeClaim ke PersistentVolume ini.

Membuat sebuah PersistentVolume:

kubectl apply -f https://k8s.io/examples/pods/storage/pv-volume.yaml 

Melihat informasi tentang PersistentVolume:

kubectl get pv task-pv-volume 

Keluaran menunjuk PersistentVolume memliki sebuah STATUS dari Available. Ini berarti PersistentVolume belum terikat ke PersistentVolumeClaim.

NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE task-pv-volume 10Gi RWO Retain Available manual 4s 

Membuat sebuah PersistentVolumeClaim

Langkah selanjutnya adalah membuat sebuah PersistentVolumeClaim. Pod menggunakan PersistentVolumeClaim untuk meminta penyimpanan fisik. Pada latihan ini, kamu akan membuat sebuah PersistentVolumeClaim yang meminta sebuah volume minimal tiga gibibytes dengan mode akses read-write setidaknya untuk satu Node.

Berikut berkas konfigurasi untuk PersistentVolumeClaim:

apiVersion: v1 kind: PersistentVolumeClaim metadata:  name: task-pv-claim spec:  storageClassName: manual  accessModes:  - ReadWriteOnce  resources:  requests:  storage: 3Gi 

Membuat sebuah PersistentVolumeClaim:

kubectl apply -f https://k8s.io/examples/pods/storage/pv-claim.yaml 

Setelah membuat sebuah PersistentVolumeClaim, Kubernetes control plane terlihat untuk sebuah PersistentVolumeClaim yang memenuhi persyaratan claim's. Jika control plane menemukan PersistentVolume yang cocok dengan StorageClass, maka akan mengikat claim ke dalam volume tersebut.

Lihat kembali PersistentVolume:

kubectl get pv task-pv-volume 

Sekarang keluaran menunjukan sebuah STATUS dari Bound.

NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE task-pv-volume 10Gi RWO Retain Bound default/task-pv-claim manual 2m 

Lihat PersistentVolumeClaim:

kubectl get pvc task-pv-claim 

Keluaran menunjukan PersistentVolumeClaim terlah terikat dengan PersistentVolume, task-pv-volume.

NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE task-pv-claim Bound task-pv-volume 10Gi RWO manual 30s 

Membuat sebuah Pod

Langkah selanjutnya adalah membuat sebuah Pod yang akan menggunakan PersistentVolumeClaim sebagai volume.

Berikut berkas konfigurasi untuk Pod:

apiVersion: v1 kind: Pod metadata:  name: task-pv-pod spec:  volumes:  - name: task-pv-storage  persistentVolumeClaim:  claimName: task-pv-claim  containers:  - name: task-pv-container  image: nginx  ports:  - containerPort: 80  name: "http-server"  volumeMounts:  - mountPath: "/usr/share/nginx/html"  name: task-pv-storage 

Perhatikan bahwa berkas konfigurasi Pod menentukan sebuah PersistentVolumeClaim, tetapi tidak menentukan PeristentVolume. Dari sudut pandang Pod, claim adalah volume.

Membuat Pod:

kubectl apply -f https://k8s.io/examples/pods/storage/pv-pod.yaml 

Pastikan bahwa Container di dalam Pod berjalan:

kubectl get pod task-pv-pod 

Mendapatkan sebuah shell ke Container yang sedang berjalan di Pod kamu:

kubectl exec -it task-pv-pod -- /bin/bash 

Di dalam shell, pastikan bahwa nginx menyajikan berkas index.html dari dalam hostPath volume:

# Pastikan kamu menjalankan 3 perintah ini di dalam shell root yang berasal dari # "kubectl exec" dari langkah sebelumnya apt update apt install curl curl http://localhost/ 

Keluaran akan menunjukan sebuah teks yang telah kamu tulis di berkas index.html di dalam hostPath volume:

Hello from Kubernetes storage 

Jika kamu melihat pesan tersebut, kamu telah berhasil mengatur sebuah Pod untuk menggunakan penyimpanan dari PersistentVolumeClaim.

Membersihkan

Hapus Pod, PersistentVolumeClaim dan PersistentVolume:

kubectl delete pod task-pv-pod kubectl delete pvc task-pv-claim kubectl delete pv task-pv-volume 

Jika kamu belum memiliki shell yang telah dibuka ke Node di klaster kamu, buka shell baru dengan cara yang sama yang telah kamu lakukan sebelumnya.

Di dalam shell Node kamu, hapus berkas dan direktori yang telah kamu buat:

# Asumsikan Node kamu menggunakan "sudo" untuk menjalankan perintah # sebagai superuser sudo rm /mnt/data/index.html sudo rmdir /mnt/data 

Sekarang kamu dapat menutup shell Node kamu.

Kontrol akses

Penyimpanan yang telah terkonfigurasi dengan group ID (GID) memungkinkan akses menulis hanya dari Pod yang menggunakan GID yang sama. GID yang tidak cocok atau hilang akan menyebabkan kesalahan izin ditolak. Untuk mengurangi kebutuhan koordinasi dengan pengguna, administrator dapat membuat anotasi sebuah PersistentVolume dengan GID. Kemudian GID akan otomatis ditambahkan ke Pod yang menggunakan PersistentVolume.

Gunakan anotasi pv.beta.kubernetes.io/gid sebagai berikut:

apiVersion: v1 kind: PersistentVolume metadata:  name: pv1  annotations:  pv.beta.kubernetes.io/gid: "1234" 

Ketika sebuah Pod mengkonsumsi PersistentVolume yang memiliki anotasi GID, anotasi GID tersebut akan diterapkan ke semua container di dalam Pod dengan cara yang sama yang ditentukan di dalam GID Pod security context. Settiap GID, baik berasal dari anotasi PersistentVolume atau Pod, diterapkan pada proses pertama yang dijalankan di setiap container.

Selanjutnya

Referensi

3.5 - Mengonfigurasi Konteks Keamanan untuk Pod atau Container

Konteks keamanan (security context) menentukan wewenang (privilege) dan aturan kontrol akses untuk sebuah Pod atau Container. Aturan konteks keamanan meliputi hal-hal berikut ini namun tidak terbatas pada hal-hal tersebut:

  • Kontrol akses bersifat diskresi: Izin untuk mengakses objek, seperti sebuah berkas, yang didasarkan pada ID pengguna atau user ID (UID) dan ID grup atau group ID (GID).

  • Security Enhanced Linux (SELinux): Di mana objek diberi label keamanan.

  • Menjalankan dengan wewenang (privileged) atau tanpa wewenang (unprivileged).

  • Kapabilitas Linux (Linux Capabilities): Memberi sebuah proses beberapa wewenang, namun tidak semua wewenang dari pengguna root.

  • AppArmor: Menggunakan profil program untuk membatasi kemampuan dari masing-masing program.

  • Seccomp: Menyaring panggilan sistem (system calls) dari suatu proses.

  • AllowPrivilegeEscalation: Mengontrol apakah suatu proses dapat memperoleh lebih banyak wewenang daripada proses induknya. Pilihan ini mengontrol secara langsung apakah opsi no_new_privs diaktifkan pada proses dalam Container. AllowPrivilegeEscalation selalu aktif (true) ketika Container: 1) berjalan dengan wewenang ATAU 2) memiliki CAP_SYS_ADMIN.

  • readOnlyRootFilesystem: Menambatkan (mount) sistem berkas (file system) root dari sebuah Container hanya sebatas untuk dibaca saja (read-only).

Poin-poin di atas bukanlah sekumpulan lengkap dari aturan konteks keamanan - silakan lihat SecurityContext untuk daftar lengkapnya.

Untuk informasi lebih lanjut tentang mekanisme keamanan pada Linux, silahkan lihat ikhtisar fitur keamanan pada Kernel Linux

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Mengatur konteks keamanan untuk Pod

Untuk menentukan aturan keamanan pada Pod, masukkan bagian securityContext dalam spesifikasi Pod. Bagian securityContext adalah sebuah objek PodSecurityContext. Aturan keamanan yang kamu tetapkan untuk Pod akan berlaku untuk semua Container dalam Pod tersebut. Berikut sebuah berkas konfigurasi untuk Pod yang memiliki volume securityContext dan emptyDir:

apiVersion: v1 kind: Pod metadata:  name: security-context-demo spec:  securityContext:  runAsUser: 1000  runAsGroup: 3000  fsGroup: 2000  volumes:  - name: sec-ctx-vol  emptyDir: {}  containers:  - name: sec-ctx-demo  image: busybox  command: [ "sh", "-c", "sleep 1h" ]  volumeMounts:  - name: sec-ctx-vol  mountPath: /data/demo  securityContext:  allowPrivilegeEscalation: false 

Dalam berkas konfigurasi ini, bagian runAsUser menentukan bahwa dalam setiap Container pada Pod, semua proses dijalankan oleh ID pengguna 1000. Bagian runAsGroup menentukan grup utama dengan ID 3000 untuk semua proses dalam setiap Container pada Pod. Jika bagian ini diabaikan, maka ID grup utama dari Container akan berubah menjadi root(0). Berkas apa pun yang dibuat juga akan dimiliki oleh pengguna dengan ID 1000 dan grup dengan ID 3000 ketika runAsGroup ditentukan. Karena fsGroup ditentukan, semua proses milik Container juga merupakan bagian dari grup tambahan dengan ID 2000. Pemilik volume /data/demo dan berkas apa pun yang dibuat dalam volume tersebut adalah grup dengan ID 2000.

Buatlah Pod tersebut:

kubectl apply -f https://k8s.io/examples/pods/security/security-context.yaml 

Periksa apakah Container dari Pod sedang berjalan:

kubectl get pod security-context-demo 

Masuk ke shell dari Container yang sedang berjalan tersebut:

kubectl exec -it security-context-demo -- sh 

Pada shell kamu, lihat daftar proses yang berjalan:

ps 

Keluarannya menunjukkan bahwa proses dijalankan oleh pengguna dengan ID 1000, yang merupakan nilai dari bagian runAsUser:

PID USER TIME COMMAND  1 1000 0:00 sleep 1h  6 1000 0:00 sh ... 

Pada shell kamu, pindah ke direktori /data, dan lihat isinya:

cd /data ls -l 

Keluarannya menunjukkan bahwa direktori /data/demo memiliki grup dengan ID 2000, yang merupakan nilai dari bagian fsGroup.

drwxrwsrwx 2 root 2000 4096 Jun 6 20:08 demo 

Pada shell kamu, pindah ke direktori /data/demo, dan buatlah sebuah berkas didalamnya:

cd demo echo hello > testfile 

Lihatlah daftar berkas dalam direktori /data/demo:

ls -l 

Keluarannya menunjukkan bahwa testfile memiliki grup dengan ID 2000, dimana merupakan nilai dari bagian fsGroup.

-rw-r--r-- 1 1000 2000 6 Jun 6 20:08 testfile 

Jalankan perintah berikut ini:

$ id uid=1000 gid=3000 groups=2000 

Kamu akan melihat bahwa nilai gid adalah 3000, sama dengan bagian runAsGroup. Jika runAsGroup diabaikan maka nilai gid akan tetap bernilai 0(root) dan proses akan dapat berinteraksi dengan berkas-berkas yang dimiliki oleh grup root(0) dan yang memiliki izin grup untuk grup root(0).

Keluarlah dari shell kamu:

exit 

Melakukan konfigurasi izin volume dan kebijakan perubahan kepemilikan untuk Pod

FEATURE STATE: Kubernetes v1.18 [alpha]

Secara bawaan, Kubernetes mengubah kepemilikan dan izin secara rekursif untuk konten masing-masing volume untuk mencocokkan fsGroup yang ditentukan dalam securityContext dari Pod pada saat volume itu ditambatkan (mounted). Untuk volume yang besar, memeriksa dan mengubah kepemilikan dan izin dapat memerlukan waktu yang sangat lama, sehingga memperlambat proses menjalankan Pod. Kamu dapat menggunakan bagian fsGroupChangePolicy dalam sebuah securityContext untuk mengontrol cara Kubernetes memeriksa dan mengelola kepemilikan dan izin untuk sebuah volume.

fsGroupChangePolicy - fsGroupChangePolicy mendefinisikan perilaku untuk mengubah kepemilikan dan izin volume sebelum diekspos di dalam sebuah Pod. Bagian ini hanya berlaku untuk tipe volume yang mendukung fsGroup untuk mengontrol kepemilikan dan izin. Bagian ini memiliki dua nilai yang dapat dimasukkan:

  • OnRootMismatch: Hanya mengubah izin dan kepemilikan jika izin dan kepemilikan dari direktori root tidak sesuai dengan izin volume yang diharapkan. Hal ini dapat membantu mempersingkat waktu yang diperlukan untuk mengubah kepemilikan dan izin sebuah volume.
  • Always: Selalu mengubah izin dan kepemilikan volume ketika volume sudah ditambatkan.

Sebagai contoh:

securityContext:  runAsUser: 1000  runAsGroup: 3000  fsGroup: 2000  fsGroupChangePolicy: "OnRootMismatch" 

Ini adalah fitur alpha. Untuk menggunakannya, silahkan aktifkan gerbang fitur ConfigurableFSGroupPolicy untuk kube-api-server, kube-controller-manager, dan kubelet.

Mengatur konteks keamanan untuk Container

Untuk menentukan aturan keamanan untuk suatu Container, sertakan bagian securityContext dalam manifes Container. Bagian securityContext adalah sebuah objek SecurityContext. Aturan keamanan yang kamu tentukan untuk Container hanya berlaku untuk Container secara individu, dan aturan tersebut menimpa aturan yang dibuat pada tingkat Pod apabila ada aturan yang tumpang tindih. Aturan pada Container mempengaruhi volume pada Pod.

Berikut berkas konfigurasi untuk Pod yang hanya memiliki satu Container. Keduanya, baik Pod dan Container memiliki bagian securityContext sebagai berikut:

apiVersion: v1 kind: Pod metadata:  name: security-context-demo-2 spec:  securityContext:  runAsUser: 1000  containers:  - name: sec-ctx-demo-2  image: gcr.io/google-samples/node-hello:1.0  securityContext:  runAsUser: 2000  allowPrivilegeEscalation: false 

Buatlah Pod tersebut:

kubectl apply -f https://k8s.io/examples/pods/security/security-context-2.yaml 

Periksa jika Container dalam Pod sedang berjalan:

kubectl get pod security-context-demo-2 

Masuk ke dalam shell Container yang sedang berjalan tersebut:

kubectl exec -it security-context-demo-2 -- sh 

Pada shell kamu, lihat daftar proses yang sedang berjalan:

ps aux 

Keluarannya menunjukkan bahwa proses dijalankan oleh user dengan ID 2000, yang merupakan nilai dari runAsUser seperti yang telah ditentukan untuk Container tersebut. Nilai tersebut menimpa nilai ID 1000 yang ditentukan untuk Pod-nya.

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 2000 1 0.0 0.0 4336 764 ? Ss 20:36 0:00 /bin/sh -c node server.js 2000 8 0.1 0.5 772124 22604 ? Sl 20:36 0:00 node server.js ... 

Keluar dari shell anda:

exit 

Mengatur Kapabilitas untuk Container

Dengan menggunakan Kapabilitas Linux (Linux Capabilities), kamu dapat memberikan wewenang tertentu kepada suatu proses tanpa memberikan semua wewenang dari pengguna root. Untuk menambah atau menghapus Kapabilitas Linux pada suatu Container, masukkan bagian capabilities pada securityContext di manifes Container-nya.

Pertama-tama, mari melihat apa yang terjadi ketika kamu tidak menyertakan bagian capabilities. Berikut ini adalah berkas konfigurasi yang tidak menambah atau mengurangi kemampuan apa pun dari Container:

apiVersion: v1 kind: Pod metadata:  name: security-context-demo-3 spec:  containers:  - name: sec-ctx-3  image: gcr.io/google-samples/node-hello:1.0 

Buatlah Pod tersebut:

kubectl apply -f https://k8s.io/examples/pods/security/security-context-3.yaml 

Periksa apakah Container dari Pod tersebut sedang berjalan:

kubectl get pod security-context-demo-3 

Masuk ke dalam shell dari Container yang berjalan:

kubectl exec -it security-context-demo-3 -- sh 

Dalam shell tersebut, lihatlah daftar proses yang berjalan:

ps aux 

Keluarannya menunjukkan ID dari proses atau process IDs (PIDs) untuk Container tersebut:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 4336 796 ? Ss 18:17 0:00 /bin/sh -c node server.js root 5 0.1 0.5 772124 22700 ? Sl 18:17 0:00 node server.js 

Dalam shell kamu, lihat status dari proses dengan ID 1:

cd /proc/1 cat status 

Keluarannya menunjukkan bitmap dari kapabilitas untuk proses tersebut:

... CapPrm:	00000000a80425fb CapEff:	00000000a80425fb ... 

Buatlah catatan untuk bitmap dari kapabilitas tersebut, dan keluarlah dari shell kamu:

exit 

Berikutnya, jalankan Container yang sama seperti dengan Container sebelumnya, namun Container ini memiliki kapabilitas tambahan yang sudah ditentukan.

Berikut ini adalah berkas konfigurasi untuk Pod yang hanya menjalankan satu Container. Konfigurasi ini menambahkan kapabilitas CAP_NET_ADMIN dan CAP_SYS_TIME:

apiVersion: v1 kind: Pod metadata:  name: security-context-demo-4 spec:  containers:  - name: sec-ctx-4  image: gcr.io/google-samples/node-hello:1.0  securityContext:  capabilities:  add: ["NET_ADMIN", "SYS_TIME"] 

Buatlah Pod tersebut:

kubectl apply -f https://k8s.io/examples/pods/security/security-context-4.yaml 

Masuk ke dalam shell dari Container yang berjalan:

kubectl exec -it security-context-demo-4 -- sh 

Di dalam shell kamu, lihatlah kapabilitas dari proses dengan ID 1:

cd /proc/1 cat status 

Keluarannya menunjukkan bitmap kapabilitas untuk proses tersebut:

... CapPrm:	00000000aa0435fb CapEff:	00000000aa0435fb ... 

Bandingkan kemampuan dari kedua Containers tersebut:

00000000a80425fb 00000000aa0435fb 

Dalam bitmap kapabilitas pada Container pertama, bit-12 dan ke-25 tidak diatur. Sedangkan dalam Container kedua, bit ke-12 dan ke-25 diatur. Bit ke-12 adalah kapabilitas CAP_NET_ADMIN, dan bit-25 adalah kapabilitas CAP_SYS_TIME. Lihatlah capability.h untuk nilai dari konstanta kapabilitas-kapabilitas yang lainnya.

Memberikan label SELinux pada sebuah Container

Untuk memberikan label SELinux pada sebuah Container, masukkan bagian seLinuxOptions pada bagian securityContext dari manifes Pod atau Container kamu. Bagian seLinuxOptions adalah sebuah objek SELinuxOptions. Berikut ini adalah contoh yang menerapkan sebuah level dari SELinux:

... securityContext:  seLinuxOptions:  level: "s0:c123,c456" 

Diskusi

Konteks keamanan untuk sebuah Pod berlaku juga untuk Container yang berada dalam Pod tersebut dan juga untuk volume dari Pod tersebut jika ada. Terkhusus untuk fsGroup dan seLinuxOptions akan diterapkan pada volume seperti berikut:

  • fsGroup: Volume yang mendukung manajemen kepemilikan (ownership) akan dimodifikasi agar dapat dimiliki dan ditulis oleh ID group (GID) yang disebutkan dalam fsGroup. Lihatlah Dokumen Desain untuk Manajemen Kepemilikan untuk lebih lanjut.

  • seLinuxOptions: Volume yang mendukung pelabelan SELinux akan dilabel ulang agar dapat diakses oleh label yang ditentukan pada seLinuxOptions. Biasanya kamu hanya perlu mengatur bagian level. Dimana ini akan menetapkan label Keamanan multi-kategori (Multi-Category Security) (MCS) yang diberikan kepada semua Container dalam Pod serta Volume yang ada didalamnya.

Bersih-bersih (Clean Up)

Hapus Pod-Pod tersebut:

kubectl delete pod security-context-demo kubectl delete pod security-context-demo-2 kubectl delete pod security-context-demo-3 kubectl delete pod security-context-demo-4 

Selanjutnya

3.6 - Mengatur ServiceAccount untuk Pod

ServiceAccount menyediakan identitas untuk proses yang sedang berjalan dalam sebuah Pod.

Ketika kamu mengakses klaster (contohnya menggunakan kubectl), kamu terautentikasi oleh apiserver sebagai sebuah akun pengguna (untuk sekarang umumnya sebagai admin, kecuali jika administrator klastermu telah melakukan pengubahan). Berbagai proses yang ada di dalam kontainer dalam Pod juga dapat mengontak apiserver. Ketika itu terjadi, mereka akan diautentikasi sebagai sebuah ServiceAccount (contohnya sebagai default).

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Menggunakan Default ServiceAccount untuk Mengakses API server.

Ketika kamu membuat sebuah Pod, jika kamu tidak menentukan sebuah ServiceAccount, maka ia akan otomatis ditetapkan sebagai ServiceAccountdefault di Namespace yang sama. Jika kamu mendapatkan json atau yaml mentah untuk sebuah Pod yang telah kamu buat (contohnya menggunakan kubectl get pods/<podname> -o yaml), kamu akan melihat field spec.serviceAccountName yang telah secara otomatis ditentukan.

Kamu dapat mengakses API dari dalam Pod menggunakan kredensial ServiceAccount yang ditambahkan secara otomatis seperti yang dijelaskan dalam Mengakses Klaster. Hak akses API dari ServiceAccount menyesuaikan dengan kebijakan dan plugin otorisasi yang sedang digunakan.

Di versi 1.6+, kamu dapat tidak memilih automounting kredensial API dari sebuah ServiceAccount dengan mengatur automountServiceAccountToken: false pada ServiceAccount:

apiVersion: v1 kind: ServiceAccount metadata:  name: build-robot automountServiceAccountToken: false ... 

Di versi 1.6+, kamu juga dapat tidak memilih automounting kredensial API dari suatu Pod tertentu:

apiVersion: v1 kind: Pod metadata:  name: my-pod spec:  serviceAccountName: build-robot  automountServiceAccountToken: false  ... 

Pengaturan dari spesifikasi Pod didahulukan dibanding ServiceAccount jika keduanya menentukan nilai dari automountServiceAccountToken.

Menggunakan Beberapa ServiceAccount.

Setiap Namespace memiliki sumber daya ServiceAccount standar default. Kamu dapat melihatnya dan sumber daya serviceAccount lainnya di Namespace tersebut dengan perintah:

kubectl get serviceaccounts 

Keluarannya akan serupa dengan:

NAME SECRETS AGE default 1 1d 

Kamu dapat membuat objek ServiceAccount tambahan seperti ini:

kubectl apply -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata:  name: build-robot EOF 

Nama dari objek ServiceAccount haruslah sebuah nama subdomain DNS yang valid.

Jika kamu mendapatkan objek ServiceAccount secara komplit, seperti ini:

kubectl get serviceaccounts/build-robot -o yaml 

Keluarannya akan serupa dengan:

apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: 2015-06-16T00:12:59Z name: build-robot namespace: default resourceVersion: "272500" uid: 721ab723-13bc-11e5-aec2-42010af0021e secrets: - name: build-robot-token-bvbk5 

maka kamu dapat melihat bahwa token telah dibuat secara otomatis dan dirujuk oleh ServiceAccount.

Kamu dapat menggunakan plugin otorisasi untuk mengatur hak akses dari ServiceAccount.

Untuk menggunakan ServiceAccount selain nilai standar, atur field spec.serviceAccountName dari Pod menjadi nama dari ServiceAccount yang hendak kamu gunakan.

Service account harus ada ketika Pod dibuat, jika tidak maka akan ditolak.

Kamu tidak dapat memperbarui ServiceAccount dari Pod yang telah dibuat.

Kamu dapat menghapus ServiceAccount dari contoh seperti ini:

kubectl delete serviceaccount/build-robot 

Membuat token API ServiceAccount secara manual.

Asumsikan kita memiliki ServiceAccount dengan nama "build-robot" seperti yang disebukan di atas, dan kita membuat Secret secara manual.

kubectl apply -f - <<EOF apiVersion: v1 kind: Secret metadata:  name: build-robot-secret  annotations:  kubernetes.io/service-account.name: build-robot type: kubernetes.io/service-account-token EOF 

Sekarang kamu dapat mengonfirmasi bahwa Secret yang baru saja dibuat diisi dengan token API dari ServiceAccount "build-robot".

Setiap token dari ServiceAccount yang tidak ada akan dihapus oleh token controller.

kubectl describe secrets/build-robot-secret 

Keluarannya akan serupa dengan:

Name: build-robot-secret Namespace: default Labels: <none> Annotations: kubernetes.io/service-account.name: build-robot kubernetes.io/service-account.uid: da68f9c6-9d26-11e7-b84e-002dc52800da Type: kubernetes.io/service-account-token Data ==== ca.crt: 1338 bytes namespace: 7 bytes token: ... 

Menambahkan ImagePullSecret ke ServiceAccount.

Membuat imagePullSecret

  • Membuat sebuah imagePullSecret, seperti yang dijelaskan pada Menentukan ImagePullSecret pada Pod.

    kubectl create secret docker-registry myregistrykey --docker-server=<registry name> \  --docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD \  --docker-email=DUMMY_DOCKER_EMAIL 
  • Memastikan bahwa Secret telah terbuat.

    kubectl get secrets myregistrykey 

    Keluarannya akan serupa dengan:

    NAME TYPE DATA AGE myregistrykey   kubernetes.io/.dockerconfigjson   1       1d 

Menambahkan imagePullSecret ke ServiceAccount

Selanjutnya, modifikasi ServiceAccount standar dari Namespace untuk menggunakan Secret ini sebagai imagePullSecret.

kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}' 

Sebagai gantinya kamu dapat menggunakan kubectl edit, atau melakukan pengubahan secara manual manifes YAML seperti di bawah ini:

kubectl get serviceaccounts default -o yaml > ./sa.yaml 

Keluaran dari berkas sa.yaml akan serupa dengan:

apiVersion: v1 kind: ServiceAccount metadata:  creationTimestamp: 2015-08-07T22:02:39Z  name: default  namespace: default  resourceVersion: "243024"  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6 secrets: - name: default-token-uudge 

Menggunakan editor pilihanmu (misalnya vi), buka berkas sa.yaml, hapus baris dengan key resourceVersion, tambahkan baris dengan imagePullSecrets: dan simpan.

Keluaran dari berkas sa.yaml akan serupa dengan:

apiVersion: v1 kind: ServiceAccount metadata:  creationTimestamp: 2015-08-07T22:02:39Z  name: default  namespace: default  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6 secrets: - name: default-token-uudge imagePullSecrets: - name: myregistrykey 

Terakhir ganti serviceaccount dengan berkas sa.yaml yang telah diperbarui.

kubectl replace serviceaccount default -f ./sa.yaml 

Memverifikasi imagePullSecrets sudah ditambahkan ke spesifikasi Pod

Ketika Pod baru dibuat dalam Namespace yang sedang aktif dan menggunakan ServiceAccount, Pod baru akan memiliki field spec.imagePullSecrets yang ditentukan secara otomatis:

kubectl run nginx --image=<registry name>/nginx --restart=Never kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}' 

Keluarannya adalah:

myregistrykey 

ServiceAccountTokenVolumeProjection

FEATURE STATE: Kubernetes v1.12 [beta]

Kubelet juga dapat memproyeksikan token ServiceAccount ke Pod. Kamu dapat menentukan properti yang diinginkan dari token seperti target pengguna dan durasi validitas. Properti tersebut tidak dapat diubah pada token ServiceAccount standar. Token ServiceAccount juga akan menjadi tidak valid terhadap API ketika Pod atau ServiceAccount dihapus.

Perilaku ini diatur pada PodSpec menggunakan tipe ProjectedVolume yaitu ServiceAccountToken. Untuk memungkinkan Pod dengan token dengan pengguna bertipe "vault" dan durasi validitas selama dua jam, kamu harus mengubah bagian ini pada PodSpec:

apiVersion: v1 kind: Pod metadata:  name: nginx spec:  containers:  - image: nginx  name: nginx  volumeMounts:  - mountPath: /var/run/secrets/tokens  name: vault-token  serviceAccountName: build-robot  volumes:  - name: vault-token  projected:  sources:  - serviceAccountToken:  path: vault-token  expirationSeconds: 7200  audience: vault 

Buat Pod:

kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml 

Token yang mewakili Pod akan diminta dan disimpan kubelet, lalu kubelet akan membuat token yang dapat diakses oleh Pod pada file path yang ditentukan, dan melakukan refresh token ketika telah mendekati waktu berakhir. Token akan diganti oleh kubelet jika token telah melewati 80% dari total TTL, atau jika token telah melebihi waktu 24 jam.

Aplikasi bertanggung jawab untuk memuat ulang token ketika terjadi penggantian. Pemuatan ulang teratur (misalnya sekali setiap 5 menit) cukup untuk mencakup kebanyakan kasus.

ServiceAccountIssuerDiscovery

FEATURE STATE: Kubernetes v1.18 [alpha]

Fitur ServiceAccountIssuerDiscovery diaktifkan dengan mengaktifkan gerbang fitur ServiceAccountIssuerDiscovery dan mengaktifkan fitur Service Account Token Volume Projection seperti yang telah dijelaskan di atas.

Fitur Service Account Issuer Discovery memungkinkan federasi dari berbagai token ServiceAccount Kubernetes yang dibuat oleh sebuah klaster (penyedia identitas) dan sistem eksternal.

Ketika diaktifkan, server API Kubernetes menyediakan dokumen OpenID Provider Configuration pada /.well-known/openid-configuration dan JSON Web Key Set (JWKS) terkait pada /openid/v1/jwks. OpenID Provider Configuration terkadang disebut juga dengan sebutan discovery document.

Ketika diaktifkan, klaster juga dikonfigurasi dengan RBAC ClusterRole standar yaitu system:service-account-issuer-discovery. Role binding tidak disediakan secara default. Administrator dimungkinkan untuk, sebagai contoh, menentukan apakah peran akan disematkan ke system:authenticated atau system:unauthenticated tergantung terhadap kebutuhan keamanan dan sistem eksternal yang direncakanan untuk diintegrasikan.

Respons JWKS memuat kunci publik yang dapat digunakan oleh sistem eksternal untuk melakukan validasi token ServiceAccount Kubernetes. Awalnya sistem eksternal akan mengkueri OpenID Provider Configuration, dan selanjutnya dapat menggunakan field jwks_uri pada respons kueri untuk mendapatkan JWKS.

Pada banyak kasus, server API Kubernetes tidak tersedia di internet publik, namun endpoint publik yang menyediakan respons hasil cache dari server API dapat dibuat menjadi tersedia oleh pengguna atau penyedia servis. Pada kasus ini, dimungkinkan untuk mengganti jwks_uri pada OpenID Provider Configuration untuk diarahkan ke endpoint publik sebagai ganti alamat server API dengan memberikan flag --service-account-jwks-uri ke API server. serupa dengan URL issuer, URI JWKS diharuskan untuk menggunakan skema https.

Selanjutnya

Lihat juga:

3.7 - Menarik Image dari Register Pribadi

Laman ini menunjukkan cara membuat Pod dengan menggunakan Secret untuk menarik image dari sebuah register atau repositori pribadi untuk Docker.

Sebelum kamu memulai

  • Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

    Untuk melihat versi, tekan kubectl version.

  • Untuk melakukan latihan ini, kamu memerlukan sebuah nama pengguna (ID) Docker dan kata sandi (password).

Masuk (login) ke Docker

Pada laptop kamu, kamu harus melakukan autentikasi dengan register untuk menarik image pribadi:

docker login 

Ketika diminta, masukkan nama pengguna dan kata sandi Docker kamu.

Proses login membuat atau memperbarui berkas config.json yang menyimpan sebuah token otorisasi.

Lihatlah berkas config.json:

cat ~/.docker/config.json 

Keluaran berisi bagian yang serupa dengan ini:

{  "auths": {  "https://index.docker.io/v1/": {  "auth": "c3R...zE2"  }  } } 

Membuat Secret berdasarkan kredensial Docker yang sudah ada

Klaster Kubernetes menggunakan Secret dari tipe docker-registry untuk melakukan autentikasi dengan register Container untuk menarik image pribadi.

Jika kamu sudah menjalankan docker login, kamu dapat menyalin kredensial itu ke Kubernetes:

kubectl create secret generic regcred \  --from-file=.dockerconfigjson=<path/to/.docker/config.json> \  --type=kubernetes.io/dockerconfigjson 

Jika kamu memerlukan lebih banyak kontrol (misalnya, untuk mengatur Namespace atau label baru pada Secret) maka kamu dapat menyesuaikan Secret tersebut sebelum menyimpannya. Pastikan untuk:

  • Mengatur nama dari pokok (item) data menjadi .dockerconfigjson
  • Melakukan enkode secara base64 dari Dockerfile (berkas Docker) dan memindahkan urutan huruf (string) tersebut, secara tidak terputus sebagai nilai untuk bidang data[".dockerconfigjson"]
  • Mengatur type menjadi kubernetes.io/dockerconfigjson

Sebagai contoh:

apiVersion: v1 kind: Secret metadata:  name: myregistrykey  namespace: awesomeapps data:  .dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg== type: kubernetes.io/dockerconfigjson 

Jika kamu mendapat pesan kesalahan error: no objects passed to create, ini berarti pengkodean base64 dari urutan huruf tersebut tidak valid. Jika kamu mendapat pesan kesalahan seperti Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ..., ini berarti enkode base64 dari urutan huruf dalam data tersebut sukses didekodekan, tetapi tidak bisa diuraikan menjadi berkas .docker/config.json.

Membuat Secret dengan memberikan kredensial pada baris perintah

Buatlah Secret ini, dan berilah nama regcred:

kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email> 

dimana:

  • <your-registry-server> merupakan FQDN dari register privat Docker kamu. (https://index.docker.io/v1/ untuk DockerHub)
  • <your-name> adalah nama pengguna Docker kamu.
  • <your-pword> adalah kata sandi Docker kamu.
  • <your-email> adalah alamat email Docker kamu.

Kamu telah berhasil mengatur kredensial untuk Docker kamu pada klaster sebagai sebuah Secret yang dipanggil dengan nama regcred.

Menginspeksi Secret regcred

Untuk memahami isi Secret regcred yang baru saja kamu buat, mulailah dengan melihat Secret dalam format YAML:

kubectl get secret regcred --output=yaml 

Keluarannya akan seperti ini:

apiVersion: v1 kind: Secret metadata:  ...  name: regcred  ... data:  .dockerconfigjson: eyJodHRwczovL2luZGV4L ... J0QUl6RTIifX0= type: kubernetes.io/dockerconfigjson 

Nilai dari bidang .dockerconfigjson merupakan representasi dalam base64 dari kredensial Docker kamu.

Untuk memahami apa yang ada dalam bidang .dockerconfigjson, ubahlah data Secret menjadi format yang bisa terbaca:

kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode 

Keluarannya akan seperti ini:

{"auths":{"your.private.registry.example.com":{"username":"janedoe","password":"xxxxxxxxxxx","email":"jdoe@example.com","auth":"c3R...zE2"}}} 

Untuk memahami apa yang ada dalam bidang auth, ubahlah data Secret menjadi format yang bisa terbaca:

echo "c3R...zE2" | base64 --decode 

Keluarannya, nama pengguna dan kata sandi yang digabungkan dengan tanda :, seperti dibawah ini:

janedoe:xxxxxxxxxxx 

Perhatikan bahwa data Secret berisi token otorisasi yang serupa dengan berkas ~/.docker/config.json lokal kamu.

Kamu telah berhasil menetapkan kredensial Docker kamu sebagai sebuah Secret yang dipanggil dengan regcred pada klaster.

Membuat Pod yang menggunakan Secret kamu

Berikut ini adalah berkas konfigurasi untuk Pod yang memerlukan akses ke kredensial Docker kamu pada regcred:

apiVersion: v1 kind: Pod metadata:  name: private-reg spec:  containers:  - name: private-reg-container  image: <image-pribadi-kamu>  imagePullSecrets:  - name: regcred  

Unduh berkas diatas:

wget -O my-private-reg-pod.yaml https://k8s.io/examples/pods/private-reg-pod.yaml 

Dalam berkas my-private-reg-pod.yaml, ubah <your-private-image> dengan tautan ke image dalam register pribadi seperti ini:

your.private.registry.example.com/janedoe/jdoe-private:v1 

Untuk menarik image dari register pribadi, Kubernetes memerlukan kredensial. Bidang imagePullSecrets dalam berkas konfigurasi menentukan bahwa Kubernetes harus mendapatkan kredensial dari Secret yang bernama regcred.

Buatlah Pod yang menggunakan Secret kamu, dan verifikasi bahwa Pod tersebut berjalan:

kubectl apply -f my-private-reg-pod.yaml kubectl get pod private-reg 

Selanjutnya

3.8 - Mengatur Probe Liveness, Readiness dan Startup

Laman ini memperlihatkan bagaimana cara untuk mengatur probe liveness, readiness, dan startup untuk Container.

Probe liveness digunakan oleh kubelet untuk mengetahui kapan perlu mengulang kembali (restart) sebuah Container. Sebagai contoh, probe liveness dapat mendeteksi deadlock, ketika aplikasi sedang berjalan tapi tidak dapat berfungsi dengan baik. Mengulang Container dengan state tersebut dapat membantu ketersediaan aplikasi yang lebih baik walaupun ada kekutu (bug).

Probe readiness digunakan oleh kubelet untuk mengetahui kapan sebuah Container telah siap untuk menerima lalu lintas jaringan (traffic). Suatu Pod dianggap siap saat semua Container di dalamnya telah siap. Sinyal ini berguna untuk mengontrol Pod-Pod mana yang digunakan sebagai backend dari Service. Ketika Pod dalam kondisi tidak siap, Pod tersebut dihapus dari Service load balancer.

Probe startup digunakan oleh kubelet untuk mengetahui kapan sebuah aplikasi Container telah mulai berjalan. Jika probe tersebut dinyalakan, probe akan menonaktifkan pemeriksaan liveness dan readiness sampai berhasil, kamu harus memastikan probe tersebut tidak mengganggu startup dari aplikasi. Mekanisme ini dapat digunakan untuk mengadopsi pemeriksaan liveness pada saat memulai Container yang lambat, untuk menghindari Container dimatikan oleh kubelet sebelum Container mulai dan berjalan.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Mendefinisikan perintah liveness

Kebanyakan aplikasi yang telah berjalan dalam waktu lama pada akhirnya akan bertransisi ke state yang rusak (broken), dan tidak dapat pulih kecuali diulang kembali. Kubernetes menyediakan probe liveness untuk mendeteksi dan memperbaiki situasi tersebut.

Pada latihan ini, kamu akan membuat Pod yang menjalankan Container dari image registry.k8s.io/busybox. Berikut ini adalah berkas konfigurasi untuk Pod tersebut:

apiVersion: v1 kind: Pod metadata:  labels:  test: liveness  name: liveness-exec spec:  containers:  - name: liveness  image: registry.k8s.io/busybox  args:  - /bin/sh  - -c  - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600  livenessProbe:  exec:  command:  - cat  - /tmp/healthy  initialDelaySeconds: 5  periodSeconds: 5 

Pada berkas konfigurasi di atas, kamu dapat melihat bahwa Pod memiliki satu Container. Field periodSeconds menentukan bahwa kubelet harus melakukan probe liveness setiap 5 detik. Field initialDelaySeconds memberitahu kubelet untuk menunggu 5 detik sebelum mengerjakan probe yang pertama. Untuk mengerjakan probe, kubelet menjalankan perintah cat /tmp/healthy pada Container tujuan. Jika perintah berhasil, kode 0 akan dikembalikan, dan kubelet menganggap Container sedang dalam kondisi hidup (alive) dan sehat (healthy). Jika perintah mengembalikan kode selain 0, maka kubelet akan mematikan Container dan mengulangnya kembali.

Saat dimulai, Container akan menjalankan perintah berikut:

/bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600" 

Container memiliki berkas /tmp/healthy pada saat 30 detik pertama setelah dijalankan. Kemudian, perintah cat /tmp/healthy mengembalikan kode sukses. Namun setelah 30 detik, cat /tmp/healthy mengembalikan kode gagal.

Buatlah sebuah Pod:

kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml 

Dalam 30 detik pertama, lihatlah event dari Pod:

kubectl describe pod liveness-exec 

Keluaran dari perintah tersebut memperlihatkan bahwa belum ada probe liveness yang gagal:

FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 24s 24s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0 23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "registry.k8s.io/busybox" 23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "registry.k8s.io/busybox" 23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined] 23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e 

Setelah 35 detik, lihatlah lagi event Pod tersebut:

kubectl describe pod liveness-exec 

Baris terakhir dari keluaran tersebut memperlihatkan pesan bahwa probe liveness mengalami kegagalan, dan Container telah dimatikan dan dibuat ulang.

FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 37s 37s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0 36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "registry.k8s.io/busybox" 36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "registry.k8s.io/busybox" 36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined] 36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e 2s 2s 1 {kubelet worker0} spec.containers{liveness} Warning Unhealthy Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory 

Tunggu 30 detik lagi, dan verifikasi bahwa Container telah diulang kembali:

kubectl get pod liveness-exec 

Keluaran perintah tersebut memperlihatkan bahwa jumlah RESTARTS telah meningkat:

NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 1 1m 

Mendefinisikan probe liveness dengan permintaan HTTP

Jenis kedua dari probe liveness menggunakan sebuah permintaan GET HTTP. Berikut ini berkas konfigurasi untuk Pod yang menjalankan Container dari image registry.k8s.io/e2e-test-images/agnhost.

apiVersion: v1 kind: Pod metadata:  labels:  test: liveness  name: liveness-http spec:  containers:  - name: liveness  image: registry.k8s.io/e2e-test-images/agnhost:2.40  args:  - liveness  livenessProbe:  httpGet:  path: /healthz  port: 8080  httpHeaders:  - name: Custom-Header  value: Awesome  initialDelaySeconds: 3  periodSeconds: 3 

Pada berkas konfigurasi tersebut, kamu dapat melihat Pod memiliki sebuah Container. Field periodSeconds menentukan bahwa kubelet harus mengerjakan probe liveness setiap 3 detik. Field initialDelaySeconds memberitahu kubelet untuk menunggu 3 detik sebelum mengerjakan probe yang pertama. Untuk mengerjakan probe tersebut, kubelet mengirimkan sebuah permintaan GET HTTP ke server yang sedang berjalan di dalam Container dan mendengarkan (listen) pada porta 8080. Jika handler path /healthz yang dimiliki server mengembalikan kode sukses, kubelet menganggap Container sedang dalam kondisi hidup dan sehat. Jika handler mengembalikan kode gagal, kubelet mematikan Container dan mengulangnya kembali.

Kode yang lebih besar atau sama dengan 200 dan kurang dari 400 mengindikasikan kesuksesan. Kode selain ini mengindikasikan kegagalan.

Kamu dapat melihat kode program untuk server ini pada server.go.

Untuk 10 detik pertama setelah Container hidup (alive), handler /healthz mengembalikan status 200. Setelah itu, handler mengembalikan status 500.

http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {  duration := time.Now().Sub(started)  if duration.Seconds() > 10 {  w.WriteHeader(500)  w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))  } else {  w.WriteHeader(200)  w.Write([]byte("ok"))  } }) 

Pemeriksaan kesehatan (health check) dilakukan kubelet 3 detik setelah Container dimulai, sehingga beberapa pemeriksaaan pertama akan berhasil. Namun setelah 10 detik, pemeriksaan akan gagal, dan kubelet akan mematikan dan mengulang Container kembali.

Untuk mencoba pemeriksaan liveness HTTP, marilah membuat sebuah Pod:

kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml 

Setelah 10 detik, lihatlah event Pod untuk memverifikasi bahwa probe liveness telah gagal dan Container telah diulang kembali:

kubectl describe pod liveness-http 

Untuk rilis sebelum v1.13 (termasuk v1.13), jika variabel lingkungan http_proxy (atau HTTP_PROXY) telah diatur pada Node dimana Pod berjalan, probe liveness HTTP akan menggunakan proksi tersebut. Untuk rilis setelah v1.13, pengaturan variabel lingkungan pada proksi HTTP lokal tidak mempengaruhi probe liveness HTTP.

Mendefinisikan probe liveness TCP

Jenis ketiga dari probe liveness menggunakaan sebuah soket TCP. Dengan konfigurasi ini, kubelet akan mencoba untuk membuka soket pada Container kamu dengan porta tertentu. Jika koneksi dapat terbentuk dengan sukses, maka Container dianggap dalam kondisi sehat. Namun jika tidak berhasil terbentuk, maka Container dianggap gagal.

apiVersion: v1 kind: Pod metadata:  name: goproxy  labels:  app: goproxy spec:  containers:  - name: goproxy  image: registry.k8s.io/goproxy:0.1  ports:  - containerPort: 8080  readinessProbe:  tcpSocket:  port: 8080  initialDelaySeconds: 5  periodSeconds: 10  livenessProbe:  tcpSocket:  port: 8080  initialDelaySeconds: 15  periodSeconds: 20 

Seperti yang terlihat, konfigurasi untuk pemeriksaan TCP cukup mirip dengan pemeriksaan HTTP. Contoh ini menggunakan probe readiness dan liveness. Probe readiness yang pertama akan dikirimkan oleh kubelet, 5 detik setelah Container mulai dijalankan. Container akan coba dihubungkan oleh kubelet dengan goproxy pada porta 8080. Jika probe berhasil, maka Pod akan ditandai menjadi ready. Pemeriksaan ini akan dilanjutkan oleh kubelet setiap 10 detik.

Selain probe readiness, probe liveness juga termasuk di dalam konfigurasi. Probe liveness yang pertama akan dijalankan oleh kubelet, 15 detik setelah Container mulai dijalankan. Sama seperti probe readiness, kubelet akan mencoba untuk terhubung dengan Container goproxy pada porta 8080. Jika probe liveness gagal, maka Container akan diulang kembali.

Untuk mencoba pemeriksaan liveness TCP, marilah membuat sebuah Pod:

kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml 

Setelah 15 detik, lihatlah event Pod untuk memverifikasi probe liveness tersebut:

kubectl describe pod goproxy 

Menggunakan sebuah porta dengan nama

Kamu dapat menggunakan ContainerPort dengan nama untuk melakukan pemeriksaan liveness HTTP atau TCP:

ports: - name: liveness-port  containerPort: 8080  livenessProbe:  httpGet:  path: /healthz  port: liveness-port 

Melindungi Container yang lambat untuk dimulai dengan probe startup

Terkadang kamu harus berurusan dengan aplikasi peninggalan (legacy) yang memerlukan waktu tambahan untuk mulai berjalan pada saat pertama kali diinisialisasi. Pada kasus ini, cukup rumit untuk mengatur parameter probe liveness tanpa mengkompromikan respons yang cepat terhadap deadlock yang memotivasi digunakannya probe_ tersebut. Triknya adalah mengatur probe startup dengan perintah yang sama, baik pemeriksaan HTTP ataupun TCP, dengan failureThreshold * periodSeconds yang mencukupi untuk kemungkinan waktu memulai yang terburuk.

Sehingga, contoh sebelumnya menjadi:

ports: - name: liveness-port  containerPort: 8080  livenessProbe:  httpGet:  path: /healthz  port: liveness-port  failureThreshold: 1  periodSeconds: 10  startupProbe:  httpGet:  path: /healthz  port: liveness-port  failureThreshold: 30  periodSeconds: 10 

Berkat probe startup, aplikasi akan memiliki paling lambat 5 menit (30 * 10 = 300 detik) untuk selesai memulai. Ketika probe startup telah berhasil satu kali, maka probe liveness akan mengambil alih untuk menyediakan respons cepat terhadap deadlock Container. Jika probe startup tidak pernah berhasil, maka Container akan dimatikan setelah 300 detik dan perilakunya akan bergantung pada restartPolicy yang dimiliki Pod.

Mendefinisikan probe readiness

Terkadang aplikasi tidak dapat melayani lalu lintas jaringan sementara. Contohnya, aplikasi mungkin perlu untuk memuat data besar atau berkas konfigurasi saat dimulai, atau aplikasi bergantung pada layanan eksternal setelah dimulai. Pada kasus-kasus ini, kamu tidak ingin mematikan aplikasi, tetapi kamu tidak ingin juga mengirimkan permintaan ke aplikasi tersebut. Kubernetes menyediakan probe readiness sebagai solusinya. Sebuah Pod dengan Container yang melaporkan dirinya tidak siap, tidak akan menerima lalu lintas jaringan dari Kubernetes Service.

Probe readiness memiliki pengaturan yang mirip dengan probe liveness. Perbedaan satu-satunya adalah kamu menggunakan field readinessProbe, bukan field livenessProbe.

readinessProbe:  exec:  command:  - cat  - /tmp/healthy  initialDelaySeconds: 5  periodSeconds: 5 

Pengaturan untuk probe readiness untuk HTTP dan TCP juga sama persis dengan pengaturan untuk probe liveness.

Probe readiness dan liveness dapat digunakan secara bersamaan untuk Container yang sama. Apabila keduanya digunakan sekaligus, lalu lintas jaringan tidak akan sampai ke Container yang belum siap, dan Container akan diulang kembali (restart) saat mengalami kegagalan.

Mengatur Probe

Probe memiliki beberapa field yang dapat digunakan untuk mengendalikan pemeriksaan liveness dan readiness secara presisi.

  • initialDelaySeconds: Durasi dalam detik setelah Container dimulai, sebelum probe liveness atau readiness diinisiasi. Nilai bawaannya adalah 0 detik. Nilai minimalnya adalah 0.
  • periodSeconds: Seberapa sering (dalam detik) probe dijalankan. Nilai bawaannya adalah 10 detik. Nilai minimalnya adalah 0.
  • timeoutSeconds: Durasi dalam detik setelah probe mengalami timeout. Nilai bawaannya adalah 1 detik. Nilai minimalnya adalah 0.
  • successThreshold: Jumlah minimal sukses yang berurutan untuk probe dianggap berhasil setelah mengalami kegagalan. Nilai bawaannya adalah 1. Nilanya harus 1 untuk liveness. Nilai minimalnya adalah 1.
  • failureThreshold: Ketika sebuah Pod dimulai dan probe mengalami kegagalan, Kubernetes akan mencoba beberapa kali sesuai nilai failureThreshold sebelum menyerah. Menyerah dalam kasus probe liveness berarti Container akan diulang kembali. Untuk probe readiness, menyerah akan menandai Pod menjadi "tidak siap" (Unready). Nilai bawaannya adalah 3. Nilai minimalnya adalah 1.

Probe HTTP memiliki field-field tambahan yang bisa diatur melalui httpGet:

  • host: Nama dari host yang akan terhubung, nilai bawaannya adalah IP dari Pod. Kamu mungkin juga ingin mengatur "Host" pada httpHeaders.
  • scheme: Skema yang digunakan untuk terhubung pada host (HTTP atau HTTPS). Nilai bawaannya adalah HTTP.
  • path: Path untuk mengakses server HTTP.
  • httpHeaders: Header khusus yang diatur dalam permintaan HTTP. HTTP memperbolehkan header yang berulang.
  • port: Nama atau angka dari porta untuk mengakses Container. Angkanya harus ada di antara 1 sampai 65535.

Untuk sebuah probe HTTP, kubelet mengirimkan permintaan HTTP untuk path yang ditentukan dan porta untuk mengerjakan pemeriksaan. Probe dikirimkan oleh kubelet untuk alamat IP Pod, kecuali saat alamat digantikan oleh field opsional pada httpGet. Jika field scheme diatur menjadi HTTPS, maka kubelet mengirimkan permintaan HTTPS dan melewati langkah verifikasi sertifikat. Pada skenario kebanyakan, kamu tidak menginginkan field host. Berikut satu skenario yang memerlukan host. Misalkan Container mendengarkan permintaan melalui 127.0.0.1 dan field hostNetwork pada Pod bernilai true. Kemudian host, melalui httpGet, harus diatur menjadi 127.0.0.1. Jika Pod kamu bergantung pada host virtual, dimana untuk kasus-kasus umum, kamu tidak perlu menggunakan host, tetapi perlu mengatur header Host pada httpHeaders.

Untuk probe TCP, kubelet membuat koneksi probe pada Node, tidak pada Pod, yang berarti bahwa kamu tidak menggunakan nama Service di dalam parameter host karena kubelet tidak bisa me-resolve-nya.

Selanjutnya

Kamu juga dapat membaca rujukan API untuk:

3.9 - Menempatkan Pod pada Node Menggunakan Afinitas Pod

Dokumen ini menunjukkan cara menempatkan Pod Kubernetes pada sebuah Node menggunakan Afinitas Node di dalam klaster Kubernetes.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Kubernetes servermu harus dalam versi yang sama atau lebih baru dari v1.10.

Untuk melihat versi, tekan kubectl version.

Menambahkan sebuah Label pada sebuah Node

  1. Jabarkan Node-Node yang ada pada klaster kamu, bersamaan dengan label yang ada:

    kubectl get nodes --show-labels 

    Keluaran dari perintah tersebut akan berupa:

    NAME STATUS ROLES AGE VERSION LABELS worker0 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker0 worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1 worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2 
  2. Pilihkan salah satu dari Node yang ada dan tambahkan label pada Node tersebut.

    kubectl label nodes <nama-node-kamu> disktype=ssd 

    dimana <nama-node-kamu> merupakan nama dari Node yang kamu pilih.

  3. Keluaran dari Node yang kamu pilih dan sudah memiliki label disktype=ssd:

    kubectl get nodes --show-labels 

    Keluaran dari perintah tersebut akan berupa:

    NAME STATUS ROLES AGE VERSION LABELS worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0 worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1 worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2 

    Pada keluaran dari perintah di atas, kamu dapat melihat bahwa Node worker0 memiliki label disktype=ssd.

Menjadwalkan Pod menggunakan Afinitas Node

Konfigurasi ini menunjukkan sebuah Pod yang memiliki afinitas node requiredDuringSchedulingIgnoredDuringExecution, disktype: ssd. Dengan kata lain, Pod hanya akan dijadwalkan hanya pada Node yang memiliki label disktype=ssd.

apiVersion: v1 kind: Pod metadata:  name: nginx spec:  affinity:  nodeAffinity:  requiredDuringSchedulingIgnoredDuringExecution:  nodeSelectorTerms:  - matchExpressions:  - key: disktype  operator: In  values:  - ssd   containers:  - name: nginx  image: nginx  imagePullPolicy: IfNotPresent  
  1. Terapkan konfigurasi berikut untuk membuat sebuah Pod yang akan dijadwalkan pada Node yang kamu pilih:

    kubectl apply -f https://k8s.io/examples/pods/pod-nginx-required-affinity.yaml 
  2. Verifikasi apakah Pod yang kamu pilih sudah dijalankan pada Node yang kamu pilih:

    kubectl get pods --output=wide 

    Keluaran dari perintah tersebut akan berupa:

    NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 13s 10.200.0.4 worker0 

Jadwalkan Pod menggunakan Afinitas Node yang Dipilih

Konfigurasi ini memberikan deskripsi sebuah Pod yang memiliki afinitas Node preferredDuringSchedulingIgnoredDuringExecution,disktype: ssd. Artinya Pod akan diutamakan dijalankan pada Node yang memiliki label disktype=ssd.

apiVersion: v1 kind: Pod metadata:  name: nginx spec:  affinity:  nodeAffinity:  preferredDuringSchedulingIgnoredDuringExecution:  - weight: 1  preference:  matchExpressions:  - key: disktype  operator: In  values:  - ssd   containers:  - name: nginx  image: nginx  imagePullPolicy: IfNotPresent  
  1. Terapkan konfigurasi berikut untuk membuat sebuah Pod yang akan dijadwalkan pada Node yang kamu pilih:

    kubectl apply -f https://k8s.io/examples/pods/pod-nginx-preferred-affinity.yaml 
  2. Verifikasi apakah Pod yang kamu pilih sudah dijalankan pada Node yang kamu pilih:

    kubectl get pods --output=wide 

    Keluaran dari perintah tersebut akan berupa:

    NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 13s 10.200.0.4 worker0 

Selanjutnya

Pelajari lebih lanjut mengenai Afinitas Node.

3.10 - Mengatur Pod untuk Menggunakan ConfigMap

ConfigMap mengizinkan kamu untuk memisahkan artifak-artifak konfigurasi dari konten image untuk menjaga aplikasi yang dikontainerisasi tetap portabel. Artikel ini menyediakan sekumpulan contoh penerapan yang mendemonstrasikan bagaimana cara membuat ConfigMap dan mengatur Pod menggunakan data yang disimpan di dalam ConfigMap.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Membuat ConfigMap

Kamu dapat menggunakan kubectl create configmap ataupun generator ConfigMap pada kustomization.yaml untuk membuat sebuah ConfigMap. Perlu diingat bahwa kubectl mulai mendukung kustomization.yaml sejak versi 1.14.

Membuat ConfigMap Menggunakan kubectl create configmap

Gunakan perintah kubectl create configmap untuk membuat ConfigMap dari direktori, berkas, ataupun nilai-nilai yang harfiah (literal values):

kubectl create configmap <map-name> <data-source> 

di mana <map-name> merupakan nama yang ingin kamu berikan pada ConfigMap tersebut dan <data-source> adalah direktori, berkas, atau nilai harfiah yang digunakan sebagai sumber data. Nama dari sebuah objek ConfigMap haruslah berupa nama subdomain DNS yang sah.

Ketika kamu membuat ConfigMap dari sebuah berkas, secara bawaan, basename dari berkas tersebut akan menjadi kunci pada <data-source>, dan isi dari berkas tersebut akan menjadi nilai dari kunci tersebut.

Kamu dapat menggunakan kubectl describe atau kubectl get untuk mengambil informasi mengenai sebuah ConfigMap.

Membuat ConfigMap dari direktori

Kamu dapat menggunakan kubectl create configmap untuk membuat sebuah ConfigMap dari banyak berkas dalam sebuah direktori yang sama. Ketika kamu membuat sebuah ConfigMap dari sebuah direktori, kubectl akan mengidentifikasi berkas-berkas yang memiliki basename yang merupakan sebuah kunci yang sah pada direktori dan mengemas tiap berkas tersebut ke dalam sebuah ConfigMap baru. Seluruh entri direktori kecuali berkas reguler akan diabaikan (subdirektori, symlink, device, pipe, dsb).

Sebagai contoh:

# Membuat direktori lokal mkdir -p configure-pod-container/configmap/  # Mengunduh berkas-berkas sampel ke dalam direktori `configure-pod-container/configmap/` wget https://kubernetes.io/examples/configmap/game.properties -O configure-pod-cont1ainer/configmap/game.properties wget https://kubernetes.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties  # Membuat configmap kubectl create configmap game-config --from-file=configure-pod-container/configmap/ 

Perintah di atas mengemas tiap berkas, dalam kasus ini, game.properties dan ui.properties dalam direktori configure-pod-container/configmap/ ke dalam ConfigMap dengan nama game-config. Kamu dapat menampilkan detail dari ConfigMap menggunakan perintah berikut:

kubectl describe configmaps game-config 

Keluaran akan tampil seperti berikut:

Name: game-config Namespace: default Labels: <none> Annotations: <none> Data ==== game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 ui.properties: ---- color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice 

Berkas-berkas game.properties dan ui.properties pada direktori configure-pod-container/configmap/ direpresentasikan oleh bagian data pada ConfigMap.

kubectl get configmaps game-config -o yaml 

Keluaran akan tampil seperti berikut:

apiVersion: v1 kind: ConfigMap metadata:  creationTimestamp: 2016-02-18T18:52:05Z  name: game-config  namespace: default  resourceVersion: "516"  uid: b4952dc3-d670-11e5-8cd0-68f728db1985 data:  game.properties: |  enemies=aliens  lives=3  enemies.cheat=true  enemies.cheat.level=noGoodRotten  secret.code.passphrase=UUDDLRLRBABAS  secret.code.allowed=true  secret.code.lives=30  ui.properties: |  color.good=purple  color.bad=yellow  allow.textmode=true  how.nice.to.look=fairlyNice 

Membuat ConfigMap dari berkas

Kamu dapat menggunakan kubectl create configmap untuk membuat sebuah ConfigMap dari berkas individual, atau dari banyak berkas.

Sebagai contoh,

kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties 

akan menghasilkan ConfigMap berikut:

kubectl describe configmaps game-config-2 

dengan keluaran seperti berikut:

Name: game-config-2 Namespace: default Labels: <none> Annotations: <none> Data ==== game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 

Kamu dapat memasukkan argumen --from-file beberapa kali untuk membuat sebuah ConfigMap dari banyak sumber data.

kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties --from-file=configure-pod-container/configmap/ui.properties 

Kamu dapat menampilkan detail dari ConfigMap game-config-2 menggunakan perintah berikut:

kubectl describe configmaps game-config-2 

Keluaran akan tampil seperti berikut:

Name: game-config-2 Namespace: default Labels: <none> Annotations: <none> Data ==== game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 ui.properties: ---- color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice 

Gunakan opsi --from-env-file untuk membuat sebuah ConfigMap dari sebuah env-file, sebagai contoh:

# Env-file berisi sebuah daftar variabel _environment_. # Ada aturan-aturan sintaks yang berlaku: # Tiap baris pada sebuah env file harus memiliki format VAR=VAL. # Baris yang diawali # (komentar) akan diabaikan. # Baris-baris kosong akan diabaikan. # Tidak ada penanganan spesial untuk tanda kutip (tanda kutip akan menjadi bagian dari nilai pada ConfigMap).  # Mengunduh berkas-berkas sampel berikut ke dalam direktori `configure-pod-container/configmap/` wget https://kubernetes.io/examples/configmap/game-env-file.properties -O configure-pod-container/configmap/game-env-file.properties  # Berkas env-file `game-env-file.properties` berisi sebagai berikut: cat configure-pod-container/configmap/game-env-file.properties enemies=aliens lives=3 allowed="true"  # Komentar ini dan baris kosong di atasnya akan diabaikan. 
kubectl create configmap game-config-env-file \  --from-env-file=configure-pod-container/configmap/game-env-file.properties 

akan menghasilkan ConfigMap sebagai berikut:

kubectl get configmap game-config-env-file -o yaml 

dengan keluaran seperti berikut:

apiVersion: v1 kind: ConfigMap metadata:  creationTimestamp: 2017-12-27T18:36:28Z  name: game-config-env-file  namespace: default  resourceVersion: "809965"  uid: d9d1ca5b-eb34-11e7-887b-42010a8002b8 data:  allowed: '"true"'  enemies: aliens  lives: "3" 

Contoh perilaku memasukkan --from-env-file beberapa kali didemonstrasikan dengan:

# Mengunduh berkas-berkas sampel berikut ke dalam direktori `configure-pod-container/configmap/`  wget https://kubernetes.io/examples/configmap/ui-env-file.properties -O configure-pod-container/configmap/ui-env-file.properties  # Membuat configmap kubectl create configmap config-multi-env-files \  --from-env-file=configure-pod-container/configmap/game-env-file.properties \  --from-env-file=configure-pod-container/configmap/ui-env-file.properties 

akan menghasilkan ConfigMap sebagai berikut:

kubectl get configmap config-multi-env-files -o yaml 

dengan keluaran seperti berikut:

apiVersion: v1 kind: ConfigMap metadata:  creationTimestamp: 2017-12-27T18:38:34Z  name: config-multi-env-files  namespace: default  resourceVersion: "810136"  uid: 252c4572-eb35-11e7-887b-42010a8002b8 data:  color: purple  how: fairlyNice  textmode: "true" 

Menentukan kunci yang akan digunakan ketika membuat ConfigMap dari sebuah berkas

Kamu dapat menentukan kunci selain dari nama berkas untuk digunakan pada bagian data pada ConfigMap yang kamu buat menggunakan argumen --from-file:

kubectl create configmap game-config-3 --from-file=<my-key-name>=<path-to-file> 

di mana <my-key-name> merupakan kunci yang ingin kamu gunakan pada ConfigMap dan <path-to-file> merupakan lokasi dari berkas sumber data yang akan menjadi nilai dari kunci tersebut.

Sebagai contoh:

kubectl create configmap game-config-3 --from-file=game-special-key=configure-pod-container/configmap/game.properties 

akan menghasilkan ConfigMap sebagai berikut:

kubectl get configmaps game-config-3 -o yaml 

dengan keluaran seperti berikut:

apiVersion: v1 kind: ConfigMap metadata:  creationTimestamp: 2016-02-18T18:54:22Z  name: game-config-3  namespace: default  resourceVersion: "530"  uid: 05f8da22-d671-11e5-8cd0-68f728db1985 data:  game-special-key: |  enemies=aliens  lives=3  enemies.cheat=true  enemies.cheat.level=noGoodRotten  secret.code.passphrase=UUDDLRLRBABAS  secret.code.allowed=true  secret.code.lives=30 

Membuat ConfigMap dari nilai harfiah

Kamu dapat menggunakan kubectl create configmap dengan argumen --from-literal untuk menentukan nilai harfiah dari baris perintah:

kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm 

Kamu dapat memasukkan beberapa pasang kunci-nilai. Tiap pasang yang dimasukkan pada command line direpresentasikan sebagai sebuah entri terpisah pada bagian data dari ConfigMap.

kubectl get configmaps special-config -o yaml 

Keluaran akan tampil seperti berikut:

apiVersion: v1 kind: ConfigMap metadata:  creationTimestamp: 2016-02-18T19:14:38Z  name: special-config  namespace: default  resourceVersion: "651"  uid: dadce046-d673-11e5-8cd0-68f728db1985 data:  special.how: very  special.type: charm 

Membuat ConfigMap dari generator

kubectl mendukung kustomization.yaml sejak versi 1.14. Kamu juga dapat membuat ConfigMap dari generator lalu menggunakannya untuk membuat objek tersebut pada peladen API. Generator harus dituliskan pada kustomization.yaml dalam sebuah direktori.

Menghasilkan ConfigMap dari berkas

Sebagai contoh, untuk menghasilkan ConfigMap dari berkas configure-pod-container/configmap/game.properties

# Membuat berkas kustomization.yaml dengan ConfigMapGenerator cat <<EOF >./kustomization.yaml configMapGenerator: - name: game-config-4  files:  - configure-pod-container/configmap/game.properties EOF 

Gunakan direktori kustomization untuk membuat objek ConfigMap.

kubectl apply -k . configmap/game-config-4-m9dm2f92bt created 

Kamu dapat melihat ConfigMap yang dihasilkan seperti berikut:

kubectl get configmap NAME DATA AGE game-config-4-m9dm2f92bt 1 37s   kubectl describe configmaps/game-config-4-m9dm2f92bt Name: game-config-4-m9dm2f92bt Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"v1","data":{"game.properties":"enemies=aliens\nlives=3\nenemies.cheat=true\nenemies.cheat.level=noGoodRotten\nsecret.code.p...  Data ==== game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 Events: <none> 

Perlu diingat baha nama dari ConfigMap yang dihasilkan memiliki sufiks yang ditambahkan dengan melakukan hashing terhadap konten dari ConfigMap tersebut. Hal ini memastikan bahwa sebuah ConfigMap baru akan dihasilkan setiap kali konten dimodifikasi.

Menentukan kunci yang akan digunakan ketika generating ConfigMap dari sebuah berkas

Kamu dapat menentukan kunci selain nama berkas untuk digunakan pada generator ConfigMap. Sebagai contoh, untuk menghasilkan sebuah ConfigMap dari berkas configure-pod-container/configmap/game.properties dengan kunci game-special-key

# Membuat berkas kustomization.yaml dengan ConfigMapGenerator cat <<EOF >./kustomization.yaml configMapGenerator: - name: game-config-5  files:  - game-special-key=configure-pod-container/configmap/game.properties EOF 

Gunakan direktori kustomization untuk membuat objek ConfigMap.

kubectl apply -k . configmap/game-config-5-m67dt67794 created 

Menghasilkan ConfigMap dari Nilai-nilai Harfiah

Untuk menghasilkan ConfigMap dari nilai-nilai harfiah special.type=charm dan special.how=very, kamu dapat menentukan generator ConfigMap pada kustomization.yaml sebagai berikut

# Membuat berkas kustomization.yaml dengan ConfigMapGenerator cat <<EOF >./kustomization.yaml configMapGenerator: - name: special-config-2  literals:  - special.how=very  - special.type=charm EOF 

Gunakan direktori kustomization untuk membuat objek ConfigMap.

kubectl apply -k . configmap/special-config-2-c92b5mmcf2 created 

Menentukan variabel environment kontainer menggunakan data ConfigMap

Menentukan variabel environment kontainer dengan data dari sebuah ConfigMap

  1. Menentukan sebuah variabel environment sebagai sepasang kunci-nilai pada ConfigMap:

    kubectl create configmap special-config --from-literal=special.how=very 
  2. Memberikan nilai special.how yang sudah terdapat pada ConfigMap pada variabel environment SPECIAL_LEVEL_KEY di spesifikasi Pod.

apiVersion: v1 kind: Pod metadata:  name: dapi-test-pod spec:  containers:  - name: test-container  image: registry.k8s.io/busybox  command: [ "/bin/sh", "-c", "env" ]  env:  # Tentukan variabel environment  - name: SPECIAL_LEVEL_KEY  valueFrom:  configMapKeyRef:  # ConfigMap berisi nilai yang ingin kamu berikan pada SPECIAL_LEVEL_KEY  name: special-config  # Tentukan kunci yang diasosiasikan dengan nilainya  key: special.how  restartPolicy: Never 

Buat Pod:

kubectl create -f https://kubernetes.io/id/examples/pods/pod-single-configmap-env-variable.yaml 

Sekarang, keluaran dari Pod meliputi variabel environment SPECIAL_LEVEL_KEY=very.

Menentukan variabel environment kontainer dengan data dari beberapa ConfigMap

  • Seperti pada contoh sebelumnya, buat ConfigMap terlebih dahulu.

    apiVersion: v1 kind: ConfigMap metadata:  name: special-config  namespace: default data:  special.how: very --- apiVersion: v1 kind: ConfigMap metadata:  name: env-config  namespace: default data:  log_level: INFO 

    Buat ConfigMap:

kubectl create -f https://kubernetes.io/examples/configmap/configmaps.yaml 
  • Tentukan variabel environment pada spesifikasi Pod.

    apiVersion: v1 kind: Pod metadata:  name: dapi-test-pod spec:  containers:  - name: test-container  image: registry.k8s.io/busybox  command: [ "/bin/sh", "-c", "env" ]  env:  - name: SPECIAL_LEVEL_KEY  valueFrom:  configMapKeyRef:  name: special-config  key: special.how  - name: LOG_LEVEL  valueFrom:  configMapKeyRef:  name: env-config  key: log_level  restartPolicy: Never 

    Buat Pod:

kubectl create -f https://kubernetes.io/id/examples/pods/pod-multiple-configmap-env-variable.yaml 

Sekarang, keluaran Pod meliputi variabel environment SPECIAL_LEVEL_KEY=very dan LOG_LEVEL=INFO.

Mengatur semua pasangan kunci-nilai pada ConfigMap sebagai variabel environment kontainer

  • Buat ConfigMap yang berisi beberapa pasangan kunci-nilai.

    apiVersion: v1 kind: ConfigMap metadata:  name: special-config  namespace: default data:  SPECIAL_LEVEL: very  SPECIAL_TYPE: charm 

    Buat ConfigMap:

kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml 
  • Gunakan envFrom untuk menentukan seluruh data pada ConfigMap sebagai variabel environment kontainer. Kunci dari ConfigMap akan menjadi nama variabel environment di dalam Pod.
apiVersion: v1 kind: Pod metadata:  name: dapi-test-pod spec:  containers:  - name: test-container  image: registry.k8s.io/busybox  command: [ "/bin/sh", "-c", "env" ]  envFrom:  - configMapRef:  name: special-config  restartPolicy: Never 

Buat Pod:

kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-envFrom.yaml 

Sekarang, Pod keluaran pod meliputi variabel environment SPECIAL_LEVEL=very dan SPECIAL_TYPE=charm.

Menggunakan variabel environment yang ditentukan ConfigMap pada perintah Pod

Kamu dapat menggunakan variabel environment yang ditentukan ConfigMap pada bagian command dari spesifikasi Pod menggunakan sintaks substitusi Kubernetes $(VAR_NAME).

Sebagai contoh, spesifikasi Pod berikut

apiVersion: v1 kind: Pod metadata:  name: dapi-test-pod spec:  containers:  - name: test-container  image: registry.k8s.io/busybox  command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]  env:  - name: SPECIAL_LEVEL_KEY  valueFrom:  configMapKeyRef:  name: special-config  key: SPECIAL_LEVEL  - name: SPECIAL_TYPE_KEY  valueFrom:  configMapKeyRef:  name: special-config  key: SPECIAL_TYPE  restartPolicy: Never 

dibuat dengan menjalankan

kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-env-var-valueFrom.yaml 

menghasilkan keluaran pada kontainer test-container seperti berikut:

kubectl logs dapi-test-pod 
very charm 

Menambahkan data ConfigMap pada Volume

Seperti yang sudah dijelaskan pada Membuat ConfigMap dari berkas, ketika kamu membuat ConfigMap menggunakan --from-file, nama dari berkas tersebut akan menjadi kunci yang disimpan pada bagian data dari ConfigMap. Isi berkas tersebut akan menjadi nilai dari kunci tersebut.

Contoh pada bagian ini merujuk pada ConfigMap bernama special-config, Seperti berikut.

apiVersion: v1 kind: ConfigMap metadata:  name: special-config  namespace: default data:  SPECIAL_LEVEL: very  SPECIAL_TYPE: charm 

Buat ConfigMap:

kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml 

Mengisi Volume dengan data yang disimpan Pada ConfigMap

Tambahkan nama ConfigMap di bawah bagian volumes pada spesifikasi Pod. Hal ini akan menambahkan data ConfigMap pada direktori yang ditentukan oleh volumeMounts.mountPath (pada kasus ini, /etc/config). Bagian command berisi daftar berkas pada direktori dengan nama-nama yang sesuai dengan kunci-kunci pada ConfigMap.

apiVersion: v1 kind: Pod metadata:  name: dapi-test-pod spec:  containers:  - name: test-container  image: registry.k8s.io/busybox  command: [ "/bin/sh", "-c", "ls /etc/config/" ]  volumeMounts:  - name: config-volume  mountPath: /etc/config  volumes:  - name: config-volume  configMap:  # Berikan nama dari ConfigMap yang berisi berkas-berkas yang ingin kamu  # tambahkan ke kontainer  name: special-config  restartPolicy: Never 

Buat Pod:

kubectl create -f https://kubernetes.io/i/examples/pods/pod-configmap-volume.yaml 

Ketika Pod berjalan, perintah ls /etc/config/ akan menghasilkan keluaran di bawah:

SPECIAL_LEVEL SPECIAL_TYPE 

Menambahkan data ConfigMap pada jalur tertentu pada Volume

Gunakan kolom path untuk menentukan jalur berkas yang diinginkan untuk butir tertentu pada ConfigMap (butir ConfigMap tertentu). Pada kasus ini, butir SPECIAL_LEVEL akan akan dipasangkan sebagai config-volume pada /etc/config/keys.

apiVersion: v1 kind: Pod metadata:  name: dapi-test-pod spec:  containers:  - name: test-container  image: registry.k8s.io/busybox  command: [ "/bin/sh","-c","cat /etc/config/keys" ]  volumeMounts:  - name: config-volume  mountPath: /etc/config  volumes:  - name: config-volume  configMap:  name: special-config  items:  - key: SPECIAL_LEVEL  path: keys  restartPolicy: Never 

Buat Pod:

kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume-specific-key.yaml 

Ketika Pod berjalan, perintah cat /etc/config/keys akan menghasilkan keluaran di bawah:

very 

Memproyeksikan kunci ke jalur dan perizinan berkas tertentu

Kamu dapat memproyeksikan kunci ke jalur dan perizinan tertentu pada setiap berkas. Panduan pengguna Secret menjelaskan mengenai sintaks-sintaksnya.

ConfigMap yang dipasang akan diperbarui secara otomatis

Ketika sebuah ConfigMap yang sudah dipasang pada sebuah volume diperbarui, kunci-kunci yang diproyeksikan akan turut diperbarui. Kubelet akan memeriksa apakah ConfigMap yang dipasang merupakan yang terbaru pada sinkronisasi berkala. Namun, ConfigMap menggunakan cache lokal berbasis ttl (time-to-live) miliknya untuk mendapatkan nilai dari ConfigMap saat ini. Hasilnya, keseluruhan penundaan dari saat ketika ConfigMap diperbarui sampai saat ketika kunci-kunci baru diproyeksikan ke pada Pod bisa selama periode sinkronisasi kubelet (secara bawaan selama 1 menit) + ttl dari cache ConfigMap (secara bawaan selama 1 menit) pada kubelet. Kamu dapat memicu pembaruan langsung dengan memperbarui salah satu dari anotasi Pod.

Memahami ConfigMap dan Pod

Sumber daya API ConfigMap menyimpan data konfigurasi sebagai pasangan kunci-nilai. Data tersebut dapat dikonsumsi oleh Pod atau sebagai penyedia konfigurasi untuk komponen-komponen sistem seperti kontroler. ConfigMap mirip dengan Secret, tetapi ConfigMap dimaksudkan untuk mengolah tulisan yang tidak memiliki informasi yang sensitif. Baik pengguna maupun komponen sistem dapat menyimpan data konfigurasi pada ConfigMap.

Kolom data pada ConfigMap berisi data konfigurasi. Seperti pada contoh di bawah, hal ini bisa berupa sesuatu yang sederhana -- seperti properti individual yang ditentukan menggunakan --from-literal -- atau sesuatu yang kompleks -- seperti berkas konfigurasi atau blob JSON yang ditentukan dengan --from-file.

apiVersion: v1 kind: ConfigMap metadata:  creationTimestamp: 2016-02-18T19:14:38Z  name: example-config  namespace: default data:  # contoh properti yang sederhana yang ditentukan menggunakan --from-literal  example.property.1: hello  example.property.2: world  # contoh properti yang kompleks yang ditentukan menggunakan --from-file  example.property.file: |-  property.1=value-1  property.2=value-2  property.3=value-3 

Batasan

  • Kamu harus membuat ConfigMap sebelum merujuknya pada spesifikasi Pod (kecuali kamu menandai ConfigMap sebagai "optional"). Jika kamu merujuk sebuah ConfigMap yang tidak ada, Pod tersebut tidak akan berjalan. Sama halnya, mereferensikan kunci yang tidak ada pada ConfigMap akan mencegah Pod untuk berjalan.

  • Jika kamu menggunakan envFrom untuk menentukan variabel environment dari ConfigMap, kunci-kunci yang dianggap tidak sah akan dilewat. Pod akan diizinkan untuk berjalan, tetapi nama-nama yang tidak sah akan direkam pada event log (InvalidVariableNames). Pesan log tersebut mencantumkan tiap kunci yang dilewat. Sebagai contoh:

    kubectl get events 

    Keluaran akan tampil seperti berikut:

    LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE 0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames {kubelet, 127.0.0.1} Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names. 
  • ConfigMap berada pada Namespace tertentu. ConfigMap hanya dapat dirujuk oleh Pod yang berada pada Namespace yang sama.

  • Kamu tidak dapat menggunakan ConfigMap untuk Pod statis, karena Kubelet tidak mendukung hal ini.

Selanjutnya

3.11 - Pembagian Namespace Proses antar Container pada sebuah Pod

FEATURE STATE: Kubernetes v1.17 [stable]

Dokumen ini akan menjelaskan menkanisme konfigurasi pembagian namespace process dalam sebuah Pod. Ketika pembagian namespace proses diaktifkan untuk sebuah Pod, proses yang ada di dalam Container akan bersifat transparan pada semua Container yang terdapat di dalam Pod tersebut.

Kamu dapat mengaktifkan fitur ini untuk melakukan konfigurasi kontainer yang saling terhubung, misalnya saja kontainer sidecar yang bertugas dalam urusan log, atau untuk melakukan proses pemecahan masalah (troubleshoot) image kontainer yang tidak memiliki utilitas debugging seperti shell.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Kubernetes servermu harus dalam versi yang sama atau lebih baru dari v1.10.

Untuk melihat versi, tekan kubectl version.

Mengatur sebuah Pod

Pembagian namespace proses (Process Namespace Sharing) diaktifkan menggunakan field shareProcessNamespace v1.PodSpec. Sebagai contoh:

apiVersion: v1 kind: Pod metadata:  name: nginx spec:  shareProcessNamespace: true  containers:  - name: nginx  image: nginx  - name: shell  image: busybox  securityContext:  capabilities:  add:  - SYS_PTRACE  stdin: true  tty: true 
  1. Buatlah sebuah Pod nginx di dalam klaster kamu:

    kubectl apply -f https://k8s.io/examples/pods/share-process-namespace.yaml 
  2. Tempelkan kontainer shell dan jalankan perintah ps:

    kubectl exec -it nginx -c shell -- /bin/sh 

    Jika kamu tidak melihat prompt perintah, kamu dapat menekan tombol enter:

    / # ps ax PID USER TIME COMMAND 1 root 0:00 /pause 8 root 0:00 nginx: master process nginx -g daemon off; 14 101 0:00 nginx: worker process 15 root 0:00 sh 21 root 0:00 ps ax 

Kamu dapat memberikan sinyal pada kontainer lain. Misalnya saja, mengirim sinyal SIGHUP pada nginx untuk menjalankan ulang proses worker. Hal ini membutuhkan kapabilitas SYS_PTRACE.

/ # kill -HUP 8 / # ps ax PID USER TIME COMMAND 1 root 0:00 /pause 8 root 0:00 nginx: master process nginx -g daemon off; 15 root 0:00 sh 22 101 0:00 nginx: worker process 23 root 0:00 ps ax 

Hal ini juga merupakan alasan mengapa kita dapat mengakses kontainer lain menggunakan tautan (link) /proc/$pid/root.

/ # head /proc/8/root/etc/nginx/nginx.conf user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; 

Memahami Pembagian Namespace Process

Pod berbagi banyak sumber daya yang ada sehingga memungkinkan adanya pembagian namespace proses. Beberapa image kontainer bisa jadi terisolasi dari kontainer lainnya, meskipun begitu, memahami beberapa perbedaan berikut juga merupakan hal yang penting untuk diketahui:

  1. Proses kontainer tidak lagi memiliki PID 1. Beberapa image kontainer akan menolak untuk dijalankan (contohnya, kontainer yang menggunakan systemd) atau menjalankan perintah seperti kill -HUP 1 untuk memberikan sinyal pada proses kontainer. Di dalam Pod dengan sebuah namespace process terbagi, sinyal kill -HUP 1 akan diberikan pada sandbox Pod. (/pause pada contoh di atas.)

  2. Proses-proses yang ada akan transparan pada kontainer lain di dalam Pod. Hal ini termasuk informasi pada /proc, seperti kata sandi yang diberikan sebagai argumen atau environment variable. Hal ini hanya dilindungi oleh perizinan reguler Unix.

  3. Berkas sistem (filesystem) kontainer bersifat transparan pada kontainer lain di dalam Pod melalui link /proc/$pid/root. Hal ini memungkinkan proses debugging menjadi lebih mudah, meskipun begitu hal ini juga berarti kata kunci (secret) yang ada di dalam filesystem juga hanya dilindungi oleh perizinan filesystem saja.

3.12 - Membuat Pod Statis

Pod statis dikelola langsung oleh daemon kubelet pada suatu Node spesifik, tanpa API server mengobservasi mereka. Tidak seperti Pod yang dikelola oleh control plane (contohnya, Deployment); kubelet akan memantau setiap Pod statis (dan menjalankan ulang jika Pod mengalami kegagalan).

Pod statis selalu terikat pada satu Kubelet di dalam Node spesifik.

Kubelet secara otomatis akan mengulang untuk membuat sebuah Pod mirror pada server API Kubernetes untuk setiap Pod statis. Ini berarti Pod yang berjalan pada Node akan terlihat oleh API server, namun tidak dapat mengontrol dari sana.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Laman ini mengasumsikan kamu menggunakan CRI-O untuk menjalankan Pod, dan Node kamu berjalan menggunakan sistem operasi Fedora. Instruksi untuk distribusi lain atau instalasi Kubernetes mungkin berbeda.

Membuat sebuah Pod statis

Kamu dapat mengatur Pod statis dengan menggunakan sebuah berkas konfigurasi pada file system atau sebuah berkas konfigurasi ditempatkan pada web.

Manifes Pod statis pada berkas sistem (file system)

Manifes adalah standar definisi Pod dalam format JSON atau YAML pada suatu direktori. Gunakan field staticPodPath: <direktori> pada berkas konfigurasi kubelet, yang akan membaca direktori secara berkala dan membuat atau menghapus Pod statis sesuai dengan berkas YAML/JSON yang bertambah atau berkurang disana.

Catatan bahwa kubelet akan mengabaikan berkas yang diawali dengan titik (dot) ketika memindai suatu direktori.

Sebagai contoh, ini cara untuk memulai server web sederhana sebagai Pod statis:

  1. Pilih Node yang kamu pilih untuk menjalankan Pod statis. Dalam contoh ini adalah my-node1.

    ssh my-node1 
  2. Pilih sebuah direktori, katakan /etc/kubelet.d dan letakkan berkas definisi Pod untuk web server disana, contohnya /etc/kubelet.d/static-web.yaml:

    # Jalankan perintah ini pada Node tempat kubelet sedang berjalan mkdir /etc/kubelet.d/ cat <<EOF >/etc/kubelet.d/static-web.yaml apiVersion: v1 kind: Pod metadata:  name: static-web  labels:  role: myrole spec:  containers:  - name: web  image: nginx  ports:  - name: web  containerPort: 80  protocol: TCP EOF 
  3. Atur kubelet pada Node untuk menggunakan direktori ini dengan menjalankannya menggunakan argumen --pod-manifest-path=/etc/kubelet.d/. Pada Fedora, ubah berkas /etc/kubernetes/kubelet dengan menambahkan baris berikut:

    KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --pod-manifest-path=/etc/kubelet.d/" 

    atau tambahkan field staticPodPath: <direktori> pada berkas konfigurasi kubelet.

  4. Jalankan ulang kubelet. Pada Fedora, kamu dapat menjalankan:

    # Jalankan perintah berikut pada Node tempat kubelet berjalan systemctl restart kubelet 

Manifes Pod statis pada Web

Berkas yang ditentukan pada argumen --manifest-url=<URL> akan diunduh oleh kubelet secara berkala dan kubelet akan menginterpretasinya sebagai sebuah berkas JSON/YAML yang berisikan definisi Pod. Mirip dengan cara kerja manifes pada filesystem, kubelet akan mengambil manifes berdasarkan jadwal. Jika ada perubahan pada daftar Pod statis, maka kubelet akan menerapkannya.

Untuk menggunakan cara ini:

  1. Buat sebuah berkas YAML dan simpan pada suatu web server sehingga kamu pada memberikan URL tersebut pada kubelet.

    apiVersion: v1 kind: Pod metadata:  name: static-web  labels:  role: myrole spec:  containers:  - name: web  image: nginx  ports:  - name: web  containerPort: 80  protocol: TCP 
  2. Atur kubelet pada suatu Node untuk menggunakan manifes pada web ini dengan menjalankan menggunakan argumen --manifest-url=<url-manifes>. Pada Fedora, ubah pada /etc/kubernetes/kubelet untuk menambahkan baris ini:

    KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --manifest-url=<url-manifes>" 
  3. Jalankan ulang kubelet. Pada Fedora, kamu dapat menjalankan:

    # Jalankan perintah ini pada Node tempat kubelet berjalan systemctl restart kubelet 

Mengobservasi perilaku Pod statis

Ketika kubelet berjalan, secara otomatis akan menjalankan semua Pod statis yang terdefinisi. Ketika kamu mendefinisikan Pod statis dan menjalankan ulang kubelet, Pod statis yang baru akan dijalankan.

Kamu dapat melihat Container yang berjalan (termasuk Pod statis) dengan menjalankan (pada Node):

# Jalankan perintah ini pada Node tempat kubelet berjalan crictl ps 

Keluarannya kira-kira seperti berikut:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f6d05272b57e nginx:latest "nginx" 8 minutes ago Up 8 minutes k8s_web.6f802af4_static-web-fk-node1_default_67e24ed9466ba55986d120c867395f3c_378e5f3c 

Kamu dapat melihat Pod mirror tersebut pada API server:

kubectl get pods 
NAME READY STATUS RESTARTS AGE static-web 1/1 Running 0 2m 

Label dari Pod statis akan dibuat juga pada Pod mirror. Kamu dapat menggunakan label tersebut seperti biasa menggunakan selector, atau yang lainnya.

Kamu dapat mencoba untuk menggunakan kubelet untuk menghapus Pod mirror tersebut pada API server, namun kubelet tidak akan menghapus Pod statis:

kubectl delete pod static-web 
pod "static-web" deleted 

Kamu akan melihat bahwa Pod tersebut tetap berjalan:

kubectl get pods 
NAME READY STATUS RESTARTS AGE static-web 1/1 Running 0 4s 

Kembali ke Node tempat kubelet berjalan, kamu dapat mencoba menghentikan Container Docker secara manual. Kamu akan melihat, setelah beberapa saat, kubelet akan mengetahui dan akan menjalankan ulang Pod secara otomatis:

# Jalankan perintah ini pada Node tempat kubelet berjalan crictl stop 129fd7d382018 # ganti dengan ID pada Container-mu sleep 20 crictl ps 
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID 89db4553e1eeb docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106 

Penambahan dan pengurangan secara dinamis pada Pod statis

Direktori konfigurasi (/etc/kubelet.d pada contoh kita) akan dipindai secara berkala oleh kubelet untuk melakukan perubahan dan penambahan/pengurangan Pod sesuai dengan penambahan/pengurangan berkas pada direktori tersebut.

# Ini mengasumsikan kamu menggunakan konfigurasi Pod statis pada _filesystem_ # Jalankan perintah ini pada Node tempat kubelet berjalan # mv /etc/kubernetes/manifests/static-web.yaml /tmp sleep 20 crictl ps # Kamu mendapatkan bahwa tidak ada Container nginx yang berjalan mv /tmp/static-web.yaml /etc/kubernetes/manifests/ sleep 20 crictl ps 
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID f427638871c35 docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106 

4 - Mengelola Sebuah Klaster

Pelajari tugas-tugas umum dalam pengelolaan sebuah klaster.

4.1 - Menggunakan Calico untuk NetworkPolicy

Laman ini menunjukkan beberapa cara cepat untuk membuat klaster Calico pada Kubernetes.

Sebelum kamu memulai

Putuskan apakah kamu ingin menggelar (deploy) sebuah klaster di cloud atau di lokal.

Membuat klaster Calico dengan menggunakan Google Kubernetes Engine (GKE)

Prasyarat: gcloud.

  1. Untuk meluncurkan klaster GKE dengan Calico, cukup sertakan opsi --enable-network-policy.

    Sintaksis

    gcloud container clusters create [CLUSTER_NAME] --enable-network-policy 

    Contoh

    gcloud container clusters create my-calico-cluster --enable-network-policy 
  2. Untuk memverifikasi penggelaran, gunakanlah perintah berikut ini.

    kubectl get pods --namespace=kube-system 

    Pod Calico dimulai dengan kata calico. Periksa untuk memastikan bahwa statusnya Running.

Membuat klaster lokal Calico dengan kubeadm

Untuk membuat satu klaster Calico dengan hos tunggal dalam waktu lima belas menit dengan menggunakan kubeadm, silakan merujuk pada

Memulai cepat Calico.

Selanjutnya

Setelah klaster kamu berjalan, kamu dapat mengikuti Mendeklarasikan Kebijakan Jaringan untuk mencoba NetworkPolicy Kubernetes.

4.2 - Mengelola Memori, CPU, dan Sumber Daya API

4.2.1 - Mengatur Batas Minimum dan Maksimum Memori pada sebuah Namespace

Laman ini menunjukkan cara untuk mengatur nilai minimum dan maksimum memori yang digunakan oleh Container yang berjalan pada sebuah Namespace. Kamu dapat menentukan nilai minimum dan maksimum memori pada objek LimitRange. Jika sebuah Pod tidak memenuhi batasan yang ditentukan oleh LimitRange, maka Pod tersebut tidak dapat dibuat pada Namespace tersebut.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Tiap Node dalam klastermu harus memiliki setidaknya 1 GiB memori.

Membuat sebuah Namespace

Buat sebuah Namespace sehingga sumber daya yang kamu buat pada latihan ini terisolasi dari komponen lain pada klastermu.

kubectl create namespace constraints-mem-example 

Membuat LimitRange dan Pod

Berikut berkas konfigurasi untuk sebuah LimitRange:

apiVersion: v1 kind: LimitRange metadata:  name: mem-min-max-demo-lr spec:  limits:  - max:  memory: 1Gi  min:  memory: 500Mi  type: Container 

Membuat LimitRange:

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints.yaml --namespace=constraints-mem-example 

Melihat informasi mendetail mengenai LimitRange:

kubectl get limitrange mem-min-max-demo-lr --namespace=constraints-mem-example --output=yaml 

Keluaran yang dihasilkan menunjukkan batasan minimum dan maksimum dari memori seperti yang diharapkan. Tetapi perhatikan hal berikut, meskipun kamu tidak menentukan nilai bawaan pada berkas konfigurasi untuk LimitRange, namun nilai tersebut akan dibuat secara otomatis.

 limits: - default: memory: 1Gi defaultRequest: memory: 1Gi max: memory: 1Gi min: memory: 500Mi type: Container 

Mulai sekarang setiap Container yang dibuat pada Namespace constraints-mem-example, Kubernetes akan menjalankan langkah-langkah berikut:

  • Jika Container tersebut tidak menentukan permintaan dan limit memori, maka diberikan nilai permintaan dan limit memori bawaan pada Container.

  • Memastikan Container memiliki permintaan memori yang lebih besar atau sama dengan 500 MiB.

  • Memastikan Container memiliki limit memori yang lebih kecil atau kurang dari 1 GiB.

Berikut berkas konfigurasi Pod yang memiliki satu Container. Manifes Container menentukan permintaan memori 600 MiB dan limit memori 800 MiB. Nilai tersebut memenuhi batasan minimum dan maksimum memori yang ditentukan oleh LimitRange.

apiVersion: v1 kind: Pod metadata:  name: constraints-mem-demo spec:  containers:  - name: constraints-mem-demo-ctr  image: nginx  resources:  limits:  memory: "800Mi"  requests:  memory: "600Mi" 

Membuat Pod:

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod.yaml --namespace=constraints-mem-example 

Memastikan Container pada Pod sudah berjalan:

kubectl get pod constraints-mem-demo --namespace=constraints-mem-example 

Melihat informasi mendetail tentang Pod:

kubectl get pod constraints-mem-demo --output=yaml --namespace=constraints-mem-example 

Keluaran yang dihasilkan menunjukkan Container memiliki permintaan memori 600 MiB dan limit memori 800 MiB. Nilai tersebut memenuhi batasan yang ditentukan oleh LimitRange.

resources:  limits:  memory: 800Mi  requests:  memory: 600Mi 

Menghapus Podmu:

kubectl delete pod constraints-mem-demo --namespace=constraints-mem-example 

Mencoba membuat Pod yang melebihi batasan maksimum memori

Berikut berkas konfigurasi untuk sebuah Pod yang memiliki satu Container. Container tersebut menentukan permintaan memori 800 MiB dan batas memori 1.5 GiB.

apiVersion: v1 kind: Pod metadata:  name: constraints-mem-demo-2 spec:  containers:  - name: constraints-mem-demo-2-ctr  image: nginx  resources:  limits:  memory: "1.5Gi"  requests:  memory: "800Mi" 

Mencoba membuat Pod:

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-2.yaml --namespace=constraints-mem-example 

Keluaran yang dihasilkan menunjukkan Pod tidak dibuat, karena Container menentukan limit memori yang terlalu besar:

Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-2.yaml": pods "constraints-mem-demo-2" is forbidden: maximum memory usage per Container is 1Gi, but limit is 1536Mi. 

Mencoba membuat Pod yang tidak memenuhi permintaan memori

Berikut berkas konfigurasi untuk sebuah Pod yang memiliki satu Container. Container tersebut menentukan permintaan memori 100 MiB dan limit memori 800 MiB.

apiVersion: v1 kind: Pod metadata:  name: constraints-mem-demo-3 spec:  containers:  - name: constraints-mem-demo-3-ctr  image: nginx  resources:  limits:  memory: "800Mi"  requests:  memory: "100Mi" 

Mencoba membuat Pod:

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-3.yaml --namespace=constraints-mem-example 

Keluaran yang dihasilkan menunjukkan Pod tidak dibuat, karena Container menentukan permintaan memori yang terlalu kecil:

Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-3.yaml": pods "constraints-mem-demo-3" is forbidden: minimum memory usage per Container is 500Mi, but request is 100Mi. 

Membuat Pod yang tidak menentukan permintaan ataupun limit memori

Berikut berkas konfigurasi untuk sebuah Pod yang memiliki satu Container. Container tersebut tidak menentukan permintaan memori dan juga limit memori.

apiVersion: v1 kind: Pod metadata:  name: constraints-mem-demo-4 spec:  containers:  - name: constraints-mem-demo-4-ctr  image: nginx  

Mencoba membuat Pod:

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-4.yaml --namespace=constraints-mem-example 

Melihat informasi mendetail tentang Pod:

kubectl get pod constraints-mem-demo-4 --namespace=constraints-mem-example --output=yaml 

Keluaran yang dihasilkan menunjukkan Container pada Pod memiliki permintaan memori 1 GiB dan limit memori 1 GiB. Bagaimana Container mendapatkan nilai tersebut?

resources: limits: memory: 1Gi requests: memory: 1Gi 

Karena Containermu tidak menentukan permintaan dan limit memori, Container tersebut diberikan permintaan dan limit memori bawaan dari LimitRange.

Pada tahap ini, Containermu mungkin saja berjalan ataupun mungkin juga tidak berjalan. Ingat bahwa prasyarat untuk tugas ini adalah Node harus memiliki setidaknya 1 GiB memori. Jika tiap Node hanya memiliki 1 GiB memori, maka tidak akan ada cukup memori untuk dialokasikan pada setiap Node untuk memenuhi permintaan 1 GiB memori. Jika ternyata kamu menggunakan Node dengan 2 GiB memori, maka kamu mungkin memiliki cukup ruang untuk memenuhi permintaan 1 GiB tersebut.

Menghapus Pod:

kubectl delete pod constraints-mem-demo-4 --namespace=constraints-mem-example 

Pelaksanaan batasan minimum dan maksimum memori

Batasan maksimum dan minimum memori yang yang ditetapkan pada sebuah Namespace oleh LimitRange dilaksanakan hanya ketika Pod dibuat atau diperbarui. Jika kamu mengubah LimitRange, hal tersebut tidak akan memengaruhi Pods yang telah dibuat sebelumnya.

Motivasi untuk batasan minimum dan maksimum memori

Sebagai seorang administrator klaster, kamu mungkin ingin menetapkan pembatasan jumlah memori yang dapat digunakan oleh Pod. Sebagai contoh:

  • Tiap Node dalam sebuah klaster memiliki 2 GB memori. Kamu tidak ingin menerima Pod yang meminta lebih dari 2 GB memori, karena tidak ada Node pada klater yang dapat memenuhi permintaan tersebut.

  • Sebuah klaster digunakan bersama pada departemen produksi dan pengembangan. Kamu ingin mengizinkan beban kerja (workload) pada produksi untuk menggunakan hingga 8 GB memori, tapi kamu ingin beban kerja pada pengembangan cukup terbatas sampai dengan 512 MB saja. Kamu membuat Namespace terpisah untuk produksi dan pengembangan, dan kamu menerapkan batasan memori pada tiap Namespace.

Bersih-bersih

Menghapus Namespace:

kubectl delete namespace constraints-mem-example 

Selanjutnya

Untuk administrator klaster

Untuk pengembang aplikasi

4.3 - Debugging Resolusi DNS

Laman ini menyediakan beberapa petunjuk untuk mendiagnosis masalah DNS.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:


Klaster kamu harus dikonfigurasi untuk menggunakan addon CoreDNS atau pendahulunya, kube-dns.

Kubernetes servermu harus dalam versi yang sama atau lebih baru dari v1.6.

Untuk melihat versi, tekan kubectl version.

Membuat Pod sederhana yang digunakan sebagai lingkungan pengujian

apiVersion: v1 kind: Pod metadata:  name: dnsutils  namespace: default spec:  containers:  - name: dnsutils  image: registry.k8s.io/e2e-test-images/agnhost:2.39  imagePullPolicy: IfNotPresent  restartPolicy: Always 

Gunakan manifes berikut untuk membuat sebuah Pod:

kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml 
pod/dnsutils created 

…dan verifikasi statusnya:

kubectl get pods dnsutils 
NAME READY STATUS RESTARTS AGE dnsutils 1/1 Running 0 <some-time> 

Setelah Pod tersebut berjalan, kamu dapat menjalankan perintah nslookup di lingkungan tersebut. Jika kamu melihat hal seperti ini, maka DNS sudah berjalan dengan benar.

kubectl exec -i -t dnsutils -- nslookup kubernetes.default 
Server: 10.0.0.10 Address 1: 10.0.0.10 Name: kubernetes.default Address 1: 10.0.0.1 

Jika perintah nslookup gagal, periksa hal berikut:

Periksa konfigurasi DNS lokal terlebih dahulu

Periksa isi dari berkas resolv.conf. (Lihat Inheriting DNS dari node dan Isu-isu yang dikenal di bawah ini untuk informasi lebih lanjut)

kubectl exec -ti dnsutils -- cat /etc/resolv.conf 

Verifikasi path pencarian dan nama server telah dibuat agar tampil seperti di bawah ini (perlu diperhatikan bahwa path pencarian dapat berbeda tergantung dari penyedia layanan cloud):

search default.svc.cluster.local svc.cluster.local cluster.local google.internal c.gce_project_id.internal nameserver 10.0.0.10 options ndots:5 

Kesalahan yang muncul berikut ini mengindikasikan terdapat masalah dengan add-on CoreDNS (atau kube-dns) atau Service terkait:

kubectl exec -i -t dnsutils -- nslookup kubernetes.default 
Server: 10.0.0.10 Address 1: 10.0.0.10 nslookup: can't resolve 'kubernetes.default' 

atau

kubectl exec -i -t dnsutils -- nslookup kubernetes.default 
Server: 10.0.0.10 Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local nslookup: can't resolve 'kubernetes.default' 

Periksa apakah Pod DNS sedang berjalan

Gunakan perintah kubectl get pods untuk memverifikasi apakah Pod DNS sedang berjalan.

kubectl get pods --namespace=kube-system -l k8s-app=kube-dns 
NAME READY STATUS RESTARTS AGE ... coredns-7b96bf9f76-5hsxb 1/1 Running 0 1h coredns-7b96bf9f76-mvmmt 1/1 Running 0 1h ... 

Jika kamu melihat tidak ada Pod CoreDNS yang sedang berjalan atau Pod tersebut gagal/telah selesai, add-on DNS mungkin tidak dijalankan (deployed) secara bawaan di lingkunganmu saat ini dan kamu harus menjalankannya secara manual.

Periksa kesalahan pada Pod DNS

Gunakan perintah kubectl logs untuk melihat log dari Container DNS.

Untuk CoreDNS:

kubectl logs --namespace=kube-system -l k8s-app=kube-dns 

Berikut contoh log dari CoreDNS yang sehat (healthy):

.:53 2018/08/15 14:37:17 [INFO] CoreDNS-1.2.2 2018/08/15 14:37:17 [INFO] linux/amd64, go1.10.3, 2e322f6 CoreDNS-1.2.2 linux/amd64, go1.10.3, 2e322f6 2018/08/15 14:37:17 [INFO] plugin/reload: Running configuration MD5 = 24e6c59e83ce706f07bcc82c31b1ea1c 

Periksa jika ada pesan mencurigakan atau tidak terduga dalam log.

Apakah layanan DNS berjalan?

Verifikasi apakah layanan DNS berjalan dengan menggunakan perintah kubectl get service.

kubectl get svc --namespace=kube-system 
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ... kube-dns ClusterIP 10.0.0.10 <none> 53/UDP,53/TCP 1h ... 

Jika kamu telah membuat Service atau seharusnya Service telah dibuat secara bawaan namun ternyata tidak muncul, lihat debugging Service untuk informasi lebih lanjut.

Apakah endpoint DNS telah ekspos?

Kamu dapat memverifikasikan apakah endpoint DNS telah diekspos dengan menggunakan perintah kubectl get endpoints.

kubectl get endpoints kube-dns --namespace=kube-system 
NAME ENDPOINTS AGE kube-dns 10.180.3.17:53,10.180.3.17:53 1h 

Jika kamu tidak melihat endpoint, lihat bagian endpoint pada dokumentasi debugging Service.

Untuk tambahan contoh Kubernetes DNS, lihat contoh cluster-dns pada repositori Kubernetes GitHub.

Apakah kueri DNS diterima/diproses?

Kamu dapat memverifikasi apakah kueri telah diterima oleh CoreDNS dengan menambahkan plugin log pada konfigurasi CoreDNS (alias Corefile). CoreDNS Corefile disimpan pada ConfigMap dengan nama coredns. Untuk mengeditnya, gunakan perintah:

kubectl -n kube-system edit configmap coredns 

Lalu tambahkan log pada bagian Corefile seperti contoh berikut:

apiVersion: v1 kind: ConfigMap metadata:  name: coredns  namespace: kube-system data:  Corefile: |  .:53 {  log  errors  health  kubernetes cluster.local in-addr.arpa ip6.arpa {  pods insecure  upstream  fallthrough in-addr.arpa ip6.arpa  }  prometheus :9153  proxy . /etc/resolv.conf  cache 30  loop  reload  loadbalance  } 

Setelah perubahan disimpan, perubahan dapat memakan waktu satu hingga dua menit untuk Kubernetes menyebarkan perubahan ini pada Pod CoreDNS.

Berikutnya, coba buat beberapa kueri dan lihat log pada bagian atas dari dokumen ini. Jika pod CoreDNS menerima kueri, kamu seharusnya akan melihatnya pada log.

Berikut ini contoh kueri yang terdapat di dalam log:

.:53 2018/08/15 14:37:15 [INFO] CoreDNS-1.2.0 2018/08/15 14:37:15 [INFO] linux/amd64, go1.10.3, 2e322f6 CoreDNS-1.2.0 linux/amd64, go1.10.3, 2e322f6 2018/09/07 15:29:04 [INFO] plugin/reload: Running configuration MD5 = 162475cdf272d8aa601e6fe67a6ad42f 2018/09/07 15:29:04 [INFO] Reloading complete 172.17.0.18:41675 - [07/Sep/2018:15:29:11 +0000] 59925 "A IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR qr,aa,rd,ra 106 0.000066649s 

Isu-isu yang Dikenal

Beberapa distribusi Linux (contoh Ubuntu) menggunakan resolver DNS lokal secara bawaan (systemd-resolved). Systemd-resolved memindahkan dan mengganti /etc/resolv.conf dengan berkas stub yang dapat menyebabkan forwarding loop yang fatal saat meresolusi nama pada server upstream. Ini dapat diatasi secara manual dengan menggunakan flag kubelet --resolv-conf untuk mengarahkan ke resolv.conf yang benar (Pada systemd-resolved, ini berada di /run/systemd/resolve/resolv.conf). kubeadm akan otomatis mendeteksi systemd-resolved, dan menyesuaikan flag kubelet sebagai mana mestinya.

Pemasangan Kubernetes tidak menggunakan berkas resolv.conf pada node untuk digunakan sebagai klaster DNS secara default, karena proses ini umumnya spesifik pada distribusi tertentu. Hal ini bisa jadi akan diimplementasi nantinya.

Libc Linux (alias glibc) secara bawaan memiliki batasan nameserver DNS sebanyak 3 rekaman (records). Selain itu, pada glibc versi yang lebih lama dari glibc-2.17-222 (versi terbaru lihat isu ini), jumlah rekaman DNS search dibatasi sejumlah 6 (lihat masalah sejak 2005 ini). Kubernetes membutuhkan 1 rekaman nameserver dan 3 rekaman search. Ini berarti jika instalasi lokal telah menggunakan 3 nameserver atau menggunakan lebih dari 3 search,sementara versi glibc kamu termasuk yang terkena dampak, beberapa dari pengaturan tersebut akan hilang. Untuk menyiasati batasan rekaman DNS nameserver, node dapat menjalankan dnsmasq,yang akan menyediakan nameserver lebih banyak. Kamu juga dapat menggunakan kubelet --resolv-conf flag. Untuk menyiasati batasan rekaman search, pertimbangkan untuk memperbarui distribusi linux kamu atau memperbarui glibc ke versi yang tidak terdampak.

Jika kamu menggunakan Alpine versi 3.3 atau lebih lama sebagai dasar image kamu, DNS mungkin tidak dapat bekerja dengan benar disebabkan masalah dengan Alpine. Masalah 30215 Kubernetes menyediakan informasi lebih detil tentang ini.

Selanjutnya

4.4 - Kustomisasi Service DNS

Laman ini menjelaskan cara mengonfigurasi DNS Pod kamu dan menyesuaikan proses resolusi DNS pada klaster kamu.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Klaster kamu harus menjalankan tambahan (add-on) CoreDNS terlebih dahulu. Migrasi ke CoreDNS menjelaskan tentang bagaimana menggunakan kubeadm untuk melakukan migrasi dari kube-dns.

Kubernetes servermu harus dalam versi yang sama atau lebih baru dari v1.12.

Untuk melihat versi, tekan kubectl version.

Pengenalan

DNS adalah Service bawaan dalam Kubernetes yang diluncurkan secara otomatis melalui addon manager add-on klaster.

Sejak Kubernetes v1.12, CoreDNS adalah server DNS yang direkomendasikan untuk menggantikan kube-dns. Jika klaster kamu sebelumnya menggunakan kube-dns, maka kamu mungkin masih menggunakan kube-dns daripada CoreDNS.

Jika kamu menjalankan CoreDNS sebagai sebuah Deployment, maka biasanya akan ditampilkan sebagai sebuah Service Kubernetes dengan alamat IP yang statis. Kubelet meneruskan informasi DNS resolver ke setiap Container dengan argumen --cluster-dns=<dns-service-ip>.

Nama DNS juga membutuhkan domain. Kamu dapat mengonfigurasi domain lokal di kubelet dengan argumen --cluster-domain=<default-local-domain>.

Server DNS mendukung forward lookup (record A dan AAAA), port lookup (record SRV), reverse lookup alamat IP (record PTR), dan lain sebagainya. Untuk informasi lebih lanjut, lihatlah DNS untuk Service dan Pod.

Jika dnsPolicy dari Pod diatur menjadi default, itu berarti mewarisi konfigurasi resolusi nama dari Node yang dijalankan Pod. Resolusi DNS pada Pod harus berperilaku sama dengan Node tersebut. Tapi lihat Isu-isu yang telah diketahui.

Jika kamu tidak menginginkan hal ini, atau jika kamu menginginkan konfigurasi DNS untuk Pod berbeda, kamu bisa menggunakan argumen --resolv-conf pada kubelet. Atur argumen ini menjadi "" untuk mencegah Pod tidak mewarisi konfigurasi DNS. Atur ke jalur (path) berkas yang tepat untuk berkas yang berbeda dengan /etc/resolv.conf untuk menghindari mewarisi konfigurasi DNS.

CoreDNS

CoreDNS adalah server DNS otoritatif untuk kegunaan secara umum yang dapat berfungsi sebagai Service DNS untuk klaster, yang sesuai dengan spesifikasi dns.

Opsi ConfigMap pada CoreDNS

CoreDNS adalah server DNS yang modular dan mudah dipasang, dan setiap plugin dapat menambahkan fungsionalitas baru ke CoreDNS. Fitur ini dapat dikonfigurasikan dengan menjaga berkas Corefile, yang merupakan berkas konfigurasi dari CoreDNS. Sebagai administrator klaster, kamu dapat memodifikasi ConfigMap untuk Corefile dari CoreDNS dengan mengubah cara perilaku pencarian Service DNS pada klaster tersebut.

Di Kubernetes, CoreDNS diinstal dengan menggunakan konfigurasi Corefile bawaan sebagai berikut:

apiVersion: v1 kind: ConfigMap metadata:  name: coredns  namespace: kube-system data:  Corefile: |  .:53 {  errors  health {  lameduck 5s  }  ready  kubernetes cluster.local in-addr.arpa ip6.arpa {  pods insecure  fallthrough in-addr.arpa ip6.arpa  ttl 30  }  prometheus :9153  forward . /etc/resolv.conf  cache 30  loop  reload  loadbalance  } 

Konfigurasi Corefile meliputi plugin berikut ini dari CoreDNS:

  • errors: Kesalahan yang ditampilkan ke output standar (stdout)
  • health: Kesehatan dari CoreDNS dilaporkan pada http://localhost:8080/health. Dalam sintaks yang diperluas lameduck akan menangani proses tidak sehat agar menunggu selama 5 detik sebelum proses tersebut dimatikan.
  • ready: Endpoint HTTP pada port 8181 akan mengembalikan OK 200, ketika semua plugin yang dapat memberi sinyal kesiapan, telah memberikan sinyalnya.
  • kubernetes: CoreDNS akan menjawab pertanyaan (query) DNS berdasarkan IP Service dan Pod pada Kubernetes. Kamu dapat menemukan lebih detail tentang plugin itu dalam situs web CoreDNS. ttl memungkinkan kamu untuk mengatur TTL khusus untuk respon dari pertanyaan DNS. Standarnya adalah 5 detik. TTL minimum yang diizinkan adalah 0 detik, dan maksimum hanya dibatasi sampai 3600 detik. Mengatur TTL ke 0 akan mencegah record untuk di simpan sementara dalam cache.
    Opsi pods insecure disediakan untuk kompatibilitas dengan Service kube-dns sebelumnya. Kamu dapat menggunakan opsi pods verified, yang mengembalikan record A hanya jika ada Pod pada Namespace yang sama untuk alamat IP yang sesuai. Opsi pods disabled dapat digunakan jika kamu tidak menggunakan record Pod.
  • prometheus: Metrik dari CoreDNS tersedia pada http://localhost:9153/metrics dalam format yang sesuai dengan Prometheus (dikenal juga sebagai OpenMetrics).
  • forward: Setiap pertanyaan yang tidak berada dalam domain klaster Kubernetes akan diteruskan ke resolver yang telah ditentukan dalam berkas (/etc/resolv.conf).
  • cache: Ini untuk mengaktifkan frontend cache.
  • loop: Mendeteksi forwarding loop sederhana dan menghentikan proses CoreDNS jika loop ditemukan.
  • reload: Mengizinkan reload otomatis Corefile yang telah diubah. Setelah kamu mengubah konfigurasi ConfigMap, beri waktu sekitar dua menit agar perubahan yang kamu lakukan berlaku.
  • loadbalance: Ini adalah load balancer DNS secara round-robin yang mengacak urutan record A, AAAA, dan MX dalam setiap responnya.

Kamu dapat memodifikasi perilaku CoreDNS bawaan dengan memodifikasi ConfigMap.

Konfigurasi Stub-domain dan Nameserver Upstream dengan menggunakan CoreDNS

CoreDNS memiliki kemampuan untuk mengonfigurasi stubdomain dan nameserver upstream dengan menggunakan plugin forward.

Contoh

Jika operator klaster memiliki sebuah server domain Consul yang terletak di 10.150.0.1, dan semua nama Consul memiliki akhiran .consul.local. Untuk mengonfigurasinya di CoreDNS, administrator klaster membuat bait (stanza) berikut dalam ConfigMap CoreDNS.

consul.local:53 { errors cache 30 forward . 10.150.0.1 } 

Untuk memaksa secara eksplisit semua pencarian DNS non-cluster melalui nameserver khusus pada 172.16.0.1, arahkan forward ke nameserver bukan ke /etc/resolv.conf

forward . 172.16.0.1 

ConfigMap terakhir bersama dengan konfigurasi Corefile bawaan terlihat seperti berikut:

apiVersion: v1 kind: ConfigMap metadata:  name: coredns  namespace: kube-system data:  Corefile: |  .:53 {  errors  health  kubernetes cluster.local in-addr.arpa ip6.arpa {  pods insecure  fallthrough in-addr.arpa ip6.arpa  }  prometheus :9153  forward . 172.16.0.1  cache 30  loop  reload  loadbalance  }  consul.local:53 {  errors  cache 30  forward . 10.150.0.1  } 

Perangkat kubeadm mendukung terjemahan otomatis dari ConfigMap kube-dns ke ConfigMap CoreDNS yang setara.

Konfigurasi CoreDNS yang setara dengan kube-dns

CoreDNS mendukung fitur kube-dns dan banyak lagi lainnya. ConfigMap dibuat agar kube-dns mendukung StubDomains dan upstreamNameservers untuk diterjemahkan ke plugin forward dalam CoreDNS. Begitu pula dengan plugin Federations dalam kube-dns melakukan translasi untuk plugin federation dalam CoreDNS.

Contoh

Contoh ConfigMap ini untuk kube-dns menentukan federasi, stub domain dan server upstream nameserver:

apiVersion: v1 data:  federations: |  {"foo" : "foo.feddomain.com"}  stubDomains: |  {"abc.com" : ["1.2.3.4"], "my.cluster.local" : ["2.3.4.5"]}  upstreamNameservers: |  ["8.8.8.8", "8.8.4.4"] kind: ConfigMap 

Untuk konfigurasi yang setara dengan CoreDNS buat Corefile berikut:

  • Untuk federasi:
federation cluster.local { foo foo.feddomain.com } 
  • Untuk stubDomain:
abc.com:53 {  errors  cache 30  forward . 1.2.3.4 } my.cluster.local:53 {  errors  cache 30  forward . 2.3.4.5 } 

Corefile lengkap dengan plugin bawaan:

.:53 { errors health kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa } federation cluster.local { foo foo.feddomain.com } prometheus :9153 forward . 8.8.8.8 8.8.4.4 cache 30 } abc.com:53 { errors cache 30 forward . 1.2.3.4 } my.cluster.local:53 { errors cache 30 forward . 2.3.4.5 } 

Migrasi ke CoreDNS

Untuk bermigrasi dari kube-dns ke CoreDNS, artikel blog yang detail tersedia untuk membantu pengguna mengadaptasi CoreDNS sebagai pengganti dari kube-dns.

Kamu juga dapat bermigrasi dengan menggunakan skrip deploy CoreDNS yang resmi.

Selanjutnya

4.5 - Melakukan Reservasi Sumber Daya Komputasi untuk Daemon Sistem

Node Kubernetes dapat dijadwalkan sesuai dengan kapasitas. Secara bawaan, Pod dapat menggunakan semua kapasitas yang tersedia pada sebuah Node. Ini merupakan masalah karena Node sebenarnya menjalankan beberapa daemon sistem yang diperlukan oleh OS dan Kubernetes itu sendiri. Jika sumber daya pada Node tidak direservasi untuk daemon-daemon tersebut, maka Pod dan daemon akan berlomba-lomba menggunakan sumber daya yang tersedia, sehingga menyebabkan starvation sumber daya pada Node.

Fitur bernama Allocatable pada Node diekspos oleh kubelet yang berfungsi untuk melakukan reservasi sumber daya komputasi untuk daemon sistem. Kubernetes merekomendasikan admin klaster untuk mengatur Allocatable pada Node berdasarkan tingkat kepadatan (density) beban kerja setiap Node.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Kubernetes servermu harus dalam versi yang sama atau lebih baru dari 1.8.

Untuk melihat versi, tekan kubectl version.

Kamu harus menjalankan Kubernetes server dengan versi 1.17 atau yang lebih baru untuk menggunakan perintah baris kubelet dengan opsi --reserved-cpus untuk menyetel daftar reservasi CPU secara eksplisit.

Allocatable pada Node

 Kapasitas Node ------------------------------ | kube-reserved | |----------------------------| | system-reserved | |----------------------------| | eviction-threshold | | (batas pengusiran) | |----------------------------| | | | allocatable | | (dapat digunakan oleh Pod) | | | | | ------------------------------ 

Allocatable atau sumber daya yang dialokasikan pada sebuah Node Kubernetes merupakan jumlah sumber daya komputasi yang dapat digunakan oleh Pod. Penjadwal tidak dapat melakukan penjadwalan melebihi Allocatable. Saat ini dukungan terhadap CPU, memory dan ephemeral-storage tersedia.

Allocatable pada Node diekspos oleh objek API v1.Node dan merupakan bagian dari baris perintah kubectl describe node.

Sumber daya dapat direservasi untuk dua kategori daemon sistem melalui kubelet.

Mengaktifkan QoS dan tingkatan cgroup dari Pod

Untuk menerapkan batasan Allocatable pada Node, kamu harus mengaktifkan hierarki cgroup yang baru melalui flag --cgroups-per-qos. Secara bawaan, flag ini telah aktif. Saat aktif, kubelet akan memasukkan semua Pod pengguna di bawah sebuah hierarki cgroup yang dikelola oleh kubelet.

Mengonfigurasi driver cgroup

Manipulasi terhadap hierarki cgroup pada hos melalui driver cgroup didukung oleh kubelet. Driver dikonfigurasi melalui flag --cgroup-driver.

Nilai yang didukung adalah sebagai berikut:

  • cgroupfs merupakan driver bawaan yang melakukan manipulasi secara langsung terhadap filesystem cgroup pada hos untuk mengelola sandbox cgroup.
  • systemd merupakan driver alternatif yang mengelola sandbox cgroup menggunakan bagian dari sumber daya yang didukung oleh sistem init yang digunakan.

Tergantung dari konfigurasi runtime Container yang digunakan, operator dapat memilih driver cgroup tertentu untuk memastikan perilaku sistem yang tepat. Misalnya, jika operator menggunakan driver cgroup systemd yang disediakan oleh runtime docker, maka kubelet harus diatur untuk menggunakan driver cgroup systemd.

Kube Reserved

  • Flag Kubelet: --kube-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]
  • Flag Kubelet: --kube-reserved-cgroup=

kube-reserved berfungsi untuk mengambil informasi sumber daya reservasi untuk daemon sistem Kubernetes, seperti kubelet, runtime Container, detektor masalah pada Node, dsb. kube-reserved tidak berfungsi untuk mereservasi sumber daya untuk daemon sistem yang berjalan sebagai Pod. kube-reserved merupakan fungsi dari kepadatan Pod pada Node.

Selain dari cpu, memory, dan ephemeral-storage,pid juga dapat diatur untuk mereservasi jumlah ID proses untuk daemon sistem Kubernetes.

Secara opsional, kamu dapat memaksa daemon sistem melalui setelan kube-reserved. Ini dilakukan dengan menspesifikasikan parent cgroup sebagai nilai dari flag --kube-reserved-cgroup pada kubelet.

Kami merekomendasikan daemon sistem Kubernetes untuk ditempatkan pada tingkatan cgroup yang tertinggi (contohnya, runtime.slice pada mesin systemd). Secara ideal, setiap daemon sistem sebaiknya dijalankan pada child cgroup di bawah parent ini. Lihat dokumentasi untuk mengetahui rekomendasi hierarki cgroup secara detail.

Catatan: kubelet tidak membuat --kube-reserved-cgroup jika cgroup yang diberikan tidak ada pada sistem. Jika cgroup yang tidak valid diberikan, maka kubelet akan mengalami kegagalan.

System Reserved

  • Flag Kubelet: --system-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]
  • Flag Kubelet: --system-reserved-cgroup=

system-reserved berfungsi untuk mengetahui reservasi sumber daya untuk daemon sistem pada OS, seperti sshd, udev, dan lainnya. system-reserved sebaiknya mereservasi memori untuk kernel juga, karena memori kernel tidak termasuk dalam hitungan kalkulasi Pod pada Kubernetes. Kami juga merekomendasikan reservasi sumber daya untuk sesi (session) login pengguna (contohnya, user.slice di dalam dunia systemd).

Melakukan Reservasi Daftar CPU secara Eksplisit

FEATURE STATE: Kubernetes v1.17 [stable]
  • Flag Kubelet: --reserved-cpus=0-3

reserved-cpus berfungsi untuk mendefinisikan cpuset secara eksplisit untuk daemon sistem OS dan daemon sistem Kubernetes. reserved-cpus dimaksudkan untuk sistem-sistem yang tidak mendefinisikan tingkatan cgroup tertinggi secara terpisah untuk daemon sistem OS dan daemon sistem Kubernetes yang berkaitan dengan sumber daya cpuset.

Jika kubelet tidak memiliki --system-reserved-cgroup dan --kube-reserved-cgroup, cpuset akan diberikan secara eksplisit oleh reserved-cpus, yang akan menimpa definisi yang diberikan oleh opsi --kube-reserved dan --system-reserved.

Opsi ini dirancang secara spesifik untuk kasus-kasus Telco/NFV, di mana interrupt atau timer yang tidak terkontrol bisa memengaruhi performa dari beban kerja. Kamu dapat menggunakan opsi untuk untuk mendefinisikan cpuset secara eksplisit untuk daemon sistem/Kubernetes dan interrupt/timer, sehingga CPU sisanya dalam sistem akan digunakan untuk beban kerja saja, dengan dampak yang sedikit terhadap interrupt/timer yang tidak terkontrol. Untuk memindahkan daemon sistem, daemon Kubernetes serta interrrupt/timer Kubernetes supaya menggunakan cpuset yang eksplisit didefinisikan oleh opsi ini, sebaiknya digunakan mekanisme lain di luar Kubernetes. Contohnya: pada Centos, kamu dapat melakukan ini dengan menggunakan toolset yang sudah disetel.

Batas Pengusiran (Eviction Threshold)

  • Flag Kubelet: --eviction-hard=[memory.available<500Mi]

Tekanan memori pada tingkatan Node menyebabkan sistem OOM (Out Of Memory) yang berdampak pada Node secara keseluruhan dan semua Pod yang dijalankan di dalamnya. Node dapat berubah menjadi offline sementara sampai memori berhasil diklaim kembali. Untuk menghindari sistem OOM, atau mengurangi kemungkinan terjadinya OOM, kubelet menyediakan fungsi untuk pengelolaan saat Kehabisan Sumber Daya (Out of Resource). Pengusiran dapat dilakukan hanya untuk kasus kehabisan memory dan ephemeral-storage. Dengan mereservasi sebagian memori melalui flag --eviction-hard, kubelet akan berusaha untuk "mengusir" (evict) Pod ketika ketersediaan memori pada Node jatuh di bawah nilai yang telah direservasi. Dalam bahasa sederhana, jika daemon sistem tidak ada pada Node, maka Pod tidak dapat menggunakan memori melebihi nilai yang ditentukan oleh flag --eviction-hard. Karena alasan ini, sumber daya yang direservasi untuk pengusiran tidak tersedia untuk Pod.

Memaksakan Allocatable pada Node

  • Flag Kubelet: --enforce-node-allocatable=pods[,][system-reserved][,][kube-reserved]

Penjadwal menganggap Allocatable sebagai kapasitas yang tersedia untuk digunakan oleh Pod.

Secara bawaan, kubelet memaksakan Allocatable untuk semua Pod. Pemaksaan dilakukan dengan cara "mengusir" Pod-Pod ketika penggunaan sumber daya Pod secara keseluruhan telah melewati nilai Allocatable. Lihat bagian ini untuk mengetahui kebijakan pengusiran secara detail. Pemaksaan ini dikendalikan dengan cara memberikan nilai Pod melalui flag --enforce-node-allocatable pada kubelet.

Secara opsional, kubelet dapat diatur untuk memaksakan kube-reserved dan system-reserved dengan memberikan nilai melalui flag tersebut. Sebagai catatan, jika kamu mengatur kube-reserved, maka kamu juga harus mengatur --kube-reserved-cgroup. Begitu pula jika kamu mengatur system-reserved, maka kamu juga harus mengatur --system-reserved-cgroup.

Panduan Umum

Daemon sistem dilayani mirip seperti Pod Guaranteed yang terjamin sumber dayanya. Daemon sistem dapat melakukan burst di dalam jangkauan cgroup. Perilaku ini dikelola sebagai bagian dari penggelaran (deployment) Kubernetes. Sebagai contoh, kubelet harus memiliki cgroup sendiri dan membagikan sumber daya kube-reserved dengan runtime Container. Namun begitu, kubelet tidak dapat melakukan burst dan menggunakan semua sumber daya yang tersedia pada Node jika kube-reserved telah dipaksakan pada sistem.

Kamu harus berhati-hati ekstra ketika memaksakan reservasi system-reserved karena dapat menyebabkan layanan sistem yang terpenting mengalami CPU starvation, OOM killed, atau tidak dapat melakukan fork pada Node. Kami menyarankan untuk memaksakan system-reserved hanya jika pengguna telah melakukan profiling sebaik mungkin pada Node mereka untuk mendapatkan estimasi yang akurat dan percaya diri terhadap kemampuan mereka untuk memulihkan sistem ketika ada grup yang terkena OOM killed.

  • Untuk memulai, paksakan Allocatable pada Pod.
  • Ketika monitoring dan alerting telah cukup dilakukan untuk memonitor daemon dari sistem Kubernetes, usahakan untuk memaksakan kube-reserved berdasarkan penggunakan heuristik.
  • Jika benar-benar diperlukan, paksakan system-reserved secara bertahap.

Sumber daya yang diperlukan oleh daemon sistem Kubernetes dapat tumbuh seiring waktu dengan adanya penambahan fitur-fitur baru. Proyek Kubernetes akan berusaha untuk menurunkan penggunaan sumber daya dari daemon sistem Node, tetapi belum menjadi prioritas untuk saat ini. Kamu dapat berekspektasi bahwa fitur kapasitas Allocatable ini akan dihapus pada versi yang akan datang.

Contoh Skenario

Berikut ini merupakan contoh yang menggambarkan komputasi Allocatable pada Node:

  • Node memiliki 16 CPU, memori sebesar 32Gi, dan penyimpanan sebesar 100Gi.
  • --kube-reserved diatur menjadi cpu=1,memory=2Gi,ephemeral-storage=1Gi
  • --system-reserved diatur menjadi cpu=500m,memory=1Gi,ephemeral-storage=1Gi
  • --eviction-hard diatur menjadi memory.available<500Mi,nodefs.available<10%

Dalam skenario ini, Allocatable akan menjadi 14.5 CPU, memori 28.5Gi, dan penyimpanan lokal 88Gi. Penjadwal memastikan bahwa semua Pod yang berjalan pada Node ini secara total tidak meminta memori melebihi 28.5Gi dan tidak menggunakan penyimpanan lokal melebihi 88Gi. Pengusiran Pod akan dilakukan kubelet ketika penggunaan memori keseluruhan oleh Pod telah melebihi 28.5Gi, atau jika penggunaan penyimpanan keseluruhan telah melebihi 88Gi. Jika semua proses pada Node mengonsumsi CPU sebanyak-banyaknya, Pod-Pod tidak dapat mengonsumsi lebih dari 14.5 CPU.

Jika kube-reserved dan/atau system-reserved tidak dipaksakan dan daemon sistem melebihi reservasi mereka, maka kubelet akan mengusir Pod ketika penggunaan memori pada Node melebihi 31.5Gi atau penggunaan penyimpanan melebihi 90Gi.

4.6 - Membagi sebuah Klaster dengan Namespace

Laman ini menunjukkan bagaimana cara melihat, menggunakan dan menghapus namespaces. Laman ini juga menunjukkan bagaimana cara menggunakan Namespace Kubernetes namespaces untuk membagi klaster kamu.

Sebelum kamu memulai

Melihat Namespace

  1. Untuk melihat Namespace yang ada saat ini pada sebuah klaster anda bisa menggunakan:
kubectl get namespaces 
NAME STATUS AGE default Active 11d kube-system Active 11d kube-public Active 11d 

Kubernetes mulai dengan tiga Namespace pertama:

  • default Namespace bawaan untuk objek-objek yang belum terkait dengan Namespace lain
  • kube-system Namespace untuk objek-objek yang dibuat oleh sistem Kubernetes
  • kube-public Namespace ini dibuat secara otomatis dan dapat dibaca oleh seluruh pengguna (termasuk yang tidak terotentikasi). Namespace ini sering dicadangkan untuk kepentingan klaster, untuk kasus dimana beberapa sumber daya seharusnya dapat terlihat dan dapat terlihat secara publik di seluruh klaster. Aspek publik pada Namespace ini hanya sebuah konvensi bukan suatu kebutuhan.

Kamu bisa mendapat ringkasan Namespace tertentu dengan menggunakan:

kubectl get namespaces <name> 

Atau kamu bisa mendapatkan informasi detail menggunakan:

kubectl describe namespaces <name> 
Name: default Labels: <none> Annotations: <none> Status: Active No resource quota. Resource Limits Type Resource Min Max Default ---- -------- --- --- --- Container cpu - - 100m 

Sebagai catatan, detail diatas menunjukkan baik kuota sumber daya (jika ada) dan juga jangkauan batas sumber daya.

Kuota sumber daya melacak penggunaan total sumber daya didalam Namespace dan mengijinkan operator-operator klaster mendefinisikan batas atas penggunaan sumber daya yang dapat di gunakan sebuah Namespace.

Jangkauan batas mendefinisikan pertimbangan min/maks jumlah sumber daya yang dapat di gunakan oleh sebuah entitas dalam sebuah Namespace.

Lihatlah Kontrol Admisi: Rentang Batas

Sebuah Namespace dapat berada dalam salah satu dari dua buah fase:

  • Active Namespace sedang digunakan
  • Terminating Namespace sedang dihapus dan tidak dapat digunakan untuk objek-objek baru

Lihat dokumentasi desain untuk detil lebih lanjut.

Membuat sebuah Namespace baru

  1. Buat berkas YAML baru dengan nama my-namespace.yaml dengan isi berikut ini:

    apiVersion: v1 kind: Namespace metadata:  name: <masukkan-nama-namespace-disini> 

    Then run:

    kubectl create -f ./my-namespace.yaml 
  2. Sebagai alternatif, kamu bisa membuat Namespace menggunakan perintah dibawah ini:

    kubectl create namespace <masukkan-nama-namespace-disini> 

Nama Namespace kamu harus merupakan Label DNS yang valid.

Ada kolom opsional finalizers, yang memungkinkan observables untuk membersihkan sumber daya ketika Namespace dihapus. Ingat bahwa jika kamu memberikan finalizer yang tidak ada, Namespace akan dibuat tapi akan berhenti pada status Terminating jika pengguna mencoba untuk menghapusnya.

Informasi lebih lanjut mengenai finalizers bisa dibaca pada dokumentasi desain dari Namespace.

Menghapus Namespace

Hapus Namespace dengan

kubectl delete namespaces <insert-some-namespace-name> 

Proses penghapusan ini asinkron, jadi untuk beberapa waktu kamu akan melihat Namespace dalam status Terminating.

Membagi klaster kamu menggunakan Namespace Kubernetes

  1. Pahami Namespace bawaan

    Secara bawaan, sebuah klaster Kubernetes akan membuat Namespace bawaan ketika menyediakan klaster untuk menampung Pod, Service, dan Deployment yang digunakan oleh klaster.

    Dengan asumsi kamu memiliki klaster baru, kamu bisa mengecek Namespace yang tersedia dengan melakukan hal berikut:

    kubectl get namespaces 
    NAME STATUS AGE default Active 13m 
  2. Membuat Namespace baru

    Untuk latihan ini, kita akan membuat dua Namespace Kubernetes tambahan untuk menyimpan konten kita

    Dalam sebuah skenario dimana sebuah organisasi menggunakan klaster Kubernetes yang digunakan bersama untuk penggunaan pengembangan dan produksi:

    Tim pengembang ingin mengelola ruang di dalam klaster dimana mereka bisa melihat daftar Pod, Service, dan Deployment yang digunakan untuk membangun dan menjalankan apliksi mereka. Di ruang ini sumber daya akan datang dan pergi, dan pembatasan yang tidak ketat mengenai siapa yang bisa atau tidak bisa memodifikasi sumber daya untuk mendukung pengembangan secara gesit (agile).

    Tim operasi ingin mengelola ruang didalam klaster dimana mereka bisa memaksakan prosedur ketat mengenai siapa yang bisa atau tidak bisa melakukan manipulasi pada kumpulan Pod, Layanan, dan Deployment yang berjalan pada situs produksi.

    Satu pola yang bisa diikuti organisasi ini adalah dengan membagi klaster Kubernetes menjadi dua Namespace: development dan production

    Mari kita buat dua Namespace untuk menyimpan hasil kerja kita.

    Buat Namespace development menggunakan kubectl:

    kubectl create -f https://k8s.io/examples/admin/namespace-dev.json 

    Kemudian mari kita buat Namespace production menggunakan kubectl:

    kubectl create -f https://k8s.io/examples/admin/namespace-prod.json 

    Untuk memastikan apa yang kita lakukan benar, lihat seluruh Namespace dalam klaster.

    kubectl get namespaces --show-labels 
    NAME STATUS AGE LABELS default Active 32m <none> development Active 29s name=development production Active 23s name=production 
  3. Buat pod pada setiap Namespace

    Sebuah Namespace Kubernetes memberikan batasan untuk Pod, Service, dan Deployment dalam klaster.

    Pengguna yang berinteraksi dengan salah satu Namespace tidak melihat konten di dalam Namespace lain

    Untuk menunjukkan hal ini, mari kita jalankan Deployment dan Pod sederhana di dalam Namespace development.

    kubectl create deployment snowflake --image=registry.k8s.io/serve_hostname -n=development kubectl scale deployment snowflake --replicas=2 -n=development 

    Kita baru aja membuat sebuah Deployment yang memiliki ukuran replika dua yang menjalankan Pod dengan nama snowflake dengan sebuah Container dasar yang hanya melayani hostname.

    kubectl get deployment -n=development 
    NAME READY UP-TO-DATE AVAILABLE AGE snowflake 2/2 2 2 2m 
    kubectl get pods -l app=snowflake -n=development 
    NAME READY STATUS RESTARTS AGE snowflake-3968820950-9dgr8 1/1 Running 0 2m snowflake-3968820950-vgc4n 1/1 Running 0 2m 

    Dan ini merupakan sesuatu yang bagus, dimana pengembang bisa melakukan hal yang ingin mereka lakukan tanpa harus khawatir hal itu akan mempengaruhi konten pada namespace production.

    Mari kita pindah ke Namespace production dan menujukkan bagaimana sumber daya di satu Namespace disembunyikan dari yang lain

    Namespace production seharusnya kosong, dan perintah berikut ini seharusnya tidak menghasilkan apapun.

    kubectl get deployment -n=production kubectl get pods -n=production 

    Production Namespace ingin menjalankan cattle, mari kita buat beberapa Pod cattle.

    kubectl create deployment cattle --image=registry.k8s.io/serve_hostname -n=production kubectl scale deployment cattle --replicas=5 -n=production  kubectl get deployment -n=production 
    NAME READY UP-TO-DATE AVAILABLE AGE cattle 5/5 5 5 10s 
    kubectl get pods -l app=cattle -n=production 
    NAME READY STATUS RESTARTS AGE cattle-2263376956-41xy6 1/1 Running 0 34s cattle-2263376956-kw466 1/1 Running 0 34s cattle-2263376956-n4v97 1/1 Running 0 34s cattle-2263376956-p5p3i 1/1 Running 0 34s cattle-2263376956-sxpth 1/1 Running 0 34s 

Sampai sini, seharusnya sudah jelas bahwa sumber daya yang dibuat pengguna pada sebuah Namespace disembunyikan dari Namespace lainnya.

Seiring dengan evolusi dukungan kebijakan di Kubernetes, kami akan memperluas skenario ini untuk menunjukkan bagaimana kamu bisa menyediakan aturan otorisasi yang berbeda untuk tiap Namespace.

Memahami motivasi penggunaan Namespace

Sebuah klaster tunggal umumnya bisa memenuhi kebutuhan pengguna yang berbeda atau kelompok pengguna (itulah sebabnya disebut 'komunitas pengguna').

Namespace Kubernetes membantu proyek-proyek, tim-tim dan pelanggan yang berbeda untuk berbagi klaster Kubernetes.

Ini dilakukan dengan menyediakan hal berikut:

  1. Cakupan untuk Names.
  2. Sebuah mekanisme untuk memasang otorisasi dan kebijakan untuk bagian dari klaster.

Penggunaan Namespace berbeda merupakan hal opsional.

Tiap komunitas pengguna ingin bisa bekerja secara terisolasi dari komunitas lainnya.

Tiap komunitas pengguna memiliki hal berikut sendiri:

  1. sumber daya (Pod, Service, ReplicationController, dll.)
  2. kebijakan (siapa yang bisa atau tidak bisa melakukan hal tertentu dalam komunitasnya)
  3. batasan (komunitas ini diberi kuota sekian, dll.)

Seorang operator klaster dapat membuat sebuah Namespace untuk tiap komunitas user yang unik.

Namespace tersebut memberikan cakupan yang unik untuk:

  1. penamaan sumber daya (untuk menghindari benturan penamaan dasar)
  2. pendelegasian otoritas pengelolaan untuk pengguna yang dapat dipercaya
  3. kemampuan untuk membatasi konsumsi sumber daya komunitas

Contoh penggunaan mencakup

  1. Sebagai operator klaster, aku ingin mendukung beberapa komunitas pengguna dalam sebuah klaster.
  2. Sebagai operator klaster, aku ingin mendelegasikan otoritas untuk mempartisi klaster ke pengguna terpercaya di komunitasnya.
  3. Sebagai operator klaster, aku ingin membatasi jumlah sumber daya yang bisa dikonsumsi komunitas dalam rangka membatasi dampak ke komunitas lain yang menggunakan klaster yang sama.
  4. Sebagai pengguna klaster, aku ingin berinteraksi dengan sumber daya yang berkaitan dengan komunitas pengguna saya secara terisolasi dari apa yang dilakukan komunitas lain di klaster yang sama.

Memahami Namespace dan DNS

Ketika kamu membuat sebuah Service, akan terbentuk entri DNS untuk Service tersebut. Entri DNS ini dalam bentuk <service-name>.<namespace-name>.svc.cluster.local, yang berarti jika sebuah Container hanya menggunakan <service-name> maka dia akan me-resolve ke layanan yang lokal dalam Namespace yang sama. Ini berguna untuk menggunakan konfigurasi yang sama pada Namespace yang berbeda seperti Development, Staging dan Production. Jika kami ingin menjangkau antar Namespace, kamu harus menggunakan fully qualified domain name (FQDN).

Selanjutnya

4.7 - Mengatur Control Plane Kubernetes dengan Ketersediaan Tinggi (High-Availability)

FEATURE STATE: Kubernetes v1.5 [alpha]

Kamu dapat mereplikasi control plane Kubernetes dalam skrip kube-up atau kube-down untuk Google Compute Engine (GCE). Dokumen ini menjelaskan cara menggunakan skrip kube-up/down untuk mengelola control plane dengan ketersedian tinggi atau high_availability (HA) dan bagaimana control plane HA diimplementasikan untuk digunakan dalam GCE.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Memulai klaster yang kompatibel dengan HA

Untuk membuat klaster yang kompatibel dengan HA, kamu harus mengatur tanda ini pada skrip kube-up:

  • MULTIZONE=true - untuk mencegah penghapusan replika control plane kubelet dari zona yang berbeda dengan zona bawaan server. Ini diperlukan jika kamu ingin menjalankan replika control plane pada zona berbeda, dimana hal ini disarankan.

  • ENABLE_ETCD_QUORUM_READ=true - untuk memastikan bahwa pembacaan dari semua server API akan mengembalikan data terbaru. Jika true, bacaan akan diarahkan ke replika pemimpin dari etcd. Menetapkan nilai ini menjadi true bersifat opsional: pembacaan akan lebih dapat diandalkan tetapi juga akan menjadi lebih lambat.

Sebagai pilihan, kamu dapat menentukan zona GCE tempat dimana replika control plane pertama akan dibuat. Atur tanda berikut:

  • KUBE_GCE_ZONE=zone - zona tempat di mana replika control plane pertama akan berjalan.

Berikut ini contoh perintah untuk mengatur klaster yang kompatibel dengan HA pada zona GCE europe-west1-b:

MULTIZONE=true KUBE_GCE_ZONE=europe-west1-b ENABLE_ETCD_QUORUM_READS=true ./cluster/kube-up.sh 

Perhatikan bahwa perintah di atas digunakan untuk membuat klaster dengan sebuah control plane; Namun, kamu bisa menambahkan replika control plane baru ke klaster dengan perintah berikutnya.

Menambahkan replika control plane yang baru

Setelah kamu membuat klaster yang kompatibel dengan HA, kamu bisa menambahkan replika control plane ke sana. Kamu bisa menambahkan replika control plane dengan menggunakan skrip kube-up dengan tanda berikut ini:

  • KUBE_REPLICATE_EXISTING_MASTER=true - untuk membuat replika dari control plane yang sudah ada.

  • KUBE_GCE_ZONE=zone - zona di mana replika control plane itu berjalan. Region ini harus sama dengan region dari zona replika yang lain.

Kamu tidak perlu mengatur tanda MULTIZONE atau ENABLE_ETCD_QUORUM_READS, karena tanda itu diturunkan pada saat kamu memulai klaster yang kompatible dengan HA.

Berikut ini contoh perintah untuk mereplikasi control plane pada klaster sebelumnya yang kompatibel dengan HA:

KUBE_GCE_ZONE=europe-west1-c KUBE_REPLICATE_EXISTING_MASTER=true ./cluster/kube-up.sh 

Menghapus replika control plane

Kamu dapat menghapus replika control plane dari klaster HA dengan menggunakan skrip kube-down dengan tanda berikut:

  • KUBE_DELETE_NODES=false - untuk mencegah penghapusan kubelet.

  • KUBE_GCE_ZONE=zone - zona di mana replika control plane akan dihapus.

  • KUBE_REPLICA_NAME=replica_name - (opsional) nama replika control plane yang akan dihapus. Jika kosong: replika mana saja dari zona yang diberikan akan dihapus.

Berikut ini contoh perintah untuk menghapus replika control plane dari klaster HA yang sudah ada sebelumnya:

KUBE_DELETE_NODES=false KUBE_GCE_ZONE=europe-west1-c ./cluster/kube-down.sh 

Mengatasi replika control plane yang gagal

Jika salah satu replika control plane di klaster HA kamu gagal, praktek terbaik adalah menghapus replika dari klaster kamu dan menambahkan replika baru pada zona yang sama. Berikut ini contoh perintah yang menunjukkan proses tersebut:

  1. Menghapus replika yang gagal:
KUBE_DELETE_NODES=false KUBE_GCE_ZONE=replica_zone KUBE_REPLICA_NAME=replica_name ./cluster/kube-down.sh 
  1. Menambahkan replika baru untuk menggantikan replika yang lama
KUBE_GCE_ZONE=replica-zone KUBE_REPLICATE_EXISTING_MASTER=true ./cluster/kube-up.sh 

Praktek terbaik untuk mereplikasi control plane untuk klaster HA

  • Usahakan untuk menempatkan replika control plane pada zona yang berbeda. Pada saat terjadi kegagalan zona, semua control plane yang ditempatkan dalam zona tersebut akan gagal pula. Untuk bertahan dari kegagalan pada sebuah zona, tempatkan juga Node pada beberapa zona yang lain (Lihatlah multi-zona untuk lebih detail).

  • Jangan gunakan klaster dengan dua replika control plane. Konsensus pada klaster dengan dua replika membutuhkan kedua replika tersebut berjalan pada saat mengubah keadaan yang persisten. Akibatnya, kedua replika tersebut diperlukan dan kegagalan salah satu replika mana pun mengubah klaster dalam status kegagalan mayoritas. Dengan demikian klaster dengan dua replika lebih buruk, dalam hal HA, daripada klaster dengan replika tunggal.

  • Ketika kamu menambahkan sebuah replika control plane, status klaster (etcd) disalin ke sebuah instance baru. Jika klaster itu besar, mungkin butuh waktu yang lama untuk menduplikasi keadaannya. Operasi ini dapat dipercepat dengan memigrasi direktori data etcd, seperti yang dijelaskan di sini (Kami sedang mempertimbangkan untuk menambahkan dukungan untuk migrasi direktori data etcd di masa mendatang).

Catatan implementasi

ha-master-gce

Ikhtisar

Setiap replika control plane akan menjalankan komponen berikut dalam mode berikut:

  • instance etcd: semua instance akan dikelompokkan bersama menggunakan konsensus;

  • server API : setiap server akan berbicara dengan lokal etcd - semua server API pada cluster akan tersedia;

  • pengontrol (controller), penjadwal (scheduler), dan scaler klaster automatis: akan menggunakan mekanisme sewa - dimana hanya satu instance dari masing-masing mereka yang akan aktif dalam klaster;

  • manajer tambahan (add-on): setiap manajer akan bekerja secara independen untuk mencoba menjaga tambahan dalam sinkronisasi.

Selain itu, akan ada penyeimbang beban (load balancer) di depan server API yang akan mengarahkan lalu lintas eksternal dan internal menuju mereka.

Penyeimbang Beban

Saat memulai replika control plane kedua, penyeimbang beban yang berisi dua replika akan dibuat dan alamat IP dari replika pertama akan dipromosikan ke alamat IP penyeimbang beban. Demikian pula, setelah penghapusan replika control plane kedua yang dimulai dari paling akhir, penyeimbang beban akan dihapus dan alamat IP-nya akan diberikan ke replika terakhir yang ada. Mohon perhatikan bahwa pembuatan dan penghapusan penyeimbang beban adalah operasi yang rumit dan mungkin perlu beberapa waktu (~20 menit) untuk dipropagasikan.

Service control plane & kubelet

Daripada sistem mencoba untuk menjaga daftar terbaru dari apiserver Kubernetes yang ada dalam Service Kubernetes, sistem akan mengarahkan semua lalu lintas ke IP eksternal:

  • dalam klaster dengan satu control plane, IP diarahkan ke control plane tunggal.

  • dalam klaster dengan multiple control plane, IP diarahkan ke penyeimbang beban yang ada di depan control plane.

Demikian pula, IP eksternal akan digunakan oleh kubelet untuk berkomunikasi dengan control plane.

Sertifikat control plane

Kubernetes menghasilkan sertifikat TLS control plane untuk IP publik eksternal dan IP lokal untuk setiap replika. Tidak ada sertifikat untuk IP publik sementara (ephemeral) dari replika; Untuk mengakses replika melalui IP publik sementara, kamu harus melewatkan verifikasi TLS.

Pengklasteran etcd

Untuk mengizinkan pengelompokkan etcd, porta yang diperlukan untuk berkomunikasi antara instance etcd akan dibuka (untuk komunikasi dalam klaster). Untuk membuat penyebaran itu aman, komunikasi antara instance etcd diotorisasi menggunakan SSL.

Bacaan tambahan

Dokumen desain - Penyebaran master HA automatis

4.8 - Menggunakan sysctl dalam Sebuah Klaster Kubernetes

FEATURE STATE: Kubernetes v1.12 [beta]

Dokumen ini menjelaskan tentang cara mengonfigurasi dan menggunakan parameter kernel dalam sebuah klaster Kubernetes dengan menggunakan antarmuka sysctl.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Melihat Daftar Semua Parameter Sysctl

Dalam Linux, antarmuka sysctl memungkinkan administrator untuk memodifikasi kernel parameter pada runtime. Parameter tersedia melalui sistem file virtual dari proses /proc/sys/. Parameter mencakup berbagai subsistem seperti:

  • kernel (dengan prefiks umum: kernel.)
  • networking (dengan prefiks umum: net.)
  • virtual memory (dengan prefiks umum: vm.)
  • MDADM (dengan prefiks umum: dev.)
  • subsistem yang lainnya dideskripsikan pada dokumentasi Kernel.

Untuk mendapatkan daftar semua parameter, kamu bisa menjalankan perintah:

sudo sysctl -a 

Mengaktifkan Sysctl Unsafe

Sysctl dikelompokkan menjadi sysctl safe dan sysctl unsafe. Sebagai tambahan untuk pengaturan Namespace yang benar, sebuah sysctl safe harus diisolasikan dengan benar diantara Pod dalam Node yang sama. Hal ini berarti mengatur sysctl safe dalam satu Pod:

  • tidak boleh mempengaruhi Pod lain dalam Node
  • tidak boleh membahayakan kesehatan dari Node
  • tidak mengizinkan untuk mendapatkan sumber daya CPU atau memori di luar batas sumber daya dari sebuah Pod.

Sejauh ini, sebagian besar sysctl yang diatur sebagai Namespace belum tentu dianggap sysctl safe. Sysctl berikut ini didukung dalam kelompok safe:

  • kernel.shm_rmid_forced,
  • net.ipv4.ip_local_port_range,
  • net.ipv4.tcp_syncookies,
  • net.ipv4.ping_group_range (sejak Kubernetes 1.18),
  • net.ipv4.ip_unprivileged_port_start (sejak Kubernetes 1.22).

Daftar ini akan terus dikembangkan dalam versi Kubernetes berikutnya ketika kubelet mendukung mekanisme isolasi yang lebih baik.

Semua sysctl safe diaktifkan secara bawaan.

Semua sysctl unsafe dinon-aktifkan secara bawaan dan harus diizinkan secara manual oleh administrator klaster untuk setiap Node. Pod dengan sysctl unsafe yang dinon-aktifkan akan dijadwalkan, tetapi akan gagal untuk dijalankan.

Dengan mengingat peringatan di atas, administrator klaster dapat mengizinkan sysctl unsafe tertentu untuk situasi yang sangat spesial seperti pada saat kinerja tinggi atau penyetelan aplikasi secara real-time. Unsafe syctl diaktifkan Node demi Node melalui flag pada kubelet; sebagai contoh:

kubelet --allowed-unsafe-sysctls \  'kernel.msg*,net.core.somaxconn' ... 

Untuk Minikube, ini dapat dilakukan melalui flag extra-config:

minikube start --extra-config="kubelet.allowed-unsafe-sysctls=kernel.msg*,net.core.somaxconn"... 

Hanya sysctl yang diatur sebagai Namespace dapat diaktifkan dengan cara ini.

Mnegatur Sysctl untuk Pod

Sejumlah sysctl adalah diatur sebagai Namespace dalam Kernel Linux hari ini. Ini berarti mereka dapat diatur secara independen untuk setiap Pod dalam sebuah Node. Hanya sysctl dengan Namespace yang dapat dikonfigurasi melalui Pod securityContext dalam Kubernetes.

Sysctl berikut dikenal sebagai Namespace. Daftar ini dapat berubah pada versi kernel Linux yang akan datang.

  • kernel.shm*,
  • kernel.msg*,
  • kernel.sem,
  • fs.mqueue.*,
  • Parameter dibawah net.* dapat diatur sebagai Namespace dari container networking Namun, ada beberapa perkecualian (seperti net.netfilter.nf_conntrack_max dan net.netfilter.nf_conntrack_expect_max yang dapat diatur dalam Namespace container networking padahal bukan merupakan Namespace).

Sysctl tanpa Namespace disebut dengan sysctl node-level. Jika kamu perlu mengatur mereka, kamu harus secara manual mengonfigurasi mereka pada sistem operasi setiap Node, atau dengan menggunakan DaemonSet melalui Container yang berwenang.

Gunakan securityContext dari Pod untuk mengonfigurasi sysctl Namespace. securityContext berlaku untuk semua Container dalam Pod yang sama.

Contoh ini menggunakan securityContext dari Pod untuk mengatur sebuah sysctl safe kernel.shm_rmid_forced, dan dua buah sysctl unsafe net.core.somaxconn dan kernel.msgmax. Tidak ada perbedaan antara sysctl safe dan sysctl unsafe dalam spesifikasi tersebut.

apiVersion: v1 kind: Pod metadata:  name: sysctl-example spec:  securityContext:  sysctls:  - name: kernel.shm_rmid_forced  value: "0"  - name: net.core.somaxconn  value: "1024"  - name: kernel.msgmax  value: "65536"  ... 

Merupakan sebuah praktik yang baik untuk mempertimbangkan Node dengan pengaturan sysctl khusus sebagai Node yang tercemar (tainted) dalam sebuah cluster, dan hanya menjadwalkan Pod yang membutuhkan pengaturan sysctl. Sangat disarankan untuk menggunakan Kubernetes fitur taints and toleration untuk mengimplementasikannya.

Pod dengan sysctl unsafe akan gagal diluncurkan pada sembarang Node yang belum mengaktifkan kedua sysctl unsafe secara eksplisit. Seperti halnya sysctl node-level sangat disarankan untuk menggunakan fitur taints and toleration atau pencemaran dalam Node untuk Pod dalam Node yang tepat.

PodSecurityPolicy

Kamu selanjutnya dapat mengontrol sysctl mana saja yang dapat diatur dalam Pod dengan menentukan daftar sysctl atau pola (pattern) sysctl dalam forbiddenSysctls dan/atau field allowedUnsafeSysctls dari PodSecurityPolicy. Pola sysctl diakhiri dengan karakter *, seperti kernel.*. Karakter * saja akan mencakup semua sysctl.

Secara bawaan, semua sysctl safe diizinkan.

Kedua forbiddenSysctls dan allowedUnsafeSysctls merupakan daftar dari nama sysctl atau pola sysctl yang polos (yang diakhiri dengan karakter *). Karakter * saja berarti sesuai dengan semua sysctl.

Field forbiddenSysctls tidak memasukkan sysctl tertentu. Kamu dapat melarang kombinasi sysctl safe dan sysctl unsafe dalam daftar tersebut. Untuk melarang pengaturan sysctl, hanya gunakan * saja.

Jika kamu menyebutkan sysctl unsafe pada field allowedUnsafeSysctls dan tidak ada pada field forbiddenSysctls, maka sysctl dapat digunakan pada Pod dengan menggunakan PodSecurityPolicy ini. Untuk mengizinkan semua sysctl unsafe diatur dalam PodSecurityPolicy, gunakan karakter * saja.

Jangan mengonfigurasi kedua field ini sampai tumpang tindih, dimana sysctl yang diberikan akan diperbolehkan dan dilarang sekaligus.

Ini merupakan contoh sysctl unsafe yang diawali dengan kernel.msg yang diperbolehkan dan sysctl kernel.shm_rmid_forced yang dilarang.

apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata:  name: sysctl-psp spec:  allowedUnsafeSysctls:  - kernel.msg*  forbiddenSysctls:  - kernel.shm_rmid_forced  ... 

4.9 - Mengoperasikan klaster etcd untuk Kubernetes

etcd adalah 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.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Prerequisites

  • Jalankan etcd sebagai klaster dimana anggotanya berjumlah ganjil.

  • Etcd adalah sistem terdistribusi berbasis leader. Pastikan leader secara berkala mengirimkan heartbeat dengan tepat waktu ke semua pengikutnya untuk menjaga kestabilan klaster.

  • Pastikan tidak terjadi kekurangan sumber daya.

    Kinerja dan stabilitas dari klaster sensitif terhadap jaringan dan IO disk. Kekurangan sumber daya apa pun dapat menyebabkan timeout dari heartbeat, yang menyebabkan ketidakstabilan klaster. Etcd yang tidak stabil mengindikasikan bahwa tidak ada leader yang terpilih. Dalam keadaan seperti itu, sebuah klaster tidak dapat membuat perubahan apa pun ke kondisi saat ini, yang menyebabkan tidak ada Pod baru yang dapat dijadwalkan.

  • Menjaga kestabilan klaster etcd sangat penting untuk stabilitas klaster Kubernetes. Karenanya, jalankan klaster etcd pada mesin khusus atau lingkungan terisolasi untuk persyaratan sumber daya terjamin.

  • Versi minimum yang disarankan untuk etcd yang dijalankan dalam lingkungan produksi adalah 3.2.10+.

Persyaratan sumber daya

Mengoperasikan etcd dengan sumber daya terbatas hanya cocok untuk tujuan pengujian. Untuk peluncuran dalam lingkungan produksi, diperlukan konfigurasi perangkat keras lanjutan. Sebelum meluncurkan etcd dalam produksi, lihat dokumentasi referensi persyaratan sumber daya.

Memulai Klaster etcd

Bagian ini mencakup bagaimana memulai klaster etcd dalam Node tunggal dan Node multipel.

Klaster etcd dalam Node tunggal

Gunakan Klaster etcd Node tunggal hanya untuk tujuan pengujian

  1. Jalankan perintah berikut ini:

    ./etcd --listen-client-urls=http://$PRIVATE_IP:2379 --advertise-client-urls=http://$PRIVATE_IP:2379 
  2. Start server API Kubernetes dengan flag --etcd-servers=$PRIVATE_IP:2379.

    Ganti PRIVATE_IP dengan IP klien etcd kamu.

Klaster etcd dengan Node multipel

Untuk daya tahan dan ketersediaan tinggi, jalankan etcd sebagai klaster dengan Node multipel dalam lingkungan produksi dan cadangkan secara berkala. Sebuah klaster dengan lima anggota direkomendasikan dalam lingkungan produksi. Untuk informasi lebih lanjut, lihat Dokumentasi FAQ.

Mengkonfigurasi klaster etcd baik dengan informasi anggota statis atau dengan penemuan dinamis. Untuk informasi lebih lanjut tentang pengklasteran, lihat Dokumentasi pengklasteran etcd.

Sebagai contoh, tinjau sebuah klaster etcd dengan lima anggota yang berjalan dengan URL klien berikut: http://$IP1:2379, http://$IP2:2379, http://$IP3:2379, http://$IP4:2379, dan http://$IP5:2379. Untuk memulai server API Kubernetes:

  1. Jalankan perintah berikut ini:

    ./etcd --listen-client-urls=http://$IP1:2379, http://$IP2:2379, http://$IP3:2379, http://$IP4:2379, http://$IP5:2379 --advertise-client-urls=http://$IP1:2379, http://$IP2:2379, http://$IP3:2379, http://$IP4:2379, http://$IP5:2379 
  2. Start server Kubernetes API dengan flag --etcd-servers=$IP1:2379, $IP2:2379, $IP3:2379, $IP4:2379, $IP5:2379.

    Ganti IP dengan alamat IP klien kamu.

Klaster etcd dengan Node multipel dengan load balancer

Untuk menjalankan penyeimbangan beban (load balancing) untuk klaster etcd:

  1. Siapkan sebuah klaster etcd.
  2. Konfigurasikan sebuah load balancer di depan klaster etcd. Sebagai contoh, anggap saja alamat load balancer adalah $LB.
  3. Mulai Server API Kubernetes dengan flag --etcd-servers=$LB:2379.

Mengamankan klaster etcd

Akses ke etcd setara dengan izin root pada klaster sehingga idealnya hanya server API yang memiliki akses ke etcd. Dengan pertimbangan sensitivitas data, disarankan untuk memberikan izin hanya kepada Node-Node yang membutuhkan akses ke klaster etcd.

Untuk mengamankan etcd, tetapkan aturan firewall atau gunakan fitur keamanan yang disediakan oleh etcd. Fitur keamanan etcd tergantung pada Infrastruktur Kunci Publik / Public Key Infrastructure (PKI) x509. Untuk memulai, buat saluran komunikasi yang aman dengan menghasilkan pasangan kunci dan sertifikat. Sebagai contoh, gunakan pasangan kunci peer.key dan peer.cert untuk mengamankan komunikasi antara anggota etcd, dan client.key dan client.cert untuk mengamankan komunikasi antara etcd dan kliennya. Lihat contoh skrip yang disediakan oleh proyek etcd untuk menghasilkan pasangan kunci dan berkas CA untuk otentikasi klien.

Mengamankan komunikasi

Untuk mengonfigurasi etcd dengan secure peer communication, tentukan flag --peer-key-file=peer.key dan --peer-cert-file=peer.cert, dan gunakan https sebagai skema URL.

Demikian pula, untuk mengonfigurasi etcd dengan secure client communication, tentukan flag --key-file=k8sclient.key dan --cert-file=k8sclient.cert, dan gunakan https sebagai skema URL.

Membatasi akses klaster etcd

Setelah konfigurasi komunikasi aman, batasi akses klaster etcd hanya ke server API Kubernetes. Gunakan otentikasi TLS untuk melakukannya.

Sebagai contoh, anggap pasangan kunci k8sclient.key dan k8sclient.cert dipercaya oleh CA etcd.ca. Ketika etcd dikonfigurasi dengan --client-cert-auth bersama dengan TLS, etcd memverifikasi sertifikat dari klien dengan menggunakan CA dari sistem atau CA yang dilewati oleh flag --trusted-ca-file. Menentukan flag --client-cert-auth=true dan --trusted-ca-file=etcd.ca akan membatasi akses kepada klien yang mempunyai sertifikat k8sclient.cert.

Setelah etcd dikonfigurasi dengan benar, hanya klien dengan sertifikat yang valid dapat mengaksesnya. Untuk memberikan akses kepada server Kubernetes API, konfigurasikan dengan flag --etcd-certfile=k8sclient.cert,--etcd-keyfile=k8sclient.key dan --etcd-cafile=ca.cert.

Mengganti anggota etcd yang gagal

Etcd klaster mencapai ketersediaan tinggi dengan mentolerir kegagalan dari sebagian kecil anggota. Namun, untuk meningkatkan kesehatan keseluruhan dari klaster, segera ganti anggota yang gagal. Ketika banyak anggota yang gagal, gantilah satu per satu. Mengganti anggota yang gagal melibatkan dua langkah: menghapus anggota yang gagal dan menambahkan anggota baru.

Meskipun etcd menyimpan ID anggota unik secara internal, disarankan untuk menggunakan nama unik untuk setiap anggota untuk menghindari kesalahan manusia. Sebagai contoh, sebuah klaster etcd dengan tiga anggota. Jadikan URL-nya, member1=http://10.0.0.1, member2=http://10.0.0.2, and member3=http://10.0.0.3. Ketika member1 gagal, ganti dengan member4=http://10.0.0.4.

  1. Dapatkan ID anggota yang gagal dari member1:

    etcdctl --endpoints=http://10.0.0.2,http://10.0.0.3 member list

    Akan tampil pesan berikut:

     8211f1d0f64f3269, started, member1, http://10.0.0.1:2380, http://10.0.0.1:2379 91bc3c398fb3c146, started, member2, http://10.0.0.2:2380, http://10.0.0.2:2379 fd422379fda50e48, started, member3, http://10.0.0.3:2380, http://10.0.0.3:2379 
  2. Hapus anggota yang gagal:

    etcdctl member remove 8211f1d0f64f3269

    Akan tampil pesan berikut:

    Removed member 8211f1d0f64f3269 from cluster 
  3. Tambahkan anggota baru:

    ./etcdctl member add member4 --peer-urls=http://10.0.0.4:2380

    Akan tampil pesan berikut:

    Member 2be1eb8f84b7f63e added to cluster ef37ad9dc622a7c4 
  4. Jalankan anggota yang baru ditambahkan pada mesin dengan IP 10.0.0.4:

     export ETCD_NAME="member4" export ETCD_INITIAL_CLUSTER="member2=http://10.0.0.2:2380,member3=http://10.0.0.3:2380,member4=http://10.0.0.4:2380" export ETCD_INITIAL_CLUSTER_STATE=existing etcd [flags] 
  5. Lakukan salah satu dari yang berikut:

    1. Perbarui flag --etcd-server untuk membuat Kubernetes mengetahui perubahan konfigurasi, lalu start ulang server API Kubernetes.
    2. Perbarui konfigurasi load balancer jika load balancer digunakan dalam Deployment.

Untuk informasi lebih lanjut tentang konfigurasi ulang klaster, lihat Dokumentasi Konfigurasi etcd.

Mencadangkan klaster etcd

Semua objek Kubernetes disimpan dalam etcd. Mencadangkan secara berkala data klaster etcd penting untuk memulihkan klaster Kubernetes di bawah skenario bencana, seperti kehilangan semua Node control plane. Berkas snapshot berisi semua status Kubernetes dan informasi penting. Untuk menjaga data Kubernetes yang sensitif aman, enkripsi berkas snapshot.

Mencadangkan klaster etcd dapat dilakukan dengan dua cara: snapshot etcd bawaan dan snapshot volume.

Snapshot bawaan

Fitur snapshot didukung oleh etcd secara bawaan, jadi mencadangkan klaster etcd lebih mudah. Snapshot dapat diambil dari anggota langsung dengan command etcdctl snapshot save atau dengan menyalin member/snap/db berkas dari etcd direktori data yang saat ini tidak digunakan oleh proses etcd. Mengambil snapshot biasanya tidak akan mempengaruhi kinerja anggota.

Di bawah ini adalah contoh untuk mengambil snapshot dari keyspace yang dilayani oleh $ENDPOINT ke berkas snapshotdb:

ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshotdb # keluar 0  # memverifikasi hasil snapshot ETCDCTL_API=3 etcdctl --write-out=table snapshot status snapshotdb +----------+----------+------------+------------+ | HASH | REVISION | TOTAL KEYS | TOTAL SIZE | +----------+----------+------------+------------+ | fe01cf57 | 10 | 7 | 2.1 MB | +----------+----------+------------+------------+ 

Snapshot volume

Jika etcd berjalan pada volume penyimpanan yang mendukung cadangan, seperti Amazon Elastic Block Store, buat cadangan data etcd dengan mengambil snapshot dari volume penyimpanan.

Memperbesar skala dari klaster etcd

Peningkatan skala klaster etcd meningkatkan ketersediaan dengan menukarnya untuk kinerja. Penyekalaan tidak akan meningkatkan kinerja atau kemampuan klaster. Aturan umum adalah untuk tidak melakukan penyekalaan naik atau turun untuk klaster etcd. Jangan mengonfigurasi grup penyekalaan otomatis untuk klaster etcd. Sangat disarankan untuk selalu menjalankan klaster etcd statis dengan lima anggota untuk klaster produksi Kubernetes untuk setiap skala yang didukung secara resmi.

Penyekalaan yang wajar adalah untuk meningkatkan klaster dengan tiga anggota menjadi dengan lima anggota, ketika dibutuhkan lebih banyak keandalan. Lihat Dokumentasi Rekonfigurasi etcd untuk informasi tentang cara menambahkan anggota ke klaster yang ada.

Memulihkan klaster etcd

Etcd mendukung pemulihan dari snapshot yang diambil dari proses etcd dari versi major.minor. Memulihkan versi dari versi patch lain dari etcd juga didukung. Operasi pemulihan digunakan untuk memulihkan data klaster yang gagal.

Sebelum memulai operasi pemulihan, berkas snapshot harus ada. Ini bisa berupa berkas snapshot dari operasi pencadangan sebelumnya, atau dari sisa direktori data. Untuk informasi dan contoh lebih lanjut tentang memulihkan klaster dari berkas snapshot, lihat dokumentasi pemulihan bencana etcd.

Jika akses URL dari klaster yang dipulihkan berubah dari klaster sebelumnya, maka server API Kubernetes harus dikonfigurasi ulang sesuai dengan URL tersebut. Pada kasus ini, start kembali server API Kubernetes dengan flag --etcd-servers=$NEW_ETCD_CLUSTER bukan flag --etcd-servers=$OLD_ETCD_CLUSTER. Ganti $NEW_ETCD_CLUSTER dan $OLD_ETCD_CLUSTER dengan alamat IP masing-masing. Jika load balancer digunakan di depan klaster etcd, kamu mungkin hanya perlu memperbarui load balancer sebagai gantinya.

Jika mayoritas anggota etcd telah gagal secara permanen, klaster etcd dianggap gagal. Dalam skenario ini, Kubernetes tidak dapat membuat perubahan apa pun ke kondisi saat ini. Meskipun Pod terjadwal mungkin terus berjalan, tidak ada Pod baru yang bisa dijadwalkan. Dalam kasus seperti itu, pulihkan klaster etcd dan kemungkinan juga untuk mengonfigurasi ulang server API Kubernetes untuk memperbaiki masalah ini.

Memutakhirkan dan memutar balikan klaster etcd

Pada Kubernetes v1.13.0, etcd2 tidak lagi didukung sebagai backend penyimpanan untuk klaster Kubernetes baru atau yang sudah ada. Timeline untuk dukungan Kubernetes untuk etcd2 dan etcd3 adalah sebagai berikut:

  • Kubernetes v1.0: hanya etcd2
  • Kubernetes v1.5.1: dukungan etcd3 ditambahkan, standar klaster baru yang dibuat masih ke etcd2
  • Kubernetes v1.6.0: standar klaster baru yang dibuat dengan kube-up.sh adalah etcd3, dan kube-apiserver standarnya ke etcd3
  • Kubernetes v1.9.0: pengumuman penghentian backend penyimpanan etcd2 diumumkan
  • Kubernetes v1.13.0: backend penyimpanan etcd2 dihapus, kube-apiserver akan menolak untuk start dengan --storage-backend=etcd2, dengan pesan etcd2 is no longer a supported storage backend

Sebelum memutakhirkan v1.12.x kube-apiserver menggunakan --storage-backend=etcd2 ke v1.13.x, data etcd v2 harus dimigrasikan ke backend penyimpanan v3 dan permintaan kube-apiserver harus diubah untuk menggunakan --storage-backend=etcd3.

Proses untuk bermigrasi dari etcd2 ke etcd3 sangat tergantung pada bagaimana klaster etcd diluncurkan dan dikonfigurasi, serta bagaimana klaster Kubernetes diluncurkan dan dikonfigurasi. Kami menyarankan kamu berkonsultasi dengan dokumentasi penyedia klaster kamu untuk melihat apakah ada solusi yang telah ditentukan.

Jika klaster kamu dibuat melalui kube-up.sh dan masih menggunakan etcd2 sebagai penyimpanan backend, silakan baca Kubernetes v1.12 etcd cluster upgrade docs

Masalah umum: penyeimbang klien etcd dengan secure endpoint

Klien etcd v3, dirilis pada etcd v3.3.13 atau sebelumnya, memiliki critical bug yang mempengaruhi kube-apiserver dan penyebaran HA. Pemindahan kegagalan (failover) penyeimbang klien etcd tidak bekerja dengan baik dengan secure endpoint. Sebagai hasilnya, server etcd boleh gagal atau terputus sesaat dari kube-apiserver. Hal ini mempengaruhi peluncuran HA dari kube-apiserver.

Perbaikan dibuat di etcd v3.4 (dan di-backport ke v3.3.14 atau yang lebih baru): klien baru sekarang membuat bundel kredensial sendiri untuk menetapkan target otoritas dengan benar dalam fungsi dial.

Karena perbaikan tersebut memerlukan pemutakhiran dependensi dari gRPC (ke v1.23.0), downstream Kubernetes tidak mendukung upgrade etcd, yang berarti perbaikan etcd di kube-apiserver hanya tersedia mulai Kubernetes 1.16.

Untuk segera memperbaiki celah keamanan (bug) ini untuk Kubernetes 1.15 atau sebelumnya, buat kube-apiserver khusus. kamu dapat membuat perubahan lokal ke vendor/google.golang.org/grpc/credentials/credentials.go dengan etcd@db61ee106.

Lihat "kube-apiserver 1.13.x menolak untuk bekerja ketika server etcd pertama tidak tersedia".

5 - Mengelola Objek Kubernetes

Paradigma deklaratif dan imperatif untuk berinteraksi dengan API Kubernetes.

5.1 - Pengelolaan Objek Kubernetes secara Deklaratif dengan Menggunakan Berkas Konfigurasi

Objek-objek Kubernetes dapat dibuat, diperbarui, dan dihapus dengan menjalankan perintah kubectl apply terhadap file-file konfigurasi objek yang disimpan dalam sebuah direktori secara rekursif sesuai dengan kebutuhan. Perintah kubectl diff bisa digunakan untuk menampilkan pratinjau tentang perubahan apa saja yang akan dibuat oleh perintah kubectil apply.

Kelebihan dan kekurangan

Perintah kubectl memungkinkan tiga cara untuk mengelola objek:

  • Perintah imperatif
  • Konfigurasi objek imperatif
  • Konfigurasi objek deklaratif

Lihat Pengelolaan Objek Kubernetes untuk menyimak diskusi mengenai kelebihan dan kekurangan dari tiap cara pengelolaan objek.

Sebelum kamu mulai

Konfigurasi objek secara deklaratif membutuhkan pemahaman yang baik tentang definisi dan konfigurasi objek-objek Kubernetes. Jika belum pernah, kamu disarankan untuk membaca terlebih dulu dokumen-dokumen berikut:

Berikut adalah beberapa defnisi dari istilah-istilah yang digunakan dalam dokumen ini:

  • objek berkas konfigurasi / berkas konfigurasi: Sebuah file yang mendefinisikan konfigurasi untuk sebuah objek Kubernetes. Dokumen ini akan memperlihatkan cara menggunakan file konfigurasi dengan perintah kubectl apply. File-file konfigurasi biasanya disimpan di sebuah source control seperti Git.
  • konfigurasi objek live / konfigurasi live: nilai konfigurasi live dari sebuah objek, sebagaimana yang tersimpan di klaster Kubernetes. Nilai-nilai ini disimpan di storage klaster Kubernetes, biasanya etcd.
  • writer konfigurasi deklaratif / writer deklaratif: Seseorang atau sebuah komponen perangkat lunak yang membuat pembaruan ke objek live. Live writer yang disebut pada dokumen ini adalah writer yang membuat perubahan terhadap file konfigurasi objek dan menjalankan perintah kubectl apply untuk menulis perubahan-perubahan tersebut.

Cara membuat objek

Gunakan perintah kubectl apply untuk membuat semua objek, kecuali objek-objek yang sudah ada sebelumnya, yang didefinisikan di file-file konfigurasi dalam direktori yang ditentukan:

kubectl apply -f <directory>/ 

Perintah di atas akan memberi anotasi kubectl.kubernetes.io/last-applied-configuration: '{...}' pada setiap objek yang dibuat. Anotasi ini berisi konten dari file konfigurasi objek yang digunakan untuk membuat objek tersebut.

Berikut sebuah contoh file konfigurasi objek:

apiVersion: apps/v1 kind: Deployment metadata:  name: nginx-deployment spec:  selector:  matchLabels:  app: nginx  minReadySeconds: 5  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.7.9  ports:  - containerPort: 80 

Jalankan perintah kubectl diff untuk menampilkan objek yang akan dibuat:

kubectl diff -f https://k8s.io/examples/application/simple_deployment.yaml 

Buat objek dengan perintah kubectl apply:

kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml 

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml 

Keluaran perintah di atas akan menunjukkan bahwa anotasi kubectl.kubernetes.io/last-applied-configuration sudah dituliskan ke konfigurasi live, dan anotasi tersebut sesuai dengan file konfigurasi:

kind: Deployment metadata:  annotations:  # ...  # Ini merupakan representasi dari simple_deployment.yaml dalam format json  # Ini ditulis oleh perintah `kubectl apply` ketika objek dibuat  kubectl.kubernetes.io/last-applied-configuration: |  {"apiVersion":"apps/v1","kind":"Deployment",  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},  "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},  "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx",  "ports":[{"containerPort":80}]}]}}}}  # ... spec:  # ...  minReadySeconds: 5  selector:  matchLabels:  # ...  app: nginx  template:  metadata:  # ...  labels:  app: nginx  spec:  containers:  - image: nginx:1.7.9  # ...  name: nginx  ports:  - containerPort: 80  # ...  # ...  # ...  # ... 

Cara memperbarui objek

Kamu juga bisa menggunakan kubectl apply untuk memperbarui semua objek yang didefinisikan dalam sebuah direktori, termasuk objek-objek yang sudah ada sebelumnya. Cara ini akan melakukan hal-hal berikut:

  1. Menyimpan nilai field-field yang ada di file konfigurasi ke konfigurasi live.
  2. Menghapus field-field yang dihapus di file konfigurasi dari konfigurasi live.
kubectl diff -f <directory>/ kubectl apply -f <directory>/ 

Berikut sebuah contoh file konfigurasi:

apiVersion: apps/v1 kind: Deployment metadata:  name: nginx-deployment spec:  selector:  matchLabels:  app: nginx  minReadySeconds: 5  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.7.9  ports:  - containerPort: 80 

Buat objek dengan perintah kubectl apply::

kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml 

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml 

Keluaran perintah di atas akan menunjukkan bahwa anotasi kubectl.kubernetes.io/last-applied-configuration sudah dituliskan ke konfigurasi live, dan anotasi tersebut sesuai dengan file konfigurasi:

kind: Deployment metadata:  annotations:  # ...  # Berikut merupakan representasi dari simple_deployment.yaml dalam format json  # Representasi berikut ditulis oleh perintah kubectl apply ketika objek dibuat  kubectl.kubernetes.io/last-applied-configuration: |  {"apiVersion":"apps/v1","kind":"Deployment",  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},  "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},  "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx",  "ports":[{"containerPort":80}]}]}}}}  # ... spec:  # ...  minReadySeconds: 5  selector:  matchLabels:  # ...  app: nginx  template:  metadata:  # ...  labels:  app: nginx  spec:  containers:  - image: nginx:1.7.9  # ...  name: nginx  ports:  - containerPort: 80  # ...  # ...  # ...  # ... 

Perbarui nilai replicas secara langsung di konfigurasi live dengan menggunakan perintah kubectl scale. Pembaruan ini tidak menggunakan perintah kubectl apply:

kubectl scale deployment/nginx-deployment --replicas=2 

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml 

Keluaran perintah di atas akan menunjukkan bahwa nilai replicas telah diubah menjadi 2, dan anotasi last-applied-configuration tidak memuat nilai replicas:

apiVersion: apps/v1 kind: Deployment metadata:  annotations:  # ...  # perhatikan bahwa anotasi tidak memuat nilai replicas  # karena nilai tersebut tidak diperbarui melalui perintah kubectl-apply  kubectl.kubernetes.io/last-applied-configuration: |  {"apiVersion":"apps/v1","kind":"Deployment",  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},  "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},  "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx",  "ports":[{"containerPort":80}]}]}}}}  # ... spec:  replicas: 2 # ditulis oleh perintah kubectl scale  # ...  minReadySeconds: 5  selector:  matchLabels:  # ...  app: nginx  template:  metadata:  # ...  labels:  app: nginx  spec:  containers:  - image: nginx:1.7.9  # ...  name: nginx  ports:  - containerPort: 80  # ... 

Perbarui file konfigurasi simple_deployment.yaml, ubah image dari nginx:1.7.9 ke nginx:1.11.9, dan hapus field minReadySeconds:

apiVersion: apps/v1 kind: Deployment metadata:  name: nginx-deployment spec:  selector:  matchLabels:  app: nginx  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.11.9 # perbarui image  ports:  - containerPort: 80 

Terapkan perubahan yang telah dibuat di file konfigurasi:

kubectl diff -f https://k8s.io/examples/application/update_deployment.yaml kubectl apply -f https://k8s.io/examples/application/update_deployment.yaml 

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml 

Keluaran perintah di atas akan menunjukkan perubahan-perubahan berikut pada konfiguasi live:

  • Field replicas tetap bernilai 2 sesuai dengan nilai yang diatur oleh perintah kubectl scale. Hal ini karena field replicas dihapuskan dari file konfigurasi.
  • Nilai field image telah diperbarui menjadi nginx:1.11.9 dari nginx:1.7.9.
  • Anotasi last-applied-configuration telah diperbari dengan image terbaru.
  • Field minReadySeconds telah dihapus.
  • Anotasi last-applied-configuration tidak lagi memuat field minReadySeconds.
apiVersion: apps/v1 kind: Deployment metadata:  annotations:  # ...  # Anotasi memuat image yang telah diperbarui ke nginx 1.11.9,  # tetapi tidak memuat nilai replica yang telah diperbarui menjadi 2  kubectl.kubernetes.io/last-applied-configuration: |  {"apiVersion":"apps/v1","kind":"Deployment",  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},  "spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},  "spec":{"containers":[{"image":"nginx:1.11.9","name":"nginx",  "ports":[{"containerPort":80}]}]}}}}  # ... spec:  replicas: 2 # Diatur oleh `kubectl scale`, tidak diubah oleh `kubectl apply`.  # minReadySeconds dihapuskan oleh `kubectl apply`  # ...  selector:  matchLabels:  # ...  app: nginx  template:  metadata:  # ...  labels:  app: nginx  spec:  containers:  - image: nginx:1.11.9 # Diatur oleh `kubectl apply`  # ...  name: nginx  ports:  - containerPort: 80  # ...  # ...  # ...  # ... 

Cara menghapus objek

Ada dua cara untuk menghapus objek-objek yang dikelola dengan kubectl apply.

Rekomendasi: kubectl delete -f <filename>

Penghapusan objek secara manual dengan menggunakan perintah imperatif merupakan cara yang direkomendasikan karena lebih eksplisit dalam menentukan objek apa yang akan dihapus dan lebih kecil kemungkinannya untuk pengguna menghapus objek lain secara tidak sengaja:

kubectl delete -f <filename> 

Alternatif: kubectl apply -f <directory/> --prune -l your=label

Lakukan ini hanya jika kamu benar-benar mengetahui apa yang kamu lakukan.

Sebagai alternatif dari kubectl delete, kamu bisa menggunakan kubectl apply untuk mengidentifikasi objek-objek yang hendak dihapus setelah berkas konfigurasi objek-objek tersebut dihapus dari direktori. Ketika dijalankan dengan argumen --prune, perintah kubectl apply akan melakukan query ke API server untuk mencari semua objek yang sesuai dengan himpunan label-label tertentu, dan berusaha untuk mencocokkan kofigurasi objek live yg diperoleh terhadap file konfigurasi objek. Jika sebuah objek cocok dengan query yang dilakukan, dan objek tersebut tidak memiliki file konfigurasi di direktori serta tidak memiliki anotasi last-applied-configuration, objek tersebut akan dihapus.

kubectl apply -f <directory/> --prune -l <labels> 

Cara melihat objek

Kamu bisa menggunakan perintah kubectl get dengan parameter -o yaml untuk melihat konfigurasi dari sebuah objek live:

kubectl get -f <filename|url> -o yaml 

Cara kubectl apply menghitung perbedaan dan menggabungkan perubahan

Ketika memperbarui konfigurasi live dari sebuah objek, kubectl apply melakukannya dengan mengirimkan request untuk melakukan patch ke API server. Patch mendefinisikan pembaruan-pembaruan yang likungpnya sepsifik terhadap sejumlah field dari objek konfigurasi live. Perintah kubectl apply menghitung patch request ini menggunakan file konfigurasi, konfigurasi live, dan anotasi last-applied-configuration yang tersimpan di konfigurasi live.

Perhitungan penggabungan patch

Perintah kubectl apply menulis konten dari berkas konfigurasi ke anotasi kubectl.kubernetes.io/last-applied-configuration. Ini digunakan untuk mengidentifikasi field apa saja yang telah dihapus dari file konfigurasi dan perlu dihapus dari konfigurasi live. Berikut adalah langkah-langkah yang digunakan untuk menghitung field apa saja yang harus dihapus atau diubah:

  1. Hitung field-field yang perlu dihapus. Ini mencakup field-field yang ada di last-applied-configuration tapi tidak ada di file konfigurasi.
  2. Hitung field-field yang perlu ditambah atau diubah. Ini mencakup field-field yang ada di file konfigurasi yang nilainya tidak sama dengan konfigurasi live.

Agar lebih jelas, simak contoh berikut. Misalkan, berikut adalah file konfigurasi untuk sebuah objek Deployment:

apiVersion: apps/v1 kind: Deployment metadata:  name: nginx-deployment spec:  selector:  matchLabels:  app: nginx  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.11.9 # perbarui image  ports:  - containerPort: 80 

Juga, misalkan, berikut adalah konfigurasi live dari objek Deployment yang sama:

apiVersion: apps/v1 kind: Deployment metadata:  annotations:  # ...  # perhatikan bagaimana anotasi berikut tidak memuat replicas  # karena replicas tidak diperbarui melalui perintah kubectl apply  kubectl.kubernetes.io/last-applied-configuration: |  {"apiVersion":"apps/v1","kind":"Deployment",  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},  "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},  "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx",  "ports":[{"containerPort":80}]}]}}}}  # ... spec:  replicas: 2 # ditulis oleh perintah kubectl scale  # ...  minReadySeconds: 5  selector:  matchLabels:  # ...  app: nginx  template:  metadata:  # ...  labels:  app: nginx  spec:  containers:  - image: nginx:1.7.9  # ...  name: nginx  ports:  - containerPort: 80  # ... 

Berikut merupakan perhitungan penggabungan yang akan dilakukan oleh perintah kubectl apply:

  1. Hitung semua field yang akan dihapus dengan membaca nilai dari last-applied-configuration dan membandingkannya dengan nilai yang ada di file konfigurasi. Hapus semua field yang nilainya secara eksplisit diubah menjadi null pada file konfigurasi objek lokal terlepas dari apakah field-field tersebut ada di anotasi last-applied-configuration atau tidak. Pada contoh di atas, field minReadySeconds muncul pada anotasi last-applied-configuration, tapi tidak ada di file konfigurasi. Aksi: Hapus minReadySeconds dari konfigurasi live.
  2. Hitung semua field yang akan diubah dengan membaca nilai-nilai dari file konfigurasi dan membandingkannya dengan nilai-nilai yang ada di konfigurasi live. Pada contoh ini, nilai dari field image di file konfigurasi tidak sama dengan nilai dari konfigurasi live. Aksi: Ubah nilai image pada konfigurasi live.
  3. Ubah anotasi last-applied-configuration agar sesuai dengan nilai yang ada di file konfigurasi.
  4. Gabungkan hasil-hasil dari langkah 1, 2, dan 3 ke dalam satu patch request ke API server.

Berikut konfigurasi live yang dihasilkan oleh proses penggabungan pada contoh di atas:

apiVersion: apps/v1 kind: Deployment metadata:  annotations:  # ...  # Anotasi memuat pembaruan image menjadi nginx 1.11.9,  # tetapi tidak memuat pembaruan replicas menjadi 2  kubectl.kubernetes.io/last-applied-configuration: |  {"apiVersion":"apps/v1","kind":"Deployment",  "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},  "spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},  "spec":{"containers":[{"image":"nginx:1.11.9","name":"nginx",  "ports":[{"containerPort":80}]}]}}}}  # ... spec:  selector:  matchLabels:  # ...  app: nginx  replicas: 2 # Diubah oleh `kubectl scale`, tidak diubah oleh `kubectl apply`.  # minReadySeconds dihapus oleh `kubectl apply`  # ...  template:  metadata:  # ...  labels:  app: nginx  spec:  containers:  - image: nginx:1.11.9 # Diubah oleh `kubectl apply`  # ...  name: nginx  ports:  - containerPort: 80  # ...  # ...  # ...  # ... 

Cara penggabungan tipe-tipe field yang berbeda

Cara sebuah field terentu dalam sebuah file konfigurasi digabungkan dengan konfigurasi live bergantung pada tipe field tersebut. Ada beberapa tipe field:

  • primitif: field yang bertipe string, integer, atau boolean. Sebagai contoh, image dan replicas termasuk sebagai field primitif. Aksi: Replace.

  • map, atau objek: field yang bertipe map atau tipe kompleks yang mengandung sub field. Sebagai contoh, labels, annotations, spec, dan metadata termasuk sebagai map. Aksi: Lakukan penggabungan tiap-tiap elemen atau sub field.

  • list: field yang berisi sejumlah item yang tiap itemnya bisa berupa tipe primitif maupun map. Sebagai contoh, containers, ports, dan args termasuk sebagai list. Aksi: Bervariasi.

Ketika digunakan untuk memperbarui sebuah field bertipe map atau list, perintah kubectl apply memperbarui nilai tiap-tiap sub elemen ketimbang mengganti nilai semua field. Misalnya, ketika menggabungkan field spec pada sebuah Deployment, bukan keseluruhan field spec yang diubah nilainya. Alih-alih, sub field dari spec seperti replicas yang kemudian dibandingkan nilainya dan digabungkan.

Menggabungkan perubahan pada field primitif

Field primitif diganti nilainya atau dihapus sama sekali.

Field pada file konfigurasi objekField pada objek konfigurasi liveField pada last-applied-configurationAksi
YaYa-Ubah nilai di konfigurasi live mengikuti nilai pada file konfigurasi.
YaTidak-Ubah nilai di konfigurasi live mengikuti nilai pada konfigurasi lokal.
Tidak-YaHapus dari konfigurasi live.
Tidak-TidakTidak melakukan apa-apa, pertahankan nilai konfigurasi live.

Menggabungkan perubahan pada field bertipe map

Field yang bertipe map digabungkan dengan membandingkan tiap sub field atau elemen dari map:

Key pada file konfigurasi objekKey pada objek konfigurasi liveField pada last-applied-configurationAksi
YaYa-Bandingkan nilai tiap sub field.
YaTidak-Ubah nilai pada konfigurasi live mengikuti nilai pada konfigurasi lokal.
Tidak-YaHapus dari konfigurasi live.
Tidak-TidakTidak melakukan apa-apa, pertahankan nilai konfigurasi live.

Menggabungkan perubahan pada field yang bertipe list

Penggabungan perubahan pada sebuah list bisa menggunakan salah satu dari tiga strategi:

  • Ganti nilai keseluruhan list.
  • Gabungkan nilai tiap-tiap elemen di dalam sebuah list yang elemennya kompleks.
  • Gabungkan list yang elemennya primitif.

Pilihan strategi dibuat berbeda-beda bergantung tipe tiap field.

Ganti nilai keseluruhan list

Perlakukan list sama dengan field primitif. Ganti atau hapus keseluruhan list. Ini akan menjaga urutan dari list.

Contoh: Gunakan kubectl apply untuk memperbarui field args pada sebuah kontainer di dalam sebuah pod. Ini akan mengubah nilai args di konfigurasi live mengikuti nilai di file konfigurasi. Elemen args apapun yang sebelumnya ditambahkan ke konfigurasi live akan hilang. Urutan dari elemen-elemen args yang didefinisikan di file konfigurasi akan dipertahankan ketika ditulis ke konfigurasi live.

# nilai last-applied-configuration*  args: ["a", "b"]  # nilai berkas konfigurasi  args: ["a", "c"]  # nilai konfigurasi live  args: ["a", "b", "d"]  # hasil setelah penggabungan  args: ["a", "c"] 

Penjelasan: Penggabungan menggunakan nilai pada file konfigurasi sebagai nilai baru untuk list args.

Menggabungkan tiap-tiap elemen dari sebuah list dengan elemen kompleks:

Perlakukan list selayaknya sebuah map, perlakukan field spesifik dari tiap element sebagai sebuah key. Tambah, hapus, atau perbarui tiap-tiap elemen. Operasi ini tidak mempertahankan urutan elemen di dalam list.

Strategi penggabungan ini menggunakan tag khusus patchMergeKey pada tiap field. Tag patchMergeKey didefinisikan untuk tiap field pada source code Kubernetes: types.go. Ketika menggabungkan sebuah list yang berisi map, field yang dispesifikasikan sebagai patchMergeKey untuk tiap elemen digunakan sebagai map key untuk elemen tersebut.

Contoh: Gunakan kubectl apply untuk memperbarui field containers pada sebuah PodSpec. Perintah ini akan menggabungkan list containers seolah-olah list tersebut adalah sebuah map dan tiap elemennya menggunakan name sebagai key.

# nilai last-applied-configuration  containers:  - name: nginx  image: nginx:1.10  - name: nginx-helper-a # key: nginx-helper-a; akan dihapus pada hasil akhir  image: helper:1.3  - name: nginx-helper-b # key: nginx-helper-b; akan dipertahankan pada hasil akhir  image: helper:1.3  # nilai berkas konfigurasi  containers:  - name: nginx  image: nginx:1.10  - name: nginx-helper-b  image: helper:1.3  - name: nginx-helper-c # key: nginx-helper-c; akan ditambahkan pada hasil akhir  image: helper:1.3  # konfigurasi live  containers:  - name: nginx  image: nginx:1.10  - name: nginx-helper-a  image: helper:1.3  - name: nginx-helper-b  image: helper:1.3  args: ["run"] # Field ini akan dipertahankan pada hasil akhir  - name: nginx-helper-d # key: nginx-helper-d; akan dipertahankan pada hasil akhir  image: helper:1.3  # hasil akhir setelah penggabungan  containers:  - name: nginx  image: nginx:1.10  # Elemen nginx-helper-a dihapus  - name: nginx-helper-b  image: helper:1.3  args: ["run"] # Field dipertahankan  - name: nginx-helper-c # Elemen ditambahkan  image: helper:1.3  - name: nginx-helper-d # Elemen tidak diubah  image: helper:1.3 

Penjelasan:

  • Kontainer dengan nama "nginx-helper-a" dihapus karena tidak ada kontainer dengan nama tersebut di file konfigurasi.
  • Kontainer dengan nama "nginx-helper-b" tetap mempertahankan nilai args pada konfigurasi live. Perintah kubectl apply bisa mengenali bahwa "nginx-helper-b" di konfigurasi live sama dengan "ngnix-helper-b" di file konfigurasi, meskipun keduanya memiliki field yang berbeda (tidak ada args pada file konfigurasi). Ini karena nilai patchMergeKey di kedua konfigurasi identik.
  • Kontainer dengan nama "nginx-helper-c" ditambahkan karena tidak ada kontainer dengan nama tersebut di konfigurasi live, tapi ada di file konfigurasi.
  • Kontainer dengan nama "nginx-helper-d" dipertahankan karena tidak ada elemen dengan nama tersebut pada last-applied-configuration.

Menggabungkan sebuah list dengan elemen-elemen primitif

Pada versi Kubernetes 1.5, penggabungan list dengan elemen-elemen primitif tidak lagi didukung.

Nilai default dari sebuah field

API server mengisi field tertentu dengan nilai default pada konfigurasi live jika nilai field-field tersebut tidak dispesifikasikan ketika objek dibuat.

Berikut adalah sebuah file konfigurasi untuk sebuah Deployment. Berkas berikut tidak menspesifikasikan strategy:

apiVersion: apps/v1 kind: Deployment metadata:  name: nginx-deployment spec:  selector:  matchLabels:  app: nginx  minReadySeconds: 5  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.7.9  ports:  - containerPort: 80 

Buat objek dengan perintah kubectl apply:

kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml 

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml 

Keluaran dari perintah tadi menunjukkan bahwa API server mengisi beberapa field dengan nilai default pada konfigurasi live. Field-field berikut tidak dispesifikan pada file konfigurasi.

apiVersion: apps/v1 kind: Deployment # ... spec:  selector:  matchLabels:  app: nginx  minReadySeconds: 5  replicas: 1 # nilai default dari apiserver  strategy:  rollingUpdate: # nilai default dari apiserver - diturunkan dari strategy.type  maxSurge: 1  maxUnavailable: 1  type: RollingUpdate # nilai default dari apiserver  template:  metadata:  creationTimestamp: null  labels:  app: nginx  spec:  containers:  - image: nginx:1.7.9  imagePullPolicy: IfNotPresent # nilai default dari apiserver  name: nginx  ports:  - containerPort: 80  protocol: TCP # nilai default dari apiserver  resources: {} # nilai default dari apiserver  terminationMessagePath: /dev/termination-log # nilai default dari apiserver  dnsPolicy: ClusterFirst # nilai default dari apiserver  restartPolicy: Always # nilai default dari apiserver  securityContext: {} # nilai default dari apiserver  terminationGracePeriodSeconds: 30 # nilai default dari apiserver # ... 

Dalam sebuah patch request, field-field dengan nilai default tidak diisi kembali dengan nilai default kecuali secara eksplisit nilainya dihapuskan sebagai bagian dari patch request. Ini bisa menimbulkan hasil yang tak terduga jika sebagian field diisi dengan nilai default yang diturunkan dari nilai field lainnya. Ketika field lain tersebut nilainya diubah, field-field yang diisi dengan nilai default berdasarkan field yang berubah tadi tidak akan diperbarui kecuali secara eksplisit dihapus.

Oleh karena itu, beberapa field yang nilainya diisi secara default oleh server perlu didefinisikan secara eksplisit di file konfigurasi, meskipun nilai yang diinginkan sudah sesuai dengan nilai default dari server. Ini untuk mempermudah mengenali nilai-nilai yang berselisih yang tidak akan diisi dengan nilai default oleh server.

Contoh:

# last-applied-configuration spec:  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.7.9  ports:  - containerPort: 80  # berkas konfigurasi spec:  strategy:  type: Recreate # nilai yang diperbarui  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.7.9  ports:  - containerPort: 80  # konfigurasi live spec:  strategy:  type: RollingUpdate # nilai default  rollingUpdate: # nilai default yang diturunkan dari type  maxSurge : 1  maxUnavailable: 1  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.7.9  ports:  - containerPort: 80  # hasil setelah penggabungan - ERROR! spec:  strategy:  type: Recreate # nilai yang diperbarui: tidak kompatibel dengan field rollingUpdate  rollingUpdate: # nilai default: tidak kompatibel dengan "type: Recreate"  maxSurge : 1  maxUnavailable: 1  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.7.9  ports:  - containerPort: 80 

Penjelasan:

  1. Pengguna sebelumnya sudah membuat sebuah Deployment tanpa mendefinisikan strategy.type (seperti yang bisa dilihat pada last-applied-configuration).
  2. Server mengisi strategy.type dengan nilai default RollingUpdate dan mengisi strategy.rollingUpdate dengan nilai default pada konfigurasi live.
  3. Pengguna mengubah nilai field strategy.type menjadi Recreate pada file konfigurasi. Nilai strategy.rollingUpdate tidak berubah dari nilai default, meskipun server sekarang berekspektasi nilai tersebut dihapus. Jika nilai strategy.rollingUpdate didefinisikan di awal pada file konfigurasi, akan jelas bagi server bahwa field tersebut perlu dihapus.
  4. Perintah kubect apply gagal karena strategy.rollingUpdate tidak dihapus. Field strategy.rollingUpdate tidak bisa didefinisikan jika field strategy.type berisi Recreate.

Rekomendasi: Field-field ini harus didefinisikan secara eksplisit di file konfigurasi objek:

  • Label Selectors dan PodTemplate pada workloads, misalnya Deployment, StatefulSet, Job, DaemonSet, ReplicaSet, dan ReplicationController
  • Strategi Deployment rollout

Cara menghilangkan field-field yang diisi dengan nilai default atau diisi oleh writer lainnya

Field-field yang tidak muncul di file konfigurasi bisa dihilangkan dengan mengisi nilainya dengan null dan kemudian jalankan kubectl apply dengan file konfigurasi tersebut. Untuk field-field yang nilainya diisi dengan nilai default oleh server, aksi ini akan mmenyebabkan pengisian ulang field dengan nilai default.

Cara mengubah kepemilikan sebuah field antara file konfigurasi dan writer imperatif

Hanya metode-metode berikut yang bisa kamu gunakan untuk mengubah satu field objek:

  • Gunakan kubectl apply.
  • Tulis secara langsung ke konfigurasi live tanpa memodifikasi file konfigurasi: misalnya, dengan perintah kubectl scale.

Mengubah kepemilikan dari writer imperatif ke file konfigurasi

Tambahkan field ke file konfigurasi. Hentikan pembaruan secara langsung ke konfigurasi live tanpa melalui kubectl apply.

Mengubah kepemilikan dari file konfigurasi ke writer imperatif

Pada versi Kubernetes 1.5, mengubah kepemilikan sebuah field dari file konfigurasi memerlukan langkah-langkah manual:

  • Hapus field dari file konfigurasi.
  • Hapus field dari anotasi kubectl.kubernetes.io/last-applied-configuration pada objek live.

Mengubah metode-metode pengelolaan objek

Objek-objek Kubernetes sebaiknya dikelola dengan satu metode dalam satu waktu. Berpindah dari satu metode ke metode lain dimungkinkan, tetapi memerlukan proses manual.

Migrasi dari pengelolaan dengan perintah imperatif ke konfigurasi objek deklaratif

Migrasi dari pengelolaan objek dengan perintah imperatif ke pengelolaan objek dengan konfigurasi deklaratif memerlukan beberapa langkah manual:

  1. Ekspor objek live ke file konfigurasi lokal:

    kubectl get <kind>/<name> -o yaml > <kind>_<name>.yaml 
  2. Hapus secara manual field status dari file konfigurasi.

  3. Ubah anotasi kubectl.kubernetes.io/last-applied-configuration pada objek:

    kubectl replace --save-config -f <kind>_<name>.yaml 
  4. Selanjutnya gunakan kubectl apply secara eksklusif untuk mengelola objek.

Migrasi dari konfigurasi objek imperatif ke konfigurasi objek deklaratif

  1. Atur anotasi kubectl.kubernetes.io/last-applied-configuration pada objek:

    kubectl replace --save-config -f <kind>_<name>.yaml 
  2. Gunakan selalu perintah kubectl apply saja untuk mengelola objek.

Pendefinisian selektor controller dan label PodTemplate

Cara yang disarankan adalah dengan mendefinisikan sebuah PodTemplate immutable yang hanya digunakan oleh selektor controller tanpa memiliki arti semantik lainnya.

Contoh:

selector:  matchLabels:  controller-selector: "extensions/v1beta1/deployment/nginx" template:  metadata:  labels:  controller-selector: "extensions/v1beta1/deployment/nginx" 

Selanjutnya

5.2 - Mengelola Objek Kubernetes secara Deklaratif menggunakan Kustomize

Kustomize merupakan sebuah alat untuk melakukan kustomisasi objek Kubernetes melalui sebuah berkas berkas kustomization.

Sejak versi 1.14, kubectl mendukung pengelolaan objek Kubernetes melalui berkas kustomization. Untuk melihat sumber daya yang ada di dalam direktori yang memiliki berkas kustomization, jalankan perintah berikut:

kubectl kustomize <direktori_kustomization> 

Untuk menerapkan sumber daya tersebut, jalankan perintah kubectl apply dengan flag --kustomize atau -k:

kubectl apply -k <kustomization_directory> 

Sebelum kamu memulai

Instal kubectl terlebih dahulu.

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Gambaran Umum Kustomize

Kustomize adalah sebuah alat untuk melakukan kustomisasi konfigurasi Kubernetes. Untuk mengelola berkas-berkas konfigurasi, kustomize memiliki fitur -fitur di bawah ini:

  • membangkitkan (generate) sumber daya dari sumber lain
  • mengatur field dari berbagai sumber daya yang bersinggungan
  • mengkomposisikan dan melakukan kustomisasi sekelompok sumber daya

Membangkitkan Sumber Daya

ConfigMap dan Secret menyimpan konfigurasi atau data sensitif yang digunakan oleh objek-objek Kubernetes lainnya, seperti Pod. Biasanya, source of truth dari ConfigMap atau Secret berasal dari luar klaster, seperti berkas .properties atau berkas kunci SSH. Kustomize memiliki secretGenerator dan configMapGenerator, yang akan membangkitkan (generate) Secret dan ConfigMap dari berkas-berkas atau nilai-nilai literal.

configMapGenerator

Untuk membangkitkan sebuah ConfigMap dari berkas, tambahkan entri ke daftar files pada configMapGenerator. Contoh di bawah ini membangkitkan sebuah ConfigMap dengan data dari berkas .properties:

# Membuat berkas application.properties cat <<EOF >application.properties FOO=Bar EOF  cat <<EOF >./kustomization.yaml configMapGenerator: - name: example-configmap-1  files:  - application.properties EOF 

ConfigMap yang telah dibangkitkan dapat dilihat menggunakan perintah berikut:

kubectl kustomize ./ 

Isinya seperti di bawah ini:

apiVersion: v1 data:  application.properties: |  FOO: Bar kind: ConfigMap metadata:  name: example-configmap-1-42cfbf598f 

ConfigMap juga dapat dibangkitkan dari pasangan key-value literal. Untuk membangkitkan secara literal, tambahkan entri pada daftar literals di configMapGenerator. Contoh di bawah ini membangkitkan ConfigMap dengan data dari pasangan key-value:

cat <<EOF >./kustomization.yaml configMapGenerator: - name: example-configmap-2  literals:  - FOO=Bar EOF 

ConfigMap yang dibangkitkan dapat dilihat menggunakan perintah berikut:

kubectl kustomize ./ 

Isinya seperti ini:

apiVersion: v1 data:  FOO: Bar kind: ConfigMap metadata:  name: example-configmap-2-g2hdhfc6tk 

secretGenerator

Kamu dapat membangkitkan Secret dari berkas atau pasangan key-value literal. Untuk membangkitkan dari berkas, tambahkan entri pada daftar files di secretGenerator. Contoh di bawah ini membangkitkan Secret dengan data dari berkas:

# Membuat berkas password.txt cat <<EOF >./password.txt username=admin password=secret EOF  cat <<EOF >./kustomization.yaml secretGenerator: - name: example-secret-1  files:  - password.txt EOF 

Isinya seperti ini:

apiVersion: v1 data:  password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg== kind: Secret metadata:  name: example-secret-1-t2kt65hgtb type: Opaque 

Untuk membangkitkan secara literal dari pasangan key-value, tambahkan entri pada daftar literals di secretGenerator. Contoh di bawah ini membangkitkan Secret dengan data dari pasangan key-value:

cat <<EOF >./kustomization.yaml secretGenerator: - name: example-secret-2  literals:  - username=admin  - password=secret EOF 

Isinya seperti ini:

apiVersion: v1 data:  password: c2VjcmV0  username: YWRtaW4= kind: Secret metadata:  name: example-secret-2-t52t6g96d8 type: Opaque 

generatorOptions

ConfigMap dan Secret yang dibangkitkan memiliki informasi sufiks hash. Hal ini memastikan bahwa ConfigMap atau Secret yang baru, dibangkitkan saat isinya berubah. Untuk menonaktifkan penambahan sufiks ini, kamu bisa menggunakan generatorOptions. Selain itu, melalui field ini kamu juga bisa mengatur opsi-opsi yang bersinggungan untuk ConfigMap dan Secret yang dibangkitkan.

cat <<EOF >./kustomization.yaml configMapGenerator: - name: example-configmap-3  literals:  - FOO=Bar generatorOptions:  disableNameSuffixHash: true  labels:  type: generated  annotations:  note: generated EOF 

Jalankan perintah kubectl kustomize ./ untuk melihat ConfigMap yang dibangkitkan:

apiVersion: v1 data:  FOO: Bar kind: ConfigMap metadata:  annotations:  note: generated  labels:  type: generated  name: example-configmap-3 

Mengatur field yang bersinggungan

Mengatur field-field yang bersinggungan untuk semua sumber daya Kubernetes dalam sebuah proyek. Beberapa contoh kasusnya seperti di bawah ini:

  • mengatur Namespace yang sama untuk semua sumber daya
  • menambahkan prefiks atau sufiks yang sama
  • menambahkan kumpulan label yang sama
  • menambahkan kumpulan anotasi yang sama

Lihat contoh di bawah ini:

# Membuat sebuah deployment.yaml cat <<EOF >./deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: nginx-deployment  labels:  app: nginx spec:  selector:  matchLabels:  app: nginx  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx EOF  cat <<EOF >./kustomization.yaml namespace: my-namespace namePrefix: dev- nameSuffix: "-001" commonLabels:  app: bingo commonAnnotations:  oncallPager: 800-555-1212 resources: - deployment.yaml EOF 

Jalankan perintah kubectl kustomize ./ untuk melihat field-field tersebut telah terisi di dalam sumber daya Deployment:

apiVersion: apps/v1 kind: Deployment metadata:  annotations:  oncallPager: 800-555-1212  labels:  app: bingo  name: dev-nginx-deployment-001  namespace: my-namespace spec:  selector:  matchLabels:  app: bingo  template:  metadata:  annotations:  oncallPager: 800-555-1212  labels:  app: bingo  spec:  containers:  - image: nginx  name: nginx 

Mengkomposisi dan Melakukan Kustomisasi Sumber Daya

Mengkomposisi kumpulan sumber daya dalam sebuah proyek dan mengelolanya di dalam berkas atau direktori yang sama merupakan hal yang cukup umum dilakukan. Kustomize menyediakan cara untuk mengkomposisi sumber daya dari berkas-berkas yang berbeda, lalu menerapkan patch atau kustomisasi lain di atasnya.

Melakukan Komposisi

Kustomize mendukung komposisi dari berbagai sumber daya yang berbeda. Field resources pada berkas kustomization.yaml, mendefinisikan daftar sumber daya yang diinginkan dalam sebuah konfigurasi. Atur terlebih dahulu jalur (path) ke berkas konfigurasi sumber daya pada daftar resources. Contoh di bawah ini merupakan sebuah aplikasi NGINX yang terdiri dari sebuah Deployment dan sebuah Service:

# Membuat berkas deployment.yaml cat <<EOF > deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  selector:  matchLabels:  run: my-nginx  replicas: 2  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - name: my-nginx  image: nginx  ports:  - containerPort: 80 EOF  # Membuat berkas service.yaml cat <<EOF > service.yaml apiVersion: v1 kind: Service metadata:  name: my-nginx  labels:  run: my-nginx spec:  ports:  - port: 80  protocol: TCP  selector:  run: my-nginx EOF  # Membuat berkas kustomization.yaml yang terdiri dari keduanya cat <<EOF >./kustomization.yaml resources: - deployment.yaml - service.yaml EOF 

Sumber daya dari kubectl kustomize ./ berisi kedua objek Deployment dan Service.

Melakukan Kustomisasi

Patch dapat digunakan untuk menerapkan berbagai macam kustomisasi pada sumber daya. Kustomize mendukung berbagai mekanisme patching yang berbeda melalui patchesStrategicMerge dan patchesJson6902. patchesStrategicMerge adalah daftar dari yang berisi tentang path berkas. Setiap berkas akan dioperasikan dengan cara strategic merge patch. Nama di dalam patch harus sesuai dengan nama sumber daya yang telah dimuat. Kami menyarankan patch-patch kecil yang hanya melakukan satu hal saja. Contoh membuat sebuah patch di bawah ini akan menambahkan jumlah replika Deployment dan patch lainnya untuk mengatur limit memori.

# Membuat berkas deployment.yaml cat <<EOF > deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  selector:  matchLabels:  run: my-nginx  replicas: 2  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - name: my-nginx  image: nginx  ports:  - containerPort: 80 EOF  # Membuat sebuah patch increase_replicas.yaml cat <<EOF > increase_replicas.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  replicas: 3 EOF  # Membuat patch lainnya set_memory.yaml cat <<EOF > set_memory.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  template:  spec:  containers:  - name: my-nginx  resources:  limits:  memory: 512Mi EOF  cat <<EOF >./kustomization.yaml resources: - deployment.yaml patchesStrategicMerge: - increase_replicas.yaml - set_memory.yaml EOF 

Jalankan perintah kubectl kustomize ./ untuk melihat isi dari Deployment:

apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  replicas: 3  selector:  matchLabels:  run: my-nginx  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - image: nginx  limits:  memory: 512Mi  name: my-nginx  ports:  - containerPort: 80 

Tidak semua sumber daya atau field mendukung strategic merge patch. Untuk mendukung field sembarang pada sumber daya field, Kustomize menyediakan penerapan patch JSON melalui patchesJson6902. Untuk mencari sumber daya yang tepat dengan sebuah patch Json, maka grup, versi, jenis dan nama dari sumber daya harus dispesifikasikan dalam kustomization.yaml. Contoh di bawah ini menambahkan jumlah replika dari objek Deployment yang bisa juga dilakukan melalui patchesJson6902.

# Membuat berkas deployment.yaml cat <<EOF > deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  selector:  matchLabels:  run: my-nginx  replicas: 2  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - name: my-nginx  image: nginx  ports:  - containerPort: 80 EOF  # Membuat patch json cat <<EOF > patch.yaml - op: replace  path: /spec/replicas  value: 3 EOF  # Membuat berkas kustomization.yaml cat <<EOF >./kustomization.yaml resources: - deployment.yaml  patchesJson6902: - target:  group: apps  version: v1  kind: Deployment  name: my-nginx  path: patch.yaml EOF 

Jalankan perintah kubectl kustomize ./ untuk melihat field replicas yang telah diperbarui:

apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  replicas: 3  selector:  matchLabels:  run: my-nginx  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - image: nginx  name: my-nginx  ports:  - containerPort: 80 

Selain patch, Kustomize juga menyediakan cara untuk melakukan kustomisasi image Container atau memasukkan nilai field dari objek lainnya ke dalam Container tanpa membuat patch. Sebagai contoh, kamu dapat melakukan kustomisasi image yang digunakan di dalam Container dengan menyebutkan spesifikasi field images di dalam kustomization.yaml.

cat <<EOF > deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  selector:  matchLabels:  run: my-nginx  replicas: 2  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - name: my-nginx  image: nginx  ports:  - containerPort: 80 EOF  cat <<EOF >./kustomization.yaml resources: - deployment.yaml images: - name: nginx  newName: my.image.registry/nginx  newTag: "1.4.0" EOF 

Jalankan perintah kubectl kustomize ./ untuk melihat image yang sedang digunakan telah diperbarui:

apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  replicas: 2  selector:  matchLabels:  run: my-nginx  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - image: my.image.registry/nginx:1.4.0  name: my-nginx  ports:  - containerPort: 80 

Terkadang, aplikasi yang berjalan di dalam Pod perlu untuk menggunakan nilai konfigurasi dari objek lainnya. Contohnya, sebuah Pod dari objek Deployment perlu untuk membaca nama Service dari Env atau sebagai argumen perintah. Ini karena nama Service bisa saja berubah akibat dari penambahan namePrefix atau nameSuffix pada berkas kustomization.yaml. Kami tidak menyarankan kamu untuk meng-hardcode nama Service di dalam argumen perintah. Untuk penggunaan ini, Kustomize dapat memasukkan nama Service ke dalam Container melalui vars.

# Membuat berkas deployment.yaml cat <<EOF > deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  selector:  matchLabels:  run: my-nginx  replicas: 2  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - name: my-nginx  image: nginx  command: ["start", "--host", "\$(MY_SERVICE_NAME)"] EOF  # Membuat berkas service.yaml cat <<EOF > service.yaml apiVersion: v1 kind: Service metadata:  name: my-nginx  labels:  run: my-nginx spec:  ports:  - port: 80  protocol: TCP  selector:  run: my-nginx EOF  cat <<EOF >./kustomization.yaml namePrefix: dev- nameSuffix: "-001"  resources: - deployment.yaml - service.yaml  vars: - name: MY_SERVICE_NAME  objref:  kind: Service  name: my-nginx  apiVersion: v1 EOF 

Jalankan perintah kubectl kustomize ./ untuk melihat nama Service yang dimasukkan ke dalam Container menjadi dev-my-nginx-001:

apiVersion: apps/v1 kind: Deployment metadata:  name: dev-my-nginx-001 spec:  replicas: 2  selector:  matchLabels:  run: my-nginx  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - command:  - start  - --host  - dev-my-nginx-001  image: nginx  name: my-nginx 

Base dan Overlay

Kustomize memiliki konsep base dan overlay. base merupakan direktori dengan kustomization.yaml, yang berisi sekumpulan sumber daya dan kustomisasi yang terkait. base dapat berupa direktori lokal maupun direktori dari repo remote, asalkan berkas kustomization.yaml ada di dalamnya. overlay merupakan direktori dengan kustomization.yaml yang merujuk pada direktori kustomization lainnya sebagai base-nya. base tidak memiliki informasi tentang overlay. dan dapat digunakan pada beberapa overlay sekaligus. overlay bisa memiliki beberapa base dan terdiri dari semua sumber daya yang berasal dari base yang juga dapat memiliki kustomisasi lagi di atasnya.

Contoh di bawah ini memperlihatkan kegunaan dari base:

# Membuat direktori untuk menyimpan base mkdir base # Membuat base/deployment.yaml cat <<EOF > base/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  selector:  matchLabels:  run: my-nginx  replicas: 2  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - name: my-nginx  image: nginx EOF  # Membuat berkas base/service.yaml cat <<EOF > base/service.yaml apiVersion: v1 kind: Service metadata:  name: my-nginx  labels:  run: my-nginx spec:  ports:  - port: 80  protocol: TCP  selector:  run: my-nginx EOF  # Membuat berkas base/kustomization.yaml cat <<EOF > base/kustomization.yaml resources: - deployment.yaml - service.yaml EOF 

base ini dapat digunakan di dalam beberapa overlay sekaligus. Kamu dapat menambahkan namePrefix yang berbeda ataupun field lainnya yang bersinggungan di dalam overlay berbeda. Di bawah ini merupakan dua buah overlay yang menggunakan base yang sama.

mkdir dev cat <<EOF > dev/kustomization.yaml resources: - ../base namePrefix: dev- EOF  mkdir prod cat <<EOF > prod/kustomization.yaml resources: - ../base namePrefix: prod- EOF 

Cara menerapkan/melihat/menghapus objek menggunakan Kustomize

Gunakan --kustomize atau -k di dalam perintah kubectl untuk mengenali sumber daya yang dikelola oleh kustomization.yaml. Perhatikan bahwa -k harus merujuk pada direktori kustomization, misalnya:

kubectl apply -k <direktori kustomization>/ 

Buatlah kustomization.yaml seperti di bawah ini:

# Membuat berkas deployment.yaml cat <<EOF > deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:  name: my-nginx spec:  selector:  matchLabels:  run: my-nginx  replicas: 2  template:  metadata:  labels:  run: my-nginx  spec:  containers:  - name: my-nginx  image: nginx  ports:  - containerPort: 80 EOF  # Membuat berkas kustomization.yaml cat <<EOF >./kustomization.yaml namePrefix: dev- commonLabels:  app: my-nginx resources: - deployment.yaml EOF 

Jalankan perintah di bawah ini untuk menerapkan objek Deployment dev-my-nginx:

> kubectl apply -k ./ deployment.apps/dev-my-nginx created 

Jalankan perintah di bawah ini untuk melihat objek Deployment dev-my-nginx:

kubectl get -k ./ 
kubectl describe -k ./ 

Jalankan perintah di bawah ini untuk membandingkan objek Deployment dev-my-nginx dengan kondisi yang diinginkan pada klaster jika manifes telah berhasil diterapkan:

kubectl diff -k ./ 

Jalankan perintah di bawah ini untuk menghapus objek Deployment dev-my-nginx:

> kubectl delete -k ./ deployment.apps "dev-my-nginx" deleted 

Daftar Fitur Kustomize

FieldTipeDeskripsi
namespacestringmenambahkan Namespace untuk semua sumber daya
namePrefixstringnilai dari field ini ditambahkan di awal pada nama dari semua sumber daya
nameSuffixstringnilai dari field ini ditambahkan di akhir pada nama dari semua sumber daya
commonLabelsmap[string]stringlabel untuk ditambahkan pada semua sumber daya dan selektor
commonAnnotationsmap[string]stringanotasi untuk ditambahkan pada semua sumber daya
resources[]stringsetiap entri di dalam daftar ini harus diselesaikan pada berkas konfigurasi sumber daya yang sudah ada
configmapGenerator[]ConfigMapArgssetiap entri di dalam daftar ini membangkitkan ConfigMap
secretGenerator[]SecretArgssetiap entri di dalam daftar ini membangkitkan Secret
generatorOptionsGeneratorOptionsmemodifikasi perilaku dari semua generator ConfigMap dan Secret
bases[]stringsetiap entri di dalam daftar ini harus diselesaikan ke dalam sebuah direktori yang berisi berkas kustomization.yaml
patchesStrategicMerge[]stringsetiap entri di dalam daftar ini harus diselesaikan dengan strategic merge patch dari sebuah objek Kubernetes
patchesJson6902[]Json6902setiap entri di dalam daftar ini harus diselesaikan ke suatu objek Kubernetes atau patch Json
vars[]Varsetiap entri digunakan untuk menangkap teks yang berasal dari field sebuah sumber daya
images[]Imagesetiap entri digunakan untuk memodifikasi nama, tag dan/atau digest untuk sebuah image tanpa membuat patch
configurations[]stringsetiap entri di dalam daftar ini harus diselesaikan ke sebuah berkas yang berisi konfigurasi transformer Kustomize
crds[]stringsetiap entri di dalam daftar ini harus diselesaikan ke sebuah berkas definisi OpenAPI untuk tipe Kubernetes

Selanjutnya

5.3 - Pengelolaan Objek Kubernetes dengan Perintah Imperatif

Objek-objek Kubernetes bisa dibuat, diperbarui, dan dihapus secara langsung dengan menggunakan perintah-perintah imperatif yang ada pada command-line kubectl. Dokumen ini menjelaskan cara perintah-perintah tersebut diorganisir dan cara menggunakan perintah-perintah tersebut untuk mengelola objek live.

Kelebihan dan kekurangan

Perintah kubectl mendukung tiga cara pengelolaan objek:

  • Perintah imperatif
  • Konfigurasi objek imperatif
  • Konfigurasi objek deklaratif

Lihat Pengelolaan Objek Kubernetes untuk mengenali lebih lanjut kelebihan dan kekurangan dari tiap pengelolaan objek.

Cara membuat objek

Perangkat kubectl mendukung perintah-perintah berbentuk kata kerja untuk membuat beberapa tipe objek yang paling umum. Perintah-perintah tersebut diberi nama yang mudah dikenali oleh pengguna yang belum familiar dengan tipe-tipe objek Kubernetes.

  • run: Membuat sebuah objek Deployment untuk menjalankan kontainer di satu atau lebih Pod.
  • expose: Membuat sebuah objek Service untuk mengatur lalu lintas beban antar Pod.
  • autoscale: Membuat sebuah objek Autoscaler untuk melakukan scaling horizontal secara otomatis terhadap sebuah objek controller, misalnya sebuah objek Deployment.

Perangkat kubectl juga mendukung perintah-perintah pembuatan objek yang berdasarkan pada tipe objek. Perintah-perintah ini mendukung lebih banyak tipe objek dan lebih eksplisit tentang intensi mereka. Tapi, perintah-perintah ini memerlukan pengguna untuk memahami tipe dari objek-objek yang hendak mereka buat.

  • create <objecttype> [<subtype>] <instancename>

Beberapa tipe objek memiliki sub tipe yang bisa kamu spesifikasikan pada perintah create. Misalnya, objek Service memiliki beberapa sub tipe seperti ClusterIP, LoadBalancer, dan NodePort. Berikut adalah sebuah contoh cara membuat sebuah Service dengan sub tipe NodePort:

kubectl create service nodeport <myservicename> 

Pada contoh di atas, perintah create service nodeport merupakan sub perintah dari create service.

Kamu bisa menggunakan parameter -h untuk mencari argumen-argumen dan paramenter-parameter yang didukung oleh sebuah sub perintah:

kubectl create service nodeport -h 

Cara memperbarui objek

Perintah kubectl mendukung perintah-perintah berbasis kata kerja untuk beberapa operasi pembaruan yang umum. Perintah-perintah ini diberi nama yang memudahkan pengguna yang belum familiar dengan objek-objek Kubernetes untuk melakukan pembaruan tanpa terlebih dulu mengetahui field-field spesifik yang harus diperbarui:

  • scale: Melakukan scaling horizontal terhadap sebuah controller untuk menambah atau menghapus Pod dengan memperbarui jumlah replika dari controller tersebut.
  • annotate: Menambah atau menghapus anotasi sebuah objek.
  • label: Menambah atau menghapus label sebuah objek.

Perintah kubectl juga mendukung perintah-perintah pembaruan berdasarkan salah satu aspek dari sebuah objek. Untuk tiap tipe objek yang berbeda, memperbarui sebuah aspek tertentu bisa berarti memperbarui sekumpulan field yang berbeda pula:

  • set <field>: Memperbarui salah satu aspek dari sebuah objek.

Perangkat kubectl juga mendukung beberapa cara lain untuk memperbarui objek live secara langsung, meskipun cara-cara berikut membutuhkan pemahaman yang lebih tentang skema objek Kubernetes.

  • edit: Secara langsung mengedit konfigurasi mentah dari sebuah objek live dengan membuka konfigurasinya di sebuah editor.
  • patch: Secara langsung memodifikasi field-field spesifik dari sebuah objek live dengan menggunakan patch string. Untuk detil lebih lanjut mengenai patch string, lihat bagian tentang patch pada Konvensi API.

Cara menghapus objek

Kamu bisa menggunakan perintah delete pada sebuah objek dari sebuah klaster:

  • delete <type>/<name>
kubectl delete deployment/nginx 

Cara melihat objek

Ada beberapa perintah untuk menampilkan informasi tentang sebuah objek:

  • get: Menampilkan informasi dasar dari objek-objek yang sesuai dengan parameter dari perintah ini. Gunakan get -h untuk melihat daftar opsi yang bisa digunakan.
  • describe: Menampilkan agregat informasi detil dari objek-objek yang sesuai dengan parameter dari perintah ini.
  • logs: Menampilkan isi stdout dan stderr dari sebuah kontainer yang berjalan di sebuah Pod.

Menggunakan perintah set untuk memodifikasi objek sebelum dibuat

Ada beberapa field objek yang tidak memiliki parameter yang bisa kamu gunakan pada perintah create. Pada kasus-kasus tersebut, kamu bisa menggunakan kombinasi dari perintah set dan create untuk menspesifikasikan nilai untuk field-field tersebut sebelum objek dibuat. Ini dilakukan dengan melakukan piping pada hasil dari perintah create ke perintah set, dan kemudian mengembalikan hasilnya ke perintah create. Simak contoh berikut:

kubectl create service clusterip my-svc --clusterip="None" -o yaml --dry-run | kubectl set selector --local -f - 'environment=qa' -o yaml | kubectl create -f - 
  1. Perintah kubectl create service -o yaml --dry-run membuat konfigurasi untuk sebuah Service, tapi kemudian menuliskan konfigurasi tadi ke stdout dalam format YAML alih-alih mengirimnya ke API Server Kubernetes.
  2. Perintah kubectl set selector --local -f - -o yaml membaca konfigurasi dari stdin, dan menuliskan pembaruan konfigurasi ke stdout dalam format YAML.
  3. Perintah kubectl create -f - membuat objek dengan menggunakan konfigurasi yang disediakan pada stdin.

Menggunakan --edit untuk memodifikasi objek sebelum dibuat

Kamu bisa menggunakan perintah kubectl create --edit untuk membuat perubahan terhadap sebuah objek sebelum objek tersebut dibuat. Simak contoh berikut:

kubectl create service clusterip my-svc --clusterip="None" -o yaml --dry-run > /tmp/srv.yaml kubectl create --edit -f /tmp/srv.yaml 
  1. Perintah kubectl create service membuat konfigurasi untuk objek Service dan menyimpannya di /tmp/srv.yaml.
  2. Perintah kubectl create --edit membuka berkas konfigurasi untuk disunting sebelum objek dibuat.

Selanjutnya

5.4 - Pengelolaan Objek Kubernetes Secara Imperatif dengan Menggunakan File Konfigurasi

Objek-objek Kubernetes bisa dibuat, diperbarui, dan dihapus dengan menggunakan perangkat command-line kubectl dan file konfigurasi objek yang ditulis dalam format YAML atau JSON. Dokumen ini menjelaskan cara mendefinisikan dan mengelola objek dengan menggunakan file konfigurasi.

Kelebihan dan kekurangan

Perintah kubectl mendukung tiga cara pengelolaan objek:

  • Perintah imperatif
  • Konfigurasi objek imperatif
  • Konfigurasi objek deklaratif

Lihat Pengelolaan Objek Kubernetes untuk mengenali lebih lanjut kelebihan dan kekurangan dari tiap cara pengelolaan objek.

Cara membuat objek

Kamu bisa menggunakan perintah kubectl create -f untuk membuat sebuah objek dari sebuah file konfigurasi. Rujuk dokumen referensi API Kubernetes untuk detil lebih lanjut.

  • kubectl create -f <nama-file|url>

Cara memperbarui objek

Kamu bisa menggunakan perintah kubectl replace -f untuk memperbarui sebuah objek live sesuai dengan sebuah file konfigurasi.

  • kubectl replace -f <nama-file|url>

Cara menghapus objek

Kamu bisa menggunakan perintah kubectl delete -f untuk menghapus sebuah objek yang dideskripsikan pada sebuah file konfigurasi.

  • kubectl delete -f <nama-file|url>

Cara melihat objek

Kamu bisa menggunakan perintah kubectl get -f untuk melihat informasi tentang sebuah objek yang dideskripsikan pada sebuah file konfigurasi.

  • kubectl get -f <nama-file|url> -o yaml

Parameter -o yaml menetapkan bahwa keseluruhan konfigurasi objek ditulis ke file yaml. Gunakan perintah kubectl get -h untuk melihat daftar pilihan selengkapnya.

Keterbatasan

Perintah-perintah create, replace, dan delete bekerja dengan baik saat tiap konfigurasi dari sebuah objek didefinisikan dan dicatat dengan lengkap pada file konfigurasi objek tersebut. Akan tetapi, ketika sebuah objek live diperbarui dan pembaruannya tidak dicatat di file konfigurasinya, pembaruan tersebut akan hilang ketika perintah replace dieksekusi di waktu berikutnya. Ini bisa terjadi saat sebuah controller, misalnya sebuah HorizontalPodAutoscaler, membuat pembaruan secara langsung ke sebuah objek live. Berikut sebuah contoh:

  1. Kamu membuat sebuah objek dari sebuah file konfigurasi.
  2. Sebuah sumber lain memperbarui objek tersebut dengan mengubah beberapa field.
  3. Kamu memperbarui objek tersebut dengan kubectl replace dari file konfigurasi. Perubahan yang dibuat dari sumber lain pada langkah nomor 2 di atas akan hilang.

Jika kamu perlu mendukung beberapa writer untuk objek yang sama, kamu bisa menggunakan kubectl apply untuk mengelola objek tersebut.

Membuat dan mengedit objek dari URL tanpa menyimpan konfigurasinya

Misalkan kamu memiliki URL dari sebuah file konfigurasi objek. Kamu bisa menggunakan kubectl create --edit untuk membuat perubahan pada konfigurasi sebelum objek tersebut dibuat. Langkah ini terutama berguna untuk mengikuti tutorial atau untuk pekerjaan-pekerjaan yang menggunakan sebuah file konfigurasi di URL terentu yang perlu dimodifikasi.

kubectl create -f <url> --edit 

Migrasi dari perintah imperatif ke konfigurasi objek imperatif

Migrsasi dari perintah imperatif ke konfigurasi objek imperatif melibatkan beberapa langkah manual.

  1. Ekspor objek live ke sebuah file konfigurasi objek lokal:
kubectl get <kind>/<name> -o yaml --export > <kind>_<name>.yaml 
  1. Hapus secara manual field status dari file konfigurasi objek.

  2. Untuk pengelolaan objek selanjutnya, gunakan perintah replace secara eksklusif.

kubectl replace -f <kind>_<name>.yaml 

Mendefinisikan controller selectors dan label PodTemplate

Pendekatan yang direkomendasikan adalah mendefinisikan sebuah label PodTemplate tunggal dan immutable yang hanya digunakan oleh controller selector tersebut, tanpa makna semantik lainnya.

Contoh label:

selector:  matchLabels:  controller-selector: "extensions/v1beta1/deployment/nginx" template:  metadata:  labels:  controller-selector: "extensions/v1beta1/deployment/nginx" 

Selanjutnya

6 - Memasukkan Data ke dalam Aplikasi

6.1 - Mendefinisikan Perintah dan Argumen untuk sebuah Kontainer

Laman ini menunjukkan bagaimana cara mendefinisikan perintah-perintah dan argumen-argumen saat kamu menjalankan Container dalam sebuah Pod.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Mendefinisikan sebuah perintah dan argumen-argumen saat kamu membuat sebuah Pod

Saat kamu membuat sebuah Pod, kamu dapat mendefinisikan sebuah perintah dan argumen-argumen untuk Container-Container yang berjalan di dalam Pod. Untuk mendefinisikan sebuah perintah, sertakan bidang command di dalam berkas konfigurasi. Untuk mendefinisikan argumen-argumen untuk perintah, sertakan bidang args di dalam berkas konfigurasi. Perintah dan argumen-argumen yang telah kamu definisikan tidak dapat diganti setelah Pod telah terbuat.

Perintah dan argumen-argumen yang kamu definisikan di dalam berkas konfigurasi membatalkan perintah dan argumen-argumen bawaan yang disediakan oleh image Container. Jika kamu mendefinisikan argumen-argumen, tetapi tidak mendefinisikan sebuah perintah, perintah bawaan digunakan dengan argumen-argumen baru kamu.

Pada latihan ini, kamu akan membuat sebuah Pod baru yang menjalankan sebuah Container. Berkas konfigurasi untuk Pod mendefinisikan sebuah perintah dan dua argumen:

apiVersion: v1 kind: Pod metadata:  name: command-demo  labels:  purpose: demonstrate-command spec:  containers:  - name: command-demo-container  image: debian  command: ["printenv"]  args: ["HOSTNAME", "KUBERNETES_PORT"]  restartPolicy: OnFailure 
  1. Buat sebuah Pod dengan berkas konfigurasi YAML:

    kubectl apply -f https://k8s.io/examples/pods/commands.yaml 
  2. Daftar Pod yang sedang berjalan

    kubectl get pods 

    Keluaran menunjukkan bahwa Container yang berjalan di dalam Pod command-demo telah selesai.

  3. Untuk melihat keluaran dari perintah yang berjalan di dalam Container, lihat log dari Pod tersebut:

    kubectl logs command-demo 

    Keluaran menunjukan nilai dari variabel lingkungan HOSTNAME dan KUBERNETES_PORT:

    command-demo tcp://10.3.240.1:443 

Menggunakan variabel lingkungan untuk mendefinisikan argumen

Dalam contoh sebelumnya, kamu mendefinisikan langsung argumen-argumen dengan menyediakan string. Sebagai sebuah alternatif untuk menyediakan string secara langsung, kamu dapat mendefinisikan argumen-argumen dengan menggunakan variabel lingkungan:

env: - name: MESSAGE  value: "hello world" command: ["/bin/echo"] args: ["$(MESSAGE)"] 

Ini berarti kamu dapat mendefinisikan sebuah argumen untuk sebuah Pod menggunakan salah satu teknik yang tersedia untuk mendefinisikan variabel-variabel lingkungan, termasuk ConfigMap dan Secret.

Menjalankan sebuah perintah di dalam shell

Di beberapa kasus, kamu butuh perintah untuk menjalankan sebuah shell. Contohnya, perintah kamu mungkin terdiri dari beberapa perintah yang digabungkan, atau mungkin berupa skrip shell. Untuk menjalankan perintah kamu di sebuah shell, bungkus seperti ini:

command: ["/bin/sh"] args: ["-c", "while true; do echo hello; sleep 10;done"] 

Catatan

Tabel ini merangkum nama-nama bidang yang digunakan oleh Docker dan Kubernetes.

DeskripsiNama bidang pada DockerNama bidang pada Kubernetes
Perintah yang dijalankan oleh ContainerEntrypointcommand
Argumen diteruskan ke perintahCmdargs

Saat kamu mengesampingkan Entrypoint dan Cmd standar, aturan-aturan ini berlaku:

  • Jika kamu tidak menyediakan command atau args untuk sebuah Container, maka command dan args yang didefinisikan di dalam image Docker akan digunakan.

  • Jika kamu menyediakan command tetapi tidak menyediakan args untuk sebuah Container, akan digunakan command yang disediakan. Entrypoint dan Cmd bawaan yang didefinisikan di dalam image Docker diabaikan.

  • Jika kamu hanya menyediakan args untuk sebuah Container, Entrypoint bawaan yang didefinisikan di dalam image Docker dijalakan dengan args yang kamu sediakan.

  • Jika kamu menyediakan command dan args, Entrypoint dan Cmd standar yang didefinisikan di dalam image Docker diabaikan. command kamu akan dijalankan dengan args kamu.

Berikut ini beberapa contoh:

Image EntrypointImage CmdContainer commandContainer argsCommand run
[/ep-1][foo bar]<not set><not set>[ep-1 foo bar]
[/ep-1][foo bar][/ep-2]<not set>[ep-2]
[/ep-1][foo bar]<not set>[zoo boo][ep-1 zoo boo]
[/ep-1][foo bar][/ep-2][zoo boo][ep-2 zoo boo]

Selanjutnya

6.2 - Mendefinisikan Variabel Lingkungan untuk sebuah Kontainer

Laman ini menunjukkan bagaimana cara untuk mendefinisikan variabel lingkungan (environment variable) untuk sebuah Container di dalam sebuah Pod Kubernetes.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Mendefinisikan sebuah variabel lingkungan untuk sebuah Container

Ketika kamu membuat sebuah Pod, kamu dapat mengatur variabel lingkungan untuk Container-Container yang berjalan di dalam sebuah Pod. Untuk mengatur variabel lingkungan, sertakan bagian env atau envFrom pada berkas konfigurasi.

Dalam latihan ini, kamu membuat sebuah Pod yang menjalankan satu buah Container. Berkas konfigurasi untuk Pod tersebut mendefinisikan sebuah variabel lingkungan dengan nama DEMO_GREETING yang bernilai "Hello from the environment". Berikut berkas konfigurasi untuk Pod tersebut:

apiVersion: v1 kind: Pod metadata:  name: envar-demo  labels:  purpose: demonstrate-envars spec:  containers:  - name: envar-demo-container  image: gcr.io/google-samples/node-hello:1.0  env:  - name: DEMO_GREETING  value: "Hello from the environment"  - name: DEMO_FAREWELL  value: "Such a sweet sorrow" 
  1. Buatlah sebuah Pod berdasarkan berkas konfigurasi YAML tersebut:

    kubectl apply -f https://k8s.io/examples/pods/inject/envars.yaml 
  2. Tampilkan Pod-Pod yang sedang berjalan:

    kubectl get pods -l purpose=demonstrate-envars 

    Keluarannya mirip seperti ini:

    NAME READY STATUS RESTARTS AGE envar-demo 1/1 Running 0 9s 
  3. Dapatkan sebuah shell ke Container yang sedang berjalan di Pod kamu:

    kubectl exec -it envar-demo -- /bin/bash 
  4. Di shell kamu, jalankan perintah printenv untuk melihat daftar variabel lingkungannya.

    root@envar-demo:/# printenv 

    Keluarannya mirip seperti ini:

    NODE_VERSION=4.4.2 EXAMPLE_SERVICE_PORT_8080_TCP_ADDR=10.3.245.237 HOSTNAME=envar-demo ... DEMO_GREETING=Hello from the environment DEMO_FAREWELL=Such a sweet sorrow 
  5. Untuk keluar dari shell tersebut, masukkan perintah exit.

Menggunakan variabel-variabel lingkungan di dalam konfigurasi kamu

Variabel-variabel lingkungan yang kamu definisikan di dalam sebuah konfigurasi Pod dapat digunakan di tempat lain dalam konfigurasi, contohnya di dalam perintah-perintah dan argumen-argumen yang kamu atur dalam Container-Container milik Pod. Pada contoh konfigurasi berikut, variabel-variabel lingkungan GREETING, HONORIFIC, dan NAME disetel masing-masing menjadi Warm greetings to, The Most Honorable, dan Kubernetes. Variabel-variabel lingkungan tersebut kemudian digunakan dalam argumen CLI yang diteruskan ke Container env-print-demo.

apiVersion: v1 kind: Pod metadata:  name: print-greeting spec:  containers:  - name: env-print-demo  image: bash  env:  - name: GREETING  value: "Warm greetings to"  - name: HONORIFIC  value: "The Most Honorable"  - name: NAME  value: "Kubernetes"  command: ["echo"]  args: ["$(GREETING) $(HONORIFIC) $(NAME)"] 

Setelah dibuat, perintah echo Warm greetings to The Most Honorable Kubernetes dijalankan di Container tersebut.

Selanjutnya

6.3 - Mendistribusikan Kredensial dengan Aman Menggunakan Secret

Laman ini menjelaskan bagaimana cara menginjeksi data sensitif, seperti kata sandi (password) dan kunci enkripsi, ke dalam Pod.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Mengubah data rahasia kamu ke dalam representasi Base64

Misalnya kamu mempunyai dua buah data rahasia: sebuah nama pengguna my-app dan kata sandi 39528$vdg7Jb. Pertama, gunakan alat penyandian Base64 untuk mengubah nama pengguna kamu dan kata sandi ke dalam representasi Base64. Berikut ini contoh menggunakan program Base64 yang umum digunakan:

echo -n 'my-app' | base64 echo -n '39528$vdg7Jb' | base64 

Hasil keluaran menampilkan representasi Base64 dari nama pengguna kamu yaitu bXktYXBw, dan representasi Base64 dari kata sandi kamu yaitu Mzk1MjgkdmRnN0pi.

Membuat Secret

Berikut ini adalah berkas konfigurasi yang dapat kamu gunakan untuk membuat Secret yang akan menampung nama pengguna dan kata sandi kamu:

apiVersion: v1 kind: Secret metadata:  name: test-secret data:  username: bXktYXBw  password: Mzk1MjgkdmRnN0pi 
  1. Membuat Secret

    kubectl apply -f https://k8s.io/examples/pods/inject/secret.yaml 
  2. Melihat informasi dari Secret:

    kubectl get secret test-secret 

    Hasil keluaran:

    NAME TYPE DATA AGE test-secret Opaque 2 1m 
  3. Melihat informasi detil dari Secret:

    kubectl describe secret test-secret 

    Hasil keluaran:

    Name: test-secret Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password: 13 bytes username: 7 bytes 

Membuat Secret langsung dengan kubectl

Jika kamu ingin melompati langkah penyandian dengan Base64, kamu dapat langsung membuat Secret yang sama dengan menggunakan perintah kubectl create secret. Contohnya:

kubectl create secret generic test-secret --from-literal='username=my-app' --from-literal='password=39528$vdg7Jb' 

Tentu saja ini lebih mudah. Pendekatan yang mendetil setiap langkah di atas bertujuan untuk mendemonstrasikan apa yang sebenarnya terjadi pada setiap langkah.

Membuat Pod yang memiliki akses ke data Secret melalui Volume

Berikut ini adalah berkas konfigurasi yang dapat kamu gunakan untuk membuat Pod:

apiVersion: v1 kind: Pod metadata:  name: secret-test-pod spec:  containers:  - name: test-container  image: nginx  volumeMounts:  # nama harus sesuai dengan nama Volume di bawah ini  - name: secret-volume  mountPath: /etc/secret-volume  # Data Secret diekspos ke Container di dalam Pod melalui Volume  volumes:  - name: secret-volume  secret:  secretName: test-secret 
  1. Membuat Pod:

    kubectl apply -f https://k8s.io/examples/pods/inject/secret-pod.yaml 
  2. Verifikasikan apakah Pod kamu sudah berjalan:

    kubectl get pod secret-test-pod 

    Hasil keluaran:

    NAME READY STATUS RESTARTS AGE secret-test-pod 1/1 Running 0 42m 
  3. Gunakan shell untuk masuk ke dalam Container yang berjalan di dalam Pod kamu:

    kubectl exec -i -t secret-test-pod -- /bin/bash 
  4. Data Secret terekspos ke Container melalui Volume yang dipasang (mount) pada /etc/secret-volume.

    Di dalam shell kamu, tampilkan berkas yang ada di dalam direktori /etc/secret-volume:

    # Jalankan ini di dalam shell dalam Container ls /etc/secret-volume 

    Hasil keluaran menampilkan dua buah berkas, masing-masing untuk setiap data Secret:

    password username 
  5. Di dalam shell kamu, tampilkan konten dari berkas username dan password:

    # Jalankan ini di dalam shell dalam Container echo "$( cat /etc/secret-volume/username )" echo "$( cat /etc/secret-volume/password )" 

    Hasil keluarannya adalah nama pengguna dan kata sandi kamu:

    my-app 39528$vdg7Jb 

Mendefinisikan variabel lingkungan Container menggunakan data Secret

Mendefinisikan variabel lingkungan Container menggunakan data dari Secret tunggal

  • Definisikan variabel lingkungan sebagai pasangan key-value pada Secret:

    kubectl create secret generic backend-user --from-literal=backend-username='backend-admin' 
  • Tentukan nilai backend-username yang didefinisikan di Secret ke variabel lingkungan SECRET_USERNAME di dalam spesifikasi Pod.

    apiVersion: v1 kind: Pod metadata:  name: env-single-secret spec:  containers:  - name: envars-test-container  image: nginx  env:  - name: SECRET_USERNAME  valueFrom:  secretKeyRef:  name: backend-user  key: backend-username 
  • Membuat Pod:

    kubectl create -f https://k8s.io/examples/pods/inject/pod-single-secret-env-variable.yaml 
  • Di dalam shell kamu, tampilkan konten dari variabel lingkungan SECRET_USERNAME dari Container

    kubectl exec -i -t env-single-secret -- /bin/sh -c 'echo $SECRET_USERNAME' 

    Hasil keluarannya

    backend-admin 

Mendefinisikan variabel lingkungan Container dengan data dari multipel Secret

  • Seperti contoh sebelumnya, buat Secret terlebih dahulu.

    kubectl create secret generic backend-user --from-literal=backend-username='backend-admin' kubectl create secret generic db-user --from-literal=db-username='db-admin' 
  • Definisikan variabel lingkungan di dalam spesifikasi Pod.

    apiVersion: v1 kind: Pod metadata:  name: envvars-multiple-secrets spec:  containers:  - name: envars-test-container  image: nginx  env:  - name: BACKEND_USERNAME  valueFrom:  secretKeyRef:  name: backend-user  key: backend-username  - name: DB_USERNAME  valueFrom:  secretKeyRef:  name: db-user  key: db-username 
  • Membuat Pod:

    kubectl create -f https://k8s.io/examples/pods/inject/pod-multiple-secret-env-variable.yaml 
  • Di dalam shell kamu, tampilkan konten dari variabel lingkungan Container

    kubectl exec -i -t envvars-multiple-secrets -- /bin/sh -c 'env | grep _USERNAME' 

    Hasil keluarannya

    DB_USERNAME=db-admin BACKEND_USERNAME=backend-admin 

Mengonfigurasi semua pasangan key-value di dalam Secret sebagai variabel lingkungan Container

  • Membuat Secret yang berisi banyak pasangan key-value

    kubectl create secret generic test-secret --from-literal=username='my-app' --from-literal=password='39528$vdg7Jb' 
  • Gunakan envFrom untuk mendefinisikan semua data Secret sebagai variabel lingkungan Container. Key dari Secret akan mennjadi nama variabel lingkungan di dalam Pod.

    apiVersion: v1 kind: Pod metadata:  name: envfrom-secret spec:  containers:  - name: envars-test-container  image: nginx  envFrom:  - secretRef:  name: test-secret 
  • Membuat Pod:

    kubectl create -f https://k8s.io/examples/pods/inject/pod-secret-envFrom.yaml 
  • Di dalam shell kamu, tampilkan variabel lingkungan Container username dan password

    kubectl exec -i -t envfrom-secret -- /bin/sh -c 'echo "username: $username\npassword: $password\n"' 

    Hasil keluarannya

    username: my-app password: 39528$vdg7Jb 

Referensi

Selanjutnya

7 - Menjalankan

Menjalankan dan mengatur aplikasi stateless dan stateful.

7.1 - Menjalankan Aplikasi Stateless Menggunakan Deployment

Dokumen ini menunjukkan cara bagaimana cara menjalankan sebuah aplikasi menggunakan objek Deployment Kubernetes.

Tujuan

  • Membuat sebuah Deployment Nginx.
  • Menggunakan kubectl untuk mendapatkan informasi mengenai Deployment.
  • Mengubah Deployment.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Kubernetes servermu harus dalam versi yang sama atau lebih baru dari v1.9.

Untuk melihat versi, tekan kubectl version.

Membuat dan Menjelajahi Deployment Nginx

Kamu dapat menjalankan aplikasi dengan membuat sebuah objek Deployment Kubernetes, dan kamu dapat mendeskripsikan sebuah Deployment di dalam berkas YAML. Sebagai contohnya, berkas YAML berikut mendeskripsikan sebuah Deployment yang menjalankan image Docker nginx:1.14.2:

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata:  name: nginx-deployment spec:  selector:  matchLabels:  app: nginx  replicas: 2 # tells deployment to run 2 pods matching the template  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.7.9  ports:  - containerPort: 80 
  1. Buatlah sebuah Deployment berdasarkan berkas YAML:

     kubectl apply -f https://k8s.io/examples/application/deployment.yaml 
  2. Tampilkan informasi dari Deployment:

     kubectl describe deployment nginx-deployment 

    Keluaran dari perintah tersebut akan menyerupai:

     Name: nginx-deployment Namespace: default CreationTimestamp: Tue, 30 Aug 2016 18:11:37 -0700 Labels: app=nginx Annotations: deployment.kubernetes.io/revision=1 Selector: app=nginx Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 1 max unavailable, 1 max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.14.2 Port: 80/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-1771418926 (2/2 replicas created) No events. 
  3. Lihatlah daftar Pod-Pod yang dibuat oleh Deployment:

     kubectl get pods -l app=nginx 

    Keluaran dari perintah tersebut akan menyerupai:

     NAME READY STATUS RESTARTS AGE nginx-deployment-1771418926-7o5ns 1/1 Running 0 16h nginx-deployment-1771418926-r18az 1/1 Running 0 16h 
  4. Tampilkan informasi mengenai Pod:

     kubectl describe pod <nama-pod> 

    dimana <nama-pod> merupakan nama dari Pod kamu.

Mengubah Deployment

Kamu dapat mengubah Deployment dengan cara mengaplikasikan berkas YAML yang baru. Berkas YAML ini memberikan spesifikasi Deployment untuk menggunakan Nginx versi 1.16.1.

apiVersion: apps/v1 # untuk versi sebelum 1.9.0 gunakan apps/v1beta2 kind: Deployment metadata:  name: nginx-deployment spec:  selector:  matchLabels:  app: nginx  replicas: 2  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.16.1 # Memperbarui versi nginx dari 1.14.2 ke 1.16.1  ports:  - containerPort: 80 
  1. Terapkan berkas YAML yang baru:

     kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml 
  2. Perhatikan bahwa Deployment membuat Pod-Pod dengan nama baru dan menghapus Pod-Pod lama:

     kubectl get pods -l app=nginx 

Meningkatkan Jumlah Aplikasi dengan Meningkatkan Ukuran Replika

Kamu dapat meningkatkan jumlah Pod di dalam Deployment dengan menerapkan berkas YAML baru. Berkas YAML ini akan meningkatkan jumlah replika menjadi 4, yang nantinya memberikan spesifikasi agar Deployment memiliki 4 buah Pod.

apiVersion: apps/v1 # untuk versi sebelum 1.9.0 gunakan apps/v1beta2 kind: Deployment metadata:  name: nginx-deployment spec:  selector:  matchLabels:  app: nginx  replicas: 4 # Memperbarui replica dari 2 menjadi 4  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx:1.16.1  ports:  - containerPort: 80 
  1. Terapkan berkas YAML:

     kubectl apply -f https://k8s.io/examples/application/deployment-scale.yaml 
  2. Verifikasi Deployment kamu saat ini yang memiliki empat Pod:

     kubectl get pods -l app=nginx 

    Keluaran dari perintah tersebut akan menyerupai:

     NAME READY STATUS RESTARTS AGE nginx-deployment-148880595-4zdqq 1/1 Running 0 25s nginx-deployment-148880595-6zgi1 1/1 Running 0 25s nginx-deployment-148880595-fxcez 1/1 Running 0 2m nginx-deployment-148880595-rwovn 1/1 Running 0 2m 

Menghapus Deployment

Menghapus Deployment dengan nama:

kubectl delete deployment nginx-deployment 

Cara Lama Menggunakan: ReplicationController

Cara yang dianjurkan untuk membuat aplikasi dengan replika adalah dengan menggunakan Deployment, yang nantinya akan menggunakan ReplicaSet. Sebelum Deployment dan ReplicaSet ditambahkan ke Kubernetes, aplikasi dengan replika dikonfigurasi menggunakan ReplicationController.

Selanjutnya

7.2 - Menghapus Paksa Pod StatefulSet

Laman ini menjelaskan bagaimana cara menghapus Pod yang menjadi bagian dari sebuah stateful set, dan menjelaskan pertimbangan yang harus diperhatikan saat melakukannya.

Sebelum kamu memulai

  • Ini merupakan tugas yang cukup rumit dan memiliki potensi melanggar beberapa properti yang melekat dari StatefulSet.
  • Sebelum melanjutkan, pastikan kamu paham dengan pertimbangan yang disebutkan di bawah ini.

Pertimbangan StatefulSet

Pada operasi normal dari StatefulSet, tidak pernah ada kebutuhan untuk menghapus paksa sebuah Pod StatefulSet. Controller StatefulSet bertanggung jawab terhadap pembuatan, penyekalaan dan penghapusan terhadap anggota dari StatefulSet. Controller akan berusaha menjaga agar jumlah Pod yang ditentukan dari 0 hingga N-1 hidup dan siap sedia. StatefulSet memastikan bahwa, pada waktu kapanpun, akan ada minimal satu Pod dengan identitas yang telah ditetapkan berjalan pada klaster. Hal ini direferensikan sebagai semantik at most one yang disediakan StatefulSet.

Penghapusan paksa secara manual harus dilakukan dengan hati-hati, karena hal tersebut berpotensi melanggar semantik at most one yang melekat pada StatefulSet. StatefulSet dapat digunakan untuk menjalankan aplikasi terklaster dan terdistribusi yang membutuhkan identitas jaringan dan penyimpanan yang stabil dan tetap. Aplikasi-aplikasi ini biasanya memiliki konfigurasi yang tergantung dengan sejumlah anggota dengan identitas yang tetap. Memiliki banyak anggota dengan identitas yang sama berpotensi menimbulkan kerusakan dan kehilangan data (contohnya skenario split brain pada sistem berbasis kuorum).

Menghapus Pod

Kamu dapat melakukan penghapusan Pod secara graceful dengan perintah berikut:

kubectl delete pods <pod> 

Agar perintah di atas mengarah ke terminasi secara graceful, Pod tidak boleh menspesifikasikan pod.Spec.TerminationGracePeriodSeconds dengan nilai 0. Praktik untuk mengatur nilai pod.Spec.TerminationGracePeriodSeconds menjadi 0 detik merupakan hal yang tidak aman dan sangat tidak disarankan untuk Pod StatefulSet. Penghapusan secara graceful itu aman dan akan memastikan bahwa Pod akan mati secara gracefully sebelum kubelet menghapus nama dari apiserver.

Kubernetes (versi 1.5 atau lebih baru) tidak akan menghapus Pod hanya karena Node tidak dapat dijangkau. Pod yang berjalan pada Node yang tidak dapat dijangkau akan memasuki keadaan 'Terminating' atau 'Unknown' setelah waktu habis. Pod juga dapat memasuki keadaan ini saat pengguna berusaha melakukan penghapusan secara graceful terhadap Pod pada Node yang tidak dapat dijangkau. Cara yang hanya dapat dilakukan untuk menghapus Pod pada keadaan tersebut dari apiserver adalah:

  • Objek Node telah dihapus (baik oleh kamu, atau oleh Controller Node).
  • Kubelet pada Node yang tidak responsif akan menanggapi, lalu mematikan Pod dan menghapusnya dari apiserver.
  • Penghapusan paksa Pod oleh pengguna.

Praktik terbaik yang direkomendasikan adalah menggunakan pendekatan pertama atau kedua. Jika sebuah Node telah terkonfirmasi mati (contohnya terputus dari jaringan secara permanen, dimatikan, dll), maka objek Node dihapus. Jika Node mengalami partisi jaringan, maka coba selesaikan masalah ini atau menunggu masalah itu terselesaikan. Saat partisi terselesaikan, kubelet akan menyelesaikan penghapusan Pod serta membebaskan namanya dari apiserver.

Normalnya, sistem akan menyelesaikan penghapusan saat Pod tidak lagi berjalan pada Node, atau Node telah dihapus oleh administrator. Kamu dapat mengabaikan hal ini dengan menghapus paksa Pod.

Penghapusan Paksa

Penghapusan paksa tidak menunggu konfirmasi dari kubelet bahwa Pod telah diterminasi. Terlepas dari apakah penghapusan paksa sukses mematikan sebuah Pod, namanya akan segera dibebaskan dari apiserver. Hal ini berakibat controller StatefulSet akan membuat Pod pengganti dengan identitas yang sama; ini dapat menimbulkan duplikasi terhadap Pod apabila ternyata Pod tersebut masih berjalan, dan jika Pod tersebut masih dapat berkomunikasi dengan anggota Statefulset lainnya, hal ini berakibat terjadi pelanggaran semantik at most one dari StatefulSet yang telah dijamin.

Saat kamu menghapus paksa sebuah Pod StatefulSet, berarti kamu menjamin bahwa Pod tersebut tidak akan pernah lagi berkomunikasi dengan Pod lain pada StatefulSet dan namanya dapat dibebaskan secara aman untuk pembuatan penggantinya.

Jika kamu ingin menghapus paksa Pod dengan menggunakan kubectl versi >= 1.5, lakukan perintah berikut:

kubectl delete pods <pod> --grace-period=0 --force 

Jika kamu menggunakan kubectl <= 1.4, kamu harus menghilangkan pilihan --force dan gunakan:

kubectl delete pods <pod> --grace-period=0 

Jika setelah perintah ini dijalankan dan Pod tetap berada pada kondisi Unknown, gunakan perintah berikut untuk menghapus Pod dari klaster:

kubectl patch pod <pod> -p '{"metadata":{"finalizers":null}}' 

Selalu jalankan penghapusan paksa Pod StatefulSet dengan hati-hati dan penuh pemahaman terhadap risiko yang dapat timbul.

Selanjutnya

Pelajari lebih lanjut debugging StatefulSet.

7.3 - HorizontalPodAutoscaler

HorizontalPodAutoscaler secara otomatis akan memperbanyak jumlah Pod di dalam ReplicationController, Deployment, ReplicaSet ataupun StatefulSet berdasarkan hasil observasi penggunaan CPU(atau, dengan metrik khusus, pada beberapa aplikasi yang menyediakan metrik). Perlu dicatat bahwa HorizontalPodAutoscale tidak dapat diterapkan pada objek yang tidak dapat diperbanyak, seperti DeamonSets.

HorizontalPodAutoscaler diimplementasikan sebagai Kubernetes API resource dan sebuah controller. Resource tersebut akan menentukan perilaku dari controller-nya. Kontroler akan mengubah jumlah replika pada ReplicationController atau pada Deployment untuk menyesuaikan dengan hasil observasi rata-rata penggunaan CPU sesuai dengan yang ditentukan oleh pengguna.

Bagaimana cara kerja HorizontalPodAutoscaler?

Diagram HorizontalPodAutoscaler

HorizontalPodAutoscaler diimplementasikan sebagai sebuah loop kontrol, yang secara berkala dikontrol oleh flag --horizontal-pod-autoscaler-sync-period pada controller manager (dengan nilai bawaan 15 detik).

Dalam setiap periode, controller manager melakukan kueri penggunaan sumber daya dan membandingkan dengan metrik yang dispesifikasikan pada HorizontalPodAutoscaler. Controller manager mendapat metrik dari sumber daya metrik API (untuk metrik per Pod) atau dari API metrik khusus (untuk semua metrik lainnya).

  • Untuk metrik per Pod (seperti CPU), controller mengambil metrik dari sumber daya metrik API untuk setiap Pod yang ditargetkan oleh HorizontalPodAutoscaler. Kemudian, jika nilai target penggunaan ditentukan, maka controller akan menghitung nilai penggunaan sebagai persentasi dari pengguaan sumber daya dari Container pada masing-masing Pod. Jika target nilai mentah (raw value) ditentukan, maka nilai metrik mentah (raw metric) akan digunakan secara langsung. Controller kemudian mengambil nilai rata-rata penggunaan atau nilai mentah (tergantung dengan tipe target yang ditentukan) dari semua Pod yang ditargetkan dan menghasilkan perbandingan yang digunakan untuk menentukan jumlah replika yang akan diperbanyak.

    Perlu dicatat bahwa jika beberapa Container pada Pod tidak memiliki nilai resource request, penggunaan CPU pada Pod tersebut tidak akan ditentukan dan autoscaler tidak akan melakukan tindakan apapun untuk metrik tersebut. Perhatikan pada bagian detail algoritma di bawah ini untuk informasi lebih lanjut mengenai cara kerja algoritma autoscale.

  • Untuk metrik khusus per Pod, controller bekerja sama seperti sumber daya metrik per Pod, kecuali Pod bekerja dengan nilai mentah, bukan dengan nilai utilisasi (utilization values).

  • Untuk objek metrik dan metrik eksternal, sebuah metrik diambil, dimana metrik tersebut menggambarkan objek tersebut. Metrik ini dibandingkan dengan nilai target untuk menghasilkan perbandingan seperti di atas. Pada API autoscaling/v2beta2, nilai perbandingan dapat secara opsional dibagi dengan jumlah Pod sebelum perbandingan dibuat.

Pada normalnya, HorizontalPodAutoscaler mengambil metrik dari serangkaian API yang sudah diagregat (custom.metric.k8s.io, dan external.metrics.k8s.io). API metrics.k8s.io biasanya disediakan oleh metric-server, dimana metric-server dijalankan secara terpisah. Perhatikan metrics-server sebagai petunjuk. HorizontalPodAutoscaler juga mengambil metrik dari Heapster secara langsung.

Perhatikan Dukungan untuk API metrik untuk lebih detail.

Autoscaler mengkases controller yang dapat diperbanyak (seperti ReplicationController, Deployment, dan ReplicaSet) dengan menggunakan scale sub-resource. Untuk lebih detail mengenai scale sub-resource dapat ditemukan di sini.

Detail Algoritma

Dari sudut pandang paling sederhana, controller HorizontalPodAutoscaler mengoperasikan perbandingan metrik yang diinginkan dengan kedaan metrik sekarang.

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )] 

Sebagai contoh, jika nilai metrik sekarang adalah 200m dan nilai metrik yang diinginkan adalah 100m, jumlah replika akan ditambah dua kali lipat, karena 200.0 / 100.0 == 2.0. Jika nilai metrik sekarang adalah 50m, maka jumlah replika akan dikurangi setengah, karena 50.0 / 100.0 == 0.5. Kita tetap memperbanyak replika (scale) jika nilai perbandingan mendekati 1.0 (dalam toleransi yang dapat dikonfigurasi secata global, dari flag --horizontal-pod-autoscaler-tolerance dengan nilai bawaan 0.1.

Ketika targetAverageValue (nilai target rata-rata) atau targetAverageUtilization (target penggunaan rata-rata) ditentukan, currentMetricValue (nilai metrik sekaraang) dihitung dengan mengambil rata-rata dari metrik dari semua Pod yang ditargetkan oleh HorizontalPodAutoscaler. Sebelum mengecek toleransi dan menentukan nilai akhir, kita mengambil kesiapan Pod dan metrik yang hilang sebagai pertimbangan.

Semua Pod yang memiliki waktu penghapusan (Pod dalam proses penutupan) dan semua Pod yang mengalami kegagalan akan dibuang.

Jika ada metrik yang hilang dari Pod, maka Pod akan dievaluasi nanti. Pod dengan nilai metrik yang hilang akan digunakan untuk menyesuaikan jumlah akhir Pod yang akan diperbanyak atau dikurangi.

Ketika scaling dilakukan karena CPU, jika terdapat Pod yang akan siap (dengan kata lain Pod tersebut sedang dalam tahap inisialisasi) atau metrik terakhir dari Pod adalah metrik sebelum Pod dalam keadaan siap, maka Pod tersebut juga akan dievaluasi nantinya.

Akibat keterbatasan teknis, controller HorizontalPodAutoscaler tidak dapat menentukan dengan tepat kapan pertama kali Pod akan dalam keadaan siap ketika menentukan apakah metrik CPU tertentu perlu dibuang. Sebaliknya, HorizontalPodAutoscaler mempertimbangkan sebuah Pod "tidak dalam keadaan siap" jika Pod tersebut dalam keadaan tidak siap dan dalam transisi ke status tidak siap dalam waktu singkat, rentang waktu dapat dikonfigurasi, sejak Pod tersebut dijalankan. Rentang waktu tersebut dapat dikonfigurasi dengan flag --horizontal-pod-autoscaler-initial-readiness-delay dan waktu bawaannya adalah 30 detik. Ketika suatu Pod sudah dalam keadaan siap, Pod tersebut mempertimbangkan untuk siap menjadi yang pertama jika itu terjadi dalam waktu yang lebih lama, rentang waktu dapat dikonfigurasi, sejak Pod tersebut dijalankan. Rentang waktu tersebut dapat dikonfigurasi dengan flag --horizontal-pod-autoscaler-cpu-initialization-period dan nilai bawaannya adalah 5 menit.

Skala perbandingan dasar currentMetricValue / desiredMetricValue dihitung menggunakan Pod yang tersisa yang belum disisihkan atau dibuang dari kondisi di atas.

Jika terdapat metrik yang hilang, kita menghitung ulang rata-rata dengan lebih konservatif, dengan asumsi Pod mengkonsumsi 100% dari nilai yang diharapkan jika jumlahnya dikurangi (scale down) dan 0% jika jumlahnya diperbanyak (scale up). Ini akan mengurangi besarnya kemungkinan untuk scale.

Selanjutnya, jika terdapat Pod dalam keadaan tidak siap, dan kita akan memperbanyak replikas (scale up) tanpa memperhitungkan metrik yang hilang atau Pod yang tidak dalam keadaan siap, kita secara konservatif mengasumsikan Pod yang tidak dalam keadaan siap mengkonsumsi 0% dari metrik yang diharapkan, akhirnya meredam jumlah replika yang diperbanyak (scale up).

Seteleh memperhitungkan Pod yang tidak dalam keadaan siap dan metrik yang hilang, kita menghitung ulang menggunakan perbandingan. Jika perbandingan yang baru membalikkan arah scale-nya atau masih di dalam toleransi, kita akan melakukan scale dengan tepat. Jika tidak, kita menggunakan perbandingan yang baru untuk memperbanyak atau mengurangi jumlah replika.

Perlu dicatat bahwa nilai asli untuk rata-rata penggunaan dilaporkan kembali melalui status HorizontalPodAutoscaler, tanpa memperhitungkan Pod yang tidak dalam keadaan siap atau metrik yang hilang, bahkan ketika perbandingan yang baru digunakan.

Jika beberapa metrik ditentukan pada sebuah HorizontalPodAutoscaler, perhitungan dilakukan untuk setiap metrik dan nilai replika terbesar yang diharapkan akan dipilih. Jika terdapat metrik yang tidak dapat diubah menjadi jumlah replika yang diharapkan (contohnya terdapat kesalahan ketika mengambil metrik dari API metrik) dan pengurangan replika disarankan dari metrik yang dapat diambil, maka scaling akan diabaikan. Ini berarti HorizontalPodAutoscaler masih mampu untuk memperbanyak replika jika satu atau lebih metrik memberikan sebuah desiredReplicas lebih besar dari nilai yang sekarang.

Pada akhirnya, sebelum HorizontalPodAutoscaler memperbanyak target, rekomendasi scaling akan dicatat. Controller mempertimbangkan semua rekomendasi dalam rentang waktu yang dapat dikonfigurasi untuk memilih rekomendasi tertinggi. Nilai ini dapat dikonfigurasi menggunakan flag --horizontal-pod-autoscaler-downscale-stabilization, dengan nilai bawaan 5 menit. Ini berarti pengurangan replika akan terjadi secara bertahap, untuk mengurangi dampak dari perubahan nilai metrik yang cepat.

Objek API

HorizontalPodAutoscaler adalah sebuah API dalam grup autoscaling pada Kubernetes. Versi stabil, yang hanya mendukung untuk autoscale CPU, dapat ditemukan pada versi API autoscaling/v1.

Versi beta, yang mendukung untuk scaling berdasarkan memori dan metrik khusus, dapat ditemukan pada autoscaling/v2beta2. Field yang baru diperkenalkan pada autoscaling/v2beta2 adalah preserved sebagai anotasi ketika menggunakan autoscaling/v1.

Ketika kamu membuat sebuah HorizontalPodAutoscaler, pastikan nama yang ditentukan adalah valid nama subdomain DNS. Untuk lebih detail tentang objek API ini dapat ditemukan di Objek HorizontalPodAutoscaler.

Dukungan untuk HorizontalPodAutoscaler pada kubectl

Seperti sumber daya API lainnya, HorizontalPodAutoscaler didukung secara bawaan oleh kubectl. Kita dapat membuat autoscaler yang baru dengan menggunakan perintah kubectl create. Kita dapat melihat daftar autoscaler dengan perintah kubectl get hpa dan melihat deskripsi detailnya dengan perintah kubectl describe hpa. Akhirnya, kita dapat menghapus autoscaler meggunakan perintah kubectl delete hpa.

Sebagai tambahan, terdapat sebuah perintah khusus kubectl autoscaler untuk mempermudah pembuatan HorizontalPodAutoscaler. Sebagai contoh, mengeksekusi kubectl autoscaler rs foo --min=2 --max=5 --cpu-percent=80 akan membuat sebuah autoscaler untuk ReplicaSet foo, dengan target pengguaan CPU 80% dan jumlah replika antara 2 sampai dengan 5. Dokumentasi lebih detail tentang kubectl autoscaler dapat ditemukan di sini.

Autoscaling ketika Rolling Update

Saat ini, dimungkinkan untuk melakukan rolling update menggunakan objek Deployment, yang akan mengatur ReplicaSet untuk kamu. HorizontalPodAutoscaler hanya mendukung pendekatan terakhir: HorizontalPodAutoscaler terikat dengan objek Deployment, yang mengatur seberapa besar dari objek Deployment tersebut, dan Deployment bertugas untuk mengatur besar dari ReplicaSet.

HorizontalPodAutoscaler tidak bekerja dengan rolling update yang menggunakan manipulasi pada ReplicationContoller secara langsung, dengan kata lain kamu tidak bisa mengikat HorizontalPodAutoscaler dengan ReplicationController dan melakukan rolling update. Alasan HorizontalPodAutoscaler tidak bekerja ketika rolling update membuat ReplicationController yang baru adalah HorizontalPodAutoscaler tidak akan terikat dengan ReplicationController yang baru tersebut.

Dukungan untuk Cooldown / Penundaan

Ketika mengolah scaleing dari sebuah grup replika menggunakan HorizonalPodAutoscaler, jumlah replika dimungkinkan tetap berubah secara sering disebabkan oleh perubahan dinamis dari metrik yang dievaluasi. Hal ini sering disebut dengan thrashing.

Mulai dari versi 1.6, operator klaster dapat mengatasi masalah ini dengan mengatur konfigurasi HorizontalPodAutoscaler global sebagai flag kube-controller-manager.

Mulai dari versi 1.12, sebuah algoritma pembaruan baru menghilangkan kebutuhan terhadap penundaan memperbanyak replika (upscale).

  • --horizontal-pod-autoscaler-downscale-stabilization: Nilai untuk opsi ini adalah sebuah durasi yang menentukan berapa lama autoscaler menunggu sebelum operasi pengurangan replika (downscale) yang lain dilakukan seteleh operasi sekarang selesai. Nilai bawaannya adalah 5 menit (5m0s).

Dukungan untuk Beberapa Metrik

Kubernetes versi 1.6 menambah dukungan untuk scaling berdasarkan beberapa metrik. Kamu dapat menggunakan API versi autoscaling/v2beta2 untuk menentukan beberapa metrik yang akan digunakan HorizontalPodAutoscaler untuk menambah atau mengurangi jumlah replika. Kemudian, controller HorizontalPodAutoscaler akan mengevaluasi setiap metrik dan menyarankan jenis scaling yang baru berdasarkan metrik tersebut. Jumlah replika terbanyak akan digunakan untuk scale yang baru.

Dukungan untuk Metrik Khusus

Kubernetes versi 1.6 menambah dukungan untuk menggunakan metrik khusus pada HorizontalPodAutoscaler. Kamu dapat menambahkan metrik khusus untuk HorizontalPodAutoscaler pada API versi autoscaling/v2beta2. Kubernetes kemudian memanggil API metrik khusus untuk mengambil nilai dari metrik khusus.

Lihat Dukungan untuk API metrik untuk kubutuhannya.

Dukungan untuk API metrik

Secara standar, controller HorizontalPodAutoscaler mengambil metrik dari beberapa API. Untuk dapat mengakses API ini, administrator klaster harus memastikan bahwa:

  • API Later Pengumpulan diaktifkan.

  • API berikut ini terdaftar:

    • Untuk metrik sumber daya, ini adalah API metrics.k8s.io, pada umumnya disediakan oleh metrics-server. API tersebut dapat diaktifkan sebagai addon atau tambahan pada klaster.

    • Untuk metrik khusus, ini adalah API custom.metrics.k8s.io. API ini disediakan oleh API adaptor server yang disediakan oleh vendor yang memberi solusi untuk metrik. Cek dengan pipeline metrikmu atau daftar solusi yang sudah diketahui. Jika kamu ingin membuat sendiri, perhatikan boilerplate berikut untuk memulai.

    • Untuk metrik eksternal, ini adalah API external.metrics.k8s.io. API ini mungkin disediakan oleh penyedia metrik khusus diatas.

  • Nilai dari --horizontal-pod-autoscaler-use-rest-clients adalah true atau tidak ada. Ubah nilai tersebut menjadi false untuk mengubah ke autoscaling berdasarkan Heapster, dimana ini sudah tidak didukung lagi.

Untuk informasi lebih lanjut mengenai metrik-metrik ini dan bagaimana perbedaan setiap metrik, perhatikan proposal desain untuk HPA V2, custom.metrics.k8s.io dan external.metrics.k8s.io.

Untuk contoh bagaimana menggunakan metrik-metrik ini, perhatikan panduan penggunaan metrik khusus dan panduan penggunaan metrik eksternal.

Dukungan untuk Perilaku Scaling yang dapat Dikonfigurasi

Mulai dari versi v1.18, API v2beta2 mengizinkan perilaku scaling dapat dikonfigurasi melalui field behavior pada HorizontalPodAutoscaler. Perilaku scaling up dan scaling down ditentukan terpisah pada field slaceUp dan field scaleDown, dibawah dari field behavior. Sebuah stabilisator dapat ditentukan untuk kedua arah scale untuk mencegah perubahan replika yang terlalu berbeda pada target scaling. Menentukan scaling policies akan mengontrol perubahan replika ketika scaling.

Scaling Policies

Satu atau lebih scaling policies dapat ditentukan pada field behavior. Ketika beberapa policies ditentukan, policy yang mengizinkan scale terbesar akan dipilih secara default. Contoh berikut menunjukkan perilaku ketika mengurangi replika:

behavior:  scaleDown:  policies:  - type: Pods  value: 4  periodSeconds: 60  - type: Percent  value: 10  periodSeconds: 60 

Ketika jumlah Pod lebih besar dari 40, policy kedua akan digunakan untuk scaling down. Misalnya, jika terdapat 80 replika dan target sudah di scale down ke 10 replika, 8 replika akan dikurangi pada tahapan pertama. Pada iterasi berikutnya, ketika jumlah replika adalah 72, 10% dari Pod adalah 7.2 tetapi akan dibulatkan menjadi 8. Dalam setiap iterasi pada controller autoscaler jumlah Pod yang akan diubah akan dihitung ulang berdarkan jumlah replika sekarang. Ketika jumlah replika dibawah 40, policy pertama (Pods) akan digunakan dan 4 replika akan dikurangi dalam satu waktu.

periodSeconds menunjukkan berapa lama waktu pada iterasi terkhir untuk menunjukkan policy mana yang akan digunakan. Policy pertama mengizinkan maksimal 4 replika di scale down dalam satu menit. Policy kedua mengixinkan maksimal 10% dari total replika sekarang di scale down dalam satu menit.

Pemilihan policy dapat diubah dengan menentukannya pada field selectPolicy untuk sebuah arah scale (baik scale up ataupun scale down). Dengan menentukan nilai Min, HorizontalPodAutoscaler akan memilih policy yang mengizinkan pergantian replika paling sedikit. Dengan menuntukan nilai Disable, akan menghentikan scaling pada arah scale tersebut.

Jendela Stabilisasi

Jendela stabilisasi digunakan untuk membatasi perubahan replika yang terlalu drastis ketika metrik yang digunakan untuk scaling tetap berubah-ubah. Jendela stabilisasi digunakan oleh algoritma autoscaling untuk memperhitungkan jumlah replika yang diharapkan dari scaling sebelumnya untuk mencengah *scaling. Berikut adalah contoh penggunaan jendela stabilisasi pada scaleDown.

scaleDown:  stabilizationWindowSeconds: 300 

Ketika metrik menandakan bahwa replika pada target akan dikurangi, algoritma akan memperhatikan jumlah replika yang diharapkan sebelumnya dan menggunakan nilai terbesar dari interval yang ditentukan. Pada contoh diatas, semua jumlah replika yang diharapkan pada 5 menit yang lalu akan dipertimbangkan.

Perilaku Standar

Untuk menggunakan scaling khusus, tidak semua field perlu ditentukan. Hanta nilai yang perlu diubah saja yang ditentukan. Nilai khusus ini akan digabungkan dengan nilai standar. Berikut adalah nilai standar perilaku pada algoritma yang digunakan HorizontalPodAutoscaler.

behavior:  scaleDown:  stabilizationWindowSeconds: 300  policies:  - type: Percent  value: 100  periodSeconds: 15  scaleUp:  stabilizationWindowSeconds: 0  policies:  - type: Percent  value: 100  periodSeconds: 15  - type: Pods  value: 4  periodSeconds: 15  selectPolicy: Max 

Untuk scaleDown, nilai dari jendela stabilisasi adalah 300 detik (atau nilai dari flag --horizontal-pod-autoscaler-downscale-stabilization jika ditentukan). Hanya terdapat satu policy, yaitu mengizinkan menghapus 100% dari replika yang berjalan, artinya target replikasi di scale ke jumlah replika minimum. Untuk scaleUp, tidak terdapat jendela stabilisasi. Jika metrik menunjukkan bahwa replika pada target perlu diperbanyak, maka replika akan diperbanyak di secara langsung. Untuk scaleUp terdapat dua policy, yaitu empat Pod atau 100% dari replika yang berjalan akan ditambahkan setiap 15 detik sampai HorizontalPodAutoscaler dalam keadaan stabil.

Contoh: Mengubah Jendela Stabiliasi pada field scaleDown

Untuk membuat jendela stabilisai untuk pengurangan replika selama satu menit, perilaku berikut ditambahkan pada HorizontalPodAutoscaler.

behavior:  scaleDown:  stabilizationWindowSeconds: 60 

Contoh: Membatasi nilai scale down

Untuk membatasi total berapa Pod yang akan dihapus, 10% setiap menut, perilaku berikut ditambahkan pada HorizontalPodAutoscaler.

behavior:  scaleDown:  policies:  - type: Percent  value: 10  periodSeconds: 60 

Untuk mengizinkan penghapusan 5 Pod terakhir, policy lain dapat ditambahkan.

behavior:  scaleDown:  policies:  - type: Percent  value: 10  periodSeconds: 60  - type: Pods  value: 5  periodSeconds: 60  selectPolicy: Max 

Contoh: menonakfitkan scale down

Nilai Disable pada selectPolicy akan menonaktifkan scaling pada arah yang ditentukan. Untuk mencegah pengurangan replika dapat menggunakan policy berikut.

behavior:  scaleDown:  selectPolicy: Disabled 

Selanjutnya

7.4 - Panduan HorizontalPodAutoscaler

HorizontalPodAutoscaler secara otomatis akan memperbanyak jumlah Pod di dalam ReplicationController, Deployment, ReplicaSet ataupun StatefulSet berdasarkan hasil observasi penggunaan CPU (atau, dengan metrik khusus, pada beberapa aplikasi yang menyediakan metrik).

Laman ini memandu kamu dengan contoh pengaktifan HorizontalPodAutoscaler untuk server php-apache. Untuk informasi lebih lanjut tentang perilaku HorizontalPodAutoscaler, lihat Petunjuk pengguna HorizontalPodAutoscaler.

Contoh dibawah ini membutuhkan klaster Kubernetes dan kubectl di versi 1.2 atau yang lebih baru yang sedang berjalan. Server metrik sebagai pemantauan perlu diluncurkan di dalam sebuah klaster untuk menyediakan metrik melalui metrik API sumber daya, karena HorizontalPodAutoscaler menggunakan API ini untuk mengumpulkan metrik. Petunjuk untuk menerapkan server metrik ada di repositori GitHub dari server metrik, jika kamu mengikuti petunjuk memulai panduan GCE, metrik-pemantauan server akan diaktifkan secara default

Untuk menentukan beberapa metrik sumber daya untuk HorizontalPodAutoscaler, kamu harus memiliki klaster Kubernetes dan kubectl di versi 1.6 atau yang lebih baru. Selanjutnya, untuk menggunakan metrik khusus, klaster kamu harus dapat berkomunikasi dengan server API yang menyediakan API metrik khusus. Terakhir, untuk menggunakan metrik yang tidak terkait dengan objek Kubernetes apa pun, kamu harus memiliki klaster Kubernetes pada versi 1.10 atau yang lebih baru, dan kamu harus dapat berkomunikasi dengan server API yang menyediakan API metrik eksternal. Lihat Panduan pengguna HorizontalPodAutoscaler untuk detail lebih lanjut.

Menjalankan & mengekspos server php-apache

Untuk mendemonstrasikan HorizontalPodAutoscaler kita akan menggunakan image Docker khusus berdasarkan image php-apache. Dockerfile memiliki konten berikut:

FROM php:5-apache ADD index.php /var/www/html/index.php RUN chmod a+rx index.php 

Bagian ini mendefinisikan laman index.php yang melakukan beberapa komputasi intensif CPU:

<?php $x = 0.0001; for ($i = 0; $i <= 1000000; $i++) { $x += sqrt($x); } echo "OK!"; ?> 

Pertama, kita akan memulai Deployment yang menjalankan image dan mengeksposnya sebagai Service menggunakan konfigurasi berikut:

apiVersion: apps/v1 kind: Deployment metadata:  name: php-apache spec:  selector:  matchLabels:  run: php-apache  template:  metadata:  labels:  run: php-apache  spec:  containers:  - name: php-apache  image: registry.k8s.io/hpa-example  ports:  - containerPort: 80  resources:  limits:  cpu: 500m  requests:  cpu: 200m --- apiVersion: v1 kind: Service metadata:  name: php-apache  labels:  run: php-apache spec:  ports:  - port: 80  selector:  run: php-apache 

Jalankan perintah berikut:

kubectl apply -f https://k8s.io/examples/application/php-apache.yaml 
deployment.apps/php-apache created service/php-apache created 

Membuat HorizontalPodAutoscaler

Sekarang server sudah berjalan, selanjutnya kita akan membuat autoscaler menggunakan kubectl autoscale. Perintah berikut akan membuat HorizontalPodAutoscaler yang mengelola antara 1 dan 10 replika Pod yang dikontrol oleh Deployment php-apache yang kita buat pada langkah pertama instruksi ini. Secara kasar, HPA akan menambah dan mengurangi jumlah replika (melalui Deployment) untuk mempertahankan pemakaian CPU rata-rata di semua Pod sebesar 50% (karena setiap Pod meminta 200 mili-core menurut kubectl run), ini berarti penggunaan CPU rata-rata adalah 100 mili-core). Lihat ini untuk detail lebih lanjut tentang algoritmanya.

kubectl autoscale deployment php-apache --cpu=50% --min=1 --max=10 
horizontalpodautoscaler.autoscaling/php-apache autoscaled 

Kita dapat memeriksa status autoscaler saat ini dengan menjalankan:

kubectl get hpa 
NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache/scale 0% / 50% 1 10 1 18s 

Harap dicatat bahwa konsumsi CPU saat ini adalah 0% karena kita tidak mengirimkan permintaan apa pun ke server (kolom TARGET menunjukkan nilai rata-rata di semua Pod yang dikontrol oleh Deployment yang sesuai).

Menambahkan beban

Sekarang, kita akan melihat bagaimana autoscaler bereaksi terhadap peningkatan beban. Kita akan memulai sebuah Container, dan mengirimkan perulangan kueri tak terbatas ke Service php-apache (jalankan di terminal yang berbeda):

kubectl run -it --rm load-generator --image=busybox /bin/sh  Hit enter for command prompt  while true; do wget -q -O- http://php-apache; done 

Dalam satu menit atau lebih, kita akan melihat beban CPU yang lebih tinggi dengan menjalankan:

kubectl get hpa 
NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache/scale 305% / 50% 1 10 1 3m 

Di sini, konsumsi CPU meningkat hingga 305% dari permintaan. Hasilnya, Deployment mengubah ukurannya menjadi 7 replika:

kubectl get deployment php-apache 
NAME READY UP-TO-DATE AVAILABLE AGE php-apache 7/7 7 7 19m 

Menghentikan beban

Kita akan menyudahi contoh dengan menghentikan beban pengguna.

Di terminal tempat kita membuat Container dengan image busybox, hentikan pembangkitan beban dengan mengetik <Ctrl> + C.

Kemudian kita akan memverifikasi status hasil (setelah satu menit atau lebih):

kubectl get hpa 
NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache/scale 0% / 50% 1 10 1 11m 
kubectl get deployment php-apache 
NAME READY UP-TO-DATE AVAILABLE AGE php-apache 1/1 1 1 27m 

Di sini penggunaan CPU turun menjadi 0, sehingga HPA secara otomatis melakukan penyekalaan jumlah replika kembali menjadi 1.

Penyekalaan otomatis pada metrik multipel dan metrik kustom

Kamu dapat memperkenalkan metrik tambahan untuk digunakan saat melakukan penyekalaan otomatis pada Deployment php-apache dengan menggunakan versi API autoscaling / v2beta2.

Pertama, dapatkan YAML HorizontalPodAutoscaler kamu dalam bentuk autoscaling / v2beta2:

kubectl get hpa.v2beta2.autoscaling -o yaml > /tmp/hpa-v2.yaml 

Buka berkas /tmp/hpa-v2.yaml di editor, dan kamu akan melihat YAML yang terlihat seperti ini:

apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata:  name: php-apache spec:  scaleTargetRef:  apiVersion: apps/v1  kind: Deployment  name: php-apache  minReplicas: 1  maxReplicas: 10  metrics:  - type: Resource  resource:  name: cpu  target:  type: Utilization  averageUtilization: 50 status:  observedGeneration: 1  lastScaleTime: <some-time>  currentReplicas: 1  desiredReplicas: 1  currentMetrics:  - type: Resource  resource:  name: cpu  current:  averageUtilization: 0  averageValue: 0 

Perhatikan bahwa kolom targetCPUUtilizationPercentage telah diganti dengan himpunan yang disebut metrics. Metrik penggunaan CPU adalah resource metric, merepresentasikan sebagai persentase sumber daya ditentukan pada Container Pod. Perhatikan bahwa kamu dapat menentukan metrik sumber daya selain CPU. Secara bawaan, satu-satunya metrik sumber daya lain yang didukung adalah memori. Sumber daya ini tidak mengubah nama dari klaster ke klaster, dan harus selalu tersedia, selama API metrics.k8s.io tersedia.

Kamu juga dapat menentukan metrik sumber daya dalam nilai secara langsung, bukan sebagai persentase dari nilai yang diminta, dengan menggunakan target.type dari AverageValue sebagai ganti Utilization, dan menyetel field target.averageValue yang sesuai, bukan target.averageUtilization.

Ada dua jenis metrik lainnya, keduanya dianggap sebagai metrik khusus: metrik Pod dan metrik objek. Metrik ini memungkinkan untuk memiliki nama yang spesifik untuk klaster, dan membutuhkan lebih banyak pengaturan pemantauan klaster lanjutan.

Jenis metrik alternatif yang pertama adalah metrik Pod. Metrik ini mendeskripsikan Pod, dan dirata-ratakan bersama di seluruh Pod dan dibandingkan dengan nilai target untuk menentukan jumlah replika. Mereka bekerja seperti metrik sumber daya, kecuali bahwa mereka hanya mendukung jenis target dari AverageValue.

Metrik Pod ditentukan menggunakan blok metrik seperti ini:

type: Pods pods:  metric:  name: packets-per-second  target:  type: AverageValue  averageValue: 1k 

Jenis metrik alternatif kedua adalah metrik objek. Metrik ini mendeskripsikan perbedaan objek di Namespace yang sama, bukan mendeskripsikan Pod. Metriknya belum tentu diambil dari objek; mereka hanya mendeskripsikannya. Metrik objek mendukung jenis target baik Value dan AverageValue. Dengan Value, target dibandingkan langsung dengan yang dikembalikan metrik dari API. Dengan AverageValue, nilai yang dikembalikan dari API metrik khusus dibagi dengan jumlah Pod sebelum dibandingkan dengan target. Contoh berikut adalah YAML representasi dari metrik requests-per-second.

type: Object object:  metric:  name: requests-per-second  describedObject:  apiVersion: networking.k8s.io/v1beta1  kind: Ingress  name: main-route  target:  type: Value  value: 2k 

Jika kamu memberikan beberapa blok metrik seperti itu, HorizontalPodAutoscaler akan mempertimbangkan setiap metrik secara bergantian. HorizontalPodAutoscaler akan menghitung jumlah replika yang diusulkan untuk setiap metrik, lalu memilih satu dengan jumlah replika tertinggi.

Misalnya, jika sistem pemantauan kamu mengumpulkan metrik tentang lalu lintas jaringan, kamu dapat memperbarui definisi di atas menggunakan kubectl edit agar terlihat seperti ini:

apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata:  name: php-apache spec:  scaleTargetRef:  apiVersion: apps/v1  kind: Deployment  name: php-apache  minReplicas: 1  maxReplicas: 10  metrics:  - type: Resource  resource:  name: cpu  target:  type: Utilization  averageUtilization: 50  - type: Pods  pods:  metric:  name: packets-per-second  target:  type: AverageValue  averageValue: 1k  - type: Object  object:  metric:  name: requests-per-second  describedObject:  apiVersion: networking.k8s.io/v1beta1  kind: Ingress  name: main-route  target:  type: Value  value: 10k status:  observedGeneration: 1  lastScaleTime: <some-time>  currentReplicas: 1  desiredReplicas: 1  currentMetrics:  - type: Resource  resource:  name: cpu  current:  averageUtilization: 0  averageValue: 0  - type: Object  object:  metric:  name: requests-per-second  describedObject:  apiVersion: networking.k8s.io/v1beta1  kind: Ingress  name: main-route  current:  value: 10k 

Kemudian, HorizontalPodAutoscaler kamu akan mencoba memastikan bahwa setiap Pod mengonsumsi kira-kira 50% dari CPU yang diminta, melayani 1000 paket per detik, dan semua Pod berada di belakang Ingress rute utama melayani total 10.000 permintaan per detik.

Penyekalaan otomatis pada metrik yang lebih spesifik

Banyak pipeline metrik memungkinkan kamu mendeskripsikan metrik baik berdasarkan nama atau kumpulan tambahan deskriptor yang disebut labels. Untuk semua jenis metrik non-sumber daya (Pod, objek, dan eksternal, dijelaskan seperti dibawah), kamu dapat menentukan pemilih label tambahan yang diteruskan ke pipa metrik kamu. Misalnya, jika kamu mengumpulkan metrik http_requests dengan label verb , kamu dapat menentukan blok metrik berikut untuk diskalakan hanya pada permintaan GET:

type: Object object:  metric:  name: http_requests  selector: {matchLabels: {verb: GET}} 

Selector ini menggunakan sintaksis yang sama dengan selector lengkap label Kubernetes. Pipa pemantauan menentukan cara mengecilkan beberapa seri menjadi satu nilai, jika nama dan pemilih cocok dengan beberapa seri. Selektor bersifat aditif, dan tidak dapat memilih metrik yang mendeskripsikan objek yang bukan objek target (target pod dalam kasus tipe Pod, dan objek yang dijelaskan dalam kasus tipe Objek).

Penyekalaan otomatis pada metrik yang tidak terkait dengan objek Kubernetes

Aplikasi yang berjalan di Kubernetes mungkin perlu melakukan penyekalaan otomatis berdasarkan metrik yang tidak memiliki hubungan yang jelas dengan objek apa pun di klaster Kubernetes, seperti metrik yang mendeskripsikan layanan yang dihosting tanpa korelasi langsung dengan namespace Kubernetes. Di Kubernetes 1.10 dan yang lebih baru, kamu dapat menangani kasus penggunaan ini dengan metrik eksternal.

Menggunakan metrik eksternal membutuhkan pengetahuan tentang sistem pemantauanmu; penyiapannya mirip dengan yang diperlukan saat menggunakan metrik khusus. Metrik eksternal memungkinkan kamu menskalakan klaster kamu secara otomatis berdasarkan metrik apa pun yang tersedia di sistem pemantauanmu. Cukup berikan blok metric dengan name dan selector (pemilih), seperti di atas, dan gunakan jenis metrik External, bukan Object. Jika beberapa series cocok dengan metricSelector, jumlah dari nilai mereka akan digunakan oleh HorizontalPodAutoscaler. Metrik eksternal mendukung jenis target Value dan AverageValue, yang berfungsi persis sama seperti saat kamu menggunakan tipe Object.

Misalnya, jika aplikasi kamu memproses tugas dari layanan antrian yang dihosting, kamu dapat menambahkan bagian berikut ke manifes HorizontalPodAutoscaler untuk menentukan bahwa kamu memerlukan satu pekerja per 30 tugas yang belum diselesaikan.

- type: External  external:  metric:  name: queue_messages_ready  selector: "queue=worker_tasks"  target:  type: AverageValue  averageValue: 30 

Jika memungkinkan, lebih baik menggunakan target metrik khusus daripada metrik eksternal, karena lebih mudah bagi administrator klaster untuk mengamankan API metrik khusus. API metrik eksternal berpotensi memungkinkan akses ke metrik apa pun, jadi administrator klaster harus berhati-hati saat mengeksposnya.

Lampiran: Kondisi Status Horizontal Pod Autoscaler

Saat menggunakan bentuk autoscaling/v2beta2 dari HorizontalPodAutoscaler, kamu akan dapat melihat status condition yang ditetapkan oleh Kubernetes pada HorizontalPodAutoscaler. Status condition ini menunjukkan apakah HorizontalPodAutoscaler dapat melakukan penyekalaan atau tidak, dan apakah saat ini dibatasi atau tidak.

Kondisi muncul pada field status.conditions. Untuk melihat kondisi yang memengaruhi HorizontalPodAutoscaler, kita bisa menggunakan kubectl description hpa:

kubectl describe hpa cm-test 
Name: cm-test Namespace: prom Labels: <none> Annotations: <none> CreationTimestamp: Fri, 16 Jun 2017 18:09:22 +0000 Reference: ReplicationController/cm-test Metrics: ( current / target )  "http_requests" on pods: 66m / 500m Min replicas: 1 Max replicas: 4 ReplicationController pods: 1 current / 1 desired Conditions:  Type Status Reason Message  ---- ------ ------ -------  AbleToScale True ReadyForNewScale the last scale time was sufficiently old as to warrant a new scale  ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from pods metric http_requests  ScalingLimited False DesiredWithinRange the desired replica count is within the acceptable range Events: 

Untuk HorizontalPodAutoscaler ini, kita dapat melihat beberapa kondisi yang menandakan dalam keadaan sehat. Yang pertama, AbleToScale, menunjukkan apakah HPA dapat mengambil dan memperbarui skala atau tidak, serta apakah kondisi terkait backoff akan mencegah penyekalaan atau tidak. Yang kedua, ScalingActive, menunjukkan apakah HPA diaktifkan atau tidak (yaitu jumlah replika target bukan nol) dan mampu menghitung skala yang diinginkan. Jika False, biasanya menunjukkan masalah dengan pengambilan metrik. Terakhir, kondisi terakhir, ScalingLimited, menunjukkan bahwa skala yang diinginkan telah dibatasi oleh maksimum atau minimum HorizontalPodAutoscaler. Ini adalah indikasi bahwa kamu mungkin ingin menaikkan atau menurunkan batasan jumlah replika minimum atau maksimum pada HorizontalPodAutoscaler kamu.

Lampiran: Kuantitas

Semua metrik di HorizontalPodAutoscaler dan metrik API ditentukan menggunakan notasi bilangan bulat khusus yang dikenal di Kubernetes sebagai kuantitas. Misalnya, kuantitas 10500m akan ditulis sebagai 10.5 dalam notasi desimal. Metrik API akan menampilkan bilangan bulat tanpa sufiks jika memungkinkan, dan secara umum akan mengembalikan kuantitas dalam satuan mili. Ini berarti kamu mungkin melihat nilai metrik berfluktuasi antara 1 dan 1500m, atau 1 dan 1,5 ketika ditulis dalam notasi desimal.

Lampiran: Skenario lain yang memungkinkan

Membuat autoscaler secara deklaratif

Daripada menggunakan perintah kubectl autoscale untuk membuat HorizontalPodAutoscaler secara imperatif, kita dapat menggunakan berkas berikut untuk membuatnya secara deklaratif:

apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata:  name: php-apache spec:  scaleTargetRef:  apiVersion: apps/v1  kind: Deployment  name: php-apache  minReplicas: 1  maxReplicas: 10  targetCPUUtilizationPercentage: 50 

Kita akan membuat autoscaler dengan menjalankan perintah berikut:

kubectl create -f https://k8s.io/examples/application/hpa/php-apache.yaml 
horizontalpodautoscaler.autoscaling/php-apache created 

8 - Mengakes Aplikasi-aplikasi di sebuah Klaster

8.1 - Antarmuka Pengguna Berbasis Web (Dashboard)

Dashboard adalah antarmuka pengguna Kubernetes. Kamu dapat menggunakan Dashboard untuk men-deploy aplikasi yang sudah dikontainerisasi ke klaster Kubernetes, memecahkan masalah pada aplikasi kamu, dan mengatur sumber daya klaster. Kamu dapat menggunakan Dashboard untuk melihat ringkasan dari aplikasi yang sedang berjalan di klaster kamu, dan juga membuat atau mengedit objek individu sumber daya Kubernetes (seperti Deployment, Job, DaemonSet, dll.). Sebagai contoh, kamu dapat mengembangkan sebuah Deployment, menginisiasi sebuah pembaruan bertahap (rolling update), memulai kembali sebuah Pod atau men-deploy aplikasi baru menggunakan sebuah deploy wizard.

Dashboard juga menyediakan informasi tentang status dari sumber daya Kubernetes di klaster kamu dan kesalahan apapun yang mungkin telah terjadi..

Antarmuka Pengguna Dashboard Kubernetes

Men-deploy Antarmuka Pengguna Dashboard

Antarmuka Dashboard tidak ter-deploy secara bawaan. Untuk men-deploy-nya, kamu dapat menjalankan perintah berikut:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml 

Mengakses Antarmuka Dashboard

Untuk melindungi data klaster kamu, pen-deploy-an Dashboard menggunakan sebuah konfigurasi RBAC yang minimal secara bawaan. Saat ini, Dashboard hanya mendukung otentikasi dengan Bearer Token. Untuk membuat token untuk demo, kamu dapat mengikuti petunjuk kita untuk membuat sebuah contoh pengguna.

Proksi antarmuka baris perintah (CLI)

Kamu dapat mengakses Dashboard menggunakan perkakas CLI kubectl dengan menjalankan perintah berikut:

kubectl proxy 

Kubectl akan membuat Dashboard tersedia di http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/.

Antarmuka pengguna berbasis web tersebut hanya dapat di akses dari mesin dimana perintah tersebut dijalankan. Lihat kubectl proxy --help untuk lebih lanjut.

Tampilan selamat datang

Ketika kamu mengakses Dashboard di klaster yang kosong, kamu akan melihat laman selamat datang. Laman ini berisi tautan ke dokumen ini serta tombol untuk men-deploy aplikasi pertama kamu. Selain itu, kamu dapat melihat aplikasi-aplikasi sistem mana saja yang berjalan secara bawaan di Namespace kube-system dari klaster kamu, misalnya Dashboard itu sendiri.

Kubernetes Dashboard welcome page

Men-deploy aplikasi yang sudah dikontainerisasi

Dashboard memungkinkan kamu untuk membuat dan men-deploy aplikasi yang sudah dikontainerisasi sebagai Deployment dan Service opsional dengan sebuah wizard sederhana. Kamu secara manual dapat menentukan detail aplikasi, atau mengunggah sebuah berkas YAML atau JSON yang berisi konfigurasi aplikasi.

Tekan tombol CREATE di pojok kanan atas di laman apapun untuk memulai.

Menentukan detail aplikasi

Deploy wizard meminta kamu untuk menyediakan informasi sebagai berikut:

  • App name (wajib): Nama dari aplikasi kamu. Sebuah label dengan nama tersebut akan ditambahkan ke Deployment dan Service, jika ada, akan di-deploy.

    Nama aplikasi harus unik di dalam Namespace Kubernetes yang kamu pilih. Nama tersebut harus dimulai dengan huruf kecil, dan diakhiri dengan huruf kecil atau angka, dan hanya berisi huruf kecil, angka dan tanda hubung (-). Nama tersebut juga dibatasi hanya 24 karakter. Spasi di depan dan belakang nama tersebut diabaikan.

  • Container image (wajib): Tautan publik dari sebuah image kontainer Docker pada registry apapun, atau sebuah image privat (biasanya di-hosting di Google Container Registry atau Docker Hub). Spesifikasi image kontainer tersebut harus diakhiri dengan titik dua.

  • Number of pods (wajib): Berapa banyak Pod yang kamu inginkan untuk men-deploy aplikasimu. Nilainya haruslah sebuah bilangan bulat positif.

    Sebuah Deployment akan terbuat untuk mempertahankan jumlah Pod di klaster kamu.

  • Service (opsional): Untuk beberapa aplikasi (misalnya aplikasi frontend) kamu mungkin akan mengekspos sebuah Service ke alamat IP publik yang mungkin berada diluar klaster kamu(Service eksternal). Untuk Service eksternal, kamu mungkin perlu membuka lebih dari satu porta jaringan untuk mengeksposnya. Lihat lebih lanjut di sini.

    Service lainnya yang hanya dapat diakses dari dalam klaster disebut Service internal.

    Terlepas dari jenis Service, jika kamu memilih untuk membuat sebuah Service dan Container kamu berjalan di sebuah porta(arah masuk), kamu perlu menentukan dua porta. Service akan memetakan porta(arah masuk) ke porta target yang ada di sisi Container. Service akan mengarahkan ke Pod-Pod kamu yang sudah di-deploy. Protokol yang didukung adalah TCP dan UDP. Nama DNS internal untuk Service ini akan sesuai dengan nama aplikasi yang telah kamu tentukan diatas.

Jika membutuhkan, kamu dapat membuka bagian Advanced options di mana kamu dapat menyetel lebih banyak pengaturan:

  • Description: Tels yang kamu masukkan ke sini akan ditambahkan sebagai sebuah anotasi ke Deployment dan akan ditampilkan di detail aplikasi.

  • Labels: Label-label bawaan yang akan digunakan untuk aplikasi kamu adalah name dan version aplikasi. Kamu dapat menentukan label lain untuk diterapkan ke Deployment, Service (jika ada), dan Pod, seperti release, environment, tier, partition, dan track rilis.

    Contoh:

    release=1.0 tier=frontend environment=pod track=stable 
  • Namespace: Kubernetes mendukung beberapa klaster virtual yang berjalan di atas klaster fisik yang sama. Klaster virtual ini disebut Namespace. Mereka mengizinkan kamu untuk mempartisi sumber daya ke beberapa grup yang diberi nama secara logis.

    Dashboard menampilkan semua Namespace yang tersedia dalam sebuah daftar dropdown, dan mengizinkan kamu untuk membuat Namespace baru. Nama yang diizinkan untuk Namespace terdiri dari maksimal 63 karakter alfanumerik dan tanda hubung (-), dan tidak boleh ada huruf kapital. Nama dari Namespace tidak boleh terdiri dari angka saja. Jika nama Namespace disetel menjadi sebuah angka, misalnya 10, maka Pod tersebut akan ditaruh di Namespace default.

    Jika pembuatan Namespace berhasil, Namespace tersebut akan dipilih secara bawaan. Jika pembuatannya gagal, maka Namespace yang pertama akan terpilih.

  • Image Pull Secret: Jika kamu menggunakan image kontainer Docker yang privat, mungkin diperlukan kredensial pull secret.

    Dashboard menampilkan semua secret yang tersedia dengan daftar dropdown, dan mengizinkan kamu untuk membuat secret baru. Nama secret tersebut harus mengikuti aturan Nama DNS, misalnya new.image-pull.secret. Isi dari sebuah secret harus dienkode dalam bentuk base64 dan ditentukan dalam sebuah berkas .dockercfg. Nama kredensial dapat berisi maksimal 253 karakter.

    Jika pembuatan image pull secret berhasil, image pull secret tersebut akan terpilih secara bawaan. Jika gagal, maka tidak ada secret yang dipilih.

  • CPU requirement (cores) dan Memory requirement (MiB): Kamu dapat menentukan batasan sumber daya minimal untuk Container. Secara bawaan, Pod-Pod berjalan dengan CPU dan memori yang tak dibatasi.

  • Run command dan Run command arguments: Secara bawaan, Container-Container kamu akan menjalankan perintah entrypoint bawaan dari image Docker yang ditentukan. Kamu dapat menggunakan opsi Run command dan Run command arguments untuk mengganti bawaannya.

  • Run as priveleged: Pengaturan ini untuk menentukan sebuah proses yang berjalan dalam privileged container sepadan dengan proses yang berjalan sebagai root pada host-nya. Priveleged container dapat menggunakan kemampuan seperti memanipulasi stack jaringan dan mengakses perangkat-perangkat.

  • Environment variables: Kubernetes mengekspos Service melalui environment variable. Kamu dapat membuat environment variable atau meneruskan argumen ke perintah-perintah untuk menjalankan Container dengan nilai dari environment variable. Environment Variable dapat digunakan pada aplikasi-aplikasi untuk menemukan sebuah Service. Nilai environment variable dapat merujuk ke variabel lain menggunakan sintaksis $(VAR_NAME).

Menggungah berkas YAML atau JSON

Kubernetes mendukung pengaturan deklaratif. Dengan cara ini, semua pengaturan disimpan dalam bentuk berkas YAML atau JSON menggunakan skema sumber daya [API.

Sebagai alternatif untuk menentukan detail aplikasi di deploy wizard, kamu dapat menentukan sendiri detail aplikasi kamu dalam berkas YAML atau JSON, dan mengunggah berkas tersebut menggunakan Dashboard.

Menggunakan Dashboard

Bagian ini akan menjelaskan bagian-bagian yang ada pada Antarmuka Dashboard Kubernetes; apa saja yang mereka sediakan dan bagaimana cara menggunakanya.

Ketika ada objek Kubernetes yang sudah didefinisikan di dalam klaster, Dashboard akan menampilkanya di tampilan awalnya. Secara bawaan hanya objek-objek dalam Namespace default saja yang ditampilkan di sini dan kamu dapat menggantinya dengan selektor Namespace yang berada di menu navigasi.

Dashboard menampilkan jenis objek Kubernetes dan mengelompokanya dalam beberapa kategori menu.

Admin Overview

Untuk administrasi klaster dan Namespace, Dashboard menampilkan Node, Namespace dan PresistentVolume dan memiliki tampilan yang detail untuk objek-objek tersebut. Daftar Node berisi metrik penggunaan CPU dan memori yang dikumpulkan dari semua Node. Tampilan detail menampilkan metrik-metrik untuk sebuah Node, spesifikasinya, status, sumber daya yang dialokasikan, event-event, dan Pod-Pod yang sedang berjalan di Node tersebut.

Workloads

Menampilkan semua aplikasi yang sedang berjalan di Namespace yang dipilih. Tampilan ini menampilkan aplikasi berdasarkan jenis beban kerja (misalnya, Deployment, Replica Set, Stateful Set, dll.) dan setiap jenis beban kerja memiliki tampilanya sendiri. Daftar ini merangkum informasi yang dapat ditindaklanjuti, seperti berapa banyak Pod yang siap untuk setiap Replica Set atau penggunaan memori pada sebuah Pod.

Tampilan detail dari beban kerja menampilkan status dan informasi spesifik serta hubungan antara objek. Misalnya, Pod-Pod yang diatur oleh ReplicaSet atau, ReplicaSet-ReplicaSet baru, dan HorizontalPodAutoscaler untuk Deployment.

Services

Menampilkan sumber daya Kubernetes yang mengizinkan untuk mengekspos Service-Service ke jaringan luar dan menemukannya (service discovery) di dalam klaster. Untuk itu, tampilan dari Service dan Ingress menunjukan Pod-Pod yang ditarget oleh mereka, endpoint-endpoint internal untuk koneksi klaster, dan endpoint-endpoint eksternal untuk pengguna eksternal.

Storage

Tampilan Storage menampilkan sumber-sumber daya PersistentVolumeClaim yang digunakan oleh aplikasi untuk menyimpan data.

Config Maps dan Secrets

Menampilkan semua sumber daya Kubernetes yang digunakan untuk pengaturan aplikasi yang sedang berjalan di klaster. Pada tampilan ini kamu dapat mengedit dan mengelola objek-objek konfigurasi dan menampilkan kredensial yang tersembunyi secara bawaan.

Logs Viewer

Laman daftar dan detail Pod tertaut dengan laman penampil log (log viewer). Kamu dapat menelusuri log yang berasal dari Container-Container pada sebuah Pod.

Logs viewer

Selanjutnya

Untuk informasi lebih lanjut, lihat Laman proyek Kubernetes Dashboard.

8.2 - Mengakses Klaster

Topik ini membahas tentang berbagai cara untuk berinteraksi dengan klaster.

Mengakses untuk pertama kalinya dengan kubectl

Saat mengakses API Kubernetes untuk pertama kalinya, kami sarankan untuk menggunakan CLI Kubernetes, kubectl.

Untuk mengakses sebuah klaster, kamu perlu mengetahui lokasi klaster dan mempunyai kredensial untuk mengaksesnya. Biasanya, ini secara otomatis diatur saat kamu mengikuti Panduan persiapan, atau orang lain yang mengatur klaster dan memberikan kredensial dan lokasi kepadamu.

Periksa lokasi dan kredensial yang ada pada konfigurasi kubectl-mu melalui perintah ini:

kubectl config view 

Beragam contoh menyediakan pengantar penggunaan kubectl, dan dokumentasi lengkap dapat ditemukan di kubectl manual.

Mengakses REST API secara langsung

Kubectl menangani pencarian dan autentikasi ke apiserver. Jika kamu ingin secara langsung mengakses REST API dengan klien HTTP seperti curl atau wget, atau peramban, ada beberapa cara untuk pencarian dan autentikasi:

  • Jalankan kubectl dalam mode proksi.
    • Pendekatan yang disarankan.
    • Menggunakan lokasi apiserver yang tersimpan.
    • Melakukan verifikasi identitas apiserver menggunakan sertifikat elektronik yang ditandatangani sendiri. Tidak memungkinkan adanya MITM.
    • Melakukan autentikasi ke apiserver.
    • Di masa depan, dimungkinkan dapat melakukan load-balancing dan failover yang cerdas dari sisi klien.
  • Penyediaan lokasi dan kredensial langsung ke klien http.
    • Pendekatan alternatif.
    • Bekerja dengan beberapa jenis kode klien dengan menggunakan proksi.
    • Perlu mengimpor sertifikat elektronik root ke peramban kamu untuk melindungi dari MITM.

Menggunakan kubectl proxy

Perintah berikut akan menjalankan kubectl dalam mode di mana ia bertindak sebagai proksi terbalik (reverse proxy). Hal ini menangani pencarian dan autentikasi apiserver. Jalankan seperti ini:

kubectl proxy --port=8080 

Lihat kubectl proxy untuk lebih jelasnya.

Kemudian kamu dapat menjelajahi API-nya dengan curl, wget, atau peramban, ganti localhost dengan [::1] untuk IPv6, seperti ini:

curl http://localhost:8080/api/ 

Hasil keluarannya seperti ini:

{  "kind": "APIVersions",  "versions": [  "v1"  ],  "serverAddressByClientCIDRs": [  {  "clientCIDR": "0.0.0.0/0",  "serverAddress": "10.0.1.149:443"  }  ] } 

Tanpa menggunakan kubectl proxy

Gunakan kubectl describe secret... untuk mendapatkan token untuk akun servis (service account) default dengan grep/cut:

APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ") SECRET_NAME=$(kubectl get secrets | grep ^default | cut -f1 -d ' ') TOKEN=$(kubectl describe secret $SECRET_NAME | grep -E '^token' | cut -f2 -d':' | tr -d " ")  curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure 

Hasil keluarannya seperti ini:

{  "kind": "APIVersions",  "versions": [  "v1"  ],  "serverAddressByClientCIDRs": [  {  "clientCIDR": "0.0.0.0/0",  "serverAddress": "10.0.1.149:443"  }  ] } 

Menggunakan jsonpath:

APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}') SECRET_NAME=$(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') TOKEN=$(kubectl get secret $SECRET_NAME -o jsonpath='{.data.token}' | base64 --decode)  curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure 

Hasil keluarannya seperti ini:

{  "kind": "APIVersions",  "versions": [  "v1"  ],  "serverAddressByClientCIDRs": [  {  "clientCIDR": "0.0.0.0/0",  "serverAddress": "10.0.1.149:443"  }  ] } 

Contoh di atas menggunakan flag --insecure. Hal ini membuatnya rentan terhadap serangan MITM. Ketika kubectl mengakses klaster, kubectl menggunakan sertifikat elektronik root yang tersimpan dan sertifikat elektronik klien untuk mengakses server. (Sertifikat-sertifikat elektronik tersebut diinstal di direktori ~/.kube). Karena sertifikat elektronik klaster biasanya ditandatangani sendiri, mungkin diperlukan konfigurasi khusus untuk membuat klien HTTP kamu menggunakan sertifikat elektronik root.

Pada beberapa klaster, apiserver tidak memerlukan autentikasi; mungkin apiserver tersebut meladen (serve) di localhost, atau dilindungi oleh sebuah dinding api (firewall). Tidak ada standar untuk ini. Mengonfigurasi Akses ke API menjelaskan bagaimana admin klaster dapat mengonfigurasi hal ini. Pendekatan semacam itu dapat bertentangan dengan dukungan ketersediaan tinggi (high-availability) pada masa depan.

Akses terprogram ke API

Kubernetes secara resmi mendukung pustaka (library) klien Go dan Python.

Klien Go

  • Untuk mendapatkan pustakanya, jalankan perintah berikut: go get k8s.io/client-go@kubernetes-<kubernetes-version-number>, lihat INSTALL.md untuk instruksi instalasi yang lebih detail. Lihat https://github.com/kubernetes/client-go untuk melihat versi yang didukung.
  • Tulis aplikasi dengan menggunakan klien client-go. Perhatikan bahwa client-go mendefinisikan objek APInya sendiri, jadi jika perlu, silakan impor definisi API dari client-go daripada dari repositori utama, misalnya, import "k8s.io/client-go/kubernetes".

Klien Go dapat menggunakan berkas kubeconfig yang sama dengan yang digunakan oleh CLI kubectl untuk mencari dan mengautentikasi ke apiserver. Lihat contoh ini.

Jika aplikasi ini digunakan sebagai Pod di klaster, silakan lihat bagian selanjutnya.

Klien Python

Untuk menggunakan klien Python, jalankan perintah berikut: pip install kubernetes. Lihat halaman Pustaka Klien Python untuk opsi instalasi lainnya.

Klien Python dapat menggunakan berkas kubeconfig yang sama dengan yang digunakan oleh CLI kubectl untuk mencari dan mengautentikasi ke apiserver. Lihat contoh.

Bahasa lainnya

Ada pustaka klien untuk mengakses API dari bahasa lain. Lihat dokumentasi pustaka lain untuk melihat bagaimana mereka melakukan autentikasi.

Mengakses API dari Pod

Saat mengakses API dari Pod, pencarian dan autentikasi ke apiserver agak berbeda.

Cara yang disarankan untuk menemukan apiserver di dalam Pod adalah dengan nama DNS kubernetes.default.svc, yang akan mengubah kedalam bentuk Service IP yang pada gilirannya akan dialihkan ke apiserver.

Cara yang disarankan untuk mengautentikasi ke apiserver adalah dengan kredensial akun servis. Oleh kube-system, Pod dikaitkan dengan sebuah akun servis (service account), dan sebuah kredensial (token) untuk akun servis (service account) tersebut ditempatkan ke pohon sistem berkas (file system tree) dari setiap Container di dalam Pod tersebut, di /var/run/secrets/kubernetes.io/serviceaccount/token.

Jika tersedia, bundel sertifikat elektronik ditempatkan ke pohon sistem berkas dari setiap Container di /var/run/secrets/kubernetes.io/serviceaccount/ca.crt, dan itu akan digunakan untuk memverifikasi sertifikat elektronik yang digunakan apiserver untuk meladen.

Terakhir, Namespace default yang akan digunakan untuk operasi API namespaced ditempatkan di dalam berkas /var/run/secrets/kubernetes.io/serviceaccount/namespace di dalam setiap Container.

Dari dalam Pod, cara yang disarankan untuk menghubungi API adalah:

  • Jalankan kubectl proxy pada Container sidecar di dalam Pod, atau sebagai proses background di dalam Container. Perintah tersebut memproksi API Kubernetes pada antarmuka localhost Pod tersebut, sehingga proses lain dalam Container apa pun milik Pod dapat mengaksesnya.
  • Gunakan pustaka klien Go, dan buatlah sebuah klien menggunakan fungsi rest.InClusterConfig() dan kubernetes.NewForConfig(). Mereka menangani pencarian dan autentikasi ke apiserver. contoh

Pada setiap kasus, kredensial Pod digunakan untuk berkomunikasi secara aman dengan apiserver.

Mengakses servis yang berjalan di klaster

Bagian sebelumnya menjelaskan tentang menghubungi server API Kubernetes. Bagian ini menjelaskan tentang menghubungi servis lain yang berjalan di klaster Kubernetes. Di Kubernetes, semua Node, Pod, dan Service memiliki IP sendiri. Dalam banyak kasus, IP Node, IP Pod, dan beberapa IP Service pada sebuah klaster tidak dapat dirutekan, sehingga mereka tidak terjangkau dari mesin di luar klaster, seperti mesin desktop kamu.

Cara untuk terhubung

Kamu memiliki beberapa opsi untuk menghubungi Node, Pod, dan Service dari luar klaster:

  • Mengakses Service melalui IP publik.
    • Gunakan Service dengan tipe NodePort atau LoadBalancer untuk membuat Service dapat dijangkau di luar klaster. Lihat dokumentasi Service dan perintah kubectl expose.
    • Bergantung pada lingkungan klaster kamu, hal ini mungkin hanya mengekspos Service ke jaringan perusahaan kamu, atau mungkin mengeksposnya ke internet. Pikirkan apakah Service yang diekspos aman atau tidak. Apakah layanan di balik Service tersebut melakukan autentikasinya sendiri?
    • Tempatkan Pod di belakang Service. Untuk mengakses satu Pod tertentu dari sekumpulan replika, misalnya untuk pengawakutuan (debugging), letakkan label unik di Pod dan buat Service baru yang memilih label ini.
    • Pada kebanyakan kasus, pengembang aplikasi tidak perlu langsung mengakses Node melalui IP Node mereka.
  • Akses Service, Node, atau Pod menggunakan Verb Proxy.
    • Apakah autentikasi dan otorisasi apiserver dilakukan sebelum mengakses Service jarak jauh. Gunakan ini jika Service tersebut tidak cukup aman untuk diekspos ke internet, atau untuk mendapatkan akses ke porta (port) pada IP Node, atau untuk pengawakutuan.
    • Proksi dapat menyebabkan masalah untuk beberapa aplikasi web.
    • Hanya bekerja pada HTTP/HTTPS.
    • Dijelaskan di sini.
  • Akses dari Node atau Pod di klaster.
    • Jalankan Pod, kemudian hubungkan ke sebuah shell di dalamnya menggunakan kubectl exec. Hubungi Node, Pod, dan Service lain dari shell itu.
    • Beberapa klaster memungkinkan kamu untuk melakukan SSH ke sebuah Node di dalam klaster. Dari sana, kamu mungkin dapat mengakses Service-Service klaster. Hal ini merupakan metode yang tidak standar, dan akan bekerja pada beberapa klaster tetapi tidak pada yang lain. Peramban dan perkakas lain mungkin diinstal atau tidak. DNS Klaster mungkin tidak berfungsi.

Menemukan Service bawaan (builtin)

Biasanya, ada beberapa Service yang dimulai pada sebuah klaster oleh kube-system. Dapatkan daftarnya dengan perintah kubectl cluster-info:

kubectl cluster-info 

Keluarannya mirip seperti ini:

Kubernetes master is running at https://104.197.5.247 elasticsearch-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy kibana-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kibana-logging/proxy kube-dns is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kube-dns/proxy grafana is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy heapster is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy 

Ini menunjukkan URL proxy-verb untuk mengakses setiap Service. Misalnya, klaster ini mempunyai pencatatan log pada level klaster (cluster-level logging) yang aktif (menggunakan Elasticsearch), yang dapat dicapai di https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/ jika kredensial yang sesuai diberikan. Pencatatan log dapat pula dicapai dengan sebuah proksi kubectl, misalnya di: http://localhost:8080/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/. (Lihat di atas untuk panduan bagaimana cara meneruskan kredensial atau menggunakan kubectl proxy.)

Membuat URL proksi apiserver secara manual

Seperti disebutkan di atas, kamu menggunakan perintah kubectl cluster-info untuk mendapatkan URL proksi suatu Service. Untuk membuat URL proksi yang memuat endpoint-endpoint Service, sufiks, dan parameter, kamu cukup menambahkan ke URL proksi Service: http://alamat_kubernetes_master/api/v1/namespaces/nama_namespace/services/nama_servis[:nama_porta]/proxy

Jika kamu belum menentukan nama untuk porta kamu, kamu tidak perlu memasukan nama_porta di URL.

Secara bawaan, server API memproksi ke Service kamu menggunakan HTTP. Untuk menggunakan HTTPS, awali nama Service dengan https:: http://alamat_kubernetes_master/api/v1/namespaces/nama_namespace/services/https:nama_servis:[nama_porta]/proxy

Format yang didukung untuk segmen nama URL adalah:

  • <nama_servis> - Memproksi ke porta bawaan atau porta tanpa nama menggunakan HTTP
  • <nama_servis>:<nama_porta> - Memproksi ke porta yang telah ditentukan menggunakan HTTP
  • https:<nama_servis>: - Memproksi ke porta bawaan atau porta tanpa nama menggunakan HTTPS (perhatikan tanda adanya titik dua)
  • https:<nama_servis>:<nama_porta> - proksi ke porta yang telah ditentukan menggunakan https
Contoh
  • Untuk mengakses endpoint Service Elasticsearch _search?q=user:kimchy, kamu dapat menggunakan: http://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_search?q=user:kimchy
  • Untuk mengakses informasi kesehatan klaster Elasticsearch _cluster/health?pretty=true, kamu dapat menggunakan: https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_cluster/health?pretty=true
{  "cluster_name" : "kubernetes_logging",  "status" : "yellow",  "timed_out" : false,  "number_of_nodes" : 1,  "number_of_data_nodes" : 1,  "active_primary_shards" : 5,  "active_shards" : 5,  "relocating_shards" : 0,  "initializing_shards" : 0,  "unassigned_shards" : 5 } 

Menggunakan peramban web untuk mengakses Service yang berjalan di klaster

Kamu mungkin dapat memasukkan URL proksi apiserver ke bilah alamat peramban. Namun:

  • Peramban web biasanya tidak dapat menerima token, jadi kamu mungkin perlu menggunakan autentikasi dasar/basic auth (kata sandi). Apiserver dapat dikonfigurasi untuk menerima autentikasi dasar, tetapi klaster kamu mungkin belum dikonfigurasi untuk menerima autentikasi dasar.
  • Beberapa aplikasi web mungkin tidak berfungsi, terutama yang memiliki javascript pada sisi klien yang digunakan untuk membuat URL sedemikian sehingga ia tidak mengetahui adanya prefiks jalur (path) proksi (/proxy).

Meminta pengalihan

Kemampuan pengalihan telah usang (deprecated) dan dihapus. Silakan gunakan proksi (lihat di bawah) sebagai gantinya.

Begitu Banyaknya Proksi

Ada beberapa proksi berbeda yang mungkin kamu temui saat menggunakan Kubernetes:

  1. Proksi kubectl:

    • berjalan di desktop pengguna atau di Pod
    • memproksi dari sebuah alamat localhost ke apiserver Kubernetes
    • dari klien ke proksi menggunakan HTTP
    • dari proksi ke apiserver menggunakan HTTPS
    • menemukan apiserver-nya
    • menambahkan header-header autentikasi
  2. Proksi apiserver:

    • merupakan sebuah bastion yang dibangun ke dalam apiserver
    • menghubungkan pengguna di luar klaster ke IP klaster yang mungkin tidak dapat dijangkau
    • berjalan dalam proses apiserver
    • dari klien ke proksi menggunakan HTTPS (atau HTTP jika apiserver dikonfigurasi)
    • dari proksi ke target dapat menggunakan HTTP atau HTTPS seperti yang dipilih oleh proksi menggunakan informasi yang tersedia
    • dapat digunakan untuk menjangkau Node, Pod, atau Service
    • melakukan load balancing saat digunakan untuk menjangkau sebuah Service
  3. kube-proxy:

    • berjalan di setiap Node
    • memproksi UDP dan TCP
    • tidak mengerti HTTP
    • menyediakan load balancing
    • hanya digunakan untuk menjangkau Service
  4. Sebuah Proksi/Load-balancer di depan apiserver:

    • keberadaan dan implementasi bervariasi dari satu klaster ke klaster lainnya (mis. nginx)
    • terletak di antara semua klien dan satu atau lebih apiserver
    • bertindak sebagai load balancer jika terdapat beberapa apiserver.
  5. Cloud Load Balancer pada Service eksternal:

    • disediakan oleh beberapa penyedia layanan cloud (mis. AWS ELB, Google Cloud Load Balancer)
    • dibuat secara otomatis ketika Service Kubernetes memiliki tipe LoadBalancer
    • hanya menggunakan UDP/TCP
    • implementasi bervariasi berdasarkan penyedia layanan cloud.

Pengguna Kubernetes biasanya tidak perlu khawatir tentang apa pun selain dua jenis pertama. Admin klaster biasanya akan memastikan bahwa tipe yang terakhir telah diatur dengan benar.

8.3 - Mengkonfigurasi Akses ke Banyak Klaster

Halaman ini menunjukkan bagaimana mengkonfigurasi akses ke banyak klaster dengan menggunakan berkas (file) konfigurasi. Setelah semua klaster, pengguna, dan konteks didefinisikan di satu atau lebih berkas konfigurasi, kamu akan dengan cepat berpindah antar klaster dengan menggunakan perintah kubectl config use-context.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Mendefinisikan klaster, pengguna, dan konteks

Misalkan kamu memiliki dua klaster, satu untuk pekerjaan pengembangan dan satu untuk pekerjaan eksperimen (scratch). Di klaster pengembangan, pengembang frontend kamu bekerja di sebuah Namespace bernama frontend, dan pengembang penyimpanan kamu bekerja di sebuah Namespace bernama storage. Di klaster scratch kamu, pengembang bekerja di Namespace default, atau mereka membuat Namespace tambahan sesuai keinginan mereka. Akses ke klaster development membutuhkan autentikasi dengan sertifikat. Akses ke klaster scratch membutuhkan autentikasi dengan nama pengguna dan kata sandi.

Buat sebuah direktori bernama config-exercise. Di direktori config-exercise kamu, buat sebuah berkas bernama config-demo dengan konten ini:

apiVersion: v1 kind: Config preferences: {}  clusters: - cluster:  name: development - cluster:  name: scratch  users: - name: developer - name: experimenter  contexts: - context:  name: dev-frontend - context:  name: dev-storage - context:  name: exp-scratch 

Berkas konfigurasi di atas mendeskripsikan semua klaster, pengguna, dan konteks. Berkas config-demo kamu memiliki kerangka kerja untuk mendeskripsikan dua klaster, dua pengguna, dan tiga konteks.

Buka direktori config-exercise kamu. Masukkan perintah-perintah berikut untuk menambahkan detail ke berkas konfigurasi kamu:

kubectl config --kubeconfig=config-demo set-cluster development --server=https://1.2.3.4 --certificate-authority=fake-ca-file kubectl config --kubeconfig=config-demo set-cluster scratch --server=https://5.6.7.8 --insecure-skip-tls-verify 

Tambahkan detail pengguna ke berkas konfigurasi kamu:

kubectl config --kubeconfig=config-demo set-credentials developer --client-certificate=fake-cert-file --client-key=fake-key-seefile kubectl config --kubeconfig=config-demo set-credentials experimenter --username=exp --password=some-password 

Tambahkan detail konteks ke berkas konfigurasi kamu:

kubectl config --kubeconfig=config-demo set-context dev-frontend --cluster=development --namespace=frontend --user=developer kubectl config --kubeconfig=config-demo set-context dev-storage --cluster=development --namespace=storage --user=developer kubectl config --kubeconfig=config-demo set-context exp-scratch --cluster=scratch --namespace=default --user=experimenter 

Buka berkas config-demo kamu untuk melihat detail-detail yang telah ditambah. Sebagai alternatif dari membuka berkas config-demo, kamu bisa menggunakan perintah config view.

kubectl config --kubeconfig=config-demo view 

Keluaran akan menampilkan dua klaster, dua pengguna, dan tiga konteks:

apiVersion: v1 clusters: - cluster:  certificate-authority: fake-ca-file  server: https://1.2.3.4  name: development - cluster:  insecure-skip-tls-verify: true  server: https://5.6.7.8  name: scratch contexts: - context:  cluster: development  namespace: frontend  user: developer  name: dev-frontend - context:  cluster: development  namespace: storage  user: developer  name: dev-storage - context:  cluster: scratch  namespace: default  user: experimenter  name: exp-scratch current-context: "" kind: Config preferences: {} users: - name: developer  user:  client-certificate: fake-cert-file  client-key: fake-key-file - name: experimenter  user:  password: some-password  username: exp 

fake-ca-file, fake-cert-file, dan fake-key-file di atas adalah placeholder untuk nama jalur (pathname) dari berkas-berkas sertifikat. Kamu harus menggantinya menjadi nama jalur sebenarnya dari berkas-berkas sertifikat di dalam lingkungan (environment) kamu.

Terkadang kamu mungkin ingin menggunakan data yang disandikan Base64 yang langsung dimasukkan di berkas konfigurasi daripada menggunakan berkas sertifikat yang terpisah. Dalam kasus ini, kamu perlu menambahkan akhiran -data ke kunci. Contoh, certificate-authority-data, client-certificate-data, dan client-key-data.

Setiap konteks memiliki tiga bagian: klaster, pengguna, dan Namespace. Sebagai contoh, konteks dev-frontend menyatakan, "Gunakan kredensial dari pengguna developer untuk mengakses Namespace frontend di klaster development.

Mengatur konteks yang digunakan:

kubectl config --kubeconfig=config-demo use-context dev-frontend 

Sekarang kapanpun kamu memasukkan perintah kubectl, aksi tersebut akan diterapkan untuk klaster, dan Namespace yang terdaftar pada konteks dev-frontend. Dan perintah tersebut akan menggunakan kredensial dari pengguna yang terdaftar pada konteks dev-frontend.

Untuk melihat hanya informasi konfigurasi yang berkaitan dengan konteks saat ini, gunakan --minify flag.

kubectl config --kubeconfig=config-demo view --minify 

Output menunjukkan informasi konfigurasi yang berkaitan dengan konteks dev-frontend:

apiVersion: v1 clusters: - cluster:  certificate-authority: fake-ca-file  server: https://1.2.3.4  name: development contexts: - context:  cluster: development  namespace: frontend  user: developer  name: dev-frontend current-context: dev-frontend kind: Config preferences: {} users: - name: developer  user:  client-certificate: fake-cert-file  client-key: fake-key-file 

Sekarang apabila kamu ingin bekerja sebentar di klaster eksperimen.

Ubah konteks saat ini menjadi exp-scratch:

kubectl config --kubeconfig=config-demo use-context exp-scratch 

Sekarang, setiap perintah kubectl yang diberikan akan berlaku untuk Namespace default dari klaster scratch. Dan perintah akan menggunakan kredensial dari pengguna yang terdaftar di konteks exp-scratch.

Untuk melihat konfigurasi yang berkaitan dengan konteks saat ini, exp-scratch.

kubectl config --kubeconfig=config-demo view --minify 

Akhirnya, misalkan kamu ingin bekerja sebentar di Namespace storage pada klaster development.

Ubah konteks saat ini menjadi dev-storage:

kubectl config --kubeconfig=config-demo use-context dev-storage 

Untuk melihat konfigurasi yang berkaitan dengan konteks baru saat ini, dev-storage.

kubectl config --kubeconfig=config-demo view --minify 

Membuat sebuah berkas konfigurasi kedua

Di direktori config-exercise kamu, buat sebuah berkas bernama config-demo-2 dengan konten ini:

apiVersion: v1 kind: Config preferences: {}  contexts: - context:  cluster: development  namespace: ramp  user: developer  name: dev-ramp-up 

Berkas konfigurasi di atas mendefinisikan sebuah konteks baru bernama dev-ramp-up.

Mengatur variabel lingkungan KUBECONFIG

Lihat apakah kamu sudah memiliki sebuah variabel lingkungan bernama KUBECONFIG. Jika iya, simpan nilai saat ini dari variabel lingkungan KUBECONFIG kamu, sehingga kamu dapat mengembalikannya nanti. Sebagai contohL

Linux

export KUBECONFIG_SAVED=$KUBECONFIG 

Windows PowerShell

$Env:KUBECONFIG_SAVED=$ENV:KUBECONFIG 

Variabel lingkungan KUBECONFIG adalah sebuah daftar dari jalur-jalur (beragam path) menuju berkas konfigurasi. Daftar ini dibatasi oleh tanda titik dua untuk Linux dan Mac, dan tanda titik koma untuk Windows. Jika kamu memiliki sebuah variabel lingkungan KUBECONFIG, biasakan diri kamu dengan berkas-berkas konfigurasi yang ada pada daftar.

Tambahkan sementara dua jalur ke variabel lingkungan KUBECONFIG kamu. Sebagai contoh:

Linux

export KUBECONFIG=$KUBECONFIG:config-demo:config-demo-2 

Windows PowerShell

$Env:KUBECONFIG=("config-demo;config-demo-2") 

Di direktori config-exercise kamu, masukan perintah ini:

kubectl config view 

Keluaran menunjukkan informasi gabungan dari semua berkas yang terdaftar dalam variabel lingkungan KUBECONFIG kamu. Secara khusus, perhatikan bahwa informasi gabungan tersebut memiliki konteks dev-ramp-up, konteks dari berkas config-demo-2, dan tiga konteks dari berkas config-demo:

contexts: - context:  cluster: development  namespace: frontend  user: developer  name: dev-frontend - context:  cluster: development  namespace: ramp  user: developer  name: dev-ramp-up - context:  cluster: development  namespace: storage  user: developer  name: dev-storage - context:  cluster: scratch  namespace: default  user: experimenter  name: exp-scratch 

Untuk informasi lebih tentang bagaimana berkas Kubeconfig tergabung, lihat Mengatur Akses Cluster Menggunakan Berkas Kubeconfig

Jelajahi direktori $HOME/.kube

Jika kamu sudah memiliki sebuah klaster, dan kamu bisa menggunakan kubectl untuk berinteraksi dengan klaster kamu, kemudian kamu mungkin memiliki sebuah berkas bernama config di direktori $HOME/.kube.

Buka $HOME/.kube, dan lihat berkas-berkas apa saja yang ada. Biasanya ada berkas bernama config. Mungkin juga ada berkas-berkas konfigurasi lain di direktori ini. Biasakan diri anda dengan konten-konten yang ada di berkas-berkas tersebut.

Tambahkan $HOME/.kube/config ke variabel lingkungan KUBECONFIG kamu

Jika kamu memiliki sebuah berkas $HOME/.kube/config, dan belum terdaftar dalam variabel lingungan KUBECONFIG kamu, tambahkan berkas tersebut ke variabel lingkungan KUBECONFIG kamu sekarang. Sebagai contoh:

Linux

export KUBECONFIG=$KUBECONFIG:$HOME/.kube/config 

Windows Powershell

$Env:KUBECONFIG=($Env:KUBECONFIG;$HOME/.kube/config) 

Lihat gabungan informasi konfigurasi dari semua berkas yang sekarang tergabung dalam variabel lingkungan KUBECONFIG kamu. Di direktori config-exercise kamu, masukkan perintah:

kubectl config view 

Membersihkan

Kembalikan variabel lingkungan KUBECONFIG kamu ke nilai asilnya. Sebagai contoh:

Linux

export KUBECONFIG=$KUBECONFIG_SAVED 

Windows PowerShell

$Env:KUBECONFIG=$ENV:KUBECONFIG_SAVED 

Selanjutnya

8.4 - Menggunakan Port Forwarding untuk Mengakses Aplikasi di sebuah Klaster

Halaman ini menunjukkan bagaimana menggunakan kubectl port-forward untuk menghubungkan sebuah server Redis yang sedang berjalan di sebuah klaster Kubernetes. Tipe dari koneksi ini dapat berguna untuk melakukan debugging basis data.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Kubernetes servermu harus dalam versi yang sama atau lebih baru dari v1.10.

Untuk melihat versi, tekan kubectl version.

Membuat Deployment dan Service Redis

  1. Buat sebuah Deployment yang menjalankan Redis:

    kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-deployment.yaml 

    Keluaran dari sebuah perintah yang sukses akan memverifikasi bahwa Deployment telah terbuat:

    deployment.apps/redis-master created 

    Lihat status Pod untuk memeriksa apakah sudah siap:

    kubectl get pods 

    Keluaran menampilkan Pod yang telah terbuat:

    NAME READY STATUS RESTARTS AGE redis-master-765d459796-258hz 1/1 Running 0 50s 

    Lihat status Deployment:

    kubectl get deployment 

    Keluaran menampilkan bahwa Deployment telah terbuat:

    NAME READY UP-TO-DATE AVAILABLE AGE redis-master 1/1 1 1 55s 

    Deployment secara otomatis mengatur sebuah ReplicaSet. Lihat status ReplicaSet menggunakan:

    kubectl get replicaset 

    Keluaran menampilkan bahwa ReplicaSet telah terbuat:

    NAME DESIRED CURRENT READY AGE redis-master-765d459796 1 1 1 1m 
  2. Buat sebuah Service untuk mengekspos Redis di jaringan:

    kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-service.yaml 

    Keluaran dari perintah yang sukses akan memverifikasi bahwa Service telah terbuat:

    service/redis-master created 

    Lihat Service yang telah terbuat menggunakan:

    kubectl get service redis-master 

    Keluaran menampilkan service yang telah terbuat:

    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE redis-master ClusterIP 10.0.0.213 <none> 6379/TCP 27s 
  3. Periksa apakah server Redis berjalan di Pod, dan mendengarkan porta 6379:

    # Ubah redis-master-765d459796-258hz menjadi nama Pod kubectl get pod redis-master-765d459796-258hz --template='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}' 

    Keluaran akan menampilkan porta dari Redis di Pod tersebut:

    6379 

    (ini adalah porta TCP yang dialokasi untuk Redis di internet)

Meneruskan sebuah porta lokal ke sebuah porta pada Pod

  1. kubectl port-forward memungkinkan penggunaan nama sumber daya, seperti sebuah nama Pod, untuk memilih Pod yang sesuai untuk melakukan penerusan porta.

    # Ubah redis-master-765d459796-258hz menjadi nama Pod kubectl port-forward redis-master-765d459796-258hz 7000:6379 

    yang sama seperti

    kubectl port-forward pods/redis-master-765d459796-258hz 7000:6379 

    atau

    kubectl port-forward deployment/redis-master 7000:6379 

    atau

    kubectl port-forward replicaset/redis-master 7000:6379 

    atau

    kubectl port-forward service/redis-master 7000:6379 

    Semua perintah di atas berfungsi. Keluarannya mirip dengan ini:

    I0710 14:43:38.274550 3655 portforward.go:225] Forwarding from 127.0.0.1:7000 -> 6379 I0710 14:43:38.274797 3655 portforward.go:225] Forwarding from [::1]:7000 -> 6379 
  2. Memulai antarmuka baris perintah (command line) Redis:

    redis-cli -p 7000 
  3. Pada baris perintah di Redis, masukkan perintah ping:

    ping 

    Sebuah permintaan ping yang sukses akan mengembalikan:

    PONG 

Diskusi

Koneksi-koneksi yang dibuat ke porta lokal 7000 diteruskan ke porta 6379 dari Pod yang menjalankan server Redis. Dengan koneksi ini, kamu dapat menggunakan workstation lokal untuk melakukan debug basis data yang berjalan di Pod.

Selanjutnya

Belajar lebih tentang kubectl port-forward.

8.5 - Membuat Load Balancer Eksternal

Laman ini menjelaskan bagaimana membuat Load Balancer Eksternal.

Ketika membuat Service, kamu mempunyai opsi untuk tersambung dengan jaringan cloud load balancer secara otomatis. Hal ini menyediakan akses eksternal alamat IP yang dapat mengirim lalu lintas melalui porta yang tepat pada klaster Node kamu asalkan klaster kamu beroperasi pada lingkungan yang mendukung dan terkonfigurasi dengan paket penyedia cloud load balancer yang benar.

Untuk informasi mengenai penyediaan dan penggunaan sumber daya Ingress yang dapat memberikan servis URL yang dapat dijangkau secara eksternal, penyeimbang beban lalu lintas, terminasi SSL, dll., silahkan cek dokumentasi Ingress

Sebelum kamu memulai

  • Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

    Untuk melihat versi, tekan kubectl version.

Berkas konfigurasi

Untuk membuat load balancer eksternal, tambahkan baris di bawah ini ke berkas konfigurasi Service kamu:

 type: LoadBalancer 

Berkas konfigurasi kamu mungkin terlihat seperti ini:

apiVersion: v1 kind: Service metadata:  name: example-service spec:  selector:  app: example  ports:  - port: 8765  targetPort: 9376  type: LoadBalancer 

Menggunakan kubectl

Kamu dapat membuat Service dengan perintah kubectl expose dan flag --type=LoadBalancer:

kubectl expose rc example --port=8765 --target-port=9376 \  --name=example-service --type=LoadBalancer 

Perintah ini membuat Service baru dengan menggunakan pemilih yang sama dengan sumber daya yang dirujuk (dalam hal contoh di atas, ReplicationController bernama example).

Untuk informasi lebih lanjut, termasuk opsi flag, mengacu kepada referensi kubectl expose.

Menemukan alamat IP kamu

Kamu dapat menemukan alamat IP yang telah dibuat untuk Service kamu dengan mendapatkan informasi Service melalui kubectl:

kubectl describe services example-service 

yang seharusnya menghasilkan keluaran seperti ini:

 Name: example-service  Namespace: default  Labels: <none>  Annotations: <none>  Selector: app=example  Type: LoadBalancer  IP: 10.67.252.103  LoadBalancer Ingress: 192.0.2.89  Port: <unnamed> 80/TCP  NodePort: <unnamed> 32445/TCP  Endpoints: 10.64.0.4:80,10.64.1.5:80,10.64.2.4:80  Session Affinity: None  Events: <none> 

Alamat IP tercantum di sebelah LoadBalancer Ingress.

minikube service example-service --url 

Preservasi IP sumber klien

Implementasi dari fitur ini menyebabkan sumber IP yang terlihat pada Container target bukan sebagai sumber IP asli dari klien. Untuk mengaktifkan preservasi IP klien, bidang berikut dapat dikonfigurasikan di dalam spek Service (mendukung lingkungan GCE/Google Kubernetes Engine):

  • service.spec.externalTrafficPolicy - menunjukkan jika Service menginginkan rute lalu lintas eksternal ke titik akhir node-local atau cluster-wide. Terdapat dua opsi yang tersedia: Cluster (bawaan) dan Local. Cluster mengaburkan sumber IP klien dan mungkin menyebabkan hop kedua ke Node berbeda, namun harus mempunyai penyebaran beban (load-spreading) yang baik secara keseluruhan. Local mempreservasi sumber IP client dan menghindari hop kedua LoadBalancer dan Service dengan tipe NodePort, namun resiko berpotensi penyebaran lalu lintas yang tidak merata.
  • service.spec.healthCheckNodePort - menentukan pemeriksaan kesehatan porta dari sebuah Node (angka porta numerik) untuk Service. Jika healthCheckNodePort tidak ditentukan, pengendali Service mengalokasi porta dari rentang NodePort dari klaster kamu. Kamu dapat mengonfigurasi rentangan tersebut dari pengaturan opsi barisan perintah API server, --service-node-port-range. Hal itu menggunakan nilai healthCheckNodePort pengguna spesifik jika ditentukan oleh klien. Hal itu dapat berefek hanya ketika type diset ke LoadBalancer dan externalTrafficPolicy diset ke Local.

Pengaturan externalTrafficPolicy ke Local pada berkas konfigurasi Service mengaktifkan fitur ini.

apiVersion: v1 kind: Service metadata:  name: example-service spec:  selector:  app: example  ports:  - port: 8765  targetPort: 9376  externalTrafficPolicy: Local  type: LoadBalancer 

Pengumpul Sampah (Garbage Collector) Load Balancer

FEATURE STATE: Kubernetes v1.17 [stable]

Pada kasus biasa, sumber daya load balancer yang berkorelasi pada penyedia cloud perlu dibersihkan segera setelah Service bertipe LoadBalancer dihapus. Namun perlu diketahui bahwa terdapat kasus tepi dimana sumber daya cloud yatim piatu (orphaned) setelah Service yang berkaitan dihapus. Finalizer Protection untuk Service LoadBalancer diperkenalkan untuk mencegah hal ini terjadi. Dengan menggunakan finalizers, sebuah sumber daya Service tidak akan pernah dihapus hingga sumber daya load balancer yang berkorelasi juga dihapus.

Secara khusus, jika Service mempunyai type LoadBalancer, pengendali Service akan melekatkan finalizer bernama service.kubernetes.io/load-balancer-cleanup. Finalizer hanya akan dihapus setelah sumber daya load balancer dibersihkan. Hal ini mencegah sumber daya load balancer yang teruntai bahkan setelah kasus tepi seperti pengendali Service berhenti.

Penyedia Load Balancer Eksternal

Penting untuk dicatat bahwa jalur data untuk fungsionalitas ini disediakan oleh load balancer eksternal ke klaster Kubernetes.

Ketika Service type diset LoadBalancer, Kubernetes menyediakan fungsionalitas yang ekuivalen dengan type sebanding ClusterIP ke berbagai Pod di dalam klaster dan mengekstensinya dengan pemrograman (eksternal dari Kubernetes) load balancer dengan entri pada Pod Kubernetes. Pengendali Service Kubernetes mengotomasi pembuatan load balancer eksternal, cek kesehatan (jika dibutuhkan), dinding api (firewall) (jika dibutuhkan), dan mengambil IP eksternal yang dialokasikan oleh penyedia cloud dan mengisinya pada objek Service.

Peringatan dan and Limitasi ketika preservasi sumber IP

Load balancers GCE/AWS tidak menyediakan bobot pada kolam targetnya (target pools). Hal ini bukan merupakan isu dengan aturan kube-proxy Load balancer lama yang akan menyeimbangkan semua titik akhir dengan benar.

Dengan fungsionalitas yang baru, lalu lintas eksternal tidak menyeimbangkan beban secara merata pada seluruh Pod, namun sebaliknya menyeimbangkan secara merata pada level Node (karena GCE/AWS dan implementasi load balancer eksternal lainnya tidak mempunyai kemampuan untuk menentukan bobot setiap Node, mereka menyeimbangkan secara merata pada semua Node target, mengabaikan jumlah Pod pada tiap Node).

Namun demikian, kita dapat menyatakan bahwa NumServicePods << NumNodes atau NumServicePods >> NumNodes, distribusi yang cukup mendekati sama akan terlihat, meski tanpa bobot.

Sekali load balancer eksternal menyediakan bobot, fungsionalitas ini dapat ditambahkan pada jalur pemrograman load balancer. Pekerjaan Masa Depan: Tidak adanya dukungan untuk bobot yang disediakan untuk rilis 1.4, namun dapat ditambahkan di masa mendatang

Pod internal ke lalu lintas Pod harus berperilaku sama seperti Service ClusterIP, dengan probabilitas yang sama pada seluruh Pod.

8.6 - Membuat Daftar Semua Image Container yang Berjalan dalam Klaster

Laman ini menunjukkan cara menggunakan kubectl untuk membuat daftar semua image Container untuk Pod yang berjalan dalam sebuah klaster.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Dalam latihan ini kamu akan menggunakan kubectl untuk mengambil semua Pod yang berjalan dalam sebuah klaster, dan mengubah format keluarannya untuk melihat daftar Container untuk masing-masing Pod.

Membuat daftar semua image Container pada semua Namespace

  • Silakan ambil semua Pod dalam Namespace dengan menggunakan perintah kubectl get pods --all-namespaces
  • Silakan format keluarannya agar hanya menyertakan daftar nama image dari Container dengan menggunakan perintah -o jsonpath={.items[*].spec.containers[*].image}. Perintah ini akan mem-parsing field image dari keluaran json yang dihasilkan.
    • Silakan lihat referensi jsonpath untuk informasi lebih lanjut tentang cara menggunakan jsonpath.
  • Silakan format keluaran dengan menggunakan peralatan standar: tr, sort, uniq
    • Gunakan tr untuk mengganti spasi dengan garis baru
    • Gunakan sort untuk menyortir hasil
    • Gunakan uniq untuk mengumpulkan jumlah image
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" |\ tr -s '[[:space:]]' '\n' |\ sort |\ uniq -c 

Perintah di atas secara berulang akan mengembalikan semua field bernama image dari semua poin yang dikembalikan.

Sebagai pilihan, dimungkinkan juga untuk menggunakan jalur (path) absolut ke field image di dalam Pod. Hal ini memastikan field yang diambil benar bahkan ketika nama field tersebut diulangi, misalnya banyak field disebut dengan name dalam sebuah poin yang diberikan:

kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" 

Jsonpath dapat diartikan sebagai berikut:

  • .items[*]: untuk setiap nilai yang dihasilkan
  • .spec: untuk mendapatkan spesifikasi
  • .containers[*]: untuk setiap Container
  • .image: untuk mendapatkan image

Membuat daftar image Container berdasarkan Pod

Format dapat dikontrol lebih lanjut dengan menggunakan operasi range untuk melakukan iterasi untuk setiap elemen secara individual.

kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}' |\ sort 

Membuat daftar image yang difilter berdasarkan label dari Pod

Untuk menargetkan hanya Pod yang cocok dengan label tertentu saja, gunakan tanda -l. Filter dibawah ini akan menghasilkan Pod dengan label yang cocok dengan app=nginx.

kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" -l app=nginx 

Membuat daftar image Container yang difilter berdasarkan Namespace Pod

Untuk hanya menargetkan Pod pada Namespace tertentu, gunakankan tanda Namespace. Filter dibawah ini hanya menyaring Pod pada Namespace kube-system.

kubectl get pods --namespace kube-system -o jsonpath="{.items[*].spec.containers[*].image}" 

Membuat daftar image Container dengan menggunakan go-template sebagai alternatif dari jsonpath

Sebagai alternatif untuk jsonpath, kubectl mendukung penggunaan go-template untuk memformat keluaran seperti berikut:

kubectl get pods --all-namespaces -o go-template --template="{{range .items}}{{range .spec.containers}}{{.image}} {{end}}{{end}}" 

Selanjutnya

Referensi

9 - Pemantauan, Pencatatan, and Debugging

Mengatur pemantauan dan pencatatan untuk memecahkan masalah klaster, atau men-debug aplikasi yang terkontainerisasi.

9.1 - Introspeksi dan _Debugging_ Aplikasi

Setelah aplikasi kamu berjalan, kamu pasti perlu untuk men-debug masalah yang ada di dalamnya. Sebelumnya telah dijelaskan bagaimana kamu dapat menggunakan kubectl get pods untuk mengambil informasi status sederhana tentang Pod kamu. Namun ada sejumlah cara untuk mendapatkan lebih banyak informasi tentang aplikasi kamu.

Menggunakan kubectl describe pod untuk mengambil detil informasi Pod

Dalam contoh ini, kamu menggunakan Deployment untuk membuat dua buah Pod, yang hampir sama dengan contoh sebelumnya.

apiVersion: apps/v1 kind: Deployment metadata:  name: nginx-deployment spec:  selector:  matchLabels:  app: nginx  replicas: 2  template:  metadata:  labels:  app: nginx  spec:  containers:  - name: nginx  image: nginx  resources:  limits:  memory: "128Mi"  cpu: "500m"  ports:  - containerPort: 80 

Buat Deployment dengan menjalankan perintah ini:

kubectl apply -f https://k8s.io/examples/application/nginx-with-request.yaml 
deployment.apps/nginx-deployment created 

Cek status dari Pod dengan menggunakan perintah:

kubectl get pods 
NAME READY STATUS RESTARTS AGE nginx-deployment-1006230814-6winp 1/1 Running 0 11s nginx-deployment-1006230814-fmgu3 1/1 Running 0 11s 

Kamu dapat memperoleh lebih banyak informasi tentang masing-masing Pod ini dengan menggunakan perintah kubectl describe pod. Sebagai contoh:

kubectl describe pod nginx-deployment-1006230814-6winp 
Name:	nginx-deployment-1006230814-6winp Namespace:	default Node:	kubernetes-node-wul5/10.240.0.9 Start Time:	Thu, 24 Mar 2016 01:39:49 +0000 Labels:	app=nginx,pod-template-hash=1006230814 Annotations: kubernetes.io/created-by={"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicaSet","namespace":"default","name":"nginx-deployment-1956810328","uid":"14e607e7-8ba1-11e7-b5cb-fa16" ... Status:	Running IP:	10.244.0.6 Controllers:	ReplicaSet/nginx-deployment-1006230814 Containers: nginx: Container ID:	docker://90315cc9f513c724e9957a4788d3e625a078de84750f244a40f97ae355eb1149 Image:	nginx Image ID:	docker://6f62f48c4e55d700cf3eb1b5e33fa051802986b77b874cc351cce539e5163707 Port:	80/TCP QoS Tier: cpu:	Guaranteed memory:	Guaranteed Limits: cpu:	500m memory:	128Mi Requests: memory:	128Mi cpu:	500m State:	Running Started:	Thu, 24 Mar 2016 01:39:51 +0000 Ready:	True Restart Count:	0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-5kdvl (ro) Conditions: Type Status Initialized True Ready True PodScheduled True Volumes: default-token-4bcbi: Type:	Secret (a volume populated by a Secret) SecretName:	default-token-4bcbi Optional: false QoS Class: Guaranteed Node-Selectors: <none> Tolerations: <none> Events: FirstSeen	LastSeen	Count	From	SubobjectPath	Type	Reason	Message ---------	--------	-----	----	-------------	--------	------	------- 54s	54s	1	{default-scheduler }	Normal	Scheduled	Successfully assigned nginx-deployment-1006230814-6winp to kubernetes-node-wul5 54s	54s	1	{kubelet kubernetes-node-wul5}	spec.containers{nginx}	Normal	Pulling	pulling image "nginx" 53s	53s	1	{kubelet kubernetes-node-wul5}	spec.containers{nginx}	Normal	Pulled	Successfully pulled image "nginx" 53s	53s	1	{kubelet kubernetes-node-wul5}	spec.containers{nginx}	Normal	Created	Created container with docker id 90315cc9f513 53s	53s	1	{kubelet kubernetes-node-wul5}	spec.containers{nginx}	Normal	Started	Started container with docker id 90315cc9f513 

Di sini kamu dapat melihat informasi konfigurasi tentang Container dan Pod (label, kebutuhan resource, dll.), serta informasi status tentang Container dan Pod (status, kesiapan, berapa kali restart, event, dll.) .

Keadaan (state) Container merupakan salah satu dari keadaan Waiting, Running, atau Terminated. Tergantung dari keadaannya, informasi tambahan akan diberikan - di sini kamu dapat melihat bahwa untuk Container dalam keadaan running, sistem memberi tahu kamu kapan Container tersebut mulai dijalankan.

Ready memberi tahu kepada kamu apakah Container berhasil melewati pemeriksaan kesiapan terakhir. (Dalam kasus ini, Container tidak memiliki pemeriksaan kesiapan yang dikonfigurasi; Container dianggap selalu siap jika tidak ada pemeriksaan kesiapan yang dikonfigurasi.)

Jumlah restart memberi tahu kamu berapa kali Container telah dimulai ulang; informasi ini dapat berguna untuk mendeteksi kemacetan tertutup (crash loop) dalam Container yang dikonfigurasi dengan nilai restart policy 'always.'.

Saat ini, satu-satunya kondisi yang terkait dengan Pod adalah kondisi Binary Ready, yang menunjukkan bahwa Pod tersebut dapat melayani permintaan dan harus ditambahkan ke kumpulan penyeimbang beban (load balancing) dari semua Service yang sesuai.

Terakhir, kamu melihat catatan (log) peristiwa terbaru yang terkait dengan Pod kamu. Sistem mengompresi beberapa peristiwa yang identik dengan menunjukkan kapan pertama dan terakhir kali peristiwa itu dilihat dan berapa kali peristiwa itu dilihat. "From" menunjukkan komponen yang mencatat peristiwa, "SubobjectPath" memberi tahu kamu objek mana (mis. Container dalam pod) yang dimaksud, dan "Reason" dan "Message" memberi tahu kamu apa yang sudah terjadi.

Contoh: Men-debug Pod yang Pending

Skenario umum yang bisa kamu deteksi menggunakan peristiwa (event) adalah saat kamu telah membuat Pod yang tidak muat di Node mana pun. Misalnya, karena Pod mungkin meminta lebih banyak sumber daya yang tersedia dalam Node mana pun, atau mungkin Pod menentukan label selector yang tidak sesuai dengan Node mana pun. Katakanlah kamu sebelumnya membuat Deployment dengan 5 replika (bukan 2) dan meminta 600 millicore, bukan 500, pada klaster dengan empat Node di mana setiap mesin (virtual) memiliki 1 CPU. Sehingga salah satu Pod tidak akan bisa dijadwalkan. (Perhatikan bahwa Pod addon seperti fluentd, skydns, dll., yang berjalan di setiap Node pada klaster, tidak bisa dijadwalkan jika kamu meminta sebanyak 1000 millicore.)

kubectl get pods 
NAME READY STATUS RESTARTS AGE nginx-deployment-1006230814-6winp 1/1 Running 0 7m nginx-deployment-1006230814-fmgu3 1/1 Running 0 7m nginx-deployment-1370807587-6ekbw 1/1 Running 0 1m nginx-deployment-1370807587-fg172 0/1 Pending 0 1m nginx-deployment-1370807587-fz9sd 0/1 Pending 0 1m 

Untuk mencari sebab kenapa Pod nginx-deployment-1370807587-fz9sd tidak berjalan, kamu dapat menggunakan kubectl describe pod pada Pod yang pending dan melihat setiap peristiwa yang terjadi di dalamnya:

kubectl describe pod nginx-deployment-1370807587-fz9sd 
 Name:	nginx-deployment-1370807587-fz9sd Namespace:	default Node:	/ Labels:	app=nginx,pod-template-hash=1370807587 Status:	Pending IP: Controllers:	ReplicaSet/nginx-deployment-1370807587 Containers: nginx: Image:	nginx Port:	80/TCP QoS Tier: memory:	Guaranteed cpu:	Guaranteed Limits: cpu:	1 memory:	128Mi Requests: cpu:	1 memory:	128Mi Environment Variables: Volumes: default-token-4bcbi: Type:	Secret (a volume populated by a Secret) SecretName:	default-token-4bcbi Events: FirstSeen	LastSeen	Count	From SubobjectPath	Type	Reason Message ---------	--------	-----	---- -------------	--------	------ ------- 1m 48s 7 {default-scheduler } Warning	FailedScheduling	pod (nginx-deployment-1370807587-fz9sd) failed to fit in any node fit failure on node (kubernetes-node-6ta5): Node didn't have enough resource: CPU, requested: 1000, used: 1420, capacity: 2000 fit failure on node (kubernetes-node-wul5): Node didn't have enough resource: CPU, requested: 1000, used: 1100, capacity: 2000 

Di sini kamu dapat melihat peristiwa yang dibuat oleh penjadwal yang mengatakan bahwa Pod gagal dijadwalkan karena alasan FailedScheduling (dan mungkin karena sebab yang lainnya). Pesan tersebut memberi tahu kamu bahwa tidak ada cukup sumber daya untuk Pod pada salah satu Node.

Untuk memperbaiki situasi ini, kamu dapat menggunakan kubectl scale untuk memperbarui Deployment kamu untuk menentukan empat replika atau yang lebih kecil. (Atau kamu bisa membiarkan satu Pod tertunda, dimana hal ini tidak berbahaya.)

Peristiwa seperti yang kamu lihat di bagian akhir keluaran dari perintah kubectl description pod akan tetap ada dalam etcd dan memberikan informasi tingkat tinggi tentang apa yang terjadi pada klaster. Untuk melihat daftar semua peristiwa kamu dapat menggunakan perintah

kubectl get events 

tetapi kamu harus ingat bahwa peristiwa bersifat Namespace. Artinya, jika kamu tertarik dengan peristiwa untuk beberapa objek dalam Namespace (misalnya, apa yang terjadi dengan Pod pada Namespace my-namespace), kamu perlu secara eksplisit menyebutkan Namespace tersebut pada perintah:

kubectl get events --namespace=my-namespace 

Untuk melihat peristiwa dari semua Namespace, kamu dapat menggunakan argumen --all-namespaces.

Sebagai tambahan dari perintah kubectl describe pod, cara lain untuk mendapatkan informasi tambahan tentang sebuah Pod (selain yang disediakan oleh kubectl get pod) adalah dengan meneruskan flag format keluaran -o yaml ke perintah kubectl get pod. Ini akan memberikan kamu lebih banyak informasi dalam format YAML daripada kubectl describe pod--semua informasi dasar yang dimiliki sistem tentang Pod. Di sini kamu akan melihat hal-hal seperti anotasi (yang merupakan metadata nilai kunci tanpa batasan label, yang digunakan secara internal oleh komponen sistem Kubernetes), kebijakan mulai ulang, porta, dan volume.

kubectl get pod nginx-deployment-1006230814-6winp -o yaml 
apiVersion: v1 kind: Pod metadata:  annotations:  kubernetes.io/created-by: |  {"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicaSet","namespace":"default","name":"nginx-deployment-1006230814","uid":"4c84c175-f161-11e5-9a78-42010af00005","apiVersion":"extensions","resourceVersion":"133434"}}  creationTimestamp: 2016-03-24T01:39:50Z  generateName: nginx-deployment-1006230814-  labels:  app: nginx  pod-template-hash: "1006230814"  name: nginx-deployment-1006230814-6winp  namespace: default  resourceVersion: "133447"  uid: 4c879808-f161-11e5-9a78-42010af00005 spec:  containers:  - image: nginx  imagePullPolicy: Always  name: nginx  ports:  - containerPort: 80  protocol: TCP  resources:  limits:  cpu: 500m  memory: 128Mi  requests:  cpu: 500m  memory: 128Mi  terminationMessagePath: /dev/termination-log  volumeMounts:  - mountPath: /var/run/secrets/kubernetes.io/serviceaccount  name: default-token-4bcbi  readOnly: true  dnsPolicy: ClusterFirst  nodeName: kubernetes-node-wul5  restartPolicy: Always  securityContext: {}  serviceAccount: default  serviceAccountName: default  terminationGracePeriodSeconds: 30  volumes:  - name: default-token-4bcbi  secret:  secretName: default-token-4bcbi status:  conditions:  - lastProbeTime: null  lastTransitionTime: 2016-03-24T01:39:51Z  status: "True"  type: Ready  containerStatuses:  - containerID: docker://90315cc9f513c724e9957a4788d3e625a078de84750f244a40f97ae355eb1149  image: nginx  imageID: docker://6f62f48c4e55d700cf3eb1b5e33fa051802986b77b874cc351cce539e5163707  lastState: {}  name: nginx  ready: true  restartCount: 0  state:  running:  startedAt: 2016-03-24T01:39:51Z  hostIP: 10.240.0.9  phase: Running  podIP: 10.244.0.6  startTime: 2016-03-24T01:39:49Z 

Contoh: Men-debug Node yang mati/tidak terjangkau (down/unreachable)

Terkadang saat men-debug melihat status sebuah Node akan sangat berguna - misalnya, karena kamu telah melihat perilaku aneh dari sebuah Pod yang sedang berjalan pada Node tersebut, atau untuk mencari tahu mengapa sebuah Pod tidak dapat dijadwalkan ke dalam Node tersebut. Seperti pada Pod, kamu dapat menggunakan perintah kubectl description node dan kubectl get node -o yaml untuk mengambil informasi mendetil tentang Node. Misalnya, disini kamu akan melihat jika sebuah Node sedang mati (terputus dari jaringan, atau kubelet mati dan tidak mau restart, dll.). Perhatikan peristiwa yang menunjukkan Node tersebut NotReady, dan juga perhatikan bahwa Pod tidak lagi berjalan (mereka akan dikeluarkan setelah lima menit berstatus NotReady).

kubectl get nodes 
NAME STATUS ROLES AGE VERSION kubernetes-node-861h NotReady <none> 1h v1.13.0 kubernetes-node-bols Ready <none> 1h v1.13.0 kubernetes-node-st6x Ready <none> 1h v1.13.0 kubernetes-node-unaj Ready <none> 1h v1.13.0 
kubectl describe node kubernetes-node-861h 
Name:	kubernetes-node-861h Role Labels: kubernetes.io/arch=amd64 kubernetes.io/os=linux kubernetes.io/hostname=kubernetes-node-861h Annotations: node.alpha.kubernetes.io/ttl=0 volumes.kubernetes.io/controller-managed-attach-detach=true Taints: <none> CreationTimestamp:	Mon, 04 Sep 2017 17:13:23 +0800 Phase: Conditions: Type	Status	LastHeartbeatTime	LastTransitionTime	Reason	Message ---- ------ ----------------- ------------------ ------ ------- OutOfDisk Unknown Fri, 08 Sep 2017 16:04:28 +0800 Fri, 08 Sep 2017 16:20:58 +0800 NodeStatusUnknown Kubelet stopped posting node status. MemoryPressure Unknown Fri, 08 Sep 2017 16:04:28 +0800 Fri, 08 Sep 2017 16:20:58 +0800 NodeStatusUnknown Kubelet stopped posting node status. DiskPressure Unknown Fri, 08 Sep 2017 16:04:28 +0800 Fri, 08 Sep 2017 16:20:58 +0800 NodeStatusUnknown Kubelet stopped posting node status. Ready Unknown Fri, 08 Sep 2017 16:04:28 +0800 Fri, 08 Sep 2017 16:20:58 +0800 NodeStatusUnknown Kubelet stopped posting node status. Addresses:	10.240.115.55,104.197.0.26 Capacity: cpu: 2 hugePages: 0 memory: 4046788Ki pods: 110 Allocatable: cpu: 1500m hugePages: 0 memory: 1479263Ki pods: 110 System Info: Machine ID: 8e025a21a4254e11b028584d9d8b12c4 System UUID: 349075D1-D169-4F25-9F2A-E886850C47E3 Boot ID: 5cd18b37-c5bd-4658-94e0-e436d3f110e0 Kernel Version: 4.4.0-31-generic OS Image: Debian GNU/Linux 8 (jessie) Operating System: linux Architecture: amd64 Container Runtime Version: docker://1.12.5 Kubelet Version: v1.6.9+a3d1dfa6f4335 Kube-Proxy Version: v1.6.9+a3d1dfa6f4335 ExternalID: 15233045891481496305 Non-terminated Pods: (9 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits --------- ---- ------------ ---------- --------------- ------------- ...... Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) CPU Requests CPU Limits Memory Requests Memory Limits ------------ ---------- --------------- ------------- 900m (60%) 2200m (146%) 1009286400 (66%) 5681286400 (375%) Events: <none> 
kubectl get node kubernetes-node-861h -o yaml 
apiVersion: v1 kind: Node metadata:  creationTimestamp: 2015-07-10T21:32:29Z  labels:  kubernetes.io/hostname: kubernetes-node-861h  name: kubernetes-node-861h  resourceVersion: "757"  uid: 2a69374e-274b-11e5-a234-42010af0d969 spec:  externalID: "15233045891481496305"  podCIDR: 10.244.0.0/24  providerID: gce://striped-torus-760/us-central1-b/kubernetes-node-861h status:  addresses:  - address: 10.240.115.55  type: InternalIP  - address: 104.197.0.26  type: ExternalIP  capacity:  cpu: "1"  memory: 3800808Ki  pods: "100"  conditions:  - lastHeartbeatTime: 2015-07-10T21:34:32Z  lastTransitionTime: 2015-07-10T21:35:15Z  reason: Kubelet stopped posting node status.  status: Unknown  type: Ready  nodeInfo:  bootID: 4e316776-b40d-4f78-a4ea-ab0d73390897  containerRuntimeVersion: docker://Unknown  kernelVersion: 3.16.0-0.bpo.4-amd64  kubeProxyVersion: v0.21.1-185-gffc5a86098dc01  kubeletVersion: v0.21.1-185-gffc5a86098dc01  machineID: ""  osImage: Debian GNU/Linux 7 (wheezy)  systemUUID: ABE5F6B4-D44B-108B-C46A-24CCE16C8B6E 

Selanjutnya

Pelajari tentang alat debugging tambahan, termasuk:

9.2 - Mendapatkan Shell Untuk Masuk ke Container yang Sedang Berjalan

Laman ini menunjukkan bagaimana cara menggunakan kubectl exec untuk mendapatkan shell untuk masuk ke dalam Container yang sedang berjalan.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Mendapatkan sebuah shell untuk masuk ke sebuah Container

Dalam latihan ini, kamu perlu membuat Pod yang hanya memiliki satu Container saja. Container tersebut menjalankan image nginx. Berikut ini adalah berkas konfigurasi untuk Pod tersebut:

apiVersion: v1 kind: Pod metadata:  name: shell-demo spec:  volumes:  - name: shared-data  emptyDir: {}  containers:  - name: nginx  image: nginx  volumeMounts:  - name: shared-data  mountPath: /usr/share/nginx/html  hostNetwork: true  dnsPolicy: Default 

Buatlah Pod tersebut:

kubectl apply -f https://k8s.io/examples/application/shell-demo.yaml 

Pastikan bahwa Container dalam Pod berjalan:

kubectl get pod shell-demo 

Dapatkan shell untuk masuk ke dalam Container:

kubectl exec -it shell-demo -- /bin/bash 

Di dalam shell kamu, perlihatkan isi dari direktori root:

root@shell-demo:/# ls / 

Di dalam shell kamu, cobalah perintah-perintah yang lainnya. Berikut beberapa contohnya:

root@shell-demo:/# ls / root@shell-demo:/# cat /proc/mounts root@shell-demo:/# cat /proc/1/maps root@shell-demo:/# apt-get update root@shell-demo:/# apt-get install -y tcpdump root@shell-demo:/# tcpdump root@shell-demo:/# apt-get install -y lsof root@shell-demo:/# lsof root@shell-demo:/# apt-get install -y procps root@shell-demo:/# ps aux root@shell-demo:/# ps aux | grep nginx 

Lihat kembali berkas konfigurasi untuk Pod kamu. Pod memiliki volume emptyDir, dan Container melakukan pemasangan (mounting) untuk volume tersebut pada /usr/share/nginx/html.

Pada shell kamu, buatlah berkas index.html dalam direktori /usr/share/nginx/html:

root@shell-demo:/# echo Hello shell demo > /usr/share/nginx/html/index.html 

Pada shell kamu, kirimkan sebuah permintaan (request) GET ke server nginx.

root@shell-demo:/# apt-get update root@shell-demo:/# apt-get install curl root@shell-demo:/# curl localhost 

Keluarannya akan menunjukkan teks yang kamu tulis pada berkas index.html.

Hello shell demo 

Setelah kamu selesai dengan shell kamu, ketiklah exit.

Menjalankan perintah individu di dalam sebuah Container

Pada jendela (window) perintah biasa, bukan pada shell kamu di dalam Container, lihatlah daftar variabel lingkungan (environment variable) pada Container yang sedang berjalan:

kubectl exec shell-demo -- env 

Cobalah dengan menjalankan perintah lainnya. Berikut beberapa contohnya:

kubectl exec shell-demo ps aux kubectl exec shell-demo ls / kubectl exec shell-demo cat /proc/1/mounts 

Membuka sebuah shell ketika sebuah Pod memiliki lebih dari satu Container

Jika sebuah Pod memiliki lebih dari satu Container, gunakanlah --container atau -c untuk menentukan Container yang dimaksud pada perintah kubectl exec. Sebagai contoh, misalkan kamu memiliki Pod yang bernama my-pod, dan Pod tersebut memiliki dua Container yang bernama main-app dan helper-app. Perintah berikut ini akan membuka sebuah shell ke Container dengan nama main-app.

kubectl exec -it my-pod --container main-app -- /bin/bash 

Selanjutnya

9.3 - Perangkat untuk Memantau Sumber Daya

Untuk melukan penyekalaan aplikasi dan memberikan Service yang handal, kamu perlu memahami bagaimana aplikasi berperilaku ketika aplikasi tersebut digelar (deploy). Kamu bisa memeriksa kinerja aplikasi dalam klaster Kubernetes dengan memeriksa Container, Pod, Service, dan karakteristik klaster secara keseluruhan. Kubernetes memberikan detail informasi tentang penggunaan sumber daya dari aplikasi pada setiap level ini. Informasi ini memungkinkan kamu untuk mengevaluasi kinerja aplikasi kamu dan mengevaluasi di mana kemacetan dapat dihilangkan untuk meningkatkan kinerja secara keseluruhan.

Di Kubernetes, pemantauan aplikasi tidak bergantung pada satu solusi pemantauan saja. Pada klaster baru, kamu bisa menggunakan pipeline metrik sumber daya atau pipeline metrik penuh untuk mengumpulkan statistik pemantauan.

Pipeline Metrik Sumber Daya

Pipeline metrik sumber daya menyediakan sekumpulan metrik terbatas yang terkait dengan komponen-komponen klaster seperti controller HorizontalPodAutoscaler, begitu juga dengan utilitas kubectl top. Metrik ini dikumpulkan oleh memori yang ringan, jangka pendek, dalam metrics-server dan diekspos ke API metrics.k8s.io.

Metrics-server menemukan semua Node dalam klaster dan bertanya ke setiap kubelet dari Node tentang penggunaan CPU dan memori. Kubelet bertindak sebagai jembatan antara control plane Kubernetes dan Node, mengelola Pod dan Container yang berjalan pada sebuah mesin. Kubelet menerjemahkan setiap Pod ke Container yang menyusunnya dan mengambil masing-masing statistik penggunaan untuk setiap Container dari runtime Container melalui antarmuka runtime Container. Kubelet mengambil informasi ini dari cAdvisor yang terintegrasi untuk pengintegrasian Docker yang lama. Hal ini yang kemudian memperlihatkan statistik penggunaan sumber daya dari kumpulan Pod melalui API sumber daya metrics-server. API ini disediakan pada /metrics/resource/v1beta1 pada kubelet yang terautentikasi dan porta read-only.

Pipeline Metrik Penuh

Pipeline metrik penuh memberi kamu akses ke metrik yang lebih banyak. Kubernetes bisa menanggapi metrik ini secara otomatis dengan mengubah skala atau mengadaptasi klaster berdasarkan kondisi saat ini, dengan menggunakan mekanisme seperti HorizontalPodAutoscaler. Pipeline pemantauan mengambil metrik dari kubelet dan kemudian memgekspos ke Kubernetes melalui adaptor dengan mengimplementasikan salah satu dari API custom.metrics.k8s.io atau API external.metrics.k8s.io.

Prometheus, sebuah proyek CNCF, yang dapat secara alami memonitor Kubernetes, Node, dan Prometheus itu sendiri. Proyek pipeline metrik penuh yang bukan merupakan bagian dari CNCF berada di luar ruang lingkup dari dokumentasi Kubernetes.

10 - TLS

10.1 - Kelola Sertifikat TLS Pada Klaster

Kubernetes menyediakan API certificates.k8s.io yang memungkinkan kamu membuat sertifikat TLS yang ditandatangani oleh Otoritas Sertifikat (CA) yang kamu kendalikan. CA dan sertifikat ini bisa digunakan oleh workload untuk membangun kepercayaan.

API certificates.k8s.io menggunakan protokol yang mirip dengan konsep ACME.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Mempercayai TLS dalam Klaster

Mempercayai CA khusus dari aplikasi yang berjalan sebagai Pod biasanya memerlukan beberapa tambahan konfigurasi aplikasi. Kamu harus menambahkan bundel sertifikat CA ke daftar sertifikat CA yang dipercaya klien atau server TLS. Misalnya, kamu akan melakukan ini dengan konfigurasi TLS golang dengan mengurai rantai sertifikat dan menambahkan sertifikat yang diurai ke RootCAs di struct tls.Config.

Kamu bisa mendistribusikan sertifikat CA sebagai sebuah ConfigMap yang bisa diakses oleh Pod kamu.

Meminta Sertifikat

Bagian berikut mendemonstrasikan cara membuat sertifikat TLS untuk sebuah Service kubernetes yang diakses melalui DNS.

Unduh dan Pasang CFSSL

Contoh ini menggunakan cfssl yang dapat diunduh pada https://github.com/cloudflare/cfssl/releases.

Membuat CertificateSigningRequest

Buat kunci pribadi dan CertificateSigningRequest (CSR) dengan menggunakan perintah berikut:

cat <<EOF | cfssl genkey - | cfssljson -bare server {  "hosts": [  "my-svc.my-namespace.svc.cluster.local",  "my-pod.my-namespace.pod.cluster.local",  "192.0.2.24",  "10.0.34.2"  ],  "CN": "my-pod.my-namespace.pod.cluster.local",  "key": {  "algo": "ecdsa",  "size": 256  } } EOF 

192.0.2.24 adalah klaster IP Service, my-svc.my-namespace.svc.cluster.local adalah nama DNS Service, 10.0.34.2 adalah IP Pod dan my-pod.my-namespace.pod.cluster.local adalah nama DNS Pod. Kamu akan melihat keluaran berikut:

2017/03/21 06:48:17 [INFO] generate received request 2017/03/21 06:48:17 [INFO] received CSR 2017/03/21 06:48:17 [INFO] generating key: ecdsa-256 2017/03/21 06:48:17 [INFO] encoded CSR 

Perintah ini menghasilkan dua berkas; Ini menghasilkan server.csr yang berisi permintaan sertifikasi PEM tersandi pkcs#10, dan server-key.pem yang berisi PEM kunci yang tersandi untuk sertifikat yang masih harus dibuat.

Membuat objek CertificateSigningRequest untuk dikirim ke API Kubernetes

Buat sebuah yaml CSR dan kirim ke API Server dengan menggunakan perintah berikut:

cat <<EOF | kubectl apply -f - apiVersion: certificates.k8s.io/v1beta1 kind: CertificateSigningRequest metadata:  name: my-svc.my-namespace spec:  request: $(cat server.csr | base64 | tr -d '\n')  usages:  - digital signature  - key encipherment  - server auth EOF 

Perhatikan bahwa berkas server.csr yang dibuat pada langkah 1 merupakan base64 tersandi dan disimpan di field .spec.request. Kami juga meminta sertifikat dengan penggunaan kunci "digital signature", "key enchiperment", dan "server auth". Kami mendukung semua penggunaan kunci dan penggunaan kunci yang diperpanjang yang terdaftar di sini sehingga kamu dapat meminta sertifikat klien dan sertifikat lain menggunakan API yang sama.

CSR semestinya bisa dilihat dari API pada status Pending. Kamu bisa melihatnya dengan menjalankan:

kubectl describe csr my-svc.my-namespace 
Name: my-svc.my-namespace Labels: <none> Annotations: <none> CreationTimestamp: Tue, 21 Mar 2017 07:03:51 -0700 Requesting User: yourname@example.com Status: Pending Subject: Common Name: my-svc.my-namespace.svc.cluster.local Serial Number: Subject Alternative Names: DNS Names: my-svc.my-namespace.svc.cluster.local IP Addresses: 192.0.2.24 10.0.34.2 Events: <none> 

Mendapatkan Persetujuan CertificateSigningRequest

Penyetujuan CertificateSigningRequest dapat dilakukan dengan otomatis atau dilakukan sekali oleh administrator klaster. Informasi lebih lanjut tentang apa yang terjadi dibahas dibawah ini.

Unduh dan Gunakan Sertifikat

Setelah CSR ditandatangani dan disetujui, kamu akan melihat:

kubectl get csr 
NAME AGE REQUESTOR CONDITION my-svc.my-namespace 10m yourname@example.com Approved,Issued 

Kamu bisa mengundur sertifikat yang telah diterbitkan dan menyimpannya ke berkas server.crt dengan menggunakan perintah berikut:

kubectl get csr my-svc.my-namespace -o jsonpath='{.status.certificate}' \  | base64 --decode > server.crt 

Sekarang kamu bisa menggunakan server.crt dan server-key.pem sebagai pasangan kunci untuk memulai server HTTPS kamu.

Penyetujuan CertificateSigningRequest

Administrator Kubernetes (dengan izin yang cukup) dapat menyetujui secara manual (atau menolak) Certificate Signing Requests dengan menggunakan perintah kubectl certificate approve dan kubectl certificate deny. Namun jika kamu bermaksud untuk menggunakan API ini secara sering, kamu dapat mempertimbangkan untuk menulis Certificate controller otomatis.

Baik itu mesin atau manusia yang menggunakan kubectl seperti di atas, peran pemberi persetujuan adalah untuk memverifikasi bahwa CSR memenuhi dua persyaratan:

  1. Subjek CSR mengontrol kunci pribadi yang digunakan untuk menandatangani CSR. Ini mengatasi ancaman pihak ketiga yang menyamar sebagai subjek resmi. Pada contoh di atas, langkah ini adalah untuk memverifikasi bahwa Pod mengontrol kunci pribadi yang digunakan untuk menghasilkan CSR.
  2. Subjek CSR berwenang untuk bertindak dalam konteks yang diminta. Ini mengatasi ancaman subjek yang tidak diinginkan bergabung dengan klaster. Dalam contoh di atas, langkah ini untuk memverifikasi bahwa Pod diizinkan berpartisipasi dalam Service yang diminta.

Jika dan hanya jika kedua persyaratan ini dipenuhi, pemberi persetujuan harus menyetujui CSR dan sebaliknya harus menolak CSR.

Peringatan tentang Izin Persetujuan

Kemampuan untuk menyetujui CSR menentukan siapa yang mempercayai siapa di dalam lingkungan kamu. Kemampuan untuk menyetujui CSR tersebut seharusnya tidak diberikan secara luas. Persyaratan tantangan yang disebutkan di bagian sebelumnya dan dampak dari mengeluarkan sertifikat khusus, harus sepenuhnya dipahami sebelum memberikan izin ini.

Catatan Untuk Administrator Klaster

Tutorial ini mengasumsikan bahwa penanda tangan diatur untuk melayani API sertifikat. Kubernetes controller manager menyediakan implementasi bawaan dari penanda tangan. Untuk mengaktifkan, berikan parameter --cluster-signed-cert-file dan --cluster-signed-key-file ke controller manager dengan path ke pasangan kunci CA kamu.

11 - Mengelola Daemon Klaster

Melakukan tugas-tugas umum untuk mengelola sebuah DaemonSet, misalnya rolling update.

11.1 - Melakukan Rollback pada DaemonSet

Laman ini memperlihatkan bagaimana caranya untuk melakukan rollback pada sebuah DaemonSet.

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Kubernetes servermu harus dalam versi yang sama atau lebih baru dari 1.7.

Untuk melihat versi, tekan kubectl version.

Sebelum lanjut, alangkah baiknya jika kamu telah mengetahui cara untuk melakukan rolling update pada sebuah DaemonSet.

Melakukan rollback pada DaemonSet

Langkah 1: Dapatkan nomor revisi DaemonSet yang ingin dikembalikan

Lompati langkah ini jika kamu hanya ingin kembali (rollback) ke revisi terakhir.

Perintah di bawah ini akan memperlihatkan daftar semua revisi dari DaemonSet:

kubectl rollout history daemonset <nama-daemonset> 

Perintah tersebut akan menampilkan daftar revisi seperti di bawah:

daemonsets "<nama-daemonset>" REVISION CHANGE-CAUSE 1 ... 2 ... ... 
  • Alasan perubahan (change cause) kolom di atas merupakan salinan dari anotasi kubernetes.io/change-cause yang berkaitan dengan revisi pada DaemonSet. Kamu boleh menyetel flag --record=true melalui kubectl untuk merekam perintah yang dijalankan akibat dari anotasi alasan perubahan.

Untuk melihat detail dari revisi tertentu, jalankan perintah di bawah ini:

kubectl rollout history daemonset <daemonset-name> --revision=1 

Perintah tersebut memberikan detail soal nomor revisi tertentu:

daemonsets "<nama-daemonset>" with revision #1 Pod Template: Labels: foo=bar Containers: app: Image: ... Port: ... Environment: ... Mounts: ... Volumes: ... 

Langkah 2: Rollback ke revisi tertentu

# Tentukan nomor revisi yang kamu dapatkan dari Langkah 1 melalui --to-revision kubectl rollout undo daemonset <nama-daemonset> --to-revision=<nomor-revisi> 

Jika telah berhasil, perintah tersebut akan memberikan keluaran berikut:

daemonset "<nama-daemonset>" rolled back 

Langkah 3: Lihat progres pada saat rollback DaemonSet

Perintah kubectl rollout undo daemonset memberitahu server untuk memulai rollback DaemonSet. Rollback sebenarnya terjadi secara asynchronous di dalam klaster _control plane_.

Perintah di bawah ini dilakukan untuk melihat progres dari rollback:

kubectl rollout status ds/<nama-daemonset> 

Ketika rollback telah selesai dilakukan, keluaran di bawah akan ditampilkan:

daemonset "<nama-daemonset>" successfully rolled out 

Memahami revisi DaemonSet

Pada langkah kubectl rollout history sebelumnya, kamu telah mendapatkan daftar revisi DaemonSet. Setiap revisi disimpan di dalam sumber daya bernama ControllerRevision.

Untuk melihat apa yang disimpan pada setiap revisi, dapatkan sumber daya mentah (raw) dari revisi DaemonSet:

kubectl get controllerrevision -l <kunci-selektor-daemonset>=<nilai-selektor-daemonset> 

Perintah di atas akan mengembalikan daftar ControllerRevision:

NAME CONTROLLER REVISION AGE <nama-daemonset>-<hash-revisi> DaemonSet/<nama-daemonset> 1 1h <nama-daemonset>-<hash-revisi> DaemonSet/<nama-daemonset> 2 1h 

Setiap ControllerRevision menyimpan anotasi dan templat dari sebuah revisi DaemonSet.

Perintah kubectl rollout undo mengambil ControllerRevision yang spesifik dan mengganti templat DaemonSet dengan templat yang tersimpan pada ControllerRevision. Perintah kubectl rollout undo sama seperti untuk memperbarui templat DaemonSet ke revisi sebelumnya dengan menggunakan perintah lainnya, seperti kubectl edit atau kubectl apply.

Troubleshoot