This the multi-page printable view of this section. Click here to print.
Dokumentasi
- 1: Dokumentasi Kubernetes
- 2: Persiapan
- 2.1: Lingkungan Pembelajaran
- 2.2: Lingkungan Produksi
- 2.3: Praktek-praktek Terbaik
- 3: Konsep
- 3.1: Ikhtisar
- 3.1.1: Apa itu Kubernetes?
- 3.1.2: Komponen-Komponen Kubernetes
- 3.1.3: API Kubernetes
- 3.1.4: Menggunakan Objek-Objek Kubernetes
- 3.1.4.1: Memahami Konsep Objek-Objek yang ada pada Kubernetes
- 3.1.4.2: Pengaturan Objek Kubernetes
- 3.1.4.3: Nama
- 3.1.4.4: Namespace
- 3.1.4.5: Label dan Selektor
- 3.1.4.6: Anotasi
- 3.1.4.7: Selektor Field
- 3.1.4.8: Label yang Disarankan
- 3.2: Arsitektur Kubernetes
- 3.2.1: Node
- 3.2.2: Komunikasi antara Control Plane dan Node
- 3.2.3: Controller
- 3.2.4: Konsep-konsep di balik Controller Manager
- 3.3: Kontainer
- 3.3.1: Ikhtisar Kontainer
- 3.3.2: Image
- 3.3.3: Kontainer Environment
- 3.3.4: Runtime Class
- 3.3.5: Lifecyle Hook pada Kontainer
- 3.4: Workloads
- 3.4.1: Pods
- 3.4.1.1: Pengenalan Pod
- 3.4.1.2: Pod
- 3.4.1.3: Siklus Hidup Pod
- 3.4.1.4: Init Container
- 3.4.1.5: Batasan Persebaran Topologi Pod
- 3.4.1.6: Pod Preset
- 3.4.1.7: Disrupsi
- 3.4.1.8: Kontainer Sementara (Ephemeral)
- 3.4.2: Controllers
- 3.4.2.1: ReplicaSet
- 3.4.2.2: ReplicationController
- 3.4.2.3: Deployment
- 3.4.2.4: StatefulSet
- 3.4.2.5: DaemonSet
- 3.4.2.6: Garbage Collection
- 3.4.2.7: Pengendali TTL untuk Sumber Daya yang Telah Selesai Digunakan
- 3.4.2.8: Jobs
- 3.4.2.9: CronJob
- 3.5: Services, Load Balancing, dan Jaringan
- 3.5.1: Service
- 3.5.2: Topologi Service (Service Topology)
- 3.5.3: EndpointSlice
- 3.5.4: DNS untuk Service dan Pod
- 3.5.5: Menghubungkan aplikasi dengan Service
- 3.5.6: Ingress
- 3.5.7: Kontroler Ingress
- 3.5.8: NetworkPolicy
- 3.5.9: Menambahkan Entry pada /etc/hosts Pod dengan HostAliases
- 3.5.10: Dual-stack IPv4/IPv6
- 3.6: Storage
- 3.6.1: Volume
- 3.6.2: Persistent Volume
- 3.6.3: VolumeSnapshot
- 3.6.4: Pengklonaan Volume CSI
- 3.6.5: StorageClass
- 3.6.6: VolumeSnapshotClass
- 3.6.7: Penyediaan Volume Dinamis
- 3.6.8: Limit Volume yang Spesifik terhadap Node
- 3.7: Konfigurasi
- 3.7.1: Konfigurasi dan Penerapan Konsep
- 3.7.2: Mengatur Sumber Daya Komputasi untuk Container
- 3.7.3: Secret
- 3.7.4: Mengatur Akses Klaster Menggunakan Berkas kubeconfig
- 3.7.5: Prioritas dan Pemindahan Pod
- 3.8: Keamanan
- 3.9: Penjadwalan dan Pengusiran
- 3.9.1: Bin Packing Sumber Daya untuk Sumber Daya Tambahan
- 3.9.2: Overhead Pod
- 3.9.3: Menetapkan Pod ke Node
- 3.9.4: Taint dan Toleration
- 3.9.5: Penjadwal Kubernetes
- 3.9.6: Kerangka Kerja Penjadwalan (Scheduling Framework)
- 3.9.7: Penyetelan Kinerja Penjadwal
- 3.10: Policies
- 3.10.1: LimitRange
- 3.10.2: Resource Quota
- 3.10.3: Pod Security Policy
- 3.11: Administrasi Klaster
- 3.11.1: Ikhtisar Administrasi Klaster
- 3.11.2: Sertifikat
- 3.11.3: Penyedia Layanan Cloud
- 3.11.4: Mengelola Resource
- 3.11.5: Jaringan Kluster
- 3.11.6: Arsitektur Logging
- 3.11.7: Metrik untuk Komponen Sistem Kubernetes
- 3.11.8: Konfigurasi Garbage Collection pada kubelet
- 3.11.9: Federation
- 3.11.10: Berbagai Proxy di Kubernetes
- 3.11.11: Metrik controller manager
- 3.11.12: Instalasi Add-ons
- 3.11.13: Prioritas dan Kesetaraan API (API Priority and Fairness)
- 3.12: Memperluas Kubernetes
- 3.12.1: Memperluas Klaster Kubernetes Kamu
- 3.12.2: Memperluas API Kubernetes
- 3.12.2.1: Memperluas Kubernetes API dengan Lapisan Agregasi
- 3.12.2.2: Custom Resource
- 3.12.3: Ekstensi Komputasi, Penyimpanan, dan Jaringan
- 3.12.3.1: Plugin Jaringan
- 3.12.3.2: Plugin Perangkat
- 3.12.4: Pola Operator
- 3.12.5: Service Catalog
- 3.12.6: Poseidon-Firmament - Sebuah Penjadwal Alternatif
- 4: Tugas
- 4.1: Menginstal Peralatan
- 4.2: Menjalankan Tugas-Tugas Otomatis dengan CronJob
- 4.3: Mengatur Pod dan Kontainer
- 4.3.1: Menetapkan Sumber Daya Memori untuk Container dan Pod
- 4.3.2: Konfigurasi Quality of Service untuk Pod
- 4.3.3: Mengatur Pod untuk Menggunakan Volume sebagai Tempat Penyimpanan
- 4.3.4: Mengatur Pod untuk Penyimpanan dengan PersistentVolume
- 4.3.5: Mengonfigurasi Konteks Keamanan untuk Pod atau Container
- 4.3.6: Mengatur ServiceAccount untuk Pod
- 4.3.7: Menarik Image dari Register Pribadi
- 4.3.8: Mengatur Probe Liveness, Readiness dan Startup
- 4.3.9: Menempatkan Pod pada Node Menggunakan Afinitas Pod
- 4.3.10: Mengatur Pod untuk Menggunakan ConfigMap
- 4.3.11: Pembagian Namespace Proses antar Container pada sebuah Pod
- 4.3.12: Membuat Pod Statis
- 4.4: Mengelola Sebuah Klaster
- 4.4.1: Menggunakan Calico untuk NetworkPolicy
- 4.4.2: Mengelola Memori, CPU, dan Sumber Daya API
- 4.4.3: Debugging Resolusi DNS
- 4.4.4: Kustomisasi Service DNS
- 4.4.5: Melakukan Reservasi Sumber Daya Komputasi untuk Daemon Sistem
- 4.4.6: Membagi sebuah Klaster dengan Namespace
- 4.4.7: Mengatur Control Plane Kubernetes dengan Ketersediaan Tinggi (High-Availability)
- 4.4.8: Menggunakan sysctl dalam Sebuah Klaster Kubernetes
- 4.4.9: Mengoperasikan klaster etcd untuk Kubernetes
- 4.5: Mengelola Objek Kubernetes
- 4.5.1: Pengelolaan Objek Kubernetes secara Deklaratif dengan Menggunakan Berkas Konfigurasi
- 4.5.2: Mengelola Objek Kubernetes secara Deklaratif menggunakan Kustomize
- 4.5.3: Pengelolaan Objek Kubernetes dengan Perintah Imperatif
- 4.5.4: Pengelolaan Objek Kubernetes Secara Imperatif dengan Menggunakan File Konfigurasi
- 4.6: Memasukkan Data ke dalam Aplikasi
- 4.6.1: Mendefinisikan Perintah dan Argumen untuk sebuah Kontainer
- 4.6.2: Mendefinisikan Variabel Lingkungan untuk sebuah Kontainer
- 4.6.3: Mendistribusikan Kredensial dengan Aman Menggunakan Secret
- 4.7: Menjalankan
- 4.7.1: Menjalankan Aplikasi Stateless Menggunakan Deployment
- 4.7.2: Menghapus Paksa Pod StatefulSet
- 4.7.3: HorizontalPodAutoscaler
- 4.7.4: Panduan HorizontalPodAutoscaler
- 4.8: Mengakes Aplikasi-aplikasi di sebuah Klaster
- 4.8.1: Antarmuka Pengguna Berbasis Web (Dashboard)
- 4.8.2: Mengakses Klaster
- 4.8.3: Mengkonfigurasi Akses ke Banyak Klaster
- 4.8.4: Menggunakan Port Forwarding untuk Mengakses Aplikasi di sebuah Klaster
- 4.8.5: Membuat Load Balancer Eksternal
- 4.8.6: Membuat Daftar Semua Image Container yang Berjalan dalam Klaster
- 4.9: Pemantauan, Pencatatan, and Debugging
- 4.9.1: Introspeksi dan _Debugging_ Aplikasi
- 4.9.2: Mendapatkan Shell Untuk Masuk ke Container yang Sedang Berjalan
- 4.9.3: Perangkat untuk Memantau Sumber Daya
- 4.10: TLS
- 4.11: Mengelola Daemon Klaster
- 5: Tutorial
- 5.1: Halo Minikube
- 5.2: Mempelajari Panduan Dasar Kubernetes
- 5.2.1: Membuat Klaster
- 5.2.2: Menyebarkan (Deploy) Aplikasi
- 5.2.2.1: Menggunakan kubectl untuk membuat Deployment
- 5.2.2.2: Tutorial Interaktif - Menyebarkan (Deploy) Aplikasi
- 5.2.3: Menjelajahi Aplikasimu
- 5.2.3.1: Melihat Pod dan Node
- 5.2.3.2: Tutorial Interaktif - Menjelajahi Aplikasimu
- 5.2.4: Mengekspos Aplikasimu Secara Publik
- 5.2.4.1: Menggunakan Service untuk Mengekspos Aplikasimu
- 5.2.4.2: Tutorial Interaktif - Mengekspos Aplikasimu
- 5.2.5: Penyekalaan Aplikasimu
- 5.2.5.1: Menjalankan Multipel Instans dari Aplikasimu
- 5.2.5.2: Tutorial Interaktif - Penyekalaan Aplikasimu
- 5.2.6: Memperbarui Aplikasimu
- 5.2.6.1: Melakukan Pembaruan Bertahap
- 5.2.6.2: Tutorial Interaktif - Memperbarui Aplikasimu
- 5.3: Aplikasi Stateless
- 5.4: Aplikasi Stateful
- 5.4.1: Dasar-dasar StatefulSet
- 6: Referensi
- 6.1: Glosarium
- 6.2: Mengakses API
- 6.2.1: Menggunakan Otorisasi RBAC
- 6.3: Baris Perintah kubectl
- 6.3.1: Contekan kubectl
- 7: Berkontribusi ke Dokumentasi Kubernetes
1 - Dokumentasi Kubernetes
1.1 - Versi Dokumentasi yang Tersedia
Situs web ini berisi dokumentasi untuk versi terkini Kubernetes dan empat versi sebelumnya.
2 - Persiapan
Bagian ini mencantumkan berbagai cara untuk menyiapkan dan menjalankan Kubernetes. Ketika kamu menginstal Kubernetes, pilih tipe instalasi berdasarkan: kemudahan perawatan, keamanan, sumber daya yang tersedia, dan keahlian yang dibutuhkan untuk mengoperasikan dan mengelola klaster.
Kamu dapat menggelar klaster Kubernetes di mesin lokal, cloud, datacenter di tempat, atau pilih klaster Kubernetes yang dikelola. Ada juga solusi khusus di berbagai penyedia cloud, atau lingkungan baremetal.
Lingkungan Pembelajaran
Jika kamu sedang belajar Kubernetes, gunakan alat yang didukung oleh komunitas Kubernetes, atau alat di ekosistem untuk menyiapkan klaster Kubernetes di mesin lokal.
Lingkungan Produksi
Pada saat mengevaluasi sebuah solusi untuk lingkungan produksi, pertimbangkan aspek dari pengoperasian klaster Kubernetes (atau abstractions) yang ingin kamu kelola atau membiarkan penyedia.
Kubernetes Partners termasuk dari daftar dari penyedia Certified Kubernetes.
2.1 - Lingkungan Pembelajaran
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 agar kind
dapat
berjalan dan bekerja.
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.
2.2 - Lingkungan Produksi
2.2.1 - Runtime Container
Kubernetes v1.6 [stable]
Untuk menjalankan Container di Pod, Kubernetes menggunakan runtime Container (Container runtimes). Berikut ini adalah petunjuk instalasi untuk berbagai macam runtime.
Sebuah kekurangan ditemukan dalam cara runc
menangani pendeskripsi berkas (file) sistem ketika menjalankan Container.
Container yang berbahaya dapat menggunakan kekurangan ini untuk menimpa konten biner runc
dan
akibatnya Container tersebut dapat menjalankan perintah yang sewenang-wenang pada sistem host dari Container tersebut.
Silahkan merujuk pada CVE-2019-5736 untuk informasi lebih lanjut tentang masalah ini.
Penerapan
Kamu harus menjalankan semua perintah dalam panduan ini sebagai root
. Sebagai contoh, awali perintah
dengan sudo
, atau masuk sebagai root
dan kemudian baru menjalankan perintah sebagai pengguna root
.
Driver cgroup
Ketika systemd dipilih sebagai sistem init untuk sebuah distribusi Linux, proses init menghasilkan
dan menggunakan grup kontrol root (cgroup
) dan proses ini akan bertindak sebagai manajer cgroup. Systemd memiliki integrasi yang ketat
dengan cgroup dan akan mengalokasikan cgroups untuk setiap proses. Kamu dapat mengonfigurasi
runtime Container dan kubelet untuk menggunakan cgroupfs
. Menggunakan cgroupfs
bersama dengan systemd berarti
akan ada dua manajer cgroup yang berbeda.
Cgroup digunakan untuk membatasi sumber daya yang dialokasikan untuk proses.
Sebuah manajer cgroup tunggal akan menyederhanakan pandangan tentang sumber daya apa yang sedang dialokasikan
dan secara bawaan (default) akan memiliki pandangan yang lebih konsisten tentang sumber daya yang tersedia dan yang sedang digunakan. Ketika kita punya memiliki
dua manajer maka kita pun akan memiliki dua pandangan berbeda tentang sumber daya tersebut. Kita telah melihat kasus di lapangan
di mana Node yang dikonfigurasi menggunakan cgroupfs
untuk kubelet dan Docker, dan systemd
untuk semua sisa proses yang berjalan pada Node maka Node tersebut akan menjadi tidak stabil di bawah tekanan sumber daya.
Mengubah aturan sedemikian rupa sehingga runtime Container dan kubelet kamu menggunakan systemd
sebagai driver cgroup
akan menstabilkan sistem. Silahkan perhatikan opsi native.cgroupdriver=systemd
dalam pengaturan Docker di bawah ini.
Docker
Pada setiap mesin kamu, mari menginstall Docker. Versi yang direkomendasikan adalah 19.03.11, tetapi versi 1.13.1, 17.03, 17.06, 17.09, 18.06 dan 18.09 juga diketahui bekerja dengan baik. Jagalah versi Docker pada versi terbaru yang sudah terverifikasi pada catatan rilis Kubernetes.
Gunakan perintah berikut untuk menginstal Docker pada sistem kamu:
# (Menginstal Docker CE)
## Mengatur repositori:
### Menginstal packet untuk mengijinkan apt untuk menggunakan repositori melalui HTTPS
apt-get update && apt-get install -y \
apt-transport-https ca-certificates curl software-properties-common gnupg2
# Menambahkan key GPG resmi dari Docker:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
# Menambahkan repositori apt dari Docker:
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
# Menginstal Docker CE
apt-get update && apt-get install -y \
containerd.io=1.2.13-2 \
docker-ce=5:19.03.11~3-0~ubuntu-$(lsb_release -cs) \
docker-ce-cli=5:19.03.11~3-0~ubuntu-$(lsb_release -cs)
# Mengatur daemon Docker
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
# Menjalankan ulang Docker
systemctl daemon-reload
systemctl restart docker
# (Menginstal Docker CE)
## Mengatur repositori
### Menginstal paket yang diperlukan
yum install -y yum-utils device-mapper-persistent-data lvm2
## Menambahkan repositori apt dari Docker
yum-config-manager --add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# Menginstal Docker CE
yum update -y && yum install -y \
containerd.io-1.2.13 \
docker-ce-19.03.11 \
docker-ce-cli-19.03.11
## Membuat berkas /etc/docker
mkdir /etc/docker
# Mengatur daemon Docker
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
# Menjalankan ulang Docker
systemctl daemon-reload
systemctl restart docker
Jika kamu menginginkan layanan Docker berjalan dari saat memulai pertama (boot), jalankan perintah ini:
sudo systemctl enable docker
Silahkan merujuk pada Panduan resmi instalasi Docker untuk informasi lebih lanjut.
CRI-O
Bagian ini mencakup langkah-langkah yang diperlukan untuk menginstal CRI-O
sebagai runtime CRI.
Gunakan perintah-perinath berikut untuk menginstal CRI-O pada sistem kamu:
Prasyarat
modprobe overlay
modprobe br_netfilter
# Mengatur parameter sysctl yang diperlukan, dimana ini akan bernilai tetap setiap kali penjalanan ulang.
cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sysctl --system
# Debian Unstable/Sid
echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_Unstable/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_Unstable/Release.key -O- | sudo apt-key add -
# Debian Testing
echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_Testing/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_Testing/Release.key -O- | sudo apt-key add -
# Debian 10
echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_10/Release.key -O- | sudo apt-key add -
# Raspbian 10
echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Raspbian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Raspbian_10/Release.key -O- | sudo apt-key add -
dan kemudian install CRI-O:
sudo apt-get install cri-o-1.17
# Mengatur repositori paket
. /etc/os-release
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/x${NAME}_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/x${NAME}_${VERSION_ID}/Release.key -O- | sudo apt-key add -
sudo apt-get update
# Menginstal CRI-O
sudo apt-get install cri-o-1.17
# Menginstal prasyarat
curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/CentOS_7/devel:kubic:libcontainers:stable.repo
curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:1.23.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:1.23/CentOS_7/devel:kubic:libcontainers:stable:cri-o:1.23.repo
# Menginstal CRI-O
yum install -y cri-o
sudo zypper install cri-o
Memulai CRI-O
systemctl daemon-reload
systemctl start crio
Silahkan merujuk pada Panduan instalasi CRI-O untuk informasi lanjut.
Containerd
Bagian ini berisi langkah-langkah yang diperlukan untuk menggunakan containerd
sebagai runtime CRI.
Gunakan perintah-perintah berikut untuk menginstal containerd pada sistem kamu:
Prasyarat
cat > /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
# Mengatur parameter sysctl yang diperlukan, dimana ini akan bernilai tetap setiap kali penjalanan ulang.
cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sysctl --system
Menginstal containerd
# (Meninstal containerd)
## Mengatur repositori paket
### Install packages to allow apt to use a repository over HTTPS
apt-get update && apt-get install -y apt-transport-https ca-certificates curl software-properties-common
## Menambahkan key GPG resmi dari Docker:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
## Mengatur repositori paket Docker
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
## Menginstal containerd
apt-get update && apt-get install -y containerd.io
# Mengonfigure containerd
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# Menjalankan ulang containerd
systemctl restart containerd
# (Menginstal containerd)
## Mengatur repositori
### Menginstal paket prasyarat
yum install -y yum-utils device-mapper-persistent-data lvm2
## Menambahkan repositori Docker
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
## Menginstal containerd
yum update -y && yum install -y containerd.io
## Mengonfigurasi containerd
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# Menjalankan ulang containerd
systemctl restart containerd
systemd
Untuk menggunakan driver cgroup systemd
, atur plugins.cri.systemd_cgroup = true
pada /etc/containerd/config.toml
.
Ketika menggunakan kubeadm, konfigurasikan secara manual
driver cgroup untuk kubelet
Runtime CRI yang lainnya: Frakti
Silahkan lihat Panduan cepat memulai Frakti untuk informasi lebih lanjut.
2.2.2 - Menginstal Kubernetes dengan perkakas penyebaran
2.2.2.1 - Menyiapkan klaster dengan kubeadm
2.2.2.1.1 - Menginstal kubeadm
Laman ini menunjukkan cara untuk menginstal kubeadm
.
Untuk informasi mengenai cara membuat sebuah klaster dengan kubeadm setelah kamu melakukan proses instalasi ini, lihat laman Menggunakan kubeadm untuk Membuat Sebuah Klaster.
Sebelum kamu memulai
- Satu mesin atau lebih yang menjalankan:
- Ubuntu 16.04+
- Debian 9+
- CentOS 7
- Red Hat Enterprise Linux (RHEL) 7
- Fedora 25+
- HypriotOS v1.0.1+
- Container Linux (teruji pada versi 1800.6.0)
- 2 GB RAM atau lebih per mesin (kurang dari nilai tersebut akan menyisakan sedikit ruang untuk aplikasi-aplikasimu)
- 2 CPU atau lebih
- Koneksi internet pada seluruh mesin pada klaster (kamu dapat menggunakan internet publik ataupun pribadi)
- Hostname yang unik, alamat MAC, dan product_uuid untuk setiap Node. Lihat di sini untuk detail lebih lanjut.
- Porta tertentu pada mesin. Lihat di sini untuk detail lebih lanjut.
- Swap dinonaktifkan. Kamu HARUS menonaktifkan swap agar kubelet dapat berfungsi dengan baik.
Memastikan alamat MAC dan product_uuid yang unik untuk setiap Node
- Kamu bisa mendapatkan alamat MAC dari antarmuka jaringan menggunakan perintah
ip link
atauifconfig -a
- product_uuid didapatkan dengan perintah
sudo cat /sys/class/dmi/id/product_uuid
Sangat memungkinkan bagi perangkat keras untuk memiliki alamat yang unik, namun beberapa mesin virtual bisa memiliki nilai yang identik. Kubernetes menggunakan nilai-nilai tersebut untuk mengidentifikasi Node-Node secara unik pada klaster. Jika nilai-nilai tersebut tidak unik pada tiap Node, proses instalasi bisa saja gagal.
Memeriksa adaptor jaringan
Jika kamu memiliki lebih dari satu adaptor jaringan, dan komponen Kubernetes tidak dapat dijangkau melalui rute bawaan (default route), kami merekomendasikan kamu untuk menambahkan rute IP sehingga alamat-alamat klaster Kubernetes melewati adaptor yang tepat.
Membuat iptables melihat bridged traffic
Agar iptables pada Node Linux dapat melihat bridged traffic dengan benar, kamu harus memastikan net.bridge.bridge-nf-call-iptables
bernilai 1 pada pengaturan sysctl
, misalnya.
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
Pastikan modul br_netfilter
sudah dimuat sebelum melakukan langkah ini. Hal ini dilakukan dengan menjalankan lsmod | grep br_netfilter
. Untuk memuatnya secara eksplisit gunakan sudo modprobe br_netfilter
.
Untuk detail lebih lanjut, silakan lihat laman Persyaratan Plugin Jaringan.
Memeriksa porta yang dibutuhkan
Node control-plane
Protokol | Arah | Rentang Porta | Kegunaan | Digunakan oleh |
---|---|---|---|---|
TCP | Inbound | 6443* | Kubernetes API server | All |
TCP | Inbound | 2379-2380 | etcd server client API | kube-apiserver, etcd |
TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
TCP | Inbound | 10251 | kube-scheduler | Self |
TCP | Inbound | 10252 | kube-controller-manager | Self |
Node pekerja (worker)
Protokol | Arah | Rentang Porta | Kegunaan | Digunakan oleh |
---|---|---|---|---|
TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
TCP | Inbound | 30000-32767 | NodePort Services† | All |
† Jangkauan porta bawaan untuk Service NodePort.
Angka porta yang ditandai dengan * dapat diganti (overrideable), sehingga kamu harus memastikan porta khusus lainnya yang kamu sediakan juga terbuka.
Meskipun porta etcd turut dituliskan pada Node control-plane, kamu juga bisa menghos klaster etcd-mu sendiri secara eksternal atau pada porta custom.
Plugin jaringan Pod yang kamu gunakan (lihat di bawah) juga mungkin membutuhkan porta tertentu untuk terbuka. Karena hal ini dapat berbeda pada setiap plugin jaringan Pod, silakan lihat dokumentasi plugin mengenai porta yang dibutuhkan.
Menginstal runtime
Untuk menjalankan Container pada Pod, Kubernetes menggunakan _runtime_ Container.
Secara bawaan, Kubernetes menggunakan Container Runtime Interface (CRI) sebagai perantara dengan runtime Container pilihanmu.
Jika kamu tidak menentukan runtime, kubeadm secara otomatis mencoba untuk mendeteksi runtime Container yang terinstal dengan memindai sekumpulan soket domain Unix yang umum digunakan. Tabel berikut menunjukkan runtime Container dan lokasi soketnya:
Runtime | Lokasi domain soket Unix |
---|---|
Docker | /var/run/docker.sock |
containerd | /run/containerd/containerd.sock |
CRI-O | /var/run/crio/crio.sock |
Jika ditemukan Docker dan containerd secara bersamaan, Docker akan terpilih. Hal ini diperlukan karena Docker 18.09 dirilis dengan containerd dan keduanya dapat ditemukan meskipun kamu hanya menginstal Docker. Jika ditemukan selain dari kedua _runtime_ Container tersebut, kubeadm akan berhenti dengan kegagalan.
Komponen kubelet berintegrasi dengan Docker melalui implementasi CRI dockershim
bawaannya.
Lihat runtime Container untuk informasi lebih lanjut.
Secara bawaan, kubeadm menggunakan Docker sebagai runtime Container.
Komponen kubelet berintegrasi dengan Docker melalui implementasi CRI dockershim
bawaannya.
Lihat runtime Container untuk informasi lebih lanjut.
Menginstal kubeadm, kubelet, dan kubectl
Kamu akan menginstal package berikut pada semua mesinmu:
-
kubeadm
: alat untuk mem-bootstrap klaster. -
kubelet
: komponen yang berjalan pada seluruh mesin pada klaster dan memiliki tugas seperti menjalankan Pod dan Container. -
kubectl
: alat untuk berinteraksi dengan klastermu.
Alat kubeadm tidak akan menginstal atau mengelola kubelet
ataupun kubectl
untukmu, jadi kamu harus memastikan
keduanya memiliki versi yang cocok dengan control plane Kubernetes yang akan kamu instal
dengan kubeadm. Jika tidak, ada risiko version skew yang dapat terjadi dan
dapat berujung pada perangai yang bermasalah dan tidak terduga. Namun, satu version skew minor antara
kubelet dan control plane masih diperbolehkan, tetapi versi kubelet tidak boleh melebihi versi API
Server. Sebagai contoh, kubelet yang berjalan pada versi 1.7.0 akan kompatibel dengan API Server versi 1.8.0, tetapi tidak sebaliknya.
Untuk informasi mengenai instalasi kubectl
, lihat Menginstal dan mengatur kubectl.
Untuk informasi lebih lanjut mengenai version skew, lihat:
- Kebijakan version-skew dan versi Kubernetes
- Kebijakan version skew yang spesifik untuk kubeadm
sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF
# Mengatur SELinux menjadi permissive mode (menonaktifkannya secara efektif)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable --now kubelet
Catatan:
-
Mengatur SELinux menjadi permissive mode dengan menjalankan
setenforce 0
dansed ...
menonaktifkannya secara efektif. Hal ini diperlukan untuk mengizinkan Container untuk mengakses filesystem hos, yang dibutuhkan untuk jaringan Pod sebagai contoh. Kamu harus melakukan ini sampai dukungan SELinux ditingkatkan pada kubelet. -
Kamu dapat membiarkan SELinux aktif jika kamu mengetahui cara mengonfigurasinya, tetapi hal tersebut mungkin membutuhkan pengaturan yang tidak didukung oleh kubeadm.
Menginstal plugin CNI (dibutuhkan untuk kebanyakan jaringan Pod):
CNI_VERSION="v0.8.2"
ARCH="amd64"
mkdir -p /opt/cni/bin
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz" | tar -C /opt/cni/bin -xz
Menginstal crictl (dibutuhkan untuk kubeadm / Kubelet Container Runtime Interface (CRI))
CRICTL_VERSION="v1.22.0"
ARCH="amd64"
mkdir -p /opt/bin
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-${ARCH}.tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz
Menginstal kubeadm
, kubelet
, kubectl
dan menambahkan systemd service kubelet
:
RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
mkdir -p /opt/bin
ARCH="amd64"
cd /opt/bin
curl -L --remote-name-all https://storage.googleapis.com/kubernetes-release/release/${RELEASE}/bin/linux/${ARCH}/{kubeadm,kubelet,kubectl}
chmod +x {kubeadm,kubelet,kubectl}
RELEASE_VERSION="v0.2.7"
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubelet/lib/systemd/system/kubelet.service" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service
mkdir -p /etc/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
Mengaktifkan dan menjalankan kubelet
:
systemctl enable --now kubelet
Sekarang kubelet akan melakukan restart setiap beberapa detik, sambil menunggu dalam kondisi crashloop sampai kubeadm memberikan instruksi yang harus dilakukan.
Mengonfigurasi driver cgroup yang digunakan oleh kubelet pada Node control-plane
Ketika menggunakan Docker, kubeadm akan mendeteksi secara otomatis driver cgroup untuk kubelet
dan mengaturnya pada berkas /var/lib/kubelet/config.yaml
pada saat runtime.
Jika kamu menggunakan CRI yang berbeda, kamu harus memodifikasi berkasnya dengan nilai cgroupDriver
yang kamu gunakan, seperti berikut:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: <value>
Harap diperhatikan, kamu hanya perlu melakukannya jika driver cgroup dari CRI pilihanmu
bukanlah cgroupfs
, karena nilai tersebut merupakan nilai bawaan yang digunakan oleh kubelet.
--cgroup-driver
sudah dihilangkan pada kubelet, jika kamu memilikinya pada /var/lib/kubelet/kubeadm-flags.env
atau /etc/default/kubelet
(/etc/sysconfig/kubelet
untuk RPM), silakan hapus dan gunakan KubeletConfiguration
(secara bawaan disimpan di /var/lib/kubelet/config.yaml
).
Kamu harus melakukan restart pada kubelet:
sudo systemctl daemon-reload
sudo systemctl restart kubelet
Deteksi driver cgroup secara otomatis untuk runtime Container lainnya seperti CRI-O dan containerd masih dalam proses pengembangan.
Penyelesaian masalah
Jika kamu menemui kesulitan dengan kubeadm, silakan merujuk pada dokumen penyelesaian masalah.
Selanjutnya
2.2.2.1.2 - Membuat sebuah klaster dengan control-plane tunggal menggunakan kubeadm
Perkakas kubeadm
membantu kamu membuat sebuah klaster Kubernetes minimum yang layak dan sesuai dengan best practice. Bahkan, kamu dapat menggunakan kubeadm
untuk membuat sebuah klaster yang lolos uji Kubernetes Conformance.
kubeadm
juga mendukung fungsi siklus hidup (lifecycle)
klaster lainnya, seperti bootstrap token dan pembaruan klaster (cluster upgrade).
kubeadm
merupakan perkakas yang bagus jika kamu membutuhkan:
- Sebuah cara yang sederhana untuk kamu mencoba Kubernetes, mungkin untuk pertama kalinya.
- Sebuah cara bagi pengguna lama (existing users) untuk mengotomatiskan penyetelan sebuah klaster dan menguji aplikasi mereka.
- Sebuah komponen dasar pada ekosistem lain dan/atau perkakas penginstal lain dengan cakupan yang lebih luas.
Kamu dapat menginstal dan menggunakan kubeadm
pada berbagai macam mesin: laptop milikmu, sekelompok
server di cloud, sebuah Raspberry Pi, dan lain-lain. Baik itu men-deploy pada
cloud ataupun on-premise, kamu dapat mengintegrasikan kubeadm
pada sistem provisioning seperti
Ansible atau Terraform.
Sebelum kamu memulai
Untuk mengikuti panduan ini, kamu membutuhkan:
- Satu mesin atau lebih, yang menjalankan sistem operasi Linux yang kompatibel dengan deb atau rpm; sebagai contoh: Ubuntu atau CentOS.
- 2 GiB atau lebih RAM per mesin--kurang dari nilai tersebut akan menyisakan sedikit ruang untuk aplikasi-aplikasimu.
- Sedikitnya 2 CPU pada mesin yang akan kamu gunakan sebagai Node control-plane.
- Koneksi internet pada seluruh mesin pada klaster. Kamu dapat menggunakan internet publik ataupun pribadi.
Kamu juga harus menggunakan versi kubeadm
yang dapat men-deploy versi
Kubernetes yang ingin kamu gunakan pada klaster barumu.
Kebijakan dukungan versi Kubernetes dan version skew juga berlaku pada kubeadm
dan Kubernetes secara umum.
Periksa kebijakan tersebut untuk mempelajari tentang versi Kubernetes dan kubeadm
mana saja yang didukung. Laman ini ditulis untuk Kubernetes v1.23.
Fitur kubeadm
secara umum berstatus General Availability (GA). Beberapa sub-fitur sedang
berada dalam pengembangan. Implementasi pembuatan klaster dapat berubah
sedikit seiring dengan berevolusinya kubeadm, namun secara umum implementasinya sudah cukup stabil.
kubeadm alpha
, sesuai definisi, didukung pada level alpha.
Tujuan
- Menginstal Kubernetes klaster dengan control-plane tunggal atau klaster dengan ketersediaan tinggi
- Menginstal jaringan Pod pada klaster sehingga Pod dapat berinteraksi satu sama lain
Instruksi
Menginstal kubeadm pada hos
Lihat "Menginstal kubeadm".
Jika kamu sudah menginstal kubeadm sebelumnya, jalankan apt-get update && apt-get upgrade
atau yum update
untuk mendapatkan versi kubeadm paling baru.
Ketika kamu melakukan pembaruan, kubelet melakukan restart setiap beberapa detik sambil menunggu dalam kondisi crashloop sampai kubeadm memberikan perintah yang harus dilakukan. Crashloop ini memang diantisipasi dan normal. Setelah kamu menginisialisasi control-plane, kubelet akan berjalan normal.
Menginisialisasi Node control-plane
Node control-plane adalah mesin dimana komponen-komponen control plane berjalan, termasuk etcd (basis data klaster) dan API Server (yang akan berkomunikasi dengan perkakas command line kubectl.
- (Direkomendasikan) Jika kamu berencana untuk memperbarui klaster
kubeadm
dengan control-plane tunggal menjadi ketersediaan tinggi kamu harus menentukan--control-plane-endpoint
agar mengarah ke endpoint yang digunakan bersama untuk semua Node control-plane. Endpoint tersebut dapat berupa nama DNS atau sebuah alamat IP dari load-balancer. - Pilih add-on jaringan Pod, dan pastikan apakah diperlukan argumen untuk
diberikan pada
kubeadm init
. Tergantung penyedia pihak ketiga yang kamu pilih, kamu mungkin harus mengatur--pod-network-cidr
dengan nilai yang spesifik pada penyedia tertentu. Lihat Menginstal add-on jaringan Pod. - (Opsional) Sejak versi 1.14,
kubeadm
mencoba untuk mendeteksi runtime kontainer pada Linux dengan menggunakan daftar domain socket path yang umum diketahui. Untuk menggunakan runtime kontainer yang berbeda atau jika ada lebih dari satu yang terpasang pada Node yang digunakan, tentukan argumen--cri-socket
padakubeadm init
. Lihat Menginstal runtime. - (Opsional) Kecuali ditentukan sebelumnya,
kubeadm
akan menggunakan antarmuka jaringan yang diasosiasikan dengan default gateway untuk mengatur alamat advertise untuk API Server pada Node control-plane ini. Untuk menggunakan antarmuka jaringan yang berbeda, tentukan argumen--apiserver-advertise-address=<ip-address>
padakubeadm init
. Untuk men-deploy klaster Kubernetes IPv6 menggunakan pengalamatan IPv6, kamu harus menentukan alamat IPv6, sebagai contoh--apiserver-advertise-address=fd00::101
- (Opsional) Jalankan
kubeadm config images pull
sebelumkubeadm init
untuk memastikan konektivitas ke container image registry gcr.io.
Untuk menginisialisasi Node control-plane jalankan:
kubeadm init <args>
Pertimbangan mengenai apiserver-advertise-address dan ControlPlaneEndpoint
Meski --apiserver-advertise-address
dapat digunakan untuk mengatur alamat advertise untuk server
API pada Node control-plane ini, --control-plane-endpoint
dapat digunakan untuk mengatur endpoint yang digunakan bersama
untuk seluruh Node control-plane.
--control-plane-endpoint
tidak hanya mengizinkan alamat IP tetapi juga nama DNS yang dapat dipetakan ke alamat IP.
Silakan hubungi administrator jaringan kamu untuk mengevaluasi solusi-solusi yang mempertimbangkan pemetaan tersebut.
Berikut contoh pemetaannya:
192.168.0.102 cluster-endpoint
Di mana 192.168.0.102
merupakan alamat IP dari Node ini dan cluster-endpoint
merupakan nama DNS custom yang dipetakan pada IP ini.
Hal ini memungkinkan kamu untuk memberikan --control-plane-endpoint=cluster-endpoint
pada kubeadm init
dan memberikan nama DNS yang sama pada
kubeadm join
. Kemudian kamu dapat memodifikasi cluster-endpoint
untuk mengarah pada alamat load-balancer dalam skenario
ketersediaan tinggi (highly availabile).
Mengubah klaster control plane tunggal yang dibuat tanpa --control-plane-endpoint
menjadi klaster dengan ketersediaan tinggi
tidak didukung oleh kubeadm.
Informasi lebih lanjut
Untuk informasi lebih lanjut mengenai argumen-argumen kubeadm init
, lihat panduan referensi kubeadm.
Untuk daftar pengaturan konfigurasi yang lengkap, lihat dokumentasi berkas konfigurasi.
Untuk menyetel komponen-komponen control plane, termasuk pemasangan IPv6 opsional pada liveness probe untuk komponen-komponen control plane dan server etcd, berikan argumen ekstra pada tiap komponen seperti yang didokumentasikan pada argumen-argumen custom.
Untuk menjalankan kubeadm init
lagi, sebelumnya kamu harus membongkar klaster.
Jika kamu menggabungkan sebuah Node dengan arsitektur yang berbeda ke klastermu, pastikan DaemonSets yang di_deploy_ memiliki image kontainer yang mendukung arsitektur tersebut.
Pertama-tama kubeadm init
akan menjalankan sekumpulan precheck untuk memastikan mesin
siap untuk menjalankan Kubernetes. Kumpulan precheck ini menunjukkan peringatan-peringatan dan akan berhenti jika terjadi kesalahan. Kemudian kubeadm init
akan mengunduh dan menginstal komponen-komponen control plane klaster. Hal ini membutuhkan waktu beberapa menit.
Keluaran yang dihasilkan terlihat seperti berikut ini:
[init] Using Kubernetes version: vX.Y.Z
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Activating the kubelet service
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [kubeadm-cp localhost] and IPs [10.138.0.4 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [kubeadm-cp localhost] and IPs [10.138.0.4 127.0.0.1 ::1]
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubeadm-cp kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.138.0.4]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 31.501735 seconds
[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-X.Y" in namespace kube-system with the configuration for the kubelets in the cluster
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "kubeadm-cp" as an annotation
[mark-control-plane] Marking the node kubeadm-cp as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node kubeadm-cp as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: <token>
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
Untuk membuat kubectl bekerja bagi pengguna non-root, jalankan perintah-perintah berikut, yang juga merupakan
bagian dari keluaran kubeadm init
:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Secara alternatif, jika kamu adalah pengguna root
, kamu dapat menjalankan:
export KUBECONFIG=/etc/kubernetes/admin.conf
Buatlah catatan dari perintah kubeadm join
yang dihasilkan kubeadm init
. Kamu
membutuhkan perintah ini untuk menggabungkan Node-Node ke klaster.
Token digunakan untuk otentikasi bersama (mutual authentication) antara Node control-plane dan Node-Node yang
akan bergabung. Token yang didapat di sini bersifat rahasia. Simpan dengan aman, karena siapapun yang memiliki token tersebut
dapat menambahkan Node-Node yang dapat mengotentikasikan diri ke klaster. Kamu dapat menampilkan daftar token,
membuat, dan menghapus token dengan perintah kubeadm token
. Lihat
panduan referensi kubeadm.
Menginstal add-on jaringan Pod
Bagian ini berisi informasi penting mengenai penyetelan jejaring dan urutan deployment. Baca seluruh saran ini dengan saksama sebelum melanjutkan.
Kamu harus men-deploy
add-on jaringan Pod berbasis Container Network Interface
(CNI) sehingga Pod dapat berkomunikasi satu sama lain.
DNS klaster (CoreDNS) tidak akan menyala sebelum jaringan dipasangkan.
-
Perlu diperhatikan bahwa jaringan Pod tidak boleh tumpang tindih dengan jaringan hos manapun: kamu akan menemui beberapa masalah jika terjadi tumpang tindih.
(Jika kamu menemukan adanya bentrokan antara jaringan Pod pilihan plugin jaringan dengan jaringan hos, kamu harus memikirkan blok CIDR yang cocok untuk digunakan, kemudian menggunakannya pada saatkubeadm init
dengan--pod-network-cidr
, atau sebagai penggantinya pada YAML plugin jaringan kamu). -
Secara bawaan,
kubeadm
mengatur klastermu untuk menggunakan dan melaksanakan penggunaan RBAC (role based access control).
Pastikan plugin jaringan Pod mendukung RBAC, dan begitu juga seluruh manifes yang kamu gunakan untuk men-deploy-nya. -
Jika kamu ingin menggunakan IPv6--baik jaringan dual-stack, ataupun jaringan single-stack IPv6 --untuk klastermu, pastikan plugin jaringan Pod mendukung IPv6.
Dukungan IPv6 telah ditambahkan pada CNI sejak v0.6.0.
Beberapa proyek eksternal menyediakan jaringan Pod Kubernetes menggunakan CNI, beberapa di antaranya juga mendukung Network Policy.
Lihat daftar add-on jejaring dan network policy yang tersedia.
Kamu dapat menginstal add-on jaringan Pod dengan perintah berikut pada Node control-plane atau Node yang memiliki kredensial kubeconfig:
kubectl apply -f <add-on.yaml>
Kamu hanya dapat menginstal satu jaringan Pod per klaster. Di bawah ini kamu dapat menemukan instruksi instalasi untuk beberapa plugin jaringan Pod yang populer:
Calico merupakan penyedia jejaring dan network policy. Calico mendukung sekumpulan opsi jejaring yang fleksibel sehingga kamu dapat memilih opsi yang paling efisien untuk situasimu, termasuk jaringan non-overlay dan overlay, dengan atau tanpa BGP. Calico menggunakan mesin yang sama untuk melaksanakan network policy pada hos, Pod, dan (jika menggunakan Istio & Envoy) aplikasi yang berada pada lapisan service mesh. Calico bekerja pada beberapa arsitektur, meliputi amd64
, arm64
, dan ppc64le
.
Secara bawaan, Calico menggunakan 192.168.0.0/16
sebagai CIDR jaringan Pod, namun hal ini dapat diatur pada berkas calico.yaml. Agar Calico dapat bekerja dengan benar, kamu perlu memberikan CIDR yang sama pada perintah kubeadm init
menggunakan opsi --pod-network-cidr=192.168.0.0/16
atau melalui konfigurasi kubeadm.
kubectl apply -f https://docs.projectcalico.org/v3.11/manifests/calico.yaml
Agar Cilium dapat bekerja dengan benar, kamu harus memberikan --pod-network-cidr=10.217.0.0/16
pada kubeadm init
.
Untuk men-deploy Cilium kamu hanya perlu menjalankan:
kubectl create -f https://raw.githubusercontent.com/cilium/cilium/v1.6/install/kubernetes/quick-install.yaml
Ketika seluruh Pod Cilium sudah bertanda READY
, kamu dapat mulai menggunakan klaster.
kubectl get pods -n kube-system --selector=k8s-app=cilium
Keluarannya akan tampil seperti berikut:
NAME READY STATUS RESTARTS AGE
cilium-drxkl 1/1 Running 0 18m
Cilium dapat digunakan sebagai kube-proxy, lihat Kubernetes tanpa kube-proxy.
Untuk informasi lebih lanjut mengenai penggunaan Cilium dengan Kubernetes, lihat panduan Instalasi Kubernetes untuk Cilium.
Contiv-VPP menggunakan CNF vSwitch berbasis FD.io VPP yang dapat diprogram, menawarkan layanan dan jejaring cloud-native yang memiliki banyak fungsi dan berkinerja tinggi.
Contiv-VPP mengimplementasikan Service dan Network Policy Kubernetes pada user space (on VPP).
Silakan merujuk pada panduan pemasangan berikut: Pemasangan Manual Contiv-VPP
Kube-router mengandalkan kube-controller-manager untuk mengalokasikan CIDR Pod untuk Node-Node. Maka dari itu, gunakan kubeadm init
dengan opsi --pod-network-cidr
.
Kube-router menyediakan jejaring Pod, network policy, dan IP Virtual Server(IPVS)/Linux Virtual Server(LVS) berbasis service proxy yang memiliki kinerja tinggi.
Informasi mengenai penggunaan kubeadm
untuk mendirikan klaster Kubernetes dengan Kube-router, dapat dilihat di panduan pemasangan resminya.
Untuk informasi lebih lanjut mengenai pemasangan klaster Kubernetes menggunakan Weave Net, silakan lihat Mengintegrasikan Kubernetes melalui Addon.
Weave Net bekerja pada platform amd64
, arm
, arm64
dan ppc64le
tanpa membutuhkan tindakan ekstra.
Weave Net menyalakan mode hairpin secara bawaan. Hal ini mengizinkan Pod untuk mengakses dirinya sendiri melalui alamat IP Service
jika mereka tidak tahu PodIP miliknya.
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
Setelah jaringan Pod dipasangkan, kamu dapat mengonfirmasi hal tersebut dengan
memastikan Pod CoreDNS berada pada kondisi Running
pada keluaran kubectl get pods --all-namespaces
.
Dan setelah Pod CoreDNS sudah menyala dan berjalan, kamu dapat melanjutkan (pemasangan klaster) dengan menggabungkan Node-Node yang lain.
Jika jaringan belum bekerja atau CoreDNS tidak berada pada kondisi Running
, periksalah/lihatlah
panduan penyelesaian masalah
untuk kubeadm
.
Isolasi Node control plane
Secara bawaan, klaster tidak akan menjadwalkan Pod pada Node control-plane untuk alasan keamanan. Jika kamu ingin Pod dapat dijadwalkan pada Node control-plane, sebagai contoh untuk klaster Kubernetes bermesin-tunggal untuk pengembangan, jalankan:
kubectl taint nodes --all node-role.kubernetes.io/master-
Dengan keluaran seperti berikut:
node "test-01" untainted
taint "node-role.kubernetes.io/master:" not found
taint "node-role.kubernetes.io/master:" not found
Hal ini akan menghapus taint node-role.kubernetes.io/master
pada Node manapun yang
memilikinya, termasuk Node control-plane, sehingga scheduler akan dapat
menjadwalkan Pod di manapun.
Menggabungkan Node-Node
Node adalah tempat beban kerja (Container, Pod, dan lain-lain) berjalan. Untuk menambahkan Node baru pada klaster lakukan hal berikut pada setiap mesin:
- SSH ke mesin
- Gunakan pengguna root (mis.
sudo su -
) - Jalankan perintah hasil keluaran
kubeadm init
. Sebagai contoh:
kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
Jika kamu tidak memiliki token, kamu bisa mendapatkannya dengan menjalankan perintah berikut pada Node control-plane:
kubeadm token list
Keluarannya akan tampil seperti berikut:
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
8ewj1p.9r9hcjoqgajrj4gi 23h 2018-06-12T02:51:28Z authentication, The default bootstrap system:
signing token generated by bootstrappers:
'kubeadm init'. kubeadm:
default-node-token
Secara bawaan, token akan kadaluarsa dalam 24 jam. Jika kamu menggabungkan Node ke klaster setelah token kadaluarsa, kamu dapat membuat token baru dengan menjalankan perintah berikut pada Node control-plane:
kubeadm token create
Keluarannya akan tampil seperti berikut:
5didvk.d09sbcov8ph2amjw
Jika kamu tidak memiliki nilai --discovery-token-ca-cert-hash
, kamu bisa mendapatkannya dengan menjalankan perintah berantai berikut pada Node control-plane:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
Keluaran yang diberikan kurang lebih akan ditampilkan sebagai berikut:
8cb2de97839780a412b93877f8507ad6c94f73add17d5d7058e91741c9d5ec78
<control-plane-host>:<control-plane-port>
, alamat IPv6 harus be ditutup dengan kurung siku, sebagai contoh: [fd00::101]:2073
.
Keluaran yang diberikan kurang lebih akan ditampilkan sebagai berikut:
[preflight] Running pre-flight checks
... (log output of join workflow) ...
Node join complete:
* Certificate signing request sent to control-plane and response
received.
* Kubelet informed of new secure connection details.
Run 'kubectl get nodes' on control-plane to see this machine join.
Beberapa saat kemudian, kamu akan melihat Node tersebut pada keluaran dari kubectl get nodes
ketika dijalankan pada Node control-plane.
(Opsional) Mengendalikan klaster dari mesin selain Node control-plane
Untuk membuat kubectl bekerja pada mesin lain (mis. laptop) agar dapat berbicara dengan klaster, kamu harus menyalin berkas kubeconfig administrator dari Node control-plane ke mesin seperti berikut:
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf get nodes
Contoh di atas mengasumsikan akses SSH dinyalakan untuk root. Jika tidak berlaku
demikian, kamu dapat menyalin berkas admin.conf
untuk dapat diakses oleh pengguna lain
dan scp
menggunakan pengguna lain tersebut.
Berkas admin.conf
memberikan penggunanya privilese (privilege) superuser terhadap klaster.
Berkas ini harus digunakan seperlunya. Untuk pengguna biasa, direkomendasikan
untuk membuat kredensial unik dengan privilese whitelist. Kamu dapat melakukan
ini dengan perintah kubeadm alpha kubeconfig user --client-name <CN>
.
Perintah tersebut akan mencetak berkas KubeConfig ke STDOUT yang harus kamu simpan
ke dalam sebuah berkas dan mendistribusikannya pada para pengguna. Setelah itu, whitelist
privilese menggunakan kubectl create (cluster)rolebinding
.
(Opsional) Memproksi API Server ke localhost
Jika kamu ingin terhubung dengan API Server dari luar klaster kamu dapat menggunakan
kubectl proxy
:
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf proxy
Kini kamu dapat mengakses API Server secara lokal melalui http://localhost:8001/api/v1
Pembongkaran
Jika kamu menggunakan server sekali pakai untuk membuat klaster, sebagai ujicoba, kamu dapat
mematikannya tanpa perlu melakukan pembongkaran. Kamu dapat menggunakan
kubectl config delete-cluster
untuk menghapus referensi lokal ke
klaster.
Namun, jika kamu ingin mengatur ulang klaster secara lebih rapih, pertama-tama kamu harus menguras (drain) Node dan memastikan Node sudah kosong, kemudian mengembalikan pengaturan pada Node kembali seperti semula.
Menghapus Node
Berinteraksi dengan Node control-plane menggunakan kredensial yang sesuai, jalankan:
kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
kubectl delete node <node name>
Lalu, pada Node yang dihapus, atur ulang semua kondisi kubeadm
yang telah dipasang:
kubeadm reset
Proses pengaturan ulang tidak mengatur ulang atau membersihkan kebijakan iptables atau tabel IPVS. Jika kamu ingin mengatur ulang iptables, kamu harus melakukannya secara manual:
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
Jika kamu ingin mengatur ulang tabel IPVS, kamu harus menjalankan perintah berikut:
ipvsadm -C
Jika kamu ingin mengulang dari awal, cukup jalankan kubeadm init
atau kubeadm join
dengan
argumen yang sesuai.
Membersihkan control plane
Kamu dapat menggunakan kubeadm reset
pada hos control plane untuk memicu pembersihan
best-effort.
Lihat dokumentasi referensi kubeadm reset
untuk informasi lebih lanjut mengenai sub-perintah ini dan
opsinya.
Selanjutnya
- Pastikan klaster berjalan dengan benar menggunakan Sonobuoy
- Lihat Memperbaharui klaster kubeadm
untuk detail mengenai pembaruan klaster menggunakan
kubeadm
. - Pelajari penggunaan
kubeadm
lebih lanjut pada dokumentasi referensi kubeadm - Pelajari lebih lanjut mengenai konsep-konsep Kubernetes dan
kubectl
. - Lihat halaman Cluster Networking untuk daftar add-on jaringan Pod yang lebih banyak.
- Lihat daftar add-on untuk mengeksplor add-on lainnya, termasuk perkakas untuk logging, monitoring, network policy, visualisasi & pengendalian klaster Kubernetes.
- Atur bagaimana klaster mengelola log untuk peristiwa-peristiwa klaster dan dari aplikasi-aplikasi yang berjalan pada Pod. Lihat Arsitektur Logging untuk gambaran umum tentang hal-hal yang terlibat.
Umpan balik
- Untuk masalah kekutu (bug), kunjungi kubeadm GitHub issue tracker
- Untuk dukungan, kunjungi kanal Slack #kubeadm
- Kanal Slack umum pengembangan SIG Cluster Lifecycle: #sig-cluster-lifecycle
- SIG Cluster Lifecycle SIG information
- Milis SIG Cluster Lifecycle: kubernetes-sig-cluster-lifecycle
Kebijakan version skew
kubeadm
versi v1.23 dapat men-deploy klaster dengan control plane versi v1.23 atau v1.22.
kubeadm
v1.23 juga dapat memperbarui klaster yang dibuat dengan kubeadm v1.22.
Karena kita tidak dapat memprediksi masa depan, CLI kubeadm v1.23 mungkin atau tidak mungkin dapat men-deploy klaster v1.24.
Sumber daya ini menyediakan informasi lebih lanjut mengenai version skew yang didukung antara kubelet dan control plane, serta komponen Kubernetes lainnya:
- Kebijakan versi and version-skew Kubernetes
- Panduan instalasi spesifik untuk kubeadm
Keterbatasan
Ketahanan klaster
Klaster yang dibuat pada panduan ini hanya memiliki Node control-plane tunggal, dengan basis data etcd tunggal yang berjalan di atasnya. Hal ini berarti jika terjadi kegagalan pada Node control-plane, klaster dapat kehilangan data dan mungkin harus dibuat kembali dari awal.
Solusi:
-
Lakukan back up etcd secara reguler. Direktori data etcd yang dikonfigurasi oleh kubeadm berada di
/var/lib/etcd
pada Node control-plane. -
Gunakan banyak Node control-plane. Kamu dapat membaca Opsi untuk topologi dengan ketersediaan tinggi untuk memilih topologi klaster yang menyediakan ketersediaan lebih tinggi.
Kompatibilitas platform
Package dbm/rpm dan binary kubeadm dibuat untuk amd64, arm (32-bit), arm64, ppc64le, dan s390x mengikuti proposal multi-platform.
Image kontainer multiplatform untuk control plane dan addon juga telah didukung sejak v1.12.
Hanya beberapa penyedia jaringan yang menawarkan solusi untuk seluruh platform. Silakan merujuk pada daftar penyedia jaringan di atas atau dokumentasi dari masing-masing penyedia untuk mencari tahu apakah penyedia tersebut mendukung platform pilihanmu.
Penyelesaian masalah
Jika kamu menemui kesulitan dengan kubeadm, silakan merujuk pada dokumen penyelesaian masalah.
2.2.2.1.3 - Membangun Klaster dengan Ketersediaan Tinggi menggunakan kubeadm
Laman ini menjelaskan dua pendekatan yang berbeda untuk membuat klaster Kubernetes dengan ketersediaan tinggi menggunakan kubeadm:
- Dengan Node control plane yang bertumpuk (stacked). Pendekatan ini membutuhkan sumber daya infrastruktur yang lebih sedikit. Anggota-anggota etcd dan Node control plane diletakkan pada tempat yang sama (co-located).
- Dengan klaster etcd eksternal. Pendekatan ini membutuhkan lebih banyak sumber daya infrastruktur. Node control plane dan anggota etcd berada pada tempat yang berbeda.
Sebelum memulai, kamu harus memikirkan dengan matang pendekatan mana yang paling sesuai untuk kebutuhan aplikasi dan environment-mu. Topik perbandingan berikut menguraikan kelebihan dan kekurangan dari masing-masing pendekatan.
Jika kamu menghadapi masalah dalam pembuatan klaster dengan ketersediaan tinggi, silakan berikan umpan balik pada pelacak isu kubeadm.
Lihat juga dokumentasi pembaruan.
Sebelum kamu memulai
Untuk kedua metode kamu membutuhkan infrastruktur seperti berikut:
- Tiga mesin yang memenuhi kebutuhan minimum kubeadm untuk Node control plane
- Tiga mesin yang memenuhi kebutuhan minimum kubeadm untuk Node worker
- Konektivitas internet pada seluruh mesin di dalam klaster (baik jaringan publik maupun jaringan pribadi)
- Hak akses sudo pada seluruh mesin
- Akses SSH dari satu perangkat ke seluruh Node pada sistem
- Perkakas
kubeadm
dankubelet
diinstal pada seluruh mesin. Perkakaskubectl
bersifat opsional.
Untuk klaster etcd eksternal saja, kamu juga membutuhkan:
- Tiga mesin tambahan untuk anggota-anggota etcd
Langkah pertama untuk kedua metode
Membuat load balancer untuk kube-apiserver
-
Buat sebuah load balancer kube-apiserver dengan sebuah nama yang yang akan mengubah ke dalam bentuk DNS.
-
Pada environment cloud kamu harus meletakkan Node control plane di belakang load balancer yang meneruskan TCP. Load balancer ini mendistribusikan trafik ke seluruh Node control plane pada daftar tujuan. Health check untuk apiserver adalah pengujian TCP pada porta yang didengarkan oleh kube-apiserver (nilai semula
:6443
). -
Tidak direkomendasikan untuk menggunakan alamat IP secara langsung pada environment cloud.
-
Load balancer harus dapat berkomunikasi dengan seluruh Node control plane pada porta yang digunakan apiserver. Load balancer tersebut juga harus mengizinkan trafik masuk pada porta yang didengarkannya.
-
Pastikan alamat load balancer sesuai dengan alamat
ControlPlaneEndpoint
pada kubeadm. -
Baca panduan Opsi untuk Software Load Balancing untuk detail lebih lanjut.
-
-
Tambahkan Node control plane pertama pada load balancer dan lakukan pengujian koneksi:
nc -v LOAD_BALANCER_IP PORT
- Kegalatan koneksi yang ditolak memang diantisipasi karena apiserver belum berjalan. Namun jika mendapat timeout, berarti load balancer tidak dapat berkomunikasi dengan Node control plane. Jika terjadi timeout, lakukan pengaturan ulang pada load balancer agar dapat berkomunikasi dengan Node control plane.
-
Tambahkan Node control plane lainnya pada grup tujuan load balancer.
Node control plane dan etcd bertumpuk (stacked)
Langkah-langkah untuk Node control plane pertama
-
Inisialisasi control plane:
sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
-
Kamu bisa menggunakan opsi
--kubernetes-version
untuk mengatur versi Kubernetes yang akan digunakan. Direkomendasikan untuk menggunakan versi kubeadm, kubelet, kubectl, dan Kubernetes yang sama. -
Opsi
--control-plane-endpoint
harus diatur menuju alamat atau DNS dan porta dari load balancer. -
Opsi
--upload-certs
digunakan untuk mengunggah sertifikat-sertifikat yang harus dibagikan ke seluruh Node control plane pada klaster. Jika sebaliknya, kamu memilih untuk menyalin sertifikat ke seluruh Node control plane sendiri atau menggunakan perkakas automasi, silakan hapus opsi ini dan merujuk ke bagian Distribusi sertifikat manual di bawah.
Catatan: Opsi--config
dan--certificate-key
padakubeadm init
tidak dapat digunakan secara bersamaan, maka dari itu jika kamu ingin menggunakan konfigurasi kubeadm kamu harus menambahkan fieldcertificateKey
pada lokasi pengaturan yang sesuai (berada di bawahInitConfiguration
danJoinConfiguration: controlPlane
).Catatan: Beberapa plugin jaringan CNI membutuhkan pengaturan tambahan, seperti menentukan CIDR IP untuk Pod, meski beberapa lainnya tidak. Lihat dokumentasi jaringan CNI. Untuk menambahkan CIDR Pod, tambahkan opsi--pod-network-cidr
, atau jika kamu menggunakan berkas konfigurasi kubeadm pasang fieldpodSubnet
di bawah objeknetworking
dariClusterConfiguration
.-
Keluaran yang dihasilkan terlihat seperti berikut ini:
... You can now join any number of control-plane node by running the following command on each as a root: kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07 Please note that the certificate-key gives access to cluster sensitive data, keep it secret! As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use kubeadm init phase upload-certs to reload certs afterward. Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
-
Salin keluaran ini pada sebuah berkas teks. Kamu akan membutuhkannya nanti untuk menggabungkan Node control plane dan worker ke klaster.
-
Ketika opsi
--upload-certs
digunakan dengankubeadm init
, sertifikat dari control plane utama akan dienkripsi dan diunggah ke Secretkubeadm-certs
. -
Untuk mengunggah ulang sertifikat dan membuat kunci dekripsi baru, gunakan perintah berikut pada Node control plane yang sudah tergabung pada klaster:
sudo kubeadm init phase upload-certs --upload-certs
-
Kamu juga dapat menentukan
--certificate-key
custom pada saatinit
yang nanti dapat digunakan pada saatjoin
. Untuk membuat kunci tersebut kamu dapat menggunakan perintah berikut:kubeadm alpha certs certificate-key
Catatan: Secretkubeadm-certs
dan kunci dekripsi akan kadaluarsa setelah dua jam.Perhatian: Seperti yang tertera pada keluaran perintah, kunci sertifikat memberikan akses ke data klaster yang bersifat sensitif, jaga kerahasiaannya! -
-
Pasang plugin CNI pilihanmu: Ikuti petunjuk berikut untuk menginstal penyedia CNI. Pastikan konfigurasinya sesuai dengan CIDR Pod yang ditentukan pada berkas konfigurasi kubeadm jika diterapkan.
Pada contoh berikut kami menggunakan Weave Net:
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
-
Tulis perintah berikut dan saksikan Pod komponen-komponen control plane mulai dinyalakan:
kubectl get pod -n kube-system -w
Langkah-langkah selanjutnya untuk Node control plane
Untuk setiap Node control plane kamu harus:
-
Mengeksekusi perintah untuk bergabung yang sebelumnya diberikan pada keluaran
kubeadm init
pada Node pertama. Perintah tersebut terlihat seperti ini:sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
- Opsi
--control-plane
menunjukkankubeadm join
untuk membuat control plane baru. - Opsi
--certificate-key ...
akan membuat sertifikat control plane diunduh dari Secretkubeadm-certs
pada klaster dan didekripsi menggunakan kunci yang diberikan.
- Opsi
Node etcd eksternal
Membangun sebuah klaster dengan Node etcd eksternal memiliki prosedur yang mirip dengan etcd bertumpuk dengan pengecualian yaitu kamu harus setup etcd terlebih dulu, dan kamu harus memberikan informasi etcd pada berkas konfigurasi kubeadm.
Memasang klaster etcd
-
Ikuti petunjuk berikut untuk membangun klaster etcd.
-
Lakukan pengaturan SSH seperti yang dijelaskan di sini.
-
Salin berkas-berkas berikut dari Node etcd manapun pada klaster ke Node control plane pertama:
export CONTROL_PLANE="[email protected]" scp /etc/kubernetes/pki/etcd/ca.crt "${CONTROL_PLANE}": scp /etc/kubernetes/pki/apiserver-etcd-client.crt "${CONTROL_PLANE}": scp /etc/kubernetes/pki/apiserver-etcd-client.key "${CONTROL_PLANE}":
- Ganti nilai
CONTROL_PLANE
denganuser@host
dari mesin control plane pertama.
- Ganti nilai
Mengatur Node control plane pertama
-
Buat sebuah berkas bernama
kubeadm-config.yaml
dengan konten sebagai berikut:apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration kubernetesVersion: stable controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" etcd: external: endpoints: - https://ETCD_0_IP:2379 - https://ETCD_1_IP:2379 - https://ETCD_2_IP:2379 caFile: /etc/kubernetes/pki/etcd/ca.crt certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt keyFile: /etc/kubernetes/pki/apiserver-etcd-client.key
external
untuk etcd
.
Pada kasus ini topologi etcd bertumpuk dikelola secara otomatis.
- Ganti variabel-variabel berikut pada templat konfigurasi dengan nilai yang sesuai untuk klastermu:
- `LOAD_BALANCER_DNS`
- `LOAD_BALANCER_PORT`
- `ETCD_0_IP`
- `ETCD_1_IP`
- `ETCD_2_IP`
Langkah-langkah berikut sama dengan pengaturan pada etcd bertumpuk:
-
Jalankan
sudo kubeadm init --config kubeadm-config.yaml --upload-certs
pada Node ini. -
Tulis perintah untuk bergabung yang didapat dari keluaran ke dalam sebuah berkas teks untuk digunakan nanti.
-
Pasang plugin CNI pilihanmu. Contoh berikut ini untuk Weave Net:
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
Langkah selanjutnya untuk Node control plane lainnya
Langkah-langkah selanjutnya sama untuk pengaturan etcd bertumpuk:
- Pastikan Node control plane pertama sudah diinisialisasi dengan sempurna.
- Gabungkan setiap Node control plane dengan perintah untuk bergabung yang kamu simpan dalam berkas teks. Direkomendasikan untuk menggabungkan Node control plane satu persatu.
- Jangan lupakan bahwa kunci dekripsi dari
--certificate-key
akan kadaluarsa setelah dua jam, pada pengaturan semula.
Tugas-tugas umum setelah menyiapkan control plane
Menginstal worker
Node worker bisa digabungkan ke klaster menggunakan perintah yang kamu simpan sebelumnya
dari keluaran perintah kubeadm init
:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
Distribusi sertifikat manual
Jika kamu memilih untuk tidak menggunakan kubeadm init
dengan opsi --upload-certs
berarti kamu harus
menyalin sertifikat dari Node control plane utama secara manual ke
Node control plane yang akan bergabung.
Ada beberapa cara untuk melakukan hal ini. Pada contoh berikut ini kami menggunakan ssh
dan scp
:
SSH dibutuhkan jika kamu ingin mengendalikan seluruh Node dari satu mesin.
-
Nyalakan ssh-agent pada perangkat utamamu yang memiliki akses ke seluruh Node pada sistem:
eval $(ssh-agent)
-
Tambahkan identitas SSH milikmu ke dalam sesi:
ssh-add ~/.ssh/path_to_private_key
-
Lakukan SSH secara bergantian ke setiap Node untuk memastikan koneksi bekerja dengan baik.
-
Ketika kamu melakukan SSH ke Node, pastikan untuk menambahkan opsi
-A
:ssh -A 10.0.0.7
-
Jika kamu menggunakan sudo pada Node, pastikan kamu menyimpan environment yang ada sehingga penerusan SSH dapat bekerja dengan baik:
sudo -E -s
-
-
Setelah mengatur SSH pada seluruh Node kamu harus menjalankan skrip berikut pada Node control plane pertama setelah menjalankan
kubeadm init
. Skrip ini akan menyalin sertifikat dari Node control plane pertama ke Node control plane lainnya:Pada contoh berikut, ganti
CONTROL_PLANE_IPS
dengan alamat IP dari Node control plane lainnya.USER=ubuntu # dapat disesuaikan CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8" for host in ${CONTROL_PLANE_IPS}; do scp /etc/kubernetes/pki/ca.crt "${USER}"@$host: scp /etc/kubernetes/pki/ca.key "${USER}"@$host: scp /etc/kubernetes/pki/sa.key "${USER}"@$host: scp /etc/kubernetes/pki/sa.pub "${USER}"@$host: scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host: scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host: scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt # Kutip baris berikut jika kamu menggunakan etcd eksternal scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key done
Perhatian: Salinlah hanya sertifikat yang berada pada daftar di atas saja. Perkakas kubeadm akan mengambil alih pembuatan sertifikat lainnya dengan SANs yang dibutuhkan untuk Node control plane yang akan bergabung. Jika kamu menyalin seluruh sertifikat tanpa sengaja, pembuatan Node tambahan dapat gagal akibat tidak adanya SANs yang dibutuhkan. -
Lalu, pada setiap Node control plane yang bergabung kamu harus menjalankan skrip berikut sebelum menjalankan
kubeadm join
. Skrip ini akan memindahkan sertifikat yang telah disalin sebelumnya dari direktori home ke/etc/kubernetes/pki
:USER=ubuntu # dapat disesuaikan mkdir -p /etc/kubernetes/pki/etcd mv /home/${USER}/ca.crt /etc/kubernetes/pki/ mv /home/${USER}/ca.key /etc/kubernetes/pki/ mv /home/${USER}/sa.pub /etc/kubernetes/pki/ mv /home/${USER}/sa.key /etc/kubernetes/pki/ mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/ mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/ mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt # Kutip baris berikut jika kamu menggunakan etcd eksternal mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
2.3 - Praktek-praktek Terbaik
2.3.1 - Menjalankan klaster dalam beberapa zona
Laman ini menjelaskan tentang bagaimana menjalankan sebuah klaster dalam beberapa zona.
Pendahuluan
Kubernetes 1.2 menambahkan dukungan untuk menjalankan sebuah klaster dalam beberapa zona kegagalan (multiple failure zones) (GCE secara sederhana menyebutnya sebagai "zones", AWS menyebutnya sebagai "availability zones", dan di sini kita akan menyebutnya sebagai "zona"). Fitur ini adalah versi sederhana dari fitur federasi klaster yang lebih luas (yang sebelumnya ditujukan pada sebuah nama panggilan yang ramah (affectionate nickname) "Ubernetes"). Federasi klaster yang penuh memungkinkan untuk menggabungkan klaster Kubernetes terpisah, yang berjalan pada wilayah atau penyedia cloud yang berbeda (baik dalam datacenter atau on-premise). Namun banyak pengguna yang ingin menjalankan klaster Kubernetes dengan tingkat ketersediaan yang lebih, dalam beberapa zona dari satu penyedia cloud mereka, dan dukungan inilah yang akhirnya memperbolehkan fitur multi-zona dalam versi Kubernetes 1.2 (sebelumnya fitur ini dikenal dengan nama panggilan "Ubernetes Lite").
Dukungan multi-zona sengaja dibuat terbatas: dimana satu klaster Kubernetes hanya dapat berjalan dalam beberapa zona, tetapi hanya pada wilayah yang sama (dan penyedia cloud yang sama pula). Hanya GCE dan AWS yang saat ini mendukung fitur ini secara otomatis (meskipun cukup mudah untuk menambahkan dukungan serupa untuk penyedia cloud yang lain atau bahkan untuk perangkat baremetal, hanya dengan mengatur label yang sesuai untuk ditambahkan ke Node dan volume).
Fungsionalitas
Ketika Node mulai dijalankan, kubelet secara otomatis menambahkan label informasi pada Node tersebut.
Kubernetes akan menyebarkan Pod secara otomatis dalam sebuah controller replikasi
atau Service lintas Node dalam sebuah klaster zona tunggal (untuk mengurangi dampak
kegagalan). Dengan klaster multi-zona, perilaku penyebaran ini akan
dilanjutkan hingga melintasi zona (untuk mengurangi dampak kegagalan dalam satu zona.) (Ini
dicapai melalui opsi SelectorSpreadPriority
). Hal tersebut adalah untuk upaya penempatan terbaik,
apabila zona pada klaster kamu bersifat heterogen
(mis. jumlah Node yang berbeda, tipe Node yang berbeda, atau
persyaratan sumber daya Pod yag berbeda), yang akan mencegah dengan sempurna
penyebaran Pod kamu untuk melintasi zona yang berbeda. Jika diinginkan, kamu bisa menggunakan
zona yang homogen (jumlah dan jenis Node yang sama) untuk mengurangi
probabilitas penyebaran yang tidak merata.
Pada saat volume persisten dibuat, controller penerima PersistentVolumeLabel
akan secara otomatis menambahkan label zona pada volume tersebut. Penjadwal (melalui
predikat VolumeZonePredicate
) kemudian akan memastikan bahwa Pod yang mengklaim
suatu volume hanya akan ditempatkan pada zona yang sama dengan volume tersebut, karena volume
tidak dapat di-attach melintasi zona yang berbeda.
Batasan
Ada beberapa batasan penting dari dukungan multi-zona:
-
Kami berasumsi bahwa zona yang berbeda terletak secara berdekatan satu sama lain dalam jaringan, jadi kami tidak melakukan routing yang sadar akan zona. Secara khusus, lalu lintas (traffic) yang berjalan melalui Service mungkin melintasi beberapa zona (bahkan ketika beberapa Pod yang mendukung Service itu berada pada zona yang sama dengan klien), dan hal ini dapat menimbulkan latensi dan biaya tambahan.
-
Volume zone-afinity hanya akan bekerja dengan PersistentVolume, dan tidak akan berfungsi apabila kamu secara langsung menentukan volume EBS dalam spesifikasi Pod (misalnya).
-
Klaster tidak dapat melebarkan jangkauan cloud atau region (fungsi ini akan membutuhkan dukungan penuh federasi).
-
Meskipun Node kamu berada dalam beberapa zona, saat ini kube-up hanya membuat satu Node master secara bawaan (default). Karena Service memerlukan ketersediaan (availability) yang tinggi dan dapat mentolerir akan hilangnya sebuah zona, maka control plane diletakkan pada setiap zona. Pengguna yang menginginkan control plane yang memiliki ketersediaan tinggi harus mengikuti instruksi ketersediaan tinggi.
Batasan Volume
Batasan berikut ditunjukkan dengan menggunakan pengikatan volume yang sadar topologi.
-
Penyebaran zona volume StatefulSet yang menggunakan penyediaan secara dinamis, saat ini tidak sesuai dengan kebijakan afinitas atau anti-afinitas Pod.
-
Jika nama StatefulSet berisi tanda hubung ("-"), maka penyebaran zona volume mungkin saja tidak menyediakan distribusi penyimpanan (storage) yang seragam di seluruh zona yang berbeda.
-
Ketika menentukan beberapa PVC dalam spesifikasi Deployment atau Pod, StorageClass perlu dikonfigurasi untuk zona tunggal tertentu, atau PV perlu disediakan secara statis pada zona tertentu. Solusi lainnya adalah menggunakan sebuah StatefulSet, yang akan memastikan bahwa semua volume untuk sebuah replika disediakan dalam zona yang sama.
Panduan
Kita sekarang akan berjalan melalui pengaturan dan menggunakan multi-zona
klaster pada GCE & AWS. Untuk melakukannya, kamu perlu mengaktifkan klaster penuh
(dengan menentukan MULTIZONE=true
), dan kemudian kamu menambahkan Node di zona tambahan
dengan menjalankan kube-up
lagi (dengan menetapkan opsi KUBE_USE_EXISTING_MASTER=true
).
Mengaktifkan klaster kamu
Buatlah klaster seperti biasa, tetapi teruskan opsi MULTIZONE untuk memberi tahu klaster untuk mengelola beberapa zona; dan membuat Node di zona us-central1-a.
GCE:
curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a NUM_NODES=3 bash
AWS:
curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a NUM_NODES=3 bash
Langkah ini akan mengaktifkan klaster seperti biasa, namun masih berjalan dalam satu zona
(tetapi opsi MULTIZONE=true
telah mengaktifkan kapabilitas multi-zona).
Node yang telah diberi label
Lihatlah Node; dimana kamu bisa melihat Node tersebut diberi label sesuai dengan informasi zona.
Node tersebut sejauh ini berada di zona us-central1-a
(GCE) atau zona us-west-2a
(AWS).
Label dari Node itu adalah failure-domain.beta.kubernetes.io/region
untuk informasi wilayah,
dan failure-domain.beta.kubernetes.io/zone
untuk informasi zona:
kubectl get nodes --show-labels
Tampilan akan seperti dibawah ini:
NAME STATUS ROLES AGE VERSION LABELS
kubernetes-master Ready,SchedulingDisabled <none> 6m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-1,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-87j9 Ready <none> 6m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv Ready <none> 6m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q Ready <none> 6m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q
Menambah lebih banyak Node di zona kedua
Mari kita tambahkan sekumpulan Node ke dalam klaster yang ada, dengan menggunakan kembali
master yang ada, namun dijalankan pada zona yang berbeda (zona us-central1-b
atau zona us-west-2b
).
Kemudian kita jalankan kube-up lagi, tetapi dengan menentukan opsi KUBE_USE_EXISTING_MASTER=true
sehingga kube-up tidak akan membuat master baru, tetapi akan menggunakan kembali master yang dibuat sebelumnya.
GCE:
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-b NUM_NODES=3 kubernetes/cluster/kube-up.sh
Pada AWS, kita juga perlu menentukan CIDR jaringan sebagai tambahan subnet, bersama dengan alamat IP internal dari master:
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2b NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.1.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh
Lihat lagi Node; dimana 3 Node lainnya harus sudah dijalankan dan ditandai
berada di us-central1-b
:
kubectl get nodes --show-labels
Hasil tampilan akan terlihat seperti dibawah ini:
NAME STATUS ROLES AGE VERSION LABELS
kubernetes-master Ready,SchedulingDisabled <none> 16m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-1,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-281d Ready <none> 2m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-87j9 Ready <none> 16m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv Ready <none> 16m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q Ready <none> 17m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q
kubernetes-minion-pp2f Ready <none> 2m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-pp2f
kubernetes-minion-wf8i Ready <none> 2m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-wf8i
Afinitas Volume
Buatlah sebuah volume dengan menggunakan pembuatan volume yang dinamis (hanya PersistentVolume yang didukung untuk afinitas zona):
kubectl apply -f - <<EOF
{
"apiVersion": "v1",
"kind": "PersistentVolumeClaim",
"metadata": {
"name": "claim1",
"annotations": {
"volume.alpha.kubernetes.io/storage-class": "foo"
}
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "5Gi"
}
}
}
}
EOF
us-central1-a
/us-west-2a
); masalah tersebut diangkat pada
(#23330)
dan telah diselesaikan pada versi 1.3+.
Sekarang marilah kita memvalidasi bahwa Kubernetes secara otomatis memberikan label zona & wilayah di mana PV itu dibuat.
kubectl get pv --show-labels
Hasil tampilan akan terlihat seperti dibawah ini:
NAME CAPACITY ACCESSMODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE LABELS
pv-gce-mj4gm 5Gi RWO Retain Bound default/claim1 manual 46s failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a
Kemudian sekarang kita akan membuat Pod yang menggunakan klaim akan volume persisten. Karena volume pada GCE PDs / AWS EBS tidak dapat di-attach melewati zona yang berbeda, hal ini berarti bahwa Pod ini hanya dapat dibuat pada zona yang sama dengan volume tersebut:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: claim1
EOF
Perhatikan bahwa Pod secara otomatis dibuat pada zona yang sama dengan volume, karena pada umumnya lampiran lintas zona tidak diizinkan oleh penyedia cloud:
kubectl describe pod mypod | grep Node
Node: kubernetes-minion-9vlv/10.240.0.5
Kemudian cek label Node:
kubectl get node kubernetes-minion-9vlv --show-labels
NAME STATUS AGE VERSION LABELS
kubernetes-minion-9vlv Ready 22m v1.6.0+fff5156 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
Pod yang tersebar melintasi zona yang berbeda
Pod dalam controller atau Service replikasi tersebar secara otomatis melintasi zona yang berbeda. Pertama-tama, mari kita luncurkan lebih banyak Node di zona ketiga:
GCE:
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-f NUM_NODES=3 kubernetes/cluster/kube-up.sh
AWS:
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2c NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.2.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh
Pastikan bahwa kamu mempunyai Node dalam 3 zona berbeda:
kubectl get nodes --show-labels
Buatlah contoh dengan program guestbook-go, yang mencakup RC dengan ukuran 3, dan menjalankan sebuah aplikasi web sederhana:
find kubernetes/examples/guestbook-go/ -name '*.json' | xargs -I {} kubectl apply -f {}
Beberapa Pod seharusnya tersebar di ketiga zona semuanya:
kubectl describe pod -l app=guestbook | grep Node
Node: kubernetes-minion-9vlv/10.240.0.5
Node: kubernetes-minion-281d/10.240.0.8
Node: kubernetes-minion-olsh/10.240.0.11
kubectl get node kubernetes-minion-9vlv kubernetes-minion-281d kubernetes-minion-olsh --show-labels
NAME STATUS ROLES AGE VERSION LABELS
kubernetes-minion-9vlv Ready <none> 34m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-281d Ready <none> 20m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-olsh Ready <none> 3m v1.13.0 beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-f,kubernetes.io/hostname=kubernetes-minion-olsh
Load-balancer menjangkau semua zona dalam satu klaster; program contoh guestbook-go sudah termasuk contoh Service dengan beban seimbang (load-balanced service):
kubectl describe service guestbook | grep LoadBalancer.Ingress
Hasil tampilan akan terlihat seperti di bawah ini:
LoadBalancer Ingress: 130.211.126.21
Atur alamat IP di atas:
export IP=130.211.126.21
Telusurilah dengan curl melalui alamat IP tersebut:
curl -s http://${IP}:3000/env | grep HOSTNAME
Hasil tampilan akan terlihat seperti di bawah ini:
"HOSTNAME": "guestbook-44sep",
Kemudian, telusurilah beberapa kali:
(for i in `seq 20`; do curl -s http://${IP}:3000/env | grep HOSTNAME; done) | sort | uniq
Hasil tampilan akan terlihat seperti dibawah ini:
"HOSTNAME": "guestbook-44sep",
"HOSTNAME": "guestbook-hum5n",
"HOSTNAME": "guestbook-ppm40",
Load balancer telah menargetkan ke semua Pod dengan benar, meskipun semuanya berada di beberapa zona yang berbeda.
Menghentikan Klaster
Shutting down the cluster
Apabila kamu sudah selesai, maka bersihkanlah:
GCE:
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-f kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a kubernetes/cluster/kube-down.sh
AWS:
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2c kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a kubernetes/cluster/kube-down.sh
3 - Konsep
Bagian konsep ini membantu kamu belajar tentang bagian-bagian sistem serta abstraksi yang digunakan Kubernetes untuk merepresentasikan klaster kamu, serta membantu kamu belajar lebih dalam bagaimana cara kerja Kubernetes.
Ikhtisar
Untuk menggunakan Kubernetes, kamu menggunakan objek-objek Kubernetes API untuk merepresentasikan
state yang diinginkan: apa yang aplikasi atau workload lain yang ingin kamu
jalankan, image kontainer yang digunakan, jaringan atau resource disk apa yang ingin
kamu sediakan, dan lain sebagainya. Kamu membuat state yang diinginkan dengan cara membuat
objek dengan menggunakan API Kubernetes, dan biasanya menggunakan command-line interface
, yaitu kubectl
.
Kamu juga dapat secara langsung berinteraksi dengan klaster untuk membuat atau mengubah
state yang kamu inginkan.
Setelah kamu membuat state yang kamu inginkan, Control Plane Kubernetes
menggunakan Pod Lifecycle Event Generator (PLEG)
untuk mengubah
state yang ada saat ini supaya sama dengan state yang diinginkan.
Untuk melakukan hal tersebut, Kubernetes melakukan berbagai task secara otomatis,
misalnya dengan mekanisme start
atau stop
kontainer, melakukan scale replika dari
suatu aplikasi, dan lain sebagainya. Control Plane Kubernetes terdiri dari sekumpulan
process
yang dijalankan di klaster:
- Kubernetes Master terdiri dari tiga buah process yang dijalankan pada sebuah node di klaster kamu, node ini disebut sebagai master, yang terdiri kube-apiserver, kube-controller-manager dan kube-scheduler.
- Setiap node non-master pada klaster kamu menjalankan dua buah process:
- kubelet, yang menjadi perantara komunikasi dengan master.
- kube-proxy, sebuah proxy yang merupakan representasi jaringan yang ada pada setiap node.
Objek Kubernetes
Kubernetes memiliki beberapa abstraksi yang merepresentasikan state dari sistem kamu: apa yang aplikasi atau workload lain yang ingin kamu jalankan, jaringan atau resource disk apa yang ingin kamu sediakan, serta beberapa informasi lain terkait apa yang sedang klaster kamu lakukan. Abstraksi ini direpresentasikan oleh objek yang tersedia di API Kubernetes; lihat ikhtisar objek-objek Kubernetes untuk penjelasan yang lebih mendetail.
Objek mendasar Kubernetes termasuk:
Sebagai tambahan, Kubernetes memiliki beberapa abstraksi yang lebih tinggi yang disebut kontroler. Kontroler merupakan objek mendasar dengan fungsi tambahan, contoh dari kontroler ini adalah:
Control Plane Kubernetes
Berbagai bagian Control Plane Kubernetes, seperti master dan process-process kubelet, mengatur bagaimana Kubernetes berkomunikasi dengan klaster kamu. Control Plane menjaga seluruh record dari objek Kubernetes serta terus menjalankan iterasi untuk melakukan manajemen state objek. Control Plane akan memberikan respon apabila terdapat perubahan pada klaster kamu dan mengubah state saat ini agar sesuai dengan state yang diinginkan.
Contohnya, ketika kamu menggunakan API Kubernetes untuk membuat sebuah Deployment,
kamu memberikan sebuah state baru yang harus dipenuhi oleh sistem. Control Plane
kemudian akan mencatat objek apa saja yang dibuat, serta menjalankan instruksi yang kamu berikan
dengan cara melakukan start
aplikasi dan melakukan scheduling
aplikasi tersebut
pada node, dengan kata lain mengubah state saat ini agar sesuai dengan state yang diinginkan.
Master
Master Kubernetes bertanggung jawab untuk memelihara state yang diinginkan pada klaster kamu.
Ketika kamu berinteraksi dengan Kubernetes, misalnya saja menggunakan perangkat kubectl
,
kamu berkomunikasi dengan master klaster Kubernetes kamu.
"master" merujuk pada tiga buah process yang dijalankan pada sebuah node pada klaster kamu, node ini disebut sebagai master, yang terdiri kube-apiserver, kube-controller-manager dan kube-scheduler.
Node
Node di dalam klaster Kubernetes adalah mesin (mesin virtual maupun fisik) yang menjalankan aplikasi kamu. Master mengontrol setiap node; kamu akan jarang berinteraksi dengan node secara langsung.
Metadata objek
Selanjutnya
Jika kamu ingin menulis halaman konsep, perhatikan cara penggunaan template pada laman untuk informasi mengenai konsep tipe halaman dan template konsep.
3.1 - Ikhtisar
3.1.1 - Apa itu Kubernetes?
Laman ini merupakan ikhtisar Kubernetes.
Kubernetes merupakan platform open-source yang digunakan untuk melakukan manajemen workloads aplikasi yang dikontainerisasi, serta menyediakan konfigurasi dan otomatisasi secara deklaratif. Kubernetes berada di dalam ekosistem yang besar dan berkembang cepat. Service, support, dan perkakas Kubernetes tersedia secara meluas.
Google membuka Kubernetes sebagai proyek open source pada tahun 2014. Kubernetes dibangun berdasarkan pengalaman Google selama satu setengah dekade dalam menjalankan workloads bersamaan dengan kontribusi berupa ide-ide terbaik yang diberikan oleh komunitas.
Mengapa Kubernetes dan hal apa saja yang dapat dilakukan oleh Kubernetes?
Kubernetes memiliki sejumlah fitur yang dapat dijabarkan sebagai berikut:
- platform kontainer
- platform microservices
- platform cloud yang tidak mudah dipindahkan
Kubernetes menyediakan manajemen environment yang berpusat pada kontainer. Kubernetes melakukan orkestrasi terhadap computing, networking, dan inftrastruktur penyimpanan. Fitur inilah yang kemudian membuat konsep Platform as a Service (PaaS) menjadi lebih sederhana dilengkapi dengan fleksibilitas yang dimiliki oleh Infrastructure as a Service (IaaS).
Lalu apa yang menyebabkan Kubernetes disebut sebagai sebuah platform?
Meskipun Kubernetes menyediakan banyak fungsionalitas, selalu ada keadaan dimana hal tersebut membutuhkan fitur baru. Workflow spesifik yang terkait dengan proses pengembangan aplikasi dapat ditambahkan pada streamline untuk meningkatkan produktivitas developer. Orkestrasi ad-hoc yang dapat diterima biasanya membutuhkan desain otomatisasi yang kokoh agar bersifat scalable. Hal inilah yang membuat Kubernetes juga didesain sebagai platform untuk membangun ekosistem komponen dan dan perkakas untuk memudahkan proses deployment, scale, dan juga manajemen aplikasi.
Labels memudahkan pengguna mengkategorisasikan resources yang mereka miliki sesuai dengan kebutuhan. Annotations memungkinkan pengguna untuk menambahkan informasi tambahan pada resource yang dimiliki.
Selain itu, Kubernetes control plane dibuat berdasarkan API yang tersedia bagi pengguna dan developer. Pengguna dapat mengimplementasikan kontroler sesuai dengan kebutuhan mereka, contohnya adalah schedulers, dengan API kustom yang mereka miliki, kontroler kustom ini kemudian dapat digunakan pada command-line tool generik yang ada.
Desain inilah yang memungkinkan beberapa sistem lain untuk dapat dibangun di atas Kubernetes.
Lalu hal apakah yang tidak termasuk di dalam Kubernetes?
Kubernetes bukanlah sebuah PaaS (Platform as a Service) yang biasanya. Meskipun Kubernetes dijalankan pada tingkatan kontainer dan bukan pada tingkatan perangkat keras, Kubernetes menyediakan beberapa fitur yang biasanya disediakan oleh Paas, seperti deployment, scaling, load balancing, logging, dan monitoring. Akan tetapi, Kubernetes bukanlah sistem monolitik, melainkan suatu sistem yang bersifat sebagai bulding block dan pluggable yang dapat digunakan untuk membangun sebuah platform yang dibutuhkan oleh developer dengan tetap mengutamakan konsep fleksibilitas.
Kubernetes:
- Tidak melakukan limitasi terhadap aplikasi yang di-support. Kubernetes bertujuan untuk mendukung berbagai variasi workloads, termasuk stateless, stateful, dan data-processing. Jika sebuah aplikasi dapat dijalankan di atas kontainer, maka aplikasi tersebut juga dapat dijalankan di atas Kubernetes.
- Tidak menyediakan mekanisme untuk melakukan deploy kode sumber maupun mekanisme build sebuah aplikasi. Continuous Integration, Delivery, and Deployment (CI/CD) workflows ditentukan oleh preferensi serta kebutuhan teknis organisasi.
- Tidak menyediakan application-level services, seperti middleware (e.g., message buses), data-processing frameworks (for example, Spark), databases (e.g., mysql), caches, maupun cluster storage systems (e.g., Ceph) sebagai suatu built-in services. Komponen tersebut dapat dijalankan di atas Kubernetes, dan/atau dapat diakses oleh aplikasi yang dijalankan di atas Kubernetes melalui sebuah mekanisme tidak mudah dipindahkan misalnya saja Open Service Broker.
- Tidak membatasi penyedia layanan logging, monitoring, maupun alerting yang digunakan. Kubernetes menyediakan proof of concept dan mekanisme integrasi yang dapat digunakan untuk mengumpulkan serta mengekspor metriks yang ada.
- Tidak menyediakan atau mengharuskan penggunaan configuration language/system (e.g., jsonnet). Kubernetes menyediakan suatu API deklaratif yang dapat digunakan oleh berbagai jenis spesifikasi deklaratif.
- Tidak menyediakan atau mengadaptasi sebuah konfigurasi, maintenance, manajemen, atau self-healing mesin dengan spesifikasi khusus.
Sebagai tambahan, Kubernetes bukanlah sebuah sitem orkestrasi biasa. Bahkan pada kenyataannya, Kubernetes menghilangkan kebutuhan untuk melakukan orkestrasi. Definisi teknis dari orkestrasi merupakan eksekusi dari sebuah workflow yang sudah didefinisikan sebelumnya: pertama kerjakan A, kemudian B, dan terakhir C. Sebaliknya, Kubernetes disusun oleh seperangkat proses kontrol yang dapat idekomposisi yang selalu menjalankan state yang ada saat ini hingga sesuai dengan state yang dinginkan. Kita tidak perlu peduli proses apa saja yang perlu dilakukan untuk melakukan A hingga C. Mekanisme kontrol yang tersentralisasi juga tidak dibutuhkan. Dengan demikian, sistem yang dihasilkan lebih mudah digunakan lebih kokoh, serta lebih extensible.
Mengapa kontainer?
Mencari alasan kenapa kita harus menggunakan kontainer?
Cara Lama untuk melakukan mekanisme deploy suatu aplikasi adalah dengan cara instalasi aplikasi tersebut pada sebuah mesin dengan menggunakan package manager yang dimiliki oleh sistem operasi mesin tersebut. Hal ini menciptakan suatu ketergantungan antara executables, konfigurasi, serta ketergantungan lain yang dibutuhkan aplikasi dengan sistem operasi yang digunakan oleh mesin. Untuk mengatasi hal ini, tentunya bisa saja kita melakukan mekanisme build suatu image VM yang immutable untuk mendapatkan mekanisme rollouts dan rollback yang dapat diprediksi. Meskipun demikian, VM masih dianggap "berat" dan tidak tidak mudah dipindahkan.
Cara Baru adalah dengan melakukan mekanisme deploy kontainer pada tingkatan virtualisasi di level sistem operasi (OS) bukan pada tingkatan virtualisasi perangkat keras. Kontainer ini berada dalam lingkungan yang terisolasi satu sama lain serta terisolasi dengan mesin dimana kontainer ini berada. Kontainer ini memiliki filesystems masing-masing. Selain itu, setiap kontainer tidak dapat "melihat" process yang sedang dijalankan di kontainer lain. Selain itu resource komputasi yang digunakan oleh kontainer ini juga dapat dibatasi. Kontainer juga dapat dengan lebih mudah di-build jika dibandingkan dengan VM, karena kontainer tidak bergantung pada filesystem yang dimiliki mesin, serta dengan mudah dapat didistribusikan.
Karena kontainer ukurannya kecil dan lebih cepat, sebuah aplikasi dapat dibangun di setiap image kontainer. Mekanisme pemetaan satu-satu antara kontainer dan aplikasi inilah yang membuka keuntungan secara meyeluruh yang dapat diberikan oleh kontainer. Dengan menggunakan kontainer, image kontainer dapat dibuat diwaktu rilis aplikasi. Pembuatan image ini memungkinkan aplikasi secara konsisten dirilis pada environment development maupun production. Selain itu, kontainer juga memiliki transparasi yang lebih tinggi dibandingkan dengan VM. Maksudnya, infrastruktur punya tugas untuk mengatur lifecycle seluruh process yang ada di dalam kontainer. Ini bukanlah lagi tugas sebuah supervisor process yang tersembunyi di dalam kontainer.
Secara garis besar, penggunaan kontainer memiliki keuntungan sebagai berikut:
- Mekanisme pembuatan aplikasi serta proses deployment yang lebih efektif: Kontainer dapat meningkatkan kemudahan dan efisiensi jika dibandingkan dengan penggunaan VM.
- Continuous development, integration, and deployment: Digunakan untuk melakukan proses build dan deploy yang sering dilakukan serta kemudahan mekanisme rollback karena image yang ada sifatnya immutable.
- Pemisahan kepentingan antara Dev dan Ops: Pembuatan image container dilakukan pada saat rilis dan bukan pada saat deploy mengurangi ketergantungan aplikasi dan infrastruktur.
- Observabilitas Tidak hanya informasi dan metriks pada level OS, tapi juga kesehatan aplikasi dan signal lain.
- Konsistensi environment pada masa pengembangan , testing, dan production: Memiliki perilaku yang sama baik ketika dijalankan di mesin lokal maupun penyedia layanan cloud.
- Portabilitas antar penyedia layanan cloud maupun distribusi OS: Dapat dijalankan pada Ubuntu, RHEL, CoreOS, on-prem, Google Kubernetes Engine, dan dimanapun.
- Manajemen yang bersifat Aplikasi sentris: Meningkatkan level abstraksi dari proses menjalankan OS pada perangkat keras virtual ke proses menjalankan aplikasi pada sebuah OS dengan menggunakan resource logis.
- Mikroservis yang renggang (loosely coupled), terdistribusi, elastis, dan terliberasi: Aplikasi dapat dipecah menjadi komponen yang lebih kecil yang independen dan dapat di-deploy dan diatur secara dinamis -- bukan sebuah sistem monolitik yang dijalankan pada sebuah mesin yang hanya punya satu tujuan.
- Isolasi resource: Performa aplikasi yang bisa diprediksi.
- Utilisasi resource: Efisiensi yang tinggi
Apakah arti Kubernetes? K8s?
Nama Kubernetes berasal dari Bahasa Yunani, yang berarti juru mudi atau pilot, dan merupakan asal kata gubernur dan cybernetic. K8s merupakan sebuah singkatan yang didapat dengan mengganti 8 huruf "ubernete" dengan "8".
Selanjutnya
- Siap untuk memulai?
- Untuk penjelasan lebih rinci, silahkan lihat Dokumentasi Kubernetes.
3.1.2 - Komponen-Komponen Kubernetes
Dokumen ini merupakan ikhtisar yang mencakup berbagai komponen yang dibutuhkan agar klaster Kubernetes dapat berjalan secara fungsional.
Komponen Master
Komponen master menyediakan control plane bagi klaster. Komponen ini berperan dalam proses pengambilan secara global pada klaster (contohnya, mekanisme schedule), serta berperan dalam proses deteksi serta pemberian respons terhadap events yang berlangsung di dalam klaster (contohnya, penjadwalan pod baru apabila jumlah replika yang ada pada replication controller tidak terpenuhi).
Komponen master dapat dijalankan di mesin manapun yang ada di klaster. Meski begitu, untuk memudahkan proses yang ada, script inisiasi awal yang dijalankan biasanya memulai komponen master pada mesin yang sama, serta tidak menjalankan kontainer bagi pengguna di mesin ini. Contoh konfigurasi multi-master VM dapat dilihat di modul [Membangun Klaster HA] (/docs/admin/high-availability/).
kube-apiserver
Komponen control plane yang mengekspos API Kubernetes. Merupakan front-end dari control plane Kubernetes.
Komponen ini didesain agar dapat diskalakan secara horizontal. Lihat Membangun Klaster HA.
etcd
Penyimpanan key value konsisten yang digunakan sebagai penyimpanan data klaster Kubernetes.
Selalu perhatikan mekanisme untuk mem-backup data etcd pada klaster Kubernetes kamu. Untuk informasi lebih lanjut tentang etcd, lihat dokumentasi etcd.
kube-scheduler
Komponen control plane yang bertugas mengamati Pod baru yang belum ditempatkan di node manapun dan kemudian memilihkan Node di mana Pod baru tersebut akan dijalankan.
Faktor-faktor yang dipertimbangkan untuk keputusan penjadwalan termasuk: kebutuhan sumber daya secara individual dan kolektif, batasan perangkat keras/perangkat lunak/peraturan, spesifikasi afinitas dan nonafinitas, lokalisasi data, interferensi antar beban kerja dan tenggat waktu.
kube-controller-manager
Komponen control plane yang menjalankan pengontrol.
Secara logis, setiap pengontrol adalah sebuah proses yang berbeda, tetapi untuk mengurangi kompleksitas, kesemuanya dikompilasi menjadi sebuah biner (binary) yang dijalankan sebagai satu proses.
Kontroler-kontroler ini meliputi:
- Kontroler Node : Bertanggung jawab untuk mengamati dan memberikan respons apabila jumlah node berkurang.
- Kontroler Replikasi : Bertanggung jawab untuk menjaga jumlah pod agar jumlahnya sesuai dengan kebutuhan setiap objek kontroler replikasi yang ada di sistem.
- Kontroler Endpoints : Menginisiasi objek Endpoints (yang merupakan gabungan Pods dan Services).
- Kontroler Service Account & Token: Membuat akun dan akses token API standar untuk setiap namespaces yang dibuat.
cloud-controller-manager
Cloud-controller-manager merupakan kontroler yang berinteraksi dengan penyedia layanan cloud. Kontroler ini merupakat fitur alfa yang diperkenalkan pada Kubernetes versi 1.6.
Cloud-controller-manager hanya menjalankan iterasi kontroler cloud-provider-specific .
Kamu harus menonaktifkan iterasi kontroler ini pada kube-controller-manager.
Kamu dapat menonaktifka iterasi kontroler ini dengan mengubah nilai argumen --cloud-provider
dengan external
ketika menginisiasi kube-controller-manager.
Adanya cloud-controller-manager memungkinkan kode yang dimiliki oleh penyedia layanan cloud dan kode yang ada pada Kubernetes saling tidak bergantung selama masa development. Pada versi sebelumnya, Kubernetes bergantung pada fungsionalitas spesifik yang disediakan oleh penyedia layanan cloud. Di masa mendatang, kode yang secara spesifik dimiliki oleh penyedia layanan cloud akan dipelihara oleh penyedia layanan cloud itu sendiri, kode ini selanjutnya akan dihubungkan dengan cloud-controller-manager ketika Kubernetes dijalankan.
Kontroler berikut ini memiliki keterkaitan dengan penyedia layanan cloud:
- Kontroler Node : Melakukan pengecekan pada penyedia layanan cloud ketika menentukan apakah sebuah node telah dihapus pada cloud apabila node tersebut berhenti memberikan respons.
- Kontroler Route : Melakukan pengaturan awal route yang ada pada penyedia layanan cloud
- Kontroler Service : Untuk membuat, memperbaharui, menghapus load balancer yang disediakan oleh penyedia layanan cloud
- Kontroler Volume : Untuk membuat, meng-attach, dan melakukan mount volume serta melakukan inetraksi dengan penyedia layanan cloud untuk melakukan orkestrasi volume
Komponen Node
Komponen ini ada pada setiap node, fungsinya adalah melakukan pemeliharaan terhadap pod serta menyediakan environment runtime bagi Kubernetes.
kubelet
Agen yang dijalankan pada setiap node di klaster yang bertugas untuk memastikan kontainer dijalankan di dalam Pod.
kube-proxy
kube-proxy membantu abstraksi service Kubernetes melakukan tugasnya. Hal ini terjadi dengan cara memelihara aturan-aturan jaringan (network rules) serta meneruskan koneksi yang ditujukan pada suatu host.
Container Runtime
Container runtime adalah perangkat lunak yang bertanggung jawab dalam menjalankan kontainer. Kubernetes mendukung beberapa runtime, diantaranya adalah: Docker, containerd, cri-o, rktlet dan semua implementasi Kubernetes CRI (Container Runtime Interface).
Addons
Addons merupakan pod dan service yang mengimplementasikan fitur-fitur yang diperlukan klaster.
Beberapa addons akan dijelaskan selanjutnya.
DNS
Meskipun tidak semua addons dibutuhkan, semua klaster Kubernetes hendaknya memiliki DNS klaster. Komponen ini penting karena banyak dibutuhkan oleh komponen lainnya.
Klaster DNS adalah server DNS, selain beberapa server DNS lain yang sudah ada di environment kamu, yang berfungsi sebagai catatan DNS bagi Kubernetes services
Kontainer yang dimulai oleh kubernetes secara otomatis akan memasukkan server DNS ini ke dalam mekanisme pencarian DNS yang dimilikinya.
Web UI (Dasbor)
Dasbor adalah antar muka berbasis web multifungsi yang ada pada klaster Kubernetes. Dasbor ini memungkinkan user melakukan manajemen dan troubleshooting klaster maupun aplikasi yang ada pada klaster itu sendiri.
Container Resource Monitoring
Container Resource Monitoring mencatat metrik time-series yang diperoleh dari kontainer ke dalam basis data serta menyediakan antar muka yang dapat digunakan untuk melakukan pencarian data yang dibutuhkan.
Cluster-level Logging
Cluster-level logging bertanggung jawab mencatat log kontainer pada penyimpanan log terpusat dengan antar muka yang dapat digunakan untuk melakukan pencarian.
3.1.3 - API Kubernetes
Secara keseluruhan standar yang digunakan untuk API dijelaskan di dalam dokumentasi API standar.
Endpoints API, resource types serta contoh penggunaan dijelaskan di dalam API Reference.
Akses remote penggunaan API dijelaskan di dalam dokumentasi akses API.
API Kubernetes juga berperan sebagai skema konfigurasi yang deklaratif di dalam sistem.. Sementara itu, kubectl merupakan command-line yang dapat digunakan untuk membuat, menmperbaharui, menghapus, dan mendapatkan obyek API.
Kubernetes menyimpan bentuk terserialisasi dari obyek API yang dimilikinya di dalam etcd.
Kubernetes sendiri dibagi menjadi beberapa komponen yang saling dapat saling interaksi melalui API.
Perubahan API
Berdasarkan pengalaman kami, semua sistem yang berhasil memerlukan kebutuhan untuk terus tumbuh dan berkembang seiring dengan bertambahnya kebutuhan yang ada. Dengan demikian, kami berekspektasi bahwa API akan selalu berubah seiring dengan bertambahnya kebutuhan yang ada. Meski begitu, perubahan yang ada akan selalu kompatibel dengan implementasi sebelumnya, untuk jangka waktu tertentu. Secara umum, penambahan pada sebuah resource API atau field resource bisa sering terjadi.. Penghapusan resource API atau suatu field, di sisi lain, diharapkan untuk dapat memenuhi kaidah deprecation API.
Hal-hal apa saja yang perlu diperhatikan untuk menjamin kompatibilitas API secara rinci dibahas di dalam dokumentasi perubahan API.
Swagger and OpenAPI Definition
Detail mengenai API didokumentasikan dengan menggunakan OpenAPI.
Semenjak Kubernetes versi 1.10, Kubernetes menghadirkan spesifikasi OpenAPI melalui endpoint /openapi/v2
.
Format request dapat diterapkan dengan cara menambahkan header HTTP:
Header | Opsi |
---|---|
Accept | application/json , application/[email protected]+protobuf (content-type standar yang digunakan adalah application/json untuk */* ) |
Accept-Encoding | gzip |
Sebelum versi 1.14, terdapat 4 buah endpoint yang menyediakan spesifikasi OpenAPI
dalam format berbeda yang dapat digunakan (/swagger.json
, /swagger-2.0.0.json
, /swagger-2.0.0.pb-v1
, /swagger-2.0.0.pb-v1.gz
).
Endpoint ini bersifat deprecated dan akan dihapus pada Kubernetes versi 1.14.
Cara mendapatkan spesifikasi OpenAPI:
Sebelum 1.10 | Mulai Kubernetes 1.10 |
---|---|
GET /swagger.json | GET /openapi/v2 Accept: application/json |
GET /swagger-2.0.0.pb-v1 | GET /openapi/v2 Accept: application/[email protected]+protobuf |
GET /swagger-2.0.0.pb-v1.gz | GET /openapi/v2 Accept: application/[email protected]+protobuf Accept-Encoding: gzip |
Kubernetes juga menyediakan alternatif mekanisme serialisasi lain, yaitu dengan menggunakan Protobuf, yang secara umum digunakan untuk mekanisme komunikasi intra-klaster, hal ini didokumentasikan di dalam proposal desain serta berkas IDL sebagai bentuk spesifikasi skema berada dalam package Go
Sebelum Kubernetes versi 1.14, apiserver Kubernetes juga mengekspos API
yang dapat digunakan untuk mendapatkan spesifikasi Swagger v1.2 pada endpoint /swaggerapi
.
Endpoint ini akan sudah bersifat deprecated dan akan dihapus pada
Kubernetes versi 1.14.
Pemberian Versi pada API
Untuk memudahkan restrukturisasi field dan resource yang ada,
Kubernetes menyediakan beberapa versi API yang berada pada path yang berbeda,
misalnya /api/v1
atau /apis/extensions/v1beta1
.
Kita dapat memilih versi yang akan digunakan pada tingkatan API dan bukan pada tingkatan field atau resource untuk memastikan API yang digunakan memperlihatkan gambaran yang jelas serta konsisten mengenai resoure dan sifat sistem yang ada.
Perhatikan bahwa pemberian versi pada API dan pemberian versi pada API dan perangkat lunak memiliki keterkaitan secara tak langsung. Proposal API and release versioning memberikan deskripsi keterkaitan antara pemberian versi pada API dan pemberian versi pada perangkat lunak.
API dengan versi yang berbeda menunjukan tingkatan kestabilan dan ketersediaan yang diberikan pada versi tersebut. Kriteria untuk setiap tingkatan dideskripsikan secara lebih detail di dalam dokumentasi perubahan API. They are summarized here:
- Tingkatan Alpha:
- Nama dari versi ini mengandung string
alpha
(misalnya,v1alpha1
). - Bisa jadi terdapat bug. Secara default fitur ini tidak diekspos.
- Ketersediaan untuk fitur yang ada bisa saja dihilangkan pada suatu waktu tanpa pemberitahuan sebelumnya.
- API yang ada mungkin saja berubah tanpa memperhatikan kompatibilitas dengan versi perangkat lunak sebelumnya.
- Hanya direkomendasikan untuk klaster yang digunakan untuk tujuan testing.
- Nama dari versi ini mengandung string
- Tingkatan Beta:
- Nama dari versi ini mengandung string
beta
(misalnyav2beta3
). - Kode yang ada sudah melalui mekanisme testing yang cukup baik. Menggunakan fitur ini dianggap cukup aman. Fitur ini diekspos secara default.
- Ketersediaan untuk fitur secara menyeluruh tidak akan dihapus, meskipun begitu detail untuk suatu fitur bisa saja berubah.
- Skema dan/atau semantik dari suatu obyek mungkin saja berubah tanpa memerhatikan kompatibilitas pada rilis beta selanjutnya. Jika hal ini terjadi, kami akan menyediakan suatu instruksi untuk melakukan migrasi di versi rilis selanjutnya. hal ini bisa saja terdiri dari penghapusan, pengubahan, ataupun pembuatan obyek API. Proses pengubahan mungkin saja membutuhkan pemikiran yang matang. Dampak proses ini bisa saja menyebabkan downtime aplikasi yang bergantung pada fitur ini.
- Disarankan hanya untuk digunakan untuk penggunaan yang untuk penggunaan yang tidak berdampak langsung pada bisnis kamu.
- Kami mohon untuk mencoba versi beta yang kami sediakan dan berikan masukan terhadap fitur yang kamu pakai! Apabila fitur tersebut sudah tidak lagi berada di dalam tingkatan beta perubahan yang kami buat terhadap fitur tersebut bisa jadi tidak lagi dapat digunakan
- Nama dari versi ini mengandung string
- Tingkatan stabil:
- Nama dari versi ini mengandung string
vX
dimanaX
merupakan bilangan bulat. - Fitur yang ada pada tingkatan ini akan selalu muncul di rilis berikutnya.
- Nama dari versi ini mengandung string
API groups
Untuk memudahkan proses ekstensi suatu API Kubernetes, kami mengimplementasikan API groups.
API group ini dispesifikasikan di dalam path REST serta di dalam field apiVersion
dari sebuah obyek yang sudah diserialisasi.
Saat ini, terdapat beberapa API groups yang digunakan:
-
Kelompok core, seringkali disebut sebagai legacy group, berada pada path REST
/api/v1
serta menggunakanapiVersion: v1
. -
Named groups berada pada path REST
/apis/$GROUP_NAME/$VERSION
, serta menggunakanapiVersion: $GROUP_NAME/$VERSION
(misalnyaapiVersion: batch/v1
). Daftar menyeluruh mengenai apa saja API groups dapat dilihat di Kubernetes API reference.
Ekstensi API dengan custom resources dapat dilakukan melalui dua buah path:
- CustomResourceDefinition digunakan jika memerlukan seluruh set semantik Kubernetes API, pengguna boleh implementasi apiserver sendiri dengan menggunakan aggregator.
- Pengguna yang membutuhkan seperangkat semantik API Kubernetes API dapat mengimplementasikan apiserver mereka sendiri. dengan menggunakan aggregator untuk membuat integrasi dengan klien menjadi lebih mudah.
Mengaktifkan API groups
Beberapa resources dan API groups sudah diaktifkan secara default.
Resource dan API groups ini dapat diaktifkan dan dinonaktifkan dengan mengatur penanda --runtime-config
pada apiserver. --runtime-config
menerima nilai yang dipisahkan oleh koma. Sebagai contoh: untuk menonaktifkan batch/v1, tetapkan
--runtime-config=batch/v1=false
, untuk mengaktifkan batch/v2alpha1, tetapkan --runtime-config=batch/v2alpha1
.
Penanda menerima nilai yang dipisahkan oleh pasangan key=value
yang mendeskripsikan konfigurasi runtime pada apiserver.
PENTING: Melakukan proses mengaktifkan atau menonaktifkan groups atau resources
membutuhkan mekanisme restart apiserver dan controller-manager
agar apiserver dapat menerima perubahan --runtime-config
.
Mengaktifkan resources di dalam groups
DaemonSets, Deployments, HorizontalPodAutoscalers,
Ingresses, Jobs, dan ReplicaSets diaktifkan secara default.
Ekstensi lain dapat diaktifkan penanda --runtime-config
pada apiserver. Penanda --runtime-config
menerima nilai yang dipisahkan oleh koma.
Sebagai contoh untuk menonaktifkan deployments dan ingress, tetapkan.
--runtime-config=extensions/v1beta1/deployments=false,extensions/v1beta1/ingresses=false
3.1.4 - Menggunakan Objek-Objek Kubernetes
3.1.4.1 - Memahami Konsep Objek-Objek yang ada pada Kubernetes
Laman ini menjelaskan bagaimana objek-objek Kubernetes direpresentasikan di dalam API Kubernetes,
dan bagaimana kamu dapat merepresentasikannya di dalam format .yaml
.
Memahami Konsep Objek-Objek yang Ada pada Kubernetes
Objek-objek Kubernetes adalah entitas persisten di dalam sistem Kubernetes. Kubernetes menggunakan entitas ini untuk merepresentasikan state yang ada pada klaster kamu. Secara spesifik, hal itu dapat dideskripsikan sebagai:
- Aplikasi-aplikasi kontainer apa sajakah yang sedang dijalankan (serta pada node apa aplikasi tersebut dijalankan)
- Resource yang tersedia untuk aplikasi tersebut
- Policy yang mengatur bagaimana aplikasi tersebut dijalankan, misalnya restart, upgrade, dan fault-tolerance.
Objek Kubernetes merupakan sebuah "record of intent"--yang mana sekali kamu membuat suatu objek, sistem Kubernetes akan bekerja secara konsisten untuk menjamin bahwa objek tersebut akan selalu ada. Dengan membuat sebuah objek, secara tak langsung kamu memberikan informasi pada sistem Kubernetes mengenai perilaku apakah yang kamu inginkan pada workload klaster yang kamu miliki; dengan kata lain ini merupakan definisi state klaster yang kamu inginkan.
Untuk menggunakan objek-objek Kubernetes--baik membuat, mengubah, atau menghapus objek-objek tersebut--kamu
harus menggunakan API Kubernetes.
Ketika kamu menggunakan perintah kubectl
, perintah ini akan melakukan API call untuk perintah
yang kamu berikan. Kamu juga dapat menggunakan API Kubernetes secara langsung pada program yang kamu miliki
menggunakan salah satu library klien yang disediakan.
Spec dan Status Objek
Setiap objek Kubernetes memiliki field berantai yang mengatur konfigurasi sebuah objek: spec dan status. Spec, merupakan field yang harus kamu sediakan, field ini mendeskripsikan state yang kamu inginkan untuk objek tersebut--karakteristik dari objek yang kamu miliki. Status mendeskripsikan state yang sebenarnya dari sebuah objek, dan hal ini disediakan dan selalu diubah oleh sistem Kubernetes. Setiap saat, Control Plane Kubernetes selalu memantau apakah state aktual sudah sesuai dengan state yang diinginkan.
Sebagai contoh, Deployment merupakan sebuah objek yang merepresentasikan sebuah aplikasi yang dijalankan di klaster kamu. Ketika kamu membuat sebuah Deployment, kamu bisa saja memberikan spec bagi Deployment untuk memberikan spesifikasi berapa banyak replica yang kamu inginkan. Sistem Kubernetes kemudian akan membaca konfigurasi yang kamu berikan dan mengaktifkan tiga buah instans untuk aplikasi yang kamu inginkan--mengubah status yang ada saat ini agar sesuai dengan apa yang kamu inginkan. Jika terjadi kegagalan dalam instans yang dibuat, sistem Kubernetes akan memberikan respons bahwa terdapat perbedaan antara spec dan status serta melakukan penyesuaian dengan cara memberikan instans pengganti.
Informasi lebih lanjut mengenai spec objek, status, dan metadata dapat kamu baca di Konvensi API Kubernetes.
Mendeskripsikan Objek Kubernetes
Ketika kamu membuat sebuah objek di Kubernetes, kamu harus menyediakan spec objek yang
mendeskripsikan state yang diinginkan, serta beberapa informasi tentang objek tersebut (seperti nama).
Ketika kamu menggunakan API Kubernetes untuk membuat objek tersebut (baik secara langsung atau menggunakan perintah
kubectl
), request API yang dibuat harus mencakup informasi seperti request body dalam format JSON.
Apabila kamu memberikan informasi dalam bentuk .yaml
ketika menggunakan perintah kubectl
maka kubectl
akan mengubah informasi yang kamu berikan ke dalam format JSON ketika melakukan request API.
Berikut merupakan contoh file .yaml
yang menunjukkan field dan spec objek untuk Deployment:
apiVersion: apps/v1 # for versions before 1.9.0 use apps/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
Salah satu cara untuk membuat Deployment menggunakan file .yaml
seperti yang dijabarkan di atas adalah dengan menggunakan perintah
kubectl apply
pada command-line interface kubectl
kamu menerapkan file .yaml
sebagai sebuah argumen.
Berikut merupakan contoh penggunaannya:
kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record
Keluaran yang digunakan kurang lebih akan ditampilkan sebagai berikut:
deployment.apps/nginx-deployment created
Field-Field yang dibutuhkan
Pada file .yaml
untuk objek Kubernetes yang ingin kamu buat, kamu perlu
menyediakan value untuk field-field berikut:
- apiVersion - Version API Kubernetes mana yang kamu gunakan untuk membuat objek tersebut
- kind - Objek apakah yang ingin kamu buat
- metadata - Data yang dapat kamu gunakan untuk melakukan identifikasi objek termasuk name dalam betuk string, UID, dan namespace yang bersifat opsional
Kamu juga harus menyediakan field spec. Format spesifik dari spec sebuah objek akan berbeda bergantung pada objek apakah yang ingin kamu buat, serta mengandung field berantai yang spesifik bagi objek tersebut. Referensi API Kubernetes memberikan penjelasan lebih lanjut mengenai format spec untuk semua objek Kubernetes yang dapat kamu buat. Misalnya saja format spec untuk Pod dapat kamu temukan di sini, dan format spec untuk Deployment dapat ditemukan di sini.
Selanjutnya
- Pelajari lebih lanjut mengenai dasar-dasar penting bagi objek Kubernetes, seperti Pod.
3.1.4.2 - Pengaturan Objek Kubernetes
Perangkat kubectl
mendukung beberapa cara untuk membuat dan mengatur objek-objek Kubernetes.
Laman ini menggambarkan berbagai macam metodenya. Baca Kubectl gitbook
untuk penjelasan pengaturan objek dengan Kubectl secara detail.
Metode pengaturan
Metode pengaturan | Dijalankan pada | Environment yang disarankan | Jumlah penulis yang didukung | Tingkat kesulitan mempelajari |
---|---|---|---|---|
Perintah imperatif | Objek live | Proyek pengembangan (dev) | 1+ | Terendah |
Konfigurasi objek imperatif | Berkas individu | Proyek produksi (prod) | 1 | Sedang |
Konfigurasi objek deklaratif | Direktori berkas | Proyek produksi (prod) | 1+ | Tertinggi |
Perintah imperatif
Ketika menggunakan perintah-perintah imperatif, seorang pengguna menjalankan operasi secara langsung
pada objek-objek live dalam sebuah klaster. Pengguna menjalankan operasi tersebut melalui
argumen atau flag pada perintah kubectl
.
Ini merupakan cara yang paling mudah untuk memulai atau menjalankan tugas "sekali jalan" pada sebuah klaster. Karena metode ini dijalankan secara langsung pada objek live, tidak ada history yang menjelaskan konfigurasi-konfigurasi terkait sebelumnya.
Contoh
Menjalankan sebuah instans Container nginx dengan membuat suatu objek Deployment:
kubectl run nginx --image nginx
Melakukan hal yang sama menggunakan sintaks yang berbeda:
kubectl create deployment nginx --image nginx
Kelebihan dan kekurangan
Beberapa kelebihan metode ini dibandingkan metode konfigurasi objek:
- Sederhana, mudah dipelajari dan diingat.
- Hanya memerlukan satu langkah untuk membuat perubahan pada klaster.
Beberapa kekurangan metode ini dibandingkan metode konfigurasi objek:
- Tidak terintegrasi dengan proses peninjauan (review) perubahan.
- Tidak menyediakan jejak audit yang terkait dengan perubahan.
- Tidak menyediakan sumber record kecuali dari apa yang live terlihat.
- Tidak menyediakan templat untuk membuat objek-objek baru.
Konfigurasi objek imperatif
Pada konfigurasi objek imperatif, perintah kubectl menetapkan jenis operasi (create, replace, etc.), flag-flag pilihan dan minimal satu nama berkas. Berkas ini harus berisi definisi lengkap dari objek tersebut dalam bentuk YAML atau JSON.
Lihat referensi API untuk info lebih detail mengenai definisi objek.
replace
menggantikan spek yang sudah ada dengan spek yang baru,
membuang semua perubahan terhadap objek tersebut yang tidak didefinisikan pada berkas konfigurasi.
Metode ini sebaiknya tidak dilakukan pada tipe sumber daya yang spek-nya diperbarui
secara independen di luar berkas konfigurasi. Service dengan tipe LoadBalancer
, sebagai contoh,
memiliki field externalIPs
yang diperbarui secara independen di luar konfigurasi, dilakukan
oleh klaster.
Contoh
Membuat objek yang didefinisikan pada sebuah berkas konfigurasi:
kubectl create -f nginx.yaml
Menghapus objek-objek yang didefinisikan pada dua berkas konfigurasi:
kubectl delete -f nginx.yaml -f redis.yaml
Memperbarui objek yang didefinisikan pada sebuah berkas konfigurasi dengan menimpa konfigurasi live:
kubectl replace -f nginx.yaml
Kelebihan dan kekurangan
Beberapa kelebihan dibandingkan metode perintah imperatif:
- Konfigurasi objek dapat disimpan pada suatu sistem kontrol kode seperti Git.
- Konfigurasi objek dapat diintegrasikan dengan proses-proses, misalnya peninjauan (review) perubahan sebelum push dan jejak audit.
- Konfigurasi objek dapat menyediakan templat untuk membuat objek-objek baru.
Beberapa kekurangan dibandingkan metode perintah imperatif:
- Konfigurasi objek memerlukan pemahaman yang mendasar soal skema objek.
- Konfigurasi objek memerlukan langkah tambahan untuk menulis berkas YAML.
Beberapa kelebihan dibandingkan metode konfigurasi objek deklaratif:
- Konfigurasi objek imperatif memiliki perilaku yang lebih sederhana dan mudah dimengerti.
- Sejak Kubernetes versi 1.5, konfigurasi objek imperatif sudah lebih stabil.
Beberapa kekurangan dibandingkan metode konfigurasi objek deklaratif:
- Konfigurasi objek imperatif bekerja dengan baik untuk berkas-berkas, namun tidak untuk direktori.
- Pembaruan untuk objek-objek live harus diterapkan pada berkas-berkas konfigurasi, jika tidak, hasil perubahan akan hilang pada penggantian berikutnya.
Konfigurasi objek deklaratif
Ketika menggunakan konfigurasi objek deklaratif, seorang pengguna beroperasi pada berkas-berkas
konfigurasi objek yang disimpan secara lokal, namun pengguna tidak mendefinisikan operasi
yang akan dilakukan pada berkas-berkas tersebut. Operasi create, update, dan delete
akan dideteksi secara otomatis per-objek dengan kubectl
. Hal ini memungkinkan penerapan
melalui direktori, dimana operasi yang berbeda mungkin diperlukan untuk objek-objek yang berbeda.
patch
supaya hanya perbedaannya saja yang ditulis,
daripada menggunakan operasi API replace
untuk menggantikan seluruh konfigurasi objek.
Contoh
Melakukan pemrosesan pada semua berkas konfigurasi objek di direktori configs
, dan melakukan
create atau patch untuk objek-objek live. Kamu dapat terlebih dahulu melakukan diff
untuk
melihat perubahan-perubahan apa saja yang akan dilakukan, dan kemudian terapkan:
kubectl diff -f configs/
kubectl apply -f configs/
Melakukan pemrosesan direktori secara rekursif:
kubectl diff -R -f configs/
kubectl apply -R -f configs/
Kelebihan dan kekurangan
Beberapa kelebihan dibandingkan konfigurasi objek imperatif:
- Perubahan-perubahan yang dilakukan secara langsung pada objek-objek live akan dipertahankan, bahkan jika perubahan tersebut tidak digabungkan kembali pada berkas-berkas konfigurasi.
- Konfigurasi objek deklaratif memiliki dukungan yang lebih baik dalam mengoperasikan direktori dan secara otomatis mendeteksi tipe operasi (create, patch, delete) per-objek.
Beberapa kekurangan dibandingkan konfigurasi objek imperatif:
- Konfigurasi objek deklaratif lebih sulit untuk di-debug dan hasilnya lebih sulit dimengerti untuk perilaku yang tidak diinginkan.
- Pembaruan sebagian menggunakan diff menghasilkan operasi merge dan patch yang rumit.
Selanjutnya
- Mengatur Objek Kubernetes menggunakan Perintah Imperatif
- Mengatur Objek Kubernetes menggunakan Konfigurasi Objek (Imperatif)
- Mengatur Objek Kubernetes menggunakan Konfigurasi Objek (Deklaratif)
- Mengatur Objek Kubernetes menggunakan Kustomize (Deklaratif)
- Referensi Perintah Kubectl
- Kubectl Gitbook
- Referensi API Kubernetes
3.1.4.3 - Nama
Seluruh objek di dalam REST API Kubernetes secara jelas ditandai dengan nama dan UID.
Apabila pengguna ingin memberikan atribut tidak unik, Kubernetes menyediakan label dan anotasi.
Bacalah dokumentasi desain penanda agar kamu dapat memahami lebih lanjut sintaks yang digunakan untuk Nama dan UID.
Nama
String yang dihasilkan oleh klien yang mengacu pada sebuah objek dalam suatu URL resource, seperti /api/v1/pods/some-name
.
Sebuah objek dengan kind yang sama tidak boleh memiliki nama yang sama pada suatu waktu tertentu. Meskipun begitu, apabila kamu menghapus sebuah objek, kamu membuat sebuah objek baru (yang memiliki kind yang sama) dengan nama yang sama dengan objek yang kamu hapus sebelumnya.
Berdasarkan ketentuan, nama dari resources Kubernetes memiliki panjang maksimum 253 karakter yang terdiri dari karakter alfanumerik huruf kecil, -
, dan .
, tetapi resources tertentu punya lebih banyak batasan yang spesifik
UID
String yang dihasilkan oleh sistem Kubernetes untuk mengidentifikasi objek secara unik.
Setiap objek yang ada pada klaster Kubernetes memiliki UID yang unik. Hal ini dilakukan untuk membedakan keberadaan historis suatu entitas dengan kind dan nama yang serupa.
3.1.4.4 - Namespace
Kubernetes mendukung banyak klaster virtual di dalam satu klaster fisik. Klaster virtual tersebut disebut dengan namespace.
Kapan menggunakan banyak Namespace
Namespace dibuat untuk digunakan di environment dengan banyak pengguna yang berada di dalam banyak tim ataupun proyek. Untuk sebuah klaster dengan beberapa pengguna saja, kamu tidak harus membuat ataupun memikirkan tentang namespace. Mulai gunakan namespace saat kamu membutuhkan fitur dari namespace itu sendiri.
Namespace menyediakan ruang untuk nama objek. Nama dari resource atau objek harus berbeda di dalam sebuah namespace, tetapi boleh sama jika berbeda namespace. Namespace tidak bisa dibuat di dalam namespace lain dan setiap resource atau objek Kubernetes hanya dapat berada di dalam satu namespace.
Namespace merupakan cara yang digunakan untuk memisahkan resource klaster untuk beberapa pengguna (dengan resource quota).
Dalam versi Kubernetes yang akan datang, objek di dalam satu namespace akan mempunyai access control policies yang sama secara default.
Tidak perlu menggunakan banyak namespace hanya untuk memisahkan sedikit perbedaan pada resource, seperti perbedaan versi dari perangkat lunak yang sama: gunakan label untuk membedakan resource di dalam namespace yang sama.
Bekerja dengan Namespace
Pembuatan dan penghapusan namespace dijelaskan di dokumentasi panduan admin untuk namespace.
Melihat namespace
Kamu dapat melihat daftar namespace di dalam klaster menggunakan:
kubectl get namespace
NAME STATUS AGE
default Active 1d
kube-system Active 1d
kube-public Active 1d
Kubernetes berjalan dengan tiga namespace awal:
default
, namespace default untuk objek yang dibuat tanpa mencantumkan namespace pada spesifikasinya.kube-system
, namespace yang digunakan untuk objek yang dibuat oleh sistem Kubernetes.kube-public
, namespace ini dibuat secara otomatis dan dapat diakses oleh semua pengguna (termasuk yang tidak diautentikasi). Namespace ini disediakan untuk penggunaan klaster, jika beberapa resouce harus terlihat dan dapat dibaca secara publik di seluruh klaster. Aspek publik dari namespace ini hanya sebuah konvensi, bukan persyaratan.
Mengkonfigurasi namespace untuk request
Untuk mengkonfigurasi sementara request untuk menggunakan namespace tertentu, gunakan --namespace
flag.
Sebagai contoh:
kubectl --namespace=<insert-namespace-name-here> run nginx --image=nginx
kubectl --namespace=<insert-namespace-name-here> get pods
Mengkonfigurasi preferensi namespace
Kamu dapat menyimpan konfigurasi namespace untuk semua perintah kubectl
dengan perintah:
kubectl config set-context --current --namespace=<insert-namespace-name-here>
# Cek namespace
kubectl config view | grep namespace:
Namespace dan DNS
Saat kamu membuat sebuah Service, Kubernetes membuat Entri DNS untuk service tersebut. Entri DNS ini berformat <service-name>.<namespace-name>.svc.cluster.local
, yang berarti jika sebuah kontainer hanya menggunakan <service-name>
, kontainer tersebut akan berkomunikasi dengan service yang berada di dalam satu namespace. Ini berguna untuk menggunakan konfigurasi yang sama di beberapa namespace seperti Development, Staging, dan Production. Jika kamu ingin berkomunikasi antar namespace, kamu harus menggunakan seluruh fully qualified domain name (FQDN).
Tidak semua objek di dalam Namespace
Kebanyakan resource di Kubernetes (contohnya pod, service, replication controller, dan yang lain) ada di dalam namespace. Namun resource namespace sendiri tidak berada di dalam namespace. Dan low-level resource seperti node dan persistentVolume tidak berada di namespace manapun.
Untuk melihat resource di dalam kubernetes yang berada di dalam namespace ataupun tidak:
# Di dalam namespace
kubectl api-resources --namespaced=true
# Tidak di dalam namespace
kubectl api-resources --namespaced=false
3.1.4.5 - Label dan Selektor
Label merupakan pasangan key/value yang melekat pada objek-objek, misalnya pada Pod. Label digunakan untuk menentukan atribut identitas dari objek agar memiliki arti dan relevan bagi para pengguna, namun tidak secara langsung memiliki makna terhadap sistem inti. Label dapat digunakan untuk mengatur dan memilih sebagian dari banyak objek. Label-label dapat ditempelkan ke objek-objek pada saat dibuatnya objek-objek tersebut dan kemudian ditambahkan atau diubah kapan saja setelahnya. Setiap objek dapat memiliki satu set label key/value. Setiap Key harus unik untuk objek tersebut.
"metadata": {
"labels": {
"key1" : "value1",
"key2" : "value2"
}
}
Label memungkinkan untuk menjalankan kueri dan pengamatan dengan efisien, serta ideal untuk digunakan pada UI dan CLI. Informasi yang tidak digunakan untuk identifikasi sebaiknya menggunakan anotasi.
Motivasi
Label memungkinkan pengguna untuk memetakan struktur organisasi mereka ke dalam objek-objek sistem yang tidak terikat secara erat, tanpa harus mewajibkan klien untuk menyimpan pemetaan tersebut.
Service deployments dan batch processing pipelines sering menjadi entitas yang berdimensi ganda (contohnya partisi berganda atau deployment, jalur rilis berganda, tingkatan berganda, micro-services berganda per tingkatan). Manajemen seringkali membutuhkan operasi lintas tim, yang menyebabkan putusnya enkapsulasi dari representasi hierarki yang ketat, khususnya pada hierarki-hierarki kaku yang justru ditentukan oleh infrastruktur, bukan oleh pengguna.
Contoh label:
"release" : "stable"
,"release" : "canary"
"environment" : "dev"
,"environment" : "qa"
,"environment" : "production"
"tier" : "frontend"
,"tier" : "backend"
,"tier" : "cache"
"partition" : "customerA"
,"partition" : "customerB"
"track" : "daily"
,"track" : "weekly"
Ini hanya contoh label yang biasa digunakan; kamu bebas mengembangkan caramu sendiri. Perlu diingat bahwa Key dari label harus unik untuk objek tersebut.
Sintaksis dan set karakter
Label merupakan pasangan key/value. Key-key dari Label yang valid memiliki dua segmen: sebuah prefiks dan nama yang opsional, yang dipisahkan oleh garis miring (/
). Segmen nama wajib diisi dan tidak boleh lebih dari 63, dimulai dan diakhiri dengan karakter alfanumerik ([a-z0-9A-Z]
) dengan tanda pisah (-
), garis bawah (_
), titik (.
), dan alfanumerik di antaranya. Sedangkan prefiks bersifat opsional. Jika ditentukan, prefiks harus berupa subdomain DNS: rangkaian label DNS yang dipisahkan oleh titik (.
), dengan total tidak lebih dari 253 karakter, yang diikuti oleh garis miring (/
).
Jika prefiks dihilangkan, Key dari label diasumsikan privat bagi pengguna. Komponen sistem otomatis (contoh kube-scheduler
, kube-controller-manager
, kube-apiserver
, kubectl
, atau otomasi pihak ketiga lainnya) yang akan menambah label ke objek-objek milik pengguna akhir harus menentukan prefiks.
Prefiks kubernetes.io/
dan k8s.io/
dikhususkan untuk komponen inti Kubernetes.
Nilai label yang valid tidak boleh lebih dari 63 karakter dan harus kosong atau diawali dan diakhiri dengan karakter alfanumerik ([a-z0-9A-Z]
) dengan tanda pisah (-
), garis bawah (_
), titik (.
), dan alfanumerik di antaranya.
Contoh di bawah ini merupakan berkas konfigurasi untuk Pod yang memiliki dua label environment: production
dan app: nginx
:
apiVersion: v1
kind: Pod
metadata:
name: label-demo
labels:
environment: production
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Selektor label
Tidak seperti nama dan UID, label tidak memberikan keunikan. Secara umum, kami memperkirakan bahwa banyak objek yang akan memiliki label yang sama.
Menggunakan sebuah label selector, klien/pengguna dapat mengidentifikasi suatu kumpulan objek. Selektor label merupakan alat/cara pengelompokan utama pada Kubernetes.
Saat ini API mendukung dua jenis selektor: equality-based dan set-based.
Sebuah selektor label dapat dibuat dari kondisi berganda yang dipisahkan oleh koma. Pada kasus kondisi berganda, semua kondisi harus dipenuhi sehingga separator koma dapat bertindak sebagai operator logika AND (&&
).
Makna dari selektor yang kosong atau tidak diisi tergantung dari konteks, dan tipe API yang menggunakan selektor harus mendokumentasikan keabsahan dan arti dari selektor yang kosong tersebut.
||
). Pastikan struktur pernyataan filter kamu ikut disesuaikan.
Kondisi Equality-based
Kondisi Equality-based atau inequality-based memungkinkan untuk melakukan filter dengan menggunakan key dan value dari label. Objek yang cocok harus memenuhi semua batasan label yang telah ditentukan, meskipun mereka dapat memiliki label tambahan lainnya.
Terdapat tiga jenis operator yang didukung yaitu =
,==
,!=
. Dua operator pertama menyatakan kesamaan (keduanya hanyalah sinonim), sementara operator terakhir menyatakan ketidaksamaan. Contoh:
environment = production
tier != frontend
Kondisi pertama akan memilih semua sumber daya dengan key environment
dan nilai key production
.
Kondisi berikutnya akan memilih semua sumber daya dengan key tier
dan nilai key selain frontend
, dan semua sumber daya yang tidak memiliki label dengan key tier
.
Kamu juga dapat memfilter sumber daya dalam production
selain frontend
dengan menggunakan operator koma: environment=production,tier!=frontend
Salah satu skenario penggunaan label dengan kondisi equality-based yaitu untuk kriteria pemilihan Node untuk Pod-Pod. Sebagai contoh, Pod percontohan di bawah ini akan memilih Node dengan label "accelerator=nvidia-tesla-p100
".
apiVersion: v1
kind: Pod
metadata:
name: cuda-test
spec:
containers:
- name: cuda-test
image: "k8s.gcr.io/cuda-vector-add:v0.1"
resources:
limits:
nvidia.com/gpu: 1
nodeSelector:
accelerator: nvidia-tesla-p100
Kondisi Set-based
Kondisi label Set-based memungkinkan memfilter key terhadap suatu kumpulan nilai. Terdapat tiga jenis operator yang didukung, yaitu: in
,notin
, dan exists
(hanya key-nya saja). Contoh:
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
Contoh pertama akan memilih semua sumber daya dengan key environment
dan nilai production
atau qa
.
Contoh kedua akan memilih semua sumber daya dengan key tier
dan nilai selain frontend
dan backend
, serta semua sumber daya yang tidak memiliki label dengan key tier
.
Contoh ketiga akan memilih semua sumber daya yang memiliki key dari labelpartition
; nilainya tidak diperiksa.
Sedangkan contoh keempat akan memilih semua sumber daya yang tidak memiliki label dengan key partition
; nilainya tidak diperiksa.
Secara serupa, operator koma bertindak sebagai operator AND. Sehingga penyaringan sumber daya dengan key partition
(tidak peduli nilai dari key) dan environment
yang tidak sama dengan qa
dapat dicapai dengan partition,environment notin (qa)
.
Selektor label set-based merupakan bentuk umum persamaan karena environment=production
sama dengan environment in (production)
; demikian pula !=
dan notin
.
Kondisi Set-based dapat digabungkan dengan kondisi equality-based. Contoh: partition in (customerA, customerB),environment!=qa
.
API
Penyaringan LIST dan WATCH
Operasi LIST dan WATCH dapat menentukan selektor label untuk memfilter suatu kumpulan objek yang didapat dengan menggunakan parameter kueri. Kedua jenis kondisi diperbolehkan (ditampilkan sebagai berikut, sama seperti saat tampil pada string kueri di URL):
- Kondisi equality-based:
?labelSelector=environment%3Dproduction,tier%3Dfrontend
- Kondisi set-based:
?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29
Kedua jenis selektor label dapat digunakan untuk menampilkan (list) dan mengamati (watch) sumber daya melalui klien REST. Contohnya, menargetkan apiserver
dengan kubectl
dan menggunakan equality-based kamu dapat menuliskan:
kubectl get pods -l environment=production,tier=frontend
atau menggunakan kondisi set-based:
kubectl get pods -l 'environment in (production),tier in (frontend)'
Seperti yang telah disebutkan sebelumnya, kondisi set-based lebih ekspresif. Sebagai contoh, mereka dapat digunakan untuk mengimplementasi operator OR pada nilai:
kubectl get pods -l 'environment in (production, qa)'
atau membatasi pencocokan negatif dengan operator exists:
kubectl get pods -l 'environment,environment notin (frontend)'
Mengatur referensi pada objek API
Pada beberapa objek Kubernetes, seperti Service
dan ReplicationController
, juga menggunakan selektor label untuk menentukan kumpulan dari sumber daya lain, seperti Pod.
Service dan ReplicationController
Kumpulan Pod yang ditargetkan oleh sebuah service
ditentukan dengan selektor label. Demikian pula kumpulan Pod yang harus ditangani oleh replicationcontroller
juga ditentukan dengan selektor label.
Selektor label untuk kedua objek tersebut ditentukan dalam berkas json
atau yaml
menggunakan maps, dan hanya mendukung kondisi equality-based:
"selector": {
"component" : "redis",
}
atau
selector:
component: redis
selektor ini (baik dalam bentuk json
atau yaml
) sama dengan component=redis
atau component in (redis)
.
Sumber daya yang mendukung kondisi set-based
Sumber daya yang lebih baru, seperti Job
, Deployment
, ReplicaSet
, dan DaemonSet
, juga mendukung kondisi set-based.
selector:
matchLabels:
component: redis
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
matchLabels
merupakan pemetaan dari pasangan {key,value}
. Sebuah {key,value}
pada pemetaan matchLabels
adalah sama dengan elemen dari matchExpressions
, yang nilai key
nya adalah "key", dengan operator
"In", dan array values
hanya berisi "value". matchExpressions
merupakan daftar kondisi untuk selektor Pod. Operator yang valid termasuk In, NotIn, Exists, dan DoesNotExist. Kumpulan nilai ini tidak boleh kosong pada kasus In dan NotIn. Semua kondisi, baik dari matchLabels
dan matchExpressions
di-AND secara sekaligus -- mereka harus memenuhi semua kondisi agar cocok.
Memilih kumpulan Node
Salah satu contoh penggunaan pemilihan dengan menggunakan label yaitu untuk membatasi suatu kumpulan Node tertentu yang dapat digunakan oleh Pod. Lihat dokumentasi pada pemilihan Node untuk informasi lebih lanjut.
3.1.4.6 - Anotasi
Kamu dapat menggunakan fitur anotasi dari Kubernetes untuk menempelkan sembarang metadata tanpa identitas pada suatu objek. Klien, seperti perangkat dan library, dapat memperoleh metadata tersebut.
Mengaitkan metadata pada objek
Kamu dapat menggunakan label maupun anotasi untuk menempelkan metadata pada suatu objek Kubernetes. Label dapat digunakan untuk memilih objek dan mencari sekumpulan objek yang memenuhi kondisi tertentu. Sebaliknya, anotasi tidak digunakan untuk mengenali atau memilih objek. Metadata dalam sebuah anotasi bisa berukuran kecil atau besar, terstruktur atau tidak terstruktur, dan dapat berisikan karakter-karakter yang tidak diperbolehkan oleh label.
Anotasi, seperti label, merupakan pemetaan key/value:
"metadata": {
"annotations": {
"key1" : "value1",
"key2" : "value2"
}
}
Berikut merupakan beberapa contoh informasi yang dapat dicatat dengan menggunakan anotasi:
-
Field-field yang dikelola secara deklaratif oleh layer konfigurasi. Menempelkan field-field tersebut sebagai anotasi membedakan mereka dari nilai default yang ditetapkan oleh klien ataupun server, dari field-field yang otomatis di-generate, serta dari field-field yang ditetapkan oleh sistem auto-sizing atau auto-scaling.
-
Informasi mengenai build, rilis, atau image, seperti timestamp, rilis ID, git branch, nomor PR, hash suatu image, dan alamat registri.
-
Penanda untuk logging, monitoring, analytics, ataupun repositori audit.
-
Informasi mengenai library klien atau perangkat yang dapat digunakan untuk debugging: misalnya, informasi nama, versi, dan build.
-
Informasi yang berhubungan dengan pengguna atau perangkat/sistem, seperti URL objek yang terkait dengan komponen dari ekosistem lain.
-
Metadata untuk perangkat rollout yang ringan (lightweight): contohnya, untuk konfigurasi atau penanda (checkpoint).
-
Nomor telepon atau pager dari orang yang bertanggung jawab, atau entri direktori yang berisi informasi lebih lanjut, seperti website sebuah tim.
-
Arahan dari pengguna (end-user) untuk melakukan implementasi, perubahan perilaku, ataupun untuk interaksi dengan fitur-fitur non-standar.
Tanpa menggunakan anotasi, kamu dapat saja menyimpan informasi-informasi dengan tipe di atas pada suatu basis data atau direktori eksternal, namun hal ini sangat mempersulit pembuatan library klien dan perangkat yang bisa digunakan sama-sama (shared) untuk melakukan deploy, pengelolaan, introspeksi, dan semacamnya.
Sintaksis dan sekumpulan karakter
Anotasi merupakan key/value pair. Key dari sebuah anotasi yang valid memiliki dua segmen: segmen prefiks yang opsional dan segmen nama, dipisahkan
oleh sebuah garis miring (/
). Segmen nama bersifat wajib dan harus terdiri dari 63 karakter atau kurang, dimulai dan diakhiri dengan karakter alfanumerik ([a-z0-9A-Z]
) dengan tanda minus (-
), garis bawah (_
), titik (.
), dan alfanumerik di tengahnya. Jika terdapat prefiks,
prefiks haruslah berupa subdomain DNS: urutan dari label DNS yang dipisahkan oleh titik (.
), totalnya tidak melebihi 253 karakter,
diikuti dengan garis miring (/
).
Jika tidak terdapat prefiks, maka key dari anotasi diasumsikan hanya bisa dilihat oleh pengguna (privat). Komponen sistem otomasi
(seperti kube-scheduler
, kube-controller-manager
, kube-apiserver
, kubectl
, ataupun otomasi pihak ketiga) yang menambahkan anotasi
pada objek-objek pengguna harus memiliki sebuah prefiks.
Prefiks kubernetes.io/
dan k8s.io/
merupakan reservasi dari komponen inti Kubernetes.
Selanjutnya
Pelajari lebih lanjut tentang Label dan Selektor.
3.1.4.7 - Selektor Field
Selektor field memungkinkan kamu untuk memilih (select) resource Kubernetes berdasarkan nilai dari satu atau banyak field resource. Di bawah ini merupakan contoh dari beberapa query selektor field:
metadata.name=my-service
metadata.namespace!=default
status.phase=Pending
Perintah kubectl
di bawah ini memilih semua Pod dengan field status.phase
yang bernilai
Running
:
kubectl get pods --field-selector status.phase=Running
Pada dasarnya, selektor field merupakan filter dari resource. Secara default, tidak ada selektor/filter apapun yang diterapkan. Artinya,
semua resource dengan tipe apapun akan terpilih. Akibatnya, query dengan perintah kubectl
di bawah ini akan memberikan hasil yang sama:
kubectl get pods
kubectl get pods --field-selector ""
Field yang didukung
Selektor-selektor field yang didukung oleh Kubernetes bervariasi tergantung dari tipe resource. Semua tipe resource mendukung field
metadata.name
dan metadata.namespace
. Jika kamu menggunakan selektor field yang tidak didukung, maka akan terjadi error. Contohnya:
kubectl get ingress --field-selector foo.bar=baz
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"
Operator yang didukung
Kamu dapat menggunakan operator =
, ==
, dan !=
pada selektor field (=
dan ==
punya arti yang sama). Sebagai contoh, perintah kubectl
ini
memilih semua Kubernetes Service yang tidak terdapat pada namespace default
:
kubectl get services --field-selector metadata.namespace!=default
Selektor berantai
Seperti halnya label dan selektor-selektor lainnya, kamu dapat membuat selektor field berantai
(chained) dengan list yang dipisahkan oleh koma. Perintah kubectl
di bawah ini memilih semua Pod dengan status.phase
tidak sama dengan
Running
dan field spec.restartPolicy
sama dengan Always
:
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always
Resource dengan beberapa tipe
Kamu dapat menggunakan selektor-selektor field dengan beberapa tipe resource sekaligus. Perintah kubectl
di bawah ini memilih semua Statefulset
dan Service yang tidak terdapat pada namespace default
:
kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default
3.1.4.8 - Label yang Disarankan
Kamu dapat melakukan visualisasi dan mengatur objek Kubernetes dengan lebih banyak tools dibandingkan dengan perintah kubectl dan dasbor. Sekumpulan label mengizinkan tools untuk bekerja dengan interoperabilitas, mendeskripsikan objek dengan cara yang umum yang dapat dipahami semua tools.
Sebagai tambahan bagi tooling tambahan, label yang disarankan ini mendeskripsikan aplikasi sehingga informasi yang ada diapat di-query.
Metadata ini diorganisasi berbasis konsep dari sebuah aplikasi. Kubernetes bukan merupakan sebuah platform sebagai sebuah service (platform as a service/PaaS) dan tidak mewajibkan sebuah gagasan formal dari sebuah aplikasi. Sebagai gantinya, aplikasi merupakan suatu hal informal yang dideskripsikan melalui metadata. Definisi yang dimiliki oleh sebuah aplikasi merupakan sebuah hal yang cukup longgar.
Label yang digunakan secara umum serta anotasi memiliki prefiks yang serupa: app.kubernetes.io
. Label
tanpa sebuah prefiks bersifat privat khusus pengguna saja. Prefiks yang digunakan secara umum tadi
menjamin bahwa label tadi tidak akan mengganggu label custom yang diberikan oleh pengguna.
Label
Untuk mendapatkan keuntungan menyeluruh dari penggunaan label ini, label harus digunakan pada seluruh objek sumber daya.
Key | Deskripsi | Contoh | Tipe |
---|---|---|---|
app.kubernetes.io/name |
Nama aplikasi | mysql |
string |
app.kubernetes.io/instance |
Nama unik yang bersifat sebagai pengidentifikasi dari sebuah instans aplikasi | wordpress-abcxzy |
string |
app.kubernetes.io/version |
Versi saat ini dari aplikasi (misalnya sebuah versi semantik, hash revisi, etc.) | 5.7.21 |
string |
app.kubernetes.io/component |
Komponen yang ada pada arsitektur | database |
string |
app.kubernetes.io/part-of |
Nama dari komponen lebih tinggi dari aplikasi yang mencakup bagian ini | wordpress |
string |
app.kubernetes.io/managed-by |
Alat yang digunakan untuk mengatur operasi pada aplikasi | helm |
string |
Untuk memberikan ilustrasi dari penggunaan label, bayangkan sebuah objek StatefulSet yang didefinisikan sebagai berikut:
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/managed-by: helm
Aplikasi dan Instans Aplikasi
Sebuah aplikasi dapat diinstal sekali atau beberapa kali di dalam klaster Kubernetes dan, pada beberapa kasus, di dalam sebuah namespace yang sama. Misalnya, wordpress dapat diinstal lebih dari satu kali dimana situs web yang berbeda merupakan hasil instalasi yang berbeda.
Nama dari sebuah aplikasi dan nama instans akan dicatat secara terpisah. Sebagai contoh,
WordPress memiliki wordpress
sebagai nilai dari app.kubernetes.io/name
dimana
nama instans yang digunakan adalah wordpress-abcxzy
yang merupakan nilai dari app.kubernetes.io/instance
.
Hal ini memungkinkan aplikasi dan instans aplikasi untuk dapat diidentifikasi. Setiap instans dari aplikasi
haruslah memiliki nama yang unik.
Contoh
Untuk memberikan ilustrasi dengan cara yang berbeda pada penggunaan label, contoh di bawah ini memiliki tingkat kompleksitas yang cukup beragam.
Sebuah Aplikasi Stateless Sederhana
Bayangkan sebuah kasus dimana sebuah aplikasi stateless di-deploy menggunakan Deployment dan Service. Di bawah ini merupakan contoh kutipan yang merepresentasikan bagaimana label dapat digunakan secara sederhana.
Deployment digunakan untuk memastikan Pod dijalankan untuk aplikasi itu sendiri.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
Service digunakan untuk mengekspos aplikasi.
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
Sebuah Aplikasi Web dengan Basis Data
Bayangkan sebuah aplikasi yang lebih kompleks: sebuah aplikasi web (WordPress) yang menggunakan basis data (MySQL), yang diinstal menggunakan Helm. Kutipan berikut merepresentasikan objek yang di-deploy untuk aplikasi ini.
Berikut merupakan konfigurasi Deployment yang digunakan untuk WordPress:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
Service yang digunakan untuk mengekspos WordPress:
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
MySQL diekspos sebagai StatefulSet dengan metadata yang digunakan untuk StatefulSet tersebut serta aplikasi yang menggunakannya:
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
...
Service yang digunakan untuk mengekspos MySQL sebagai bagian dari WordPress:
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
...
Dengan StatefulSet MySQL dan Service kamu dapat mengetahui informasi yang ada pada MySQL dan Wordpress.
3.2 - Arsitektur Kubernetes
3.2.1 - Node
Node merupakan sebuah mesin worker di dalam Kubernetes, yang sebelumnya dinamakan minion
.
Sebuah node bisa berupa VM ataupun mesin fisik, tergantung dari klaster-nya.
Masing-masing node berisi beberapa servis yang berguna untuk menjalankan banyak pod dan diatur oleh komponen-komponen yang dimiliki oleh master.
Servis-servis di dalam sebuah node terdiri dari runtime kontainer, kubelet dan kube-proxy.
Untuk lebih detail, lihat dokumentasi desain arsitektur pada Node Kubernetes.
Status Node
Sebuah status node berisikan informasi sebagai berikut:
Masing-masing bagian dijelaskan secara rinci di bawah ini.
Addresses
Penggunaan field-field ini bergantung pada penyedia layanan cloud ataupun konfigurasi bare metal yang kamu punya.
- HostName: Merupakan hostname yang dilaporkan oleh kernel node. Dapat diganti melalui parameter
--hostname-override
pada kubelet. - ExternalIP: Biasanya merupakan alamat IP pada node yang punya route eksternal (bisa diakses dari luar klaster).
- InternalIP: Biasanya merupakan alamat IP pada node yang hanya punya route di dalam klaster.
Condition
Field conditions
menjelaskan tentang status dari semua node yang sedang berjalan (Running
).
Kondisi Node | Penjelasan |
---|---|
OutOfDisk |
True jika node sudah tidak punya cukup kapasitas disk untuk menjalankan pod baru, False jika sebaliknya |
Ready |
True jika node sehat (healthy) dan siap untuk menerima pod, False jika node tidak lagi sehat (unhealthy) dan tidak siap menerima pod, serta Unknown jika kontroler node tidak menerima pesan di dalam node-monitor-grace-period (standarnya 40 detik) |
MemoryPressure |
True jika memori pada node terkena tekanan (pressure) -- maksudnya, jika kapasitas memori node sudah di titik rendah; False untuk sebaliknya |
PIDPressure |
True jika process-process mengalami tekanan (pressure) -- maksudnya, jika node menjalankan terlalu banyak process; False untuk sebaliknya |
DiskPressure |
True jika ukuran disk mengalami tekanan (pressure) -- maksudnya, jika kapasitas disk sudah di titik rendah; False untuk sebaliknya |
NetworkUnavailable |
True jika jaringan untuk node tidak dikonfigurasi dengan benar, False untuk sebaliknya |
Condition pada node direpresentasikan oleh suatu obyek JSON. Sebagai contoh, respon berikut ini menggambarkan node yang sedang sehat (healthy).
"conditions": [
{
"type": "Ready",
"status": "True"
}
]
Jika status untuk Ready condition
bernilai Unknown
atau False
untuk waktu yang lebih dari pod-eviction-timeout
, tergantung bagaimana kube-controller-manager dikonfigurasi, semua pod yang dijalankan pada node tersebut akan dihilangkan oleh Kontroler Node.
Durasi eviction timeout yang standar adalah lima menit.
Pada kasus tertentu ketika node terputus jaringannya, apiserver tidak dapat berkomunikasi dengan kubelet yang ada pada node.
Keputusan untuk menghilangkan pod tidak dapat diberitahukan pada kubelet, sampai komunikasi dengan apiserver terhubung kembali.
Sementara itu, pod-pod akan terus berjalan pada node yang sudah terputus, walaupun mendapati schedule untuk dihilangkan.
Pada versi Kubernetes sebelum 1.5, kontroler node dapat menghilangkan dengan paksa (force delete) pod-pod yang terputus dari apiserver. Namun, pada versi 1.5 dan seterusnya, kontroler node tidak menghilangkan pod dengan paksa, sampai ada konfirmasi bahwa pod tersebut sudah berhenti jalan di dalam klaster. Pada kasus dimana Kubernetes tidak bisa menarik kesimpulan bahwa ada node yang telah meninggalkan klaster, admin klaster mungkin perlu untuk menghilangkan node secara manual. Menghilangkan obyek node dari Kubernetes akan membuat semua pod yang berjalan pada node tersebut dihilangkan oleh apiserver, dan membebaskan nama-namanya agar bisa digunakan kembali.
Pada versi 1.12, fitur TaintNodesByCondition
telah dipromosikan ke beta, sehingga kontroler lifecycle node secara otomatis membuat taints yang merepresentasikan conditions.
Akibatnya, scheduler menghiraukan conditions ketika mempertimbangkan sebuah Node; scheduler akan melihat pada taints sebuah Node dan tolerations sebuah Pod.
Sekarang, para pengguna dapat memilih antara model scheduling yang lama dan model scheduling yang lebih fleksibel. Pada model yang lama, sebuah pod tidak memiliki tolerations apapun sampai mendapat giliran schedule. Namun, pod dapat dijalankan pada Node tertentu, dimana pod melakukan toleransi terhadap taints yang dimiliki oleh Node tersebut.
Capacity
Menjelaskan tentang resource-resource yang ada pada node: CPU, memori, dan jumlah pod secara maksimal yang dapat dijalankan pada suatu node.
Info
Informasi secara umum pada suatu node, seperti versi kernel, versi Kubernetes (versi kubelet dan kube-proxy), versi Docker (jika digunakan), nama OS. Informasi ini dikumpulkan oleh Kubelet di dalam node.
Manajemen
Tidak seperti pod dan service, sebuah node tidaklah dibuat dan dikonfigurasi oleh Kubernetes: tapi node dibuat di luar klaster oleh penyedia layanan cloud, seperti Google Compute Engine, atau pool mesin fisik ataupun virtual (VM) yang kamu punya. Jadi ketika Kubernetes membuat sebuah node, obyek yang merepresentasikan node tersebut akan dibuat. Setelah pembuatan, Kubernetes memeriksa apakah node tersebut valid atau tidak. Contohnya, jika kamu mencoba untuk membuat node dari konten berikut:
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "10.240.79.157",
"labels": {
"name": "my-first-k8s-node"
}
}
}
Kubernetes membuat sebuah obyek node secara internal (representasinya), dan melakukan validasi terhadap node. Validasi dilakukan dengan memeriksa kondisi kesehatan node (health checking), berdasarkan field metadata.name
. Jika node valid -- terjadi saat semua servis yang diperlukan sudah jalan -- maka node diperbolehkan untuk menjalankan sebuah pod.
Namun jika tidak valid, node tersebut akan dihiraukan untuk aktivitas apapun yang berhubungan dengan klaster, sampai telah menjadi valid.
Saat ini, ada tiga komponen yang berinteraksi dengan antarmuka node di Kubernetes: kontroler node, kubelet, dan kubectl.
Kontroler Node
Kontroler node adalah komponen master Kubernetes yang berfungsi untuk mengatur berbagai aspek dari node.
Kontroler node memiliki berbagai peran (role) dalam sebuah lifecycle node. Pertama, menetapkan blok CIDR pada node tersebut saat registrasi (jika CIDR assignment diaktifkan).
Kedua, terus memperbarui daftar internal node di dalam kontroler node, sesuai dengan daftar mesin yang tersedia di dalam penyedia layanan cloud. Ketika berjalan di dalam environment cloud, kapanpun saat sebuah node tidak lagi sehat (unhealthy), kontroler node bertanya pada penyedia cloud, apakah VM untuk node tersebut masihkah tersedia atau tidak. Jika sudah tidak tersedia, kontroler node menghilangkan node tersebut dari daftar node.
Ketiga, melakukan monitor terhadap kondisi kesehatan (health) node.
Kontroler node bertanggung jawab untuk mengubah status NodeReady condition
pada NodeStatus
menjadi ConditionUnknown
, ketika sebuah node terputus jaringannya (kontroler node tidak lagi mendapat heartbeat karena suatu hal, contohnya karena node tidak hidup), dan saat kemudian melakukan eviction terhadap semua pod yang ada pada node tersebut (melalui terminasi halus -- graceful) jika node masih terus terputus. (Timeout standar adalah 40 detik untuk mulai melaporkan ConditionUnknown
dan 5 menit setelah itu untuk mulai melakukan eviction terhadap pod.)
Kontroler node memeriksa state masing-masing node untuk durasi yang ditentukan oleh argumen --node-monitor-period
.
Pada versi Kubernetes sebelum 1.13, NodeStatus
adalah heartbeat yang diberikan oleh node.
Setelah versi 1.13, fitur node lease diperkenalkan sebagai fitur alpha (fitur gate NodeLease
,
KEP-0009).
Ketika fitur node lease diaktifasi, setiap node terhubung dengan obyek Lease
di dalam namespace kube-node-lease
yang terus diperbarui secara berkala.
Kemudian, NodeStatus
dan node lease keduanya dijadikan sebagai heartbeat dari node.
Semua node lease diperbarui sesering mungkin, sedangkan NodeStatus
dilaporkan dari node untuk master hanya ketika ada perubahan atau telah melewati periode waktu tertentu (default-nya 1 menit, lebih lama daripada default timeout node-node yang terputus jaringannya).
Karena node lease jauh lebih ringan daripada NodeStatus
, fitur ini membuat heartbeat dari node jauh lebih murah secara signifikan dari sudut pandang skalabilitas dan performa.
Di Kubernetes 1.4, kami telah memperbarui logic dari kontroler node supaya lebih baik dalam menangani kasus saat banyak sekali node yang tidak bisa terhubung dengan master (contohnya, karena master punya masalah jaringan). Mulai dari 1.4, kontroler node melihat state dari semua node di dalam klaster, saat memutuskan untuk melakukan eviction pada pod.
Pada kasus kebanyakan, kontroler node membatasi rate eviction menjadi --node-eviction-rate
(default-nya 0.1) per detik.
Artinya, kontroler node tidak akan melakukan eviction pada pod lebih dari 1 node per 10 detik.
Perlakuan eviction pada node berubah ketika sebuah node menjadi tidak sehat (unhealthy) di dalam suatu zona availability.
Kontroler node memeriksa berapa persentase node di dalam zona tersebut yang tidak sehat (saat NodeReady condition
menjadi ConditionUnknown
atau ConditionFalse
) pada saat yang bersamaan.
Jika persentase node yang tidak sehat bernilai --unhealthy-zone-threshold
(default-nya 0.55), maka rate eviction berkurang: untuk ukuran klaster yang kecil (saat jumlahnya lebih kecil atau sama dengan jumlah node --large-cluster-size-threshold
- default-nya 50), maka eviction akan berhenti dilakukan.
Jika masih besar jumlahnya, rate eviction dikurangi menjadi --secondary-node-eviction-rate
(default-nya 0.01) per detik.
Alasan kenapa hal ini diimplementasi untuk setiap zona availability adalah karena satu zona bisa saja terputus dari master, saat yang lainnya masih terhubung. Jika klaster tidak menjangkau banyak zona availability yang disediakan oleh penyedia cloud, maka hanya ada satu zona (untuk semua node di dalam klaster).
Alasan utama untuk menyebarkan node pada banyak zona availability adalah supaya workload dapat dipindahkan ke zona sehat (healthy) saat suatu zona mati secara menyeluruh.
Kemudian, jika semua node di dalam suatu zona menjadi tidak sehat (unhealthy), maka kontroler node melakukan eviction pada rate normal --node-eviction-rate
.
Kasus khusus, ketika seluruh zona tidak ada satupun sehat (tidak ada node yang sehat satupun di dalam klaster).
Pada kasus ini, kontroler node berasumsi ada masalah pada jaringan master, dan menghentikan semua eviction sampai jaringan terhubung kembali.
Mulai dari Kubernetes 1.6, kontroler node juga bertanggung jawab untuk melakukan eviction pada pod-pod yang berjalan di atas node dengan taints NoExecute
, ketika pod-pod tersebut sudah tidak lagi tolerate terhadap taints.
Sebagai tambahan, hal ini di-nonaktifkan secara default pada fitur alpha, kontroler node bertanggung jawab untuk menambahkan taints yang berhubungan dengan masalah pada node, seperti terputus atau NotReady
.
Lihat dokumentasi ini untuk bahasan detail tentang taints NoExecute
dan fitur alpha.
Mulai dari versi 1.8, kontroler node bisa diatur untuk bertanggung jawab pada pembuatan taints yang merepresentasikan node condition. Ini merupakan fitur alpha untuk versi 1.8.
Self-Registration untuk Node
Ketika argumen --register-node
pada kubelet bernilai true (default-nya), kubelet akan berusaha untuk registrasi dirinya melalui API server.
Ini merupakan pattern yang disukai, digunakan oleh kebanyakan distros.
Kubelet memulai registrasi diri (self-registration) dengan opsi-opsi berikut:
--kubeconfig
- Path berisi kredensial-kredensial yang digunakan untuk registrasi diri pada apiserver.--cloud-provider
- Cara berbicara pada sebuah penyedia layanan cloud, baca tentang metadata-nya.--register-node
- Registrasi secara otomatis pada API server.--register-with-taints
- Registrasi node dengan daftar taints (dipisahkan oleh koma<key>=<value>:<effect>
). No-op jikaregister-node
bernilai false.--node-ip
- Alamat IP dari node dimana kubelet berjalan.--node-labels
- Label-label untuk ditambahkan saat melakukan registrasi untuk node di dalam klaster (lihat label yang dibatasi secara paksa oleh NodeRestriction admission plugin untuk 1.13+).--node-status-update-frequency
- Menentukan seberapa sering kubelet melaporkan status pada master.
Ketika mode otorisasi Node dan NodeRestriction admission plugin diaktifkan, semua kubelet hanya punya otoritas untuk membuat/modifikasi resource Node masing-masing.
Administrasi Node secara Manual
Seorang admin klaster dapat membuat dan memodifikasi obyek node.
Jika admin ingin untuk membuat obyek node secara manual, atur argument --register-node=false
pada kubelet.
Admin dapat memodifikasi resource-resource node (terlepas dari --register-node
).
Modifikasi terdiri dari pengaturan label pada node dan membuat node tidak dapat di-schedule.
Label-label pada node digunakan oleh selector node untuk mengatur proses schedule untuk pod, misalnya, membatasi sebuah pod hanya boleh dijalankan pada node-node tertentu.
Menandai sebuah node untuk tidak dapat di-schedule mencegah pod baru untuk tidak di-schedule pada node, tanpa mempengaruhi pod-pod yang sudah berjalan pada node tersebut. Ini berguna sebagai langkah persiapan untuk melakukan reboote pada node. Sebagai contoh, untuk menandai sebuah node untuk tidak dapat di-schedule, jalankan perintah berikut:
kubectl cordon $NODENAME
Kapasitas Node
Kapasitas node (jumlah CPU dan memori) adalah bagian dari obyek node. Pada umumnya, node-node melakukan registrasi diri dan melaporkan kapasitasnya saat obyek node dibuat. Jika kamu melakukan administrasi node manual, maka kamu perlu mengatur kapasitas node saat menambahkan node baru.
Scheduler Kubernetes memastikan kalau ada resource yang cukup untuk menjalankan semua pod di dalam sebuah node. Kubernetes memeriksa jumlah semua request untuk kontainer pada sebuah node tidak lebih besar daripada kapasitas node. Hal ini termasuk semua kontainer yang dijalankan oleh kubelet. Namun, ini tidak termasuk kontainer-kontainer yang dijalankan secara langsung oleh runtime kontainer ataupun process yang ada di luar kontainer.
Kalau kamu ingin secara eksplisit menyimpan resource cadangan untuk menjalankan process-process selain Pod, ikut tutorial menyimpan resource cadangan untuk system daemon.
Obyek API
Node adalah tingkatan tertinggi dari resource di dalam Kubernetes REST API. Penjelasan lebih detail tentang obyek API dapat dilihat pada: Obyek Node API.
3.2.2 - Komunikasi antara Control Plane dan Node
Dokumen ini menjelaskan tentang jalur-jalur komunikasi di antara klaster Kubernetes dan control plane yang sebenarnya hanya berhubungan dengan apiserver saja. Kenapa ada dokumen ini? Supaya kamu, para pengguna Kubernetes, punya gambaran bagaimana mengatur instalasi untuk memperketat konfigurasi jaringan di dalam klaster. Hal ini cukup penting, karena klaster bisa saja berjalan pada jaringan tak terpercaya (untrusted network), ataupun melalui alamat-alamat IP publik pada penyedia cloud.
Node Menuju Control Plane
Kubernetes memiliki sebuah pola API "hub-and-spoke". Semua penggunaan API dari Node (atau Pod dimana Pod-Pod tersebut dijalankan) akan diterminasi pada apiserver (tidak ada satu komponen control plane apa pun yang didesain untuk diekspos pada servis remote). Apiserver dikonfigurasi untuk mendengarkan koneksi aman remote yang pada umumnya terdapat pada porta HTTPS (443) dengan satu atau lebih bentuk autentikasi klien yang dipasang. Sebaiknya, satu atau beberapa metode otorisasi juga dipasang, terutama jika kamu memperbolehkan permintaan anonim (anonymous request) ataupun service account token.
Jika diperlukan, Pod-Pod dapat terhubung pada apiserver secara aman dengan menggunakan ServiceAccount. Dengan ini, Kubernetes memasukkan public root certificate dan bearer token yang valid ke dalam Pod, secara otomatis saat Pod mulai dijalankan. Kubernetes Service (di dalam semua Namespace) diatur dengan sebuah alamat IP virtual. Semua yang mengakses alamat IP ini akan dialihkan (melalui kube-proxy) menuju endpoint HTTPS dari apiserver.
Komponen-komponen juga melakukan koneksi pada apiserver klaster melalui porta yang aman.
Akibatnya, untuk konfigurasi yang umum dan standar, semua koneksi dari klaster (node-node dan pod-pod yang berjalan di atas node tersebut) menujucontrol planesudah terhubung dengan aman. Dan juga, klaster dancontrol planebisa terhubung melalui jaringan publik dan/atau yang tak terpercaya (untrusted).
Control Plane menuju Node
Ada dua jalur komunikasi utama dari control plane (apiserver) menuju klaster. Pertama, dari apiserver ke proses kubelet yang berjalan pada setiap Node di dalam klaster. Kedua, dari apiserver ke setiap Node, Pod, ataupun Service melalui fungsi proksi pada apiserver
Apiserver menuju kubelet
Koneksi dari apiserver menuju kubelet bertujuan untuk:
- Melihat log dari pod-pod.
- Masuk ke dalam pod-pod yang sedang berjalan (attach).
- Menyediakan fungsi port-forward dari kubelet.
Semua koneksi ini diterminasi pada endpoint HTTPS dari kubelet. Secara default, apiserver tidak melakukan verifikasi serving certificate dari kubelet, yang membuat koneksi terekspos pada serangan man-in-the-middle, dan juga tidak aman untuk terhubung melalui jaringan tak terpercaya (untrusted) dan/atau publik.
Untuk melakukan verifikasi koneksi ini, berikan root certificate pada apiserver melalui tanda --kubelet-certificate-authority
, sehingga apiserver dapat memverifikasi serving certificate dari kubelet.
Cara lainnya, gunakan tunnel SSH antara apiserver dan kubelet jika diperlukan, untuk menghindari komunikasi melalui jaringan tak terpercaya (untrusted) atau publik.
Terakhir, yang terpenting, aktifkan autentikasi dan/atau otorisasi Kubelet untuk mengamankan API kubelet.
Apiserver menuju Node, Pod, dan Service
Secara default, koneksi apiserver menuju node, pod atau service hanyalah melalui HTTP polos (plain), sehingga tidak ada autentikasi maupun enkripsi.
Koneksi tersebut bisa diamankan melalui HTTPS dengan menambahkan https:
pada URL API dengan nama dari node, pod, atau service.
Namun, koneksi tidak tervalidasi dengan certificate yang disediakan oleh endpoint HTTPS maupun kredensial client, sehingga walaupun koneksi sudah terenkripsi, tidak ada yang menjamin integritasnya.
Koneksi ini tidak aman untuk dilalui pada jaringan publik dan/atau tak terpercaya untrusted.
Tunnel SSH
Kubernetes menyediakan tunnel SSH untuk mengamankan jalur komunikasi control plane -> Klaster. Dengan ini, apiserver menginisiasi sebuah tunnel SSH untuk setiap node di dalam klaster (terhubung ke server SSH di port 22) dan membuat semua trafik menuju kubelet, node, pod, atau service dilewatkan melalui tunnel tesebut. Tunnel ini memastikan trafik tidak terekspos keluar jaringan dimana node-node berada.
Tunnel SSH saat ini sudah usang (deprecated), jadi sebaiknya jangan digunakan, kecuali kamu tahu pasti apa yang kamu lakukan. Sebuah desain baru untuk mengganti kanal komunikasi ini sedang disiapkan.
3.2.3 - Controller
Dalam bidang robotika dan otomatisasi, control loop atau kontrol tertutup adalah lingkaran tertutup yang mengatur keadaan suatu sistem.
Berikut adalah salah satu contoh kontrol tertutup: termostat di sebuah ruangan.
Ketika kamu mengatur suhunya, itu mengisyaratkan ke termostat tentang keadaan yang kamu inginkan. Sedangkan suhu kamar yang sebenarnya adalah keadaan saat ini. Termostat berfungsi untuk membawa keadaan saat ini mendekati ke keadaan yang diinginkan, dengan menghidupkan atau mematikan perangkat.
Di Kubernetes, controller adalah kontrol tertutup yang mengawasi keadaan klaster klaster kamu, lalu membuat atau meminta perubahan jika diperlukan. Setiap controller mencoba untuk memindahkan status klaster saat ini mendekati keadaan yang diinginkan.
Di Kubernetes, pengontrol adalah kontrol tertutup yang mengawasi kondisi klaster, lalu membuat atau meminta perubahan jika diperlukan. Setiap pengontrol mencoba untuk memindahkan status klaster saat ini lebih dekat ke kondisi yang diinginkan.Pola controller
Sebuah controller melacak sekurang-kurangnya satu jenis sumber daya dari Kubernetes. objek-objek ini memiliki spec field yang merepresentasikan keadaan yang diinginkan. Satu atau lebih controller untuk resource tersebut bertanggung jawab untuk membuat keadaan sekarang mendekati keadaan yang diinginkan.
Controller mungkin saja melakukan tindakan itu sendiri; namun secara umum, di Kubernetes, controller akan mengirim pesan ke API server yang mempunyai efek samping yang bermanfaat. Kamu bisa melihat contoh-contoh di bawah ini.
Kontrol melalui server API
Controller Job adalah contoh dari controller bawaan dari Kubernetes. Controller bawaan tersebut mengelola status melalui interaksi dengan server API dari suatu klaster.
Job adalah sumber daya dalam Kubernetes yang menjalankan a Pod, atau mungkin beberapa Pod sekaligus, untuk melakukan sebuah pekerjaan dan kemudian berhenti.
(Setelah dijadwalkan, objek Pod akan menjadi bagian dari keadaan yang diinginkan oleh kubelet).
Ketika controller job melihat tugas baru, maka controller itu memastikan bahwa, di suatu tempat pada klaster kamu, kubelet dalam sekumpulan Node menjalankan Pod-Pod dengan jumlah yang benar untuk menyelesaikan pekerjaan. Controller job tidak menjalankan sejumlah Pod atau kontainer apa pun untuk dirinya sendiri. Namun, controller job mengisyaratkan kepada server API untuk membuat atau menghapus Pod. Komponen-komponen lain dalam control plane bekerja berdasarkan informasi baru (adakah Pod-Pod baru untuk menjadwalkan dan menjalankan pekerjan), dan pada akhirnya pekerjaan itu selesai.
Setelah kamu membuat Job baru, status yang diharapkan adalah bagaimana pekerjaan itu bisa selesai. Controller job membuat status pekerjaan saat ini agar mendekati dengan keadaan yang kamu inginkan: membuat Pod yang melakukan pekerjaan yang kamu inginkan untuk Job tersebut, sehingga Job hampir terselesaikan.
Controller juga memperbarui objek yang mengkonfigurasinya. Misalnya: setelah
pekerjaan dilakukan untuk Job tersebut, controller job memperbarui objek Job
dengan menandainya Finished
.
(Ini hampir sama dengan bagaimana beberapa termostat mematikan lampu untuk mengindikasikan bahwa kamar kamu sekarang sudah berada pada suhu yang kamu inginkan).
Kontrol Langsung
Berbeda dengan sebuah Job, beberapa dari controller perlu melakukan perubahan sesuatu di luar dari klaster kamu.
Sebagai contoh, jika kamu menggunakan kontrol tertutup untuk memastikan apakah cukup Node dalam kluster kamu, maka controller memerlukan sesuatu di luar klaster saat ini untuk mengatur Node-Node baru apabila dibutuhkan.
controller yang berinteraksi dengan keadaan eksternal dapat menemukan keadaan yang diinginkannya melalui server API, dan kemudian berkomunikasi langsung dengan sistem eksternal untuk membawa keadaan saat ini mendekat keadaan yang diinginkan.
(Sebenarnya ada sebuah controller yang melakukan penskalaan node secara horizontal dalam klaster kamu.
Status sekarang berbanding status yang diinginkan
Kubernetes mengambil pandangan sistem secara cloud-native, dan mampu menangani perubahan yang konstan.
Klaster kamu dapat mengalami perubahan kapan saja pada saat pekerjaan sedang berlangsung dan kontrol tertutup secara otomatis memperbaiki setiap kegagalan. Hal ini berarti bahwa, secara potensi, klaster kamu tidak akan pernah mencapai kondisi stabil.
Selama controller dari klaster kamu berjalan dan mampu membuat perubahan yang bermanfaat, tidak masalah apabila keadaan keseluruhan stabil atau tidak.
Perancangan
Sebagai prinsip dasar perancangan, Kubernetes menggunakan banyak controller yang masing-masing mengelola aspek tertentu dari keadaan klaster. Yang paling umum, kontrol tertutup tertentu menggunakan salah satu jenis sumber daya sebagai suatu keadaan yang diinginkan, dan memiliki jenis sumber daya yang berbeda untuk dikelola dalam rangka membuat keadaan yang diinginkan terjadi.
Sangat penting untuk memiliki beberapa controller sederhana daripada hanya satu controller saja, dimana satu kumpulan monolitik kontrol tertutup saling berkaitan satu sama lain. Karena controller bisa saja gagal, sehingga Kubernetes dirancang untuk memungkinkan hal tersebut.
Misalnya: controller pekerjaan melacak objek pekerjaan (untuk menemukan adanya pekerjaan baru) dan objek Pod (untuk menjalankan pekerjaan tersebut dan kemudian melihat lagi ketika pekerjaan itu sudah selesai). Dalam hal ini yang lain membuat pekerjaan, sedangkan controller pekerjaan membuat Pod-Pod.
Ada kemungkinan beberapa controller membuat atau memperbarui jenis objek yang sama. Namun di belakang layar, controller Kubernetes memastikan bahwa mereka hanya memperhatikan sumbr daya yang terkait dengan sumber daya yang mereka kendalikan.
Misalnya, kamu dapat memiliki Deployment dan Job; dimana keduanya akan membuat Pod. Controller Job tidak akan menghapus Pod yang dibuat oleh Deployment kamu, karena ada informasi (labels) yang dapat oleh controller untuk membedakan Pod-Pod tersebut.
Berbagai cara menjalankan beberapa controller
Kubernetes hadir dengan seperangkat controller bawaan yang berjalan di dalam kube-controller-manager. Beberapa controller bawaan memberikan perilaku inti yang sangat penting.
Controller Deployment dan controller Job adalah contoh dari controller yang hadir sebagai bagian dari Kubernetes itu sendiri (controller "bawaan"). Kubernetes memungkinkan kamu menjalankan control plane yang tangguh, sehingga jika ada controller bawaan yang gagal, maka bagian lain dari control plane akan mengambil alih pekerjaan.
Kamu juga dapat menemukan pengontrol yang berjalan di luar control plane, untuk mengembangkan lebih jauh Kubernetes. Atau, jika mau, kamu bisa membuat controller baru sendiri. Kamu dapat menjalankan controller kamu sendiri sebagai satu kumpulan dari beberapa Pod, atau bisa juga sebagai bagian eksternal dari Kubernetes. Manakah yang paling sesuai akan tergantung pada apa yang controller khusus itu lakukan.
Selanjutnya
- Silahkan baca tentang control plane Kubernetes
- Temukan beberapa dasar tentang objek-objek Kubernetes
- Pelajari lebih lanjut tentang Kubernetes API
- Apabila kamu ingin membuat controller sendiri, silakan lihat pola perluasan dalam memperluas Kubernetes.
3.2.4 - Konsep-konsep di balik Controller Manager
Konsep Cloud Controller Manager/CCM (jangan tertukar dengan program biner kube-controller-manager) awalnya dibuat untuk memungkinkan kode vendor cloud spesifik dan kode inti Kubernetes untuk berkembang secara independen satu sama lainnya. CCM berjalan bersama dengan komponen Master lainnya seperti Kubernetes Controller Manager, API Server, dan Scheduler. CCM juga dapat dijalankan sebagai Kubernetes Addon (tambahan fungsi terhadap Kubernetes), yang akan berjalan di atas klaster Kubernetes.
Desain CCM didasarkan pada mekanisme plugin yang memungkinkan penyedia layanan cloud untuk berintegrasi dengan Kubernetes dengan mudah dengan menggunakan plugin. Sudah ada rencana untuk pengenalan penyedia layanan cloud baru pada Kubernetes, dan memindahkan penyedia layanan cloud yang sudah ada dari model yang lama ke model CCM.
Dokumen ini mendiskusikan konsep di balik CCM dan mendetail fungsi-fungsinya.
Berikut adalah arsitektur sebuah klaster Kubernetes tanpa CCM:
Desain
Pada diagram sebelumnya, Kubernetes dan penyedia layanan cloud diintegrasikan melalui beberapa komponen berbeda:
- Kubelet
- Kubernetes Controller Manager
- Kubernetes API server
CCM menggabungkan semua logika yang bergantung pada cloud dari dalam tiga komponen tersebut ke dalam sebuah titik integrasi dengan cloud. Arsitektur baru di dalam model CCM adalah sebagai berikut:
Komponen-komponen CCM
CCM memisahkan beberapa fungsi Kubernetes Controller Manager (KCM) dan menjalankannya sebagai proses yang berbeda. Secara spesifik, CCM memisahkan pengendali-pengendali (controller) di dalam KCM yang bergantung terhadap penyedia layanan cloud. KCM memiliki beberapa komponen pengendali yang bergantung pada cloud sebagai berikut:
- Node Controller
- Volume Controller
- Route Controller
- Service Controller
Pada versi 1.9, CCM menjalankan pengendali-pengendali dari daftar sebelumnya sebagai berikut:
- Node Controller
- Route Controller
- Service Controller
Rencana awal untuk mendukung volume menggunakan CCM adalah dengan menggunakan FlexVolume untuk mendukung penambahan volume secara pluggable. Namun, ada sebuah usaha lain yang diberi nama Container Storage Interface (CSI) yang sedang berlangsung untuk menggantikan FlexVolume.
Mempertimbangkan dinamika tersebut, kami memutuskan untuk mengambil tindakan sementara hingga CSI siap digunakan.
Fungsi-fungsi CCM
Fungsi-fungsi CCM diwarisi oleh komponen-komponen Kubernetes yang bergantung pada penyedia layanan cloud. Bagian ini disusun berdasarkan komponen-komponen tersebut.
1. Kubernetes Controller Manager
Kebanyakan fungsi CCM diturunkan dari KCM. Seperti yang telah disebutkan pada bagian sebelumnya, CCM menjalankan komponen-komponen pengendali sebagai berikut:
- Node Controller
- Route Controller
- Service Controller
Node Controller
Node Controller bertugas untuk menyiapkan sebuah node dengan cara mengambil informasi node-node yang berjalan di dalam klaster dari penyedia layanan cloud. Node Controller melakukan fungsi-fungsi berikut:
- Menyiapkan sebuah node dengan memberi label zone/region yang spesifik pada cloud.
- Menyiapkan sebuah node dengan informasi instance yang spesifik cloud , misalnya tipe dan ukurannya.
- Mendapatkan alamat jaringan dan hostname milik node tersebut.
- Dalam hal sebuah node menjadi tidak responsif, memeriksa cloud untuk melihat apakah node tersebut telah dihapus dari cloud. Juga, menghapus objek Node tersebut dari klaster Kubernetes, jika node tersebut telah dihapus dari cloud.
Route Controller
Route Controller bertugas mengkonfigurasi rute jaringan di dalam cloud secara sesuai agar Container pada node-node yang berbeda di dalam klaster Kubernetes dapat berkomunikasi satu sama lain. Route Controller hanya berlaku untuk klaster yang berjalan pada Google Compute Engine (GCE) di penyedia layanan cloud GCP.
Service Controller
Service Controller bertugas memantau terjadinya operasi create
, update
, dan delete
pada Service. Berdasarkan keadaan terkini Service-service pada klaster Kubernetes, Service Controller mengkonfigurasi load balancer spesifik cloud (seperti ELB, Google LB, atau Oracle Cloud Infrastructure LB) agar sesuai dengan keadaan Service-service pada klaster Kubernetes. Sebagai tambahan, Service Controller juga memastikan bahwa service backend (target dari load balancer yang bersangkutan) dari load balancer cloud tersebut berada dalam kondisi terkini.
2. Kubelet
Node Controller berisi fungsi Kubelet yang bergantung pada cloud. Sebelum CCM, Kubelet bertugas untuk menyiapkan node dengan informasi spesifik cloud seperti alamat IP, label zone/region, dan tipe instance. Setelah diperkenalkannya CCM, tugas tersebut telah dipindahkan dari Kubelet ke dalam CCM.
Pada model baru ini, Kubelet menyiapkan sebuah node tanpa informasi spesifik cloud. Namun, Kubelet menambahkan sebuah Taint pada node yang baru dibuat yang menjadikan node tersebut tidak dapat dijadwalkan (sehingga tidak ada Pod yang dapat dijadwalkan ke node tersebut) hingga CCM menyiapkan node tersebut dengan informasi spesifik cloud. Setelah itu, Kubelet menghapus Taint tersebut.
Mekanisme Plugin
CCM menggunakan interface Go untuk memungkinkan implementasi dari cloud apapun untuk ditambahkan. Secara spesifik, CCM menggunakan CloudProvider Interface yang didefinisikan di sini
Implementasi dari empat kontroler-kontroler yang disorot di atas, dan beberapa kerangka kerja, bersama dengan CloudProvider Interface, akan tetap berada pada kode inti Kubernetes. Implementasi spesifik penyedia layanan cloud akan dibuat di luar kode inti dan menggunakan CloudProvider Interface yang didefinisikan di kode inti.
Untuk informasi lebih lanjut mengenai pengembangan plugin, lihat Mengembangkan Cloud Controller Manager.
Otorisasi
Bagian ini memerinci akses yang dibutuhkan oleh CCM terhadap berbagai objek API untuk melakukan tugas-tugasnya.
Akses untuk Node Controller
Node Controller hanya berinteraksi dengan objek-objek Node. Node Controller membutuhkan akses penuh untuk operasi get
, list
, create
, update
, patch
, watch
, dan delete
terhadap objek-objek Node.
v1/Node:
- Get
- List
- Create
- Update
- Patch
- Watch
- Delete
Akses untuk Route Controller
Route Controller memantau pembuatan objek Node dan mengkonfigurasi rute jaringan secara sesuai. Route Controller membutuhkan akses untuk operasi get
terhadap objek-objek Node.
v1/Node:
- Get
Akses untuk Service Controller
Service Controller memantau terjadinya operasi create
, update
dan delete
, kemudian mengkonfigurasi Endpoint untuk Service-service tersebut secara sesuai.
Untuk mengakses Service-service, Service Controller membutuhkan akses untuk operasi list dan watch. Untuk memperbarui Service-service, dibutuhkan akses untuk operasi patch
dan update
.
Untuk menyiapkan Endpoint bagi untuk Service-service, dibutuhkan akses untuk operasi create
, list
, get
, watch
, dan update
.
v1/Service:
- List
- Get
- Watch
- Patch
- Update
Akses Lainnya
Implementasi dari inti CCM membutuhkan akses untuk membuat Event, dan untuk memastikan operasi yang aman, dibutuhkan akses untuk membuat ServiceAccount.
v1/Event:
- Create
- Patch
- Update
v1/ServiceAccount:
- Create
Detail RBAC dari ClusterRole untuk CCM adalah sebagai berikut:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cloud-controller-manager
rules:
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- update
- apiGroups:
- ""
resources:
- nodes
verbs:
- '*'
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
- apiGroups:
- ""
resources:
- services
verbs:
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- apiGroups:
- ""
resources:
- persistentvolumes
verbs:
- get
- list
- update
- watch
- apiGroups:
- ""
resources:
- endpoints
verbs:
- create
- get
- list
- watch
- update
Implementasi Vendor-vendor
Penyedia layanan cloud berikut telah mengimplementasikan CCM:
Administrasi Klaster
Petunjuk lengkap untuk mengkonfigurasi dan menjalankan CCM disediakan di sini.
3.3 - Kontainer
3.3.1 - Ikhtisar Kontainer
Kontainer adalah teknologi untuk mengemas kode (yang telah dikompilasi) menjadi suatu aplikasi beserta dengan dependensi-dependensi yang dibutuhkannya pada saat dijalankan. Setiap kontainer yang Anda jalankan dapat diulang; standardisasi dengan menyertakan dependensinya berarti Anda akan mendapatkan perilaku yang sama di mana pun Anda menjalankannya.
Kontainer memisahkan aplikasi dari infrastruktur host yang ada dibawahnya. Hal ini membuat penyebaran lebih mudah di lingkungan cloud atau OS yang berbeda.
Image-Image Kontainer
Kontainer image meruapakan paket perangkat lunak yang siap dijalankan, mengandung semua yang diperlukan untuk menjalankan sebuah aplikasi: kode dan setiap runtime yang dibutuhkan, library dari aplikasi dan sistem, dan nilai default untuk penganturan yang penting.
Secara desain, kontainer tidak bisa berubah: Anda tidak dapat mengubah kode dalam kontainer yang sedang berjalan. Jika Anda memiliki aplikasi yang terkontainerisasi dan ingin melakukan perubahan, maka Anda perlu membuat kontainer baru dengan menyertakan perubahannya, kemudian membuat ulang kontainer dengan memulai dari image yang sudah diubah.
Kontainer runtime
Kontainer runtime adalah perangkat lunak yang bertanggung jawab untuk menjalankan kontainer. Kubernetes mendukung beberapa kontainer runtime: Docker, containerd, CRI-O, dan semua implementasi dari Kubernetes CRI (Container Runtime Interface).
Selanjutnya
- Baca tentang image-image kontainer
- Baca tentang Pod
3.3.2 - Image
Kamu membuat Docker image dan mengunduhnya ke sebuah registri sebelum digunakan di dalam Kubernetes Pod.
Properti image
dari sebuah Container mendukung sintaksis yang sama seperti perintah docker
, termasuk registri privat dan tag.
Memperbarui Image
Kebijakan pull default adalah IfNotPresent
yang membuat Kubelet tidak
lagi mengunduh (pull) sebuah image jika sudah ada terlebih dahulu. Jika kamu ingin agar
selalu diunduh, kamu bisa melakukan salah satu dari berikut:
- mengatur
imagePullPolicy
dari Container menjadiAlways
. - buang
imagePullPolicy
dan gunakan:latest
tag untuk image yang digunakan. - buang
imagePullPolicy
dan juga tag untuk image. - aktifkan AlwaysPullImages admission controller.
Harap diingat kamu sebaiknya hindari penggunaan tag :latest
, lihat panduan konfigurasi untuk informasi lebih lanjut.
Membuat Image Multi-arsitektur dengan Manifest
Docker CLI saat ini mendukung perintah docker manifest
dengan anak perintah create
, annotate
, dan push
. Perintah-perintah ini dapat digunakan
untuk membuat (build) dan mengunggah (push) manifes. Kamu dapat menggunakan perintah docker manifest inspect
untuk membaca manifes.
Lihat dokumentasi docker di sini: https://docs.docker.com/edge/engine/reference/commandline/manifest/
Lihat contoh-contoh bagaimana kami menggunakan ini untuk proses build harness: https://cs.k8s.io/?q=docker%20manifest%20(create%7Cpush%7Cannotate)&i=nope&files=&repos=
Perintah-perintah ini bergantung pada Docker CLI, dan diimplementasi hanya di sisi CLI. Kamu harus mengubah $HOME/.docker/config.json
dan mengatur key experimental
untuk mengaktifkan
atau cukup dengan mengatur DOCKER_CLI_EXPERIMENTAL
variabel environment menjadi enabled
ketika memanggil perintah-perintah CLI.
Kalau kamu terkena masalah ketika mengunggah manifes-manifes yang rusak, cukup bersihkan manifes-manifes yang lama di $HOME/.docker/manifests
untuk memulai dari awal.
Untuk Kubernetes, kami biasanya menggunakan image-image dengan sufiks -$(ARCH)
. Untuk kompatibilitas (backward compatibility), lakukan generate image-image yang lama dengan sufiks. Idenya adalah men-generate, misalnya pause
image yang memiliki manifes untuk semua arsitektur dan misalnya pause-amd64
yang punya kompatibilitas terhadap konfigurasi-konfigurasi lama atau berkas-berkas YAML yang bisa saja punya image-image bersufiks yang di-hardcode.
Menggunakan Registri Privat (Private Registry)
Biasanya kita memerlukan key untuk membaca image-image yang tersedia pada suatu registri privat. Kredensial ini dapat disediakan melalui beberapa cara:
- Menggunakan Google Container Registry
- per-klaster
- konfigurasi secara otomatis pada Google Compute Engine atau Google Kubernetes Engine
- semua Pod dapat membaca registri privat yang ada di dalam proyek
- Menggunakan Amazon Elastic Container Registry (ECR)
- menggunakan IAM role dan policy untuk mengontrol akses ke repositori ECR
- secara otomatis refresh kredensial login ECR
- Menggunakan Oracle Cloud Infrastructure Registry (OCIR)
- menggunakan IAM role dan policy untuk mengontrol akses ke repositori OCIR
- Menggunakan Azure Container Registry (ACR)
- Menggunakan IBM Cloud Container Registry
- menggunakan IAM role dan policy untuk memberikan akses ke IBM Cloud Container Registry
- Konfigurasi Node untuk otentikasi registri privat
- semua Pod dapat membaca registri privat manapun
- memerlukan konfigurasi Node oleh admin klaster
- Pra-unduh image
- semua Pod dapat menggunakan image apapun yang di-cached di dalam sebuah Node
- memerlukan akses root ke dalam semua Node untuk pengaturannya
- Mengatur ImagePullSecrets dalam sebuah Pod
- hanya Pod-Pod yang menyediakan key sendiri yang dapat mengakses registri privat
Masing-masing opsi dijelaskan lebih lanjut di bawah ini.
Menggunakan Google Container Registry
Kubernetes memiliki dukungan native untuk Google Container Registry (GCR), ketika dijalankan pada Google Compute Engine (GCE). Jika kamu menjalankan klaster pada GCE atau Google Kubernetes Engine, cukup gunakan nama panjang image (misalnya gcr.io/my_project/image:tag).
Semua Pod di dalam klaster akan memiliki akses baca image di registri ini.
Kubelet akan melakukan otentikasi GCR menggunakan service account yang dimiliki
instance Google. Service acccount pada instance akan memiliki sebuah https://www.googleapis.com/auth/devstorage.read_only
,
sehingga dapat mengunduh dari GCR di proyek yang sama, tapi tidak untuk unggah.
Menggunakan Amazon Elastic Container Registry
Kubernetes memiliki dukungan native untuk Amazon Elastic Container Registry, ketika Node adalah AWS EC2 instance.
Cukup gunakan nama panjang image (misalnya ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag
) di dalam definisi Pod.
Semua pengguna klaster yang dapat membuat Pod akan bisa menjalankan Pod yang dapat menggunakan image-image di dalam registri ECR.
Kubelet akan mengambil dan secara periodik memperbarui kredensial ECR, yang memerlukan permission sebagai berikut:
ecr:GetAuthorizationToken
ecr:BatchCheckLayerAvailability
ecr:GetDownloadUrlForLayer
ecr:GetRepositoryPolicy
ecr:DescribeRepositories
ecr:ListImages
ecr:BatchGetImage
Persyaratan:
- Kamu harus menggunakan versi kubelet
v1.2.0
atau lebih (misal jalankan/usr/bin/kubelet --version=true
). - Jika Node yang kamu miliki ada di region A dan registri kamu ada di region yang berbeda misalnya B, kamu perlu versi
v1.3.0
atau lebih. - ECR harus tersedia di region kamu.
Cara troubleshoot:
- Verifikasi semua persyaratan di atas.
- Dapatkan kredensial $REGION (misalnya
us-west-2
) pada workstation kamu. Lakukan SSH ke dalam host dan jalankan Docker secara manual menggunakan kredensial tersebut. Apakah berhasil? - Tambahkan verbositas level log kubelet paling tidak 3 dan periksa log kubelet (misal
journalctl -u kubelet
) di baris-baris yang seperti ini:aws_credentials.go:109] unable to get ECR credentials from cache, checking ECR API
aws_credentials.go:116] Got ECR credentials from ECR API for <AWS account ID for ECR>.dkr.ecr.<AWS region>.amazonaws.com
Menggunakan Azure Container Registry (ACR)
Ketika menggunakan Azure Container Registry kamu dapat melakukan otentikasi menggunakan pengguna admin maupun sebuah service principal. Untuk keduanya, otentikasi dilakukan melalui proses otentikasi Docker standar. Instruksi-instruksi ini menggunakan perangkat azure-cli.
Kamu pertama perlu membuat sebuah registri dan men-generate kredensial, dokumentasi yang lengkap tentang hal ini dapat dilihat pada dokumentasi Azure container registry.
Setelah kamu membuat registri, kamu akan menggunakan kredensial berikut untuk login:
DOCKER_USER
: service principal, atau pengguna adminDOCKER_PASSWORD
: kata sandi dari service principal, atau kata sandi dari pengguna adminDOCKER_REGISTRY_SERVER
:${some-registry-name}.azurecr.io
DOCKER_EMAIL
:${some-email-address}
Ketika kamu sudah memiliki variabel-variabel di atas, kamu dapat mengkonfigurasi sebuah Kubernetes Secret dan menggunakannya untuk deploy sebuah Pod.
Menggunakan IBM Cloud Container Registry
IBM Cloud Container Registry menyediakan sebuah registri image privat yang multi-tenant, dapat kamu gunakan untuk menyimpan dan membagikan image-image secara aman. Secara default, image-image di dalam registri privat kamu akan dipindai (scan) oleh Vulnerability Advisor terintegrasi untuk deteksi isu keamanan dan kerentanan (vulnerability) yang berpotensi. Para pengguna di dalam akun IBM Cloud kamu dapat mengakses image, atau kamu dapat menggunakan IAM role dan policy untuk memberikan akses ke namespace di IBM Cloud Container Registry.
Untuk instalasi plugin CLI di IBM Cloud Containerr Registry dan membuat sebuah namespace untuk image-image kamu, lihat Mulai dengan IBM Cloud Container Registry.
Jika kamu menggunakan akun dan wilayah (region) yang sama, kamu dapat melakukan deploy image-image yang disimpan di dalam IBM Cloud Container Registry ke dalam namespace default dari klaster IBM Cloud Kubernetes Service yang kamu miliki tanpa konfigurasi tambahan, lihat Membuat kontainer dari image. Untuk opsi konfigurasi lainnya, lihat Bagaimana cara mengotorasi klaster untuk mengunduh image dari sebuah registri.
Konfigurasi Node untuk Otentikasi ke sebuah Registri Privat
.dockercfg
pada setiap Node dengan kredensial untuk Google Container Registry. Kamu tidak bisa menggunakan cara ini.
auths
dan HttpHeaders
dari konfigurasi docker. Hal ini berarti bantuan kredensial (credHelpers
atau credsStore
) tidak didukung.
Docker menyimpan key untuk registri privat pada $HOME/.dockercfg
atau berkas $HOME/.docker/config.json
. Jika kamu menempatkan berkas yang sama
pada daftar jalur pencarian (search path) berikut, kubelet menggunakannya sebagai penyedia kredensial saat mengunduh image.
{--root-dir:-/var/lib/kubelet}/config.json
{cwd of kubelet}/config.json
${HOME}/.docker/config.json
/.docker/config.json
{--root-dir:-/var/lib/kubelet}/.dockercfg
{cwd of kubelet}/.dockercfg
${HOME}/.dockercfg
/.dockercfg
HOME=/root
secara eksplisit pada berkas environment kamu untuk kubelet.
Berikut langkah-langkah yang direkomendasikan untuk mengkonfigurasi Node kamu supaya bisa menggunakan registri privat. Pada contoh ini, coba jalankan pada desktop/laptop kamu:
- Jalankan
docker login [server]
untuk setiap set kredensial yang ingin kamu gunakan. Ini akan memperbarui$HOME/.docker/config.json
. - Lihat
$HOME/.docker/config.json
menggunakan editor untuk memastikan sudah berisi kredensial yang ingin kamu gunakan. - Dapatkan daftar Node, contohnya:
- jika kamu ingin mendapatkan nama:
nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')
- jika kamu ingin mendapatkan IP:
nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')
- jika kamu ingin mendapatkan nama:
- Salin
.docker/config.json
yang ada di lokal kamu pada salah satu jalur pencarian di atas.- contohnya:
for n in $nodes; do scp ~/.docker/config.json root@$n:/var/lib/kubelet/config.json; done
- contohnya:
Verifikasi dengana membuat sebuah Pod yanag menggunakan image privat, contohnya:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: private-image-test-1
spec:
containers:
- name: uses-private-image
image: $PRIVATE_IMAGE_NAME
imagePullPolicy: Always
command: [ "echo", "SUCCESS" ]
EOF
pod/private-image-test-1 created
Jika semuanya berjalan dengan baik, maka setelah beberapa lama, kamu dapat menjalankan:
kubectl logs private-image-test-1
dan lihat pada keluaran perintah:
SUCCESS
Jika kamu mencurigai ada perintah yang gagal, kamu dapat menjalankan:
kubectl describe pods/private-image-test-1 | grep 'Failed'
Pada kasus gagal, keluarannya mirip seperti:
Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found
Kamu harus memastikan semua Node di dalam klaster memiliki .docker/config.json
yang sama. Jika tidak, Pod-Pod
akan jalan pada beberapa Node saja dan gagal di Node lainnya. Contohnya, jika kamu menggunakan Node autoscaling, maka
setiap templat instance perlu untuk mempunyai .docker/config.json
atau mount sebuah penyimpanan yang berisi berkas tersebut.
Semua Pod memiliki akses baca (read) untuk image-image di registri privat manapun ketika
key registri privat ditambahkan pada .docker/config.json
.
Image Pra-unduh
.dockercfg
pada setiap Node dengan kredensial untuk Google Container Registry. Kamu dapat menggunakan cara ini.
Secara default, kubelet akan mencoba untuk mengunduh setiap image dari registri yang dispesifikasikan.
Hanya saja, jika properti imagePullPolicy
diatur menjadi IfNotPresent
atau Never
, maka
sebuah image lokal digunakan.
Jika kamu ingin memanfaatkan image pra-unduh sebagai pengganti untuk otentikasi registri, kamu harus memastikan semua Node di dalam klaster memiliki image pra-unduh yang sama.
Cara ini bisa digunakan untuk memuat image tertentu untuk kecepatan atau sebagai alternatif untuk otentikasi untuk sebuah registri privat.
Semua Pod akan mendapatkan akses baca ke image pra-unduh manapun.
Tentukan ImagePullSecrets pada sebuah Pod
Kubernetes mendukung penentuan key registri pada sebuah Pod.
Membuat sebuah Secret dengan Docker Config
Jalankan perintah berikut, ganti nilai huruf besar dengan yang tepat:
kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
Jika kamu sudah memiliki berkas kredensial Docker, daripada menggunakan perintah di atas,
kamu dapat mengimpor berkas kredensial sebagai Kubernetes Secret.
Membuat sebuah Secret berbasiskan pada kredensial Docker yang sudah ada menjelaskan bagaimana mengatur ini.
Cara ini berguna khususnya jika kamu menggunakan beberapa registri kontainer privat,
perintah kubectl create secret docker-registry
akan membuat sebuah Secret yang akan
hanya bekerja menggunakan satu registri privat.
Mengacu pada imagePullSecrets di dalam sebuah Pod
Sekarang, kamu dapat membuat Pod yang mengacu pada Secret dengan menambahkan bagian imagePullSecrets
untuk sebuah definisi Pod.
cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
EOF
cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF
Cara ini perlu untuk diselesaikan untuk setiap Pod yang mengguunakan registri privat.
Hanya saja, mengatur field ini dapat diotomasi dengan mengatur imagePullSecrets di dalam sumber daya serviceAccount. Periksa Tambahan ImagePullSecrets untuk sebuah Service Account untuk instruksi yang lebih detail.
Kamu dapat menggunakan cara ini bersama .docker/config.json
pada setiap Node. Kredensial-kredensial
akan dapat di-merged. Cara ini akan dapat bekerja pada Google Kubernetes Engine.
Kasus-Kasus Penggunaan (Use Case)
Ada beberapa solusi untuk konfigurasi registri privat. Berikut beberapa kasus penggunaan dan solusi yang disarankan.
- Klaster yang hanya menjalankan image non-proprietary (misalnya open-source). Tidak perlu unutuk menyembunyikan image.
- Gunakan image publik pada Docker hub.
- Tidak ada konfigurasi yang diperlukan.
- Pada GCE/Google Kubernetes Engine, sebuah mirror lokal digunakan secara otomatis untuk meningkatkan kecepatan dan ketersediaan.
- Gunakan image publik pada Docker hub.
- Klaster yang menjalankan image proprietary yang seharusnya disembunyikan dari luar perusahaan, tetapi bisa terlihat oleh pengguna klaster.
- Gunakan sebuah privat registri Docker yang hosted.
- Bisa saja di-host pada Docker Hub, atau lainnya.
- Konfigurasi
.docker/config.json
secara manual pada setiap Node seperti dijelaskan di atas.
- Atau, jalankan sebuah registri privat internal di belakang firewall kamu dengan akses baca terbuka.
- Tidak ada konfigurasi Kubernetes yang diperlukan.
- Atau, ketika pada GCE/Google Kubernetes Engine, menggunakan Google Container Registry yang ada di proyek.
- Hal ini bisa bekerja baik dengan autoscaling klaster dibandingkan konfigurasi Node manual.
- Atau, pada sebuah klaster dimana mengubah konfigurasi Node tidak nyaman, gunakan
imagePullSecrets
.
- Gunakan sebuah privat registri Docker yang hosted.
- Klaster dengan image proprietary, beberapa memerlukan akses kontrol yang lebih ketat.
- Pastikan AlwaysPullImages admission controller aktif. Sebaliknya, semua Pod berpotensi memiliki akses ke semua image.
- Pindahkan data sensitif pada sumber daya "Secret", daripada mengemasnya menjadi sebuah image.
- Sebuah klaster multi-tenant dimana setiap tenant memerlukan registri privatnya masing-masing.
- Pastikan AlwaysPullImages admission controller aktif. Sebaliknya, semua Pod dari semua tenant berpotensi memiliki akses pada semua image.
- Jalankan sebuah registri privat dimana otorisasi diperlukan.
- Men-generate kredensial registri uuntuk setiap tenant, masukkan ke dalam secret uuntuk setiap namespace tenant.
- Tenant menambahkan secret pada imagePullSecrets uuntuk setiap namespace.
Jika kamu memiliki akses pada beberapa registri, kamu dapat membuat satu secret untuk setiap registri.
Kubelet akan melakukan merge imagePullSecrets
manapun menjadi sebuah virtual .docker/config.json
.
3.3.3 - Kontainer Environment
Laman ini menjelaskan berbagai resource yang tersedia di dalam Kontainer pada suatu environment.
Environment Kontainer
Environment Kontainer pada Kubernetes menyediakan beberapa resource penting yang tersedia di dalam Kontainer:
- Sebuah Filesystem, yang merupakan kombinasi antara image dan satu atau banyak volumes.
- Informasi tentang Kontainer tersebut.
- Informasi tentang objek-objek lain di dalam klaster.
Informasi tentang Kontainer
Hostname sebuah Kontainer merupakan nama dari Pod dimana Kontainer dijalankan.
Informasi ini tersedia melalui perintah hostname
atau panggilan (function call)
gethostname
pada libc
.
Nama Pod dan namespace tersedia sebagai variabel environment melalui API downward.
Variabel environment yang ditulis pengguna dalam Pod definition juga tersedia di dalam Kontainer, seperti halnya variabel environment yang ditentukan secara statis di dalam image Docker.
Informasi tentang Klaster
Daftar semua Service yang dijalankan ketika suatu Kontainer dibuat, tersedia di dalam Kontainer tersebut sebagai variabel environment. Variabel-variabel environment tersebut sesuai dengan sintaksis links dari Docker.
Untuk suatu Service bernama foo yang terkait dengan Kontainer bernama bar, variabel-variabel di bawah ini tersedia:
FOO_SERVICE_HOST=<host dimana service dijalankan>
FOO_SERVICE_PORT=<port dimana service dijalankan>
Semua Service memiliki alamat-alamat IP yang bisa didapatkan di dalam Kontainer melalui DNS, jika addon DNS diaktifkan.
Selanjutnya
- Pelajari lebih lanjut tentang berbagai hook pada lifecycle Kontainer.
- Dapatkan pengalaman praktis soal memberikan handler untuk event dari lifecycle Kontainer.
3.3.4 - Runtime Class
Kubernetes v1.14 [beta]
Laman ini menjelaskan tentang resource RuntimeClass dan proses pemilihan runtime.
Runtime Class
RuntimeClass merupakan sebuah fitur untuk memilih konfigurasi runtime kontainer. Konfigurasi tersebut digunakan untuk menjalankan kontainer-kontainer milik suatu Pod.
Persiapan
Pastikan gerbang fitur (feature gate) RuntimeClass
sudah aktif (secara default sudah aktif).
Lihat Gerbang Fitur untuk lebih
jelasnya soal pengaktifan gerbang fitur.
Gerbang fitur RuntimeClass ini harus aktif pada semua apiserver dan kubelet.
- Lakukan konfigurasi pada implementasi CRI untuk setiap node (tergantung runtime yang dipilih)
- Buat resource RuntimeClass yang terkait
1. Lakukan konfigurasi pada implementasi CRI untuk setiap node
Pilihan konfigurasi yang tersedia melalui RuntimeClass tergantung pada implementasi Container Runtime Interface (CRI). Lihat bagian (di bawah ini) soal bagaimana melakukan konfigurasi untuk implementasi CRI yang kamu miliki.
Seluruh konfigurasi memiliki nama handler
yang terkait, dijadikan referensi oleh RuntimeClass.
Nama handler harus berupa valid label 1123 DNS (alfanumerik + karakter -
).
2. Buat resource RuntimeClass
yang terkait
Masing-masing konfigurasi pada langkah no.1 punya nama handler
yang merepresentasikan
konfigurasi-konfigurasi tersebut. Untuk masing-masing handler
, buatlah sebuah objek RuntimeClass terkait.
Resource RuntimeClass saat ini hanya memiliki 2 field yang penting: nama RuntimeClass tersebut
(metadata.name
) dan handler (handler
). Definisi objek tersebut terlihat seperti ini:
apiVersion: node.k8s.io/v1beta1 # RuntimeClass didefinisikan pada grup API node.k8s.io
kind: RuntimeClass
metadata:
name: myclass # Nama dari RuntimeClass yang nantinya akan dijadikan referensi
# RuntimeClass merupakan resource tanpa namespace
handler: myconfiguration # Nama dari konfigurasi CRI terkait
Penggunaan
Ketika RuntimeClass sudah dikonfigurasi pada klaster, penggunaannya sangatlah mudah.
Kamu bisa tentukan runtimeClassName
di dalam spec
sebuah Pod, sebagai contoh:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
runtimeClassName: myclass
# ...
Kubelet akan mendapat instruksi untuk menggunakan RuntimeClass dengan nama yang sudah ditentukan tersebut
untuk menjalankan Pod ini. Jika RuntimeClass dengan nama tersebut tidak ditemukan, atau CRI tidak dapat
menjalankan handler yang terkait, maka Pod akan memasuki tahap Failed
.
Lihat event untuk mengetahui pesan error yang terkait.
Jika tidak ada runtimeClassName
yang ditentukan di dalam Pod, maka RuntimeHandler yang default akan digunakan.
Untuk kasus ini, perilaku klaster akan seperti saat fitur RuntimeClass dinonaktifkan.
Konfigurasi CRI
Lihat instalasi CRI untuk lebih detail mengenai pengaturan runtime CRI.
dockershim
Built-in dockershim CRI yang dimiliki Kubernetes tidak mendukung handler runtime.
containerd
Handler runtime diatur melalui konfigurasi containerd pada /etc/containerd/config.toml
.
Handler yang valid dapat dikonfigurasi pada bagian runtime:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${HANDLER_NAME}]
Lihat dokumentasi konfigurasi containerd untuk lebih detail: https://github.com/containerd/cri/blob/master/docs/config.md
cri-o
Handler runtime dapat diatur menggunakan konfigurasi cri-o pada /etc/crio/crio.conf
.
Handler yang valid dapat dikonfigurasi pada tabel crio.runtime:
[crio.runtime.runtimes.${HANDLER_NAME}]
runtime_path = "${PATH_TO_BINARY}"
Lihat dokumentasi konfigurasi cri-o untuk lebih detail: https://github.com/kubernetes-sigs/cri-o/blob/master/cmd/crio/config.go
Memperbarui RuntimeClass dari Alpha ke Beta
Fitur Beta pada RuntimeClass memiliki perubahan sebagai berikut:
- Grup API resource
node.k8s.io
danruntimeclasses.node.k8s.io
telah dimigrasi ke suatu API built-in dari CustomResourceDefinition. - Atribut
spec
telah disederhakan pada definisi RuntimeClass (tidak ada lagi yang namanya RuntimeClassSpec). - Field
runtimeHandler
telah berubah nama menjadihandler
. - Field
handler
sekarang bersifat wajib untuk semua versi API. Artinya, fieldruntimeHandler
pada API Alpha juga bersifat wajib. - Field
handler
haruslah berupa label DNS valid (RFC 1123), yang artinya tidak bisa berisi karakter.
(pada semua versi). Handler valid harus sesuai dengan regular expression ini:^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
.
Tindakan yang diperlukan: Tindakan-tindaka berikut ini diperlukan untuk melakukan pembaruan fitur RuntimeClass dari versi alpha ke versi beta:
- Resource RuntimeClass harus dibuat ulang setelah diperbarui ke v.1.14, dan
CRD
runtimeclasses.node.k8s.io
harus dihapus secara manual:kubectl delete customresourcedefinitions.apiextensions.k8s.io runtimeclasses.node.k8s.io
- Fitur Alpha pada RuntimeClass akan menjadi tidak valid, jika
runtimeHandler
tidak ditentukan atau kosong atau menggunakan karakter.
pada handler. Ini harus dimigrasi ke handler dengan konfigurasi yang valid (lihat petunjuk di atas).
3.3.5 - Lifecyle Hook pada Kontainer
Laman ini menjelaskan bagaimana semua Kontainer yang diatur kubelet menggunakan framework lifecycle hook untuk menjalankan kode yang di-trigger oleh event selama lifecycle berlangsung.
Ikhtisar
Kubernetes menyediakan hook untuk lifecycle Kontainer. Hal ini sejalan dengan framework bahasa pemrograman pada umumnya yang memiliki hook untuk lifecycle komponen, seperti Angular contohnya. Hook tersebut digunakan Kontainer untuk selalu siap menerima event selama lifecycle dan menjalankan kode yang diimplementasi pada suatu handler, ketika hook lifecycle terkait telah dieksekusi.
Jenis-jenis hook pada Kontainer
Ada dua jenis hook yang diekspos pada Kontainer:
PostStart
Hook ini dijalankan segera setelah suatu kontainer dibuat.
Hanya saja, tidak ada jaminan bahwa hook akan tereksekusi sebelum ENTRYPOINT
dari kontainer.
Tidak ada parameter yang diberikan pada handler.
PreStop
Hook ini akan dipanggil sesaat sebelum kontainer dimatikan, karena suatu request API atau event pengaturan,
contohnya kegagalan pada liveness probe, preemption, perebutan resource, dan lainnya.
Sebuah panggilan untuk hook PreStop
akan gagal jika kontainer tersebut telah ada pada state terminate atau complete.
Hal ini bersifat blocking, yang artinya panggilan bersifat sinkron (synchronous), harus menunggu eksekusi selesai, sebelum melakukan panggilan
untuk menghapus kontainer tersebut.
Tidak ada parameter yang diberikan pada handler.
Penjelasan yang lebih rinci tentang proses terminasi dapat dilihat pada Terminasi Pod.
Implementasi handler untuk hook
Kontainer dapat mengakses sebuah hook melalui implementasi dan registrasi sebuah handler untuk hook tersebut. Ada dua jenis handler untuk hook yang dapat diimplementasikan untuk Kontainer:
- Exec - Mengeksekusi sebuah perintah tertentu, contohnya
pre-stop.sh
, di dalam cgroups dan namespace suatu Kontainer. Resource yang dikonsumsi oleh perintah tersebut dianggap sebagai bagian dari Kontainer. - HTTP - Mengeksekusi sebuah request HTTP untuk endpoint tertentu pada Kontainer tersebut.
Eksekusi handler untuk hook
Ketika manajemen hook untuk suatu lifecycle Kontainer dipanggil, sistem manajemen internal pada Kubernetes akan mengeksekusi handler di dalam Kontainer yang terdaftar untuk hook tersebut.
Panggilan handler untuk hook semuanya bersifat synchronous di dalam konteks Pod yang
memiliki Kontainer tersebut. Artinya, untuk hook PostStart
, Kontainer ENTRYPOINT
dan hook dieksekusi secara asyncrhonous. Akan tetapi, jika hook mengambil waktu terlalu lama,
atau hang, Kontainer tersebut tidak bisa sampai ke state running
.
Perilaku ini mirip dengan yang terjadi pada hook PreStop
.
Jika hook terlalu lama atau hang saat dieksekusi, Pod tersebut tetap ada pada state Terminating
dan akan dimatikan setelah terminationGracePeriodSeconds
Pod selesai.
Jika sebuah hook PostStart
atau PreStop
gagal dieksekusi, Kontainer akan dimatikan.
Para pengguna sangat disarankan membuat handler untuk hook seringan mungkin (lightweight). Biar bagaimanapun, ada beberapa kasus yang memang membutuhkan waktu lama untuk mengeksekusi suatu perintah, misalnya saat proses penyimpanan state sebelum Kontainer dimatikan.
Jaminan pengiriman hook
Proses pengiriman hook akan dilakukan paling tidak satu kali.
Artinya suatu hook boleh dipanggil beberapa kali untuk event yang sama,
seperti dalam PostStart
atauPreStop
.
Namun begitu, implementasi hook masing-masing harus memastikan bagaimana
menangani kasus ini dengan benar.
Pada umumnya, hanya terjadi satu proses pengiriman. Jika misalnya sebuah penerima HTTP hook mati atau tidak bisa menerima trafik, maka tidak ada usaha untuk mengirimkan kembali. Namun demikian, bisa saja terjadi dua kali proses pengiriman untuk kasus tertentu. Contohnya, jika kubelet restart saat di tengah proses pengiriman hook, hook tersebut akan dikirimkan kembali saat kubelet sudah hidup kembali.
Melakukan debug handler untuk hook
Log untuk suatu handler hook tidak terekspos pada event Pod.
Jika handler gagal dieksekusi untuk alasan tertentu, handler akan melakukan broadcast sebuah event.
Untuk PostStart
, akan dilakukan broadcast event FailedPostStartHook
,
dan untuk PreStop
, akan dilakukan broadcast event FailedPreStopHook
.
Kamu dapat melihat event-event ini dengan menjalankan perintah kubectl describe pod <pod_name>
.
Berikut merupakan contoh keluaran event-event setelah perintah tersebut dijalankan.
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {default-scheduler } Normal Scheduled Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulling pulling image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Created Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined]
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulled Successfully pulled image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Started Started container with docker id 5c6a256a2567
38s 38s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1
37s 37s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1
38s 37s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1"
1m 22s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Warning FailedPostStartHook
Selanjutnya
- Pelajari lebih lanjut tentang environment Kontainer.
- Pelajari bagaimana caranya melakukan attach handler pada event lifecycle sebuah Kontainer.
3.4 - Workloads
3.4.1 - Pods
3.4.1.1 - Pengenalan Pod
Halaman ini menyajikan ikhtisar dari Pod
, objek terkecil yang dapat di deploy di dalam objek model Kubernetes.
Memahami Pod
Sebuah Pod adalah unit dasar di Kubernetes--unit terkecil dan paling sederhana di dalam objek model Kubernetes yang dapat dibuat dan di deploy. Sebuah Pod merepresentasikan suatu proses yang berjalan di dalam klaster.
Pod membungkus sebuah kontainer (atau, di beberapa kasus, beberapa kontainer), sumber penyimpanan, alamat jaringan IP yang unik, dan opsi yang mengatur bagaimana kontainer harus dijalankan. Pod merupakan representasi dari unit deployment: sebuah instance aplikasi di dalam Kubernetes, yang mungkin terdiri dari satu kontainer atau sekumpulan kontainer yang berbagi resource.
Docker adalah salah satu kontainer runtime yang paling umum digunakan di Kubernetes Pod, tetapi Pod mendukung kontainer runtime lainnya.
Pod di Kubernetes klaster dapat digunakan dengan dua cara:
- Pod menjalankan satu kontainer. Model satu kontainer per Pod adalah model yang umum digunakan di Kubernetes; kamu dapat membayangkan sebuah Pod sebagai pembungkus kontainer tersebut, dan Kubernetes tidak mengelola kontainer secara langsung tetapi mengelola Pod tersebut.
- Pod menjalankan beberapa kontainer yang perlu berjalan bersamaan. Sebuah Pod dapat membungkus sebuah aplikasi yang terdiri dari beberapa kontainer yang perlu berbagi resource. Kontainer yang ditempatkan di dalam satu Pod ini membentuk sebuah layanan. Sebuah kontainer menyajikan berkas dari sumber penyimpanan ke publik, sedangkan kontainer sidecar yang lain melakukan pembaharuan terhadap berkas tersebut. Pod membungkus semua kontainer dan resource penyimpanan sebagai satu kesatuan yang dapat dikelola.
Kubernetes Blog menyediakan beberapa informasi tambahan terkait penggunaan Pod. Informasi selengkapnya, kunjungi:
Setiap Pod dimaksudkan untuk menjalankan satu instance aplikasi. Jika kamu ingin mengembangkan aplikasi secara horizontal (contoh, banyak instance sekaligus), kamu dapat menggunakan banyak Pod, satu untuk setiap instance. Di Kubernetes, konsep ini umumnya disebut dengan replikasi. Pod yang direplikasi biasanya dibuat dan dikelola sebagai grup oleh objek abstraksi yang disebut kontroler. Lihat Pod dan Kontroler untuk informasi selengkapnya.
Bagaimana Pod mengelola beberapa Kontainer
Pod didesain untuk mendukung banyak proses (sebagai kontainer) yang membentuk sebuah layanan. Kontainer di dalam sebuah Pod akan otomatis ditempatkan bersama di dalam satu mesin fisik atau mesin virtual di dalam klaster. Kontainer tersebut dapat berbagi resource dan dependensi, berkomunikasi satu sama lain, dan berkoordinasi kapan dan bagaimana mereka diterminasi.
Perhatikan bahwa mengelompokan kontainer di dalam satu Pod merupakan kasus lanjutan. Kamu dapat menggunakan pola ini hanya dalam kasus tertentu. Sebagai contoh, kamu memiliki kontainer yang bertindak sebagai web server yang menyajikan berkas dari resource penyimpanan bersama, dan kontainer sidecar melakukan pembaharuan terhadap berkas tersebut dari sumber lain, seperti dalam diagram Pod berikut:
Pod menyediakan dua jenis resource sebagai penyusun dari kontainer: jaringan dan penyimpanan.
Jaringan
Setiap Pod diberikan sebuah alamat IP unik. Setiap kontainer di dalam Pod berbagi network namespace, termasuk alamat IP dan port jaringan. Setiap kontainer di dalam Pod dapat berkomunikasi satu sama lain menggunakan localhost. Saat para kontainer di dalam Pod berkomunikasi dengan entitas lain di luar Pod, mereka harus berkoordinasi satu sama lain bagaimana mereka menggunakan resource jaringan (seperti Port).
Penyimpanan
Pod dapat menentukan penyimpanan bersama yaitu volumes. Semua kontainer di dalam Pod dapat mengakses volumes ini, mengizinkan kontainer untuk berbagi data. Volumes juga memungkinkan data di Pod untuk bertahan jika salah satu kontainer perlu melakukan proses restart. Lihat Volumes untuk informasi lebih lanjut bagaimana Kubernetes mengimplementasikan penyimpanan di dalam Pod.
Bekerja dengan Pod
Kamu akan jarang membuat Pod secara langsung di Kubernetes. Ini karena Pod dirancang sebagai entitas sesaat. Saat Pod dibuat (baik oleh kamu, atau secara tidak langsung oleh kontroler), Pod ditempatkan dan dijalankan di sebuah Node di dalam klaster. Pod akan tetap di Node tersebut sampai proses dihentikan, Objek Pod dihapus, Pod dihentikan karena kekurangan resource, atau Node tersebut berhenti berjalan.
Pod tidak melakukan mekanisme penyembuhan diri sendiri. Jika Pod ditempatkan disebuah Node yang gagal, atau proses penempatan Pod itu sendiri gagal, Pod akan dihapus; demikian juga, Pod tidak akan bertahan jika Node tersebut kehabisan resource atau sedang dalam tahap pemeliharaan. Kubernetes menggunakan abstraksi yang disebut kontroler, yang menangani dan mengelola Pod. Jadi, meskipun Pod dapat dipakai secara langsung di Kubernetes, kontroler merupakan cara umum yang digunakan untuk mengelola Pod. Lihat Pod dan kontroler untuk informasi lebih lanjut bagaimana Kubernetes menggunakan kontroler untuk mengimpelentasikan mekanisme penyembuhan diri sendiri dan replikasi pada Pod.
Pod dan Kontroler
Kontroler dapat membuat dan mengelola banyak Pod untuk kamu, menangani replikasi dan menyediakan kemampuan penyembuhan diri sendiri pada lingkup klaster. Sebagai contoh, jika sebuah Node gagal, kontroler akan otomatis mengganti Pod tersebut dengan menempatkan Pod yang identik di Node yang lain.
Beberapa contoh kontroler yang berisi satu atau lebih Pod meliputi:
Secara umum, kontroler menggunakan templat Pod yang kamu sediakan untuk membuat Pod.
Templat Pod
Templat Pod adalah spesifikasi dari Pod yang termasuk di dalam objek lain seperti Replication Controllers, Jobs, dan DaemonSets. Kontroler menggunakan templat Pod untuk membuat Pod.
Contoh di bawah merupakan manifestasi sederhana untuk Pod yang berisi kontainer yang membuat sebuah pesan.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
Perubahan yang terjadi pada templat atau berganti ke templat yang baru tidak memiliki efek langsung pada Pod yang sudah dibuat. Pod yang dibuat oleh replication controller dapat diperbarui secara langsung.
Selanjutnya
- Pelajari lebih lanjut tentang perilaku Pod:
3.4.1.2 - Pod
Pod adalah unit komputasi terkecil yang bisa di-deploy dan dibuat serta dikelola dalam Kubernetes.
Apa Itu Pod?
Sebuah Pod (seperti pod pada paus atau kacang polong) adalah sebuah kelompok yang terdiri dari satu atau lebih kontainer (misalnya kontainer Docker), dengan ruang penyimpanan ataupun jaringan yang dipakai bersama, dan sebuah spesifikasi mengenai bagaimana menjalankan kontainer. Isi dari Pod akan selalu diletakkan dan dijadwalkan bersama, serta berjalan dalam konteks yang sama. Sebuah Pod memodelkan "logical host" yang spesifik terhadap aplikasi. Ini mengandung lebih dari satu kontainer aplikasi yang secara relatif saling terhubung erat. Sebelum masa kontainer, menjalankan aplikasi dalam mesin fisik atau virtual berarti menjalankan dalam logical host yang sama.
Walaupun Kubernetes mendukung lebih banyak runtime kontainer selain Docker, namun Docker adalah yang paling umum diketahui dan ini membantu dalam menjelaskan Pod dengan istilah pada Docker.
Konteks bersama dalam sebuah Pod adalah kumpulan Linux namespace, cgroup dan kemungkinan segi isolasi lain, hal yang sama yang mengisolasi kontainer Docker. Dalam sebuah konteks pada Pod, setiap aplikasi bisa menerapkan sub-isolasi lebih lanjut.
Semua kontainer dalam suatu Pod akan berbagi alamat IP dan port yang sama,
dan bisa saling berkomunikasi melalui localhost
. Komunikasi tersebut mengunakan
standar inter-process communications (IPC) seperti SystemV semaphores
atau POSIX shared memory. Kontainer pada Pod yang berbeda memiliki alamat IP
yang berbeda dan tidak dapat berkomunikasi menggunakan IPC tanpa
pengaturan khusus. Kontainer ini
biasa berkomunikasi dengan yang lain menggunakan alamat IP setiap Pod.
Aplikasi dalam suatu Pod juga memiliki akses ke ruang penyimpanan bersama, yang didefinisikan sebagai bagian dari Pod dan dibuat bisa diikatkan ke masing-masing filesystem pada aplikasi.
Dalam istilah konsep Docker, sebuah Pod dimodelkan sebagai gabungan dari kontainer Docker yang berbagi namespace dan ruang penyimpanan filesystem.
Layaknya aplikasi dengan kontainer, Pod dianggap sebagai entitas yang relatif tidak kekal (tidak bertahan lama). Seperti yang didiskusikan dalam siklus hidup Pod, Pod dibuat, diberikan ID unik (UID), dan dijadwalkan pada suatu mesin dan akan tetap disana hingga dihentikan (bergantung pada aturan restart) atau dihapus. Jika mesin mati, maka semua Pod pada mesin tersebut akan dijadwalkan untuk dihapus, namun setelah suatu batas waktu. Suatu Pod tertentu (sesuai dengan ID unik) tidak akan dijadwalkan ulang ke mesin baru, namun akan digantikan oleh Pod yang identik, bahkan jika dibutuhkan bisa dengan nama yang sama, tapi dengan ID unik yang baru (baca replication controller untuk info lebih lanjut)
Ketika sesuatu dikatakan memiliki umur yang sama dengan Pod, misalnya saja ruang penyimpanan, maka itu berarti akan tetap ada selama Pod tersebut masih ada. Jika Pod dihapus dengan alasan apapun, sekalipun Pod pengganti yang identik telah dibuat, semua yang berhubungan (misalnya ruang penyimpanan) akan dihapus dan dibuat ulang.
Sebuah Pod dengan banyak kontainer, yaitu File Puller dan Web Server yang menggunakan ruang penyimpanan persisten untuk berbagi ruang penyimpanan bersama antara kontainer.
Motivasi suatu Pods
Pengelolaan
Pod adalah suatu model dari pola beberapa proses yang bekerja sama dan membentuk suatu unit layanan yang kohesif. Menyederhanakan proses melakukan deploy dan pengelolaan aplikasi dengan menyediakan abstraksi tingkat yang lebih tinggi daripada konstituen aplikasinya. Pod melayani sebagai unit dari deployment, penskalaan horizontal, dan replikasi. Colocation (co-scheduling), berbagi nasib (misalnya dimatikan), replikasi terkoordinasi, berbagi sumber daya dan pengelolaan ketergantungan akan ditangani otomatis untuk kontainer dalam suatu Pod.
Berbagi sumber daya dan komunikasi
Pod memungkinkan berbagi data dan komunikasi diantara konstituennya.
Semua aplikasi dalam suatu Pod menggunakan namespace jaringan yang sama
(alamat IP dan port yang sama), dan menjadikan bisa saling mencari dan berkomunikasi
dengan menggunakan localhost
. Oleh karena itu, aplikasi dalam Pod harus
berkoordinasi mengenai penggunaan port. Setiap Pod memiliki alamat IP
dalam satu jaringan bersama yang bisa berkomunikasi dengan komputer lain
dan Pod lain dalam jaringan yang sama.
Kontainer dalam suatu Pod melihat hostname sistem sebagai sesuatu yang sama
dengan konfigurasi name
pada Pod. Informasi lebih lanjut terdapat dibagian
jaringan.
Sebagai tambahan dalam mendefinisikan kontainer aplikasi yang berjalan dalam Pod, Pod memberikan sepaket sistem penyimpanan bersama. Sistem penyimpanan memungkinkan data untuk bertahan saat kontainer dijalankan ulang dan dibagikan kepada semua aplikasi dalam Pod tersebut.
Penggunaan Pod
Pod dapat digunakan untuk menjalankan beberapa aplikasi yang terintegrasi secara vertikal (misalnya LAMP), namun motivasi utamanya adalah untuk mendukung berlokasi bersama, mengelola program pembantu, diantaranya adalah:
- sistem pengelolaan konten, pemuat berkas dan data, manajer cache lokal, dll.
- catatan dan checkpoint cadangan, kompresi, rotasi, dll.
- pengamat perubahan data, pengintip catatan, adapter pencatatan dan pemantauan, penerbit peristiwa, dll.
- proksi, jembatan dan adaptor.
- pengontrol, manajer, konfigurasi dan pembaharu.
Secara umum, masing-masing Pod tidak dimaksudkan untuk menjalankan beberapa aplikasi yang sama.
Penjelasan lebih lengkap bisa melihat The Distributed System ToolKit: Patterns for Composite Containers.
Alternatif pertimbangan
Kenapa tidak menjalankan banyak program dalam satu kontainer (Docker)?
- Transparansi. Membuat kontainer dalam suatu Pod menjadi terlihat dari infrastruktur, memungkinkan infrastruktur menyediakan servis ke kontainer tersebut, misalnya saja pengelolaan proses dan pemantauan sumber daya. Ini memfasilitasi sejumlah kenyamanan untuk pengguna.
- Pemisahan ketergantungan perangkat lunak. Setiap kontainer mungkin memiliki versi, dibuat dan dijalankan ulang secara independen. Kubernetes mungkin mendukung pembaharuan secara langsung terhadap suatu kontainer, suatu saat nanti.
- Mudah digunakan. Penguna tidak diharuskan menjalankan manajer prosesnya sendiri, khawatir dengan sinyal dan propagasi exit-code, dan lain sebagainya.
- Efisiensi. Karena infrastruktur memegang lebih banyak tanggung jawab, kontainer bisa lebih ringan.
Kenapa tidak mendukung penjadwalan kontainer berdasarkan affinity?
Cara itu bisa menyediakan lokasi yang sama, namun tidak memberikan banyak keuntungan dari Pod, misalnya saja berbagi sumber daya, IPC, jaminan berbagi nasib dan kemudahan manajemen.
Ketahanan suatu Pod (atau kekurangan)
Pod tidak dimaksudkan untuk diperlakukan sebagai entitas yang tahan lama. Mereka tidak akan bertahan dengan kegagalan penjadwalan, kegagalan mesin, atau eviction (pengusiran), misalnya karena kurangnya sumber daya atau dalam suatu kasus mesin sedang dalam pemeliharaan.
Secara umum, pengguna tidak seharusnya butuh membuat Pod secara langsung. Mereka seharusnya selalu menggunakan pengontrol, sekalipun untuk yang tunggal, misalnya, Deployment. Pengontrol menyediakan penyembuhan diri dengan ruang lingkup kelompok, begitu juga dengan pengelolaan replikasi dan penluncuran. Pengontrol seperti StatefulSet bisa memberikan dukungan terhadap Pod yang stateful.
Penggunaan API kolektif sebagai user-facing primitive utama adalah hal yang relatif umum diantara sistem penjadwalan kluster, seperti
Borg, Marathon, Aurora, dan Tupperware.
Pod diekspose sebagai primitive untuk memfasilitasi hal berikut:
- penjadwalan dan pengontrol sifat pluggability
- mendukung operasi pada level Pod tanpa perlu melakukan proksi melalui API pengontrol
- pemisahan antara umur suatu Pod dan pengontrol, seperti misalnya bootstrapping.
- pemisahan antara pengontrol dan servis, pengontrol endpoint hanya memperhatikan Pod
- komposisi yang bersih antara fungsionalitas dilevel Kubelet dan klaster. Kubelet secara efektif adalah pengontrol Pod.
- aplikasi dengan ketersediaan tinggi, yang akan mengharapkan Pod akan digantikan sebelum dihentikan dan tentu saja sebelum dihapus, seperti dalam kasus penggusuran yang direncanakan atau pengambilan gambar.
Penghentian Pod
Karena Pod merepresentasikan proses yang berjalan pada mesin didalam klaster, sangat penting untuk memperbolehkan proses ini berhenti secara normal ketika sudah tidak dibutuhkan (dibandingkan dengan dihentikan paksa dengan sinyal KILL dan tidak memiliki waktu untuk dibersihkan). Pengguna seharusnya dapat meminta untuk menghapus dan tahu proses penghentiannya, serta dapat memastikan penghentian berjalan sempurna. Ketika pengguna meminta menghapus Pod, sistem akan mencatat masa tenggang untuk penghentian secara normal sebelum Pod dipaksa untuk dihentikan, dan sinyal TERM akan dikirim ke proses utama dalam setiap kontainer. Setelah masa tenggang terlewati, sinyal KILL akan dikirim ke setiap proses dan Pod akan dihapus dari API server. Jika Kubelet atau kontainer manajer dijalankan ulang ketika menunggu suatu proses dihentikan, penghentian tersebut akan diulang dengan mengembalikan masa tenggang senilai semula.
Contohnya sebagai berikut:
- Pengguna mengirim perintah untuk menghapus Pod, dengan masa tenggang (30 detik)
- Pod dalam API server akan diperbarui dengan waktu dimana Pod dianggap "mati" bersama dengan masa tenggang.
- Pod ditampilkan dalam status "Terminating" ketika tercantum dalam perintah klien
- (bersamaan dengan poin 3) Ketika Kubelet melihat Pod sudah ditandai sebagai
"Terminating" karena waktu pada poin 2 sudah diatur, ini memulai proses penghentian Pod
- Jika salah satu kontainer pada Pod memiliki
preStop hook,
maka akan dipanggil di dalam kontainer. Jika
preStop
hook masih berjalan setelah masa tenggang habis, langkah 2 akan dipanggil dengan tambahan masa tenggang yang sedikit, 2 detik. - Semua kontainer akan diberikan sinyal TERM. Sebagai catatan, tidak semua kontainer
akan menerima sinyal TERM dalam waktu yang sama dan mungkin butuh waktu untuk
menjalankan
preStop
hook jika bergantung pada urutan penghentiannya.
- Jika salah satu kontainer pada Pod memiliki
preStop hook,
maka akan dipanggil di dalam kontainer. Jika
- (bersamaan dengan poin 3) Pod akan dihapus dari daftar endpoint untuk servis dan tidak lagi dianggap sebagai bagian dari Pod yang berjalan dalam replication controllers. Pod yang dihentikan, secara perlahan tidak akan melayani permintaan karena load balancer (seperti servis proksi) menghapus mereka dari daftar rotasi.
- Ketika masa tenggang sudah lewat, semua proses yang masih berjalan dalam Pod akan dihentikan dengan sinyal SIGKILL.
- Kubelet akan selesai menghapus Pod dalam API server dengan mengatur masa tenggang menjadi 0 (langsung menghapus). Pod akan menghilang dari API dan tidak lagi terlihat oleh klien.
Secara default, semua penghapusan akan berjalan normal selama 30 detik. Perintah
kubectl delete
mendukung opsi --grace-period=<waktu dalam detik>
yang akan
memperbolehkan pengguna untuk menimpa nilai awal dan memberikan nilai sesuai keinginan
pengguna. Nilai 0
akan membuat Pod
dihapus paksa.
Kamu harus memberikan opsi tambahan --force
bersamaan dengan --grace-period=0
untuk melakukan penghapusan paksa.
Penghapusan paksa sebuah Pod
Penghapusan paksa dari sebuah Pod didefinisikan sebagai penghapusan Pod dari state klaster dan etcd secara langsung. Ketika penghapusan paksa dilakukan, API server tidak akan menunggu konfirmasi dari kubelet bahwa Pod sudah dihentikan pada mesin ia berjalan. Ini menghapus Pod secara langsung dari API, sehingga Pod baru bisa dibuat dengan nama yang sama. Dalam mesin, Pod yang dihentikan paksa akan tetap diberikan sedikit masa tenggang sebelum dihentikan paksa.
Penghentian paksa dapat menyebabkan hal berbahaya pada beberapa Pod dan seharusnya dilakukan dengan perhatian lebih. Dalam kasus StatefulSet Pods, silakan melihat dokumentasi untuk penghentian Pod dari StatefulSet.
Hak istimewa untuk kontainer pada Pod
Setiap kontainer dalam Pod dapat mengaktifkan hak istimewa (mode privileged), dengan menggunakan tanda
privileged
pada konteks keamanan
pada spesifikasi kontainer. Ini akan berguna untuk kontainer yang ingin menggunakan
kapabilitas Linux seperti memanipulasi jaringan dan mengakses perangkat. Proses dalam
kontainer mendapatkan hak istimewa yang hampir sama dengan proses di luar kontainer.
Dengan hak istimerwa, seharusnya lebih mudah untuk menulis pada jaringan dan plugin
ruang penyimpanan sebagai Pod berbeda yang tidak perlu dikompilasi ke dalam kubelet.
API Object
Pod adalah sumber daya tingkat tinggi dalam Kubernetes REST API. Definisi Objek Pod API menjelaskan mengenai objek secara lengkap.
3.4.1.3 - Siklus Hidup Pod
Halaman ini menjelaskan siklus hidup sebuah Pod
Fase Pod
Field status
dari sebuah Pod merupakan sebuah objek PodStatus, yang memiliki sebuah field phase
.
Fase dari sebuah Pod adalah sesuatu yang sederhana, ringkasan yang lebih tinggi tentang Pod dalam siklus hidupnya. Fase ini tidak ditujukan sebagai sebuah kesimpulan yang luas dari observasi suatu kontainer atau state suatu Pod, serta tidak ditujukan sebagai state machine yang luas.
Jumlah dan arti dari nilai-nilai fase Pod dijaga ketat. Selain yang ada dalam dokumentasi ini, tidak perlu berasumsi mengenai Pod telah diberikan nilai phase
.
Berikut adalah nilai yang mungkin diberikan untuk suatu phase
:
Nilai | Deskripsi |
---|---|
Pending |
Pod telah disetujui oleh sistem Kubernetes, tapi ada satu atau lebih image kontainer yang belum terbuat. Ini termasuk saat sebelum dijadwalkan dan juga saat mengunduh image melalui jaringan, yang mungkin butuh beberapa waktu. |
Running |
Pod telah terikat ke suatu node, dan semua kontainer telah terbuat. Setidaknya ada 1 kontainer yang masih berjalan, atau dalam proses memulai atau restart. |
Succeeded |
Semua kontainer di dalam Pod sudah berhasil dihentikan, dan tidak akan dilakukan restart. |
Failed |
Semua kontainer dalan suatu Pod telah dihentikan, dan setidaknya ada satu kontainer yang terhenti karena kegagalan. Itu merupakan kontainer yang keluar dengan kode status bukan 0 atau dihentikan oleh sistem. |
Unknown |
State suatu Pod tidak dapat diperoleh karena suatu alasan, biasanya karena kesalahan dalam komunikasi dengan host yang digunakan Pod tersebut. |
Kondisi Pod
Suatu Pod memiliki sebuah PodStatus, yang merupakan array dari PodConditions yang telah atau belum dilewati oleh Pod. Setiap elemen dari array PodConditions mungkin memiliki enam field berikut:
-
Field
lastProbeTime
memberikan nilai timestamp yang menandakan kapan terakhir kali kondisi kondisi Pod diperiksa. -
Field
lastTransitionTime
memberikan nilai timestamp yang menandakan kapan terakhir kali Pod berubah status ke status lain. -
Field
message
adalah pesan yang bisa dibaca manusia yang mengidikasikan detail dari suatu transisi. -
Field
reason
adalah suatu alasan yang unik, satu kata, ditulis secara CamelCase untuk kondisi transisi terakhir. -
Field
status
adalah sebuah kata dengan kemungkinan nilainya berupa "True
", "False
", dan "Unknown
". -
Field
type
adalah sebuah kata yang memiliki kemungkinan nilai sebagai berikut:PodScheduled
: Pod telah dijadwalkan masuk ke node;Ready
: Pod sudah mampu menerima request masuk dan seharusnya sudah ditambahkan ke daftar pembagian beban kerja untuk servis yang sama;Initialized
: Semua init containers telah berjalan sempurna.Unschedulable
: scheduler belum dapat menjadwalkan Pod saat ini, sebagai contoh karena kekurangan resources atau ada batasan-batasan lain.ContainersReady
: Semua kontainer di dalam Pod telah siap.
Pemeriksaan Kontainer
Sebuah Probe adalah sebuah diagnosa yang dilakukan secara berkala oleh kubelet dalam suatu kontainer. Untuk melakukan diagnosa, kubelet memanggil sebuah Handler yang diimplementasikan oleh kontainer. Ada 3 tipe Handler yang tersedia, yaitu:
-
ExecAction: Mengeksekusi perintah tertentu di dalam kontainer. Diagnosa dikatakan berhasil jika perintah selesai dengan kode status 0.
-
TCPSocketAction: Melakukan pengecekan TCP terhadap alamat IP kontainer dengan port tertentu. Diagnosa dikatakan berhasil jika port tersebut terbuka.
-
HTTPGetAction: Melakukan sebuah request HTTP Get terhadap alamat IP kontainer dengan port dan path tertentu. Diagnosa dikatakan berhasil jika responnya memiliki kode status lebih besar atau sama dengan 200 dan kurang dari 400.
Setiap pemeriksaan akan menghasilkan salah satu dari tiga hasil berikut:
- Success: Kontainer berhasil melakukan diagnosa.
- Failure: Kontainer gagal melakukan diagnosa.
- Unknown: Gagal melakukan diagnosa, sehingga tidak ada aksi yang harus dilakukan.
Kubelet dapat secara optimal melakukan dan bereaksi terhadap dua jenis pemeriksaan yang sedang berjalan pada kontainer, yaitu:
-
livenessProbe
: Ini menunjukkan apakah kontainer sedang berjalan. Jika tidak berhasil melakukan pemeriksaan terhadap liveness dari kontainer, maka kubelet akan mematikan kontainer, dan kontainer akan mengikuti aturan dari restart policy. Jika kontainer tidak menyediakan pemeriksaan terhadap liveness, maka nilai dari state adalahSuccess
. -
readinessProbe
: Ini menunjukan apakah kontainer sudah siap melayani request. Jika tidak berhasil melakukan pemeriksaan terhadap kesiapan dari kontainer, maka endpoints controller akan menghapus alamat IP Pod dari daftar semua endpoint untuk servis yang sama dengan Pod. Nilai awal state sebelum jeda awal adalahFailure
. Jika kontainer tidak menyediakan pemeriksaan terhadap readiness, maka nilai awal state adalahSuccess
.
Kapan sebaiknya menggunakan pemeriksaan terhadap liveness atau readiness?
Jika proses dalam kontainer mungkin gagal yang dikarenakan menghadapi suatu masalah
atau menjadi tidak sehat, maka pemeriksaan terhadap liveness tidak diperlukan.
Kubelet akan secara otomatis melakukan aksi yang tepat mengikuti restartPolicy
dari Pod.
Jika kamu ingin kontainer bisa dimatikan dan dijalankan ulang ketika gagal melakukan
pemeriksaan, maka tentukan pemeriksaan liveness dan tentukan nilai restartPolicy
sebagai Always
atau OnFailure
.
Jika kamu ingin mulai mengirim traffic ke Pod hanya ketika pemeriksaan berhasil, maka tentukan pemeriksaan readiness. Dalam kasus ini, pemeriksaan readiness mungkin akan sama dengan pemeriksaan liveness, tapi keberadaan pemeriksaan readiness dalam spec berarti Pod akan tetap dijalankan tanpa menerima traffic apapun dan akan mulai menerima traffic ketika pemeriksaan yang dilakukan mulai berhasil. Jika kontainermu dibutuhkan untuk tetap berjalan ketika loading data yang besar, file konfigurasi, atau melakukan migrasi ketika startup, maka tentukanlah pemeriksaan readiness.
Jika kamu ingin kontainermu dalam mematikan dirinya sendiri, kamu dapat menentukan suatu pemeriksaan readiness yang melakukan pengecekan terhadap endpoint untuk readiness. endpoint tersebut berbeda dengan endpoint untuk pengecekan liveness.
Perlu dicatat, jika kamu hanya ingin bisa menutup request ketika Pod sedang dihapus maka kamu tidak perlu menggunakan pemeriksaan readiness. Dalam penghapusan, Pod akan secara otomatis mengubah state dirinya menjadi unready tanpa peduli apakah terdapat pemeriksaan readiness atau tidak. Pod tetap ada pada state unready selama menunggu kontainer dalam Pod berhenti.
Untuk informasi lebih lanjut mengenai pengaturan pemeriksaan liveness atau readiness, lihat bagian Konfigurasi Liveness dan Readiness Probe.
Status Pod dan Kontainer
Untuk informasi lebih mendalam mengenai status Pod dan kontainer, silakan lihat PodStatus dan ContainerStatus. Mohon diperhatikan, informasi tentang status Pod bergantung pada ContainerState.
State Kontainer
Ketika Pod sudah ditempatkan pada suatu node oleh scheduler, kubelet mulai membuat kontainer menggunakan runtime kontainer.
Ada tiga kemungkinan state untuk suatu kontainer, yaitu Waiting, Running, dan Terminated.
Untuk mengecek state suatu kontainer, kamu bisa menggunakan perintah kubectl describe pod [NAMA_POD]
.
State akan ditampilkan untuk masing-masing kontainer dalam Pod tersebut.
-
Waiting
: Merupakan state default dari kontainer. Jika state kontainer bukan Running atau Terminated, berarti dalam Wating state. Suatu kontainer dalam Waiting state akan tetap menjalan operasi-operasi yang dibutuhkan, misalnya mengunduh images, mengaplikasikan Secrets, dsb. Bersamaan dengan state ini, sebuah pesan dan alasan tentang state akan ditampilkan untuk memberi informasi lebih.... State: Waiting Reason: ErrImagePull ...
-
Running
: Menandakan kontainer telah berjalan tanpa masalah. Setelah kontainer masuk ke state Running, jika terdapat hookpostStart
maka akan dijalankan. State ini juga menampilkan waktu ketika kontainer masuk ke state Running.... State: Running Started: Wed, 30 Jan 2019 16:46:38 +0530 ...
-
Terminated
: Menandakan kontainer telah menyelesaikan "tugasnya". Kontainer akan menjadi state ini ketika telah menyelesaikan eksekusi atau terjadi kesalahan. Terlepas dari itu, sebuah alasan dan exit code akan ditampilkan, bersama dengan waktu kontainer mulai dijalankan dan waktu berhenti. Sebelum kontainer masuk ke state Terminated, jika terdapatpreStop
hook maka akan dijalankan.... State: Terminated Reason: Completed Exit Code: 0 Started: Wed, 30 Jan 2019 11:45:26 +0530 Finished: Wed, 30 Jan 2019 11:45:26 +0530 ...
Pod readiness gate
Kubernetes v1.14 [stable]
Dalam rangka menambahkan ekstensibilitas terhadap kesiapan Pod dengan menggunakan
injeksi umpan balik tambahan atau sinyal ke dalam PodStatus
,
Kubernetes 1.11 memperkenalkan sebuah fitur bernama Pod ready++.
Kamu dapat menggunakan field baru ReadinessGate
dalam sebuah PodSpec
untuk
menunjukan kondisi tambahan yang akan dievaluasi untuk kesiapan Pod. Jika Kubernetes
tidak dapat menemukan kondisi pada field status.conditions
dalam suatu Pod,
maka statusnya akan secara otomatis menjadi False
. Berikut adalah contoh pemakaiannya:
Kind: Pod
...
spec:
readinessGates:
- conditionType: "www.example.com/feature-1"
status:
conditions:
- type: Ready # ini adalah PodCondition yang telah tersedia
status: "False"
lastProbeTime: null
lastTransitionTime: 2018-01-01T00:00:00Z
- type: "www.example.com/feature-1" # sebuah PodCondition tambahan
status: "False"
lastProbeTime: null
lastTransitionTime: 2018-01-01T00:00:00Z
containerStatuses:
- containerID: docker://abcd...
ready: true
...
Kondisi Pod yang baru harus memenuhi format label pada Kubernetes.
Sejak perintah kubectl patch
belum mendukung perubahan status objek, kondisi Pod yang baru harus mengubah melalui aksi PATCH
dengan menggunakan
salah satu dari KubeClient libraries.
Dengan diperkenalkannya kondisi Pod yang baru, sebuah Pod akan dianggap siap hanya jika memenuhi dua syarat berikut:
- Semua kontainer dalam Pod telah siap.
- Semua kontainer yang diatur dalam
ReadinessGates
bernilai "True
".
Untuk memfasilitasi perubahan tersebut terhadap evaluasi kesiapan Pod, dibuatkan sebuah kondisi Pod baru yaitu ContainerReady
,
untuk dapat menangani kondisi Pod Ready
yang sudah ada.
Dalam K8s 1.11, sebagai fitur alpha, fitur "Pod Ready++" harus diaktifkan melalui pengaturan
fitur gate pada PodReadinessGates
.
Dalam K8s 1.12, fitur tersebut sudah diaktifkan dari awal.
Aturan Menjalankan Ulang
Sebuah PodSpec memiliki field restartPolicy
dengan kemungkinan nilai berupa Always, OnFailure, dan Never.
Nilai awalnya berupa Always. restartPolicy
akan berlaku untuk semua kontainer dalam Pod.
Kontainer yang mati dan dijalankan ulang oleh kubelet akan dijalankan ulang dengan jeda waktu yang ekponensial (10s, 20s, 40s, ...)
dengan batas atas senilai lima menit. Jeda waktu ini akan diatur ulang setelah sukses berjalan selama 10 menit.
Sesuai dengan diskusi pada dokumen Pod,
setelah masuk ke suatu node, sebuah Pod tidak akan pindah ke node lain.
Umur Pod
Secara umum, Pod tidak hilang sampai ada yang menghapusnya. Ini mungkin dihapus oleh orang atau pengontrol.
Satu pengecualian untuk aturan ini adalah Pod dengan phase
bernilai Succeeded atau Failed untuk waktu
beberapa lama yang akan berakhir dan secara otomatis akan dihapus.
(diatur dalam terminated-pod-gc-threshold
pada master)
Tiga tipe pengontrol yang tersedia yaitu:
-
Menggunakan sebuah Job untuk Pod yang diharapkan akan berakhir, sebagai contoh, penghitungan dalam jumlah banyak. Jobs hanyak cocok untuk Pod dengan
restartPolicy
yang bernilai OnFailure atau Never. -
Menggunakan sebuah ReplicationController, ReplicaSet, atau Deployment untuk Pod yang tidak diharapkan untuk berakhir, sebagai contoh, web servers. ReplicationControllers hanya cocok digunakan pada Pod dengan
restartPolicy
yang bernilai Always. -
Menggunakan sebuah DaemonSet untuk Pod yang akan berjalan hanya satu untuk setiap mesin, karena menyediakan servis yang spesifik untuk suatu mesin.
Ketiga tipe pengontrol ini memiliki sebuah PodTemplate. Direkomdasikan untuk membuat pengontrol yang sesuai dan membiarkan ini membuat Pod, daripada membuat Pod sendiri secara langsung. Karena Pod itu sendiri tidak tahan terhadap gagalnya suatu mesin, namun pengontrol tahan.
Jika node mati atau sambungannya terputus dari klaster, Kubernetes mengatur
phase
dari semua Pod pada node yang mati untuk menjadi Failed.
Contoh
Contoh Liveness Probe tingkat lanjut
Liveness probe dieksekusi oleh kubelet, jadi semua permintaan akan dilakukan di dalam namespace jaringan kubelet.
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- args:
- /server
image: k8s.gcr.io/liveness
livenessProbe:
httpGet:
# ketika "host" tidak ditentukan, "PodIP" akan digunakan
# host: my-host
# ketika "scheme" tidak ditentukan, _scheme_ "HTTP" akan digunakan. Hanya "HTTP" and "HTTPS" yang diperbolehkan
# scheme: HTTPS
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 15
timeoutSeconds: 1
name: liveness
Contoh State
-
Pod sedang berjalan dan memiliki sebuah kontainer. Kontainer berhenti dengan sukses.
- Mencatat event penyelesaian.
- Jika nilai
restartPolicy
adalah:- Always: Jalankan ulang kontainer; nilai
phase
Pod akan tetap Running. - OnFailure: nilai
phase
Pod akan berubah menjadi Succeeded. - Never: nilai
phase
Pod akan berubah menjadi Succeeded.
- Always: Jalankan ulang kontainer; nilai
-
Pod sedang berjalan dan memiliki sebuah kontainer. Kontainer berhenti dengan kegagalan.
- Mencatat event kegagalan.
- Jika nilai
restartPolicy
adalah:- Always: Jalankan ulang kontainer, nilai
phase
Pod akan tetap Running. - OnFailure: Jalankan ulang kontainer, nilai
phase
Pod akan tetap Running. - Never: nilai
phase
Pod akan menjadi Failed.
- Always: Jalankan ulang kontainer, nilai
-
Pod sedang berjalan dan memiliki dua kontainer. Kontainer pertama berhenti dengan kegagalan.
- Mencatat event kegagalan.
- Jika nilai
restartPolicy
adalah:- Always: Jalankan ulang kontainer, nilai
phase
Pod akan tetap Running. - OnFailure: Jalankan ulang kontainer, nilai
phase
Pod akan tetap Running. - Never: Tidak akan menjalankan ulang kontainer, nilai
phase
Pod akan tetap Running.
- Always: Jalankan ulang kontainer, nilai
- Jika kontainer pertama tidak berjalan dan kontainer kedua berhenti:
- Mencatat event kegagalan.
- Jika nilai
restartPolicy
adalah:- Always: Jalankan ulang kontainer, nilai
phase
Pod akan tetap Running. - OnFailure: Jalankan ulang kontainer, nilai
phase
Pod akan tetap Running. - Never: nilai
phase
Pod akan menjadi Failed.
- Always: Jalankan ulang kontainer, nilai
-
Pod sedang berjalan dan memiliki satu kontainer. Kontainer berhenti karena kehabisan memory.
- Kontainer diberhentikan dengan kegagalan.
- Mencatat kejadian kehabisan memory (OOM)
- Jika nilai
restartPolicy
adalah:- Always: Jalankan ulang kontainer, nilai
phase
Pod akan tetap Running. - OnFailure: Jalankan ulang kontainer, nilai
phase
Pod akan tetap Running. - Never: Mencatat kejadian kegagalan, nilai
phase
Pod akan menjadi Failed.
- Always: Jalankan ulang kontainer, nilai
-
Pod sedang berjalan dan sebuah disk mati.
- Menghentikan semua kontainer.
- Mencatat kejadian yang sesuai.
- Nilai
phase
Pod menjadi Failed. - Jika berjalan menggunakan pengontrol, maka Pod akan dibuat ulang di tempat lain.
-
Pod sedang berjalan, dan node mengalami segmented out.
- Node pengontrol menunggu sampai suatu batas waktu.
- Node pengontrol mengisi nilai
phase
Pod menjadi Failed. - Jika berjalan menggunakan pengontrol, maka Pod akan dibuat ulang di tempat lain.
Selanjutnya
-
Dapatkan pengalaman langsung mengenai penambahan handlers pada kontainer lifecycle events.
-
Dapatkan pengalaman langsung mengenai pengaturan liveness dan readiness probes.
-
Pelajari lebih lanjut mengenai lifecycle hooks pada kontainer.
3.4.1.4 - Init Container
Halaman ini menyediakan ikhtisar untuk Init Container, yaitu Container khusus yang dijalankan sebelum Container aplikasi dan berisi skrip peralatan atau setup yang tidak tersedia di dalam image dari Container aplikasi.
Fitur ini telah keluar dari trek Beta sejak versi 1.6. Init Container dapat dispesifikasikan di dalam PodSpec bersama dengan array containers
aplikasi. Nilai anotasi beta akan tetap diperhitungkan dan akan menimpa nilai pada PodSpec, tetapi telah ditandai sebagai kedaluarsa pada versi 1.6 dan 1.7. Pada versi 1.8, anotasi beta tidak didukung lagi dan harus diganti menjadi nilai pada PodSpec.
Memahami Init Container
Sebuah Pod dapat memiliki beberapa Container yang berjalan di dalamnya, dan dapat juga memiliki satu atau lebih Init Container, yang akan berjalan sebelum Container aplikasi dijalankan.
Init Container sama saja seperti Container biasa, kecuali:
- Mereka selalu berjalan hingga selesai.
- Setiap Init Container harus selesai secara sukses sebelum Init Container berikutnya dijalankan.
Jika sebuah Init Container tidak selesai secara sukses untuk sebuah Pod, Kubernetes akan mengulang kembali Pod tersebut secara terus menerus hingga Init Container selesai secara sukses. Tetapi, jika Pod tersebut memiliki nilai restartPolicy
berupa Never
, Pod tersebut tidak akan diulang kembali.
Untuk menspesifikasikan sebuah Container sebagai Init Container, tambahkan kolom initContainers
pada PodSpec sebagai sebuah array JSON yang berisi objek dengan tipe Container, berdampingan dengan array containers
aplikasi.
Status-status dari Init Container dikembalikan di kolom .status.initContainerStatuses
sebagai sebuah array dari status-status Container (mirip seperti kolom status.containerStatuses
)
Perbedaan dengan Container biasa
Init Container mendukung semua kolom dan fitur dari Container aplikasi, termasuk konfigurasi limit
sumber daya, volume
, dan keamanan. Tetapi, request
dan limit
sumber daya dari sebuah Init Container ditangani dengan cara yang sedikit berbeda, yang didokumentasikan di bagian Sumber Daya di bawah. Juga, Init Container tidak mendukung readiness probe karena mereka harus berjalan hingga selesai sebelum Pod dapat siap.
Jika beberapa Init Container dispesifikasikan untuk sebuah Pod, Container-container tersebut akan dijalankan satu per satu secara berurutan. Setiap Init Container harus selesai secara sukses sebelum yang berikutnya dapat berjalan. Saat semua Init Container telah berjalan hingga selesai, Kubernetes akan menginisialisasi Pod dan menjalankan Container aplikasi seperti biasa.
Apa kegunaan Init Container?
Karena Init Container memiliki image yang berbeda dengan Container aplikasi, mereka memiliki beberapa kelebihan untuk kode yang berhubungan dengan dimulainya Init Container:
- Mereka dapat berisi dan menjalankan skrip peralatan yang tidak diinginkan untuk berada di dalam image Container aplikasi karena alasan keamanan.
- Mereka dapat berisi skrip peralatan atau setup yang tidak tersedia di dalam image aplikasi. Misalnya, kita tidak perlu membuat image dengan instruksi
FROM
dari image lainnya hanya untuk menggunakan peralatan sepertised
,awk
,python
, ataudig
pada saat setup. - Peran builder atau deployer dari image dapat bekerja secara independen tanpa harus digabung untuk membuat satu image aplikasi.
- Mereka menggunakan namespace Linux, sehingga mereka dapat memiliki sudut pandang filesystem yang berbeda dengan Container aplikasi. Oleh karenanya, mereka dapat diberikan akses terhadap
Secret
yang tidak boleh diakses oleh Container aplikasi. - Mereka berjalan hingga selesai sebelum Container aplikasi manapun dimulai, sedangkan Container aplikasi dijalankan secara paralel, sehingga Init Container menyediakan cara yang mudah untuk menunda dijalankannya Container aplikasi hingga ketentuan-ketentuan yang diinginkan dipenuhi.
Contoh-contoh
Berikut beberapa contoh kasus penggunaan Init Container:
-
Menunggu sebuah Service untuk dibuat dengan perintah shell seperti:
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
-
Mendaftarkan suatu Pod ke sebuah peladen terpisah dari downward API dengan perintah seperti:
`curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'`
-
Menunggu beberapa waktu sebelum menjalankan Container aplikasi dengan perintah seperti
sleep 60
. -
Mengklon sebuah git repository ke dalam sebuah volume.
-
Menaruh nilai-nilai tertentu ke dalam sebuah file konfigurasi dan menjalankan peralatan template untuk membuat file konfigurasi secara dinamis untuk Container aplikasi utama. Misalnya, untuk menaruh nilai POD_IP ke dalam sebuah konfigurasi dan membuat konfigurasi aplikasi utama menggunakan Jinja.
Contoh-contoh penggunaan yang lebih detail dapat dilihat pada dokumentasi StatefulSet dan petunjuk Produksi Pod.
Menggunakan Init Container
File YAML untuk Kubernetes 1.5 berikut menguraikan sebuah Pod sederhana yang memiliki dua buah Init Container.
Pod pertama menunggu myservice
dan yang kedua menunggu mydb
. Saat kedua Init Container tersebut sudah selesai, Podnya akan dijalankan.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
annotations:
pod.beta.kubernetes.io/init-containers: '[
{
"name": "init-myservice",
"image": "busybox:1.28",
"command": ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
},
{
"name": "init-mydb",
"image": "busybox:1.28",
"command": ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
}
]'
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
Ada sintaksis baru pada Kubernetes 1.6, walaupun sintaksis anotasi yang lama tetap akan bekerja untuk versi 1.6 dan 1.7. Sintaksis yang baru harus digunakan untuk versi 1.8 ke atas. Deklarasi Init Container dipindahkan ke dalam spec
:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
Sintaksis versi 1.5 tetap akan bekerja pada versi 1.6 dan 1.7, tetapi kami menyarankan untuk menggunakan sintaksis versi 1.6. Pada Kubernetes 1.6, Init Container dijadikan sebagai sebuah kolom di dalam API Kubernetes. Anotasi beta tetap akan diperhitungkan pada versi 1.6 dan 1.7, tetapi tidak didukung lagi pada versi 1.8 ke atas.
File YAML di bawah menguraikan Service mydb
dan myservice
.
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
Pod ini dapat dijalankan dan di-debug dengan menggunakan perintah berikut:
kubectl apply -f myapp.yaml
pod/myapp-pod created
kubectl get -f myapp.yaml
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
kubectl describe -f myapp.yaml
Name: myapp-pod
Namespace: default
[...]
Labels: app=myapp
Status: Pending
[...]
Init Containers:
init-myservice:
[...]
State: Running
[...]
init-mydb:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Containers:
myapp-container:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201
16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
kubectl logs myapp-pod -c init-myservice # Memeriksa Init Container pertama
kubectl logs myapp-pod -c init-mydb # Memeriksa Init Container kedua
Saat kita menjalankan Service mydb
dan myservice
, kita dapat melihat Init Container telah selesai dan myapp-pod
pun dibuat:
kubectl apply -f services.yaml
service/myservice created
service/mydb created
kubectl get -f myapp.yaml
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
Contoh ini sangat sederhana, tetapi dapat memberikan sedikit petunjuk bagi kamu untuk membuat Init Container sendiri.
Perilaku mendetail
Saat dimulainya sebuah Pod, Init Container dijalankan secara berurutan, setelah jaringan dan volume telah diinisialisasi. Setiap Init Container harus selesai dan keluar secara berhasil sebelum yang berikutnya dijalankan. Jika ada Init Container yang gagal dijalankan atau keluar secara gagal, dia akan diulang kembali sesuai dengan restartPolicy
yang dimiliki Pod. Tetapi, jika restartPolicy
Pod disetel dengan nilai Always
, Init Container akan menggunakan strategi RestartPolicy
OnFailure
.
Sebuah Pod tidak dapat masuk ke status Ready
hingga semua Init Container berhasil selesai. Port di sebuah Init Container tidak diagregasikan di dalam sebuah Service. Sebuah Pod yang sedang diinisalisasikan akan masuk ke dalam status Pending
, tetapi akan memiliki kondisi Initialized
yang disetel menjadi true
.
Jika sebuah Pod diulang kembali, semua Init Container harus dijalankan kembali.
Perubahan pada spesifikasi Init Container dibatasi hanya pada kolom image
pada Init Container. Mengganti kolom image
sebuah Init Container sama dengan mengulang kembali Pod tersebut.
Karena Init Container dapat diulang kembali, dicoba ulang, atau dijalankan ulang, Init Container sebaiknya bersifat idempotent. Khususnya, kode yang menulis ke dalam file pada EmptyDir
sebaiknya dipersiapkan untuk menangani kemungkinan jika file keluaran yang diharapkan sudah ada di dalam EmptyDir
tersebut.
Init Container memiliki semua kolom yang dimiliki oleh Container aplikasi. Tetapi, Kubernetes melarang penggunaan readinessProbe
karena Init Container tidak dapat mendefinisikan/menggunakan readiness probe setelah selesai/keluar secara berhasil. Hal ini dipaksakan saat proses validasi.
Gunakan activeDeadlineSeconds
pada Pod dan livenessProbe
pada Container untuk mencegah Init Container gagal terus menerus. Nilai activeDeadlineSeconds
berlaku juga terhadap Init Container.
Nama setiap Container aplikasi dan Init Container pada sebuah Pod haruslah unik; Kesalahan validasi akan terjadi jika ada Container atau Init Container yang memiliki nama yang sama.
Sumber Daya
Karena eksekusi Init Container yang berurutan, aturan-aturan untuk sumber daya berlaku sebagai berikut:
- Yang tertinggi antara
request
ataulimit
sumber daya yang didefinisikan pada semua Init Container adalahrequest
/limit
inisialisasi yang berlaku. request
/limit
sumber daya Pod yang berlaku adalah yang paling besar diantara:- Jumah
request
/limit
semua Container aplikasi untuk suatu sumber daya. request
/limit
inisialisasi yang berlaku untuk suatu sumber daya.
- Jumah
- Penjadwalan dilakukan berdasarkan
request
/limit
(Pod) yang berlaku, yang berarti bahwa Init Container dapat mengambil sumber daya inisialisasi yang tidak digunakan selama umur Pod tersebut. - Tingkat QoS yang berlaku milik Pod adalah sama dengan tingkat QoS untuk Init Container dan Container aplikasi.
ResourceQuota
dan limitedResources
diberlakukan berdasarkan request
dan limit
Pod yang berlaku.
Cgroup pada tingat Pod didasarkan pada request
dan limit
Pod yang berlaku, sama dengan scheduler.
Alasan Pod diulang kembali
Pod dapat diulang kembali, yang berakibat pada diulangnya eksekusi Init Container, diakibatkan oleh beberapa alasan berikut:
- Seorang pengguna memperbarui
PodSpec
, mengakibatkanimage
Init Container berubah. Perubahan apapun padaimage
Init Container akan mengulang kembali Pod tersebut. Perubahan padaimage
Container aplikasi hanya mengulang kembali Container aplikasi yang bersangkutan. - Infrastruktur Container Pod diulang kembali. Hal ini jarang terjadi, dan hanya dapat dilakukan oleh seseorang yang memiliki akses root pada node yang bersangkutan.
- Semua Container di dalam Pod diterminasi, dengan nilai
restartPolicy
yang disetel sebagaiAlways
, memaksa pengulangan kembali, dan catatan selesainya Init Container telah hilang karena garbage collection.
Dukungan dan kompatibilitas
Sebuah klaster dengan versi Apiserver 1.6.0 ke atas mendukung Init Container melalui kolom .spec.initContainers
. Versi-versi sebelumnya mendukung Init Container melalui anotasi alpha atau beta. Kolom .spec.initContainers
juga diduplikasikan dalam bentuk anotasi alpha dan beta agar Kubelet versi 1.3.0 ke atas dapat menjalankan Init Container, dan agar Apiserver versi 1.6 dapat dengan aman dikembalikan ke versi 1.5.x tanpa kehilangan fungsionalitas Pod-pod yang telah dibuat sebelumnya.
Pada Apiserver dan Kubelet versi 1.8.0 ke atas, dukungan untuk anotasi alpha dan beta telah dihapus, sehingga dibutuhkan konversi (manual) dari anotasi yang telah kedaluwarsa tersebut ke dalam bentuk kolom .spec.initContainers
.
Selanjutnya
3.4.1.5 - Batasan Persebaran Topologi Pod
Kubernetes v1.18 [beta]
Kamu dapat menggunakan batasan perseberan topologi (topology spread constraints) untuk mengatur bagaimana Pod akan disebarkan pada klaster yang ditetapkan sebagai failure-domains, seperti wilayah, zona, Node dan domain topologi yang ditentukan oleh pengguna. Ini akan membantu untuk mencapai ketersediaan yang tinggi dan juga penggunaan sumber daya yang efisien.
Persyaratan
Mengaktifkan Gerbang Fitur
Gerbang fitur (feature gate)
EvenPodsSpread
harus diaktifkan untuk
API Server dan
penjadwal (_scheduler_).
Label Node
Batasan persebaran topologi bergantung dengan label pada Node untuk menentukan
domain topologi yang memenuhi untuk semua Node. Misalnya saja, sebuah Node bisa memiliki
label sebagai berikut: node=node1,zone=us-east-1a,region=us-east-1
Misalkan kamu memiliki klaster dengan 4 Node dengan label sebagai berikut:
NAME STATUS ROLES AGE VERSION LABELS
node1 Ready <none> 4m26s v1.16.0 node=node1,zone=zoneA
node2 Ready <none> 3m58s v1.16.0 node=node2,zone=zoneA
node3 Ready <none> 3m17s v1.16.0 node=node3,zone=zoneB
node4 Ready <none> 2m43s v1.16.0 node=node4,zone=zoneB
Maka klaster tersebut secara logika akan dilihat sebagai berikut:
+---------------+---------------+
| zoneA | zoneB |
+-------+-------+-------+-------+
| node1 | node2 | node3 | node4 |
+-------+-------+-------+-------+
Tanpa harus memberi label secara manual, kamu dapat menggunakan [label ternama] (/docs/reference/kubernetes-api/labels-annotations-taints/) yang terbuat dan terkumpulkan secara otomatis pada kebanyakan klaster.
Batasan Persebaran untuk Pod
API
Field pod.spec.topologySpreadConstraints
diperkenalkan pada versi 1.16 sebagai berikut:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
topologySpreadConstraints:
- maxSkew: <integer>
topologyKey: <string>
whenUnsatisfiable: <string>
labelSelector: <object>
Kamu dapat mendefinisikan satu atau lebih topologySpreadConstraint
untuk menginstruksikan
kube-scheduler mengenai cara peletakan tiap Pod baru dengan menggunakan kondisi Pod yang
sudah ada dalam klaster kamu. Field yang ada adalah:
- maxSkew menentukan batasan yang menandakan Pod tidak tersebar secara merata. Ini merupakan nilai maksimal dari selisih jumlah Pod yang sama untuk setiap 2 domain topologi yang sama. Nilai ini harus lebih dari 0.
- topologyKey adalah kunci dari label Node. Jika terdapat dua Node memiliki label dengan kunci ini dan memiliki nilai yang identik untuk label tersebut, maka penjadwal akan menganggap kedua Noode dalam topologi yang sama. Penjadwal akan mencoba untuk menyeimbangkan jumlah Pod dalam setiap domain topologi.
- whenUnsatisfiable mengindikasikan cara menangani Pod yang tidak memenuhi batasan persebaran:
DoNotSchedule
(default) memberitahukan penjadwal untuk tidak menjadwalkan Pod tersebut.ScheduleAnyway
memberitahukan penjadwal untuk tetap menjadwalkan Pod namun tetap menjaga ketidakseimbangan Node sekecil mungkin.
- labelSelector digunakan untuk mencari Pod yang sesuai. Pod dengan label yang sama dengan ini akan dihitung untuk menentukan jumlah Pod dalam domain topologi yang sesuai. Silakan baca Label dan Selector untuk lebih detailnya.
Kamu juga bisa membaca lebih detail mengenai field ini dengan menjalankan perintah
kubectl explain Pod.spec.topologySpreadConstraints
.
Contoh: Satu TopologySpreadConstraint
Misalkan kamu memiliki klaster dengan 4 Node dimana 3 Pod berlabel foo:bar
terdapat pada node1,
node2 dan node3 (P
merepresentasikan Pod):
+---------------+---------------+
| zoneA | zoneB |
+-------+-------+-------+-------+
| node1 | node2 | node3 | node4 |
+-------+-------+-------+-------+
| P | P | P | |
+-------+-------+-------+-------+
Jika kita ingin Pod baru akan disebar secara merata berdasarkan Pod yang telah ada pada semua zona, maka spec bernilai sebagai berikut:
kind: Pod
apiVersion: v1
metadata:
name: mypod
labels:
foo: bar
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
foo: bar
containers:
- name: pause
image: k8s.gcr.io/pause:3.1
topologyKey: zone
berarti persebaran merata hanya akan digunakan pada Node dengan pasangan label
"zone: whenUnsatisfiable: DoNotSchedule
memberitahukan penjadwal untuk membiarkan
tetap ditunda jika Pod yang baru tidak memenuhi batasan yang diterapkan.
Jika penjadwal menempatkan Pod baru pada "zoneA", persebaran Pod akan menjadi [3, 1], menjadikan
ketidakseimbangan menjadi bernilai 2 (3 - 1), yang mana akan melanggar batasan maxSkew: 1
.
Dalam contoh ini, Pod baru hanya dapat ditempatkan pada "zoneB":
+---------------+---------------+ +---------------+---------------+
| zoneA | zoneB | | zoneA | zoneB |
+-------+-------+-------+-------+ +-------+-------+-------+-------+
| node1 | node2 | node3 | node4 | OR | node1 | node2 | node3 | node4 |
+-------+-------+-------+-------+ +-------+-------+-------+-------+
| P | P | P | P | | P | P | P P | |
+-------+-------+-------+-------+ +-------+-------+-------+-------+
Kamu dapat mengatur spesifikasi Pod untuk memenuhi beberapa persyaratan berikut:
- Ubah nilai
maxSkew
menjadi lebih besar, misal "2", sehingga Pod baru dapat ditempatkan pada "zoneA". - Ubah nilai
topologyKey
menjadi "node" agar Pod disebarkan secara merata pada semua Node, bukan zona. Pada contoh di atas, jikamaxSkew
tetap bernilai "1", maka Pod baru hanya akan ditempatkan pada "node4". - Ubah nilai
whenUnsatisfiable: DoNotSchedule
menjadiwhenUnsatisfiable: ScheduleAnyway
untuk menjamin agar semua Pod baru akan tetap dijadwalkan (misalkan saja API penjadwalan lain tetap terpenuhi). Namun, ini lebih suka ditempatkan pada domain topologi yang memiliki lebih sedikit Pod yang sesuai. (Harap diperhatikan bahwa preferensi ini digabungkan bersama dengan prioritas penjadwalan internal yang lain, seperti rasio penggunaan sumber daya, dan lain sebagainya.)
Contoh: Beberapa TopologySpreadConstraint
Ini dibuat berdasarkan contoh sebelumnya. Misalkan kamu memiliki klaster dengan 4 Node dengan
3 Pod berlabel foo:bar
yang ditempatkan pada node1, node2 dan node3. (P
merepresentasikan Pod):
+---------------+---------------+
| zoneA | zoneB |
+-------+-------+-------+-------+
| node1 | node2 | node3 | node4 |
+-------+-------+-------+-------+
| P | P | P | |
+-------+-------+-------+-------+
Kamu dapat menggunakan 2 TopologySpreadConstraint untuk mengatur persebaran Pod pada zona dan Node:
kind: Pod
apiVersion: v1
metadata:
name: mypod
labels:
foo: bar
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
foo: bar
- maxSkew: 1
topologyKey: node
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
foo: bar
containers:
- name: pause
image: k8s.gcr.io/pause:3.1
Dalam contoh ini, untuk memenuhi batasan pertama, Pod yang baru hanya akan ditempatkan pada "zoneB", sedangkan untuk batasan kedua, Pod yang baru hanya akan ditempatkan pada "node4". Maka hasil dari 2 batasan ini akan digunakan (AND), sehingga opsi untuk menempatkan Pod hanya pada "node4".
Beberapa batasan dapat berujung pada konflik. Misalnya saja kamu memiliki klaster dengan 3 Node pada 2 zona berbeda:
+---------------+-------+
| zoneA | zoneB |
+-------+-------+-------+
| node1 | node2 | node3 |
+-------+-------+-------+
| P P | P | P P |
+-------+-------+-------+
Jika kamu menerapkan "two-constraints.yaml" pada klaster ini, kamu akan mendapatkan "mypod" tetap
dalam kondisi Pending
. Ini dikarenakan oleh: untuk memenuhi batasan pertama, "mypod" hanya dapat
ditempatkan pada "zoneB", sedangkan untuk batasan kedua, "mypod" hanya dapat ditempatkan pada
"node2". Tidak ada hasil penggabungan dari "zoneB" dan "node2".
Untuk mengatasi situasi ini, kamu bisa menambahkan nilai maxSkew
atau mengubah salah satu dari
batasan untuk menggunakan whenUnsatisfiable: ScheduleAnyway
.
Konvensi
Ada beberapa konvensi implisit yang perlu diperhatikan di sini:
-
Hanya Pod dengan Namespace yang sama dengan Pod baru yang bisa menjadi kandidat yang cocok.
-
Node tanpa memiliki
topologySpreadConstraints[*].topologyKey
akan dilewatkan. Ini berarti:- Pod yang ditempatkan pada Node tersebut tidak berpengaruh pada perhitungan
maxSkew
. Dalam contoh di atas, misalkan "node1" tidak memiliki label "zone", maka kedua Pod tidak diperhitungkan dan menyebabkan Pod yang baru akan dijadwalkan masuk ke "zoneA". - Pod yang baru tidak memiliki kesempatan untuk dijadwalkan ke Node tersebut, pada contoh di atas, misalkan terdapat "node5" dengan label
{zone-typo: zoneC}
bergabung dalam klaster, Node ini akan dilewatkan karena tidak memiliki label dengan kunci "zone".
- Pod yang ditempatkan pada Node tersebut tidak berpengaruh pada perhitungan
-
Harap diperhatikan mengenai hal yang terjadi jika nilai
topologySpreadConstraints[*].labelSelector
pada Pod yang baru tidak sesuai dengan labelnya. Pada contoh di atas, jika kita menghapus label pada Pod yang baru, maka Pod akan tetap ditempatkan pada "zoneB" karena batasan yang ada masih terpenuhi. Namun, setelah ditempatkan, nilai ketidakseimbangan pada klaster masih tetap tidak berubah, zoneA tetap memiliki 2 Pod dengan label {foo:bar} dan zoneB memiliki 1 Pod dengan label {foo:bar}. Jadi jika ini tidak yang kamu harapkan, kami menyarankan nilai daritopologySpreadConstraints[*].labelSelector
disamakan dengan labelnya. -
Jika Pod yang baru memiliki
spec.nodeSelector
atauspec.affinity.nodeAffinity
, Node yang tidak sesuai dengan nilai tersebut akan dilewatkan.Misalkan kamu memiliki klaster dengan 5 Node dari zoneA sampai zoneC:
+---------------+---------------+-------+ | zoneA | zoneB | zoneC | +-------+-------+-------+-------+-------+ | node1 | node2 | node3 | node4 | node5 | +-------+-------+-------+-------+-------+ | P | P | P | | | +-------+-------+-------+-------+-------+
dan kamu mengetahui bahwa "zoneC" harus tidak diperhitungkan. Dalam kasus ini, kamu dapat membuat berkas yaml seperti di bawah, jadi "mypod" akan ditempatkan pada "zoneB", bukan "zoneC". Demikian juga
spec.nodeSelector
akan digunakan.kind: Pod apiVersion: v1 metadata: name: mypod labels: foo: bar spec: topologySpreadConstraints: - maxSkew: 1 topologyKey: zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: foo: bar affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: zone operator: NotIn values: - zoneC containers: - name: pause image: k8s.gcr.io/pause:3.1
Batasan default pada tingkat klaster
Kubernetes v1.18 [alpha]
Ini memungkinkan untuk mengatur batasan persebaran topologi bawaan untuk klaster. Batasan persebaran topologi bawaan akan digunakan pada Pod jika dan hanya jika:
- Hal ini tidak mendefinisikan batasan apapun pada
.spec.topologySpreadConstraints
. - Hal ini milik sebuah Service, ReplicationController, ReplicaSet atau StatefulSet.
Batasan bawaan akan diatur sebagai bagian dari argumen pada plugin PodTopologySpread
di dalam sebuah profil penjadwalan.
Batasan dispesifikasikan dengan API yang sama dengan di atas, kecuali bagian labelSelector
harus kosong. selector akan dihitung dari Service, ReplicationController, ReplicaSet atau
StatefulSet yang dimiliki oleh Pod tersebut.
Sebuah contoh konfigurasi sebagai berikut:
apiVersion: kubescheduler.config.k8s.io/v1alpha2
kind: KubeSchedulerConfiguration
profiles:
- pluginConfig:
- name: PodTopologySpread
args:
defaultConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
DefaultPodTopologySpread
plugin.
Direkomendasikan untuk kamu menonaktifkan plugin ini dalam profil penjadwalan ketika
menggunakan batasan default untuk PodTopologySpread
.
Perbandingan dengan PodAffinity/PodAntiAffinity
Di Kubernetes, arahan yang terkait dengan "Afinitas" mengontrol bagaimana Pod dijadwalkan - lebih terkumpul atau lebih tersebar.
- Untuk
PodAffinity
, kamu dapat mencoba mengumpulkan beberapa Pod ke dalam suatu domain topologi yang memenuhi syarat. - Untuk
PodAntiAffinity
, hanya satu Pod yang dalam dijadwalkan pada sebuah domain topologi.
Fitur "EvenPodsSpread" memberikan opsi fleksibilas untuk mendistribusikan Pod secara merata pada domain topologi yang berbeda, untuk meraih ketersediaan yang tinggi atau menghemat biaya. Ini juga dapat membantu saat perbaruan bergilir dan menaikan jumlah replika dengan lancar. Silakan baca motivasi untuk lebih detail.
Limitasi yang diketahui
Pada versi 1.18, dimana fitur ini masih Beta, beberapa limitasi yang sudah diketahui:
- Pengurangan jumlah Deployment akan membuat ketidakseimbangan pada persebaran Pod.
- Pod yang cocok pada tainted Node akan dihargai. Lihat Issue 80921
3.4.1.6 - Pod Preset
Halaman ini menyajikan gambaran umum tentang PodPreset, yang merupakan objek untuk memasukkan informasi tertentu ke dalam Pod pada saat waktu penciptaan. Informasi dapat berupa secret, volume, volume mount, dan variabel environment.
Memahami Pod Preset
Sebuah Pod Preset
adalah sebuah resource API untuk memasukkan kebutuhan runtime tambahan ke dalam sebuah Pod pada saat waktu penciptaan. Kamu akan menggunakan label selector untuk menunjuk Pod dimana Pod Preset diterapkan.
Menggunakan sebuah Pod Preset memungkinkan pembuat templat pod untuk tidak menyediakan secara eksplisit semua informasi untuk setiap pod. Dengan demikian, pembuat templat pod yang mengkonsumsi sebuah service spesifik tidak perlu tahu semua detail-detail tentang service tersebut.
Untuk informasi lebih lanjut mengenai latar belakang lihat proposal desain untuk PodPreset.
Bagaimana Cara Kerja Pod Preset
Kubernetes menyediakan sebuah admission controller (PodPreset
) dimana, ketika diaktifkan, PodPreset diterapkan kepada permintaan penciptaan Pod yang akan datang. Ketika sebuah penciptaan Pod terjadi, sistem melakukan hal-hal berikut:
- Mengambil semua
PodPreset
yang tersedia untuk digunakan. - Cek jika label selector dari salah satu
PodPreset
cocok dengan label pada pod yang sedang diciptakan. - Usaha untuk menggabungkan berbagai resource didefinisikan oleh
PodPreset
ke dalam Pod yang sedang diciptakan. - Ketika terjadi galat, lempar sebuah event yang mendokumentasikan galat penggabungan dalam pod, dan membuat pod tanpa salah satu resource dari
PodPreset
. - Anotasikan hasil spesifikasi Pod yang telah dimodifikasi untuk menunjukkan bahwa Pod telah dimodifikasi oleh sebuah PodPreset. Anotasi berupa
podpreset.admission.kubernetes.io/podpreset-<nama pod-preset>: "<versi resource>"
.
Tiap Pod akan bisa dipasangkan oleh nol atau lebih PodPreset; dan tiap PodPreset bisa diterapkan ke nol atau lebih Pod. Ketika sebuah PodPreset diterapkan ke satu atau lebih Pod, Kubernetes memodifikasi Pod Spec. Untuk perubahan terhadap Env
,EnvFrom
, dan VolumeMount
, Kubernetes memodifikasi spesifikasi kontainer untuk semua kontainer di dalam Pod; Untuk perubahan terhadap Volume
, Kubernetes memodifikasi Pod Spec.
.spec.containers
pada sebuah Pod Spec jika sesuai. Tidak ada definisi resource dari Pod Preset yang akan diterapkan kepada kolom initContainer
.
Menonaktifkan Pod Preset untuk sebuah Pod Spesifik
Mungkin akan ada keadaan dimana kamu menginginkan sebuah Pod tidak bisa diubah oleh sebuah mutasi PodPreset. Pada kasus ini, kamu bisa menambahkan sebuah anotasi pada Pod Spec dalam bentuk: podpreset.admission.kubernetes.io/exclude: "true"
.
Mengaktifkan Pod Preset
Dalam rangka untuk menggunakan Pod Preset di dalam klaster kamu, kamu harus memastikan hal berikut:
-
Kamu telah mengaktifkan tipe API
settings.k8s.io/v1alpha1/podpreset
. Sebagai contoh, ini bisa dilakukan dengan menambahkansettings.k8s.io/v1alpha1=true
di dalam opsi--runtime-config
untuk API server. Dalam minikube tambahkan argumen berikut--extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=true
saat menginisialisasi klaster. -
Kamu telah mengaktifkan admission controller dari
PodPreset
. Salah satu cara untuk melakukannya adalah dengan menambahkanPodPreset
di dalam nilai opsi--enable-admission-plugins
yang dispesifikasikan untuk API server. Dalam minikube tambahkan argumen berikut--extra-config=apiserver.enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset
saat menginisialisasi klaster.
-
Kamu telah membuat objek
PodPreset
pada namespace yang kamu gunakan dengan cara mendefinisikan Pod Preset.
Selanjutnya
3.4.1.7 - Disrupsi
Petunjuk ini ditujukan pada pemilik aplikasi yang meninginkan aplikasinya memiliki ketersediaan yang tinggi, sehingga butuh untuk mengerti jenis-jenis Disrupsi yang dapat terjadi pada Pod-pod.
Petunjuk ini juga ditujukan pada administrator klaster yang ingin melakukan berbagai tindakan otomasi pada klaster, seperti pembaruan dan autoscaling klaster.
Disrupsi yang Disengaja dan Tidak Disengaja
Pod-pod tidak akan terhapus sampai sesuatu (orang ataupun pengendali) menghancurkan mereka atau ada kesalahan perangkat keras maupun perangkat lunak yang tidak dapat dihindari.
Kita menyebut kasus-kasus yang tidak dapat dihindari sebagai disrupsi yang tidak disengaja terhadap aplikasi. Beberapa contohnya adalah sebagai berikut:
- Kesalahan perangkat keras pada mesin yang menjalankan Node
- Administrator klaster menghapus virtual machine secara tidak sengaja
- Kesalahan pada penyedia layanan cloud yang mengakibatkan terhapusnya virtual machine
- Sebuah kernel panic
- Node menghilang dari klaster karena partisi jaringan klaster
- Pod mengalami eviction karena Node kehabisan sumber daya
Dengan pengecualian pada kondisi kehabisan sumber daya, kondisi-kondisi tersebut pada umumnya diketahui oleh kebanyakan pengguna karena kondisi-kondisi tersebut tidak spesifik pada Kubernetes saja.
Kita menyebut kasus-kasus lainnya sebagai disrupsi yang disengaja. Hal ini termasuk tindakan yang dilakukan oleh pemilik aplikasi atau yang dilakukan oleh administrator klaster. Pemilik aplikasi umumnya melakukan hal-hal berikut:
- Menghapus Deployment atau pengendali yang mengatur Pod
- Memperbarui templat Pod yang menyebabkan pengulangan kembali/restart
- Menghapus Pod secara langsung
Administrator klaster umumnya melakukan hal-hal berikut:
- Melakukan drain terhadap Node untuk perbaikan atau pembaruan.
- Melakukan drain terhadap sebuah node dari klaster untuk memperkecil ukuran klaster (untuk lebih lanjutnya, pelajari Autoscaling klaster).
- Menghapus sebuah Pod dari node untuk memuat Pod lain ke node tersebut.
Tindakan-tindakan tersebut dapat dilakukan secara langsung oleh administrator klaster, atau oleh alat otomasi yang dijalankan oleh administrator klaster, atau oleh penyedia layanan Kubernetes kamu.
Tanyakan administrator klaster atau penyedia layanan cloud kamu, atau lihatlah dokumentasi penyedia layanan Kubernetes kamu untuk mengetahui bila ada sumber-sumber yang berpotensi mengakibatkan disrupsi yang disengaja yang ada pada klastermu. Jika tidak ada, kamu bisa melewatkan pembuatan PodDisruptionBudget
Mengatasi Disrupsi
Berikut beberapa cara untuk mengatasi disrupsi yang tidak disengaja:
- Pastikan Pod-pod kamu merinci permintaan sumber daya klaster yang dibutuhkan.
- Replikasikan aplikasimu jika membutuhkan ketersediaan yang tinggi. (Pelajari tentang menjalankan aplikasi stateless dan stateful).
- Untuk mencapai ketersediaan yang bahkan lebih tinggi lagi saat mereplikasikan aplikasi, sebarkanlah Pod-pod kamu di rak-rak pada data center (menggunakan anti-affinity) atau di seluruh zona (jika kamu menggunakan klaster pada beberapa zona).
Frekuensi disrupsi yang disengaja dapat berubah-ubah. Pada klaster Kubernetes yang dasar, tidak ada disrupsi yang disengaja sama sekali. Tetapi, administrator klaster atau penyedia layanan Kubernetes kamu mungkin saja menjalankan beberapa servis tambahan yang dapat mengakibatkan disrupsi yang disengaja. Misalnya, memperbarui perangkat lunak pada node yang dapat mengakibatkan disrupsi yang disengaja. Selain itu, beberapa implementasi autoscaling klaster (atau node) dapat mengakibatkan disrupsi yang disengaja untuk merapikan dan memadatkan node-node pada klaster. Administrator klaster atau penyedia layanan Kubernetes kamu perlu mendokumentasikan tingkatan disrupsi yang disengaja, jika ada disrupsi yang telah diperkirakan.
Kubernetes menawarkan fitur-fitur untuk membantu menjalankan aplikasi-aplikasi dengan ketersediaan tinggi bersamaan dengan seringnya disrupsi yang disengaja, fitur-fitur tersebut dinamai Disruption Budget.
Bagaimana cara kerja Disruption Budget
Pemilik aplikasi dapat membuat objek PodDisruptionBudget
(PDB) untuk setiap aplikasi. Sebuah PDB membatasi jumlah Pod yang boleh mati secara bersamaan pada aplikasi yang direplikasi dikarenakan disrupsi yang disengaja.
Misalnya, sebuah aplikasi yang bekerja secara quorum mau memastikan bahwa jumlah replika yang berjalan tidak jatuh ke bawah yang dibutuhkan untuk membentuk sebuah quorum. Contoh lainnya, sebuah front-end web mungkin perlu memastikan bahwa jumlah replika yang melayani trafik tidak pernah turun ke total persentase yang telah ditentukan.
Administrator klaster dan penyedia layanan Kubernetes sebaiknya menggunakan alat-alat yang menghormati PDB dengan cara berkomunikasi dengan Eviction API dari pada menghapus Pod atau Deployment secara langsung. Contohnya adalah perintah kubectl drain
dan skrip pembaruan Kubernets-on-GCE (cluster/gce/upgrade.sh
)
Saat seorang administrator klaster ingin melakukan drain terhadap sebuah node, ia akan menggunakan perintah kubectl drain
. Alat tersebut mencoba untuk "mengusir" semua Pod di node tersebut. Permintaan untuk mengusir Pod tersebut mungkin ditolak untuk sementara, dan alat tersebut akan mencoba ulang permintaannya secara periodik hingga semua Pod dihapus, atau hingga batas waktu yang ditentukan telah dicapai.
Sebua PDB merinci jumlah replika yang dapat ditoleransi oleh sebuah aplikasi, relatif terhadap berapa banyak yang seharusnya dimiliki oleh aplikasi tersebut. Sebagai contoh, sebuah Deployment yang memiliki rincian .spec.replicas :5
diharapkan memiliki 5 Pod pada satu waktu. Jika PDB aplikasi tersebut mengizinkan ada 4 replika pada satu waktu, maka Eviction API akan mengizinkan disrupsi yag disengaja sebanyak satu, tapi tidak mengizinkan dua, pada satu waktu.
Sebuah kelompok Pod yang mewakili aplikasi dispesifikasikan menggunakan sebuah label selector yang sama dengan yang digunakan oleh pengatur aplikasi tersebut (Deployment, StatefulSet, dsb.)
Jumlah Pod yang "diharapkan" dihitung dari .spec.replicas
dari pengendali Pod tersebut. Pengendali dari sebuah Pod dapat ditemukan di spesifikasi .metadata.ownerReferences
objek Pod yang bersangkutan.
PDB tidak dapat mencegah disrupsi yang tidak disengaja, tapi disrupsi ini akan dihitung terhadap bujet PDB.
Pod yang dihapus atau tidak tersetia dikarenakan pembaruan bertahap juga dihitung terhadap bujet PDB, tetapi pengendali (seperti Deployment dan StatefulSet) tidak dibatasi oleh PDB ketika melakukan pembaruan bertahap; Penanganan kerusakan saat pembaruan aplikasi dikonfigurasikan pada spesifikasi pengendali. (Pelajari tentang memperbarui sebuah Deployment.)
Saat sebuah Pod diusir menggunakan eviction API, Pod tersebut akan dihapus secara graceful (lihat terminationGracePeriodSeconds
pada PodSpec.))
Contoh PDB
Kita ambil contoh sebuah klaster dengan 3 node, node-1
hingga node-3
.
Klaster tersebut menjalankan beberapa aplikasi. Salah satu dari aplikasi tersebut awalnya memiliki 3 replika, yang akan kita namai Pod-a
, Pod-b
, dan Pod-c
. Sebuah Pod lain yang tidak bersangkutan dan tidak memiliki PDB, dinamai Pod-x
juga terlihat. Awalnya, Pod-pod tersebut berada pada node-node sebagai berikut:
node-1 | node-2 | node-3 |
---|---|---|
Pod-a available | Pod-b available | Pod-c available |
Pod-x available |
3 Pod Pod-a
hingga Pod-c
adalah bagian dari sebuah Deployment, dan mereka secara kolektif memiliki sebuah PDB yang mengharuskan ada setidaknya 2 dari 3 Pod untuk tersedia sepanjang waktu.
Sebagai contoh, asumsikan administrator klaster ingin me-reboot ke dalam versi kernel baru untuk memperbaiki kesalahan di dalam kernel lama. Administator klaster pertama-tama mencoba untuk melakukan drain terhadap node-1
menggunakan perintah kubectl drain
. Perintah tersebut mencoba untuk mengusir Pod-a
dan Pod-x
. Hal ini langsung berhasil. Kedua Pod tersebut masuk ke dalam kondisi terminating
secara bersamaan. Hal ini mengubah kondisi klaster menjadi sebagai berikut:
node-1 draining | node-2 | node-3 |
---|---|---|
Pod-a terminating | Pod-b available | Pod-c available |
Pod-x terminating |
Deployment tersebut melihat bahwa salah satu Pod berada dalam kondisi terminating
, sehingga Deployment mencoba untuk membuat penggantinya, Pod-d
. Sejak node-1
ditutup (karena perintah kubectl-drain
), Pod-d
masuk ke node lainnya. Sesuatu juga membuat Pod-y
sebagai pengganti Pod-x
(Catatan: untuk sebuah StatefulSet, Pod-a
, akan dinamai dengan Pod-1
, harus diterminasi hingga selesai sebelum penggantinya, yang juga dinamai Pod-1
tetapi memiliki UID yang berbeda, akan dibuat. Selain hal ini, seluruh contoh ini juga berlaku untuk StatefulSet.)
Sekarang, klaster berada pada kondisi berikut:
node-1 draining | node-2 | node-3 |
---|---|---|
Pod-a terminating | Pod-b available | Pod-c available |
Pod-x terminating | Pod-d starting | Pod-y |
Pada satu waktu, Pod-pod yang diusir pun selesai diterminasi, dan kondisi klaster menjadi seperti berikut:
node-1 drained | node-2 | node-3 |
---|---|---|
Pod-b available | Pod-c available | |
Pod-d starting | Pod-y |
Pada titik ini, jika seorang administrator klaster yang tidak sabar mencoba untuk melakukan drain terhadap node-2
atau node-3
, perintah untuk melakukan drain terhadap node tersebut akan terhalang, karena hanya ada 2 Pod yang tersedia, dan PDB-nya membutuhkan setidaknya ada 2 Pod tersedia. Setelah beberapa waktu, Pod-d
menjadi tersedia.
Kondisi klaster menjadi seperti berikut:
node-1 drained | node-2 | node-3 |
---|---|---|
Pod-b available | Pod-c available | |
Pod-d available | Pod-y |
Sekarang, administrator klaster mencoba untuk melakukan drain terhadap node-2
. Perintah drain tersebut akan mencoba mengusir Pod-pod tersebut secara berurutan (tidak bersamaan), misalnya Pod-b
yang pertama dan diikuti dengan Pod-d
. Perintah tersebut akan berhasil mengusir Pod-b
. Tetapi, pada saat ia mencoba untuk mengusir Pod-d
, hal tersebut akan ditolak karena hal tersebut akan mengakibatkan hanya satu Pod yang tersedia untuk Deployment yang bersangkutan.
Deployment tersebut membuat pengganti Pod-b
yang dinamai Pod-e
.
Karena tidak ada sumber daya klaster yang cukup untuk mengalokasikan Pod-e
, proses drain akan kembali terhalang.
Klaster mungkin berada pada kondisi berikut:
node-1 drained | node-2 | node-3 | no node |
---|---|---|---|
Pod-b available | Pod-c available | Pod-e pending | |
Pod-d available | Pod-y |
Pada titik ini, administrator klaster mesti menambah sebuah node untuk klaster agar bisa melanjutkan pembaruan klaster.
Kamu dapat melihat bagaimana frekuensi disrupsi dapat berubah-ubah pada Kubernetes, tergantung pada:
- Berapa banyak replika yang dibutuhkan sebuah aplikasi
- Berapa lama waktu yang dibutuhkan untuk mematikan sebuah Pod secara graceful
- Berapa lama waktu yang dibutuhkan untuk memulai sebuah Pod
- Tipe pengendali
- Kapasitas sumber daya klaster
Memisahkan Peran Pemilik Klaster dan Pemilik Aplikasi
Seringkali akan bermanfaat untuk berpikir Administrator Klaster dan Pemilik Aplikasi sebagai peran yang terpisah dan dengan pengetahuan yang terbatas satu sama lainnya. Pemisahan ini dapat dimengerti dalam beberapa skenario berikut:
- Saat ada banyak tim aplikasi yang berbagi pakai sebuah klaster Kubernetes, dan ada pembagian peran yang spesifik
- Saat alat atau servis pihak ketiga digunakan untuk melakukan otomasi manajemen klaster.
PDB mendukung pemisahan peran ini dengan cara menyediakan antarmuka bagi peran-peran tersebut.
Jika kamu tidak memiliki pemisahan peran seperti ini pada organisasimu, kamu mungkin tidak membutuhkan PDB.
Bagaimana cara melakukan Tindakan Disruptif terhadap Klaster
Jika kamu adalah Administrator Klaster, maka kamu mesti melakukan tindakan disruptif pada setiap node di klastermu, seperti melakukan pembaruan perangkat lunak pada node, berikut beberapa opsinya:
- Menerima downtime pada saat pembaruan node
- Melakukan failover ke replika lengkap klaster lain.
- Tanpa downtime, tetapi mungkin lebih mahal, baik ongkos duplikasi node-node dan tenaga yang dibutuhkan untuk melakukan failover.
- Membuat aplikasi yang toleran terhadap disrupsi, dan gunakan PDB.
- Tanpa downtime.
- Duplikasi sumber daya yang minimal.
- Mengizinkan lebih banyak otomasi administrasi klaster.
- Membuat aplikasi yang toleran terhadap disrupsi agak rumit, tetapi usaha yang dilakukan untuk menoleransi disrupsi yang disengaja kebanyakan beririsan dengan usaha untuk mendukung autoscaling dan menoleransi disrupsi yang tidak disengaja.
Selanjutnya
-
Ikuti langkah-langkah untuk melindungi aplikasimu dengan membuat sebuah PodDisruptionBudget.
-
Pelajari lebih lanjut mengenai melakukan drain terhadap node.
3.4.1.8 - Kontainer Sementara (Ephemeral)
Kubernetes v1.16 [alpha]
Halaman ini memberikan gambaran umum tentang kontainer sementara: satu jenis kontainer khusus yang berjalan sementara pada Pod yang sudah ada untuk melakukan tindakan yang diinisiasi oleh pengguna seperti dalam pemecahan masalah. Kamu menggunakan kontainer sementara untuk memeriksa layanan bukan untuk membangun aplikasi.
Memahami Kontainer Sementara
Pod adalah blok pembangun fundamental dalam aplikasi Kubernetes. Karena Pod diharapkan digunakan hanya sekali dan dapat diganti, sehingga kamu tidak dapat menambahkan kontainer ke dalam Pod setelah Pod tersebut dibuat. Sebaliknya, kamu biasanya menghapus dan mengganti beberapa Pod dengan cara yang terkontrol melalui Deployment.
Namun, kadang-kadang perlu juga untuk memeriksa keadaan Pod yang telah ada, sebagai contoh untuk memecahkan masalah bug yang sulit direproduksi. Dalam kasus ini, kamu dapat menjalankan sebuah kontainer sementara di dalam suatu Pod yang sudah ada untuk memeriksa statusnya dan menjalankannya segala macam perintah.
Apa itu Kontainer Sementara?
Kontainer sementara berbeda dengan kontainer lainnya karena tidak memiliki jaminan sumber daya maupun akan eksekusi, dan mereka tidak akan pernah secara otomatis melakukan restart, jadi mereka tidak sesuai untuk membangun aplikasi. Kontainer sementara dideskripsikan dengan menggunakan ContainerSpec yang sama dengan kontainer biasa, tetapi banyak bagian yang tidak kompatibel dan tidak diperbolehkan untuk kontainer sementara.
- Kontainer sementara mungkin tidak memiliki port, sehingga bagian seperti
port
,livenessProbe
,readinessProbe
tidak diperbolehkan. - Alokasi sumber daya untuk Pod tidak dapat diubah, sehingga pengaturan sumber daya tidak diperbolehkan.
- Untuk daftar lengkap bagian yang diperbolehkan, dapat di lihat referensi dokumentasi Kontainer Sementara.
Kontainer sementara dibuat dengan menggunakan handler khusus
EphemeralContainers dalam API tanpa menambahkannya langsung ke pod.spec
,
sehingga tidak memungkinan untuk menambahkan kontainer sementara dengan
menggunakan kubectl edit
.
Seperti dengan kontainer biasa, kamu tidak dapat mengubah atau menghapus kontainer sementara setelah kamu memasukkannya ke dalam sebuah Pod.
Penggunaan Kontainer Sementara
Kontainer sementara berguna untuk pemecahan masalah secara interaktif pada saat
kubectl exec
tidak mencukupi karena sebuah kontainer telah hancur atau
kontainer image tidak memiliki utilitas untuk debugging.
Khususnya, untuk images_distroless
memungkinkan kamu untuk menyebarkan kontainer image minimal yang mengurangi
surface attack dan paparan bug dan vulnerability. Karena
image distroless tidak mempunyai sebuah shell atau utilitas debugging apa
pun, sehingga sulit untuk memecahkan masalah image distroless dengan
menggunakan kubectl exec
saja.
Saat menggunakan kontainer sementara, akan sangat membantu untuk mengaktifkan process namespace sharing sehingga kamu dapat melihat proses pada kontainer lain.
Contoh
EphemeralContainers
feature
gate untuk
diaktifkan, dan membutuhkan Kubernetes klien dan server versi v1.16 atau
yang lebih baru.
Contoh-contoh pada bagian ini menunjukkan bagaimana kontainer sementara muncul
dalam API. Kamu biasanya dapat menggunakan plugin kubectl
untuk mengatasi
masalah untuk mengotomatiskan langkah-langkah ini.
Kontainer sementara dibuat menggunakan subresource ephemeralcontainers
Pod, yang dapat didemonstrasikan menggunakan kubectl --raw
. Pertama-tama
deskripsikan kontainer sementara untuk ditambahkan dalam daftar
EphemeralContainers
:
{
"apiVersion": "v1",
"kind": "EphemeralContainers",
"metadata": {
"name": "example-pod"
},
"ephemeralContainers": [{
"command": [
"sh"
],
"image": "busybox",
"imagePullPolicy": "IfNotPresent",
"name": "debugger",
"stdin": true,
"tty": true,
"terminationMessagePolicy": "File"
}]
}
Untuk memperbarui kontainer yang sudah berjalan dalam example-pod
:
kubectl replace --raw /api/v1/namespaces/default/pods/example-pod/ephemeralcontainers -f ec.json
Ini akan menampilkan daftar baru dari seluruh kontainer sementara:
{
"kind":"EphemeralContainers",
"apiVersion":"v1",
"metadata":{
"name":"example-pod",
"namespace":"default",
"selfLink":"/api/v1/namespaces/default/pods/example-pod/ephemeralcontainers",
"uid":"a14a6d9b-62f2-4119-9d8e-e2ed6bc3a47c",
"resourceVersion":"15886",
"creationTimestamp":"2019-08-29T06:41:42Z"
},
"ephemeralContainers":[
{
"name":"debugger",
"image":"busybox",
"command":[
"sh"
],
"resources":{
},
"terminationMessagePolicy":"File",
"imagePullPolicy":"IfNotPresent",
"stdin":true,
"tty":true
}
]
}
Kamu dapat melihat kondisi kontainer sementara yang baru dibuat dengan
menggunakan kubectl describe
:
kubectl describe pod example-pod
...
Ephemeral Containers:
debugger:
Container ID: docker://cf81908f149e7e9213d3c3644eda55c72efaff67652a2685c1146f0ce151e80f
Image: busybox
Image ID: docker-pullable://busybox@sha256:9f1003c480699be56815db0f8146ad2e22efea85129b5b5983d0e0fb52d9ab70
Port: <none>
Host Port: <none>
Command:
sh
State: Running
Started: Thu, 29 Aug 2019 06:42:21 +0000
Ready: False
Restart Count: 0
Environment: <none>
Mounts: <none>
...
Kamu dapat mengakses kontainer sementara yang baru menggunakan
kubectl attach
:
kubectl attach -it example-pod -c debugger
Jika proses berbagi namespace diaktifkan, kamu dapat melihat proses dari semua
kontainer dalam Pod tersebut. Misalnya, setelah mengakses, kamu jalankan
ps
di kontainer debugger:
# Jalankan ini pada _shell_ dalam _debugger_ dari kontainer sementara
ps auxww
Hasilnya akan seperti ini:
PID USER TIME COMMAND
1 root 0:00 /pause
6 root 0:00 nginx: master process nginx -g daemon off;
11 101 0:00 nginx: worker process
12 101 0:00 nginx: worker process
13 101 0:00 nginx: worker process
14 101 0:00 nginx: worker process
15 101 0:00 nginx: worker process
16 101 0:00 nginx: worker process
17 101 0:00 nginx: worker process
18 101 0:00 nginx: worker process
19 root 0:00 /pause
24 root 0:00 sh
29 root 0:00 ps auxww
3.4.2 - Controllers
3.4.2.1 - ReplicaSet
Tujuan dari ReplicaSet adalah untuk memelihara himpunan stabil dari replika Pod yang sedang berjalan pada satu waktu tertentu. Maka dari itu, ReplicaSet seringkali digunakan untuk menjamin ketersediaan dari beberapa Pod identik dalam jumlah tertentu.
Cara kerja ReplicaSet
Sebuah ReplicaSet didefinisikan dengan beberapa field termasuk selektor yang menentukan bagaimana mengidentifikasi Pod yang dapat diakuisisi, jumlah replika yang mengindikasi berapa jumlah Pod yang harus dikelola, dan sebuah templat pod yang menentukan data dari berbagai Pod baru yang harus dibuat untuk memenuhi kriteria jumlah replika. Sebuah ReplicaSet selanjutnya akan memenuhi tujuannya dengan membuat dan menghapus Pod sesuai dengan kebutuhan untuk mencapai jumlah yang diinginkan. Ketika ReplicaSet butuh untuk membuat Pod baru, templat Pod akan digunakan.
Tautan dari sebuah ReplicaSet terhadap Pod yang dimiliki adalah melalui field metadata.ownerReferences pada Pod, yang menentukan sumber daya yang dimiliki oleh objek saat ini. Semua Pod yang diakuisisi oleh sebuah ReplicaSet masing-masing memiliki informasi yang mengidentifikasi ReplicaSet dalam field ownerReferences. Melalui tautan ini ReplicaSet dapat mengetahui keadaan dari Pod yang sedang dikelola dan melakukan perencanaan yang sesuai.
Sebuah ReplicaSet mengidentifikasi Pod baru untuk diakuisisi menggunakan selektornya. Jika terdapat sebuah Pod yang tidak memiliki OwnerReference atau OwnerReference yang dimiliki bukanlah sebuah Controller dan sesuai dengan selektor dari ReplicaSet, maka Pod akan langsung diakuisisi oleh ReplicaSet tersebut.
Kapan menggunakan ReplicaSet
Sebuah ReplicaSet memastikan replika-replika pod dalam jumlah yang ditentukan berjalan pada satu waktu tertentu. Namun demikian, sebuah Deployment adalah konsep dengan tingkatan yang lebih tinggi yang mengatur ReplicaSet dan mengubah Pod secara deklaratif serta berbagai fitur bermanfaat lainnya. Maka dari itu, kami merekomendasikan untuk menggunakan Deployment alih-alih menggunakan ReplicaSet secara langsung, kecuali jika kamu membutuhkan orkestrasi pembaruan yang khusus atau tidak membutuhkan pembaruan sama sekali.
Hal ini berarti kamu boleh jadi tidak akan membutuhkan manipulasi objek ReplicaSet: Gunakan Deployment dan definisikan aplikasi kamu pada bagian spec.
Contoh
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
# modify replicas according to your case
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
Menyimpan manifest ini dalam frontend.yaml
dan mengirimkannya ke klaster Kubernetes akan membuat ReplicaSet yang telah didefinisikan beserta dengan Pod yang dikelola.
kubectl apply -f https://kubernetes.io/examples/controllers/frontend.yaml
Selanjutnya kamu bisa mendapatkan ReplicaSet yang sedang di-deploy:
kubectl get rs
Dan melihat frontend yang telah dibuat:
NAME DESIRED CURRENT READY AGE
frontend 3 3 3 6s
Kamu juga dapat memeriksa kondisi dari ReplicaSet:
kubectl describe rs/frontend
Dan kamu akan melihat keluaran yang serupa dengan:
Name: frontend
Namespace: default
Selector: tier=frontend,tier in (frontend)
Labels: app=guestbook
tier=frontend
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=guestbook
tier=frontend
Containers:
php-redis:
Image: gcr.io/google_samples/gb-frontend:v3
Port: 80/TCP
Requests:
cpu: 100m
memory: 100Mi
Environment:
GET_HOSTS_FROM: dns
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-qhloh
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-dnjpy
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-9si5l
Terakhir, kamu dapat memeriksa Pod yang dibawa:
kubectl get Pods
Kamu akan melihat informasi Pod yang serupa dengan:
NAME READY STATUS RESTARTS AGE
frontend-9si5l 1/1 Running 0 1m
frontend-dnjpy 1/1 Running 0 1m
frontend-qhloh 1/1 Running 0 1m
Kamu juga dapat memastikan bahwa referensi pemilik dari pod-pod ini telah disesuaikan terhadap ReplicaSet frontend. Untuk melakukannya, yaml dari Pod yang sedang berjalan bisa didapatkan dengan:
kubectl get pods frontend-9si5l -o yaml
Keluarannya akan terlihat serupa dengan contoh berikut ini, dengan informasi ReplicaSet frontend yang ditentukan pada field ownerReferences pada bagian metadata:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: 2019-01-31T17:20:41Z
generateName: frontend-
labels:
tier: frontend
name: frontend-9si5l
namespace: default
ownerReferences:
- apiVersion: extensions/v1beta1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: frontend
uid: 892a2330-257c-11e9-aecd-025000000001
...
Akuisisi Pod Non-Templat
Walaupun kamu bisa membuat Pod biasa tanpa masalah, sangat direkomendasikan untuk memastikan Pod tersebut tidak memiliki label yang sama dengan selektor dari salah satu ReplicaSet yang kamu miliki. Hal in disebabkan sebuah ReplicaSet tidak dibatasi untuk memilki Pod sesuai dengan templatnya -- ReplicaSet dapat mengakuisisi Pod lain dengan cara yang telah dijelaskan pada bagian sebelumnya.
Mengambil contoh ReplicaSet frontend sebelumnya, dan Pod yang ditentukan pada manifest berikut:
apiVersion: v1
kind: Pod
metadata:
name: pod1
labels:
tier: frontend
spec:
containers:
- name: hello1
image: gcr.io/google-samples/hello-app:2.0
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
labels:
tier: frontend
spec:
containers:
- name: hello2
image: gcr.io/google-samples/hello-app:1.0
Karena Pod tersebut tidak memiliki Controller (atau objek lain) sebagai referensi pemilik yang sesuai dengan selektor dari ReplicaSet frontend, Pod tersebut akan langsung diakuisisi oleh ReplicaSet.
Misalkan kamu membuat Pod tersebut setelah ReplicaSet frontend telah di-deploy dan telah mengkonfigurasi replika Pod awal untuk memenuhi kebutuhan jumlah replika:
kubectl apply -f https://kubernetes.io/examples/pods/pod-rs.yaml
Pod baru akan diakuisisi oleh ReplicaSet, dan setelah itu langsung diterminasi ketika ReplicaSet melebihi jumlah yang diinginkan.
Memperoleh Pod:
kubectl get Pods
Keluaran menunjukkan bahwa Pod baru dalam keaadan telah diterminasi, atau sedang dalam proses terminasi:
NAME READY STATUS RESTARTS AGE
frontend-9si5l 1/1 Running 0 1m
frontend-dnjpy 1/1 Running 0 1m
frontend-qhloh 1/1 Running 0 1m
pod2 0/1 Terminating 0 4s
Jika kamu membuat Pod terlebih dahulu:
kubectl apply -f https://kubernetes.io/examples/pods/pod-rs.yaml
Dan selanjutnya membuat ReplicaSet maka:
kubectl apply -f https://kubernetes.io/examples/controllers/frontend.yaml
Kamu akan melihat bahwa ReplicaSet telah mengakuisisi Pod dan hanya membuat Pod yang baru sesuai dengan spec
yang ditentukan hingga jumlah dari Pod yang baru dan yang orisinil sesuai dengan jumlah yang diinginkan. Dengan memperoleh Pod:
kubectl get Pods
Akan diperlihatkan pada keluarannya:
NAME READY STATUS RESTARTS AGE
frontend-pxj4r 1/1 Running 0 5s
pod1 1/1 Running 0 13s
pod2 1/1 Running 0 13s
Dengan cara ini, sebuah ReplicaSet dapat memiliki himpunan berbagai Pod yang tidak homogen.
Menulis manifest ReplicaSet
Seperti objek API Kubernetes lainnya, sebuah ReplicaSet membutuhkan field apiVersion
, kind
, dan metadata
. Untuk ReplicaSet, nilai dari kind
yang memungkinkan hanyalah ReplicaSet. Pada Kubernetes 1.9 versi API apps/v1
pada kind
ReplicaSet adalah versi saat ini dan diaktifkan secara default. Versi API apps/v1beta2
telah dideprekasi. Lihat baris-baris awal pada contoh frontend.yaml
untuk petunjuk.
Sebuah ReplicaSet juga membutuhkan bagian .spec
.
Templat Pod
.spec.template
adalah sebuah templat pod yang juga dibutuhkan untuk mempunyai label. Pada contoh frontend.yaml
kita memiliki satu label: tier: frontend
.
Hati-hati agar tidak tumpang tindih dengan selektor dari controller lain, agar mereka tidak mencoba untuk mengadopsi Pod ini.
Untuk field restart policy dari templat, .spec.template.spec.restartPolicy
, nilai yang diperbolehkan hanyalah Always
, yang merupakan nilai default.
Selektor Pod
Field .spec.selector
adalah sebuah selektor labe. Seperti yang telah dibahas sebelumnya, field ini adalah label yang digunakan untuk mengidentifikasi Pod yang memungkinkan untuk diakuisisi. Pada contoh frontend.yaml
, selektornya adalah:
matchLabels:
tier: frontend
Pada ReplicaSet, .spec.template.metadata.labels
harus memiliki nilai yang sama dengan spec.selector
, atau akan ditolak oleh API.
.spec.selector
yang sama tetapi memiliki nilai yang berbeda pada field .spec.template.metadata.labels
dan .spec.template.spec
, setiap ReplicaSet akan mengabaikan Pod yang dibuat oleh ReplicaSet lain.
Replika
Kamu dapat menentukan jumlah Pod yang seharusnya berjalan secara konkuren dengan mengatur nilai dari .spec.replicas
. ReplicaSet akan membuat/menghapus Pod-nya hingga jumlahnya sesuai dengan field ini.
Jika nilai .spec.replicas
tidak ditentukan maka akan diatur ke nilai default 1.
Menggunakan ReplicaSet
Menghapus ReplicaSet dan Pod-nya
Untuk menghapus sebuah ReplicaSet beserta dengan Pod-nya, gunakan kubectl delete
. Garbage collector secara otomatis akan menghapus semua Pod dependen secara default.
Ketika menggunakan REST API atau library client-go
, kamu harus mengatur nilai propagationPolicy
menjadi Background
atau Foreground
pada opsi -d.
Sebagai contoh:
kubectl proxy --port=8080
curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \
> -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
> -H "Content-Type: application/json"
Menghapus hanya ReplicaSet
Kamu dapat menghapus ReplicaSet tanpa memengaruhi Pod-nya menggunakan kubectl delete
dengan menggunakan opsi --cascade=false
.
Ketika menggunakan REST API atau library client-go
, kamu harus mengatur nilai propagationPolicy
menjadi Orphan
.
Sebagai contoh:
kubectl proxy --port=8080
curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \
> -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
> -H "Content-Type: application/json"
Ketika ReplicaSet yang asli telah dihapus, kamu dapat membuat ReplicaSet baru untuk menggantikannya. Selama field .spec.selector
yang lama dan baru memilki nilai yang sama, maka ReplicaSet baru akan mengadopsi Pod lama namun tidak serta merta membuat Pod yang sudah ada sama dan sesuai dengan templat Pod yang baru.
Untuk memperbarui Pod dengan spec baru dapat menggunakan Deployment karena ReplicaSet tidak mendukung pembaruan secara langsung.
Mengisolasi Pod dari ReplicaSet
Kamu dapat menghapus Pod dari ReplicaSet dengan mengubah nilai labelnya. Cara ini dapat digunakan untuk menghapus Pod dari servis untuk keperluan debugging, data recovery, dan lainnya. Pod yang dihapus dengan cara ini akan digantikan seecara otomatis (dengan asumsi jumlah replika juga tidak berubah).
Mengatur jumlah Pod pada ReplicaSet
Jumlah Pod pada ReplicaSet dapat diatur dengan mengubah nilai dari field .spec.replicas
. Pengatur ReplicaSet akan memastikan Pod dengan jumlah yang telah ditentukan dan dengan nilai selektor yang sama sedang dalam keadaan berjalan.
Pengaturan jumlah Pod pada ReplicaSet menggunakan Horizontal Pod Autoscaler
Pengaturan jumlah Pod pada ReplicaSet juga dapat dilakukan mengunakan Horizontal Pod Autoscalers (HPA). Berikut adalah contoh HPA terhadap ReplicaSet yang telah dibuat pada contoh sebelumnya.
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: frontend-scaler
spec:
scaleTargetRef:
kind: ReplicaSet
name: frontend
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 50
Menyimpan manifest ini dalam hpa-rs.yaml
dan mengirimkannya ke klaster Kubernetes akan membuat HPA tersebut yang akan mengatur jumlah Pod pada ReplicaSet yang telah didefinisikan bergantung terhadap penggunaan CPU dari Pod yang direplikasi.
kubectl apply -f https://k8s.io/examples/controllers/hpa-rs.yaml
Opsi lainnya adalah dengan menggunakan perintah kubectl autoscale
untuk tujuan yang sama.
kubectl autoscale rs frontend --max=10
Alternatif selain ReplicaSet
Deployment (direkomendasikan)
Deployment
adalah sebuah objek yang bisa memiliki ReplicaSet dan memperbarui ReplicaSet dan Pod-nya melalui rolling update deklaratif dan server-side.
Walaupun ReplicaSet dapat digunakan secara independen, seringkali ReplicaSet digunakan oleh Deployments sebagai mekanisme untuk mengorkestrasi pembuatan, penghapusan dan pembaruan Pod. Ketika kamu menggunakan Deployments kamu tidak perlu khawatir akan pengaturan dari ReplicaSet yang dibuat. Deployments memiliki dan mengatur ReplicaSet-nya sendiri.
Maka dari itu penggunaan Deployments direkomendasikan jika kamu menginginkan ReplicaSet.
Pod sederhana
Tidak seperti pada kasus ketika pengguna secara langsung membuat Pod, ReplicaSet akan menggantikan Pod yang dihapus atau diterminasi dengan alasan apapun, seperti pada kasus dimana terjadi kegagalan node atau pemeliharaan node yang disruptif, seperti pada kasus upgrade kernel. Karena alasan ini kami merekomendasikan kamu untuk menggunakan ReplicaSet walaupun jika aplikasimu membutuhkan hanya satu Pod. Hal ini mirip dengan pengawas proses, hanya saja pada kasus ini mengawasi banyak Pod pada berbagai node alih-alih berbagai proses individu pada sebuah node. ReplicaSet mendelegasikan proses pengulangan kembali dari kontainer lokal kepada agen yang terdapat di node (sebagai contoh, Kubelet atau Docker).
Job
Gunakan Job
alih-alih ReplicaSet untuk Pod yang diharapkan untuk diterminasi secara sendirinya.
DaemonSet
Gunakan DaemonSet
alih-alih ReplicaSet untuk Pod yang menyediakan fungsi pada level mesin, seperti monitoring mesin atau logging mesin. Pod ini memiliki waktu hidup yang bergantung terhadap waktu hidup mesin: Pod perlu untuk berjalan pada mesin sebelum Pod lain dijalankan, dan aman untuk diterminasi ketika mesin siap untuk di-reboot atau dimatikan.
ReplicationController
ReplicaSet adalah suksesor dari ReplicationControllers. Keduanya memenuhi tujuan yang sama dan memiliki perilaku yang serupa, kecuali bahwa ReplicationController tidak mendukung kebutuhan selektor set-based seperti yang dijelaskan pada panduan penggunaan label. Pada kasus tersebut, ReplicaSet lebih direkomendasikan dibandingkan ReplicationController.
3.4.2.2 - ReplicationController
Deployment
yang mengonfigurasi ReplicaSet
sekarang menjadi cara yang direkomendasikan untuk melakukan replikasi.
Sebuah ReplicationController memastikan bahwa terdapat sejumlah Pod yang sedang berjalan dalam suatu waktu tertentu. Dengan kata lain, ReplicationController memastikan bahwa sebuah Pod atau sebuah kumpulan Pod yang homogen selalu berjalan dan tersedia.
Bagaimana ReplicationController Bekerja
Jika terdapat terlalu banyak Pod, maka ReplicationController akan membatasi dan mematikan Pod-Pod yang berlebih. Jika terdapat terlalu sedikit, maka ReplicationController akan memulai dan menjalankan Pod-Pod baru lainnya. Tidak seperti Pod yang dibuat secara manual, Pod-Pod yang diatur oleh sebuah ReplicationController akan secara otomatis diganti jika mereka gagal, dihapus, ataupun dimatikan. Sebagai contoh, Pod-Pod yang kamu miliki akan dibuat ulang dalam sebuah Node setelah terjadi proses pemeliharaan seperti pembaruan kernel. Untuk alasan ini, maka kamu sebaiknya memiliki sebuah ReplicationController bahkan ketika aplikasimu hanya membutuhkan satu buah Pod saja. Sebuah ReplicationController memiliki kemiripan dengan sebuah pengawas proses, tetapi alih-alih mengawasi sebuah proses individu pada sebuah Node, ReplicationController banyak Pod yang terdapat pada beberapa Node.
ReplicationController seringkali disingkat sebagai "rc" dalam diskusi, dan sebagai shortcut dalam perintah kubectl.
Sebuah contoh sederhana adalah membuat sebuah objek ReplicationController untuk menjalankan sebuah instance Pod secara berkelanjutan. Contoh pemakaian lainnya adalah untuk menjalankan beberapa replika identik dari sebuah servis yang direplikasi, seperti peladen web.
Menjalankan Sebuah Contoh ReplicationController
Contoh ReplicationController ini mengonfigurasi tiga salinan dari peladen web nginx.
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Jalankan contoh di atas dengan mengunduh berkas contoh dan menjalankan perintah ini:
kubectl apply -f https://k8s.io/examples/controllers/replication.yaml
replicationcontroller/nginx created
Periksa status dari ReplicationController menggunakan perintah ini:
kubectl describe replicationcontrollers/nginx
Name: nginx
Namespace: default
Selector: app=nginx
Labels: app=nginx
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 0 Running / 3 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- ---- ------ -------
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-qrm3m
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-3ntk0
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-4ok8v
Tiga Pod telah dibuat namun belum ada yang berjalan, kemungkinan karena image yang sedang di-pull. Beberapa waktu kemudian, perintah yang sama akan menunjukkan:
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Untuk melihat semua Pod yang dibuat oleh ReplicationController dalam bentuk yang lebih mudah dibaca mesin, kamu dapat menggunakan perintah seperti ini:
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods
nginx-3ntk0 nginx-4ok8v nginx-qrm3m
Pada perintah di atas, selektor yang dimaksud adalah selektor yang sama dengan yang terdapat pada ReplicationController (yang dapat dilihat pada keluaran kubectl describe
), dan dalam bentuk yang berbeda dengan yang terdapat pada replication.yaml
. Opsi --output=jsonpath
menentukan perintah untuh mendapatkan hanya nama dari setiap Pod yang ada pada daftar hasil.
Menulis Spesifikasi ReplicationController
Seperti semua konfigurasi Kubernetes lainnya, sebuah ReplicationController membutuhkan field apiVersion
, kind
, dan metadata
.
Untuk informasi umum mengenai berkas konfigurasi, kamu dapat melihat pengaturan objek.
Sebuah ReplicationController juga membutuhkan bagian .spec
.
Templat Pod
.spec.template
adalah satu-satunya field yang diwajibkan pada .spec
.
.spec.template
adalah sebuah templat Pod. Ia memiliki skema yang sama persis dengan sebuah Pod, namun dapat berbentuk nested dan tidak memiliki field apiVersion
ataupun kind
.
Selain field-field yang diwajibkan untuk sebuah Pod, templat Pod pada ReplicationController harus menentukan label dan kebijakan pengulangan kembali yang tepat. Untuk label, pastikan untuk tidak tumpang tindih dengan kontroler lain. Lihat selektor pod.
Nilai yang diperbolehkan untuk .spec.template.spec.restartPolicy
hanyalah Always
, yaitu nilai bawaan jika tidak ditentukan.
Untuk pengulangan kembali dari sebuah kontainer lokal, ReplicationController mendelegasikannya ke agen pada Node, contohnya Kubelet atau Docker.
Label pada ReplicationController
ReplicationController itu sendiri dapat memiliki label (.metadata.labels
). Biasanya, kamu akan mengaturnya untuk memiliki nilai yang sama dengan .spec.template.metadata.labels
; jika .metadata.labels
tidak ditentukan maka akan menggunakan nilai bawaan yaitu .spec.template.metadata.labels
. Namun begitu, kedua label ini diperbolehkan untuk memiliki nilai yang berbeda, dan .metadata.labels
tidak akan memengaruhi perilaku dari ReplicationController.
Selektor Pod
Field .spec.selector
adalah sebuah selektor label. Sebuah ReplicationController mengatur semua Pod dengan label yang sesuai dengan nilai selektor tersebut. Ia tidak membedakan antara Pod yang ia buat atau hapus atau Pod yang dibuat atau dihapus oleh orang atau proses lain. Hal ini memungkinkan ReplicationController untuk digantikan tanpa memengaruhi Pod-Pod yang sedang berjalan.
Jika ditentukan, .spec.template.metadata.labels
harus memiliki nilai yang sama dengan .spec.selector
, atau akan ditolak oleh API. Jika .spec.selector
tidak ditentukan, maka akan menggunakan nilai bawaan yaitu .spec.template.metadata.labels
.
Selain itu, kamu juga sebaiknya tidak membuat Pod dengan label yang cocok dengan selektor ini, baik secara langsung, dengan menggunakan ReplicationController lain, ataupun menggunakan kontroler lain seperti Job. Jika kamu melakukannya, ReplicationController akan menganggap bahwa ia telah membuat Pod-Pod lainnya. Kubernetes tidak akan menghentikan kamu untuk melakukan aksi ini.
Jika kamu pada akhirnya memiliki beberapa kontroler dengan selektor-selektor yang tumpang tindih, kamu harus mengatur penghapusannya sendiri (lihat di bawah).
Beberapa Replika
Kamu dapat menentukan jumlah Pod yang seharusnya berjalan secara bersamaan dengan mengatur nilai .spec.replicas
dengan jumlah Pod yang kamu inginkan untuk berjalan secara bersamaan. Jumlah yang berjalan dalam satu satuan waktu dapat lebih tinggi ataupun lebih rendah, seperti jika replika-replika tersebut melewati proses penambahan atau pengurangan, atau jika sebuah Pod melalui proses graceful shutdown, dan penggantinya telah dijalankan terlebih dahulu.
Jika kamu tidak menentukan nilai dari .spec.replicas
, maka akan digunakan nilai bawaan 1.
Bekerja dengan ReplicationController
Menghapus Sebuah ReplicationController dan Pod-nya
Untuk menghapus sebuah ReplicationController dan Pod-Pod yang berhubungan dengannya, gunakan perintah kubectl delete
. Kubectl akan mengatur ReplicationController ke nol dan menunggunya untuk menghapus setiap Pod sebelum menghapus ReplicationController itu sendiri. Jika perintah kubectl ini terhenti, maka dapat diulang kembali.
Ketika menggunakan REST API atau library klien go, maka kamu perlu melakukan langkah-langkahnya secara eksplisit (mengatur replika-replika ke 0, menunggu penghapusan Pod, dan barulah menghapus ReplicationController).
Menghapus Hanya ReplicationController
Kamu dapat menghapus ReplicationController tanpa memengaruhi Pod-Pod yang berhubungan dengannya.
Dengan menggunakan kubectl, tentukan opsi --cascade=false
ke kubectl delete
.
Ketika menggunakan REST API atau library klien go, cukup hapus objek ReplicationController.
Ketika ReplicationController yang asli telah dihapus, kamu dapat membuat ReplicationController yang baru sebagai penggantinya. Selama .spec.selector
yang lama dan baru memiliki nilai yang sama, maka ReplicationController baru akan mengadopsi Pod-Pod yang lama.
Walaupun begitu, ia tidak akan melakukan usaha apapun untuk membuat Pod-Pod yang telah ada sebelumnya untuk sesuai dengan templat Pod yang baru dan berbeda.
Untuk memperbarui Pod-Pod ke spesifikasi yang baru dengan cara yang terkontrol, gunakan pembaruan bergulir.
Mengisolasi Pod dari ReplicationController
Pod-Pod dapat dihapus dari kumpulan target sebuah ReplicationController dengan mengganti nilai dari labelnya. Teknik ini dapat digunakan untuk mencopot Pod-Pod dari servis untuk keperluan pengawakutuan (debugging), pemulihan data, dan lainnya. Pod-Pod yang dicopot dengan cara ini dapat digantikan secara otomatis (dengan asumsi bahwa jumlah replika juga tidak berubah).
Pola penggunaan umum
Penjadwalan ulang
Seperti yang telah disebutkan sebelumnya, baik kamu memiliki hanya 1 Pod untuk tetap dijalankan, ataupun 1000, ReplicationController akan memastikan tersedianya jumlah Pod yang telat ditentukan, bahkan ketika terjadi kegagalan Node atau terminasi Pod (sebagai contoh karena adanya tindakan dari agen kontrol lain).
Penskalaan
ReplicationController memudahkan penskalaan jumlah replika, baik meningkatkan ataupun mengurangi, secara manual ataupun dengan agen kontrol penskalaan otomatis, dengan hanya mengubah nilai dari field replicas
.
Pembaruan bergulir
ReplicationController didesain untuk memfasilitasi pembaruan bergulir untuk sebuah servis dengan mengganti Pod-Pod satu per satu.
Seperti yang telah dijelaskan di #1353, pendekatan yang direkomendasikan adalah dengan membuat ReplicationController baru dengan 1 replika, skala kontroler yang baru (+1) atau yang lama (-1) satu per satu, dan kemudian hapus kontroler lama setelah menyentuh angka 0 replika. Hal ini memungkinkan pembaruan dilakukan dengan dapat diprediksi terlepas dari adanya kegagalan yang tak terduga.
Idealnya, kontroler pembaruan bergulir akan memperhitungkan kesiapan dari aplikasi, dan memastikan cukupnya jumlah Pod yang secara produktif meladen kapanpun.
Dua ReplicationController diharuskan untuk memiliki setidaknya satu label yang berbeda, seperti tag image dari kontainer utama dari Pod, karena pembaruan bergulir biasanya dilakukan karena adanya pembaruan image.
Pembaruan bergulir diimplementasikan pada perkakas klien kubectl rolling-update
. Lihat kubectl rolling-update
task untuk contoh-contoh yang lebih konkrit.
Operasi rilis majemuk
Selain menjalankan beberapa rilis dari sebuah aplikasi ketika proses pembaruan bergulir sedang berjalan, adalah hal yang awam untuk menjalankan beberapa rilis untuk suatu periode waktu tertentu, atau bahkan secara kontinu, menggunakan operasi rilis majemuk. Operasi-operasi ini akan dibedakan menggunakan label.
Sebagai contoh, sebuah servis dapat menyasar semua Pod dengan tier in (frontend), environment in (prod)
. Anggap kamu memiliki 10 Pod tiruan yang membangun tier ini tetapi kamu ingin bisa menggunakan 'canary' terhadap versi baru dari komponen ini. Kamu dapat mengatur sebuah ReplicationController dengan nilai replicas
9 untuk replika-replikanya, dengan label tier=frontend, environment=prod, track=stable
, dan ReplicationController lainnya dengan nilai replicas
1 untuk canary, dengan label tier=frontend, environment=prod, track=canary
. Sekarang servis sudah mencakup baik canary maupun Pod-Pod yang bukan canary. Kamu juga dapat mencoba-coba ReplicationController secara terpisah untuk melakukan pengujian, mengamati hasilnya, dan lainnya.
Menggunakan ReplicationController dengan Service
Beberapa ReplicationController dapat berada di belakang sebuah Service, sedemikian sehingga, sebagai contoh, sebagian traffic dapat ditujukan ke versi lama, dan sebagian lainnya ke versi yang baru.
Sebuah ReplicationController tidak akan berhenti dengan sendirinya, namun ia tidak diekspektasikan untuk berjalan selama Service-Service yang ada. Service dapat terdiri dari berbagai Pod yang dikontrol beberapa ReplicationController, dan terdapat kemungkinan bahwa beberapa ReplicationController untuk dibuat dan dimatikan dalam jangka waktu hidup Service (contohnya adalah untuk melakukan pembaruan Pod-Pod yang menjalankan Service). Baik Service itu sendiri dan kliennya harus tetap dalam keadaan tidak mempunyai pengetahuan terhadap ReplicationController yang memelihara Pod-Pod dari Service tersebut.
Menulis program untuk Replikasi
Pod-Pod yang dibuat oleh ReplicationController ditujukan untuk dapat sepadan dan memiliki semantik yang identik, walaupun konfigurasi mereka dapat berbeda seiring keberjalanan waktunya. Ini adalah contoh yang cocok untuk peladen stateless, namun ReplicationController juga dapat digunakan untuk memelihara ketersediaan dari aplikasi-aplikasi yang master-elected, sharded, worker-pool. Aplikasi-aplikasi seperti itu sebaiknya menggunakan mekanisme penetapan kerja yang dinamis, seperti antrian kerja RabbitMQ, berlainan dengan pengubahan statis/satu kali dari konfigurasi setiap Pod, yang dipandang sebagai sebuah anti-pattern. Pengubahan apapun yang dilakukan terhadap Pod, seperti auto-sizing vertikal dari sumber daya (misalnya cpu atau memori), sebaiknya dilakukan oleh proses kontroller luring lainnya, dan bukan oleh ReplicationController itu sendiri.
Tanggung Jawab ReplicationController
ReplicationController hanya memastikan ketersediaan dari sejumlah Pod yang cocok dengan selektor label dan berjalan dengan baik. Saat ini, hanya Pod yang diterminasi yang dijadikan pengecualian dari penghitungan. Kedepannya, kesiapan dan informasi yang ada lainnya dari sistem dapat menjadi pertimbangan, kami dapat meningkatkan kontrol terhadap kebijakan penggantian, dan kami berencana untuk menginformasikan kejadian (event) yang dapat digunakan klien eksternal untuk implementasi penggantian yang sesuai dan/atau kebijakan pengurangan.
ReplicationController akan selalu dibatasi terhadap tanggung jawab spesifik ini. Ia tidak akan melakukan probe kesiapan atau keaktifan. Daripada melakukan auto-scaling, ia ditujukan untuk dikontrol oleh auto-scaler eksternal (seperti yang didiskusikan pada #492), yang akan mengganti field replicas
. Kami tidak akan menambahkan kebijakan penjadwalan (contohnya spreading) untuk ReplicationController. Ia juga tidak seharusnya melakukan verifikasi terhadap Pod-Pod yang sedang dikontrol yang cocok dengan spesifikasi templat saat ini, karena hal itu dapat menghambat auto-sizing dan proses otomatis lainnya. Demikian pula batas waktu penyelesaian, pengurutan dependencies, ekspansi konfigurasi, dan fitur-fitur lain yang seharusnya berada di komponen lain. Kami juga bahkan berencana untuk mengeluarkan mekanisme pembuatan Pod secara serentak (#170).
ReplicationController ditujukan untuk menjadi primitif komponen yang dapat dibangun untuk berbagai kebutuhan. Kami menargetkan API dengan tingkatan yang lebih tinggi dan/atau perkakas-perkakas untuk dibangun di atasnya dan primitif tambahan lainnya untuk kenyamanan pengguna kedepannya. Operasi-operasi makro yang sudah didukung oleh kubectl (run, scale, rolling-update) adalah contoh proof-of-concept dari konsep ini. Sebagai contohnya, kita dapat menganggap sesuatu seperti Asgard yang mengatur beberapa ReplicationController, auto-scaler, servis, kebijakan penjadwalan, canary, dan yang lainnya.
Objek API
ReplicationController adalah sebuah sumber daya top-level pada REST API Kubernetes. Detil dari objek API dapat ditemukan di: objek API ReplicationController.
Alternatif untuk ReplicationController
ReplicaSet
ReplicaSet
adalah kelanjutan dari ReplicationController yang mendukung selektor selektor label set-based yang baru. Umumnya digunakan oleh Deployment
sebagai mekanisme untuk mengorkestrasi pembuatan, penghapusan, dan pembaruan Pod.
Perhatikan bahwa kami merekomendasikan untuk menggunakan Deployment sebagai ganti dari menggunakan ReplicaSet secara langsung, kecuali jika kamu membutuhkan orkestrasi pembaruan khusus atau tidak membutuhkan pembaruan sama sekali.
Deployment (Direkomendasikan)
Deployment
adalah objek API tingkat tinggi yang memperbarui ReplicaSet dan Pod-Pod di bawahnya yang mirip dengan cara kerja kubectl rolling-update
. Deployment direkomendasikan jika kamu menginginkan fungsionalitas dari pembaruan bergulir ini, karena tidak seperti kubectl rolling-update
, Deployment memiliki sifat deklaratif, server-side, dan memiliki beberapa fitur tambahan lainnya.
Pod sederhana
Tidak seperti pada kasus ketika pengguna secara langsung membuat Pod, ReplicationController menggantikan Pod-Pod yang dihapus atau dimatikan untuk alasan apapun, seperti pada kasus kegagalan Node atau pemeliharaan Node yang disruptif, seperti pembaruan kernel. Untuk alasan ini, kami merekomendasikan kamu untuk menggunakan ReplicationController bahkan ketika aplikasimu hanya membutuhkan satu Pod saja. Anggap hal ini mirip dengan pengawas proses, hanya pada kasus ini mengawasi banyak Pod yang terdapat pada berbagai Node dan bukan proses-proses tunggal pada satu Node. ReplicationController mendelegasikan pengulangan kontainer lokal ke agen yang terdapat dalam Node (contohnya Kubelet atau Docker).
Job
Gunakan Job
sebagai ganti ReplicationController untuk Pod-Pod yang diharapkan diterminasi dengan sendirinya (seperti batch jobs).
DaemonSet
Gunakan DaemonSet
sebagai ganti ReplicationController untuk Pod-Pod yang menyediakan fungsi pada level mesin, seperti pengamatan mesin atau pencatatan mesin. Pod-Pod ini memiliki waktu hidup yang bergantung dengan waktu hidup mesin: Pod butuh untuk dijalankan di mesin sebelum Pod-Pod lainnya dimulai, dan aman untuk diterminasi ketika mesin sudah siap untuk dinyalakan ulang atau dimatikan.
Informasi lanjutan
3.4.2.3 - Deployment
Deployment menyediakan pembaruan Pods dan ReplicaSets secara deklaratif.
Kamu mendeskripsikan sebuah state yang diinginkan dalam Deployment, kemudian Deployment Pengontrol mengubah state sekarang menjadi seperti pada deskripsi secara bertahap. Kamu dapat mendefinisikan Deployment untuk membuat ReplicaSets baru atau untuk menghapus Deployment yang sudah ada dan mengadopsi semua resourcenya untuk Deployment baru.
Penggunaan
Berikut adalah penggunaan yang umum pada Deployment:
- Membuat Deployment untuk merilis ReplicaSet. ReplicaSet membuat Pod di belakang layar. Cek status rilis untuk tahu proses rilis sukses atau tidak.
- Mendeklarasikan state baru dari Pods dengan membarui PodTemplateSpec milik Deployment. ReplicaSet baru akan dibuat dan Deployment mengatur perpindahan Pod secara teratur dari ReplicaSet lama ke ReplicaSet baru. Tiap ReplicaSet baru akan mengganti revisi Deployment.
- Mengembalikan ke revisi Deployment sebelumnya jika state Deployment sekarang tidak stabil. Tiap pengembalian mengganti revisi Deployment.
- Memperbesar Deployment untuk memfasilitasi beban yang lebih.
- Menjeda Deployment untuk menerapkan perbaikan pada PodTemplateSpec-nya, lalu melanjutkan untuk memulai rilis baru.
- Memakai status Deployment sebagai indikator ketika rilis tersendat.
- Membersihkan ReplicaSet lama yang sudah tidak terpakai.
Membuat Deployment
Berikut adalah contoh Deployment. Dia membuat ReplicaSet untuk membangkitkan tiga Pod nginx
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Dalam contoh ini:
-
Deployment baru akan dibuat dengan nama
nginx-deployment
, tertulis pada kolom.metadata.name
. -
Deployment membuat tiga Pod yang direplikasi, ditandai dengan kolom
replicas
. -
Kolom
selector
mendefinisikan bagaimana Deployment menemukan Pod yang diatur. Dalam kasus ini, kamu hanya perlu memilih sebuah label yang didefinisikan pada templat Pod (app: nginx
). Namun, aturan pemilihan yang lebih canggih mungkin dilakukan asal templat Pod-nya memenuhi aturan.Catatan: KolommatchLabels
berbentuk pasangan {key,value}. Sebuah {key,value} dalam mapmatchLabels
ekuivalen dengan elemen padamatchExpressions
, yang mana kolom key adalah "key", operator adalah "In", dan larik values hanya berisi "value". Semua prasyarat darimatchLabels
maupunmatchExpressions
harus dipenuhi agar dapat dicocokkan. -
Kolom
template
berisi sub kolom berikut:- Pod dilabeli
app: nginx
dengan kolomlabels
. - Spesifikasi templat Pod atau kolom
.template.spec
menandakan bahwa Pod mennjalankan satu kontainernginx
, yang menjalankan imagenginx
Docker Hub dengan versi 1.7.9. - Membuat satu kontainer bernama
nginx
sesuai kolomname
.
Ikuti langkah-langkah berikut untuk membuat Deployment di atas:
Sebelum memulai, pastikan klaster Kubernetes sedang menyala dan bekerja.
-
Buat Deployment dengan menjalankan perintah berikut:
Catatan: Kamu dapat menambahkan argument--record
untuk menulis perintah yang dijalankan pada anotasi sumber dayakubernetes.io/change-cause
. Ini berguna untuk pemeriksaan di masa depan. Contohnya yaitu untuk melihat perintah yang dijalankan pada tiap revisi Deployment.
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
- Jalankan
kubectl get deployments
untuk mengecek apakah Deployment telah dibuat. Jika Deployment masih sedang pembuatan, keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 3 0 0 0 1s
Ketika kamu memeriksa Deployments pada klastermu, kolom berikut akan tampil:
* `NAME` menampilkan daftar nama Deployment pada klaster. * `DESIRED` menampilkan jumlah replika aplikasi yang diinginkan sesuai yang didefinisikan saat pembuatan Deployment. Ini adalah _state_ yang diinginkan. * `CURRENT` menampilkan berapa jumlah replika yang sedang berjalan. * `UP-TO-DATE` menampilkan jumlah replika yang diperbarui agar sesuai state yang diinginkan. * `AVAILABLE` menampilkan jumlah replika aplikasi yang dapat diakses pengguna. * `AGE` menampilkan lama waktu aplikasi telah berjalan.
Perhatikan bahwa jumlah replika yang diinginkan adalah tiga sesuai kolom
.spec.replicas
.- Untuk melihat status rilis Deployment, jalankan
kubectl rollout status deployment.v1.apps/nginx-deployment
. Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated... deployment "nginx-deployment" successfully rolled out
- Jalankan
kubectl get deployments
lagi beberapa saat kemudian. Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 3 3 3 3 18s
Perhatikan bahwa Deployment telah membuat ketiga replika dan semua replika sudah merupakan yang terbaru (mereka mengandung pembaruan terakhir templat Pod) dan dapat diakses.
- Untuk melihat ReplicaSet (
rs
) yang dibuat Deployment, jalankankubectl get rs
. Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE nginx-deployment-75675f5897 3 3 3 18s
Perhatikan bahwa nama ReplicaSet selalu dalam format
[NAMA-DEPLOYMENT]-[KATA-ACAK]
. Kata acak dibangkitkan secara acak dan menggunakan pod-template-hash sebagai benih.- Untuk melihat label yang dibangkitkan secara otomatis untuk tiap Pod, jalankan
kubectl get pods --show-labels
. Perintah akan menghasilkan keluaran berikut:
NAME READY STATUS RESTARTS AGE LABELS nginx-deployment-75675f5897-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453 nginx-deployment-75675f5897-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453 nginx-deployment-75675f5897-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453
ReplicaSet yang dibuat menjamin bahwa ada tiga Pod
nginx
.Catatan: Kamu harus memasukkan selektor dan label templat Pod yang benar pada Deployment (dalam kasus ini,app: nginx
). Jangan membuat label atau selektor yang beririsan dengan kontroler lain (termasuk Deployment dan StatefulSet lainnya). Kubernetes tidak akan mencegah adanya label yang beririsan. Namun, jika beberapa kontroler memiliki selektor yang beririsan, kontroler itu mungkin akan konflik dan berjalan dengan tidak semestinya. - Pod dilabeli
Label pod-template-hash
Label pod-template-hash
ditambahkan oleh Deployment kontroler pada tiap ReplicaSet yang dibuat atau diadopsi Deployment.
Label ini menjamin anak-anak ReplicaSet milik Deployment tidak tumpang tindih. Dia dibangkitkan dengan melakukan hash pada PodTemplate
milik ReplicaSet dan memakainya sebagai label untuk ditambahkan ke selektor ReplicaSet, label templat Pod, dan Pod apapun yang ReplicaSet miliki.
Membarui Deployment
.spec.template
), contohnya perubahan kolom label atau image container. Yang lain, seperti replika, tidak akan memicu rilis.
Ikuti langkah-langkah berikut untuk membarui Deployment:
-
Ganti Pod nginx menjadi image
nginx:1.9.1
dari imagenginx:1.7.9
.kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment image updated
Alternatif lainnya, kamu dapat
edit
Deployment dan mengganti.spec.template.spec.containers[0].image
daringinx:1.7.9
kenginx:1.9.1
:kubectl edit deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment edited
-
Untuk melihat status rilis, jalankan:
kubectl rollout status deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
atau
deployment "nginx-deployment" successfully rolled out
Untuk menampilkan detail lain dari Deployment yang terbaru:
-
Setelah rilis sukses, kamu dapat melihat Deployment dengan menjalankan
kubectl get deployments
. Keluaran akan tampil seperti berikut:NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 3 3 3 3 36s
-
Jalankan
kubectl get rs
to see that the Deployment updated the Pods dengan membuat ReplicaSet baru dan menggandakannya menjadi 3 replika, sembari menghapus ReplicaSet menjadi 0 replika.kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE nginx-deployment-1564180365 3 3 3 6s nginx-deployment-2035384211 0 0 0 36s
-
Menjalankan
get pods
sekarang hanya akan menampilkan Pod baru:kubectl get pods
Keluaran akan tampil seperti berikut:
NAME READY STATUS RESTARTS AGE nginx-deployment-1564180365-khku8 1/1 Running 0 14s nginx-deployment-1564180365-nacti 1/1 Running 0 14s nginx-deployment-1564180365-z9gth 1/1 Running 0 14s
Selanjutnya ketika ingin membarui Pod, kamu hanya perlu mengganti templat Pod Deployment lagi.
Deployment memastikan hanya ada beberapa Pod yang mati saat pembaruan berlangsung. Umumnya, dia memastikan paling sedikit ada 75% jumlah Pod yang diinginkan menyala (25% maksimal tidak dapat diakses).
Deployment juga memastikan hanya ada beberapa Pod yang dibuat melebihi jumlah Pod yang diinginkan. Umumnya, dia memastikan paling banyak ada 125% jumlah Pod yang diinginkan menyala (25% tambahan maksimal).
Misalnya, jika kamu lihat Deployment diatas lebih jauh, kamu akan melihat bahwa pertama-tama dia membuat Pod baru, kemudian menghapus beberapa Pod lama, dan membuat yang baru. Dia tidak akan menghapus Pod lama sampai ada cukup Pod baru menyala, dan pula tidak membuat Pod baru sampai ada cukup Pod lama telah mati. Dia memastikan paling sedikit 2 Pod menyala dan paling banyak total 4 Pod menyala.
-
Melihat detil Deployment:
kubectl describe deployments
Keluaran akan tampil seperti berikut:
Name: nginx-deployment Namespace: default CreationTimestamp: Thu, 30 Nov 2017 10:56:25 +0000 Labels: app=nginx Annotations: deployment.kubernetes.io/revision=2 Selector: app=nginx Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.9.1 Port: 80/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-1564180365 (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 2m deployment-controller Scaled up replica set nginx-deployment-2035384211 to 3 Normal ScalingReplicaSet 24s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 1 Normal ScalingReplicaSet 22s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 2 Normal ScalingReplicaSet 22s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 2 Normal ScalingReplicaSet 19s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 1 Normal ScalingReplicaSet 19s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 3 Normal ScalingReplicaSet 14s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 0
Disini bisa dilihat ketika pertama Deployment dibuat, dia membuat ReplicaSet (nginx-deployment-2035384211) dan langsung menggandakannya menjadi 3 replika. Saat Deployment diperbarui, dia membuat ReplicaSet baru (nginx-deployment-1564180365) dan menambah 1 replika kemudian mengecilkan ReplicaSet lama menjadi 2, sehingga paling sedikit 2 Pod menyala dan paling banyak 4 Pod dibuat setiap saat. Dia kemudian lanjut menaik-turunkan ReplicaSet baru dan ReplicaSet lama, dengan strategi pembaruan rolling yang sama. Terakhir, kamu akan dapat 3 replika di ReplicaSet baru telah menyala, dan ReplicaSet lama akan hilang (berisi 0).
Perpanjangan (alias banyak pembaruan secara langsung)
Setiap kali Deployment baru is teramati oleh Deployment kontroler, ReplicaSet dibuat untuk membangkitkan Pod sesuai keinginan.
Jika Deployment diperbarui, ReplicaSet yang terkait Pod dengan label .spec.selector
yang cocok,
namun kolom .spec.template
pada templat tidak cocok akan dihapus. Kemudian, ReplicaSet baru akan
digandakan sebanyak .spec.replicas
dan semua ReplicaSet lama dihapus.
Jika kamu mengubah Deployment saat rilis sedang berjalan, Deployment akan membuat ReplicaSet baru tiap perubahan dan memulai penggandaan. Lalu, dia akan mengganti ReplicaSet yang dibuat sebelumnya -- mereka ditambahkan ke dalam daftar ReplicaSet lama dan akan mulai dihapus.
Contohnya, ketika kamu membuat Deployment untuk membangkitkan 5 replika nginx:1.7.9
,
kemudian membarui Deployment dengan versi nginx:1.9.1
ketika ada 3 replika nginx:1.7.9
yang dibuat.
Dalam kasus ini, Deployment akan segera menghapus 3 replika Pod nginx:1.7.9
yang telah dibuat, dan mulai membuat
Pod nginx:1.9.1
. Dia tidak akan menunggu kelima replika nginx:1.7.9
selesai baru menjalankan perubahan.
Mengubah selektor label
Umumnya, sekali dibuat, selektor label tidak boleh diubah. Sehingga disarankan untuk direncanakan dengan hati-hati sebelumnya. Bagaimanapun, jika kamu perlu mengganti selektor label, lakukan dengan seksama dan pastikan kamu tahu segala konsekuensinya.
apps/v1
, selektor label Deployment tidak bisa diubah ketika selesai dibuat.
- Penambahan selektor mensyaratkan label templat Pod di spek Deployment untuk diganti dengan label baru juga. Jika tidak, galat validasi akan muncul. Perubahan haruslah tidak tumpang-tindih, dengan kata lain selektor baru tidak mencakup ReplicaSet dan Pod yang dibuat dengan selektor lama. Sehingga, semua ReplicaSet lama akan menggantung sedangkan ReplicaSet baru tetap dibuat.
- Pengubahan selektor mengubah nilai pada kunci selektor -- menghasilkan perilaku yang sama dengan penambahan.
- Penghapusan selektor menghilangkan kunci yang ada pada selektor Deployment -- tidak mensyaratkan perubahan apapun pada label templat Pod. ReplicaSet yang ada tidak menggantung dan ReplicaSet baru tidak dibuat. Tapi perhatikan bahwa label yang dihapus masih ada pada Pod dan ReplicaSet masing-masing.
Membalikkan Deployment
Kadang, kamu mau membalikkan Deployment; misalnya, saat Deployment tidak stabil, seperti crash looping. Umumnya, semua riwayat rilis Deployment disimpan oleh sistem sehingga kamu dapat kembali kapanpun kamu mau (kamu dapat mengubahnya dengan mengubah batas riwayat revisi).
.spec.template
) berubah, misalnya jika kamu membarui label atau image kontainer pada templat.
Pembaruan lain, seperti penggantian skala Deployment, tidak membuat revisi Deployment, jadi kamu dapat memfasilitasi
penggantian skala secara manual atau otomatis secara simultan. Artinya saat kamu membalikkan ke versi sebelumnya,
hanya bagian templat Pod Deployment yang dibalikkan.
-
Misal kamu membuat saltik saat mengganti Deployment, dengan memberi nama image dengan
nginx:1.91
alih-alihnginx:1.9.1
:kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment image updated
-
Rilis akan tersendat. Kamu dapat memeriksanya dengan melihat status rilis:
kubectl rollout status deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
-
Tekan Ctrl-C untuk menghentikan pemeriksaan status rilis di atas. Untuk info lebih lanjut tentang rilis tersendat, baca disini.
-
Kamu lihat bahwa jumlah replika lama (
nginx-deployment-1564180365
dannginx-deployment-2035384211
) adalah 2, dan replika baru (nginx-deployment-3066724191) adalah 1.kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE nginx-deployment-1564180365 3 3 3 25s nginx-deployment-2035384211 0 0 0 36s nginx-deployment-3066724191 1 1 0 6s
-
Lihat pada Pod yang dibuat. Akan ada 1 Pod dibuat dari ReplicaSet baru tersendat loop(?) ketika penarikan image.
kubectl get pods
Keluaran akan tampil seperti berikut:
NAME READY STATUS RESTARTS AGE nginx-deployment-1564180365-70iae 1/1 Running 0 25s nginx-deployment-1564180365-jbqqo 1/1 Running 0 25s nginx-deployment-1564180365-hysrc 1/1 Running 0 25s nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s
Catatan: Controller Deployment menghentikan rilis yang buruk secara otomatis dan juga berhenti meningkatkan ReplicaSet baru. Ini tergantung pada parameter rollingUpdate (secara khususmaxUnavailable
) yang dimasukkan. Kubernetes umumnya mengatur jumlahnya menjadi 25%. -
Tampilkan deskripsi Deployment:
kubectl describe deployment
Keluaran akan tampil seperti berikut:
Name: nginx-deployment Namespace: default CreationTimestamp: Tue, 15 Mar 2016 14:48:04 -0700 Labels: app=nginx Selector: app=nginx Replicas: 3 desired | 1 updated | 4 total | 3 available | 1 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.91 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True ReplicaSetUpdated OldReplicaSets: nginx-deployment-1564180365 (3/3 replicas created) NewReplicaSet: nginx-deployment-3066724191 (1/1 replicas created) Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3 22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1 22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2 22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2 21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 1 21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3 13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0 13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1
Untuk memperbaikinya, kamu harus kembali ke revisi Deployment yang sebelumnya stabil.
Mengecek Riwayat Rilis Deployment
Ikuti langkah-langkah berikut untuk mengecek riwayat rilis:
-
Pertama, cek revisi Deployment sekarang:
kubectl rollout history deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
deployments "nginx-deployment" REVISION CHANGE-CAUSE 1 kubectl apply --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml --record=true 2 kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record=true 3 kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
CHANGE-CAUSE
disalin dari anotasi Deploymentkubernetes.io/change-cause
ke revisi saat pembuatan. Kamu dapat menentukan pesanCHANGE-CAUSE
dengan:- Menambahkan anotasi pada Deployment dengan
kubectl annotate deployment.v1.apps/nginx-deployment kubernetes.io/change-cause="image updated to 1.9.1"
- Menambahkan argumen
--record
untuk menyimpan perintahkubectl
yang menyebabkan perubahan sumber daya. - Mengganti manifest sumber daya secara manual.
- Menambahkan anotasi pada Deployment dengan
-
Untuk melihat detil tiap revisi, jalankan:
kubectl rollout history deployment.v1.apps/nginx-deployment --revision=2
Keluaran akan tampil seperti berikut:
deployments "nginx-deployment" revision 2 Labels: app=nginx pod-template-hash=1159050644 Annotations: kubernetes.io/change-cause=kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record=true Containers: nginx: Image: nginx:1.9.1 Port: 80/TCP QoS Tier: cpu: BestEffort memory: BestEffort Environment Variables: <none> No volumes.
Kembali ke Revisi Sebelumnya
Ikuti langkah-langkah berikut untuk membalikkan Deployment dari versi sekarang ke versi sebelumnya, yaitu versi 2.
-
Sekarang kamu telah menentukan akan mengembalikan rilis sekarang ke sebelumnya:
kubectl rollout undo deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment
Gantinya, kamu dapat kambali ke revisi tertentu dengan menambahkan argumen
--to-revision
:kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment
Untuk detil lebih lanjut perintah terkait rilis, baca
rilis kubectl
.Deployment sekarang dikembalikan ke revisi stabil sebelumnya. Seperti terlihat, ada event
DeploymentRollback
yang dibentuk oleh kontroler Deployment untuk pembalikan ke revisi 2. -
Cek apakah rilis telah sukses dan Deployment berjalan seharusnya, jalankan:
kubectl get deployment nginx-deployment
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 3 3 3 3 30m
-
Tampilkan deskripsi Deployment:
kubectl describe deployment nginx-deployment
Keluaran akan tampil seperti berikut:
Name: nginx-deployment Namespace: default CreationTimestamp: Sun, 02 Sep 2018 18:17:55 -0500 Labels: app=nginx Annotations: deployment.kubernetes.io/revision=4 kubernetes.io/change-cause=kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record=true Selector: app=nginx Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.9.1 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-c4747d96c (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set nginx-deployment-75675f5897 to 3 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 1 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 2 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 2 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 1 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 3 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 0 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-595696685f to 1 Normal DeploymentRollback 15s deployment-controller Rolled back deployment "nginx-deployment" to revision 2 Normal ScalingReplicaSet 15s deployment-controller Scaled down replica set nginx-deployment-595696685f to 0
Mengatur Skala Deployment
Kamu dapat mengatur skala Deployment dengan perintah berikut:
kubectl scale deployment.v1.apps/nginx-deployment --replicas=10
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment scaled
Dengan asumsi horizontal Pod autoscaling dalam klaster dinyalakan, kamu dapat mengatur autoscaler untuk Deployment-mu dan memilih jumlah minimal dan maksimal Pod yang mau dijalankan berdasarkan penggunaan CPU dari Pod.
kubectl autoscale deployment.v1.apps/nginx-deployment --min=10 --max=15 --cpu-percent=80
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment scaled
Pengaturan skala proporsional
Deployment RollingUpdate mendukung beberapa versi aplikasi berjalan secara bersamaan. Ketika kamu atau autoscaler mengubah skala Deployment RollingUpdate yang ada di tengah rilis (yang sedang berjalan maupun terjeda), kontroler Deployment menyeimbangkan replika tambahan dalam ReplicaSet aktif (ReplicaSet dengan Pod) untuk mencegah resiko. Ini disebut pengaturan skala proporsional.
Sebagai contoh, kamu menjalankan Deployment dengan 10 replika, maxSurge=3, dan maxUnavailable=2.
-
Pastikan ada 10 replica di Deployment-mu yang berjalan.
kubectl get deploy
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 10 10 10 10 50s
-
Ganti ke image baru yang kebetulan tidak bisa ditemukan dari dalam klaster.
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:sometag
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment image updated
-
Penggantian image akan memulai rilis baru dengan ReplicaSet nginx-deployment-1989198191, namun dicegah karena persyaratan
maxUnavailable
yang disebut di atas. Cek status rilis:kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE nginx-deployment-1989198191 5 5 0 9s nginx-deployment-618515232 8 8 8 1m
-
Kemudian, permintaan peningkatan untuk Deployment akan masuk. Autoscaler menambah replika Deployment menjadi 15. Controller Deployment perlu menentukan dimana 5 replika ini ditambahkan. Jika kamu memakai pengaturan skala proporsional, kelima replika akan ditambahkan ke ReplicaSet baru. Dengan pengaturan skala proporsional, kamu menyebarkan replika tambahan ke semua ReplicaSet. Proporsi terbesar ada pada ReplicaSet dengan replika terbanyak dan proporsi yang lebih kecil untuk replika dengan ReplicaSet yang lebih sedikit. Sisanya akan diberikan ReplicaSet dengan replika terbanyak. ReplicaSet tanpa replika tidak akan ditingkatkan.
Dalam kasus kita di atas, 3 replika ditambahkan ke ReplicaSet lama dan 2 replika ditambahkan ke ReplicaSet baru. Proses rilis akan segera memindahkan semua ReplicaSet baru, dengan asumsi semua replika dalam kondisi sehat. Untuk memastikannya, jalankan:
kubectl get deploy
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
Status rilis mengkonfirmasi bagaimana replika ditambahkan ke tiap ReplicaSet.
kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
Menjeda dan Melanjutkan Deployment
Kamu dapat menjeda Deployment sebelum memicu satu atau lebih pembaruan kemudian meneruskannya. Hal ini memungkinkanmu menerapkan beberapa perbaikan selama selang jeda tanpa melakukan rilis yang tidak perlu.
-
Sebagai contoh, Deployment yang baru dibuat: Lihat detil Deployment:
kubectl get deploy
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 3 3 3 3 1m
Lihat status rilis:
kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE nginx-2142116321 3 3 3 1m
-
Jeda dengan menjalankan perintah berikut:
kubectl rollout pause deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment paused
-
Lalu ganti kolom image Deployment:
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment image updated
-
Perhatikan tidak ada rilis baru yang muncul:
kubectl rollout history deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
deployments "nginx" REVISION CHANGE-CAUSE 1 <none>
-
Lihat status rilis untuk memastikan Deployment berhasil diperbarui:
kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE nginx-2142116321 3 3 3 2m
-
Kamu bisa membuat pembaruan sebanyak yang kamu mau. Contohnya pembaruan sumber daya yang akan dipakai:
kubectl set resources deployment.v1.apps/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment resource requirements updated
The state awal Deployment sebelum jeda akan melanjutkan fungsinya, tapi perubahan Deployment tidak akan berefek apapun selama Deployment masih terjeda.
-
Kemudian, mulai kembali Deployment dan perhatikan ReplicaSet baru akan muncul dengan semua perubahan baru:
kubectl rollout resume deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment resumed
-
Perhatikan status rilis sampai selesai.
kubectl get rs -w
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE nginx-2142116321 2 2 2 2m nginx-3926361531 2 2 0 6s nginx-3926361531 2 2 1 18s nginx-2142116321 1 2 2 2m nginx-2142116321 1 2 2 2m nginx-3926361531 3 2 1 18s nginx-3926361531 3 2 1 18s nginx-2142116321 1 1 1 2m nginx-3926361531 3 3 1 18s nginx-3926361531 3 3 2 19s nginx-2142116321 0 1 1 2m nginx-2142116321 0 1 1 2m nginx-2142116321 0 0 0 2m nginx-3926361531 3 3 3 20s
-
Lihat status rilis terakhir:
kubectl get rs
Keluaran akan tampil seperti berikut:
NAME DESIRED CURRENT READY AGE nginx-2142116321 0 0 0 2m nginx-3926361531 3 3 3 28s
Status Deployment
Deployment melalui berbagai state dalam daur hidupnya. Dia dapat berlangsung selagi merilis ReplicaSet baru, bisa juga selesai, atau juga gagal.
Deployment Berlangsung
Kubernetes menandai Deployment sebagai progressing saat salah satu tugas di bawah dikerjakan:
- Deployment membuat ReplicaSet baru.
- Deployment menaikkan kapasitas ReplicaSet terbaru.
- Deployment menurunkan kapasitas ReplicaSet yang lebih lama.
- Pod baru menjadi siap atau dapat diakses (siap selama setidaknya MinReadySeconds).
Kamu dapat mengawasi perkembangan Deployment dengan kubectl rollout status
.
Deployment Selesai
Kubernetes menandai Deployment sebagai complete saat memiliki karakteristik berikut:
- Semua replika terkait Deployment telah diperbarui ke versi terbaru yang dispecify, artinya semua pembaruan yang kamu inginkan telah selesai.
- Semua replika terkait Deployment dapat diakses.
- Tidak ada replika lama untuk Deployment yang berjalan.
Kamu dapat mengecek apakah Deployment telah selesai dengan kubectl rollout status
.
Jika rilis selesai, kubectl rollout status
akan mengembalikan nilai balik nol.
kubectl rollout status deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out
$ echo $?
0
Deployment Gagal
Deployment-mu bisa saja terhenti saat mencoba deploy ReplicaSet terbaru tanpa pernah selesai. Ini dapat terjadi karena faktor berikut:
- Kuota tidak mencukupi
- Kegagalan pengecekan kesiapan
- Galat saat mengunduh image
- Tidak memiliki ijin
- Limit ranges
- Konfigurasi runtime aplikasi yang salah
Salah satu cara untuk mendeteksi kondisi ini adalah untuk menjelaskan parameter tenggat pada spesifikasi Deployment:
(.spec.progressDeadlineSeconds
). .spec.progressDeadlineSeconds
menyatakan
lama kontroler Deployment menunggu sebelum mengindikasikan (pada status Deployment) bahwa kemajuan Deployment
tersendat dalam detik.
Perintah kubectl
berikut menetapkan spek dengan progressDeadlineSeconds
untuk membuat kontroler
melaporkan kemajuan Deployment yang sedikit setelah 10 menit:
kubectl patch deployment.v1.apps/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
Keluaran akan tampil seperti berikut:
deployment.apps/nginx-deployment patched
Ketika tenggat sudah lewat, kontroler Deployment menambah DeploymentCondition dengan atribut
berikut ke .status.conditions
milik Deployment:
- Type=Progressing
- Status=False
- Reason=ProgressDeadlineExceeded
Lihat konvensi Kubernetes API untuk info lebih lanjut tentang kondisi status.
Reason=ProgressDeadlineExceeded
.
Orkestrator yang lebih tinggi dapat memanfaatkannya untuk melakukan tindak lanjut. Misalnya, mengembalikan Deployment ke versi sebelumnya.
Kamu dapat mengalami galat sejenak pada Deployment disebabkan timeout yang dipasang terlalu kecil atau hal-hal lain yang terjadi sementara. Misalnya, kamu punya kuota yang tidak mencukupi. Jika kamu mendeskripsikan Deployment kamu akan menjumpai pada bagian ini:
kubectl describe deployment nginx-deployment
Keluaran akan tampil seperti berikut:
<...>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True ReplicaSetUpdated
ReplicaFailure True FailedCreate
<...>
Jika kamu menjalankan kubectl get deployment nginx-deployment -o yaml
, Deployment status akan muncul seperti berikut:
status:
availableReplicas: 2
conditions:
- lastTransitionTime: 2016-10-04T12:25:39Z
lastUpdateTime: 2016-10-04T12:25:39Z
message: Replica set "nginx-deployment-4262182780" is progressing.
reason: ReplicaSetUpdated
status: "True"
type: Progressing
- lastTransitionTime: 2016-10-04T12:25:42Z
lastUpdateTime: 2016-10-04T12:25:42Z
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: 2016-10-04T12:25:39Z
lastUpdateTime: 2016-10-04T12:25:39Z
message: 'Error creating: pods "nginx-deployment-4262182780-" is forbidden: exceeded quota:
object-counts, requested: pods=1, used: pods=3, limited: pods=2'
reason: FailedCreate
status: "True"
type: ReplicaFailure
observedGeneration: 3
replicas: 2
unavailableReplicas: 2
Begitu tenggat kemajuan Deployment terlewat, Kubernetes membarui status dan alasan untuk kondisi Progressing:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate
Kamu dapat menangani isu keterbatasan kuota dengan menurunkan jumlah Deployment, bisa dengan menghapus kontrolers
yang sedang berjalan, atau dengan meningkatkan kuota pada namespace. Jika kuota tersedia, kemudian kontroler Deployment
akan dapat menyelesaikan rilis Deployment. Kamu akan melihat bahwa status Deployment berubah menjadi kondisi sukses (Status=True
dan Reason=NewReplicaSetAvailable
).
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
Type=Available
dengan Status=True
artinya Deployment-mu punya ketersediaan minimum. Ketersediaan minimum diatur
oleh parameter yang dibuat pada strategi deployment. Type=Progressing
dengan Status=True
berarti Deployment
sedang dalam rilis dan masih berjalan atau sudah selesai berjalan dan jumlah minimum replika tersedia
(lihat bagian Alasan untuk kondisi tertentu - dalam kasus ini Reason=NewReplicaSetAvailable
berarti Deployment telah selesai).
Kamu dapat mengecek apakah Deployment gagal berkembang dengan perintah kubectl rollout status
. kubectl rollout status
mengembalikan nilai selain nol jika Deployment telah melewati tenggat kemajuan.
kubectl rollout status deployment.v1.apps/nginx-deployment
Keluaran akan tampil seperti berikut:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline
$ echo $?
1
Menindak Deployment yang gagal
Semua aksi yang dapat diterapkan pada Deployment yang selesai berjalan juga pada Deployment gagal. Kamu dapat menaik/turunkan replika, membalikkan ke versi sebelumnya, atau menjedanya jika kamu perlu menerapkan beberapa perbaikan pada templat Pod Deployment.
Kebijakan Pembersihan
Kamu dapat mengisi kolom .spec.revisionHistoryLimit
di Deployment untuk menentukan banyak ReplicaSet
pada Deployment yang ingin dipertahankan. Sisanya akan di garbage-collected di balik layar. Umumnya, nilai kolom berisi 10.
Deployment Canary
Jika kamu ingin merilis ke sebagian pengguna atau server menggunakan Deployment, kamu dapat membuat beberapa Deployment, satu tiap rilis, dengan mengikuti pola canary yang didesripsikan pada mengelola sumber daya.
Menulis Spesifikasi Deployment
Sebagaimana konfigurasi Kubernetes lainnya, Deployment memerlukan kolom apiVersion
, kind
, dan metadata
.
Untuk informasi umum tentang penggunaan berkas konfigurasi, lihat dokumen deploy aplikasi,
mengatur kontainer, dan memakai kubectl untuk mengatur sumber daya.
Deployment juga perlu bagian .spec
.
Templat Pod
Dalam .spec
hanya ada kolom .spec.template
dan .spec.selector
yang wajib diisi.
.spec.template
adalah templat Pod. Dia memiliki skema yang sama dengan Pod. Bedanya dia bersarang dan tidak punya apiVersion
atau kind
.
Selain kolom wajib untuk Pod, templat Pod pada Deployment harus menentukan label dan aturan menjalankan ulang yang tepat. Untuk label, pastikaan tidak bertumpang tindih dengan kontroler lainnya. Lihat selektor).
.spec.template.spec.restartPolicy
hanya boleh berisi Always
,
yang tidak ditentukan pada bawaan.
Replika
.spec.replicas
adalah kolom opsional yang mengatur jumlah Pod yang diinginkan. Setelan bawaannya berisi 1.
Selektor
.spec.selector
adalah kolom wajib yang mengatur selektor label
untuk Pod yang dituju oleh Deployment ini.
.spec.selector
harus sesuai .spec.template.metadata.labels
, atau akan ditolak oleh API.
Di versi API apps/v1
, .spec.selector
dan .metadata.labels
tidak berisi .spec.template.metadata.labels
jika tidak disetel.
Jadi mereka harus disetel secara eksplisit. Perhatikan juga .spec.selector
tidak dapat diubah setelah Deployment dibuat pada apps/v1
.
Deployment dapat mematikan Pod yang labelnya cocok dengan selektor jika templatnya berbeda
dari .spec.template
atau total jumlah Pod melebihi .spec.replicas
. Dia akan membuat Pod baru
dengan .spec.template
jika jumlah Pod kurang dari yang diinginkan.
Jika kamu punya beberapa kontroler dengan selektor bertindihan, mereka akan saling bertikai dan tidak akan berjalan semestinya.
Strategi
.spec.strategy
mengatur strategi yang dipakai untuk mengganti Pod lama dengan yang baru.
.spec.strategy.type
dapat berisi "Recreate" atau "RollingUpdate". Nilai bawaannya adalah "RollingUpdate".
Membuat Ulang Deployment
Semua Pod yang ada dimatikan sebelum yang baru dibuat ketika nilai .spec.strategy.type==Recreate
.
Membarui Deployment secara Bergulir
Deployment membarui Pod secara bergulir
saat .spec.strategy.type==RollingUpdate
. Kamu dapat menentukan maxUnavailable
dan maxSurge
untuk mengatur
proses pembaruan bergulir.
Ketidaktersediaan Maksimum
.spec.strategy.rollingUpdate.maxUnavailable
adalah kolom opsional yang mengatur jumlah Pod maksimal
yang tidak tersedia selama proses pembaruan. Nilainya bisa berupa angka mutlak (contohnya 5)
atau persentase dari Pod yang diinginkan (contohnya 10%). Angka mutlak dihitung berdasarkan persentase
dengan pembulatan ke bawah. Nilai tidak bisa nol jika .spec.strategy.rollingUpdate.maxSurge
juga nol.
Nilai bawaannya yaitu 25%.
Sebagai contoh, ketika nilai berisi 30%, ReplicaSet lama dapat segera diperkecil menjadi 70% dari Pod yang diinginkan saat pembaruan bergulir dimulai. Seketika Pod baru siap, ReplicaSet lama dapat lebih diperkecil lagi, diikuti dengan pembesaran ReplicaSet, menjamin total jumlah Pod yang siap kapanpun ketika pembaruan paling sedikit 70% dari Pod yang diinginkan.
Kelebihan Maksimum
.spec.strategy.rollingUpdate.maxSurge
adalah kolom opsional yang mengatur jumlah Pod maksimal yang
dapat dibuat melebihi jumlah Pod yang diinginkan. Nilainya bisa berupa angka mutlak (contohnya 5) atau persentase
dari Pod yang diinginkan (contohnya 10%). Nilai tidak bisa nol jika MaxUnavailable
juga nol. Angka mutlak
dihitung berdasarkan persentase dengan pembulatan ke bawah. Nilai bawaannya yaitu 25%.
Sebagai contoh, ketika nilai berisi 30%, ReplicaSet baru dapat segera diperbesar saat pembaruan bergulir dimulai, sehingga total jumlah Pod yang baru dan lama tidak melebihi 130% dari Pod yang diinginkan. Saat Pod lama dimatikan, ReplicaSet baru dapat lebih diperbesar lagi, menjamin total jumlah Pod yang siap kapanpun ketika pembaruan paling banyak 130% dari Pod yang diinginkan.
Tenggat Kemajuan dalam Detik
.spec.progressDeadlineSeconds
adalah kolom opsional yang mengatur lama tunggu dalam dalam detik untuk Deployment-mu berjalan
sebelum sistem melaporkan lagi bahwa Deployment gagal - ditunjukkan dengan kondisi Type=Progressing
, Status=False
,
dan Reason=ProgressDeadlineExceeded
pada status sumber daya. Controller Deployment akan tetap mencoba ulang Deployment.
Nantinya begitu pengembalian otomatis diimplementasikan, kontroler Deployment akan membalikkan Deployment segera
saat dia menjumpai kondisi tersebut.
Jika ditentukan, kolom ini harus lebih besar dari .spec.minReadySeconds
.
Lama Minimum untuk Siap dalam Detik
.spec.minReadySeconds
adalah kolom opsional yang mengatur lama minimal sebuah Pod yang baru dibuat
seharusnya siap tanpa ada kontainer yang rusak, untuk dianggap tersedia, dalam detik.
Nilai bawaannya yaitu 0 (Pod akan dianggap tersedia segera ketika siap). Untuk mempelajari lebih lanjut
kapan Pod dianggap siap, lihat Pemeriksaan Kontainer.
Kembali Ke
Kolom .spec.rollbackTo
telah ditinggalkan pada versi API extensions/v1beta1
dan apps/v1beta1
, dan sudah tidak didukung mulai versi API apps/v1beta2
.
Sebagai gantinya, disarankan untuk menggunakan kubectl rollout undo
sebagaimana diperkenalkan dalam Kembali ke Revisi Sebelumnya.
Batas Riwayat Revisi
Riwayat revisi Deployment disimpan dalam ReplicaSet yang dia kendalikan.
.spec.revisionHistoryLimit
adalah kolom opsional yang mengatur jumlah ReplicaSet lama yang dipertahankan
untuk memungkinkan pengembalian. ReplicaSet lama ini mengambil sumber daya dari etcd
dan memunculkan keluaran
dari kubectl get rs
. Konfigurasi tiap revisi Deployment disimpan pada ReplicaSet-nya; sehingga, begitu ReplicaSet lama dihapus,
kamu tidak mampu lagi membalikkan revisi Deployment-nya. Umumnya, 10 ReplicaSet lama akan dipertahankan,
namun nilai idealnya tergantung pada frekuensi dan stabilitas Deployment-deployment baru.
Lebih spesifik, mengisi kolom dengan nol berarti semua ReplicaSet lama dengan 0 replika akan dibersihkan. Dalam kasus ini, rilis Deployment baru tidak dapat dibalikkan, sebab riwayat revisinya telah dibersihkan.
Terjeda
.spec.paused
adalah kolom boolean opsional untuk menjeda dan melanjutkan Deployment. Perbedaan antara Deployment yang terjeda
dan yang tidak hanyalah perubahan apapun pada PodTemplateSpec Deployment terjeda tidak akan memicu rilis baru selama masih terjeda.
Deployment umumnya tidak terjeda saat dibuat.
Alternatif untuk Deployment
kubectl rolling update
kubectl rolling update
membarui Pod dan ReplicationController
dengan cara yang serupa. Namun, Deployments lebih disarankan karena deklaratif, berjalan di sisi server, dan punya fitur tambahan,
seperti pembalikkan ke revisi manapun sebelumnya bahkan setelah pembaruan rolling selesais.
3.4.2.4 - StatefulSet
StatefulSet merupakan salah satu objek API workload yang digunakan untuk aplikasi stateful.
Melakukan proses manajemen deployment dan scaling dari sebuah set Pods, serta menjamin mekanisme ordering dan keunikan dari Pod ini.
Seperti halnya Deployment, sebuah StatefulSet akan melakukan proses manajemen Pod yang didasarkan pada spec container identik. Meskipun begitu tidak seperti sebuah Deployment, sebuah StatefulSet akan menjamin identitas setiap Pod yang ada. Pod ini akan dibuat berdasarkan spec yang sama, tetapi tidak dapat digantikan satu sama lainnya: setiap Pod memiliki identifier persisten yang akan di-maintain meskipun pod tersebut di (re)schedule.
Sebuah StatefulSet beroperasi dengan pola yang sama dengan Kontroler lainnya. Kamu dapat mendefinisikan state yang diinginkan pada objek StatefulSet, dan kontroler StatefulSet akan membuat update yang dibutuhkan dari state saat ini.
Menggunakan StatefulSet
StatefulSet akan sangat bermanfaat apabila digunakan untuk aplikasi yang membutuhkan salah satu atau beberapa fungsi berikut.
- Memiliki identitas jaringan unik yang stabil.
- Penyimpanan persisten yang stabil.
- Mekanisme scaling dan deployment yang graceful tertara berdasarkan urutan.
- Mekanisme rolling update yang otomatis berdasarkan urutan.
Stabil dalam poin-poin di atas memiliki arti yang sama dengan persisten pada Pod saat dilakukan (re)scheduling. Jika suatu aplikasi tidak membutuhkan identitas yang stabil atau deployment yang memiliki urutan, penghapusan, atau mekanisme scaling, kamu harus melakukan deploy aplikasi dengan controller yang menyediakan replika stateless. Controller seperti Deployment atau ReplicaSet akan lebih sesuai dengan kebutuhan kamu.
Keterbatasan
- StatefulSet merupakan sumber daya beta sebelum 1.9 dan tidak tersedia pada Kubernetes rilis sebelum versi 1.5.
- Penyimpanan untuk sebuah Pod harus terlebih dahulu di-provision dengan menggunakan sebuah Provisioner PersistentVolume berdasarkan
storage class
yang dispesifikasikan, atau sudah ditentukan sebelumnya oleh administrator. - Menghapus dan/atau scaling sebuah StatefulSet tidak akan menghapus volume yang berkaitan dengan StatefulSet tersebut. Hal ini dilakukan untuk menjamin data yang disimpan, yang secara umum dinilai lebih berhaga dibandingkan dengan mekanisme penghapusan data secara otomatis pada sumber daya terkait.
- StatefulSet saat ini membutuhkan sebuah Headless Service yang nantinya akan bertanggung jawab terhadap pada identitas jaringan pada Pod. Kamulah yang bertanggung jawab untuk membuat Service tersebut.
- StatefulSet tidak menjamin terminasi Pod ketika sebuah StatefulSet dihapus. Untuk mendapatkan terminasi Pod yang terurut dan graceful pada StatefulSet, kita dapat melakukan scale down Pod ke 0 sebelum penghapusan.
- Ketika menggunakan Rolling Update dengan
Kebijakan Manajemen Pod (
OrderedReady
) secara default, hal ini memungkinkan untuk mendapatkan state yang lebih terperinci yang membutuhkan mekanisme intervensi manual untuk perbaikan.
Komponen-Komponen
Contoh di bawah ini akna menunjukkan komponen-komponen penyusun StatefulSet.
- Sebuah Service Headless, dengan nama nginx, digunakan untuk mengontrol domain jaringan.
- StatefulSet, dengan nama web, memiliki Spek yang mengindikasikan terdapat 3 replika Container yang akan dihidupkan pada Pod yang unik.
- Field
volumeClaimTemplates
akan menyediakan penyimpanan stabil menggunakan PersistentVolume yang di-provision oleh sebuah Provisioner PersistentVolume.
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # harus sesuai dengan .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # nilai default-nya adalah 1
template:
metadata:
labels:
app: nginx # harus sesuai dengan .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
Selector Pod
Kamu harus menspesifikasikan field .spec.selector
dari sebuah StatefulSet untuk menyesuaikan dengan label yang ada pada .spec.template.metadata.labels
. Sebelum Kubernetes 1.8, field .spec.selector
dapat diabaikan. Sejak versi 1.8 dan versi selanjutnya, apabila tidak terdapat selector Pod yang sesuai maka akan menghasilkan eror pada validasi pembuatan StatefulSet.
Identitas Pod
Pod pada StatefulSet memiliki identitas unik yang tersusun berdasarkan skala ordinal, sebuah identitas jaringan yang stabil, serta penyimpanan yang stabil. Identitas yang ada pada Pod ini akan tetap melekat, meskipun Pod tersebut dilakukan (re)schedule pada Node yang berbeda.
Indeks Ordinal
Untuk sebuah StatefulSet dengan N buah replika, setiap Pod di dalam StatefulSet akan diberi nama pada suatu indeks ordinal tertentu, dari 0 hingga N-1, yang unik pada Set ini.
ID Jaringan yang Stabil
Setiap Pod di dalam StatefulSet memiliki hostname diturunkan dari nama SatetulSet tersebut
serta ordinal Pod tersebut. Pola pada hostname yang terbentuk adalah
$(statefulset name)-$(ordinal)
. Contoh di atas akan menghasilkan tiga Pod
dengan nama web-0,web-1,web-2
.
Sebuah StatefulSet dapat menggunakan sebuah Service Headless
untuk mengontrol domain dari Pod yang ada. Domain yang diatur oleh Service ini memiliki format:
$(service name).$(namespace).svc.cluster.local
, dimana "cluster.local" merupakan
domain klaster.
Seiring dibuatnya setiap Pod, Pod tersebut akan memiliki subdomain DNS-nya sendiri, yang memiliki format:
$(podname).$(governing service domain)
, dimana Service yang mengatur didefinisikan oleh
field serviceName
pada StatefulSet.
Seperti sudah disebutkan di dalam bagian keterbatasan, kamulah yang bertanggung jawab untuk membuat Service Headless yang bertanggung jawab terhadap identitas jaringan pada Pod.
Di sini terdapat beberapa contoh penggunaan Domain Klaster, nama Service, nama StatefulSet, dan bagaimana hal tersebut berdampak pada nama DNS dari Pod StatefulSet.
Domain Klaster | Service (ns/nama) | StatefulSet (ns/nama) | Domain StatefulSet | DNS Pod | Hostname Pod |
---|---|---|---|---|---|
cluster.local | default/nginx | default/web | nginx.default.svc.cluster.local | web-{0..N-1}.nginx.default.svc.cluster.local | web-{0..N-1} |
cluster.local | foo/nginx | foo/web | nginx.foo.svc.cluster.local | web-{0..N-1}.nginx.foo.svc.cluster.local | web-{0..N-1} |
kube.local | foo/nginx | foo/web | nginx.foo.svc.kube.local | web-{0..N-1}.nginx.foo.svc.kube.local | web-{0..N-1} |
cluster.local
kecuali
nilainya dikonfigurasi.
Penyimpanan Stabil
Kubernetes membuat sebuah PersistentVolume untuk setiap
VolumeClaimTemplate. Pada contoh nginx di atas, setiap Pod akan menerima sebuah PersistentVolume
dengan StorageClass my-storage-class
dan penyimpanan senilai 1 Gib yang sudah di-provisioning. Jika tidak ada StorageClass
yang dispesifikasikan, maka StorageClass default akan digunakan. Ketika sebuah Pod dilakukan (re)schedule
pada sebuah Node, volumeMounts
akan me-mount PersistentVolumes yang terkait dengan
PersistentVolume Claim-nya. Perhatikan bahwa, PersistentVolume yang terkait dengan
PersistentVolumeClaim dari Pod tidak akan dihapus ketika Pod, atau StatefulSet dihapus.
Penghapusan ini harus dilakukan secara manual.
Label Pod Name
Ketika sebuah controller StatefulSet membuat sebuah Pod, controller ini akan menambahkan label, statefulset.kubernetes.io/pod-name
,
yang akan diaktifkan pada nama Pod. Label ini akan mengizinkan kamu untuk meng-attach sebuah Service pada Pod spesifik tertentu.
di StatefulSet.
Jaminan Deployment dan Mekanisme Scaling
- Untuk sebuah StatefulSet dengan N buah replika, ketika Pod di-deploy, Pod tersebut akan dibuat secara berurutan dengan urutan nilai {0..N-1}.
- Ketika Pod dihapus, Pod tersebut akan dihentikan dengan urutan terbalik, yaitu {N-1..0}.
- Sebelum operasi scaling diaplikasikan pada sebuah Pod, semua Pod sebelum Pod tersebut haruslah sudah dalam status Running dan Ready.
- Sebelum sebuah Pod dihentikan, semua Pod setelah Pod tersebut haruslah sudah terlebih dahulu dihentikan.
StatefulSet tidak boleh menspesifikasikan nilai dari pod.Spec.TerminationGracePeriodSeconds
menjadi 0. Hal ini tidaklah aman dan tidak disarankan. Untuk penjelasan lebih lanjut, silakan lihat penghapusan paksa Pod pada StatefulSet.
Ketika contoh nginx di atas dibuat, tiga Pod akan di-deploy dengan urutan web-0, web-1, web-2. web-1 tidak akan di-deploy sebelum web-0 berada dalam status Running dan Ready, dan web-2 tidak akan di-deploy sebelum web-1 berada dalam status Running dan Ready. Jika web-0 gagal, setelah web-1 berada dalam status Running and Ready, tapi sebelum web-2 dibuat, maka web-2 tidak akan dibuat hingga web-0 sukses dibuat ulang dan berada dalam status Running dan Ready.
Jika seorang pengguna akan melakukan mekanisme scale pada contoh di atas dengan cara melakukan patch,
pada StatefulSet sehingga replicas=1
, maka web-2 akan dihentikan terlebih dahulu.
web-1 tidak akan dihentikan hingga web-2 benar-benar berhenti dan dihapus.
Jika web-0 gagal setelah web-2 diterminasi dan berada dalam status mati,
tetapi sebelum web-1 dihentikan, maka web-1 tidak akan dihentikan hingga
web-0 berada dalam status Running dan Ready.
Kebijakan Manajemen Pod
Pada Kubernetes versi 1.7 dan setelahnya, StatefulSet mengizinkan kamu untuk
melakukan mekanisme urutan tadi menjadi lebih fleksibel dengan tetap
menjamin keunikan dan identitas yang ada melalui field .spec.podManagementPolicy
.
Manajemen OrderedReady pada Pod
Manajemen OrderedReady
pada Pod merupakan nilai default dari StatefulSet.
Hal ini akan mengimplementasikan perilaku yang dijelaskan di atas.
Manajemen Pod secara Paralel
Manajemen Pod secara paralel
akan menyebabkan kontroler StatefulSet untuk
memulai atau menghentikan semua Pod yang ada secara paralel, dan tidak
menunggu Pod berada dalam status Running dan Ready atau sudah dihentikan secara menyeluruh
sebelum me-launch atau menghentikan Pod yang lain. Opsi ini hanya akan memengaruhi operasi
scaling. Operasi pembaruan tidak akan terpengaruh.
Strategi Update
Pada Kubernetes versi 1.7 dan setelahnya, field .spec.updateStrategy
pada StatefulSet
memungkinkan-mu untuk melakukan konfigurasi dan menonaktifkan otomatisasi
rolling updates untuk container, label, resource request/limits, dan
annotation pada Pod yang ada di dalam sebuah StatefulSet.
Mekanisme Strategi Update On Delete
Mekanisme strategi update OnDelete
mengimplementasikan perilaku legasi (versi 1.6 dan sebelumnya).
Ketika sebuah field .spec.updateStrategy.type
pada StatefulSet diubah menjadi OnDelete
maka kontroler StatefulSet tidak akan secara otomatis melakukan update
pada Pod yang ada di dalam StatefulSet tersebut. Pengguna haruslah secara manual
melakukan penghapusan Pod agar kontroler membuat Pod baru yang mengandung modifikasi
yang dibuat pada field .spec.template
StatefulSet.
Mekanisme Strategi Update Rolling Updates
Mekanisme strategi update RollingUpdate
mengimplementasikan otomatisasi rolling update
untuk Pod yang ada pada StatefulSet. Strategi inilah yang diterapkan ketika .spec.updateStrategy
tidak dispesifikasikan.
Ketika field .spec.updateStrategy.type
diubah nilainya menjadi RollingUpdate
, maka
kontroler StatefulSet akan menghapus dan membuat setiap Pod di dalam StatefulSet. Kemudian
hal ini akan diterapkan dengan urutan yang sama dengan mekanisme terminasi Pod (dari nilai ordinal terbesar ke terkecil),
yang kemudian akan melakukan update Pod satu per satu. Mekanisme ini akan memastikan sebuah Pod yang di-update
berada dalam status Running dan Ready sebelum meng-update Pod dengan nilai ordinal lebih rendah.
Mekanisme Strategi Update dengan Partisi
Mekanisme strategi update RollingUpdate
dapat dipartisi, dengan cara menspesifikasikan nilai
dari .spec.updateStrategy.rollingUpdate.partition
. Jika nilai dari field ini dispesifikasikan,
maka semua Pod dengan nilai ordinal yang lebih besar atau sama dengan nilai partisi akan diupdate ketika
nilai .spec.template
pada StatefulSet diubah. Semua Pod dengan nilai ordinal yang lebih kecil
dari partisi tidak akan diupdate, dan, bahkan setelah Pod tersebut dihapus, Pod ini akan digantikan
dengan Pod versi sebelumnya. Jika nilai .spec.updateStrategy.rollingUpdate.partition
lebih besar dari
nilai .spec.replicas
, update pada .spec.template
tidak akan dipropagasi pada Pod-Pod-nya.
Pada sebagian besar kasus, kamu tidak akan perlu menggunakan partisi, tapi hal tersebut
akan sangat berguna apabila kamu ingin mekakukan mekanisme update canary.
Mekanisme Strategi Update yang Dipaksa (Forced Rollback)
Ketika menggunakan strategi update Rolling Updates dengan nilai default
Kebijakan Manajemen Pod (OrderedReady
),
hal ini memungkinkan adanya kondisi broken yang membutuhkan intervensi secara manual
agar kondisi ini dapat diperbaiki.
Jika kamu melakukan update pada template Pod untuk konfigurasi yang tidak pernah berada dalam status Running dan Ready (sebagai contohnya, apabila terdapat kode binary yang buruk atau error pada konfigurasi di level aplikasi), maka StatefulSet akan menghentikan proses rollout dan berada dalam status wait.
Dalam kondisi ini, maka templat Pod tidak akan diubah secara otomatis pada konfigurasi sebelumnya Hal ini terjadi karena adanya isu, StatefulSet akan tetap berada dalam kondisi wait untuk menunggu Pod yang bermasalah untuk menjadi Ready (yang tidak akan terjadi) dan sebelum StatefulSet ini berusaha untuk melakukan revert pada konfigurasi sebelumnya.
Setelah melakukan mekanisme revert templat, kamu juga harus menghapus semua Pod di dalam StatefulSet tersebut yang telah berusaha untuk menggunakan konfigurasi yang broken. StatefulSet akan mulai membuat Pod dengan templat konfigurasi yang sudah di-revert.
Selanjutnya
- Ikuti contoh yang ada pada bagaimana cara melakukan deployi aplikasi stateful.
- Ikuti contoh yang ada pada bagaimana cara melakukan deploy Cassandra dengan StatefulSets.
3.4.2.5 - DaemonSet
DaemonSet memastikan semua atau sebagian Node memiliki salinan sebuah Pod. Ketika Node baru ditambahkan ke klaster, Pod ditambahkan ke Node tersebut. Ketika Node dihapus dari klaster, Pod akan dibersihkan oleh garbage collector. Menghapus DaemonSet akan menghapus semua Pod yang ia buat.
Beberapa penggunaan umum DaemonSet, yaitu:
- menjalankan daemon penyimpanan di klaster, seperti
glusterd
,ceph
, di setiap Node. - menjalankan daemon pengumpulan log di semua Node, seperti
fluentd
ataulogstash
. - menjalankan daemon pemantauan Node di setiap Node, seperti Prometheus Node Exporter, Flowmill, Sysdig Agent,
collectd
, Dynatrace OneAgent, AppDynamics Agent, Datadog agent, New Relic agent, Gangliagmond
atau Instana Agent.
Dalam kasus sederhana, satu DaemonSet, mencakup semua Node, akan digunakan untuk setiap jenis daemon. Pengaturan yang lebih rumit bisa saja menggunakan lebih dari satu DaemonSet untuk satu jenis daemon, tapi dengan flag dan/atau permintaan cpu/memori yang berbeda untuk jenis hardware yang berbeda.
Menulis Spek DaemonSet
Buat DaemonSet
Kamu bisa definisikan DaemonSet dalam berkas YAML. Contohnya, berkas
daemonset.yaml
di bawah mendefinisikan DaemonSet yang menjalankan image Docker
fluentd-elasticsearch:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- Buat DaemonSet berdasarkan berkas YAML:
kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml
Field Wajib
Seperti semua konfigurasi Kubernetes lainnya, DaemonSet membutuhkan field
apiVersion
, kind
, dan metadata
. Untuk informasi umum tentang berkas konfigurasi, lihat dokumen men-deploy aplikasi,
pengaturan kontainer, dan pengelolaan objek dengan kubectl.
DaemonSet juga membutuhkan bagian .spec
.
Templat Pod
.spec.template
adalah salah satu field wajib di dalam .spec
.
.spec.template
adalah sebuah templat Pod. Skemanya benar-benar sama dengan Pod, kecuali bagian bahwa ia bersarang/nested dan tidak memiliki apiVersion
atau kind
.
Selain field wajib untuk Pod, templat Pod di DaemonSet harus menspesifikasikan label yang sesuai (lihat selektor Pod).
Templat Pod di DaemonSet harus memiliki RestartPolicy
yang bernilai Always
, atau tidak dispesifikasikan, sehingga default menjadi Always
.
DaemonSet dengan nilai Always
membuat Pod akan selalu di-restart saat kontainer
keluar/berhenti atau terjadi crash.
Selektor Pod
Field .spec.selector
adalah selektor Pod. Cara kerjanya sama dengan .spec.selector
pada Job.
Pada Kubernetes 1.8, kamu harus menspesifikasikan selektor Pod yang cocok dengan label pada .spec.template
.
Selektor Pod tidak akan lagi diberi nilai default ketika dibiarkan kosong. Nilai default selektor tidak
cocok dengan kubectl apply
. Juga, sesudah DaemonSet dibuat, .spec.selector
tidak dapat diubah.
Mengubah selektor Pod dapat menyebabkan Pod orphan yang tidak disengaja, dan membingungkan pengguna.
Objek .spec.selector
memiliki dua field:
matchLabels
- bekerja seperti.spec.selector
pada ReplicationController.matchExpressions
- bisa digunakan untuk membuat selektor yang lebih canggih dengan mendefinisikan key, daftar value dan operator yang menyatakan hubungan antara key dan value.
Ketika keduanya dispesifikasikan hasilnya diperoleh dari operasi AND.
Jika .spec.selector
dispesifikasikan, nilainya harus cocok dengan .spec.template.metadata.labels
. Konfigurasi yang tidak cocok akan ditolak oleh API.
Selain itu kamu tidak seharusnya membuat Pod apapun yang labelnya cocok dengan selektor tersebut, entah secara langsung, via DaemonSet lain, atau via workload resource lain seperti ReplicaSet. Jika kamu coba buat, Pengontrol DaemonSet akan berpikir bahwa Pod tersebut dibuat olehnya. Kubernetes tidak akan menghentikan kamu melakukannya. Contoh kasus di mana kamu mungkin melakukan ini dengan membuat Pod dengan nilai yang berbeda di sebuah Node untuk testing.
Menjalankan Pod di Sebagian Node
Jika kamu menspesifikasikan .spec.template.spec.nodeSelector
, maka controller DaemonSet akan
membuat Pod pada Node yang cocok dengan selektor
Node. Demikian juga, jika kamu menspesifikasikan .spec.template.spec.affinity
,
maka controller DaemonSet akan membuat Pod pada Node yang cocok dengan Node affinity.
Jika kamu tidak menspesifikasikan sama sekali, maka controller DaemonSet akan
membuat Pod pada semua Node.
Bagaimana Pod Daemon Dijadwalkan
Dijadwalkan oleh default scheduler
Kubernetes v1.23 [stable]
DaemonSet memastikan bahwa semua Node yang memenuhi syarat menjalankan salinan Pod. Normalnya, Node yang menjalankan Pod dipilih oleh scheduler Kubernetes. Namun, Pod DaemonSet dibuat dan dijadwalkan oleh controller DaemonSet. Hal ini mendatangkan masalah-masalah berikut:
- Inkonsistensi perilaku Pod: Pod normal yang menunggu dijadwalkan akan dibuat
dalam keadaan
Pending
, tapi Pod DaemonSet tidak seperti itu. Ini membingungkan untuk pengguna. - Pod preemption ditangani oleh default scheduler. Ketika preemption dinyalakan, controller DaemonSet akan membuat keputusan penjadwalan tanpa memperhitungkan prioritas Pod dan preemption.
ScheduleDaemonSetPods
mengizinkan kamu untuk menjadwalkan DaemonSet
menggunakan default scheduler daripada controller DaemonSet, dengan
menambahkan syarat NodeAffinity
pada Pod DaemonSet daripada syarat
.spec.nodeName
. Kemudian, default scheduler digunakan untuk mengikat Pod ke
host target. Jika afinitas Node dari Pod DaemonSet sudah ada, maka ini
akan diganti. Controller DaemonSet hanya akan melakukan operasi-operasi ini
ketika membuat atau mengubah Pod DaemonSet, dan tidak ada perubahan yang terjadi
pada spec.template
DaemonSet.
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-name
Sebagai tambahan, toleration node.kubernetes.io/unschedulable:NoSchedule
ditambahkan secara otomatis pada Pod DaemonSet. Default scheduler akan
mengabaikan Node unschedulable
ketika menjadwalkan Pod DaemonSet.
Taint dan Toleration
Meskipun Pod Daemon menghormati taint dan toleration, toleration berikut ini akan otomatis ditambahkan ke Pod DaemonSet sesuai dengan fitur yang bersangkutan.
Toleration Key | Effect | Versi | Deskripsi |
---|---|---|---|
node.kubernetes.io/not-ready |
NoExecute | 1.13+ | Pod DaemonSet tidak akan menjadi evicted ketika ada masalah Node seperti partisi jaringan. |
node.kubernetes.io/unreachable |
NoExecute | 1.13+ | Pod DaemonSet tidak akan menjadi evicted ketika ada masalah Node seperti partisi jaringan. |
node.kubernetes.io/disk-pressure |
NoSchedule | 1.8+ | |
node.kubernetes.io/memory-pressure |
NoSchedule | 1.8+ | |
node.kubernetes.io/unschedulable |
NoSchedule | 1.12+ | Pod DaemonSet mentoleransi atribut unschedulable default scheduler. |
node.kubernetes.io/network-unavailable |
NoSchedule | 1.12+ | Pod DaemonSet yang menggunakan jaringan host mentoleransi atribut network-unavailable default scheduler. |
Berkomunikasi dengan Pod Daemon
Beberapa pola yang mungkin digunakan untuk berkomunikasi dengan Pod dalam DaemonSet, yaitu:
- Push: Pod dalam DaemonSet diatur untuk mengirim pembaruan status ke servis lain, contohnya stats database. Pod ini tidak memiliki klien.
- IP Node dan Konvensi Port: Pod dalam DaemonSet dapat menggunakan
hostPort
, sehingga Pod dapat diakses menggunakan IP Node. Klien tahu daftar IP Node dengan suatu cara, dan tahu port berdasarkan konvensi. - DNS: Buat headless service dengan Pod selektor yang sama,
dan temukan DaemonSet menggunakan resource
endpoints
atau mengambil beberapa A record dari DNS. - Service: Buat Servis dengan Pod selektor yang sama, dan gunakan Servis untuk mengakses daemon pada Node random. (Tidak ada cara mengakses spesifik Node)
Melakukan Pembaruan DaemonSet
Jika label Node berubah, DaemonSet akan menambahkan Pod ke Node cocok yang baru dan menghapus Pod dari Node tidak cocok yang baru.
Kamu bisa mengubah Pod yang dibuat DaemonSet. Namun, Pod tidak membolehkan perubahan semua field. Perlu diingat, controller DaemonSet akan menggunakan templat yang asli di waktu selanjutnya Node baru (bahkan dengan nama yang sama) dibuat.
Kamu bisa menghapus DaemonSet. Jika kamu spesifikasikan --cascade=false
dengan kubectl
, maka
Pod akan dibiarkan pada Node. Jika kamu pada waktu kemudian membuat DaemonSet baru dengan selektor
yang sama, DaemonSet yang baru akan mengadopsi Pod yang sudah ada. Jika ada Pod yang perlu diganti,
DaemonSet akan mengganti sesuai dengan updateStrategy
.
Kamu bisa melakukan rolling update pada DaemonSet.
Alternatif DaemonSet
Init Scripts
Kamu mungkin menjalankan proses daemon dengan cara menjalankan mereka langsung pada Node (e.g.
menggunakan init
, upstartd
, atau systemd
). Tidak ada salahnya seperti itu. Namun, ada beberapa
keuntungan menjalankan proses daemon via DaemonSet.
- Kemampuan memantau dan mengatur log daemon dengan cara yang sama dengan aplikasi.
- Bahasa dan alat Konfigurasi yang sama (e.g. Templat Pod,
kubectl
) untuk daemon dan aplikasi. - Menjalankan daemon dalam kontainer dengan batasan resource meningkatkan isolasi antar daemon dari kontainer aplikasi. Namun, hal ini juga bisa didapat dengan menjalankan daemon dalam kontainer tapi tanpa Pod (e.g. dijalankan langsung via Docker).
Pod Polosan
Dimungkinkan untuk membuat Pod langsung dengan menspesifikasikan Node mana untuk dijalankan. Namun, DaemonSet akan menggantikan Pod yang untuk suatu alasan dihapus atau dihentikan, seperti pada saat kerusakan Node atau pemeliharaan Node yang mengganggu seperti pembaruan kernel. Oleh karena itu, kamu perlu menggunakan DaemonSet daripada membuat Pod satu per satu.
Pod Statis
Dimungkinkan untuk membuat Pod dengan menulis sebuah berkas ke direktori tertentu yang di-watch oleh Kubelet. Pod ini disebut dengan istilah Pod statis. Berbeda dengan DaemonSet, Pod statis tidak dapat dikelola menggunakan kubectl atau klien API Kubernetes yang lain. Pod statis tidak bergantung kepada apiserver, membuat Pod statis berguna pada kasus-kasus bootstrapping klaster.
Deployment
DaemonSet mirip dengan Deployment sebab mereka sama-sama membuat Pod, dan Pod yang mereka buat punya proses yang seharusnya tidak berhenti (e.g. peladen web, peladen penyimpanan)
Gunakan Deployment untuk layanan stateless, seperti frontend, di mana proses scaling naik dan turun jumlah replika dan rolling update lebih penting daripada mengatur secara tepat di host mana Pod berjalan. Gunakan DaemonSet ketika penting untuk satu salinan Pod selalu berjalan di semua atau sebagian host, dan ketika Pod perlu berjalan sebelum Pod lainnya.
3.4.2.6 - Garbage Collection
Peran daripada garbage collector Kubernetes adalah untuk menghapus objek tertentu yang sebelumnya mempunyai pemilik, tetapi tidak lagi mempunyai pemilik.
Pemilik dan dependen
Beberapa objek Kubernetes adalah pemilik dari objek lainnya. Sebagai contoh, sebuah ReplicaSet adalah pemilik dari sekumpulan Pod. Objek-objek yang dimiliki disebut dependen dari objek pemilik. Setiap objek dependen memiliki sebuah kolom metadata.ownerReferences
yang menunjuk ke objek pemilik.
Terkadang, Kubernetes menentukan nilai dari ownerReference
secara otomatis. Sebagai contoh, ketika kamu membuat sebuah ReplicaSet, Kubernetes secara otomatis akan menentukan tiap kolom ownerReference
dari tiap Pod di dalam ReplicaSet. Pada versi 1.8, Kubernetes secara otomatis menentukan nilai dari ownerReference
untuk objek yang diciptakan atau diadopsi oleh ReplicationController, ReplicaSet, StatefulSet, DaemonSet, Deployment, Job dan CronJob.
Kamu juga bisa menspesifikasikan hubungan antara pemilik dan dependen dengan cara menentukan kolom ownerReference
secara manual.
Berikut adalah berkas untuk sebuah ReplicaSet yang memiliki tiga Pod:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-repset
spec:
replicas: 3
selector:
matchLabels:
pod-is-for: garbage-collection-example
template:
metadata:
labels:
pod-is-for: garbage-collection-example
spec:
containers:
- name: nginx
image: nginx
Jika kamu membuat ReplicaSet tersebut dan kemudian melihat metadata Pod, kamu akan melihat kolom OwnerReferences:
kubectl apply -f https://k8s.io/examples/controllers/replicaset.yaml
kubectl get pods --output=yaml
Keluaran menunjukkan bahwa pemilik Pod adalah sebuah ReplicaSet bernama my-repset
:
apiVersion: v1
kind: Pod
metadata:
...
ownerReferences:
- apiVersion: apps/v1
controller: true
blockOwnerDeletion: true
kind: ReplicaSet
name: my-repset
uid: d9607e19-f88f-11e6-a518-42010a800195
...
Referensi pemilik lintas namespace tidak diperbolehkan oleh desain. Artinya:
- Dependen dengan cakupan namespace hanya bisa menspesifikasikan pemilik jika berada di namespace yang sama, dan pemilik memiliki cakupan klaster.
- Dependen dengan cakupan klaster hanya bisa menspesifikasikan pemilik yang memiliki cakupan klaster, tetapi tidak berlaku untuk pemilik yang memiliki cakupan klaster.
Mengontrol bagaimana garbage collector menghapus dependen
Ketika kamu menghapus sebuah objek, kamu bisa menspesifikasi apakah dependen objek tersebut juga dihapus secara otomatis. Menghapus dependen secara otomatis disebut cascading deletion. Cascading deletion memiliki dua mode: background dan foreground.
Foreground cascading deletion
Pada foreground cascading deletion, pertama objek utama akan memasuki keadaan "deletion in progress". Pada saat keadaan "deletion in progress", kondisi-kondisi berikut bernilai benar:
- Objek masih terlihat via REST API
deletionTimestamp
objek telah ditentukanmetadata.finalizers
objek memiliki nilaiforegroundDeletion
.
Ketika dalam keadaan "deletion in progress", garbage collector menghapus dependen dari objek. Ketika garbage collector telah menghapus semua "blocking" dependen (objek dengan ownerReference.blockOwnerDeleteion=true
), garbage collector menghapus objek pemilik.
Jika kolom ownerReferences
sebuah objek ditentukan oleh sebuah controller (seperti Deployment atau Replicaset), blockOwnerDeletion
akan ditentukan secara otomatis dan kamu tidak perlu memodifikasi kolom ini secara manual.
Background cascading deletion
Pada background cascading deletion, Kubernetes segera menghapus objek pemilik dan garbage collector kemudian menghapus dependen pada background.
Mengatur kebijakan cascading deletion
Untuk mengatur kebijakan cascading deletion, tambahkan kolom propagationPolicy
pada argumen deleteOptions
ketika menghapus sebuah Object. Nilai yang dapat digunakan adalah "Orphan", "Foreground", atau "Background".
Sebelum Kubernetes 1.9, kebijakan default dari garbage collection untuk banyak resource controller adalah orphan. Ini meliputi ReplicationController, ReplicaSet, StatefulSet, DaemonSet, dan Deployment. Untuk jenis pada kelompok versi extensions/v1beta1
, apps/v1beta1
, dan apps/v1beta2
, kecuali kamu menspesifikasikan dengan cara lain, objek dependen adalah orphan secara default. Pada Kubernetes 1.9, untuk semua jenis pada kelompok versi apps/v1
, objek dependen dihapus secara default.
Berikut sebuah contoh yang menghapus dependen di background:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
-H "Content-Type: application/json"
Berikut adalah sebuah contoh yang mengapus dependen di foreground:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
-H "Content-Type: application/json"
Berikut adalah contoh orphan yang dependen:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
-H "Content-Type: application/json"
kubectl juga mendukung cascading deletion. Untuk menghapus dependen secara otomatis dengan menggunakan kubectl, Ubah nilai --cascade
menjadi true. Untuk orphan yang dependen, ubah nilai --cascade
menjadi false. Nilai default untuk --cascade
adalah true.
Berikut adalah contoh yang membuat dependen ReplicaSet menjadi orphan:
kubectl delete replicaset my-repset --cascade=false
Catatan tambahan untuk Deployment
Sebelum versi 1.7, ketika menggunakan cascading delete dengan Deployment, kamu harus menggunakan propagationPolicy: Foreground
untuk menghapus tidak hanya ReplicaSet yang telah diciptakan, tetapi juga Pod yang mereka miliki. Jika tipe propagationPolicy tidak digunakan, hanya ReplicaSet yag akan dihapus, dan Pod akan menjadi orphan. Lihat kubeadm/#149 untuk informasi lebih lanjut.
Isu yang diketahui
Ditemukan pada #26120
Selanjutnya
3.4.2.7 - Pengendali TTL untuk Sumber Daya yang Telah Selesai Digunakan
Kubernetes v1.12 [alpha]
Pengendali TTL menyediakan mekanisme TTL yang membatasi umur dari suatu objek sumber daya yang telah selesai digunakan. Pengendali TTL untuk saat ini hanya menangani Jobs, dan nantinya bisa saja digunakan untuk sumber daya lain yang telah selesai digunakan misalnya saja Pod atau sumber daya khusus (custom resource) lainnya.
Peringatan Fitur Alpha: fitur ini tergolong datam fitur alpha dan dapat diaktifkan dengan
feature gate
TTLAfterFinished
.
Pengendali TTL
Pengendali TTL untuk saat ini hanya mendukung Job. Sebuah operator klaster
dapat menggunakan fitur ini untuk membersihkan Job yang telah dieksekusi (baik
Complete
atau Failed
) secara otomatis dengan menentukan field
.spec.ttlSecondsAfterFinished
pada Job, seperti yang tertera di
contoh.
Pengendali TTL akan berasumsi bahwa sebuah sumber daya dapat dihapus apabila
TTL dari sumber daya tersebut telah habis. Proses dihapusnya sumber daya ini
dilakukan secara berantai, dimana sumber daya lain yang
berkaitan akan ikut terhapus. Perhatikan bahwa ketika sebuah sumber daya dihapus,
siklus hidup yang ada akan menjaga bahwa finalizer akan tetap dijalankan sebagaimana mestinya.
Waktu TTL dalam detik dapat diatur kapan pun. Terdapat beberapa contoh untuk mengaktifkan field
.spec.ttlSecondsAfterFinished
pada suatu Job:
- Spesifikasikan field ini pada manifest sumber daya, sehingga Job akan dihapus secara otomatis beberapa saat setelah selesai dieksekusi.
- Aktifkan field ini pada sumber daya yang sudah selesai dieksekusi untuk menerapkan fitur ini.
- Gunakan sebuah mengubah (mutating) _admission) untuk mengaktifkan field ini secara dinamis pada saat pembuatan sumber daya. Administrator klaster dapat menggunakan hal ini untuk menjamin kebijakan (policy) TTL pada sumber daya yang telah selesai digunakan.
- Gunakan sebuah mengubah (mutating) _admission untuk mengaktifkan field ini secara dinamis setelah sumber daya selesai digunakan dan TTL didefinisikan sesuai dengan status, label, atau hal lain yang diinginkan.
Peringatan
Mengubah TTL Detik
Perhatikan bahwa periode TTL, yaitu field .spec.ttlSecondsAfterFinished
pada Job,
dapat dimodifikasi baik setelah sumber daya dibuat atau setelah selesai digunakan.
Meskipun begitu, setelah Job dapat dihapus (TTL sudah habis), sistem tidak akan
menjamin Job tersebut akan tetap ada, meskipun nilai TTL berhasil diubah.
Time Skew
Karena pengendali TTL menggunakan cap waktu (timestamp) yang disimpan di sumber daya Kubernetes untuk menentukan apakah TTL sudah habis atau belum, fitur ini tidak sensitif terhadap time skew yang ada pada klaster dan bisa saja menghapus objek pada waktu yang salah bagi objek tersebut akibat adanya time skew.
Pada Kubernetes, NTP haruslah dilakukan pada semua node untuk mecegah adanya time skew (lihat #6159). Clock tidak akan selalu tepat, meskipun begitu perbedaan yang ada haruslah diminimalisasi. Perhatikan bahwa hal ini dapat terjadi apabila TTL diaktifkan dengan nilai selain 0.
Selanjutnya
3.4.2.8 - Jobs
Sebuah Job membuat satu atau beberapa Pod dan menjamin bahwa jumlah Pod yang telah dispesifikasikan sebelumnya berhasil dijalankan. Pada saat Pod telah dihentikan, Job akan menandainya sebagai Job yang sudah berhasil dijalankan. Ketika jumlah sukses yang dispesifikasikan sebelumnya sudah terpenuhi, maka Job tersebut dianggap selesai. Menghapus sebuah Job akan menghapus semua Pod yang dibuat oleh Job tersebut.
Sebuah kasus sederhana yang dapat diberikan adalah membuat sebuah objek Job untuk menjamin sebuah Pod dijalankan hingga selesai. Objek Job ini akan membuat sebuah Pod baru apabila Pod pertama gagal atau dihapus (salah satu contohnya adalah akibat adanya kegagalan pada perangkat keras atau terjadinya reboot pada Node).
Kamu juga dapat menggunakan Job untuk menjalankan beberapa Pod secara paralel.
Menjalankan Contoh Job
Berikut merupakan contoh konfigurasi Job. Job ini melakukan komputasi π hingga digit ke 2000 kemudian memberikan hasilnya sebagai keluaran. Job tersebut memerlukan waktu 10 detik untuk dapat diselesaikan.
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
Kamu dapat menjalankan contoh tersebut dengan menjalankan perintah berikut:
kubectl apply -f https://k8s.io/examples/controllers/job.yaml
job "pi" created
Perhatikan status dari Job yang baru dibuat dengan menggunakan perintahkubectl
:
kubectl describe jobs/pi
Name: pi
Namespace: default
Selector: controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495
Labels: controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495
job-name=pi
Annotations: <none>
Parallelism: 1
Completions: 1
Start Time: Tue, 07 Jun 2016 10:56:16 +0200
Pods Statuses: 0 Running / 1 Succeeded / 0 Failed
Pod Template:
Labels: controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495
job-name=pi
Containers:
pi:
Image: perl
Port:
Command:
perl
-Mbignum=bpi
-wle
print bpi(2000)
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: pi-dtn4q
Untuk melihat Pod yang sudah selesai dari sebuah Job, kamu dapat menggunakan perintah kubectl get pods
.
Untuk menampilkan semua Pod yang merupakan bagian dari suatu Job di mesin kamu dalam bentuk yang mudah dipahami, kamu dapat menggunakan perintah berikut ini:
pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath='{.items[*].metadata.name}')
echo $pods
pi-aiw0a
Disini, selektor yang ada merupakan selektor yang sama dengan yang ada pada Job.
Opsi --output=jsonpath
menspesifikasikan bahwa ekspresi yang hanya
menampilkan nama dari setiap Pod pada list yang dikembalikan.
Untuk melihat keluaran standar dari salah satu pod:
kubectl logs $pods
Keluaran yang dihasilkan akan sama dengan:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901
Menulis Spek Job
Sama halnya dengan konfigurasi Kubernetes lainnya, sebuah Job memerlukan field
apiVersion
, kind
, dan metadata
.
Sebuah Job juga membutuhkan sebuah bagian .spec
.
Templat Pod
Field .spec.template
merupakan satu-satunya field wajib pada .spec
.
Field .spec.template
merupakan sebuah templat Pod. Field ini memiliki skema yang sama dengan yang ada pada Pod,
kecuali field ini bersifat nested dan tidak memiliki field apiVersion
atau field kind
.
Sebagai tambahan dari field wajib pada sebuah Job, sebuah tempat pod pada Job haruslah menspesifikasikan label yang sesuai (perhatikan selektor pod) dan sebuah mekanisme restart yang sesuai.
Hanya sebuah RestartPolicy
yang sesuai dengan Never
atau OnFailure
yang bersifat valid.
Selektor Pod
Field .spec.selector
bersifat opsional. Dan dalam sebagian besar kasus, kamu tidak perlu memberikan
spesifikasi untuk hal ini. Perhatikan bagian menspesifikasikan selektor Pod kamu sendiri.
Job Paralel
Terdapat tiga jenis utama dari task yang sesuai untuk dijalankan sebagai sebuah Job:
- Job non-paralel
- secara umum, hanya sebuah Pod yang dimulai, kecuali jika Pod tersebut gagal.
- Job akan dianggap sudah selesai dikerjakan apabila Pod dari Job tersebut sudah selesai dijalankan dan mengalami terminasi dengan status sukses.
- Job paralel dengan jumlah nilai penyelesaian tetap:
- berikan spesifikasi pada
.spec.completions
dengan nilai non-negatif. - Job yang ada merupakan representasi dari task yang dikerjakan, dan akan dianggap selesai apabila terdapat lebih dari satu Pod yang sukses untuk setiap nilai yang ada dalam jangkauan 1 hingga
.spec.completions
. - belum diimplementasikan saat ini: Setiap Pod diberikan nilai indeks yang berbeda di dalam jangkauan 1 hingga
.spec.completions
.
- Job paralel dengan sebuah work queue:
- jangan berikan spesifikasi pada
.spec.completions
, nilai default-nya merupakan.spec.parallelism
. - Pod yang ada haruslah dapat berkoordinasi satu sama lain atau dengan Service eksternal lain untuk menentukan apa yang setiap Pod tadi perlu lakukan. Sebagai contohnya, sebuah Pod bisa saja melakukan fetch job batch hingga N kali pada work queue
- setiap Pod secara independen mampu menentukan apakah Pod lainnya telah menyelesaikan tugasnya dengan baik atau belum, dengan kata lain suatu Job telah dikatakan selesai
- ketika Pod mana pun dari sebuah Job berhenti dalam keadaan sukses, maka tidak ada Pod lain yang akan dibuat untuk Job tersebut.
- apabila salah satu Pod sudah dihentikan sekali dalam keadaan sukses, maka Job akan ditandai sebagai sukses.
- apabila sebuah Pod sudah dihentikan dalam keadaan sukses, tidak boleh ada Pod lain yang mengerjakan task tersebut. Dengan kata lain, semua Pod tersebut haruslah dalam keadaan akan dihentikan.
Untuk sebuah Job yang non-paralel, kamu tidak perlu menspesifikasikan field .spec.completions
dan .spec.parallelism
. Ketika kedua field tersebut
dalam keadaan tidak dispesifikasikan, maka nilai defult-nya akan diubah menjadi 1.
Untuk sebuah Job dengan jumlah nilai penyelesaian tetap, kamu harus memberikan spesifikasi nilai
dari .spec.completions
dengan nilai yang diinginkan. Kamu dapat menspesifikasikan .spec.parallelism
,
atau jika kamu tidak melakukannya nilai dari field ini akan memiliki nilai default 1.
Untuk sebuah Job work queue, kamu harus meninggalkan spesifikasi field .spec.completions
menjadi kosong, serta
memberikan nilai pada .spec.parallelism
menjadi sebuah bilangan bulat non negatif.
Untuk informasi lebih lanjut mengenai bagaimana menggunakan Job dengan jenis yang berbeda, kamu dapat melihat bagian pola job.
Mengendalikan Paralelisme
Paralelisme yang diminta (.spec.parallelism
) dapat diaktifkan dengan cara
memberikan nilai bilangan bulat non-negatif. Jika tidak dispesifikasikan maka nilainya akan
secara default yaitu 1. Jika dispesifikasikan sebagai 0, maka Job akan secara otomatis dihentikan sementara
hingga nilainya dinaikkan.
Paralelisme yang sebenarnya (jumlah Pod yang dijalankan pada satu waktu tertentu) bisa saja lebih atau kurang dari nilai yang diharapkan karena adanya alasan berikut:
- Untuk Job fixed completion count, nilai sebenarnya dari jumlah Pod yang dijalankan secara paralel tidak akan melebihi jumlah
completion yang tersisa. Nilai yang lebih tinggi dari.spec.parallelism
secara efektif, akan diabaikan. - Untuk Job work queue, tidak akan ada Pod yang dimulai setelah ada Pod yang berhasil -- meskipun begitu, sisa Pod yang ada akan diizinkan untuk menyelesaikan tugasnya.
- Jika sebuah Pengontrol Job tidak memiliki waktu untuk memberikan reaksi.
- Jika sebuah controller Job gagal membuat Pod dengan alasan apa pun (kurangnya
ResourceQuota
, kurangnya permission, dkk.), maka bisa saja terdapat lebih sedikit Pod dari yang diminta. - Jika controller Job melakukan throttle pembuatan Pod karena terdapat gagalnya pembuatan Pod yang berlebihan sebelumnya pada Job yang sama.
- Ketika sebuah Pod dihentikan secara graceful, maka Pod tersebut akan membutuhkan waktu untuk berhenti.
Mengatasi Kegagalan Pod dan Container
Sebuah Container pada sebuah Pod bisa saja mengalami kegagalan karena berbagai alasan
yang berbeda, misalnya saja karena proses yang ada di dalamnya berakhir dengan exit code
yang tidak sama dengan nol, atau Container yang ada di-kill karena menyalahi batasan memori, dkk.
Jika hal ini terjadi, dan .spec.template.spec.restartPolicy = "OnFailure"
, maka Pod
akan tetap ada di dalam node, tetapi Container tersebut akan dijalankan kembali. Dengan demikian,
program kamu harus dapat mengatasi kasus dimana program tersebut di-restart secara lokal, atau jika
tidak maka spesifikasikan .spec.template.spec.restartPolicy = "Never"
. Perhatikan
lifecycle pod untuk informasi lebih lanjut mengenai restartPolicy
.
Sebuah Pod juga dapat gagal secara menyeluruh, untuk beberapa alasan yang mungkin, misalnya saja,
ketika Pod tersebut dipindahkan dari Node (ketika Node diperbarui, di-restart, dihapus, dsb.), atau
jika sebuah Container dalam Pod gagal dan .spec.template.spec.restartPolicy = "Never"
. Ketika
sebuah Pod gagal, maka controller Job akan membuat sebuah Pod baru. Ini berarti aplikasi kamu haruslah
bisa mengatasi kasus dimana aplikasimu dimulai pada Pod yang baru. Secara khusus apabila aplikasi kamu
berurusan dengan berkas temporer, locks, keluaran yang tak lengkap dan hal-hal terkait dengan
program yang dijalankan sebelumnya.
Perhatikan bahwa bahakan apabila kamu menspesifikasikan .spec.parallelism = 1
dan .spec.completions = 1
dan
.spec.template.spec.restartPolicy = "Never"
, program yang sama bisa saja tetap dijalankan lebih dari sekali.
Jika kamu menspesifikasikan .spec.parallelism
dan .spec.completions
dengan nilai yang lebih besar dari 1,
maka bisa saja terdapat keadaan dimana terdapat beberapa Pod yang dijalankan pada waktu yang sama.
Dengan demikian, Pod kamu haruslah fleksibel terhadap adanya konkurensi.
Mekanisme Kebijakan Backoff apabila Terjadi Kegagalan
Terdapat situasi dimana kamu ingin membuat suatu Job gagal
setelah dijalankan mekanisme retry beberapa kali akibat adanya kesalahan pada konfigurasi
dsb. Untuk melakukan hal tersebut, spesifikasikan .spec.backoffLimit
dengan nilai retry yang diinginkan
sebelum menerjemahkan Job dalam keadaan gagal. Secara default, nilai dari field tersebut adalah 6.
Pod yang gagal dijalankan dan terkait dengan suatu Job tertentu akan dibuat kembali oleh
controller Job dengan delay back-off eksponensial (10 detik, 20 detik, 40 detik ...)
yang dibatasi pada 6 menit. Penghitungan back-off akan diulang jika tidak terdapat Pod baru yang gagal
sebelum siklus pengecekan status Job selanjutnya.
restartPolicy = "OnFailure"
, perhatikan bahwa Container kamu yang menjalankan
Job tersebut akan dihentikan ketika limit back-off telah dicapai. Hal ini akan membuat proses debugging semakin sulit.
Dengan demikian, kami memberikan saran untuk menspesifikasikan restartPolicy = "Never"
ketika melakukan
proses debugging atau menggunakan mekanisme logging untuk menjamin keluaran
dari Job yang gagal agar tidak terus menerus hilang.
Terminasi dan Clean Up Job
Ketika sebuah Job selesai dijalankan, tidak akan ada lagi Pod yang dibuat,
meskipun begitu Pod yang ada juga tidak akan dihapus. Dengan demikian kamu masih bisa mengakses log
yang ada dari Pod yang sudah dalam status complete untuk mengecek apabila terjadi eror, warning, atau hal-hal
yang dapat digunakan untuk proses pelaporan dan identifikasi. Objek Job itu sendiri akan tetap ada,
sehingga kamu tetap bisa melihat statusnya. Penghapusan objek akan diserahkan sepenuhnya pada pengguna
apabila Job tidak lagi digunakan. Penghapusan Job dengan perintah kubectl
(misalnya, kubectl delete jobs/pi
atau kubectl delete -f ./job.yaml
).
Ketika kamu menghapus Job menggunakan perintah kubectl
, semua Pod yang terkait dengan Job tersebut akan ikut dihapus.
Secara default, sebuah Job akan dijalankan tanpa adanya interupsi kecuali terdapat Pod yang gagal, (restartPolicy=Never
) atau terdapat
Container yang dihentikan dalam kondisi error (restartPolicy=OnFailure
), suatu keadaan dimana Job akan dijalankan dengan mekanisme
yang dijelaskan di atas berdasarkan pada .spec.backoffLimit
.
Apabila .spec.backoffLimit
telah mencapai limit, maka Job akan ditandai sebagai gagal dan Pod yang saat ini sedang dijalankan juga akan dihentikan.
Cara lain untuk menghentikan sebuah Job adalah dengan mengatur deadline aktif.
Untuk melakukannya kamu dapat menspesifikasikan field .spec.activeDeadlineSeconds
dari sebuah Job dengan suatu angka dalam satuan detik. Field activeDeadlineSeconds
diterapkan pada durasi dari sebuah Job, tidak peduli seberapa banyak Pod yang dibuat.
Setelah sebuah Job mencapai limit activeDeadlineSeconds
, semua Pod yang dijalankan akan dihentikan
dan status dari Job tersebut akan berubah menjadi type: Failed
dengan reason: DeadlineExceeded
.
Perhatikan bahwa field .spec.activeDeadlineSeconds
pada Job memiliki tingkat
presedensi di atas .spec.backoffLimit
. Dengan demikian, sebuah Job
yang sedang mencoba melakukan restart pada suatu Pod-nya tidak akan melakukan
pembuatan Pod yang baru apabila Job tersebut telah mencapai limit yang didefinisikan pada
activeDeadlineSeconds
, bahkan apabila nilai dari backoffLimit
belum tercapai.
Contoh:
apiVersion: batch/v1
kind: Job
metadata:
name: pi-with-timeout
spec:
backoffLimit: 5
activeDeadlineSeconds: 100
template:
spec:
Containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
Perhatikan bahwa baik spek Job dan spek templat Pod di dalam Job memiliki field activeDeadlineSeconds
.
Pastikan kamu telah menspesifikasikan nilai tersebut pada level yang dibutuhkan.
Mekanisme Clean Up Otomatis pada Job yang Sudah Selesai
Job yang sudah selesai biasanya tidak lagi dibutuhkan di dalam sistem. Tetap menjaga keberadaan objek-objek tersebut di dalam sistem akan memberikan tekanan tambahan pada API server. Jika sebuah Job yang diatur secara langsung oleh controller dengan level yang lebih tinggi, seperti CronJob, maka Job ini dapat di-clean up oleh CronJob berdasarkan policy berbasis kapasitas yang dispesifikasikan.
Mekanisme TTL untuk Job yang Telah Selesai Dijalankan
Kubernetes v1.12 [alpha]
Salah satu cara untuk melakukan clean up Job yang telah selesai dijalankan
(baik dengan status Complete
atau Failed
) secara otomatis adalah dengan
menerapkan mekanisme TTL yang disediakan oleh
controller TTL untuk
sumber daya yang telah selesai digunakan, dengan cara menspesifikasikan
field .spec.ttlSecondsAfterFinished
dari Job tersebut.
Ketika controller TTL melakukan proses clean up pada Job, maka controller tersebut akan menghapus objek-objek terkait seperti Pod, serta Job itu sendiri. Perhatikan bahwa ketika suatu Job dihapus, maka lifecycle-nya akan menjamin, mekanisme finalizer yang ada akan tetap dihargai.
Sebagai contoh:
apiVersion: batch/v1
kind: Job
metadata:
name: pi-with-ttl
spec:
ttlSecondsAfterFinished: 100
template:
spec:
Containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
Job pi-with-ttl
akan dihapus secara otomatis, dalam jangka waktu 100
detik setelah Job tersebut selesai dijalankan.
Jika field ini dispesifikasikan sebagai 0
, maka Job akan secara otomatis dihapus
segera setelah Job tersebut selesai dijalankan. Jika field tersebut tidak dispesifikasikan,
maka Job ini tidak akan dihapus oleh controller TTL setelah Job ini selesai dijalankan.
Perhatikan bahwa mekanisme TTL ini merupakan fitur alpha, dengan gerbang fitur TTLAfterFinished
.
Untuk informasi lebih lanjut, kamu dapat membaca dokumentasi untuk
controller TTL untuk
sumber daya yang telah selesai dijalankan.
Pola Job
Sebuah objek Job dapat digunakan untuk mendukung eksekusi paralel yang dapat diandalkan pada Pod. Objek Job tidak di-desain untuk mendukung proses paralel bersifat closely-communicating, seperti yang secara umum ditemukan dalam komputasi ilmiah. Meskipun begitu objek ini mendukung set work item yang independen namun saling terkait satu sama lainnya. Ini termasuk surel yang harus dikirim, frame yang harus di-render, berkas yang harus di-transcoded, jangkauan key yang ada di dalam basis data NoSQL, dsb.
Pada suatu sistem yang kompleks, terdapat beberapa set work item yang berbeda. Di sini, kami hanya mempertimbangkan work item yang ingin digunakan oleh pengguna untuk melakukan manajemen secara bersamaan — sebuah batch job.
Terdapat beberapa perbedaan pola pada komputasi paralel, setiap pola memiliki kelebihan dan kekurangannya masing-masing. Kekurangan dan kelebihan ini dijabarkan sebagai berikut:
- Satu objek Job untuk setiap work item, atau sebuah Job untuk semua work item. Pilihan kedua akan lebih baik apabila digunakan untuk jumlah work item yang lebih besar. Sementara itu, pilihan pertama akan mengakibatkan overhead bagi pengguna dan juga sistem untuk mengaur jumlah objek Job yang cukup banyak.
- Jumlah Pod yang dibuat sesuai dengan jumlah work item atau setiap Pod dapat memproses beberapa work item sekaligus. Pilihan pertama secara umum memerlukan modifikasi lebih sedikit untuk kode dan Container yang suda ada. Pilihan kedua akan lebih baik jika digunakan untuk jumlah work item yang lebih banyak, untuk alasan yang sama dengan poin sebelumnya.
- Beberapa pendekatan menggunakan prinsip work queue. Hal ini membutuhkan sebuah service queue yang dijalankan, serta modifikasi untuk program atau Container yang sudah ada untuk mengizinkannya menggunakan working queue. Pendekatan lain akan lebih mudah untuk digunakan bagi aplikasi yang sudah ada.
Tradeoff yang dirangkum di sini, dengan kolom 2 dan 4 berkaitan dengan tradeoff yang dijelaskan di atas. Nama dari pola yang ada juga terkait dengan contoh dan deskripsi lebih lanjut.
Pola | Objek dengan satu Job | Pod yang lebih sedikit tadi work items? | Penggunaan app tanpa modifikasi? | Dapat dijalankan pada Kube versi 1.1? |
---|---|---|---|---|
Perluasan Templat Job | ✓ | ✓ | ||
Queue dengan Pod untuk setiap Work Item | ✓ | sometimes | ✓ | |
Queue dengan Variabel Pod Count | ✓ | ✓ | ✓ | |
Job Single dengan penempatan Kerja Statis | ✓ | ✓ |
Ketika kamu menspesifikasikan completion dengan .spec.completions
, setiap Pod yang dibuat oleh controller Job
memiliki spec
yang identik. Artinya
semua Pod untuk sebuah task akan memiliki perintah yang sama serta image, volume, serta variabel environment yang (hampir) sama.
Pola ini merupakan salah satu cara berbeda yang diterapkan untuk mengatur Pod agar dapat bekerja untuk hal yang berbeda-beda.
Tabel ini menunjukkan pengaturan yang dibutuhkan untuk .spec.parallelism
dan .spec.completions
bagi setiap pola.
Disini, W
merupakan jumlah dari work item.
Pattern | .spec.completions |
.spec.parallelism |
---|---|---|
Job Template Expansion | 1 | should be 1 |
Queue with Pod Per Work Item | W | any |
Queue with Variable Pod Count | 1 | any |
Single Job with Static Work Assignment | W | any |
Penggunaan Tingkat Lanjut
Menspesifikasikan Selektor Pod Kamu Sendiri
Secara umum, ketika kamu membuat sebuah objek Job, kamu
tidak menspesifikasikan .spec.selector
. Sistem akan memberikan nilai
default pada field ini ketika Job dibuat. Sistem akan memilih nilai dari selektor yang ada
dan memastikan nilainya tidak akan beririsan dengan Job lainnya.
Meskipun demikian, pada beberapa kasus, kamu bisa saja memiliki kebutuhan untuk meng-override
nilai dari selektor ini. Untuk melakukannya, kamu dapat menspesifikasikan .spec.selector
dari Job.
Berhati-hatilah ketika kamu melakukan proses ini. Jika kamu menspesifikasikan sebuah label
selektor yang tidak unik pada Pod yang ada di dalam Job tersebut, serta sesuai dengan Pod yang tidak
terkait dengan Job tadi, maka Pod dari Job yang tidak terkait dengan Job tadi akna dihapus, atau Job ini
akan menghitung completion dari Pod lain sebagai tolak ukur suksesnya Job tersebut, atau bisa saja salah satu
atau kedua Job tidak dapat membuat Pod baru yang digunakan untuk menyelesaikan Job tersebut.
Jika selektor yang tidak unik dipilih, maka controller lain (misalnya ReplicationController) dan Pod
yang ada di dalamnya bisa saja memiliki perilaku yang tidak dapat diprediksi. Kubernetes tidak akan
mencegah kemungkinan terjadinya hal ini ketika kamu menspesifikasikan nilai .spec.selector
.
Berikut merupakan contoh skenario dimana kamu ingin menggunakan fitur ini.
Misalnya saja Job dengan nama old
sudah dijalankan.
Dan kamu ingin Pod yang sudah dijalankan untuk tetap berada pada state tersebut,
tapi kamu juga ingin Pod selanjutnya yang dibuat untuk menggunakan templat Pod yang berbeda dan agar
Job tersebut memiliki nama yang berbeda. Kamu tidak dapat mengubah Job karena field ini
merupakan nilai yang tidak bisa diubah. Dengan demikian, kamu menghapus Job old
tetapi tetap membiarkan Pod yang ada untuk jalan, menggunakan perintah kubectl delete jobs/old --cascade=false
.
Sebelum menghapus Job tadi, kamu mencatat selektor yang digunakan oleh Job tadi:
kubectl get job old -o yaml
kind: Job
metadata:
name: old
...
spec:
selector:
matchLabels:
controller-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
...
Kemudian kamu membuat sebuah Job baru dengan nama new
dan kamu secara eksplisit menspesifikasikan selektor yang sama.
Karena Pod dengan selektor yang sama memiliki label controller-uid=a8f3d00d-c6d2-11e5-9f87-42010af00002
,
maka Pod-Pod lama tadi dikendalikan juga oleh Job new
.
Kamu harus menspesifikasikan manualSelector: true
pada Job yang baru
karena kamu tidak menggunakan selektor yang diberikan secara default oleh sistem.
kind: Job
metadata:
name: new
...
spec:
manualSelector: true
selector:
matchLabels:
controller-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
...
Job yang baru tadi kemudian akan memiliki uid yang berbeda dari a8f3d00d-c6d2-11e5-9f87-42010af00002
. Pengaturan
manualSelector: true
memberikan perintah pada sistem bahwa kamu mengetahui apa yang kamu lakukan
dan untuk mengizikan ketidaksesuaian ini untuk terjadi.
Alternatif
Pod Polosan
Ketika node dimana Pod dijalankan berada dalam kondisi reboot atau gagal, Pod tadi akan dihentikan dan tidak akan di-restart. Meskipun demikian, sebuah Job akan membuat Pod baru yang menggantikan Pod lama yang dihentikan. Untuk alasan inilah, kami memberikan rekomendasi agar kamu menggunakan sebuah Job dibandingkan dengan Pod yang biasa, bahkan jika aplikasi yang kamu gunakan hanya memerlukan sebuah Pod.
Replication Controller
Job merupakan komplemen dari Replication Controller. Sebuah Replication Controller mengatur Pod yang diharapkan untuk tidak dihentikan (misalnya, web server), dan sebuah Job mengatur Pod yang diharapkan untuk berhenti (misalnya, batch task).
Seperti yang sudah dibahas pada Lifecycle Pod, Job
hanya pantas
digunakan untuk Pod dengan RestartPolicy
yang sama dengan OnFailure
atau Never
.
(Perhatikan bahwa: Jika RestartPolicy
tidak dispesifikasikan, nilai defaultnya adalah Always
.)
Job Tunggal akan menginisiasi Kontroller Pod
Pola lain yang mungkin diterapkan adalah untuk sebuah Job tunggal untuk membuat sebuah Pod yang kemudian akan membuat Pod lainnya, bersifat selayaknya controller kustom bagi Pod tersebut. Hal ini mengizinkan fleksibilitas optimal, tetapi cukup kompleks untuk digunakan dan memiliki integrasi terbatas dengan Kubernetes.
Salah satu contoh dari pola ini adalah sebuah Job yang akan menginisiasi sebuah Pod yang menjalankan script yang kemudian akan menjalankan controller master Spark (kamu dapat melihatnya di contoh Spark), yang menjalankan driver Spark, dan kemudian melakukan mekanisme clean up.
Keuntungan dari pendekatan ini adalah proses keseluruhan yang memiliki jaminan completion dari sebuah Job, tetapi kontrol secara mutlak atas Pod yang dibuat serta tugas yang diberikan pada Pod tersebut.
CronJob
Kamu dapat menggunakan CronJob
untuk membuat Job yang akan
dijalankan pada waktu/tanggal yang spesifik, mirip dengan perangkat lunak cron
yang ada pada Unix.
3.4.2.9 - CronJob
Suatu CronJob menciptakan Job yang dijadwalkan berdasarkan waktu tertentu.
Satu objek CronJob sepadan dengan satu baris pada file crontab (cron table). CronJob tersebut menjalankan suatu pekerjaan secara berkala pada waktu tertentu, dituliskan dalam format Cron.
schedule:
pada CronJob mengikuti zona waktu dari master di mana Job diinisiasi.
Untuk panduan dalam berkreasi dengan cron job, dan contoh spec file untuk suatu cron job, lihat Menjalankan otomasi task dengan cron job.
Limitasi Cron Job
Suatu cron job menciptakan kurang lebih satu objek Job setiap penjadwalan. Istilah yang digunakan adalah "kurang lebih" karena terdapat beberapa kasus yang menyebabkan dua Job terbuat, atau tidak ada Job sama sekali yang terbuat. Kemungkinan-kemungkinan seperti itu memang diusahakan untuk tidak sering terjadi, tapi tidak ada jaminan kemungkinan-kemungkinan tersebut tidak akan pernah terjadi. Oleh karena itu, Job sudah sepantasnya memiliki sifat idempoten.
Jika pengaturan startingDeadlineSeconds
menggunakan nilai yang besar atau tidak diatur (menggunakan nilai default)
dan jika pengaturan concurrencyPolicy
dijadikan Allow
, Job yang terbuat akan dijalankan paling tidak satu kali.
CronJob controller memeriksa berapa banyak jadwal yang terlewatkan sejak waktu terakhir eksekusi hingga saat ini. Jika terdapat lebih dari 100 jadwal yang terlewat, maka CronJob controller tidak memulai Job dan mencatat kesalahan:
Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew.
Perlu diingat bahwa jika pengaturan startingDeadlineSeconds
memiliki suatu nilai (bukan nil
), CronJob controller akan menghitung berapa banyak Job yang terlewatkan dari sejak startingDeadlineSeconds
hingga sekarang dan bukan sejak waktu terakhir eksekusi. Misalnya: Jika startingDeadlineSeconds
memiliki nilai 200
, CronJob controller akan menghitung berapa banyak Job yang terlewatkan dalam 200 detik terakhir.
Suatu CronJob dianggap terlewat jika ia gagal diciptakan pada waktu yang semestinya. Misalnya: Jika pengaturan concurrencyPolicy
dijadikan Forbid
dan suatu CronJob dicoba dijadwalkan saat masih ada penjadwalan sebelumnya yang masih berjalan, maka ia akan dianggap terlewat.
Contoh: Suatu CronJob akan menjadwalkan Job baru tiap satu menit dimulai sejak 08:30:00
, dan startingDeadlineSeconds
tidak diatur.
Jika CronJob controller tidak aktif dari 08:29:00
sampai 10:21:00
, Job tidak akan dijalankan karena jumlah Job yang terlewat
sudah lebih dari 100.
Sebagai ilustrasi lebih lanjut, misalkan suatu CronJob diatur untuk menjadwalkan Job baru setiap satu menit dimulai sejak 08:30:00
,
dan startingDeadlineSeconds
memiliki nilai 200
. Jika CronJob controller tidak aktif seperti pada contoh sebelumnya (08:29:00
sampai 10:21:00
),
Job akan tetap dijalankan pada 10:22:00. Hal ini terjadi karena CronJob controller memeriksa banyaknya jadwal yang terlewatkan pada 200 detik terakhir
(dalam kasus ini: 3 jadwal terlewat), dan bukan dari sejak waktu eksekusi terakhir.
CronJob hanya bertanggung-jawab untuk menciptakan Job yang sesuai dengan jadwalnya sendiri, dan Job tersebut bertanggung jawab terhadap pengelolaan Pod yang direpresentasikan olehnya.
3.5 - Services, Load Balancing, dan Jaringan
3.5.1 - Service
Pod
pada Kubernetes bersifat mortal.
Artinya apabila pod-pod tersebut dibuat dan kemudian mati, pod-pod tersebut
tidak akan dihidupkan kembali. ReplicaSets
secara
khusus bertugas membuat dan menghapus Pod
secara dinamis (misalnya, pada proses scaling out atau scaling in).
Meskipun setiap Pod
memiliki alamat IP-nya masing-masing, kamu tidak dapat mengandalkan alamat IP
yang diberikan pada pod-pod tersebut, karena alamat IP yang diberikan tidak stabil.
Hal ini kemudian menimbulkan pertanyaan baru: apabila sebuah sekumpulan Pod
(yang selanjutnya kita sebut backend)
menyediakan service bagi sebuah sekumpulan Pod
lain (yang selanjutnya kita sebut frontend) di dalam
klaster Kubernetes, bagaimana cara frontend menemukan backend mana yang digunakan?
Inilah alasan kenapa Service
ada.
Sebuah Service
pada Kubernetes adalah sebuah abstraksi yang memberikan definisi
set logis yang terdiri beberapa Pod
serta policy bagaimana cara kamu mengakses sekumpulan Pod
tadi - seringkali disebut sebagai microservices.
Set Pod
yang dirujuk oleh suatu Service
(biasanya) ditentukan oleh sebuah Label Selector
(lihat penjelasan di bawah untuk mengetahui alasan kenapa kamu mungkin saja membutuhkan Service
tanpa
sebuah selector).
Sebagai contoh, misalnya terdapat sebuah backend yang menyediakan fungsionalitas image-processing
yang memiliki 3 buah replica. Replica-replica tadi sifatnya sepadan - dengan kata lain frontend
tidak peduli backend manakah yang digunakan. Meskipun Pod
penyusun sekumpulan backend bisa berubah,
frontend tidak perlu peduli bagaimana proses ini dijalankan atau menyimpan list dari backend-backend
yang ada saat itu. Service
memiliki tujuan untuk decouple mekanisme ini.
Untuk aplikasi yang dijalankan di atas Kubernetes, Kubernetes menyediakan API endpoint sederhana
yang terus diubah apabila state sebuah sekumpulan Pod
di dalam suatu Service
berubah. Untuk
aplikasi non-native, Kubernetes menyediakan bridge yang berbasis virtual-IP bagi Service
yang diarahkan pada Pod
backend.
Mendefinisikan sebuah Service
Sebuah Service
di Kubernetes adalah sebuah objek REST, layaknya sebuah Pod
. Seperti semua
objek REST, definisi Service
dapat dikirim dengan method POST pada apiserver untuk membuat
sebuah instans baru. Sebagai contoh, misalnya saja kamu memiliki satu sekumpulan Pod
yang mengekspos port
9376 dan memiliki label "app=MyApp"
.
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
Spesifikasi ini akan ditranslasikan sebagai sebuah objek Service
baru dengan nama "my-service"
dengan target port 9376 pada setiap Pod
yang memiliki label "app=MyApp"
. Service
ini
juga akan memiliki alamat IP tersendiri (yang terkadang disebut sebagai "cluster IP"), yang nantinya
akan digunakan oleh service proxy (lihat di bagian bawah). Selector pada Service
akan selalu dievaluasi
dan hasilnya akan kembali dikirim dengan menggunakan method POST ke objek Endpoints
yang juga disebut "my-service"
.
Perhatikan bahwa sebuah Service
dapat melakukan pemetaan setiap incoming port pada targetPort
mana pun. Secara default, field targetPort
akan memiliki value yang sama dengan value dari field port
.
Hal menarik lainnya adalah value dari targetPort
bisa saja berupa string yang merujuk pada nama
dari port yang didefinisikan pada Pod
backend. Nomor port yang diberikan pada port dengan nama
tadi bisa saja memiliki nilai yang berbeda di setiap Pod
backend. Hal ini memberikan fleksibilitas
pada saat kamu melakukan deploy atau melakukan perubahan terhadap Service
. Misalnya saja suatu saat
kamu ingin mengubah nomor port yang ada pada Pod
backend pada rilis selanjutnya tanpa menyebabkan
permasalahan pada sisi klien.
Secara default, protokol yang digunakan pada service adalah TCP
, tapi kamu bisa saja menggunakan
protokol yang tersedia. Karena banyak Service
memiliki kebutuhan untuk
mengekspos lebih dari sebuah port, Kubernetes menawarkan definisi multiple port pada sebuah objek
Service. Setiap definisi port dapat memiliki protokol yang berbeda.
Service
tanpa selector
Secara umum, Service
memberikan abstraksi mekanisme yang dilakukan untuk mengakses Pod
, tapi
mereka juga melakukan abstraksi bagi backend lainnya. Misalnya saja:
- Kamu ingin memiliki sebuah basis data eksternal di environment production tapi pada tahap test, kamu ingin menggunakan basis datamu sendiri.
- Kamu ingin merujuk service kamu pada service lainnya yang berada pada Namespace yang berbeda atau bahkan klaster yang berbeda.
- Kamu melakukan migrasi workloads ke Kubernetes dan beberapa backend yang kamu miliki masih berada di luar klaster Kubernetes.
Berdasarkan skenario-skenario di atas, kamu dapat membuat sebuah Service
tanpa selector:
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
Karena Service
ini tidak memiliki selector, objek Endpoints
bagi Service
ini tidak akan dibuat.
Dengan demikian, kamu bisa membuat Endpoints
yang kamu inginkan:
kind: Endpoints
apiVersion: v1
metadata:
name: my-service
subsets:
- addresses:
- ip: 1.2.3.4
ports:
- port: 9376
Endpoints
tidak boleh berupa
loopback (127.0.0.0/8), link-local (169.254.0.0/16), atau link-local multicast (224.0.0.0/24).
Alamat IP tersebut juga tidak boleh berupa cluster IP dari Service
Kubernetes lainnya,
karena kube-proxy
belum menyediakan dukungan IP virtual sebagai destination.
Cara mengakses suatu Service
tanpa selector sama saja dengan mengakses suatu Service
dengan selector. Trafik yang ada akan di-route ke Endpoints
yang dispesifikasikan oleh
pengguna (dalam contoh kali ini adalah 1.2.3.4:9376
).
Sebuah ExternalName
Service
merupakan kasus spesial dari Service
dimana Service
tidak memiliki selector dan menggunakan penamaan DNS. Untuk
informasi lebih lanjut silahkan baca bagian ExternalName.
IP Virtual dan proxy Service
Setiap node di klaster Kubernetes menjalankan kube-proxy
. kube-proxy
bertanggung jawab terhadap implementasi IP virtual bagi Services dengan tipe
selain ExternalName
.
Pada Kubernetes versi v1.0, Services adalah "layer 4" (TCP/UDP pada IP), proxy
yang digunakan murni berada pada userspace. Pada Kubernetes v1.1, API Ingress
ditambahkan untuk merepresentasikan "layer 7"(HTTP), proxy iptables
juga ditambahkan
dan menjadi mode operasi default sejak Kubernetes v1.2. Pada Kubernetes v1.8.0-beta.0,
proxy ipvs juga ditambahkan.
Mode Proxy: userspace
Pada mode ini, kube-proxy
mengamati master Kubernetes apabila terjadi penambahan
atau penghapusan objek Service
dan Endpoints
. Untuk setiap Service
, kube-proxy
akan membuka sebuah port (yang dipilih secara acak) pada node lokal. Koneksi
pada "proxy port" ini akan dihubungkan pada salah satu Pod
backend dari Service
(yang tercatat pada Endpoints
). Pod
backend yang akan digunakan akan diputuskan berdasarkan
SessionAffinity
pada Service
. Langkah terakhir yang dilakukan oleh kube-proxy
adalah melakukan instalasi rules iptables
yang akan mengarahkan trafik yang ada pada
clusterIP
(IP virtual) dan port dari Service
serta melakukan redirect trafik ke proxy
yang memproksikan Pod
backend. Secara default, mekanisme routing yang dipakai adalah
round robin.
Mode Proxy: iptables
Pada mode ini, kube-proxy
mengamati master Kubernetes apabila terjadi penambahan
atau penghapusan objek Service
dan Endpoints
. Untuk setiap Service
,
kube-proxy
akan melakukan instalasi rules iptables
yang akan mengarahkan
trafik ke clusterIP
(IP virtual) dan port dari Service
. Untuk setiap objek Endpoints
,
kube-proxy
akan melakukan instalasi rules iptables
yang akan memilih satu buah Pod
backend. Secara default, pemilihan backend ini dilakukan secara acak.
Tentu saja, iptables
yang digunakan tidak boleh melakukan switching
antara userspace dan kernelspace, mekanisme ini harus lebih kokoh dan lebih cepat
dibandingkan dengan userspace proxy. Meskipun begitu, berbeda dengan mekanisme
proxy userspace, proxy iptables
tidak bisa secara langsung menjalankan mekanisme
retry ke Pod
lain apabila Pod
yang sudah dipilih sebelumnya tidak memberikan respons,
dengan kata lain hal ini akan sangat bergantung pada
readiness probes.
Mode Proxy: ipvs
Kubernetes v1.9 [beta]
Pada mode ini, kube-proxy
mengamati Services dan Endpoints
, kemudian memanggil
interface netlink untuk membuat rules ipvs yang sesuai serta melakukan sinkronisasi
rules ipvs dengan Services dan Endpoints
Kubernetes secara periodik, untuk memastikan
status ipvs konsisten dengan apa yang diharapkan. Ketika sebuah Services diakses,
trafik yang ada akan diarahkan ke salah satu Pod
backend.
Sama halnya dengan iptables
, ipvs juga berdasarkan pada fungsi hook netfilter,
bedanya adalah ipvs menggunakan struktur data hash table dan bekerja di kernelspace.
Dengan kata lain ipvs melakukan redirect trafik dengan lebih cepat dan dengan performa yang lebih
baik ketika melakukan sinkronisasi rules proxy. Selain itu, ipvs juga menyediakan
lebih banyak opsi algoritma load balancing:
rr
: round-robinlc
: least connectiondh
: destination hashingsh
: source hashingsed
: shortest expected delaynq
: never queue
kube-proxy
dijalankan. Ketika kube-proxy
dijalankan dengan mode proxy ipvs,
kube-proxy
akan melakukan proses validasi, apakah module IPVS sudah diinstal di node,
jika module tersebut belum diinstal, maka kube-proxy
akan menggunakan mode iptables
.
Dari sekian model proxy yang ada, trafik inbound apa pun yang ada diterima oleh IP:Port pada Service
akan dilanjutkan melalui proxy pada backend yang sesuai, dan klien tidak perlu mengetahui
apa informasi mendetail soal Kubernetes, Service
, atau Pod
. afinitas session (session affinity) berbasis
Client-IP dapat dipilih dengan cara menerapkan nilai "ClientIP" pada service.spec.sessionAffinity
(nilai default untuk hal ini adalah "None"), kamu juga dapat mengatur nilai maximum session
timeout yang ada dengan mengatur opsi service.spec.sessionAffinityConfig.clientIP.timeoutSeconds
jika
sebelumnya kamu sudah menerapkan nilai "ClusterIP" pada service.spec.sessionAffinity
(nilai default untuk opsi ini adalah "10800").
Multi-Port Services
Banyak Services dengan kebutuhan untuk mengekspos lebih dari satu port.
Untuk kebutuhan inilah, Kubernetes mendukung multiple port definitions pada objek Service
.
Ketika menggunakan multiple port, kamu harus memberikan nama pada setiap port yang didefinisikan,
sehingga Endpoint yang dibentuk tidak ambigu. Contoh:
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
Perhatikan bahwa penamaan port hanya boleh terdiri dari karakter alphanumeric lowercase
dan -, serta harus dimulai dan diakhiri dengan karakter alphanumeric, misalnya saja 123-abc
dan web
merupakan penamaan yang valid, tapi 123_abc
dan -web
bukan merupakan penamaan yang valid.
Memilih sendiri alamat IP yang kamu inginkan
Kamu dapat memberikan spesifikasi alamat cluster IP yang kamu inginkan
sebagai bagian dari request pembuatan objek Service
. Untuk melakukan hal ini,
kamu harus mengisi fields .spec.clusterIP
field. Contoh penggunaannya adalah sebagai berikut,
misalnya saja kamu sudah memiliki entry DNS yang ingin kamu gunakan kembali,
atau sebuah sistem legacy yang sudah diatur pada alamat IP spesifik
dan sulit untuk diubah. Alamat IP yang ingin digunakan pengguna haruslah merupakan alamat IP
yang valid dan berada di dalam range CIDR service-cluster-ip-range
yang dispesifikasikan di dalam
penanda yang diberikan apiserver. Jika value yang diberikan tidak valid, apiserver akan
mengembalikan response code HTTP 422 yang mengindikasikan value yang diberikan tidak valid.
Mengapa tidak menggunakan DNS round-robin?
Pertanyaan yang selalu muncul adalah kenapa kita menggunakan IP virtual dan bukan DNS round-robin standar? Terdapat beberapa alasan dibalik semua itu:
- Terdapat sejarah panjang dimana library DNS tidak mengikuti TTL DNS dan melakukan caching hasil dari lookup yang dilakukan.
- Banyak aplikasi yang melakukan lookup DNS hanya sekali dan kemudian melakukan cache hasil yang diperoleh.
- Bahkan apabila aplikasi dan library melakukan resolusi ulang yang proper, load dari setiap klien yang melakukan resolusi ulang DNS akan sulit untuk di manage.
Kami berusaha untuk mengurangi ketertarikan pengguna untuk melakukan yang mungkin akan menyusahkan pengguna. Dengan demikian, apabila terdapat justifikasi yang cukup kuat, kami mungkin saja memberikan implementasi alternatif yang ada.
Discovering services
Kubernetes mendukung 2 buah mode primer untuk melakukan Service
- variabel environment dan DNS.
Variabel Environment
Ketika sebuah Pod
dijalankan pada node, kubelet menambahkan seperangkat variabel environment
untuk setiap Service
yang aktif. Environment yang didukung adalah Docker links compatible variabel (perhatikan
makeLinkVariables)
dan variabel {SVCNAME}_SERVICE_HOST
dan {SVCNAME}_SERVICE_PORT
, dinama nama Service
akan diubah
menjadi huruf kapital dan tanda minus akan diubah menjadi underscore.
Sebagai contoh, Service
"redis-master"
yang mengekspos port TCP 6379 serta alamat
cluster IP 10.0.0.11 akan memiliki environment sebagai berikut:
REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11
Hal ini merupakan kebutuhan yang urutannya harus diperhatikan - Service
apa pun yang
akan diakses oleh sebuah Pod
harus dibuat sebelum Pod
tersebut dibuat,
jika tidak variabel environment tidak akan diinisiasi.
Meskipun begitu, DNS tidak memiliki keterbatasan ini.
DNS
Salah satu add-on opsional
(meskipun sangat dianjurkan) adalah server DNS. Server DNS bertugas untuk mengamati apakah
terdapat objek Service
baru yang dibuat dan kemudian bertugas menyediakan DNS baru untuk
Service tersebut. Jika DNS ini diaktifkan untuk seluruh klaster, maka semua Pod
akan secara otomatis
dapat melakukan resolusi DNS.
Sebagai contoh, apabila kamu memiliki sebuah Service
dengan nama "my-service"
pada Namespace
"my-ns", maka record DNS "my-service.my-ns"
akan dibuat. Pod
yang berada di dalam
Namespace "my-ns" dapat langsung melakukan lookup dengan hanya menggunakan "my-service"
.
Sedangkan Pod
yang berada di luar Namespace my-ns" harus menggunakan "my-service.my-ns"
.
Hasil dari resolusi ini menrupakan cluster IP.
Kubernetes juga menyediakan record DNS SRV (service) untuk named ports. Jika
Service "my-service.my-ns"
memiliki port dengan nama "http"
dengan protokol TCP
,
kamu dapat melakukan query DNS SRV untuk "_http._tcp.my-service.my-ns"
untuk mengetahui
nomor port yang digunakan oleh http.
Server DNS Kubernetes adalah satu-satunya cara untuk mengakses
Service dengan tipe ExternalName
. Informasi lebih lanjut tersedia di
DNS Pods dan Services.
Service
headless
Terkadang kamu tidak membutuhkan mekanisme load-balancing dan sebuah single IP Sevice.
Dalam kasus ini, kamu dapat membuat "headless" Service
dengan cara memberikan spesifikasi
None pada cluster IP (.spec.clusterIP
).
Opsi ini memungkinkan pengguna mengurangi ketergantungan terhadap sistem Kubernetes dengan cara memberikan kebebasan untuk mekanisme service discovery. Aplikasi akan tetap membutuhkan mekanisme self-registration dan adapter service discovery lain yang dapat digunakan berdasarkan API ini.
Untuk Service
"headless" alokasi cluster IP tidak dilakukan dan kube-proxy
tidak me-manage Service-Service, serta tidak terdapat mekanisme load balancing
yang dilakukan. Bagaimana konfigurasi otomatis bagi DNS dilakukan bergantung pada
apakah Service
tersebut memiliki selector yang dispesifikasikan.
Dengan selector
Untuk Service
"headless" dengan selector, kontroler Endpoints
akan membuat suatu
record Endpoints
di API, serta melakukan modifikasi konfigurasi DNS untuk mengembalikan
A records (alamat) yang merujuk secara langsung pada Pod
backend.
Tanpa selector
Untuk Service
"headless" tanpa selector, kontroler Endpoints
tidak akan membuat record Enpoints. Meskipun demikian,
sistem DNS tetap melakukan konfigurasi salah satu dari:
- record CNAME untuk
ExternalName
-tipe services. - record untuk semua
Endpoints
yang memiliki namaService
yang sama, untuk tipe lainnya.
Mekanisme publish Service
- jenis-jenis Service
Untuk beberapa bagian dari aplikasi yang kamu miliki (misalnya saja, frontend),
bisa saja kamu memiliki kebutuhan untuk mengekspos Service
yang kamu miliki
ke alamat IP eksternal (di luar klaster Kubernetes).
ServiceTypes
yang ada pada Kubernetes memungkinkan kamu untuk menentukan
jenis Service
apakah yang kamu butuhkan. Secara default, jenis Service
yang diberikan adalah ClusterIP
.
Value dan perilaku dari tipe Service
dijelaskan sebagai berikut:
ClusterIP
: MengeksposService
ke range alamat IP di dalam klaster. Apabila kamu memilih value iniService
yang kamu miliki hanya dapat diakses secara internal. tipe ini adalah default value dari ServiceType.NodePort
: MengeksposService
pada setiap IP node pada port statis atau port yang sama. SebuahService
ClusterIP
, yang manaService
NodePort
akan di-route , dibuat secara otomatis. Kamu dapat mengaksesService
dengan tipe ini, dari luar klaster melalui<NodeIP>:<NodePort>
.LoadBalancer
: MengeksposService
secara eksternal dengan menggunakanLoadBalancer
yang disediakan oleh penyedia layanan cloud.Service
dengan tipeNodePort
danClusterIP
, dimana trafik akan di-route, akan dibuat secara otomatis.ExternalName
: Melakukan pemetaanService
ke konten dari fieldexternalName
(misalnya:foo.bar.example.com
), dengan cara mengembalikan catatanCNAME
beserta value-nya. Tidak ada metode proxy apa pun yang diaktifkan. Mekanisme ini setidaknya membutuhkankube-dns
versi 1.7.
Type NodePort
Jika kamu menerapkan value NodePort
pada field type, master Kubernetes akan mengalokasikan
port dari range yang dispesifikasikan oleh penanda --service-node-port-range
(secara default, 30000-32767)
dan setiap Node akan memproksikan port tersebut (setiap Node akan memiliki nomor port yang sama) ke Service
yang kamu miliki. Port
tersebut akan dilaporkan pada field .spec.ports[*].nodePort
di Service
kamu.
Jika kamu ingin memberikan spesifikasi IP tertentu untuk melakukan poxy pada port.
kamu dapat mengatur penanda --nodeport-addresses
pada kube-proxy
untuk range alamat IP
tertentu (mekanisme ini didukung sejak v1.10). Sebuah daftar yang dipisahkan koma (misalnya, 10.0.0.0/8, 1.2.3.4/32)
digunakan untuk mem-filter alamat IP lokal ke node ini. Misalnya saja kamu memulai kube-proxy
dengan penanda
--nodeport-addresses=127.0.0.0/8
, maka kube-proxy
hanya akan memilih interface loopback untuk Service
dengan tipe
NodePort
. Penanda --nodeport-addresses
memiliki nilai default kosong ([]
), yang artinya akan memilih semua interface yang ada
dan sesuai dengan perilaku NodePort
default.
Jika kamu menginginkan nomor port yang berbeda, kamu dapat memberikan spesifikasi value dari field nodePort, dan sistem yang ada akan mengalokasikan port tersebut untuk kamu, jika port tersebut belum digunakan (perhatikan bahwa jika kamu menggunakan teknik ini, kamu perlu mempertimbangkan collision yang mungkin terjadi dan bagaimana cara mengatasi hal tersebut) atau transaksi API yang dilakukan akan gagal.
Hal ini memberikan kebebasan bagi pengembang untuk memilih load balancer yang akan digunakan, terutama apabila load balancer yang ingin digunakan belum didukung sepenuhnya oleh Kubernetes.
Perhatikan bahwa Service
dapat diakses baik dengan menggunakan <NodeIP>:spec.ports[*].nodePort
atau .spec.clusterIP:spec.ports[*].port
. (Jika penanda --nodeport-addresses
diterapkan,
Type LoadBalancer
Pada penyedia layanan cloud yang menyediakan pilihan load balancer eksternal, pengaturan field type
ke LoadBalancer
akan secara otomatis melakukan proses provision load balancer untuk Service
yang kamu buat.
Informasi mengenai load balancer yang dibuat akan ditampilkan pada field .status.loadBalancer
pada Service
kamu. Contohnya:
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
clusterIP: 10.0.171.239
loadBalancerIP: 78.11.24.19
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 146.148.47.155
Trafik dari load balancer eksternal akan diarahkan pada Pod
backend, meskipun mekanisme
bagaimana hal ini dilakukan bergantung pada penyedia layanan cloud. Beberapa penyedia layanan
cloud mengizinkan konfigurasi untuk value loadBalancerIP
. Dalam kasus tersebut, load balancer akan dibuat
dengan loadbalancerIP yang dispesifikasikan. Jika value dari loadBalancerIP
tidak dispesifikasikan.
sebuah IP sementara akan diberikan pada loadBalancer. Jika loadBalancerIP
dispesifikasikan,
tetapi penyedia layanan cloud tidak mendukung hal ini, maka field yang ada akan diabaikan.
Catatan Khusus untuk Azure: Untuk spesifikasi loadBalancerIP
publik yang didefinisikan oleh pengguna,
sebuah alamat IP statis publik akan disediakan terlebih dahulu, dan alamat IP tersebut harus berada di
resource group dari resource yang secara otomatis dibuat oleh klaster. Misalnya saja, MC_myResourceGroup_myAKSCluster_eastus
.
Berikan spesifikasi alamat IP sebagai loadBalancerIP
. Pastikan kamu sudah melakukan update pada
securityGroupName pada file konfigurasi penyedia layanan cloud.
Untuk informasi lebih lanjut mengenai permission untuk CreatingLoadBalancerFailed
kamu dapat membaca troubleshooting untuk
Penggunaan alamat IP statis pada load balancer Azure Kubernetes Service (AKS) atau
CreatingLoadBalancerFailed pada klaster AKS dengan advanced networking.
Service
akan tetap diterima, meskipun proses pembuatan load balancer itu sendiri gagal.
Load balancer internal
Di dalam environment, terkadang terdapat kebutuhan untuk melakukan route trafik antar Service yang berada di dalam satu VPC.
Di dalam environment split-horizon DNS kamu akan membutuhkan dua service yang mampu melakukan mekanisme route trafik eskternal maupun internal ke endpoints yang kamu miliki.
Hal ini dapat diraih dengan cara menambahkan anotasi berikut untuk service yang disediakan oleh penyedia layanan cloud.
Pilih salah satu tab.
[...]
metadata:
name: my-service
annotations:
cloud.google.com/load-balancer-type: "Internal"
[...]
Gunakan cloud.google.com/load-balancer-type: "internal" untuk master dengan versi 1.7.0 to 1.7.3. Untuk informasi lebih lanjut, dilahkan baca dokumentasi.
[...]
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0
[...]
[...]
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
[...]
[...]
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/openstack-internal-load-balancer: "true"
[...]
[...]
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/cce-load-balancer-internal-vpc: "true"
[...]
Dukungan untuk SSL di AWS
Dukungan parsial untuk SSL bagi klaster yang dijalankan di AWS mulai diterapkan,
mulai versi 1.3 terdapat 3 anotasi yang dapat ditambahkan pada Service
dengan tipe
LoadBalancer
:
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012
Anotasi pertama memberikan spesifikasi ARN dari sertifikat yang akan digunakan. Sertifikat yang digunakan bisa saja berasal dari third party yang diunggah ke IAM atau sertifikat yang dibuat secara langsung dengan menggunakan sertifikat manajer AWS.
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: (https|http|ssl|tcp)
Anotasi kedua memberikan spesifikasi bagi protokol yang digunakan oleh Pod
untuk saling berkomunikasi.
Untuk HTTPS dan SSL, ELB membutuhkan Pod
untuk melakukan autentikasi terhadap dirinya sendiri melalui
koneksi yang dienkripsi.
Protokol HTTP dan HTTPS akan memilih mekanisme proxy di tingkatan ke-7:
ELB akan melakukan terminasi koneksi dengan pengguna, melakukan proses parsing headers, serta
memasukkan value bagi header X-Forwarded-For
dengan alamat IP pengguna (Pod hanya dapat melihat
alamat IP dari ELB pada akhir koneksi yang diberikan) ketika melakukan forwarding suatu request.
Protokol TCP dan SSL akan memilih mekanisme proxy pada tingkatan 4: ELB akan melakukan forwarding trafik tanpa melakukan modifikasi headers.
Pada environment campuran dimana beberapa port diamankan sementara port lainnya dalam kondisi tidak dienkripsi, anotasi-anotasi berikut dapat digunakan:
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443,8443"
Pada contoh di atas, jika Service
memiliki 3 buah port, yaitu: 80
, 443
, dan
8443
, maka 443
adan 8443
akan menggunakan sertifikat SSL, tetapi 80
hanya akan
di-proxy menggunakan protokol HTTP.
Mulai versi 1.9, Service
juga dapat menggunakan predefined policy
untuk HTTPS atau listener SSL. Untuk melihat policy apa saja yang dapat digunakan, kamu dapat menjalankan perintah awscli:
aws elb describe-load-balancer-policies --query 'PolicyDescriptions[].PolicyName'
Policy ini kemudian dapat dispesifikasikan menggunakan anotasi "service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy", contohnya:
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: "ELBSecurityPolicy-TLS-1-2-2017-01"
Protokol PROXY pada AWS
Untuk mengaktifkan dukungan protokol PROXY untuk klaster yang dijalankan di AWS, kamu dapat menggunakan anotasi di bawah ini:
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
Sejak versi 1.3.0, penggunaan anotasi berlaku untuk semua port yang diproksi oleh ELB dan tidak dapat diatur sebaliknya.
Akses Log ELB pada AWS
Terdapat beberapa anotasi yang digunakan untuk melakukan manajemen akses log untuk ELB pada AWS.
Anotasi service.beta.kubernetes.io/aws-load-balancer-access-log-enabled
mengatur akses log mana sajakah yang diaktifkan.
Anotasi service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval
mengatur interval (dalam menit) publikasi akses log. Kamu dapat memberikan spesifikasi interval
diantara range 5-60 menit.
Anotasi service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name
mengatur nama bucket Amazon S3 dimana akses log load balancer disimpan.
Anotasi service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix
memberikan spesifikasi hierarki logis yang kamu buat untuk bucket Amazon S3 yang kamu buat.
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-access-log-enabled: "true"
# Specifies whether access logs are enabled for the load balancer
service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval: "60"
# The interval for publishing the access logs. You can specify an interval of either 5 or 60 (minutes).
service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name: "my-bucket"
# The name of the Amazon S3 bucket where the access logs are stored
service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix: "my-bucket-prefix/prod"
# The logical hierarchy you created for your Amazon S3 bucket, for example _my-bucket-prefix/prod_
Mekanisme Draining Koneksi pada AWS
Mekanisme draining untuk ELB klasik dapat dilakukan dengan menggunakan anotasi
service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled
serta mengatur
value-nya menjadi "true"
. Anotasi
service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout
juga
dapat digunakan untuk mengatur maximum time (dalam detik), untuk menjaga koneksi yang ada
agar selalu terbuka sebelum melakukan deregistering instance.
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout: "60"
Anotasi ELB lainnya
Terdapat beberapa anotasi lain yang dapat digunakan untuk mengatur ELB klasik sebagaimana dijelaskan seperti di bawah ini:
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60"
# The time, in seconds, that the connection is allowed to be idle (no data has been sent over the connection) before it is closed by the load balancer
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
# Specifies whether cross-zone load balancing is enabled for the load balancer
service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: "environment=prod,owner=devops"
# A comma-separated list of key-value pairs which will be recorded as
# additional tags in the ELB.
service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: ""
# The number of successive successful health checks required for a backend to
# be considered healthy for traffic. Defaults to 2, must be between 2 and 10
service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: "3"
# The number of unsuccessful health checks required for a backend to be
# considered unhealthy for traffic. Defaults to 6, must be between 2 and 10
service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: "20"
# The approximate interval, in seconds, between health checks of an
# individual instance. Defaults to 10, must be between 5 and 300
service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout: "5"
# The amount of time, in seconds, during which no response means a failed
# health check. This value must be less than the service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval
# value. Defaults to 5, must be between 2 and 60
service.beta.kubernetes.io/aws-load-balancer-extra-security-groups: "sg-53fae93f,sg-42efd82e"
# A list of additional security groups to be added to ELB
Dukungan Network Load Balancer (NLB) pada AWS [alpha]
Sejak versi 1.9.0, Kubernetes mendukung Network Load Balancer (NLB). Untuk
menggunakan NLB pada AWS, gunakan anotasi service.beta.kubernetes.io/aws-load-balancer-type
dan atur value-nya dengan nlb
.
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
Tidak seperti ELB klasik, NLB, melakukan forwarding IP klien melalui node.
Jika field .spec.externalTrafficPolicy
diatur value-nya menjadi Cluster
, maka
alamat IP klien tidak akan diteruskan pada Pod
.
Dengan mengatur value dari field .spec.externalTrafficPolicy
ke Local
,
alamat IP klien akan diteruskan ke Pod
, tapi hal ini bisa menyebabkan distribusi trafik
yang tidak merata. Node yang tidak memiliki Pod
untuk Service
dengan tipe LoadBalancer
akan menyebabkan kegagalan health check NLB Target pada tahapan auto-assigned .spec.healthCheckNodePort
dan tidak akan menerima trafik apa pun.
Untuk menghasilkan distribusi trafik yang merata, kamu dapat menggunakan
DaemonSet atau melakukan spesifikasi
pod anti-affinity
agar Pod
tidak di-assign ke node yang sama.
NLB juga dapat digunakan dengan anotasi internal load balancer.
Agar trafik klien berhasil mencapai instances dibelakang ELB, security group dari node akan diberikan rules IP sebagai berikut:
Rule | Protokol | Port |
IpRange(s) | Deskripsi IpRange |
---|---|---|---|---|
Health Check | TCP | NodePort(s) (.spec.healthCheckNodePort for .spec.externalTrafficPolicy = Local) |
VPC CIDR | kubernetes.io/rule/nlb/health=<loadBalancerName> |
Client Traffic | TCP | NodePort(s) | .spec.loadBalancerSourceRanges (defaults to 0.0.0.0/0 ) |
kubernetes.io/rule/nlb/client=<loadBalancerName> |
MTU Discovery | ICMP | 3,4 | .spec.loadBalancerSourceRanges (defaults to 0.0.0.0/0 ) |
kubernetes.io/rule/nlb/mtu=<loadBalancerName> |
Perhatikan bahwa jika .spec.loadBalancerSourceRanges
tidak dispesifikasikan,
Kubernetes akan mengizinkan trafik dari 0.0.0.0/0
ke Node Security Group.
Jika node memiliki akses publik, maka kamu harus memperhatikan tersebut karena trafik yang tidak berasal
dari NLB juga dapat mengakses semua instance di security group tersebut.
Untuk membatasi klien IP mana yang dapat mengakses NLB, kamu harus memberikan spesifikasi loadBalancerSourceRanges.
spec:
loadBalancerSourceRanges:
- "143.231.0.0/16"
Tipe ExternalName
Service dengan tipe ExternalName
melakukan pemetaan antara Service
dan DNS, dan bukan
ke selector seperti my-service
atau cassandra
. Kamu memberikan spesifikasi spec.externalName
pada Service
tersebut.
Definisi Service
ini, sebagai contoh, melaukan pemetaan
Service
my-service
pada namespace prod
ke DNS my.database.example.com
:
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
ExternalName
menerima alamat IPv4 dalam bentuk string,
tapi karena DNS tersusun atas angka dan bukan sebagai alamat IP.
ExternalName
yang menyerupai alamat IPv4 tidak bisa di-resolve oleh CoreDNS
atau ingress-nginx karena ExternalName
memang ditujukan bagi penamaan canonical DNS.
Untuk melakukan hardcode alamat IP, kamu dapat menggunakan headless Service
sebagai alternatif.
Ketika melakukan pencarian host my-service.prod.svc.cluster.local
,
servis DNS klaster akan mengembalikan record CNAME
dengan value my.database.example.com
.
Mekanisme akses pada my-service
bekerja dengan cara yang sama dengan
Service
pada umumnya, perbedaan yang krusial untuk hal ini adalah mekanisme redirection
terjadi pada tingkatan DNS dan bukan melalui proxy forward. Apabila kamu berniat memindahkan basis data
yang kamu pakai ke dalam klaster, kamu hanya perlu mengganti instans basis data kamu dan menjalankannya
di dalam Pod
, menambahkan selector atau endpoint yang sesuai, serta mengupah type dari
Service yang kamu gunakan.
IP Eksternal
Jika terdapat sebuah alamat IP eksternal yang melakukan mekanisme route ke satu atau lebih node yang ada di klaster, Service
Kubernetes dapat diekspos
dengan menggunakan externalIP
. Trafik yang diarahkan ke klaster dengan IP eksternal
(sebagai destinasi IP), pada port Service
akan di-route ke salah satu endpoint Service
.
Value dari externalIP
tidak diatur oleh Kubernetes dan merupakan tanggung jawab
dari administrator klaster.
Pada ServiceSpec, kamu dapat memberikan spesifikasi externalIP
dan ServiceTypes
.
Pada contoh di bawah ini. "my-service"
dapat diakses oleh klien pada "80.11.12.10:80
" (externalIP:port
).
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
externalIPs:
- 80.11.12.10
Kekurangan
Penggunaan proxy userspace untuk VIP dapat digunakan untuk skala kecil hingga menengah,
meski begitu hal ini tidak scalable untuk klaster yang sangat besar dan memiliki ribuan Service
.
Perhatikan Desain proposal orisinil untuk portal untuk informasi
lebih lanjut.
Penggunaan proxy userspace menghilangkan source-IP dari packet yang mengakses
sebuah Service
. Hal ini membuat mekanisme firewall menjadi sulit untuk diterapkan.
Proxy iptables
tidak menghilangkan source IP yang berasal dari dalam klaster,
meski begitu, hal ini masih berimbas pada klien yang berasal dari Service
dengan tipe
load-balancer atau node-port.
Field tipe didesain sebagai fungsionalitas yang berantai - setiap tingkatan
menambahkan tambahan pada tingkatansebelumnya. Hal ini tidak selalu berlaku bagi
semua penyedia layanan cloud (misalnya saja Google Compute Engine tidak perlu
melakukan alokasi NodePort
untuk membuat LoadBalancer
bekerja sebagaimana mestinya,
hal ini berbeda dengan AWS yang memerlukan hal ini, setidaknya untuk API yang mereka miliki
saat ini).
Pengerjaan lebih lanjut
Di masa mendatang, kami berencana untuk membuat policy proxy menjadi lebih
bervariasi dan bukan hanya round robin, misalnya saja master-elected atau sharded.
Kami juga berharap bahwa beberapa Service
bisa saja memiliki load balancer yang sebenarnya,
suatu kasus dimana VIP akan secara langsung mengantarkan paket.
Kami ingin meningkatkan dukungan lebih lanjut untuk Service
dengan tingkatan Service
L7(HTTP).
Kami ingin memiliki mode ingress yang lebih fleksibel untuk Service
yang
mencakup mode ClusterIP
, NodePort
, dan LoadBalancer
dan banyak lagi.
Detail mendalam mengenai IP virtual
Informasi sebelumnya sudah cukup bagi sebagian orang yang hanya ingin menggunakan Service. Meskipun begitu, terdapat banyak hal yang sebenarnya terjadi dan akan sangat bermanfaat untuk dipelajari lebih lanjut.
Menghindari collison
Salah satu filosofi Kubernetes adalah pengguna tidak mungkin menghadapi situasi dimana apa yang mereka mengalami kegagalan tanpa adanya alasan yang jelas. Dalam kasus ini, kita akan coba memahami lebih lanjut mengenai network port - pengguna tidak seharusnya memilih nomor port jika hal itu memungkinkan terjadinya collision dengan pengguna lainnya. Hal ini merupakan mekanisme isolasi kegagalan.
Agar pengguna dapat menentukan nomor port bagi Service
mereka, kita harus
memastikan bahwa tidak ada dua Service
yang mengalami collision. Kita melakukan
hal tersebut dengan cara melakukan alokasi alamat IP pada setiap Service
.
Untuk memastikan setiap Service
memiliki alamat IP yang unik, sebuah allocator
internal akan secara atomik melakukan pemetaan alokasi global di dalam etcd ketika
membuat sebuah Service
baru. Pemetaan objek harus tersedia pada registry Service
dimana Service
akan diberikan sebuah IP, jika tidak, proses pembuatan Service
akan gagal
dan sebuah pesan akan memberikan informasi bahwa alamat IP tidak dapat dialokasikan.
Sebuah backgroud controller bertanggung jawab terhadap mekanisme pemetaan tersebut (migrasi
dari versi Kubernetes yang digunakan dalam memory locking) sekaligus melakukan pengecekan
terhadap assignment yang tidak valid yang terjadi akibat intervensi administrator dan melakukan
penghapusan daftar IP yang dialokasikan tapi tidak digunakan oleh Service
mana pun.
IP dan VIP
Tidak seperti alamat IP Pod
, yang akan di route ke destinasi yang "pasti",
IP Service
tidak mengarahkan request hanya pada satu host. Sebagai gantinya,
kita mneggunakan iptables
(logika pemrosesan paket pada Linux) untuk melakukan definisi
alamat IP virtual yang secara transparan akan diarahkan sesuai kebutuhan. Ketika klien
dihubungkan pada VIP, trafik yang ada akan secara otomatis dialihkan pada endpoint yang sesuai.
Variabel environment dan DNS untuk Service
terdiri dalam bentuk VIP dan port.
Kami mendukung tiga jenis mode proxy - userspace, iptables
, dan ipvs yang memiliki
perbedaan cara kerja satu sama lainnya.
Userspace
Sebagai contoh, anggaplah kita memiliki aplikasi image processing seperti yang sudah
disebutkan di atas. Ketika Service
backend dibuat, master Kubernetes akan mengalokasikan
sebuah alamat IP virtual, misalnya 10.0.0.1. Dengan asumsi port dari Service
tersebut adalah 1234,
maka Service
tersebut akan diamati oleh semua instance kube-proxy
yang ada di klaster.
Ketika sebuah proxy mendapati sebuah Service
baru, proxy tersebut akan membuka sebuah port
acak, menyediakan iptables
yang mengarahkan VIP pada port yang baru saja dibuat, dan mulai
koneksi pada port tersebut.
Ketika sebuah klien terhubung ke VIP dan terdapat rules iptables
yang diterapkan, paket akan diarahkan ke port dari proxy Service
itu sendiri.
Proxy Service
akan memilih sebuah backend, dan mulai melakukan mekanisme proxy
trafik dari klien ke backend.
Dengan demikian, pemilik Service
dapat memilih port mana pun yang dia inginkan
tanpa adanya kemungkinan terjadinya collision. Klien dapat dengan mudah mengakses IP dan port,
tanpa harus mengetahui Pod
mana yang sebenarnya diakses.
Iptables
Kembali, bayangkan apabila kita memiliki aplikasi image processing seperti yang sudah
disebutkan di atas. Ketika Service
backend dibuat, master Kubernetes akan mengalokasikan
sebuah alamat IP virtual, misalnya 10.0.0.1. Dengan asumsi port dari Service
tersebut adalah 1234,
maka Service
tersebut akan diamati oleh semua instance kube-proxy
yang ada di klaster.
Ketika sebuah proxy mendapati sebuah Service
baru, proxy tersebut akan melakukan instalasi
serangkaian rules iptables
yang akan melakukan redirect VIP ke rules tiap Service
. Rules
untuk tiap Service
ini terkait dengan rules tiap Endpoints
yang mengarahkan (destinasi NAT)
ke backend.
Ketika sebuah klien terhubung ke VIP dan terdapat _rules _iptables
yang diterapkan. Sebuah backend akan dipilih (hal ini dapat dilakukan berdasarkan session affinity
maupun secara acak) dan paket-paket yang ada akan diarahkan ke backend. Tidak seperti mekanisme
yang terjadi di userspace, paket-paket yang ada tidak pernah disalin ke userspace, kube-proxy
tidak harus aktif untuk menjamin kerja VIP, serta IP klien juga tidak perlu diubah.
Tahapan yang dijalankan sama dengan tahapan yang dijalankan ketika trafik masuk melalui sebuah node-port atau load-balancer, meskipun pada dua kasus di atas klien IP tidak akan mengalami perubahan.
Ipvs
Operasi iptables
berlangsung secara lambat pada klaster dengan skala besar (lebih dari 10.000 Service
).
IPVS didesain untuk mekanisme load balance dan berbasis pada hash tables yang berada di dalam kernel.
Dengan demikian kita dapat mendapatkan performa yang konsisten pada jumlah Service
yang cukup besar dengan
menggunakan kube-proxy
berbasis ipvs. Sementara itu, kube-proxy
berbasis ipvs memiliki algoritma
load balance yang lebih bervariasi (misalnya saja least conns, locality, weighted, persistence).
Objek API
Service merupakan resource top-level pada API Kubernetes.
Penjelasan lebih lanjut mengenai objek API dapat ditemukan pada:
objek API Service
.
Protokol yang didukung
TCP
Kubernetes v1.0 [stable]
Kamu dapat menggunakan TCP untuk Service
dengan type apa pun, dan protokol ini merupakan
protokol default yang digunakan.
UDP
Kubernetes v1.0 [stable]
Kamu dapat menggunakan UDP untuk sebagian besar Service
.
Untuk Service
dengan type=LoadBalancer, dukungan terhadap UDP
bergantung pada penyedia layanan cloud yang kamu gunakan.
HTTP
Kubernetes v1.1 [stable]
Apabila penyedia layanan cloud yang kamu gunakan mendukung, kamu dapat menggunakan
Service dengan type LoadBalancer
untuk melakukan mekanisme reverse proxy
bagi HTTP/HTTPS, dan melakukan forwarding ke Endpoints
dari _Service.
Service
untuk HTTP/HTTPS.
Protokol PROXY
Kubernetes v1.1 [stable]
Apabila penyedia layanan cloud yang kamu gunakan mendukung, (misalnya saja, AWS),
Service dengan type LoadBalancer
untuk melakukan konfigurasi load balancer
di luar Kubernetes sendiri, serta akan melakukan forwarding koneksi yang memiliki prefiks
protokol PROXY.
Load balancer akan melakukan serangkaian inisiasi octet yang memberikan deskripsi koneksi yang datang, dengan bentuk yang menyerupai:
PROXY TCP4 192.0.2.202 10.0.42.7 12345 7\r\n
yang kemudian diikuti data dari klien.
SCTP
Kubernetes v1.12 [alpha]
Kubernetes memberikan dukungan bagi SCTP sebagai value dari definition yang ada pada
Service, Endpoints
, NetworkPolicy
dan Pod
sebagai fitur alpha. Untuk mengaktifkan fitur ini,
administrator klaster harus mengaktifkan feature gate SCTPSupport pada apiserver, contohnya
“--feature-gates=SCTPSupport=true,...”
. Ketika fature gate ini diaktifkan, pengguna dapat
memberikan value SCTP pada field protocol Service
, Endpoints
, NetworkPolicy
dan Pod
.
Kubernetes kemudian akan melakukan pengaturan agar jaringan yang digunakan agar jaringan tersebut menggunakan SCTP,
seperti halnya Kubernetes mengatur jaringan agar menggunakan TCP.
Perhatian
Dukungan untuk asoasiasi multihomed SCTP
Dukungan untuk asosiasi multihomed SCTP membutuhkan plugin CNI yang dapat memberikan
pengalokasian multiple interface serta alamat IP pada sebuah Pod
.
NAT untuk asosiasi multihomed SCTP membutuhkan logika khusus pada modul kernel terkait.
Service
dengan type=LoadBalancer
Sebuah Service
dengan type LoadBalancer
dan protokol SCTP dapat dibuat
hanya jika implementasi load balancer penyedia layanan cloud menyediakan dukungan
bagi protokol SCTP. Apabila hal ini tidak terpenuhi, maka request pembuatan Servixe ini akan ditolak.
Load balancer yang disediakan oleh penyedia layanan cloud yang ada saat ini (Azure, AWS, CloudStack, GCE, OpenStack) tidak mendukung SCTP.
Windows
SCTP tidak didukung pada node berbasis Windows.
Kube-proxy userspace
Kube-proxy tidak mendukung manajemen asosiasi SCTP ketika hal ini dilakukan pada mode userspace
Selanjutnya
Baca Bagaimana cara menghubungkan Front End ke Back End menggunakan sebuah Service
.
3.5.2 - Topologi Service (Service Topology)
Kubernetes v1.17 [alpha]
Topologi Service memungkinkan Service untuk merutekan lalu lintas jaringan berdasarkan topologi Node dalam klaster. Misalnya, suatu layanan dapat menentukan lalu lintas jaringan yang lebih diutamakan untuk dirutekan ke beberapa endpoint yang berada pada Node yang sama dengan klien, atau pada availability zone yang sama.
Pengantar
Secara bawaan lalu lintas jaringan yang dikirim ke ClusterIP
atau NodePort
dari Service
dapat dialihkan ke alamat backend untuk Service tersebut. Sejak Kubernetes 1.7
dimungkinkan untuk merutekan lalu lintas jaringan "eksternal" ke Pod yang berjalan di
Node yang menerima lalu lintas jaringan, tetapi fitur ini tidak didukung untuk ClusterIP
dari
Service, dan topologi yang lebih kompleks — seperti rute zonasi —
belum memungkinkan. Fitur topologi Service mengatasi kekurangan ini dengan
mengizinkan pembuat layanan untuk mendefinisikan kebijakan dalam merutekan lalu lintas jaringan
berdasarkan label Node untuk Node-Node asal dan tujuan.
Dengan menggunakan label Node yang sesuai antara asal dan tujuan, operator dapat menunjuk kelompok Node mana yang "lebih dekat" dan mana yang "lebih jauh" antara satu sama lain, dengan menggunakan metrik apa pun yang masuk akal untuk memenuhi persyaratan dari operator itu. Untuk sebagian besar operator di publik cloud, misalnya, ada preferensi untuk menjaga layanan lalu lintas jaringan dalam zona yang sama, karena lalu lintas jaringan antar zona memiliki biaya yang dibebankan, sementara lalu lintas jaringan dalam zona yang sama tidak ada biaya. Kebutuhan umum lainnya termasuk kemampuan untuk merutekan lalu lintas jaringan ke Pod lokal yang dikelola oleh sebuah DaemonSet, atau menjaga lalu lintas jaringan ke Node yang terhubung ke top-of-rack switch yang sama untuk mendapatkan latensi yang terendah.
Menggunakan Topologi Service
Jika klaster kamu mengaktifkan topologi Service kamu dapat mengontrol rute lalu lintas jaringan Service
dengan mengatur bagian topologyKeys
pada spesifikasi Service. Bagian ini
adalah daftar urutan label-label Node yang akan digunakan untuk mengurutkan endpoint
saat mengakses Service ini. Lalu lintas jaringan akan diarahkan ke Node yang nilai
label pertamanya cocok dengan nilai dari Node asal untuk label yang sama. Jika
tidak ada backend untuk Service pada Node yang sesuai, maka label kedua akan
dipertimbangkan, dan seterusnya, sampai tidak ada label yang tersisa.
Jika tidak ditemukan kecocokan, lalu lintas jaringan akan ditolak, sama seperti jika tidak ada
sama sekali backend untuk Service tersebut. Artinya, endpoint dipilih
berdasarkan kunci topologi yang pertama yang tersedia pada backend. Jika dalam
bagian ini ditentukan dan semua entri tidak memiliki backend yang sesuai dengan
topologi klien, maka Service tidak memiliki backend untuk klien dan koneksi harus
digagalkan. Nilai khusus "*"
dapat digunakan untuk mengartikan "topologi
apa saja". Nilai catch-all ini, jika digunakan, maka hanya sebagai
nilai terakhir dalam daftar.
Jika topologyKeys
tidak ditentukan atau kosong, tidak ada batasan topologi
yang akan diterapkan.
Seandainya sebuah klaster dengan Node yang dilabeli dengan nama host ,
nama zona, dan nama wilayah mereka, maka kamu dapat mengatur nilai
topologyKeys
dari sebuah Service untuk mengarahkan lalu lintas jaringan seperti berikut ini.
- Hanya ke endpoint dalam Node yang sama, gagal jika tidak ada endpoint pada Node:
["kubernetes.io/hostname"]
. - Lebih memilih ke endpoint dalam Node yang sama, jika tidak ditemukan maka ke endpoint pada zona yang sama, diikuti oleh wilayah yang sama, dan selain itu akan gagal:
["kubernetes.io/hostname ", "topology.kubernetes.io/zone", "topology.kubernetes.io/region"]
. Ini mungkin berguna, misalnya, dalam kasus di mana lokalitas data sangatlah penting. - Lebih memilih ke endpoint dalam zona yang sama, tetapi memilih endpoint mana saja yang tersedia apabila tidak ada yang tersedia dalam zona ini:
["topology.kubernetes.io/zone ","*"]
.
Batasan
- Topologi Service tidak kompatibel dengan
externalTrafficPolicy=Local
, dan karena itu Service tidak dapat menggunakan kedua fitur ini sekaligus. Dimungkinkan untuk menggunakan kedua fitur pada klaster yang sama untuk Service yang berbeda, bukan untuk Service yang sama. - Untuk saat ini kunci topologi yang valid hanya terbatas pada
kubernetes.io/hostname
,topology.kubernetes.io/zone
, dantopology.kubernetes.io/region
, tetapi akan digeneralisasikan ke label Node yang lain di masa depan. - Kunci topologi harus merupakan kunci label yang valid dan paling banyak hanya 16 kunci yang dapat ditentukan.
- Nilai catch-all,
"*"
, harus menjadi nilai terakhir pada kunci topologi, jika nilai itu digunakan.
Contoh
Berikut ini adalah contoh umum penggunaan fitur topologi Service.
Hanya pada endpoint pada Node lokal
Service yang hanya merutekan ke endpoint pada Node lokal. Jika tidak ada endpoint pada Node, lalu lintas jaringan akan dihentikan:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
topologyKeys:
- "kubernetes.io/hostname"
Lebih memilih endpoint pada Node lokal
Service yang lebih memilih endpoint pada Node lokal, namun akan memilih ke endpoint dalam klaster jika endpoint pada Node lokal tidak ada:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
topologyKeys:
- "kubernetes.io/hostname"
- "*"
Hanya untuk endpoint pada zona atau wilayah yang sama
Service yang lebih memilih endpoint dalam zona yang sama daripada wilayah yang sama. Jika tidak ada endpoint pada
keduanya, maka lalu lintas jaringan akan dihentikan.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
topologyKeys:
- "topology.kubernetes.io/zone"
- "topology.kubernetes.io/region"
Lebih memilih endpoint pada Node lokal, zona yang sama, dan kemudian wilayah yang sama
Service yang lebih memilih endpoint pada Node lokal, zona yang sama, dan kemudian baru wilayah yang sama, namun jika tetap tidak ditemukan maka akan memilih endpoint diseluruh klaster.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
topologyKeys:
- "kubernetes.io/hostname"
- "topology.kubernetes.io/zone"
- "topology.kubernetes.io/region"
- "*"
Selanjutnya
- Baca tentang mengaktifkan topologi Service
- Baca menghubungkan aplikasi dengan Service
3.5.3 - EndpointSlice
Kubernetes v1.17 [beta]
EndpointSlice menyediakan sebuah cara yang mudah untuk melacak endpoint jaringan dalam sebuah klaster Kubernetes. EndpointSlice memberikan alternatif yang lebih scalable dan lebih dapat diperluas dibandingkan dengan Endpoints.
Motivasi
Endpoints API telah menyediakan sebuah cara yang mudah dan sederhana untuk melacak endpoint jaringan pada Kubernetes. Sayangnya, seiring dengan besarnya klaster Kubernetes dan Service, batasan-batasan yang dimiliki API tersebut semakin terlihat. Terutama, hal tersebut termasuk kendala-kendala mengenai proses scaling endpoint jaringan dalam jumlah yang besar.
Karena semua endpoint jaringan untuk sebuah Service disimpan dalam satu sumber daya Endpoints, sumber daya tersebut dapat menjadi cukup besar. Hal itu dapat mempengaruhi kinerja dari komponen-komponen Kubernetes (terutama master control plane) dan menyebabkan lalu lintas jaringan dan pemrosesan yang cukup besar ketika Endpoints berubah. EndpointSlice membantu kamu menghindari masalah-masalah tersebut dan juga menyediakan platform yang dapat diperluas untuk fitur-fitur tambahan seperti topological routing.
Sumber daya EndpointSlice
Pada Kubernetes, sebuah EndpointSlice memiliki referensi-referensi terhadap sekumpulan endpoint jaringan. Controller EndpointSlice secara otomatis membuat EndpointSlice untuk sebuah Service Kubernetes ketika sebuah selektor dituliskan. EndpointSlice tersebut akan memiliki referensi-referensi menuju Pod manapun yang cocok dengan selektor pada Service tersebut. EndpointSlice mengelompokkan endpoint jaringan berdasarkan kombinasi Service dan Port yang unik. Nama dari sebuah objek EndpointSlice haruslah berupa nama subdomain DNS yang sah.
Sebagai contoh, berikut merupakan sampel sumber daya EndpointSlice untuk sebuah Service Kubernetes
yang bernama example
.
apiVersion: discovery.k8s.io/v1beta1
kind: EndpointSlice
metadata:
name: example-abc
labels:
kubernetes.io/service-name: example
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 80
endpoints:
- addresses:
- "10.1.2.3"
conditions:
ready: true
hostname: pod-1
topology:
kubernetes.io/hostname: node-1
topology.kubernetes.io/zone: us-west2-a
Secara bawaan, setiap EndpointSlice yang dikelola oleh controller EndpointSlice tidak akan memiliki lebih dari 100 endpoint. Di bawah skala tersebut, EndpointSlice akan memetakan 1:1 dengan Endpoints dan Service dan akan memiliki kinerja yang sama.
EndpointSlice dapat bertindak sebagai sumber kebenaran untuk kube-proxy sebagai acuan mengenai bagaimana cara untuk merutekan lalu lintas jaringan internal. Ketika diaktifkan, EndpointSlice semestinya memberikan peningkatan kinerja untuk Service yang memiliki Endpoints dalam jumlah besar.
Tipe-tipe Alamat
EndpointSlice mendukung tiga tipe alamat:
- IPv4
- IPv6
- FQDN (Fully Qualified Domain Name)
Topologi
Setiap endpoint pada EndpointSlice dapat memiliki informasi topologi yang relevan. Hal ini digunakan untuk mengindikasikan di mana endpoint berada, berisi informasi mengenai Node yang bersangkutan, zona, dan wilayah. Ketika nilai-nilai tersebut tersedia, label-label Topology berikut akan ditambahkan oleh controller EndpointSlice:
kubernetes.io/hostname
- Nama dari Node tempat endpoint berada.topology.kubernetes.io/zone
- Zona tempat endpoint berada.topology.kubernetes.io/region
- Region tempat endpoint berada.
Nilai-nilai dari label-label berikut berasal dari sumber daya yang diasosiasikan dengan tiap endpoint pada sebuah slice. Label hostname merepresentasikan nilai dari kolom NodeName pada Pod yang bersangkutan. Label zona dan wilayah merepresentasikan nilai dari label-label dengan nama yang sama pada Node yang bersangkutan.
Pengelolaan
Secara bawaan, EndpointSlice dibuat dan dikelola oleh controller
EndpointSlice. Ada berbagai macam kasus lain untuk EndpointSlice, seperti
implementasi service mesh, yang memungkinkan adanya entitas atau controller lain
yang dapat mengelola beberapa EndpointSlice sekaligus. Untuk memastikan beberapa entitas dapat
mengelola EndpointSlice tanpa mengganggu satu sama lain, sebuah
label endpointslice.kubernetes.io/managed-by
digunakan untuk mengindikasikan entitas
yang mengelola sebuah EndpointSlice. Controller EndpointSlice akan menambahkan
endpointslice-controller.k8s.io
sebagai nilai dari label tersebut pada seluruh
EndpointSlice yang dikelolanya. Entitas lain yang mengelola EndpointSlice juga diharuskan untuk
menambahkan nilai yang unik untuk label tersebut.
Kepemilikan
Pada kebanyakan kasus, EndpointSlice akan dimiliki oleh Service yang diikutinya. Hal ini diindikasikan dengan referensi pemilik pada tiap EndpointSlice dan
juga label kubernetes.io/service-name
yang memudahkan pencarian seluruh
EndpointSlice yang dimiliki oleh sebuah Service.
Controller EndpointSlice
Controller EndpointSlice mengamati Service dan Pod untuk memastikan EndpointSlice yang bersangkutan berada dalam kondisi terkini. Controller EndpointSlice akan mengelola EndpointSlice untuk setiap Service yang memiliki selektor. Ini akan merepresentasikan IP dari Pod yang cocok dengan selektor dari Service tersebut.
Ukuran EndpointSlice
Secara bawaan, jumlah endpoint yang dapat dimiliki tiap EndpointSlice dibatasi sebanyak 100 endpoint. Kamu dapat
mengaturnya melalui opsi --max-endpoints-per-slice
kube-controller-manager sampai dengan
jumlah maksimum sebanyak 1000 endpoint.
Distribusi EndpointSlice
Tiap EndpointSlice memiliki sekumpulan port yang berlaku untuk seluruh endpoint dalam sebuah sumber daya. Ketika nama port digunakan untuk sebuah Service, Pod mungkin mendapatkan nomor target port yang berbeda-beda untuk nama port yang sama, sehingga membutuhkan EndpointSlice yang berbeda. Hal ini mirip dengan logika mengenai bagaimana subset dikelompokkan dengan Endpoints.
Controller EndpointSlice akan mencoba untuk mengisi EndpointSlice sebanyak mungkin, tetapi tidak secara aktif melakukan rebalance terhadap EndpointSlice tersebut. Logika dari controller cukup sederhana:
- Melakukan iterasi terhadap EndpointSlice yang sudah ada, menghapus endpoint yang sudah tidak lagi dibutuhkan dan memperbarui endpoint yang sesuai yang mungkin telah berubah.
- Melakukan iterasi terhadap EndpointSlice yang sudah dimodifikasi pada langkah pertama dan mengisinya dengan endpoint baru yang dibutuhkan.
- Jika masih tersisa endpoint baru untuk ditambahkan, mencoba untuk menambahkannya pada slice yang tidak berubah sebelumnya dan/atau membuat slice yang baru.
Terlebih penting, langkah ketiga memprioritaskan untuk membatasi pembaruan EndpointSlice terhadap distribusi dari EndpointSlice yang benar-benar penuh. Sebagai contoh, jika ada 10 endpoint baru untuk ditambahkan dan ada 2 EndpointSlice yang masing-masing memiliki ruang untuk 5 endpoint baru, pendekatan ini akan membuat sebuah EndpointSlice baru daripada mengisi 2 EndpointSlice yang sudah ada. Dengan kata lain, pembuatan sebuah EndpointSlice lebih diutamakan daripada pembaruan beberapa EndpointSlice.
Dengan kube-proxy yang berjalan pada tiap Node dan mengamati EndpointSlice, setiap perubahan pada sebuah EndpointSlice menjadi sangat mahal karena hal tersebut akan dikirimkan ke setiap Node dalam klaster. Pendekatan ini ditujukan untuk membatasi jumlah perubahan yang perlu dikirimkan ke setiap Node, meskipun hal tersebut berdampak pada banyaknya EndpointSlice yang tidak penuh.
Pada praktiknya, distribusi yang kurang ideal seperti ini akan jarang ditemukan. Kebanyakan perubahan yang diproses oleh controller EndpointSlice akan cukup kecil untuk dapat masuk pada EndpointSlice yang sudah ada, dan jika tidak, cepat atau lambat sebuah EndpointSlice baru akan segera dibutuhkan. Pembaruan bertahap (rolling update) dari Deployment juga menyediakan sebuah proses pengemasan ulang EndpointSlice yang natural seiring dengan digantikannya seluruh Pod dan endpoint yang bersangkutan.
Selanjutnya
3.5.4 - DNS untuk Service dan Pod
Laman ini menyediakan ikhtisar dari dukungan DNS oleh Kubernetes.
Pendahuluan
Kubernetes DNS melakukan scheduling DNS Pod dan Service yang ada pada klaster, serta melakukan konfigurasi kubelet untuk memberikan informasi bagi setiap Container untuk menggunakan DNS Service IP untuk melakukan resolusi DNS.
Apa Sajakah yang Mendapatkan Nama DNS?
Setiap Service yang didefinisikan di dalam klaster (termasuk server DNS itu sendiri) memiliki nama DNS. Secara default, sebuah list pencarian DNS pada Pod klien akan mencantumkan namespace Pod itu sendiri serta domain default klaster. Hal ini dapat diilustrasikan dengan contoh berikut:
Asumsikan sebuah Service dengan nama foo
pada Kubernetes dengan namespace bar
.
Sebuah Pod yang dijalankan di namespace bar
dapat melakukan resolusi
terhadap Service ini dengan melakukan query DNS
untuk foo
. Sebuah Pod yang dijalankan pada namespace quux
dapat melakukan
resolusi Service ini dengan melakukan query DNS untuk foo.bar
.
Bagian di bawah ini akan menampilkan detail tipe rekaman serta layout yang didukung. Layout atau nama query lain yang dapat digunakan dianggap sebagai detail implementasi yang bisa saja berubah tanpa adanya pemberitahuan sebelumnya. Untuk informasi spesifikasi terbaru kamu dapat membaca Service Discovery pada Kubernetes berbasis DNS.
Service
A record
Service "Normal" (bukan headless) akan diberikan sebuah A record untuk sebuah nama dalam bentuk
my-svc.my-namespace.svc.cluster-domain.example
. Inilah yang kemudian digunakan untuk melakukan
resolusi IP klaster dari Service tersebut.
Service "Headless" (tanpa IP klaster) juga memiliki sebuah A record DNS dengan format
my-svc.my-namespace.svc.cluster-domain.example
. Tidak seperti halnya Service normal,
DNS ini akan melakukan resolusi pada serangkauan IP dari Pod yang dipilih oleh Service tadi.
Klien diharapkan untuk mengkonsumsi serangkaian IP ini atau cara lain yang digunakan adalah pemilihan
menggunakan penjadwalan Round-Robin dari set yang ada.
SRV record
SRV record dibuat untuk port bernama yang merupakan bagian dari Service normal maupun Headless
Services.
Untuk setiap port bernama, SRV record akan memiliki format
_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example
.
Untuk sebuah Service normal, ini akan melakukan resolusi pada nomor port dan
nama domain: my-svc.my-namespace.svc.cluster-domain.example
.
Untuk Service headless, ini akan melakukan resolusi pada serangkaian Pod yang merupakan backend dari Service
tersebut yang memiliki format: auto-generated-name.my-svc.my-namespace.svc.cluster-domain.example
.
Pod
Hostname Pod dan Field Subdomain
Saat ini ketika sebuah Pod dibuat, hostname-nya adalah nilai dari metadata.name
.
Spek Pod memiliki field opsional hostname
, yang dapat digunakan untuk menspesifikasikan
hostname Pod. Ketika dispesifikasikan, maka nama ini akan didahulukan di atas nama Pod .
Misalnya, sebuah Pod dengan hostname
yang diberikan nilai "my-host
", maka hostname Pod tersebut akan menjadi "my-host
".
Spek Pod juga memiliki field opsional subdomain
yang dapat digunakan untuk menspesifikasikan
subdomain Pod tersebut. Misalnya saja sebuah Pod dengan hostname
yang diberi nilai "foo
", dan subdomain
yang diberi nilai "bar
", pada namespace "my-namespace
", akan memiliki fully qualified
domain name (FQDN) "foo.bar.my-namespace.svc.cluster-domain.example
".
Contoh:
apiVersion: v1
kind: Service
metadata:
name: default-subdomain
spec:
selector:
name: busybox
clusterIP: None
ports:
- name: foo # Actually, no port is needed.
port: 1234
targetPort: 1234
---
apiVersion: v1
kind: Pod
metadata:
name: busybox1
labels:
name: busybox
spec:
hostname: busybox-1
subdomain: default-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
---
apiVersion: v1
kind: Pod
metadata:
name: busybox2
labels:
name: busybox
spec:
hostname: busybox-2
subdomain: default-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
Jika terdapat sebuah Service headless memiliki nama yang sama dengan
subdomain dari suatu Pod pada namespace yang sama, server KubeDNS klaster akan mengembalikan
A record untuk FQDN Pod.
Sebagai contoh, misalnya terdapat sebuah Pod dengan hostname "busybox-1
" dan
subdomain "default-subdomain
", serta sebuah Service headless dengan nama "default-subdomain
"
berada pada suatu namespace yang sama, maka Pod tersebut akan menerima FQDN dirinya sendiri
sebagai "busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example
". DNS mengembalikan
A record pada nama tersebut dan mengarahkannya pada IP Pod. Baik Pod "busybox1
" dan
"busybox2
" bisa saja memiliki A record yang berbeda.
Objek Endpoint dapat menspesifikasikan hostname
untuk alamat endpoint manapun
beserta dengan alamat IP-nya.
hostname
diperlukan
agar sebuah Pod memiliki A record. Sebuah Pod yang tidak memiliki hostname
tetapi memiliki subdomain
hanya akan membuat sebuah A record untuk Service headless
(default-subdomain.my-namespace.svc.cluster-domain.example
), yang merujuk pada IP dari
Pod tersebut. Pod juga harus dalam status ready agar dapat memiliki A record kecuali
field publishNotReadyAddresses=True
diaktifkan pada Service.
Kebijakan DNS Pod
Kebijakan DNS dapat diaktifkan untuk setiap Pod. Kubernetes saat ini mendukung
kebijakan DNS spesifik Pod (pod-specific DNS policies). Kebijakan ini
dispesifikasikan pada field dnsPolicy
yang ada pada spek Pod.
- "
Default
": Pod akan mewarisi konfigurasi resolusi yang berasal dari Node dimana Pod tersebut dijalankan. Silakan baca diskusi terkait untuk detailnya. - "
ClusterFirst
": Query DNS apa pun yang tidak sesuai dengan sufiks domain klaster yang sudah dikonfigurasi misalnya "www.kubernetes.io
", akan di-forward ke nameserver upstream yang diwarisi dari Node. Administrator klaster bisa saja memiliki stub-domain atau DNS usptream lain yang sudah dikonfigurasi. Silakan lihat diskusi terkait untuk detail lebih lanjut mengenai bagaimana query DNS melakukan hal tersebut. - "
ClusterFirstWithHostNet
": Untuk Pod yang dijalankan dengan menggunakanhostNetwork
, kamu harus secara eksplisit mengaktifkan kebijakan DNS-nya menjadi "ClusterFirstWithHostNet
". - "
None
": Hal ini mengisikan sebuah Pod untuk mengabaikan konfigurasi DNS dari environment Kubernetes Semua pengaturan DNS disediakan menngunakan fielddnsConfig
yang ada pada spek Pod. Silakan lihat konfigurasi DNS Pod di bawah.
dnsPolicy
tidak secara eksplisit dispesifikasikan, maka “ClusterFirst” akan digunakan.
Contoh di bawah ini menunjukkan sebuah Pod dengan kebijakan
DNS yang diubah menjadi "ClusterFirstWithHostNet
" karena field hostNetwork
diubah menjadi true
.
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
Konfigurasi DNS Pod
Konfigurasi DNS Pod mengizinkan pengguna untuk memiliki lebih banyak kontrol terhadap pengaturan DNS pada Pod.
Field dnsConfig
bersifat opsional dan dapat digunakan dengan
pengaturan dnsPolicy
apa pun.
Meskipun begitu, ketika field dnsPolicy
pada sebuah Pod diubah menjadi "None
",
maka field dnsConfig
harus dispesifikasikan.
Berikut merupakan properti yang dapat dispesifikasikan oleh pengguna
pada field dnsConfig
:
nameservers
: serangkaian alamat IP yang akan digunakan sebagai server DNS bagi Pod. Jumlah maksimum dari IP yang dapat didaftarkan pada field ini adalah tiga buah IP. Ketika sebuahdnsPolicy
pada Pod diubah menjadi "None
", maka list ini setidaknya harus mengandung sebuah alamat IP, selain kasus tersebut properti ini bersifat opsional. Server yang didaftarkan akan digabungkan di dalam nameserver dasar yang dihasilkan dari kebijakan DNS yang dispesifikasikan, apabila terdapat duplikat terhadap alamat yang didaftarkan maka alamat tersebut akan dihapus.searches
: merupakan serangkaian domain pencarian DNS yang digunakan untuk proses lookup pada Pod. Properti ini bersifat opsional. Ketika dispesifikasikan, list yang disediakan akan digabungkan dengan nama domain pencarian dasar yang dihasilkan dari kebijakan DNS yang dipilih. Alamat yang duplikat akan dihapus. Nilai maksimum domain pencarian yang dapat didaftarkan adalah 6 domain.options
: merupakan sebuah list opsional yang berisikan objek dimana setiap objek bisa saja memiliki propertiname
(yang bersifat wajib). Isi dari properti ini akan digabungkan dengan opsi yang dihasilkan kebijakan DNS yang digunakan. Alamat yang duplikat akan dihapus.
Di bawah ini merupakan contoh sebuah Pod dengan pengaturan DNS kustom:
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: dns-example
spec:
containers:
- name: test
image: nginx
dnsPolicy: "None"
dnsConfig:
nameservers:
- 1.2.3.4
searches:
- ns1.svc.cluster-domain.example
- my.dns.search.suffix
options:
- name: ndots
value: "2"
- name: edns0
Ketika Pod diatas dibuat, maka Container test
memiliki isi berkas /etc/resolv.conf
sebagai berikut:
nameserver 1.2.3.4
search ns1.svc.cluster-domain.example my.dns.search.suffix
options ndots:2 edns0
Untuk pengaturan IPv6, path pencarian dan name server harus dispesifikasikan sebagai berikut:
kubectl exec -it dns-example -- cat /etc/resolv.conf
Keluaran yang dihasilkan akan menyerupai:
nameserver fd00:79:30::a
search default.svc.cluster-domain.example svc.cluster-domain.example cluster-domain.example
options ndots:5
Keberadaan Fitur (Feature Availability)
Keberadaan Pod DNS Config dan DNS Policy "None
"" diilustrasikan pada tabel di bawah ini.
versi k8s | Dukungan Fitur |
---|---|
1.14 | Stable |
1.10 | Beta (aktif secara default) |
1.9 | Alpha |
Selanjutnya
Untuk petunjuk lebih lanjut mengenai administrasi konfigurasi DNS, kamu dapat membaca Cara Melakukan Konfigurasi Service DNS
3.5.5 - Menghubungkan aplikasi dengan Service
Model Kubernetes untuk menghubungkan kontainer
Sekarang kamu memiliki aplikasi yang telah direplikasi, kamu dapat mengeksposnya di jaringan. Sebelum membahas pendekatan jaringan di Kubernetes, akan lebih baik jika kamu paham bagaimana jaringan bekerja di dalam Docker.
Secara default, Docker menggunakan jaringan host, jadi kontainer dapat berkomunikasi dengan kontainer lainnya jika mereka berada di dalam node yang sama. Agar kontainer Docker dapat berkomunikasi antar node, masing-masing kontainer tersebut harus diberikan port yang berbeda di alamat IP node tersebut, yang akan diteruskan (proxied) ke dalam kontainer. Artinya adalah para kontainer di dalam sebuah node harus berkoordinasi port mana yang akan digunakan atau dialokasikan secara otomatis.
Akan sulit untuk mengkoordinasikan port yang digunakan oleh banyak pengembang. Kubernetes mengasumsikan bahwa Pod dapat berkomunikasi dengan Pod lain, terlepas di Node mana Pod tersebut di deploy. Kubernetes memberikan setiap Pod alamat ClusterIP sehingga kamu tidak perlu secara explisit membuat jalur antara Pod ataupun memetakan port kontainer ke dalam port di dalam Node tersebut. Ini berarti kontainer di dalam sebuah Pod dapat berkomunikasi dengan localhost via port, dan setiap Pod di dalam klaster dapat berkomunikasi tanpa NAT. Panduan ini akan membahas bagaimana kamu dapat menjalankan sebuah layanan atau aplikasi di dalam model jaringan di atas.
Panduan ini menggunakan server nginx sederhana untuk mendemonstrasikan konsepnya. Konsep yang sama juga ditulis lebih lengkap di Aplikasi Jenkins CI.
Mengekspos Pod ke dalam klaster
Kita melakukan ini di beberapa contoh sebelumnya, tetapi mari kita lakukan sekali lagi dan berfokus pada prespektif jaringannya. Buat sebuah nginx Pod, dan perhatikan bahwa templat tersebut mempunyai spesifikasi port kontainer:
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
Ini membuat aplikasi tersebut dapat diakses dari node manapun di dalam klaster kamu. Cek lokasi node dimana Pod tersebut berjalan:
kubectl apply -f ./run-my-nginx.yaml
kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-jr4a2 1/1 Running 0 13s 10.244.3.4 kubernetes-minion-905m
my-nginx-3800858182-kna2y 1/1 Running 0 13s 10.244.2.5 kubernetes-minion-ljyd
Cek IP dari Pod kamu:
kubectl get pods -l run=my-nginx -o yaml | grep podIP
podIP: 10.244.3.4
podIP: 10.244.2.5
Kamu dapat melakukan akses dengan ssh ke dalam node di dalam klaster dan mengakses IP Pod tersebut menggunakan curl. Perlu dicatat bahwa kontainer tersebut tidak menggunakan port 80 di dalam node, atau aturan NAT khusus untuk merutekan trafik ke dalam Pod. Ini berarti kamu dapat menjalankan banyak nginx Pod di node yang sama dimana setiap Pod dapat menggunakan containerPort yang sama, kamu dapat mengakses semua itu dari Pod lain ataupun dari node di dalam klaster menggunakan IP. Seperti Docker, port masih dapat di publikasi ke dalam * interface node*, tetapi kebutuhan seperti ini sudah berkurang karena model jaringannya.
Kamu dapat membaca lebih detail bagaimana kita melakukan ini jika kamu penasaran.
Membuat Service
Kita mempunyai Pod yang menjalankan nginx di dalam klaster. Teorinya, kamu dapat berkomunikasi ke Pod tersebut secara langsung, tapi apa yang terjadi jika sebuah node mati? Pod di dalam node tersebut ikut mati, dan Deployment akan membuat Pod baru, dengan IP yang berbeda. Ini adalah masalah yang Service selesaikan.
Service Kubernetes adalah sebuah abstraksi yang mendefinisikan sekumpulan Pod yang menyediakan fungsi yang sama dan berjalan di dalam klaster. Saat dibuat, setiap Service diberikan sebuah alamat IP (disebut juga ClusterIP). Alamat ini akan terus ada, dan tidak akan pernah berubah selama Service hidup. Pod dapat berkomunikasi dengan Service dan trafik yang menuju Service tersebut akan otomatis dilakukan mekanisme load balancing ke Pod yang merupakan anggota dari Service tersebut.
Kamu dapat membuat Service untuk replika 2 nginx dengan kubectl explose
:
kubectl expose deployment/my-nginx
service/my-nginx exposed
Perintah di atas sama dengan kubectl apply -f
dengan yaml sebagai berikut:
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
Spesifikasi ini akan membuat Service yang membuka TCP port 80 di setiap Pod dengan label run: my-nginx
dan mengeksposnya ke dalam port Service (targetPort
: adalah port kontainer yang menerima trafik, port
adalah service port yang dapat berupa port apapun yang digunakan Pod lain untuk mengakses Service).
Lihat Service objek API untuk melihat daftar field apa saja yang didukung di definisi Service. Cek Service kamu:
kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 <none> 80/TCP 21s
Seperti yang disebutkan sebelumnya, sebuah Service berisi sekumpulan Pod. Pod diekspos melalui endpoints
. Service selector akan mengecek Pod secara terus-menerus dan hasilnya akan dikirim (POSTed) ke objek endpoint yang bernama my-nginx
. Saat sebuah Pod mati, IP Pod di dalam endpoint tersebut akan otomatis dihapus, dan Pod baru yang sesuai dengan Service selector akan otomatis ditambahkan ke dalam endpoint. Cek endpoint dan perhatikan bahwa IP sama dengan Pod yang dibuat di langkah pertama:
kubectl describe svc my-nginx
Name: my-nginx
Namespace: default
Labels: run=my-nginx
Annotations: <none>
Selector: run=my-nginx
Type: ClusterIP
IP: 10.0.162.149
Port: <unset> 80/TCP
Endpoints: 10.244.2.5:80,10.244.3.4:80
Session Affinity: None
Events: <none>
kubectl get ep my-nginx
NAME ENDPOINTS AGE
my-nginx 10.244.2.5:80,10.244.3.4:80 1m
Kamu sekarang dapat melakukan curl ke dalam nginx Service di <CLUSTER-IP>:<PORT>
dari node manapun di klaster. Perlu dicatat bahwa Service IP adalah IP virtual, IP tersebut tidak pernah ada di interface node manapun. Jika kamu penasaran bagaimana konsep ini bekerja, kamu dapat membaca lebih lanjut tentang service proxy.
Mengakses Service
Kubernetes mendukung 2 mode utama untuk menemukan sebuah Service - variabel environment dan DNS. DNS membutuhkan tambahan CoreDNS di dalam klaster.
Variabel Environment
Saat sebuah Pod berjalan di Node, kubelet akan menambahkan variabel environment untuk setiap Service yang aktif ke dalam Pod. Ini menimbulkan beberapa masalah. Untuk melihatnya, periksa environment dari Pod nginx yang telah kamu buat (nama Pod-mu akan berbeda-beda):
kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
Perlu dicatat tidak ada variabel environment yang menunjukan Service yang kamu buat. Ini terjadi karena kamu membuat replika terlebih dahulu sebelum membuat Service. Kerugian lain ditimbulkan adalah bahwa komponen scheduler mungkin saja bisa menempatkan semua Pod di dalam satu Node, yang akan membuat keseluruhan Service mati jika Node tersebut mati. Kita dapat menyelesaikan masalah ini dengan menghapus 2 Pod tersebut dan menunggu Deployment untuk membuat Pod kembali. Kali ini Service ada sebelum replika Pod tersebut ada. Ini akan memberikan kamu scheduler-level Service (jika semua Node kamu mempunyai kapasitas yang sama), serta variabel environment yang benar:
kubectl scale deployment my-nginx --replicas=0; kubectl scale deployment my-nginx --replicas=2;
kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-e9ihh 1/1 Running 0 5s 10.244.2.7 kubernetes-minion-ljyd
my-nginx-3800858182-j4rm4 1/1 Running 0 5s 10.244.3.8 kubernetes-minion-905m
Kamu mungkin saja melihat Pod dengan nama yang berbeda, hal ini terjadi karena Pod-Pod itu dihapus dan dibuat ulang.
kubectl exec my-nginx-3800858182-e9ihh -- printenv | grep SERVICE
KUBERNETES_SERVICE_PORT=443
MY_NGINX_SERVICE_HOST=10.0.162.149
KUBERNETES_SERVICE_HOST=10.0.0.1
MY_NGINX_SERVICE_PORT=80
KUBERNETES_SERVICE_PORT_HTTPS=443
DNS
Kubernetes menawarkan sebuah layanan DNS klaster tambahan yang secara otomatis memberikan sebuah nama dns pada Service. Kamu dapat mengecek jika DNS berjalan di dalam klaster Kubernetes:
kubectl get services kube-dns --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.0.0.10 <none> 53/UDP,53/TCP 8m
Jika DNS belum berjalan, kamu dapat mengaktifkannya.
Sisa panduan ini mengasumsikan kamu mempunyai Service dengan IP (my-nginx), dan sebuah server DNS yang memberikan nama ke dalam IP tersebut (CoreDNS klaster), jadi kamu dapat berkomunikasi dengan Service dari Pod lain di dalam klaster menggunakan metode standar (contohnya gethostbyname). Jalankan aplikasi curl lain untuk melakukan pengujian ini:
kubectl run curl --image=radial/busyboxplus:curl -i --tty
Waiting for pod default/curl-131556218-9fnch to be running, status is Pending, pod ready: false
Hit enter for command prompt
Lalu tekan enter dan jalankan nslookup my-nginx
:
[ root@curl-131556218-9fnch:/ ]$ nslookup my-nginx
Server: 10.0.0.10
Address 1: 10.0.0.10
Name: my-nginx
Address 1: 10.0.162.149
Mengamankan Service
Hingga sekarang kita hanya mengakses nginx server dari dalam klaster. Sebelum mengekspos Service ke internet, kamu harus memastikan bahwa kanal komunikasi aman. Untuk melakukan hal tersebut, kamu membutuhkan:
- Self signed certificates untuk https (kecuali jika kamu sudah mempunyai identity certificate)
- Sebuah server nginx yang terkonfigurasi untuk menggunakan certificate tersebut
- Sebuah secret yang membuat setifikat tersebut dapat diakses oleh pod
Kamu dapat melihat semua itu di contoh nginx https. Contoh ini mengaharuskan kamu melakukan instalasi go dan make. Jika kamu tidak ingin melakukan instalasi tersebut, ikuti langkah-langkah manualnya nanti, singkatnya:
make keys KEY=/tmp/nginx.key CERT=/tmp/nginx.crt
kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crt
secret/nginxsecret created
kubectl get secrets
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret Opaque 2 1m
Berikut ini adalah langkah-langkah manual yang harus diikuti jika kamu mengalami masalah menjalankan make (pada windows contohnya):
#membuat sebuah key-pair public private
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /d/tmp/nginx.key -out /d/tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"
#rubah key tersebut ke dalam pengkodean base64
cat /d/tmp/nginx.crt | base64
cat /d/tmp/nginx.key | base64
Gunakan hasil keluaran dari perintah sebelumnya untuk membuat sebuah file yaml seperti berikut. Nilai yang dikodekan base64 harus berada di dalam satu baris.
apiVersion: "v1"
kind: "Secret"
metadata:
name: "nginxsecret"
namespace: "default"
data:
nginx.crt: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURIekNDQWdlZ0F3SUJBZ0lKQUp5M3lQK0pzMlpJTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ1l4RVRBUEJnTlYKQkFNVENHNW5hVzU0YzNaak1SRXdEd1lEVlFRS0V3aHVaMmx1ZUhOMll6QWVGdzB4TnpFd01qWXdOekEzTVRKYQpGdzB4T0RFd01qWXdOekEzTVRKYU1DWXhFVEFQQmdOVkJBTVRDRzVuYVc1NGMzWmpNUkV3RHdZRFZRUUtFd2h1CloybHVlSE4yWXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSjFxSU1SOVdWM0IKMlZIQlRMRmtobDRONXljMEJxYUhIQktMSnJMcy8vdzZhU3hRS29GbHlJSU94NGUrMlN5ajBFcndCLzlYTnBwbQppeW1CL3JkRldkOXg5UWhBQUxCZkVaTmNiV3NsTVFVcnhBZW50VWt1dk1vLzgvMHRpbGhjc3paenJEYVJ4NEo5Ci82UVRtVVI3a0ZTWUpOWTVQZkR3cGc3dlVvaDZmZ1Voam92VG42eHNVR0M2QURVODBpNXFlZWhNeVI1N2lmU2YKNHZpaXdIY3hnL3lZR1JBRS9mRTRqakxCdmdONjc2SU90S01rZXV3R0ljNDFhd05tNnNTSzRqYUNGeGpYSnZaZQp2by9kTlEybHhHWCtKT2l3SEhXbXNhdGp4WTRaNVk3R1ZoK0QrWnYvcW1mMFgvbVY0Rmo1NzV3ajFMWVBocWtsCmdhSXZYRyt4U1FVQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjcKTUI4R0ExVWRJd1FZTUJhQUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjdNQXdHQTFVZEV3UUZNQU1CQWY4dwpEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRVhTMW9FU0lFaXdyMDhWcVA0K2NwTHI3TW5FMTducDBvMm14alFvCjRGb0RvRjdRZnZqeE04Tzd2TjB0clcxb2pGSW0vWDE4ZnZaL3k4ZzVaWG40Vm8zc3hKVmRBcStNZC9jTStzUGEKNmJjTkNUekZqeFpUV0UrKzE5NS9zb2dmOUZ3VDVDK3U2Q3B5N0M3MTZvUXRUakViV05VdEt4cXI0Nk1OZWNCMApwRFhWZmdWQTRadkR4NFo3S2RiZDY5eXM3OVFHYmg5ZW1PZ05NZFlsSUswSGt0ejF5WU4vbVpmK3FqTkJqbWZjCkNnMnlwbGQ0Wi8rUUNQZjl3SkoybFIrY2FnT0R4elBWcGxNSEcybzgvTHFDdnh6elZPUDUxeXdLZEtxaUMwSVEKQ0I5T2wwWW5scE9UNEh1b2hSUzBPOStlMm9KdFZsNUIyczRpbDlhZ3RTVXFxUlU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
nginx.key: "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2RhaURFZlZsZHdkbFIKd1V5eFpJWmVEZWNuTkFhbWh4d1NpeWF5N1AvOE9ta3NVQ3FCWmNpQ0RzZUh2dGtzbzlCSzhBZi9WemFhWm9zcApnZjYzUlZuZmNmVUlRQUN3WHhHVFhHMXJKVEVGSzhRSHA3VkpMcnpLUC9QOUxZcFlYTE0yYzZ3MmtjZUNmZitrCkU1bEVlNUJVbUNUV09UM3c4S1lPNzFLSWVuNEZJWTZMMDUrc2JGQmd1Z0ExUE5JdWFubm9UTWtlZTRuMG4rTDQKb3NCM01ZUDhtQmtRQlAzeE9JNHl3YjREZXUraURyU2pKSHJzQmlIT05Xc0RadXJFaXVJMmdoY1kxeWIyWHI2UAozVFVOcGNSbC9pVG9zQngxcHJHclk4V09HZVdPeGxZZmcvbWIvNnBuOUYvNWxlQlkrZStjSTlTMkQ0YXBKWUdpCkwxeHZzVWtGQWdNQkFBRUNnZ0VBZFhCK0xkbk8ySElOTGo5bWRsb25IUGlHWWVzZ294RGQwci9hQ1Zkank4dlEKTjIwL3FQWkUxek1yall6Ry9kVGhTMmMwc0QxaTBXSjdwR1lGb0xtdXlWTjltY0FXUTM5SjM0VHZaU2FFSWZWNgo5TE1jUHhNTmFsNjRLMFRVbUFQZytGam9QSFlhUUxLOERLOUtnNXNrSE5pOWNzMlY5ckd6VWlVZWtBL0RBUlBTClI3L2ZjUFBacDRuRWVBZmI3WTk1R1llb1p5V21SU3VKdlNyblBESGtUdW1vVlVWdkxMRHRzaG9reUxiTWVtN3oKMmJzVmpwSW1GTHJqbGtmQXlpNHg0WjJrV3YyMFRrdWtsZU1jaVlMbjk4QWxiRi9DSmRLM3QraTRoMTVlR2ZQegpoTnh3bk9QdlVTaDR2Q0o3c2Q5TmtEUGJvS2JneVVHOXBYamZhRGR2UVFLQmdRRFFLM01nUkhkQ1pKNVFqZWFKClFGdXF4cHdnNzhZTjQyL1NwenlUYmtGcVFoQWtyczJxWGx1MDZBRzhrZzIzQkswaHkzaE9zSGgxcXRVK3NHZVAKOWRERHBsUWV0ODZsY2FlR3hoc0V0L1R6cEdtNGFKSm5oNzVVaTVGZk9QTDhPTm1FZ3MxMVRhUldhNzZxelRyMgphRlpjQ2pWV1g0YnRSTHVwSkgrMjZnY0FhUUtCZ1FEQmxVSUUzTnNVOFBBZEYvL25sQVB5VWs1T3lDdWc3dmVyClUycXlrdXFzYnBkSi9hODViT1JhM05IVmpVM25uRGpHVHBWaE9JeXg5TEFrc2RwZEFjVmxvcG9HODhXYk9lMTAKMUdqbnkySmdDK3JVWUZiRGtpUGx1K09IYnRnOXFYcGJMSHBzUVpsMGhucDBYSFNYVm9CMUliQndnMGEyOFVadApCbFBtWmc2d1BRS0JnRHVIUVV2SDZHYTNDVUsxNFdmOFhIcFFnMU16M2VvWTBPQm5iSDRvZUZKZmcraEppSXlnCm9RN3hqWldVR3BIc3AyblRtcHErQWlSNzdyRVhsdlhtOElVU2FsbkNiRGlKY01Pc29RdFBZNS9NczJMRm5LQTQKaENmL0pWb2FtZm1nZEN0ZGtFMXNINE9MR2lJVHdEbTRpb0dWZGIwMllnbzFyb2htNUpLMUI3MkpBb0dBUW01UQpHNDhXOTVhL0w1eSt5dCsyZ3YvUHM2VnBvMjZlTzRNQ3lJazJVem9ZWE9IYnNkODJkaC8xT2sybGdHZlI2K3VuCnc1YytZUXRSTHlhQmd3MUtpbGhFZDBKTWU3cGpUSVpnQWJ0LzVPbnlDak9OVXN2aDJjS2lrQ1Z2dTZsZlBjNkQKckliT2ZIaHhxV0RZK2Q1TGN1YSt2NzJ0RkxhenJsSlBsRzlOZHhrQ2dZRUF5elIzT3UyMDNRVVV6bUlCRkwzZAp4Wm5XZ0JLSEo3TnNxcGFWb2RjL0d5aGVycjFDZzE2MmJaSjJDV2RsZkI0VEdtUjZZdmxTZEFOOFRwUWhFbUtKCnFBLzVzdHdxNWd0WGVLOVJmMWxXK29xNThRNTBxMmk1NVdUTThoSDZhTjlaMTltZ0FGdE5VdGNqQUx2dFYxdEYKWSs4WFJkSHJaRnBIWll2NWkwVW1VbGc9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"
Sekarang buat secrets menggunakan file tersebut:
kubectl apply -f nginxsecrets.yaml
kubectl get secrets
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret Opaque 2 1m
Sekarang modifikasi replika nginx untuk menjalankan server https menggunakan certificate di dalam secret dan Service untuk mengekspos semua port (80 dan 443):
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
type: NodePort
ports:
- port: 8080
targetPort: 80
protocol: TCP
name: http
- port: 443
protocol: TCP
name: https
selector:
run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
volumes:
- name: secret-volume
secret:
secretName: nginxsecret
containers:
- name: nginxhttps
image: bprashanth/nginxhttps:1.0
ports:
- containerPort: 443
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/ssl
name: secret-volume
Berikut catatan penting tentang manifes nginx-secure-app:
- di dalam file tersebut, ada spesifikasi Deployment dan Service
- ada server nginx yang melayani trafik HTTP di port 80 dan trafik HTTPS di port 443, dan Service nginx yang mengekspos kedua port tersebut.
- Setiap kontainer mempunyai akses ke key melalui volume yang di mount pada
/etc/nginx/ssl
. Ini adalah konfigurasi sebelum server nginx dijalankan.
kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml
Pada tahapan ini, kamu dapat berkomunikasi dengan server nginx dari node manapun.
kubectl get pods -o yaml | grep -i podip
podIP: 10.244.3.5
node $ curl -k https://10.244.3.5
...
<h1>Welcome to nginx!</h1>
Perlu dicatat bahwa kita menggunakan parameter -k
saat menggunakan curl, ini karena kita tidak tau apapun tentang Pod yang menjalankan nginx saat pembuatan seritifikat, jadi kita harus memberitahu curl untuk mengabaikan ketidakcocokan CName. Dengan membuat Service, kita menghubungkan CName yang digunakan pada certificate dengan nama pada DNS yang digunakan Pod. Lakukan pengujian dari sebuah Pod (secret yang sama digunakan untuk agar mudah, Pod tersebut hanya membutuhkan nginx.crt untuk mengakses Service)
apiVersion: apps/v1
kind: Deployment
metadata:
name: curl-deployment
spec:
selector:
matchLabels:
app: curlpod
replicas: 1
template:
metadata:
labels:
app: curlpod
spec:
volumes:
- name: secret-volume
secret:
secretName: nginxsecret
containers:
- name: curlpod
command:
- sh
- -c
- while true; do sleep 1; done
image: radial/busyboxplus:curl
volumeMounts:
- mountPath: /etc/nginx/ssl
name: secret-volume
kubectl apply -f ./curlpod.yaml
kubectl get pods -l app=curlpod
NAME READY STATUS RESTARTS AGE
curl-deployment-1515033274-1410r 1/1 Running 0 1m
kubectl exec curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/nginx.crt
...
<title>Welcome to nginx!</title>
...
Mengekspos Service
Kamu mungkin ingin mengekspos Service ke alamat IP eksternal. Kubernetes mendukung dua cara untuk melakukan ini: NodePort dan LoadBalancer. Service yang dibuat tadi sudah menggunakan NodePort
, jadi replika nginx sudah siap untuk menerima trafik dari internet jika Node kamu mempunyai IP publik.
kubectl get svc my-nginx -o yaml | grep nodePort -C 5
uid: 07191fb3-f61a-11e5-8ae5-42010af00002
spec:
clusterIP: 10.0.162.149
ports:
- name: http
nodePort: 31704
port: 8080
protocol: TCP
targetPort: 80
- name: https
nodePort: 32453
port: 443
protocol: TCP
targetPort: 443
selector:
run: my-nginx
kubectl get nodes -o yaml | grep ExternalIP -C 1
- address: 104.197.41.11
type: ExternalIP
allocatable:
--
- address: 23.251.152.56
type: ExternalIP
allocatable:
...
$ curl https://<EXTERNAL-IP>:<NODE-PORT> -k
...
<h1>Welcome to nginx!</h1>
Mari coba membuat ulang Service menggunakan cloud load balancer, ubah saja type
Service my-nginx
dari NodePort
ke LoadBalancer
:
kubectl edit svc my-nginx
kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 162.222.184.144 80/TCP,81/TCP,82/TCP 21s
curl https://<EXTERNAL-IP> -k
...
<title>Welcome to nginx!</title>
IP address pada kolom EXTERNAL-IP
menunjukan IP yang tersedia di internet. Sedangkan kolom CLUSTER-IP
merupakan IP yang hanya tersedia di dalam klaster kamu (IP private).
Perhatikan pada AWS, tipe LoadBalancer
membuat sebuah ELB, yang menggunakan hostname yang panjang, bukan IP. Karena tidak semua keluar pada standar keluaran kubectl get svc
. Jadi kamu harus menggunakan kubectl describe service my-nginx
untuk melihatnya. Kamu akan melihat seperti ini:
kubectl describe service my-nginx
...
LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
...
Selanjutnya
Kubernetes juga mendukung Federated Service, yang bisa mempengaruhi banyak klaster dan penyedia layanan cloud, untuk meningkatkan ketersediaan, peningkatan toleransi kesalahan, dan pengembangan dari Service kamu. Lihat Panduan Federated Service untuk informasi lebih lanjut.
3.5.6 - Ingress
Sebuah obyek API yang mengatur akses eksternal terhadap Service yang ada di dalam klaster, biasanya dalam bentuk request HTTP.
Ingress juga menyediakan load balancing, terminasi SSL, serta name-based virtual hosting.
Terminologi
Untuk memudahkan, di awal akan dijelaskan beberapa terminologi yang sering dipakai:
- Node: Sebuah mesin fisik atau virtual yang berada di dalam klaster Kubernetes.
- Klaster: Sekelompok node yang merupakan resource komputasi primer yang diatur oleh Kubernetes, biasanya diproteksi dari internet dengan menggunakan firewall.
- Edge router: Sebuah router mengatur policy firewall pada klaster kamu. Router ini bisa saja berupa gateway yang diatur oleh penyedia layanan cloud maupun perangkat keras.
- Jaringan klaster: Seperangkat links baik logis maupus fisik, yang memfasilitasi komunikasi di dalam klaster berdasarkan model jaringan Kubernetes.
- Service: Sebuah Service yang mengidentifikasi beberapa Pod dengan menggunakan selector label. Secara umum, semua Service diasumsikan hanya memiliki IP virtual yang hanya dapat diakses dari dalam jaringan klaster.
Apakah Ingress itu?
Ingress ditambahkan sejak Kubernetes v1.1, mengekspos rute HTTP dan HTTPS ke berbagai services di dalam klaster. Mekanisme routing trafik dikendalikan oleh aturan-aturan yang didefinisikan pada Ingress.
internet
|
[ Ingress ]
--|-----|--
[ Services ]
Sebuah Ingress dapat dikonfigurasi agar berbagai Service memiliki URL yang dapat diakses dari eksternal (luar klaster), melakukan load balance pada trafik, terminasi SSL, serta Virtual Host berbasis Nama. Sebuah kontroler Ingress bertanggung jawab untuk menjalankan fungsi Ingress yaitu sebagai loadbalancer, meskipun dapat juga digunakan untuk mengatur edge router atau frontend tambahan untuk menerima trafik.
Sebuah Ingress tidak mengekspos sembarang port atau protokol. Mengekspos Service untuk protokol selain HTTP ke HTTPS internet biasanya dilakukan dengan menggunakan service dengan tipe Service.Type=NodePort atau Service.Type=LoadBalancer.
Prasyarat
Kubernetes v1.1 [beta]
Sebelum kamu mulai menggunakan Ingress, ada beberapa hal yang perlu kamu ketahui sebelumnya. Ingress merupakan resource dengan tipe beta.
GCE/Google Kubernetes Engine melakukan deploy kontroler Ingress pada master. Perhatikan laman berikut keterbatasan versi beta kontroler ini jika kamu menggunakan GCE/GKE.
Jika kamu menggunakan environment selain GCE/Google Kubernetes Engine, kemungkinan besar kamu harus melakukan proses deploy kontroler ingress kamu sendiri. Terdapat beberapa jenis kontroler Ingress yang bisa kamu pilih.
Sebelum kamu memulai
Secara ideal, semua kontroler Ingress harus memenuhi spesifikasi ini, tetapi beberapa kontroler beroperasi sedikit berbeda satu sama lain.
Resource Ingress
Berikut ini merupakan salah satu contoh konfigurasi Ingress yang minimum:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /testpath
backend:
serviceName: test
servicePort: 80
Seperti layaknya resource Kubernetes yang lain, sebuah Ingress membutuhkan field apiVersion
, kind
, dan metadata
.
Untuk informasi umum soal bagaimana cara bekerja dengan menggunakan berkas konfigurasi, silahkan merujuk pada melakukan deploy aplikasi, konfigurasi kontainer, mengatur resource.
Ingress seringkali menggunakan anotasi untuk melakukan konfigurasi beberapa opsi yang ada bergantung pada kontroler Ingress yang digunakan, sebagai contohnya
adalah anotasi rewrite-target.
Kontroler Ingress yang berbeda memiliki jenis anotasi yang berbeda. Pastikan kamu sudah terlebih dahulu memahami dokumentasi
kontroler Ingress yang akan kamu pakai untuk mengetahui jenis anotasi apa sajakah yang disediakan.
Spesifikasi Ingress memiliki segala informasi yang dibutuhkan untuk melakukan proses konfigurasi loadbalancer atau server proxy. Hal yang terpenting adalah bagian inilah yang mengandung semua rules yang nantinya akan digunakan untuk menyesuaikan trafik yang masuk. Resource Ingress hanya menyediakan fitur rules untuk mengarahkan trafik dengan protokol HTTP.
Rule Ingress
Setiap rule HTTP mengandung informasi berikut:
- Host opsional. Di dalam contoh ini, tidak ada host yang diberikan, dengan kata lain, semua rules berlaku untuk inbound trafik HTTP bagi alamat IP yang dispesifikasikan. JIka sebuah host dispesifikasikan (misalnya saja, foo.bar.com), maka rules yang ada akan berlaku bagi host tersebut.
- Sederetan path (misalnya, /testpath), setiap path ini akan memiliki pasangan berupa sebuah backend yang didefinisikan dengan
serviceName
danservicePort
. Baik host dan path harus sesuai dengan konten dari request yang masuk sebelum loadbalancer akan mengarahkan trafik pada service yang sesuai. - Suatu backend adalah kombinasi service dan port seperti yang dideskripsikan di dokumentasi Service. Request HTTP (dan HTTPS) yang sesuai dengan host dan path yang ada pada rule akan diteruskan pada backend terkait.
Backend default seringkali dikonfigurasi pada kontroler kontroler Ingress, tugas backend default ini adalah mengarahkan request yang tidak sesuai dengan path yang tersedia pada spesifikasi.
Backend Default
Sebuah Ingress yang tidak memiliki rules akan mengarahkan semua trafik pada sebuah backend default. Backend default inilah yang biasanya bisa dimasukkan sebagai salah satu opsi konfigurasi dari kontroler Ingress dan tidak dimasukkan dalam spesifikasi resource Ingress.
Jika tidak ada host atau path yang sesuai dengan request HTTP pada objek Ingress, maka trafik tersebut akan diarahkan pada backend default.
Jenis Ingress
Ingress dengan satu Service
Terdapat konsep Kubernetes yang memungkinkan kamu untuk mengekspos sebuah Service, lihat alternatif lain. Kamu juga bisa membuat spesifikasi Ingress dengan backend default yang tidak memiliki rules.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
backend:
serviceName: testsvc
servicePort: 80
Jika kamu menggunakan kubectl apply -f
kamu dapat melihat:
kubectl get ingress test-ingress
NAME HOSTS ADDRESS PORTS AGE
test-ingress * 107.178.254.228 80 59s
Dimana 107.178.254.228
merupakan alamat IP yang dialokasikan oleh kontroler Ingress untuk
memenuhi Ingress ini.
ADDRESS
sebagai <pending>
.
Fanout sederhana
Sebuah konfigurasi fanout akan melakukan route trafik dari sebuah alamat IP ke banyak Service, berdasarkan URI HTTP yang diberikan. Sebuah Ingress memungkinkan kamu untuk memiliki jumlah loadbalancer minimum. Contohnya, konfigurasi seperti di bawah ini:
foo.bar.com -> 178.91.123.132 -> / foo service1:4200
/ bar service2:8080
akan memerlukan konfigurasi Ingress seperti:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: simple-fanout-example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: service1
servicePort: 4200
- path: /bar
backend:
serviceName: service2
servicePort: 8080
Ketika kamu membuat Ingress dengan perintah kubectl apply -f
:
kubectl describe ingress simple-fanout-example
Name: simple-fanout-example
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
Kontroler Ingress akan menyediakan loadbalancer (implementasinya tergantung dari jenis Ingress yang digunakan), selama service-service yang didefinisikan (s1
, s2
) ada.
Apabila Ingress selesai dibuat, maka kamu dapat melihat alamat IP dari berbagai loadbalancer
pada kolom address
.
Virtual Host berbasis Nama
Virtual Host berbasis Nama memungkinkan mekanisme routing berdasarkan trafik HTTP ke beberapa host name dengan alamat IP yang sama.
foo.bar.com --| |-> foo.bar.com s1:80
| 178.91.123.132 |
bar.foo.com --| |-> bar.foo.com s2:80
Ingress di bawah ini memberikan perintah pada loadbalancer untuk melakukan mekanisme routing berdasarkan header host.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
- host: bar.foo.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
Jika kamu membuat sebuah Ingress tanpa mendefinisikan host apa pun, maka
trafik web ke alamat IP dari kontroler Ingress tetap dapat dilakukan tanpa harus
menyesuaikan aturan name based virtual host. Sebagai contoh,
resource Ingress di bawah ini akan melakukan pemetaan trafik
dari first.bar.com
ke service1
, second.foo.com
ke service2
, dan trafik lain
ke alamat IP tanpa host name yang didefinisikan di dalam request (yang tidak memiliki request header) ke service3
.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: first.bar.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
- host: second.foo.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
- http:
paths:
- backend:
serviceName: service3
servicePort: 80
TLS
Kamu dapat mengamankan Ingress yang kamu miliki dengan memberikan spesifikasi secret
yang mengandung private key dan sertifikat TLS. Saat ini, Ingress hanya
memiliki fitur untuk melakukan konfigurasi single TLS port, yaitu 443, serta melakukan terminasi TLS.
Jika section TLS pada Ingress memiliki spesifikasi host yang berbeda,
rules yang ada akan dimultiplekskan pada port yang sama berdasarkan
hostname yang dispesifikasikan melalui ekstensi TLS SNI. Secret TLS harus memiliki
key
bernama tls.crt
dan tls.key
yang mengandung private key dan sertifikat TLS, contohnya:
apiVersion: v1
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
kind: Secret
metadata:
name: testsecret-tls
namespace: default
type: kubernetes.io/tls
Ketika kamu menambahkan secret pada Ingress maka kontroler Ingress akan memberikan perintah untuk
memproteksi channel dari klien ke loadbalancer menggunakan TLS.
Kamu harus memastikan secret TLS yang digunakan memiliki sertifikat yang mengandung
CN untuk sslexample.foo.com
.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- sslexample.foo.com
secretName: testsecret-tls
rules:
- host: sslexample.foo.com
http:
paths:
- path: /
backend:
serviceName: service1
servicePort: 80
Loadbalancing
Sebuah kontroler Ingress sudah dibekali dengan beberapa policy terkait mekanisme load balance yang nantinya akan diterapkan pada semua Ingress, misalnya saja algoritma load balancing, backend weight scheme, dan lain sebagainya. Beberapa konsep load balance yang lebih advance (misalnya saja persistent sessions, dynamic weights) belum diekspos melalui Ingress. Meskipun begitu, kamu masih bisa menggunakan fitur ini melalui loadbalancer service.
Perlu diketahui bahwa meskipun health check tidak diekspos secara langsung melalui Ingress, terdapat beberapa konsep di Kubernetes yang sejalan dengan hal ini, misalnya readiness probes yang memungkinkan kamu untuk memperoleh hasil yang sama. Silahkan pelajari lebih lanjut dokumentasi kontroler yang kamu pakai untuk mengetahui bagaimana implementasi health checks pada kontroler yang kamu pilih (nginx, GCE).
Mengubah Ingress
Untuk mengubah Ingress yang sudah ada dan menambahkan host baru, kamu dapat mengubahnya dengan mode edit:
kubectl describe ingress test
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo s1:80 (10.8.0.90:80)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 35s loadbalancer-controller default/test
kubectl edit ingress test
Sebuah editor akan muncul dan menampilkan konfigurasi Ingress kamu dalam format YAML apabila kamu telah menjalankan perintah di atas. Ubah untuk menambahkan host:
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: s1
servicePort: 80
path: /foo
- host: bar.baz.com
http:
paths:
- backend:
serviceName: s2
servicePort: 80
path: /foo
..
Menyimpan konfigurasi dalam bentuk YAML ini akan mengubah resource pada API server, yang kemudian akan memberi tahu kontroler Ingress untuk mengubah konfigurasi loadbalancer.
kubectl describe ingress test
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo s1:80 (10.8.0.90:80)
bar.baz.com
/foo s2:80 (10.8.0.91:80)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 45s loadbalancer-controller default/test
Kamu juga dapat mengubah Ingress dengan menggunakan perintah kubectl replace -f
pada berkas konfigurasi
Ingress yang ingin diubah.
Mekanisme failing pada beberapa zona availability
Teknik untuk menyeimbangkan persebaran trafik pada failure domain berbeda antar penyedia layanan cloud. Kamu dapat mempelajari dokumentasi yang relevan bagi kontoler Ingress untuk informasi yang lebih detail. Kamu juga dapat mempelajari dokumentasi federasi untuk informasi lebih detail soal bagaimana melakukan deploy untuk federasi klaster.
Pengembangan selanjutnya
Silahkan amati SIG Network untuk detail lebih lanjut mengenai perubahan Ingress dan resource terkait lainnya. Kamu juga bisa melihat repositori Ingress untuk informasi yang lebih detail soal perubahan berbagai kontroler.
Alternatif lain
Kamu dapat mengekspos sebuah Service dalam berbagai cara, tanpa harus menggunakan resource Ingress, dengan menggunakan:
Selanjutnya
3.5.7 - Kontroler Ingress
Agar Ingress dapat bekerja sebagaimana mestinya, sebuah klaster harus memiliki paling tidak sebuah kontroler Ingress.
Berbeda dengan kontroler-kontroler lainnya yang dijalankan
sebagai bagian dari binary kube-controller-manager
, kontroler Ingress
tidak secara otomatis dijalankan di dalam klaster. Kamu bisa menggunakan
laman ini untuk memilih implementasi kontroler Ingress yang kamu pikir
paling sesuai dengan kebutuhan kamu.
Kubernetes sebagai sebuah proyek, saat ini, mendukung dan memaintain kontroler-kontroler GCE dan nginx.
Kontroler-kontroler lainnya
- Ambassador API Gateway merupakan ingress berbasis Envoy kontroler dengan dukungan komunitas atau komersial dari Datawire.
- AppsCode Inc. menawarkan dukungan dan pemeliharaan untuk ingress berbasis HAProxy, Voyager.
- Contour merupakan ingress berbasis Envoy yang disediakan dan didukung oleh VMware.
- Citrix menyediakan sebuah kontroler Ingress untuk perangkat keras (MPX), virtualisasi (VPX) dan kontainerisasi cuma-cuma (CPX) ADC untuk mesin baremetal dan penyedia layanan cloud deployments.
- F5 Networks menyediakan dukungan dan pemeliharaan untuk kontroler F5 BIG-IP bagi Kubernetes.
- Gloo adalah sebuah proyek kontroler Ingress open source berbasis Envoy yang menawarkan fungsionalitas API Gateway dengan dukungan enterprise dari solo.io.
- Kontroler Ingress berbasis HAProxy jcmoraisjr/haproxy-ingress yang disebutkan di dalam artikel HAProxy Ingress Controller for Kubernetes. HAProxy Technologies menawarkan dukungan dan pemeliharaan bagi HAProxy Enterprise dan Ingress kontroler jcmoraisjr/haproxy-ingress.
- Kontroler Ingress berbasis Istio Control Ingress Traffic.
- Kong menawarkan dukungan dan pemeliharaan komunitas atau komersial Kontroler Ingress untuk Kubernetes.
- NGINX, Inc. menawarkan dukungan dan pemeliharaan Kontroler Ingress NGINX untuk Kubernetes.
- Traefik adalah sebuah kontroler Ingress yang menyediakan semua fitur secara lengkap (fully featured) (Let's Encrypt, secrets, http2, websocket), dengan tambahan dukungan komersial oleh Containous.
Menggunakan beberapa jenis kontroler Ingress sekaligus
Kamu dapat melakukan deploy berapa pun banyaknya kontroler Ingress
dalam sebuah klaster. Jika kamu ingin membuat Ingress, kamu tinggal memberikan anotasi setiap Ingress sesuai dengan
ingress.class
yang sesuai untuk menandai kontroler Ingress mana yang digunakan jika terdapat lebih dari satu kontroler Ingress yang ada di
klaster kamu.
Apabila kamu tidak mendefinisikan class
yang dipakai, penyedia layanan cloud kamu akan menggunakan kontroler Ingress default yang mereka miliki.
Idealnya, semua ingress harus memenuhi spesifikasi ini, tetapi berbagai jenis kontroler Ingress bisa saja memiliki sedikit perbedaan cara kerja.
Selanjutnya
- Pelajari Ingress lebih lanjut.
- Melakukan konfigurasi Ingress pada Minikube dengan kontroler NGINX
3.5.8 - NetworkPolicy
Sebuah NetworkPolicy adalah spesifikasi dari sekelompok Pod atau endpoint yang diizinkan untuk saling berkomunikasi.
NetworkPolicy
menggunakan label untuk memilih Pod serta mendefinisikan serangkaian rule yang digunakan
untuk mendefinisikan trafik yang diizinkan untuk suatu Pod tertentu.
Prasyarat
NetworkPolicy diimplementasikan dengan menggunakan plugin jaringan,
dengan demikian kamu harus memiliki penyedia jaringan yang mendukung NetworkPolicy
-
membuat resource tanpa adanya controller tidak akan berdampak apa pun.
Pod yang terisolasi dan tidak terisolasi
Secara default, Pod bersifat tidak terisolasi; Pod-Pod tersebut menerima trafik dari resource apa pun.
Pod menjadi terisolasi apabila terdapat NetworkPolicy
yang dikenakan pada Pod-Pod tersebut.
Apabila terdapat NetworkPolicy
di dalam namespace yang dikenakan pada suatu Pod, Pod tersebut
akan menolak koneksi yang tidak diizinkan NetworkPolicy
. (Pod lain dalam namespace
yang tidak dikenakan NetworkPolicy
akan tetap menerima trafik dari semua resource.)
Resource NetworkPolicy
Lihat NetworkPolicy
untuk definisi lengkap resource.
Sebuah contoh NetworkPolicy
akan terlihat seperti berikut:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
Mengirimkan ini ke API server dengan metode POST tidak akan berdampak apa pun kecuali penyedia jaringan mendukung network policy.
Field-field yang bersifat wajib: Sama dengan seluruh config Kubernetes lainnya, sebuah NetworkPolicy
membutuhkan field-field apiVersion
, kind
, dan metadata
. Informasi generik mengenai
bagaimana bekerja dengan file config
, dapat dilihat di
Konfigurasi Kontainer menggunakan ConfigMap
,
serta Manajemen Objek.
spec: NetworkPolicy
spec memiliki semua informasi yang harus diberikan untuk memberikan definisi network policy yang ada pada namespace tertentu.
podSelector: Setiap NetworkPolicy
memiliki sebuah podSelector
yang bertugas memfilter Pod-Pod yang dikenai policy tersebut. Contoh yang ada memfilter Pod dengan label "role=db"
. Sebuah podSelector
yang empty akan memilih semua Pod yang ada di dalam namespace.
policyTypes: Setiap NetworkPolicy
memiliki sebuah daftar policyTypes
yang dapat berupa Ingress
, Egress
, atau keduanya. Field policyTypes
mengindikasikan apakah suatu policy diberikan pada trafik ingress, egress, atau camputan ingress dan egress pada Pod tertentu. Jika tidak ada policyTypes
tyang diberikan pada NetworkPolicy
maka Ingress
default akan diterapkan dan Egress
akan diterapkan apabila policy tersebut memberikan spesifikasi egress.
ingress: Setiap NetworkPolicy
bisa saja memberikan serangkaian whitelist rule-rule ingress
. Setiap rule mengizinkan trafik yang sesuai dengan section from
dan ports
. Contoh policy yang diberikan memiliki sebuah rule, yang sesuai dengan trafik pada sebuah port
single, bagian pertama dispesifikasikan melalui ipBlock
, yang kedua melalui namespaceSelector
dan yang ketiga melalui podSelector
.
egress: Setiap NetworkPolicy
bisa saja meliputi serangkaian whitelist rule-rule egress
. Setiap rule mengizinkan trafik yang sesuai dengan section to
dan ports
. Contoh policy yang diberikan memiliki sebuah rule, yang sesuai dengan port
single pada destinasi 10.0.0.0/24
.
Pada contoh, NetworkPolicy
melakukan hal berikut:
-
Mengisolasi Pod-Pod dengan label
"role=db"
pada namespace"default"
baik untukingress
atauegress
. -
(Rule
Ingress
) mengizinkan koneksi ke semua Pod pada namespace“default”
dengan label“role=db”
untuk protokol TCPport
6379
dari:- semua Pod pada namespace
"default"
dengan label"role=frontend"
- semua Pod dalam sebuah namespace dengan label
"project=myproject"
- alamat IP pada range
172.17.0.0–172.17.0.255
dan172.17.2.0–172.17.255.255
(yaitu, semua172.17.0.0/16
kecuali172.17.1.0/24
)
- semua Pod pada namespace
-
(Rule Egress) mengizinkan koneksi dari semua Pod pada namespace
"default"
dengan label"role=db"
ke CIDR10.0.0.0/24
untuk protokol TCP padaport
5978
Lihat mekanisme Deklarasi Network Policy untuk penjelasan lebih mendalam.
Perilaku selektor to
dan from
Terdapat empat jenis selektor yang dapat dispesifikasikan dalam section
ingress
from
atau section
egress
to
:
podSelector: Ini digunakan untuk memfilter Pod tertentu pada namespace dimana NetworkPolicy
berada yang akan mengatur destinasi ingress atau egress.
namespaceSelector: Ini digunakan untuk memfilter namespace tertentu dimana semua Pod diperbolehkan sebagai source ingress
atau destinasi egress
.
namespaceSelector and podSelector: Sebuah entri to
/from
yang memberikan spesifikasi namespaceSelector
dan podSelector
serta memilih Pod-Pod tertentu yang ada di dalam namespace. Pastikan kamu menggunakan sintaks YAML yang tepat; policy
ini:
...
ingress:
- from:
- namespaceSelector:
matchLabels:
user: alice
podSelector:
matchLabels:
role: client
...
mengandung sebuah elemen from
yang mengizinkan koneksi dari Pod-Pod dengan label role=client
di namespace dengan label user=alice
. Akan tetapi, policy ini:
...
ingress:
- from:
- namespaceSelector:
matchLabels:
user: alice
- podSelector:
matchLabels:
role: client
...
mengandung dua elemen pada array from
, dan mengizinkan koneksi dari Pod pada Namespace lokal dengan label
role=client
, atau dari Pod di namespace apa pun dengan label user=alice
.
Ketika kamu merasa ragu, gunakan kubectl describe
untuk melihat bagaimana Kubernetes
menginterpretasikan policy tersebut.
ipBlock: Ini digunakan untuk memilih range IP CIDR tertentu untuk berperan sebagai source ingress atau destinasi egress. Alamat yang digunakan harus merupakan alamat IP eksternal klaster, karena alamat IP Pod bersifat ephemeral dan tidak dapat ditebak.
Mekanisme ingress dan egress klaster seringkali membutuhkan mekanisme rewrite alamat IP source dan destinasi
paket. Pada kasus-kasus dimana hal ini, tidak dapat dipastikan bahwa apakah hal ini
terjadi sebelum atau setelah pemrosesan NetworkPolicy
, dan perilaku yang ada mungkin saja berbeda
untuk kombinasi plugin jaringan, penyedia layanan cloud, serta implementasi Service
yang berbeda.
Pada ingress, artinya bisa saja kamu melakukan filter paket yang masuk berdasarkan source IP
,
sementara di kasus lain "source IP" yang digunakan oleh Network Policy adalah alamat IP LoadBalancer
,
node dimana Pod berada, dsb.
Pada egress, bisa saja sebuah koneksi dari Pod ke IP Service
di-rewrite ke IP eksternal klaster
atau bahkan tidak termasuk di dalam ipBlock
policy.
Policy Default
Secara default, jika tidak ada policy yang ada dalam suatu namespace, maka semua trafik ingress dan egress yang diizinkan ke atau dari Pod dalam namespace. Contoh di bawah ini akan memberikan gambaran bagaimana kamu dapat mengubah perilaku default pada sebuah namespace.
Default: tolak semua trafik ingress
Kamu dapat membuat policy isolasi "default"
untuk sebuah namespace
dengan membuat sebuah NetworkPolicy
yang memilih semua Pod tapi tidak mengizinkan
trafik ingress masuk ke Pod-Pod tersebut.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
Hal ini menjamin bahwa bahkan Pod yang tidak dipilih oleh NetworkPolicy
lain masih terisolasi.
Policy ini tidak mengubah perilaku default dari egress.
Default: izinkan semua trafik ingress
Jika kamu ingin mengizinkan semua trafik ingress pada semua Pod dalam sebuah namespace (bahkan jika policy ditambahkan dan menyebabkan beberapa Pod menjadi terisolasi), kamu dapat secara eksplisit mengizinkan semua trafik bagi namespace tersebut.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
ingress:
- {}
policyTypes:
- Ingress
Default: tolak semua trafik egress
Kamu dapat membuat policy isolasi "default"
untuk sebuah namespace
dengan membuat sebuah NetworkPolicy
yang memilih semua Pod tapi tidak mengizinkan
trafik egress keluar dari Pod-Pod tersebut.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Egress
Hal ini menjamin bahwa bahkan Pod yang tidak dipilih oleh NetworkPolicy
lain masih terisolasi.
Policy ini tidak mengubah perilaku default dari ingress.
Default: izinkan semua trafik egress
Jika kamu ingin mengizinkan semua trafik egress pada semua Pod dalam sebuah namespace (bahkan jika policy ditambahkan dan menyebabkan beberapa Pod menjadi terisolasi), kamu dapat secara eksplisit mengizinkan semua trafik bagi namespace tersebut.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
egress:
- {}
policyTypes:
- Egress
Default: tolak semua trafik ingress dan egress
Kamu dapat membuat sebuah policy "default" jika kamu ingin menolak semua trafik ingress maupun egress pada semua Pod dalam sebuah namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Hal ini menjamin bahwa bahkan Pod yang tidak dipilih oleh NetworkPolicy
tidak akan mengizinkan trafik ingress atau egress.
Dukungan terhadap SCTP
Kubernetes v1.12 [alpha]
Kubernetes mendukung SCTP sebagai value protocol
pada definisi NetworkPolicy
sebagai fitur alpha. Untuk mengaktifkan fitur ini, administrator klaster harus mengaktifkan gerbang fitur SCTPSupport
pada apiserver
, contohnya “--feature-gates=SCTPSupport=true,...”
. Ketika gerbang fitur ini diaktifkan, pengguna dapat menerapkan value
dari field protocol
pada NetworkPolicy
menjadi SCTP
. Kubernetes akan mengatur jaringan sesuai dengan SCTP, seperti halnya koneksi TCP.
Plugin CNI harus mendukung SCTP sebagai value dari protocol
pada NetworkPolicy
.
Selanjutnya
- Lihat Deklarasi Network Policy untuk melihat lebih banyak contoh penggunaan.
- Baca lebih lanjut soal panduan bagi skenario generik resource
NetworkPolicy
.
3.5.9 - Menambahkan Entry pada /etc/hosts Pod dengan HostAliases
Menambahkan entri pada berkas /etc/hosts Pod akan melakukan override resolusi hostname pada level Pod ketika DNS dan opsi lainnya tidak tersedia. Pada versi 1.7, pengguna dapat menambahkan entri yang diinginkan beserta field HostAliases pada PodSpec.
Modifikasi yang dilakukan tanpa menggunakan HostAliases tidaklah disarankan karena berkas ini diatur oleh Kubelet dan dapat di-override ketika Pod dibuat/di-restart.
Isi Default pada Berkas Hosts
Misalnya saja kamu mempunyai sebuah Pod Nginx yang memiliki sebuah IP Pod:
kubectl run nginx --image nginx --generator=run-pod/v1
pod/nginx created
Perhatikan IP Pod tersebut:
kubectl get pods --output=wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
File hosts
yang ada akan tampak sebagai berikut:
kubectl exec nginx -- cat /etc/hosts
# Berkas hosts yang dikelola Kubernetes
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.200.0.4 nginx
Secara default, berkas hosts
hanya berisikan boilerplate alamat IP IPv4 and IPv6 seperti
localhost
dan hostname dari Pod itu sendiri.
Menambahkan Entri Tambahan dengan HostAliases
Selain boilerplate default, kita dapat menambahkan entri pada berkas
hosts
untuk melakukan resolusi foo.local
, bar.local
pada 127.0.0.1
dan foo.remote
,
bar.remote
pada 10.1.2.3
, kita dapat melakukannya dengan cara menambahkan
HostAliases pada Pod di bawah field .spec.hostAliases
:
apiVersion: v1
kind: Pod
metadata:
name: hostaliases-pod
spec:
restartPolicy: Never
hostAliases:
- ip: "127.0.0.1"
hostnames:
- "foo.local"
- "bar.local"
- ip: "10.1.2.3"
hostnames:
- "foo.remote"
- "bar.remote"
containers:
- name: cat-hosts
image: busybox
command:
- cat
args:
- "/etc/hosts"
Pod ini kemudian dapat dihidupkan dengan perintah berikut:
kubectl apply -f hostaliases-pod.yaml
pod/hostaliases-pod created
Perhatikan IP dan status Pod tersebut:
kubectl get pod --output=wide
NAME READY STATUS RESTARTS AGE IP NODE
hostaliases-pod 0/1 Completed 0 6s 10.200.0.5 worker0
File hosts
yang ada akan tampak sebagai berikut:
kubectl logs hostaliases-pod
# Berkas hosts yang dikelola Kubernetes
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.200.0.5 hostaliases-pod
# Entries added by HostAliases.
127.0.0.1 foo.local bar.local
10.1.2.3 foo.remote bar.remote
Dengan tambahan entri yang telah dispesifikasikan sebelumnya.
Kenapa Kubelet Melakukan Mekanisme Manajemen Berkas Hosts
?
Kubelet melakukan proses manajemen
berkas hosts
untuk setiap container yang ada pada Pod untuk mencegah Docker melakukan
modifikasi pada berkas tersebut
setelah kontainer dihidupkan.
Karena sifat dari berkas tersebut yang secara otomatis di-manage,
semua hal yang didefinisikan oleh pengguna akan ditimpa (overwrite) ketika berkas
hosts
di-mount kembali oleh Kubelet ketika ada kontainer yang di-restart
atau Pod di-schedule ulang. Dengan demikian tidak dianjurkan untuk
memodifikasi berkas tersebut secara langsung.
3.5.10 - Dual-stack IPv4/IPv6
Kubernetes v1.16 [alpha]
Dual-stack IPv4/IPv6 memungkinkan pengalokasian alamat IPv4 dan IPv6 untuk Pod dan Service.
Jika kamu mengaktifkan jaringan dual-stack IPv4/IPv6 untuk klaster Kubernetes kamu, klaster akan mendukung pengalokasian kedua alamat IPv4 dan IPv6 secara bersamaan.
Fitur-fitur yang didukung
Mengaktifkan dual-stack IPv4 / IPv6 pada klaster Kubernetes kamu untuk menyediakan fitur-fitur berikut ini:
- Jaringan Pod dual-stack (pengalokasian sebuah alamat IPv4 dan IPv6 untuk setiap Pod)
- Service yang mendukung IPv4 dan IPv6 (setiap Service hanya untuk satu keluarga alamat)
- Perutean Pod ke luar klaster (misalnya Internet) melalui antarmuka IPv4 dan IPv6
Prasyarat
Prasyarat berikut diperlukan untuk menggunakan dual-stack IPv4/IPv6 pada klaster Kubernetes :
- Kubernetes versi 1.16 atau yang lebih baru
- Dukungan dari penyedia layanan untuk jaringan dual-stack (Penyedia layanan cloud atau yang lainnya harus dapat menyediakan antarmuka jaringan IPv4/IPv6 yang dapat dirutekan) untuk Node Kubernetes
- Sebuah plugin jaringan yang mendukung dual-stack (seperti Kubenet atau Calico)
- Kube-proxy yang berjalan dalam mode IPVS
Mengaktifkan dual-stack IPv4/IPv6
Untuk mengaktifkan dual-stack IPv4/IPv6, aktifkan gerbang fitur (feature gate) IPv6DualStack
untuk komponen-komponen yang relevan dari klaster kamu, dan tetapkan jaringan
dual-stack pada klaster:
- kube-controller-manager:
--feature-gates="IPv6DualStack=true"
--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>
misalnya--cluster-cidr=10.244.0.0/16,fc00::/24
--service-cluster-ip-range=<IPv4 CIDR>,<IPv6 CIDR>
--node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6
nilai bawaannya adalah /24 untuk IPv4 dan /64 untuk IPv6
- kubelet:
--feature-gates="IPv6DualStack=true"
- kube-proxy:
--proxy-mode=ipvs
--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>
--feature-gates="IPv6DualStack=true"
--cluster-cidr
pada baris perintah, maka penetapan tersebut akan gagal.
Service
Jika klaster kamu mengaktifkan jaringan dual-stack IPv4/IPv6, maka kamu dapat
membuat Service dengan
alamat IPv4 atau IPv6. Kamu dapat memilih keluarga alamat untuk clusterIP
Service kamu dengan mengatur bagian, .spec.ipFamily
, pada Service tersebut.
Kamu hanya dapat mengatur bagian ini saat membuat Service baru. Mengatur bagian
.spec.ipFamily
bersifat opsional dan hanya boleh digunakan jika kamu berencana
untuk mengaktifkan Service
dan Ingress IPv4 dan IPv6
pada klaster kamu. Konfigurasi bagian ini bukanlah syarat untuk lalu lintas
[egress] (#lalu-lintas-egress).
--service-cluster-ip-range
pada kube-controller-manager.
Kamu dapat mengatur .spec.ipFamily
menjadi salah satu dari:
IPv4
: Dimana server API akan mengalokasikan IP dariservice-cluster-ip-range
yaituipv4
IPv6
: Dimana server API akan mengalokasikan IP dariservice-cluster-ip-range
yaituipv6
Spesifikasi Service berikut ini tidak memasukkan bagian ipFamily
.
Kubernetes akan mengalokasikan alamat IP (atau yang dikenal juga sebagai
"cluster IP") dari service-cluster-ip-range
yang dikonfigurasi pertama kali
untuk Service ini.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
Spesifikasi Service berikut memasukkan bagian ipFamily
. Sehingga Kubernetes
akan mengalokasikan alamat IPv6 (atau yang dikenal juga sebagai "cluster IP")
dari service-cluster-ip-range
yang dikonfigurasi untuk Service ini.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ipFamily: IPv6
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
Sebagai perbandingan, spesifikasi Service berikut ini akan dialokasikan sebuah alamat
IPv4 (atau yang dikenal juga sebagai "cluster IP") dari service-cluster-ip-range
yang dikonfigurasi untuk Service ini.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ipFamily: IPv4
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
Tipe LoadBalancer
Penyedia layanan cloud yang mendukung IPv6 untuk pengaturan beban eksternal,
Mengatur bagian type
menjadi LoadBalancer
sebagai tambahan terhadap mengatur bagian
ipFamily
menjadi IPv6
menyediakan sebuah cloud load balancer untuk Service kamu.
Lalu lintas egress
Penggunaan blok alamat IPv6 yang dapat dirutekan dan yang tidak dapat dirutekan secara publik diperbolehkan selama CNI dari penyedia layanan dapat mengimplementasikan transportasinya. Jika kamu memiliki Pod yang menggunakan IPv6 yang dapat dirutekan secara publik dan ingin agar Pod mencapai tujuan di luar klaster (misalnya Internet publik), kamu harus mengatur IP samaran untuk lalu lintas keluar dan balasannya. ip-masq-agent bersifat dual-stack aware, jadi kamu bisa menggunakan ip-masq-agent untuk masquerading IP dari klaster dual-stack.
Masalah-masalah yang diketahui
- Kubenet memaksa pelaporan posisi IP untuk IPv4,IPv6 IP (--cluster-cidr)
Selanjutnya
3.6 - Storage
3.6.1 - Volume
Berkas-berkas yang disimpan di disk di dalam Container bersifat tidak permanen (akan terhapus seiring dengan dihapusnya Container/Pod), yang menimbulkan beberapa masalah untuk aplikasi biasa saat berjalan di dalam Container. Pertama, saat sebuah Container mengalami kegagalan, Kubelet akan memulai kembali Container tersebut, tetapi semua berkas di dalamnya akan hilang - Container berjalan dalam kondisi yang bersih. Kedua, saat menjalankan banyak Container bersamaan di dalam sebuah Pod
, biasanya diperlukan untuk saling berbagi berkas-berkas di antara Container-container tersebut. Kedua masalah tersebut dipecahkan oleh abstraksi Volume
pada Kubernetes.
Pengetahuan tentang Pod disarankan.
Latar Belakang
Docker juga memiliki konsep volume, walaupun konsepnya Docker agak lebih fleksibel dan kurang dikelola. Pada Docker, sebuah volume adalah sesederhana sebuah direktori pada disk atau di dalam Container lainnya. Lifetime tidak dikelola dan hingga baru-baru ini hanya ada volume yang didukung disk lokal. Docker sekarang menyediakan driver untuk volume, namun fungsionalitasnya masih sangat terbatas (misalnya hingga Docker 1.7 hanya ada satu driver volume yang diizinkan untuk setiap Container, dan tidak ada cara untuk menyampaikan parameter kepada volume).
Sebaliknya, sebuah Volume Kubernetes memiliki lifetime yang gamblang - sama dengan lifetime Pod yang berisi Volume tersebut. Oleh karena itu, sebuah Volume bertahan lebih lama dari Container-container yang berjalan di dalam Pod tersebut, dan data di Volum tersebut juga dipertahankan melewati diulangnya Container. Tentu saja, saat sebuah Pod berakhir, Volume tersebut juga akan berakhir/terhapus. Dan mungkin lebih penting lagi, Kubernetes mendukung banyak jenis Volume, dan sebuah Pod dapat menggunakan sebanyak apapun Volume secara bersamaan.
Pada intinya, sebuah volume hanyalah sebuah direktori, dan mungkin berisi data, yang dapat diakses oleh Container-container di dalam Pod. Bagaimana direktori tersebut dibuat, medium yang menyokongnya, dan isinya ditentukan oleh jenis volume yang digunakan.
Untuk menggunakan sebuah volume, sebuah Pod memerinci volume-volume yang akan disediakan untuk Pod tersebut (kolom .spec.volumes
) dan di mana volume-volume tersebut akan ditambatkan (di-mount) di dalam Container-container di Pod (kolom .spec.containers.volumeMounts
).
Sebuah proses di dalam Container memiliki sudut pandang filesystem yang disusun dari image dan volume Dockernya. Docker Image berada pada bagian teratas hierarki filesystem, dan volume manapun yang ditambatkan pada path yang diperinci di dalam Image tersebut. Volume tidak dapat ditambatkan pada volume lain atau memiliki hard link ke volume lain. Setiap Container di dalam Pod harus secara independen memerinci di mana tiap Volume ditambatkan.
Jenis-jenis Volume
Kubernetes mendukung beberapa jenis Volume:
- awsElasticBlockStore
- azureDisk
- azureFile
- cephfs
- cinder
- configMap
- csi
- downwardAPI
- emptyDir
- fc (fibre channel)
- flexVolume
- flocker
- gcePersistentDisk
- gitRepo (deprecated)
- glusterfs
- hostPath
- iscsi
- local
- nfs
- persistentVolumeClaim
- projected
- portworxVolume
- quobyte
- rbd
- scaleIO
- secret
- storageos
- vsphereVolume
Kami menyambut kontribusi tambahan.
awsElasticBlockStore
Sebuah Volume awsElasticBlockStore
menambatkan sebuah Volume EBS Amazon Web Services (AWS) ke dalam Pod kamu. Hal ini berarti bahwa sebuah Volume EBS dapat sebelumnya diisi terlebih dahulu dengan data, dan data dapat "dipindahkan" diantara banyak Pod.
awscli
dengan perintah aws ec2 create-volume
atau menggunakan AWS API sebelum kamu dapat menggunakannya.
Ada beberapa batasan saat menggunakan Volume awsElasticBlockStore
:
- Node di mana Pod berjalan haruslah merupakan instance AWS EC2.
- Instance tersebut mesti berada pada region dan availability-zone yang sama dengan volume EBS.
- EBS hanya mendukung penambatan pada satu instance EC2 pada saat yang bersamaan.
Membuat sebuah Volume EBS
Sebelum kamu dapat menggunakan sebuah volume EBS pada sebuah Pod, kamu harus membuatnya pada AWS terlebih dahulu.
aws ec2 create-volume --availability-zone=eu-west-1a --size=10 --volume-type=gp2
Pastikan availability zone yang kamu masukkan sama dengan availability zone klaster kamu. (Dan pastikan juga ukuran dan jenis EBSnya sesuai dengan penggunaan yang kamu butuhkan!)
Contoh Konfigurasi AWS EBS
apiVersion: v1
kind: Pod
metadata:
name: test-ebs
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-ebs
name: test-volume
volumes:
- name: test-volume
# volume EBS ini harus sudah dibuat di AWS
awsElasticBlockStore:
volumeID: <volume-id>
fsType: ext4
Migrasi CSI awsElasticBlocStore
Kubernetes v1.14 [alpha]
Pada saat fitur migrasi CSI (Container Storage Interface) untuk awsElasticBlockStore
diaktifkan, fitur ini akan menterjemahkan semua operasi plugin dari plugin yang sudah ada di kode inti Kubernetes ke bentuk Driver CSI ebs.csi.aws.com
. Untuk menggunakan fitur ini, Driver CSI AWS EBS harus dinstal di klaster dan fitur Alpha CSIMigration
serta CSIMigrationAWS
harus diaktifkan.
azureDisk
Sebuah azureDisk
digunakan untuk menambatkan sebuah Data Disk Microsoft Azure ke dalam sebuah Pod.
Selengkapnya dapat ditemukan di sini.
Migrasi CSI azureDisk
Kubernetes v1.15 [alpha]
Pada saat fitur migrasi CSI untuk azureDisk
diaktifkan, fitur ini akan menterjemahkan semua operasi plugin dari plugin yang sudah ada di kode inti Kubernetes ke bentuk Driver CSI disk.csi.azure.com
. Untuk menggunakan fitur ini, Driver CSI Azure Disk harus dinstal di klaster dan fitur Alpha CSIMigration
serta CSIMigrationAzureDisk
harus diaktifkan.
azureFile
Sebuah azureFile
digunakan untuk menambatkan sebuah Microsoft Azure File Volume (SMB 2.1 dan 3.0) ke dalam sebuah Pod.
Selengkapnya dapat ditemukan di sini.
Migrasi CSI azureFile
Kubernetes v1.15 [alpha]
Pada saat fitur migrasi CSI untuk azureFile
diaktifkan, fitur ini akan menterjemahkan semua operasi plugin dari plugin yang sudah ada di kode inti Kubernetes ke bentuk Driver CSI file.csi.azure.com
. Untuk menggunakan fitur ini, Driver CSI Azure File harus dinstal di klaster dan fitur Alpha CSIMigration
serta CSIMigrationAzureFile
harus diaktifkan.
cephfs
Sebuah Volume cephfs
memungkinkan sebuah volume CephFS yang sudah ada untuk ditambatkan ke dalam Pod kamu. Berbeda dengan emptyDir
, yang juga ikut dihapus saat Pod dihapus, isi data di dalam sebuah volume CephFS akan dipertahankan dan Volume tersebut hanya dilepaskan tambatannya (mount-nya). Hal ini berarti bahwa sebuah Volume CephFS dapat sebelumnya diisi terlebih dahulu dengan data, dan data dapat "dipindahkan" diantara banyak Pod.
Selengkapnya, lihat contoh CephFS.
cinder
cinder
digunakan untuk menambatkan Volume Cinder ke dalam Pod kamu.
Contoh Konfigurasi Volume Cinder
apiVersion: v1
kind: Pod
metadata:
name: test-cinder
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-cinder-container
volumeMounts:
- mountPath: /test-cinder
name: test-volume
volumes:
- name: test-volume
# Volume OpenStack ini harus sudah ada sebelumnya.
cinder:
volumeID: <volume-id>
fsType: ext4
Migrasi CSI Cinder
Kubernetes v1.14 [alpha]
Pada saat fitur migrasi CSI untuk Cinder diaktifkan, fitur ini akan menterjemahkan semua operasi plugin dari plugin yang sudah ada di kode inti Kubernetes ke bentuk Driver CSI cinder.csi.openstack.com
. Untuk menggunakan fitur ini, Driver CSI Openstack Cinder harus dinstal di klaster dan fitur Alpha CSIMigration
serta CSIMigrationOpenStack
harus diaktifkan.
configMap
Sumber daya configMap
memungkinkan kamu untuk menyuntikkan data konfigurasi ke dalam Pod.
Data yang ditaruh di dalam sebuah objek ConfigMap
dapat dirujuk dalam sebuah Volume dengan tipe configMap
dan kemudian digunakan oleh aplikasi/container yang berjalan di dalam sebuah Pod.
Saat mereferensikan sebuah objek configMap
, kamu tinggal memasukkan nama ConfigMap tersebut ke dalam rincian Volume yang bersangkutan. Kamu juga dapat mengganti path spesifik yang akan digunakan pada ConfigMap. Misalnya, untuk menambatkan ConfigMap log-config
pada Pod yang diberi nama configmap-pod
, kamu dapat menggunakan YAML ini:
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: test
image: busybox
volumeMounts:
- name: config-vol
mountPath: /etc/config
volumes:
- name: config-vol
configMap:
name: log-config
items:
- key: log_level
path: log_level
ConfigMap log-config
ditambatkan sebagai sebuah Volume, dan semua isinya yang ditaruh di dalam entri log_level
-nya ditambatkan dalam Pod tersebut pada path "/etc/config/log_level
".
Perlu dicatat bahwa path tersebut berasal dari isian mountPath
pada Volume, dan path
yang ditunjuk dengan key
bernama log_level
.
downwardAPI
Sebuah Volume downwardAPI
digunakan untuk menyediakan data downward API
kepada aplikasi.
Volume ini menambatkan sebuah direktori dan menulis data yang diminta pada berkas-berkas teks biasa.
Lihat contoh Volume downwardAPI
untuk lebih detilnya.
emptyDir
Sebuah Volume emptyDir
pertama kali dibuat saat sebuah Pod dimasukkan ke dalam sebuah Node, dan akan terus ada selama Pod tersebut berjalan di Node tersebut. Sesuai dengan namanya, Volume ini awalnya kosong. Container-container di dalam Pod dapat membaca dan menulis berkas-berkas yang sama di dalam Volume emptyDir
, walaupun Volume tersebut dapat ditambatkan pada path
yang sama maupun berbeda pada setiap Container. Saat sebuah Pod dihapus dari sebuah Node untuk alasan apapun, data di dalam emptyDir
tersebut dihapus untuk selamanya.
emptyDir
akan aman jika Container di dalam Podnya gagal.
Beberapa kegunaan emptyDir
adalah sebagai berikut:
- Scratch space, misalnya untuk merge sort menggunakan berkas-berkas di disk
- Checkpointing untuk komputasi panjang yang dipulihkan dari proses yang sebelumnya mengalami kegagalan
- Menyimpan berkas-berkas yang diambil oleh Container aplikasi Content Manager saat sebuah peladen web melayani data tersebut
Secara bawaan, emptyDir
ditaruh pada media penyimpanan apapun yang menyokong Node yang bersangkuta - mungkin sebuah disk atau SSD atau penyimpanan berbasis jaringan, tergantung lingkungan Node yang kamu miliki. Tetapi, kamu juga dapat menyetel bagian emptyDir.medium
menjadi "Memory"
untuk memberitahukan pada Kubernetes untuk menggunakan sebuah tmpfs
(filesystem berbasis RAM) sebagai gantinya. tmpfs
memang sangan cepat, tetapi kamu harus sadar bahwa ia tidak seperti disk, data di tmpfs
akan terhapus saat Node tersebut diulang kembali. Selain itu, berkas apapun yang kamu tulis akan dihitung terhadap limit
memory
milik Container kamu.
Contoh Pod
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
fc (fibre channel)
Sebuah Volume fc
memunginkan sebuah volume fibre channel yang sudah ada untuk ditambatkan ke sebuah Pod.
Kamu dapat menentukan satu atau banyak target World Wide Names menggunakan parameter targetWWNs
pada konfigurasi Volume kamu. Jika banyak WWN ditentukan, maka targetWWNs
mengharapkan bahwa WWN tersebut berasal dari koneksi multi-path.
Lihat Contoh FC untuk lebih detilnya.
flocker
Flocker adalah sebuah proyek open-source yg berfungsi sebagai pengatur volume data Container yang diklasterkan. Flocker menyediakan pengelolaan dan orkestrasi volume yang disokong oleh banyak jenis media penyimpanan.
Sebuah Volume flockere
memungkinkan sebuah dataset Flocker untuk ditambatkan ke dalam sebuah Pod. Jika dataset tersebut belum ada di dalam Flocker, maka ia harus dibuat terlebih dahulu dengan menggunakan Flocker CLI atau menggunakan Flocker API. Jika dataset tersebut sudah ada, ia akan ditambatkan kembali oleh Flocker ke Node di mana Pod tersebut dijadwalkan. Hal ini berarti data dapat dioper diantara Pod-pod sesuai dengan kebutuhan.
Lihat Contoh Flocker untuk lebih detil.
gcePersistentDisk
Sebuah volume gcePersistentDisk
menambatkan sebuah PersistentDisk Google Compute Engine (GCE) ke dalam Pod kamu. Tidak seperti emptyDir
yang ikut dihapus saat Pod dihapus, isi dari sebuah PD dipertahankan dan volume-nya hanya dilepaskan tambatannya. Hal ini berarti sebuah PD dapat diisi terlebih dahulu dengan data, dan data tersebut dapat "dioper" diantara Pod-pod.
gcloud
atau GCE API atau GCP UI sebelum kamu dapat menggunakannya.
Ada beberapa batasan saat menggunakan sebuah gcePersistentDisk
:
- Node-node di mana Pod-pod berjalan haruslah GCE VM.
- VM tersebut harus berada pada proyek GCE yang sama dan zone yang sama dengan PD tersebut
Sebuah fitur PD yaitu mereka dapat ditambatkan sebagai read-only secara bersamaan oleh beberapa pengguna. Hal ini berarti kamu dapat mengisi data terlebih dahulu dan menyediakan data tersebut secara paralel untuk sebanyak apapun Pod yang kamu butuhkan. Sayangnya, PD hanya dapat ditambatkan kepada satu pengguna saja pada mode read-write - yaitu, tidak boleh ada banyak penulis secara bersamaan.
Menggunakan sebuah PD pada sebuah Pod yang diatur oleh sebuah ReplicationController
akan gagal, kecuali jika PD tersebut berada pada mode read-only
, atau jumlah replica
-nya adalah 0 atau 1.
Membuat sebuah PD
Sebelum kamu dapat menggunakan sebuah PD dengan sebuah Pod, kamu harus membuat PD tersebut terlebih dahulu.
gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk
Contoh Pod
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
# GCE PD ini harus sudah ada.
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4
Regional Persistent Disks
Kubernetes v1.10 [beta]
Fitur Regional Persistent Disks memungkinkan pembuatan Persistent Disk yang berada pada beberapa zone pada region yang sama. Untuk menggunakan fitur ini, Volume tersebut harus dibuat sebagai sebuah PersistentVolume; mereferensikan Volume tersebut langsung dari sebuah Pod tidak didukung.
Menyediakan sebuah Regional PD PersistentVolume Secara Manual
Penyediaan secara dinamis mungkin dilakukan dengan sebuah StorageClass untuk GCE PD. Sebelum membuat sebuah PersistentVolume, kamu harus membuat PD-nya:
gcloud beta compute disks create --size=500GB my-data-disk
--region us-central1
--replica-zones us-central1-a,us-central1-b
Contoh spesifikasi PersistentVolume:
apiVersion: v1
kind: PersistentVolume
metadata:
name: test-volume
labels:
failure-domain.beta.kubernetes.io/zone: us-central1-a__us-central1-b
spec:
capacity:
storage: 400Gi
accessModes:
- ReadWriteOnce
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4
Migrasi CSI GCE PD
Kubernetes v1.14 [alpha]
Pada saat fitur migrasi CSI untuk GCE PD diaktifkan, fitur ini akan menterjemahkan semua operasi plugin dari plugin yang sudah ada di kode inti Kubernetes ke bentuk Driver CSI pd.csi.storage.gke.io
. Untuk menggunakan fitur ini, Driver CSI GCE PD harus dinstal di klaster dan fitur Alpha CSIMigration
serta CSIMigrationGCE
harus diaktifkan.
gitRepo (kedaluwarsa)
gitRepo
telah kedaluwarsa. Untuk membuat sebuah Container dengan sebuah git repo, tambatkan sebuah EmptyDir ke dalam sebuah InitContainer yang akan mengklon repo tersebut menggunakan git, dan kemudian tambatkan EmptyDir tersebut ke dalam Container Pod tersebut.
Sebuah Volume gitRepo
adalah sebuah percontohan yang menunjukkan apa yang dapat dilakukan dengan plugin volume. Ia menambatkan sebuah direktori kosong dan mengklon sebuah repository git ke dalamnya untuk digunakan oleh Pod kamu. Ke depannya, Volume seperti ini dapat dipindahkan ke model yang bahkan lebih terpisah, daripada melakukan ekstensi pada Kubernetes API untuk setiap kasus serupa.
Berikut sebuah contoh Volume gitRepo:
apiVersion: v1
kind: Pod
metadata:
name: server
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /mypath
name: git-volume
volumes:
- name: git-volume
gitRepo:
repository: "git@somewhere:me/my-git-repository.git"
revision: "22f1d8406d464b0c0874075539c1f2e96c253775"
glusterfs
Sebuah Volume glusterfs
memungkinkan sebuah volume Glusterfs (sebuah proyek open-source filesystem berbasis jaringan) untuk ditambatkan ke dalam Pod kamu.
Tidak seperti emptyDir
yang ikut dihapus saat Pod dihapus, isi dari sebuah glusterfs
dipertahankan dan volume-nya hanya dilepaskan tambatannya. Hal ini berarti sebuah glusterfs
dapat diisi terlebih dahulu dengan data, dan data tersebut dapat "dioper" diantara Pod-pod. GlusterFS dapat ditambatkan kepada beberapa penulis secara bersamaan.
Lihat contoh GlusterFS untuk lebih detil.
hostPath
Sebuah Volume hostPath
menambatkan sebuah berkas atau direktori dari filesystem Node di mana Pod kamu berjalan ke dalam Pod kamu.
Hal ini bukanlah sesuatu yang dibutuhkan oleh sebagian besar Pod kamu, tetapi hal ini menawarkan sebuah mekanisme pintu darurat untuk beberapa aplikasi.
Contohnya, beberapa kegunaan hostPath
adalah sebagai berikut:
- Menjalankan sebuah Container yang membutuhkan akses terhadap sistem dalaman Docker; misalnya menggunakan
hostPath
dari/var/lib/docker
- Menjalankan cAdvisor di dalam sebuah Container; menggunakan
hostPath
dari/sys
- Memungkinkan sebuah Pod untuk merinci apakah
hostPath
harus sudah ada sebelum dijalankannya Pod, apakah ia harus dibuat, dan sebagai apa ia harus dibuat.
Sebagai tambahan pada path
yang dibutuhkan, pengguna dapat secara opsional merinci type
untuk sebuah hostPath
.
Nilai yang didukung untuk kolom type
adalah:`
Nilai | Perilaku |
---|---|
String kosong (bawaan) adalah untuk kecocokan dengan versi-versi bawah, yang berarti bahwa tidak ada pemeriksaan yang dilakukan sebelum menambatkan Volume hostPath. | |
DirectoryOrCreate |
Jika tidak ada yang tersedia pada path yang dirinci, sebuah direktori kosong akan dibuat sesuai kebutuhan, dengan permission yang disetel menjadi 0755, dan mempunyai grup dan kepemilikan yang sama dengan Kubelet. |
Directory |
Sebuah direktori harus sudah tersedia pada path yang dirinci |
FileOrCreate |
Jika tidak ada yang tersedia pada path yang dirinci, maka sebuah berkas kosong akan dibuat sesuai kebutuhan dengan permission yang disetel menjadi 0644, dan mempunyai grup dan kepemilikan yang sama dengan Kubelet. |
File |
Sebuah berkas harus sudah tersedia pada path yang dirinci |
Socket |
Sebuah socket UNIX harus sudah tersedia pada path yang dirinci |
CharDevice |
Sebuah character device sudah tersedia pada path yang dirinci |
BlockDevice |
Sebuah block device harus sudah tersedia pada path yang dirinci |
Berhati-hatilah saat menggunakan tipe volume ini, karena:
- Pod-pod dengan konfigurasi identik (misalnya dibuat dari podTemplate) mungkin berperilaku berbeda pada Node-node yang berbeda oleh karena berkas-berkas yang berbeda pada Node-node tersebut.
- Saat Kubernetes menambahkan penjadwalan yang sadar terhadap sumber-daya klaster, sesuai yang telah direncanakan, ia tidak dapat melakukan perhitungan terhadap sumber daya yang digunakan oleh sebuah
hostPath
- Berkas-berkas atau direktori-direktori yang dibuat pada host-host bersangkutan hanya dapat ditulis oleh
root
. Kamu butuh antara menjalankan proses aplikasi kamu sebagairoot
pada sebuah privileged Container atau mengubah permission berkas kamu pada host tersebut agar dapat menulis pada VolumehostPath
Contoh Pod
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# Lokasi direktori pada host
path: /data
# kolom ini bersifat opsional
type: Directory
iscsi
Sebuah Volume iscsi
memungkinkan sebuah volume iSCSI (SCSI over IP) yang sudah ada untuk ditambatkan ke dalam Pod kamu.
Tidak seperti emptyDir
yang ikut dihapus saat Pod dihapus, isi dari sebuah iscsi
dipertahankan dan volume-nya hanya dilepaskan tambatannya. Hal ini berarti sebuah iscsi
dapat diisi terlebih dahulu dengan data, dan data tersebut dapat "dioper" diantara Pod-pod.
Salah satu fitur iSCSI yaitu mereka dapat ditambatkan sebagai read-only secara bersamaan oleh beberapa pengguna. Hal ini berarti kamu dapat mengisi data terlebih dahulu dan menyediakan data tersebut secara paralel untuk sebanyak apapun Pod yang kamu butuhkan. Sayangnya, iSCSI hanya dapat ditambatkan kepada satu pengguna saja pada mode read-write - yaitu, tidak boleh ada banyak penulis secara bersamaan.
Lihat contoh iSCSI untuk lebih detil.
local
Kubernetes v1.14 [stable]
Sebuah Volume local
merepresentasikan sebuah media penyimpanan lokal yang ditambatkan, seperti disk, partisi, atau direktori.
Volume local
hanya dapat digunakan sebagai PersistentVolume yang dibuat secara statis. Dynamic provisioning belum didukung untuk Volume local
.
Dibandingkan dengan Volume hostPath
, Volume local
dapat digunakan secara durable dan portabel tanpa harus menjadwalkan Pod ke Node secara manual, dikarenakan sistem mengetahui pembatasan yang berlaku terhadap Volume pada Node tersebut, dengan cara melihat node affinity
pada PersistentVolume-nya.
Tetapi, Volume local
masih bergantung pada ketersediaan Node yang bersangkutan, dan tidak semua aplikasi cocok menggunakannya. Jika sebuah Node tiba-tiba gagal, maka Volume local
pada Node tersebut menjadi tidak dapat diakses juga, dan Pod yang menggunakannya tidak dapat dijalankan. Aplikasi yang menggunakan Volumelocal
harus dapat mentoleransi hal ini dan juga potensi kehilangan data, tergantung pada karakteristik ketahanan disk yang digunakan.
Berikut sebuah contoh spesifikasi PersistentVolume menggunakan sebuah Volume local
dan nodeAffinity
:
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
# kolom volumeMode membutuhkan diaktifkannya feature gate Alpha
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node
Kolom nodeAffinity
ada PersistentVolue dibutuhkan saat menggunakan Volume local
. Ia memungkinkan Kubernetes Scheduler untuk menjadwalkan Pod-pod dengan tepat menggunakan Volume local
pada Node yang tepat.
Kolom volumeMode
pada PersistentVolume sekarang dapat disetel menjadi "Block" (menggantikan nilai bawaan "Filesystem") untuk membuka Volume local
tersebut sebagai media penyimpanan blok mentah. Hal ini membutuhkan diaktifkannya Alpha feature gate BlockVolume
.
Saat menggunakan Volume local
, disarankan untuk membuat sebuah StorageClass dengan volumeBindingMode
yang disetel menjadi WaitForFirstConsumer
. Lihatcontohnya. Menunda pengikatan Volume memastikan bahwa keputusan pengikatan PersistentVolumeClaim juga akan dievaluasi terhadap batasan-batasan Node yang berlaku pada Pod, seperti kebutuhan sumber daya Node, nodeSelector
, podAffinity
, dan podAntiAffinity
.
Sebuah penyedia statis eksternal dapat berjalan secara terpisah untuk memperbaik pengaturan siklus hidup Volume local
. Perlu dicatat bahwa penyedia ini belum mendukung dynamic provisioning. Untuk contoh bagaimana menjalankan penyedia Volume local
eksternal, lihat petunjuk penggunaannya.
lokal
tersebut.
nfs
Sebuah Volume nfs
memungkinkan sebuah NFS (Network File System) yang sudah ada untuk ditambatkan ke dalam Pod kamu.
Tidak seperti emptyDir
yang ikut dihapus saat Pod dihapus, isi dari sebuah nfs
dipertahankan dan volume-nya hanya dilepaskan tambatannya. Hal ini berarti sebuah nfs
dapat diisi terlebih dahulu dengan data, dan data tersebut dapat "dioper" diantara Pod-pod. NFS juga dapat ditambatkan oleh beberapa penulis secara sekaligus.
Lihat contoh NFS untuk lebih lanjut.
persistentVolumeClaim
Sebuah Volume persistentVolumeClaim
digunakan untuk menambatkan sebuah PersistentVolume ke dalam sebuag Pod. PersistentVolume adalah sebuah cara bagi pengguna untuk "mengklaim" penyimpanan yang durable (seperti sebuah GCE PD atau sebuah volume iSCSI) tanpa mengetahui detil lingkungan cloud yang bersangkutan.
Lihat contoh PersistentVolumes untuk lebih lanjut.
projected
Sebuah Volume projected
memetakan beberapa sumber Volume yang sudah ada ke dalam direktori yang sama.
Saat ini, tipe-tipe sumber Volume berikut dapat diproyeksikan:
secret
downwardAPI
configMap
serviceAccountToken
Semua sumber harus berada pada namespace
yang sama dengan Pod yang menggunakannya. Untuk lebih lanjut, lihat dokumen desain Volume.
Proyeksi serviceAccountToken
adalah fitur yang diperkenalkan pada Kubernetes 1.11 dan dipromosikan menjadi Beta pada 1.12.
Untuk mengaktifkan fitur inipada 1.11, kamu harus menyetel feature gate TokenRequestProjection
secara eksplisit menjadi True
.
Contoh Pod dengan sebuah Secret, Downward API, dan ConfigMap.
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "cpu_limit"
resourceFieldRef:
containerName: container-test
resource: limits.cpu
- configMap:
name: myconfigmap
items:
- key: config
path: my-group/my-config
Contoh Pod dengan banyak Secret dengan mode permission bukan bawaan
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- secret:
name: mysecret2
items:
- key: password
path: my-group/my-password
mode: 511
Setiap sumber Volume projected
terdaftar pada spesifikasi di kolom sources
. Parameter-parameter tersebut hampir sama persis dengan dua pengecualian berikut:
- Untuk Secret, kolom
secretName
telah diganti menjadiname
agar konsisten dengan penamaan ConfigMap. - Kolom
defaultMode
hanya dapat dispesifikasikan pada tingkatprojected
dan tidak untuk setiap sumber Volume. Tetapi, seperti yang ditunjukkan di atas, kamu dapat secara eksplisit menyetelmode
untuk setiap proyeksi.
Saat fitur TokenRequestProjection
diaktifkan, kamu dapat menyuntikkan token untuk ServiceAccount yang bersangkutan ke dalam Pod pada path
yang diinginkan. Berikut contohnya:
apiVersion: v1
kind: Pod
metadata:
name: sa-token-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: token-vol
mountPath: "/service-account"
readOnly: true
volumes:
- name: token-vol
projected:
sources:
- serviceAccountToken:
audience: api
expirationSeconds: 3600
path: token
Contoh Pod tersebut memiliki Volume projected
yang berisi token ServiceAccount yang disuntikkan. Token ini dapat digunakan oleh Container dalam Pod untuk mengakses Kubernetes API Server misalnya. Kolom audience
berisi audiensi token yang dituju. Sebuah penerima token tersebut harus mengidentifikasikan dirinya dengan tanda pengenal yang dispesifikasikan pada audience
token tersebut, atau jika tidak, harus menolak token tersebut. Kolom ini bersifat opsional dan secara bawaan akan berisi tanda pengenal API Server.
Kolom expirationSeconds
adalah masa berlaku yang diinginkan untuk token ServiceAccount tersebut. Secara bawaan, nilainya adalah 1 jam dan harus paling singkat bernilai 10 menit (600 detik). Seorang administrator juga dapat membatasi nilai maksimumnya dengan menyetel opsi --service-account-max-token-expiration
pada API Server. Kolom path
menunjukkan relative path untuk menambatkan Volume projected
tersebut.
projected
sebagai tambatan Volume subPath tidak akan menerima pembaruan pada sumber Volume tersebut.
portworxVolume
Sebuah portworxVolume
adalah sebuah penyimpanan blok elastis yang berjalan secara hyperconverged dengan Kubernetes. Portworx mengambil sidik jari media penyimpanan pada sebuah server, mengklasifikasikannya berdasarkan kemampuannya, dan mengagregasikan kapasitasnya di banyak server. Portworx berjalan secara in-guest pada mesin virtual atau pada Node Linux bare metal.
Sebuah portworxVolume
dapat dibuat secara dinamis melalui Kubernetes, atau ia juga dapat disediakan terlebih dahulu dan dirujuk dari dalam Pod Kubernetes. Berikut contoh sebuah Pod yang mereferensikan PortworxVolume yang telah disediakan terlebih dahulu:
apiVersion: v1
kind: Pod
metadata:
name: test-portworx-volume-pod
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /mnt
name: pxvol
volumes:
- name: pxvol
# Volume Portworx ini harus sudah tersedia.
portworxVolume:
volumeID: "pxvol"
fsType: "<fs-type>"
pxvol
sebelum dapat menggunakannya pada Pod.
Lihat di sini untuk lebih lanjut.
quobyte
Sebuah Volume quobyte
memungkinkan sebuah volume Quobyte yang sudah tersedia untuk ditambatkan ke dalam Pod kamu.
Quobyte mendukung Container Storage Interface. CSI adalah plugin yang direkomendasikan untuk menggunakan Volume Quobyte di dalam Kubernetes. Ada petunjuk dan contoh untuk menggunakan Quobyte menggunakan CSI pada proyek GitHub Quobyte.j
rbd
Sebuah Volume rbd
memungkinkan sebuah volume Rados Block Device ditambatkan ke dalam Pod kamu.
Tidak seperti emptyDir
yang ikut dihapus saat Pod dihapus, isi dari sebuah rbd
dipertahankan dan volume-nya hanya dilepaskan tambatannya. Hal ini berarti sebuah rbd
dapat diisi terlebih dahulu dengan data, dan data tersebut dapat "dioper" diantara Pod-pod.
Sebuah fitur RBD yaitu mereka dapat ditambatkan sebagai read-only secara bersamaan oleh beberapa pengguna. Hal ini berarti kamu dapat mengisi data terlebih dahulu dan menyediakan data tersebut secara paralel untuk sebanyak apapun Pod yang kamu butuhkan. Sayangnya, RBD hanya dapat ditambatkan kepada satu pengguna saja pada mode read-write - yaitu, tidak boleh ada banyak penulis secara bersamaan.
Lihat contoh RBD untuk lebih lanjut.
scaleIO
ScaleIO adalah platform penyimpanan berbasis perangkat lunak yang dapat menggunakan perangkat keras yang sudah tersedia untuk membuat klaster-klaster media penyimpanan terhubung jaringan yang scalable. Plugin Volume scaleIO
memungkinkan Pod-pod yang di-deploy untuk mengakses Volume-volume ScaleIO yang telah tersedia (atau dapat menyediakan volume-volume untuk PersistentVolumeClaim secara dinamis, lihat Persistent Volume ScaleIO).
Berikut contoh konfigurasi sebuah Pod yang menggunakan ScaleIO:
apiVersion: v1
kind: Pod
metadata:
name: pod-0
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: pod-0
volumeMounts:
- mountPath: /test-pd
name: vol-0
volumes:
- name: vol-0
scaleIO:
gateway: https://localhost:443/api
system: scaleio
protectionDomain: sd0
storagePool: sp1
volumeName: vol-0
secretRef:
name: sio-secret
fsType: xfs
Lihat contoh ScaleIO untuk lebih lanjut.
secret
Sebuah Volume secret
digunakan untuk memberikan informasi yang bersifat sensitif, seperti kata sandi, kepada Pod-pod. Kamu dapat menaruh secret
dalam Kubernetes API dan menambatkan mereka sebagai berkas-berkas untuk digunakan oleh Pod-pod tanpa harus terikat pada Kubernetes secara langsung. Volume secret
didukung oleh tmpfs (filesystem yang didukung oleh RAM) sehingga mereka tidak pernah ditulis pada media penyimpanan yang non-volatile.
secret
di dalam Kubernetes API sebelum kamu dapat menggunakannya.
Secret dijelaskan lebih lanjut di sini.
storageOS
Sebuah Volume storageos
memungkinkan volume StorageOS yang sudah tersedia untuk ditambatkan ke dalam Pod kamu.
StorageOS berjalan sebagai sebuah COntainer di dalam lingkungan Kubernetes kamu, membuat penyimpanan yang lokal atau penyimpanan yang sedang dipasang untuk diakses dari Node manapun di dalam klaster Kubernetes. Data dapat direplikasikan untuk melindungi dari kegagalan Node. Thin provisioning dan kompresi dapat meningkatkan utilisasi dan mengurangi biaya.
Di dalam intinya, StorageOS menyediakan penyimpanan blok kepada Container-container, yang dapat diakses melalui sebuah filesystem.
Container StorageOS membutuhkan Linux 64-bit dan tidak memiliki ketergantungan tambahan apapun. Tersedia pula sebuah lisensi gratis untuk developer.
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis
role: master
name: test-storageos-redis
spec:
containers:
- name: master
image: kubernetes/redis:v1
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /redis-master-data
name: redis-data
volumes:
- name: redis-data
storageos:
# Volume `redis-vol01` harus sudah tersedia di dalam StorageOS pada Namespace `default`
volumeName: redis-vol01
fsType: ext4
Untuk lebih lanjut, termasuk Dynamic Provisioning dan Persistent Volume Claim, lihat contoh-contoh StorageOS.
vsphereVolume
Sebuah vsphereVolume
digunakan untuk menambatkan sebuah Volume VMDK vSphere ke dalam Pod kamu. Isi dari sebuah volume dipertahankan pada saat tambatannya dilepas. Ia mendukung penyimpanan data VMFS dan VSAN.
Membuat sebuah Volume VMDK
Pilih satu dari beberapa cara berikut untuk membuat sebuah VMDK.
Pertama-tama, ssh ke dalam ESX, kemudian gunakan perintah berikut untuk membuat sebuah VMDK:
vmkfstools -c 2G /vmfs/volumes/DatastoreName/volumes/myDisk.vmdk
Gunakan perintah berikut untuk membuat sebuah VMDK:
vmware-vdiskmanager -c -t 0 -s 40GB -a lsilogic myDisk.vmdk
Contoh Konfigurasi vSphere VMDK
apiVersion: v1
kind: Pod
metadata:
name: test-vmdk
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-vmdk
name: test-volume
volumes:
- name: test-volume
# Volume VMDK ini harus sudah tersedia.
vsphereVolume:
volumePath: "[DatastoreName] volumes/myDisk"
fsType: ext4
Lebih banyak contoh dapat ditemukan di sini.
Menggunakan subPath
Terkadang, diperlukan untuk membagi sebuah Volume untuk banyak kegunaan berbeda pada sebuah Pod. Kolom volumeMounts.subPath
dapat digunakan untuk merinci sebuah sub-path di dalam Volume yang dimaksud, menggantikan root path-nya.
Berikut contoh sebuah Pod dengan stack LAMP (Linux Apache Mysql PHP) menggunakan sebuah Volume yang dibagi-bagi.
Isi HTML-nya dipetakan ke dalam direktori html
-nya, dan database-nya akan disimpan di dalam direktori mysql
-nya.
apiVersion: v1
kind: Pod
metadata:
name: my-lamp-site
spec:
containers:
- name: mysql
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "rootpasswd"
volumeMounts:
- mountPath: /var/lib/mysql
name: site-data
subPath: mysql
- name: php
image: php:7.0-apache
volumeMounts:
- mountPath: /var/www/html
name: site-data
subPath: html
volumes:
- name: site-data
persistentVolumeClaim:
claimName: my-lamp-site-data
Menggunakan subPath dengan environment variable yang diekspansi
Kubernetes v1.15 [beta]
Gunakan kolom subPathExpr
untuk membuat nama-nama direktori subPath
dari environment variable Downward API.
Sebelum kamu menggunakan fitur ini, kamu harus mengaktifkan feature gate VolumeSubpathEnvExpansion
. Kolom subPath
dan subPathExpr
bersifat mutually exclusive.
Pada contoh ini, sebuah Pod menggunakan subPathExpr
untuk membuat sebuah direktori pod1
di dalam Volume hostPath /var/log/pods
, menggunakan nama Pod dari Downward API. Direktori host /var/log/pods/pod1
ditambatkan pada /logs
di dalam Container-nya.
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: container1
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
image: busybox
command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
volumeMounts:
- name: workdir1
mountPath: /logs
subPathExpr: $(POD_NAME)
restartPolicy: Never
volumes:
- name: workdir1
hostPath:
path: /var/log/pods
Sumber-sumber
Media penyimpanan (Disk, SSD, dll.) dari sebuah Volume emptyDir
ditentukan oleh medium dari filesystem yang menyimpan direktori root dari Kubelet (biasanya /var/lib/kubelet
). Tidak ada batasan berapa banyak ruang yang dapat digunakan oleh Volume emptyDir
dan hostPath
, dan tidak ada isolasi antara Container-container atau antara Pod-pod.
Ke depannya, kita mengharapkan Volume emptyDir
dan hostPath
akan dapat meminta jumlah ruangan penyimpanan tertentu dengan mengunakan spesifikasi [resource]resource, dan memilih tipe media penyimpanan yang akan digunakan, untuk klaster yang memiliki beberapa jenis media penyimpanan.
Plugin Volume yang Out-of-Tree
Plugin Volume yang Out-of-tree termasuk Container Storage Interface (CSI) dan Flexvolume. Mereka memungkinkan vendor penyimpanan untuk membuat plugin penyimpanan buatan tanpa perlu menambahkannya pada repository Kubernetes.
Sebelum dikenalkannya CSI dan Flexvolume, semua plugin volume (seperti jenis-jenis volume yang terdaftar di atas) berada pada "in-tree", yang berarti bahwa mereka dibangun, di-link, di-compile, dan didistribusikan bersama-sama dengan kode inti Kubernetes dan mengekstensi inti dari Kubernetes API. Hal ini berarti menambah sistem penyimpanan baru ke dalam Kubernetes (sebuah plugin volume) membutukan penambahan kode tersebut ke dalam repository kode inti Kubernetes.
CSI dan Flexvolume memungkinkan plugin volume untuk dikembangkan secara terpisah dari kode inti Kubernetes, dan diinstal pada klaster Kubernetes sebagai ekstensi.
Bagi vendor-vendor penyimpanan yang ingin membuat sebuah plugin volume yang out-of-tree, lihat FAQ ini.
CSI
Container Storage Interface (CSI) mendefinisikan standar antarmuka untuk sistem orkestrasi (seperti Kubernetes) untuk mengekspos sistem penyimpanan apapun ke dalam beban kerja Container mereka.
Silahkan lihat proposal desain CSI untuk lebih lanjut.
Dukungan untuk CSI dikenalkan sebagai Alpha pada Kubernetes v1.9, dan menjadi Beta pada Kubernetes v1.10, dan menjadi GA pada Kubernetes v1.13.
Saat sebuah driver volume CSI dipasang pada klaster Kubernetes, pengguna dapat menggunakan tipe Volume csi
untuk menambatkan volume-volume yang diekspos oleh driver CSI tersebut.
Tipe Volume csi
tidak mendukung referensi secara langsung dari Pod dan hanya dapat dirujuk di dalam sebuah Pod melalui sebuah objek PersistentVolumeClaim
.
Kolom-kolom berikut tersedia untuk administrator-administrator penyimpanan untuk mengkonfigurasi sebuah Persistent Volume CSI.
driver
: Sebuah nilai string yang merinci nama dari driver volume yang akan digunakan. Nilai ini harus sesuai dengan nilai yang dikembalikan olehGetPluginInfoResponse
dari _driver_CSI seperti yang didefinisikan pada spesifikasi CSI. Ia digunakan oleh Kubernetes untuk mengidentifikasikan driver CSI mana yang akan dipanggil, dan oleh komponen driver CSI untuk mengidentifikasikan objek PersistentVolume mana yang dimiliki oleh driver CSI tersebut.volumeHandle
: Sebuah nilai string yang secara unik mengidentifikasikan volume tersebut. Nilai ini harus sesuai dengan nilai yang dikembalikan oleh kolomvolume.id
dariCreateVolumeResponse
dari driver CSI seperti yang didefinisikan pada spesifikasi CSI. Nilai tersebut dioper sebagaivolume_id
pada semua panggilan terhadap driver volume CSI saat mereferensikan volume yang bersangkutan.readOnly
: Sebuah nilai boolean bersifat opsional yang mengindikasikan jika sebuah volume akan dijadikan sebagai "ControllerPublished" (ditambatkan) sebagai read-only. Nilai bawaannya adalahfalse
. Nilai ini dioper ke driver CSI melalui kolomreadonly
padaControllerPublishVolumeRequest
.fsType
: Jika nilaiVolumeMode
milik PV adalahFileSystem
, maka kolom ini dapat digunakan untuk menunjukkan filesystem yang akan digunakan untu menambatkan volume tersebut. Jika volume tersebut belum diformat dan memformat tidak didukung, maka nilai ini akan digunakan untuk memformat volume tersebut. Nilai ini dioper kepada driver CSI melalui kolomVolumeCapability
dariControllerPublishVolumeRequest
,NodeStageVolumeRequest
, danNodePublishVolumeRequest
.volumeAttributes
: Sebuah map dari string kepada string yang merinci properti statis dari sebuah volume. Nilai map ini harus sesuai dengan map yang dikembalikan di dalam kolomvolume.attributes
padaCreateVolumeResponse
dari driver CSI seperti yang didefinisikan pada spesifikasi CSI. Map tersebut dioper kepada driver CSI melalui kolomvolume_attributes
padaControllerPublishVolumeRequest
,NodeStageVolumeRequests
, danNodePublishVolumeRequest
.controllerPublishSecretRef
: Sebuah referensi ke objek Secret yang berisi informasi sensitif untuk diberikan pada driver CSI untuk menyelesaikan panggilanControllerPublishVolume
danControllerUnpublishVolume
. Kolom ini bersifat opsional, dan dapat bernilai kosong jika tidak ada Secret yang dibutuhkan. Jika objek Secret berisi lebih dari satu secret, maka semua secret tersebut akan diberikan.nodeStageSecretRef
: Sebuah referensi ke objek Secret yang berisi informasi sensitif untuk diberikan pada driver CSI untuk menyelesaikan panggilanNodeStageVolume
. Kolom ini bersifat opsional, dan dapat bernilai kosong jika tidak ada Secret yang dibutuhkan. Jika objek Secret berisi lebih dari satu secret, maka semua secret tersebut akan diberikan.nodePublishSecretRef
: Sebuah referensi ke objek Secret yang berisi informasi sensitif untuk diberikan pada driver CSI untuk menyelesaikan panggilanNodePublishVolume
. Kolom ini bersifat opsional, dan dapat bernilai kosong jika tidak ada Secret yang dibutuhkan. Jika objek Secret berisi lebih dari satu secret, maka semua secret tersebut akan diberikan.
Dukungan CSI untuk volume blok raw
Kubernetes v1.14 [beta]
Dimulai pada versi 1.11, CSI memperkenalkan dukungak untuk volume blok raw, yang bergantung pada fitur volume blok raw yang dikenalkan pada versi Kubernetes sebelumnya. Fitur ini akan memungkinkan vendor-vendor dengan driver CSI eksternal untuk mengimplementasi dukungan volume blok raw pada beban kerja Kubernetes.
Dukungan untuk volume blok CSI bersifat feature-gate, tapi secara bawaan diaktifkan. Kedua feature-gate yang harus diaktifkan adalah BlockVolume
dan CSIBlockVolume
.
Pelajari cara menyiapkan PV/PVC dengan dukungan volume blok raw.
Volume CSI Sementara
Kubernetes v1.15 [alpha]
FItur ini memungkinkan volume CSI untuk dipasang secara langsung pada spesifikasi Pod, menggantikan spesifikasi pada PersistentVolume. Volume yang dirinci melalui cara ini bersifat sementara tidak akan dipertahankan saat Pod diulang kembali.
Contoh:
kind: Pod
apiVersion: v1
metadata:
name: my-csi-app
spec:
containers:
- name: my-frontend
image: busybox
volumeMounts:
- mountPath: "/data"
name: my-csi-inline-vol
command: [ "sleep", "1000000" ]
volumes:
- name: my-csi-inline-vol
csi:
driver: inline.storage.kubernetes.io
volumeAttributes:
foo: bar
Fitur ini memerlukan diaktifkannya feature-gate CSIInlineVolume:
--feature-gates=CSIInlineVolume=true
Volume CSI sementara hanya didukung oleh sebagian dari driver-driver CSI. Silahkan lihat daftar driver CSI di sini.
Sumber-sumber untuk developer
Untuk informasi bagaimana mengembangkan sebuah driver CSI, lihat dokumentasi kubernetes-csi.
Migrasi ke driver-driver CSI dari plugin in-tree
Migrating to CSI drivers from in-tree plugins
Kubernetes v1.14 [alpha]
Fitur CSI Migration, saat diaktifkan, akan mengarahkan operasi-operasi terhadap plugin-plugin in-tree yang sudah ada ke plugin-plugin CSI yang sesuai (yang diharap sudah dipasang dan dikonfigurasi). Fitur ini mengimplementasi logika translasi dan terjemahan yang dibutuhkan untuk mengarahkan ulang operasi-operasi bersangkutan dengan mulus. Hasilnya, operator-operator tidak perlu membuat perubahan konfigurasi apapun pada StorageClass, PV, atau PVC yang sudah ada (mengacu pada plugin in-tree) saat melakukan transisi pada driver CSI yang menggantikan plugin in-tree yang bersangkutan.
Pada keadaan Alpha, operasi-operasi dan fitur-fitur yang didukung termasuk provisioning/delete, attach/detach, mount/unmount, dan mengubah ukuran volume-volume.
Plugin-plugin in-tree yang mendukung CSI Migration dan mempunyai driver CSI yang sesuai yang telah diimplementasikan terdaftar pada bagian "Jenis-jenis Volume" di atas.
Flexvolume
Flexvolume adalah antarmuka plugin out-of-tree yang telah ada sejak Kubernetes versi 1.2 (sebelum CSI). Ia menggunakan model berbasis exec untuk berhubungan dengan driver-driver. Program driver Flexvolume harus dipasan pada volume plugin path yang telah didefinisikan sebelumnya pada setiap Node (dan pada beberapa kasus, di Master).
Pod-pod berinteraksi dengan driver-driver Flexvolume melalui plugin in-tree flexvolume
.
Untuk lebih lanjut, dapat ditemukan di sini.
Mount Propagation
Mount propagation memungkinkan berbagi volume-volume yang ditambatkan oleh sebuah Container kepada Container-container lain di dalam Pod yang sama, atau bahkan pada Pod lainnya di dalam Node yang sama.
Mount propagation dari sebuah volume diatur oleh kolom mountPropagation
di dalam Container.volumeMounts
.
Nilai-nilainya adalah sebagai berikut:
-
None
- Tambatan volume ini tidak akan menerima apapun tambatan selanjutnya yang ditambatkan pada volume ini atau apapun sub-direktori yang dimilikinya oleh host. Dengan cara yang sama, tidak ada tambatan yang dibuat oleh Container yang dapat terlihat pada host. Ini adalah mode bawaan.Mode ini setara dengan mount propagation
private
, seperti yang dideskripsikan pada dokumentasi kernel Linux -
HostToContainer
- Tambatan volume ini akan menerima semua tambatan selanjutnya yang ditambatkan pada volume ini atau pada apapun sub-direktori yang dimilikinya.Dalam kata lain, jika host yang bersangkutan menambatkan apapun di dalam tambatan volume, Container akan melihatnya ditambatkan di sana.
Secara serupa, jika ada Pod dengan mount propagation
Bidirectional
terhadap volume yang sama menambatkan apapun ke situ, maka Container dengan mount propagationHostToContainer
akan melihatnya.Mode ini setara dengan mount propagation
rslave
, seperti yang dideskripsikan pada dokumentasi kernel Linux -
Bidirectional
- Tambatan volume ini memiliki perilaku yang sama dengan tambatanHostToContainer
. Sebagai tambahannya, semua tambatan volume yang dibuat oleh Container akan dipropagasi kembali kepada host yang bersangkutan dan ke semua Container dari semua Pod yang menggunakan volume yang sama.Contoh kasus umum untuk mode ini adalah Pod dengan sebuah Flexvolume atau driver CSI atau sebuah Pod yang perlu menambatkan sesuatu pada host-nya dengan menggunakan Volume
hostPath
.Mode ini setara dengan mount propagation
rshared
, seperti yang dideskripsikan pada dokumentasi kernel Linux
Bidirectional
bisa jadi berbahaya. Ia dapat merusak sistem operasi host-nya, sehingga hanya diizinkan pada Container yang privileged. Keterbiasaan dengan perilaku kernel Linux sangat dianjurkan.
Sebagai tambahan, tambatan volume apapun yang dibuat oleh Container-container di dalam Pod-pod harus dihancurkan (dilepaskan tambatannya) oleh Container-container pada saat terminasi.
Konfigurasi
Sebelum mount propagation dapat bekerja dengan baik pada beberapa instalasi (CoreOS, RedHat/Centos, Ubuntu), mount share harus dikonfigurasi dengan benar pada Docker, seperti yang ditunjukkan di bawah.
Sunting berkas servis systemd
Docker kamu. Setel MountFlags
sebagai berikut:
MountFlags=shared
Atau, hapus MountFlags=slave
jika ada. Kemudian, ulang kembali daemon Docker-nya:
sudo systemctl daemon-reload
sudo systemctl restart docker
Selanjutnya
- Ikuti contoh memasang WordPress dan MySQL dengan Persistent Volume.
3.6.2 - Persistent Volume
Dokumen ini menjelaskan kondisi terkini dari PersistentVolumes
pada Kubernetes. Disarankan telah memiliki familiaritas dengan volume.
Pengenalan
Mengelola penyimpanan adalah hal yang berbeda dengan mengelola komputasi. Sub-sistem PersistentVolume
(PV) menyediakan API untuk para pengguna dan administrator yang mengabstraksi detail-detail tentang bagaimana penyimpanan disediakan dari bagaimana penyimpanan dikonsumsi. Untuk melakukan ini, kami mengenalkan dua sumber daya API baru: PersistentVolume
(PV) dan PersistentVolumeClaim
(PVC).
Sebuah PersistentVolume
(PV) adalah suatu bagian dari penyimpanan pada klaster yang telah disediakan oleh seorang administrator. PV merupakan sebuah sumber daya pada klaster sama halnya dengan node yang juga merupakan sumber daya klaster. PV adalah volume plugin seperti Volumes, tetapi memiliki siklus hidup yang independen dari pod individual yang menggunakan PV tersebut. Objek API ini menangkap detail-detail implementasi dari penyimpanan, seperti NFS, iSCSI, atau sistem penyimpanan yang spesifik pada penyedia layanan cloud.
Sebuah PersistentVolumeClaim
(PVC) merupakan permintaan penyimpanan oleh pengguna. PVC mirip dengan sebuah pod. Pod mengonsumsi sumber daya node dan PVC mengonsumsi sumber daya PV. Pods dapat meminta taraf-taraf spesifik dari sumber daya (CPU dan Memory). Klaim dapat meminta ukuran dan mode akses yang spesifik (seperti, dapat dipasang sekali sebagai read/write atau lain kali sebagai read-only).
Meskipun PersistentVolumeClaims
mengizinkan pengguna untuk mengkonsumsi sumber daya penyimpanan
abstrak, pada umumnya para pengguna membutuhkan PersistentVolumes
dengan properti yang
bermacam-macam, seperti performa, untuk mengatasi masalah yang berbeda. Para administrator klaster
harus dapat menawarkan berbagai macam PersistentVolumes
yang berbeda tidak hanya pada ukuran dan
mode akses, tanpa memaparkan detail-detail bagaimana cara volume tersebut diimplementasikan
kepada para pengguna. Untuk mengatasi hal ini maka dibutuhkan sumber daya
StorageClass
.
Silakan lihat panduan mendetail dengan contoh-contoh yang sudah berjalan.
Siklus hidup dari sebuah volume dan klaim
PV adalah sumber daya dalam sebuah klaster. PVC adalah permintaan terhadap sumber daya tersebut dan juga berperan sebagai pemeriksaan klaim dari sumber daya yang diminta. Interaksi antara PV dan PVC mengikuti siklus hidup berikut ini:
Penyediaan
Ada dua cara untuk menyediakan PV: secara statis atau dinamis.
Statis
Seorang administrator klaster membuat beberapa PV. PV yang telah dibuat membawa detail-detail dari penyimpanan yang sesungguhnya tersedia untuk digunakan oleh pengguna klaster. PV tersebut ada pada Kubernetes API dan siap untuk digunakan.
Dinamis
Ketika tidak ada PV statis yang dibuat oleh administrator yang sesuai dengan PersistentVolumeClaim
(PVC) yang dibuat oleh pengguna, klaster akan mencoba untuk menyediakan volume khusus sesuai permintaan PVC.
Penyediaan dinamis ini berbasis StorageClass
: artinya PVC harus meminta sebuah storage class dan storage class tersebut harus sudah dibuat dan dikonfigurasi oleh administrator agar penyediaan dinamis bisa terjadi. Klaim yang meminta PV dengan storage class ""
secara efektif telah menonaktifkan penyediaan dinamis.
Untuk mengaktifkan penyediaan storage dinamis berdasarkan storage class, administrator klaster harus mengaktifkan admission controller
DefaultStorageClass
pada API server. Hal ini dapat dilakukan, dengan cara memastikan DefaultStorageClass
ada di antara urutan daftar value yang dibatasi koma untuk flag --enable-admission-plugins
pada komponen API server. Untuk informasi lebih lanjut mengenai flag perintah pada API server, silakan cek dokumentasi,
kube-apiserver.
Pengikatan
Seorang pengguna membuat, atau telah membuat (dalam kasus penyediaan dinamis), sebuah PersistentVolumeClaim
(PVC) dengan jumlah penyimpanan spesifik yang diminta dan dengan mode akses tertentu. Sebuah control loop pada master akan melihat adanya PVC baru, mencari PV yang cocok (jika memungkinkan), dan mengikat PVC dengan PV tersebut. Jika sebuah PV disediakan secara dinamis untuk sebuah PVC baru, loop tersebut akan selalu mengikat PV tersebut pada PVC yang baru dibuat itu. Jika tidak, pengguna akan selalu mendapatkan setidaknya apa yang dimintanya, tetapi volume tersebut mungkin lebih dari apa yang diminta sebelumnya. Setelah terikat, ikatan PersistentVolumeClaim
(PVC) bersifat eksklusif, terlepas dari bagaimana caranya mereka bisa terikat. Sebuah ikatan PVC ke PV merupakan pemetaan satu ke satu.
Klaim akan berada dalam kondisi tidak terikat tanpa kepastian jika tidak ada volume yang cocok. Klaim akan terikat dengan volume yang cocok ketika ada volume yang cocok. Sebagai contoh, sebuah klaster yang sudah menyediakan banyak PV berukuran 50Gi tidak akan cocok dengan PVC yang meminta 100Gi. PVC hanya akan terikat ketika ada PV 100Gi yang ditambahkan ke klaster.
Penggunaan
Pod menggunakan klaim sebagai volume. Klaster menginspeksi klaim untuk menemukan volume yang terikat dengan klaim tersebut dan memasangkan volume tersebut ke pada pod. Untuk volume yang mendukung banyak mode akses, pengguna yang menentukan mode yang diinginkan ketika menggunakan klaim sebagai volume dalam sebuah pod.
Ketika pengguna memiliki klaim dan klaim tersebut telah terikat, PV yang terikat menjadi hak penggunanya selama yang dibutuhkan. Pengguna menjadwalkan pod dan mengakses PV yang sudah diklaim dengan menambahkan persistentVolumeClaim
pada blok volume pada Pod miliknya. Lihat pranala di bawah untuk detail-detail mengenai sintaks.
Object Penyimpanan dalam Perlindungan Penggunaan
Tujuan dari Objek Penyimpanan dalam Perlindungan Penggunan adalah untuk memastikan Persistent Volume Claim (PVC) yang sedang aktif digunakan oleh sebuah pod dan Persistent Volume (PV) yang terikat pada PVC tersebut tidak dihapus dari sistem karena hal ini dapat menyebabkan kehilangan data.
Jika seorang pengguna menghapus PVC yang sedang aktif digunakan oleh sebuah pod, PVC tersebut tidak akan langsung dihapus. Penghapusan PVC akan ditunda sampai PVC tidak lagi aktif digunakan oleh pod manapun, dan juga ketika admin menghapus sebuah PV yang terikat dengan sebuah PVC, PV tersebut tidak akan langsung dihapus. Penghapusan PV akan ditunda sampai PV tidak lagi terikat dengan sebuah PVC.
Kamu dapat melihat PVC yang dilindungi ketika status PVC berisi Terminating
dan daftar Finalizers
meliputi kubernetes.io/pvc-protection
:
kubectl describe pvc hostpath
Name: hostpath
Namespace: default
StorageClass: example-hostpath
Status: Terminating
Volume:
Labels: <none>
Annotations: volume.beta.kubernetes.io/storage-class=example-hostpath
volume.beta.kubernetes.io/storage-provisioner=example.com/hostpath
Finalizers: [kubernetes.io/pvc-protection]
...
Kamu dapat melihat sebuah PV dilindungi ketika status PV berisi Terminating
dan daftar Finalizers
juga meliputi kubernetes.io/pv-protection
:
kubectl describe pv task-pv-volume
Name: task-pv-volume
Labels: type=local
Annotations: <none>
Finalizers: [kubernetes.io/pv-protection]
StorageClass: standard
Status: Available
Claim:
Reclaim Policy: Delete
Access Modes: RWO
Capacity: 1Gi
Message:
Source:
Type: HostPath (bare host directory volume)
Path: /tmp/data
HostPathType:
Events: <none>
Melakukan Reklaim
Ketika seorang pengguna telah selesai dengan volumenya, ia dapat menghapus objek PVC dari API yang memungkinkan untuk reklamasi dari sumber daya tersebut. Kebijakan reklaim dari sebuah PersistentVolume
(PV) menyatakan apa yang dilakukan klaster setelah volume dilepaskan dari klaimnya. Saat ini, volume dapat dipertahankan (Retained), didaur ulang (Recycled), atau dihapus (Deleted).
Retain
Retain
merupakan kebijakan reklaim yang mengizinkan reklamasi manual dari sebuah sumber daya. Ketika PersistentVolumeClaim
(PVC) dihapus, PersistentVolume
(PV) masih akan tetap ada dan volume tersebut dianggap "terlepas" . Tetapi PV tersebut belum tersedia untuk klaim lainnya karena data milik pengklaim sebelumnya masih terdapat pada volume. Seorang administrator dapat mereklaim volume secara manual melalui beberapa langkah.
- Menghapus
PersistentVolume
(PV). Aset storage yang terasosiasi dengan infrastruktur eksternal (seperti AWS EBS, GCE PD, Azure Disk, atau Cinder Volume) akan tetap ada setelah PV dihapus. - Secara manual membersihkan data pada aset storage terkait.
- Secara manual menghapus aset storage, atau jika kamu ingin menggunakan aset storage yang sama, buatlah sebuah
PersistentVolume
baru dengan definisi aset storage tersebut.
Delete
Untuk volume plugin yang mendukung kebijakan reklaim Delete
, penghapusan akan menghilangkan kedua objek dari Kubernetes, PersistentVolume
(PV) dan juga aset storage yang terasosiasi pada infrastruktur eksternal seperti, AWS EBS, GCE PD, Azure Disk, atau Cinder Volume. Volume yang disediakan secara dinamis mewarisi kebijakan reklaim dari StorageClass
miliknya, yang secara bawaan adalah Delete
. Administrator harus mengkonfigurasi StorageClass
sesuai ekspektasi pengguna, jika tidak maka PV tersebut harus diubah atau ditambal setelah dibuat nanti. Lihat Mengganti Kebijakan Reklaim pada PersistentVolume.
Recycle
Recycle
sudah ditinggalkan. Sebagai gantinya, pendekatan yang direkomendasikan adalah menggunakan penyediaan dinamis.
Jika didukung oleh plugin volume yang berada di baliknya, kebijakan reklaim Recycle
melakukan penghapusan dasar (rm -rf /thevolume/*
) pada volume dan membuatnya kembali tersedia untuk klaim baru.
Namun, seorang administrator dapat mengkonfigurasi templat recycler pod kustom menggunakan argumen baris perintah controller manager Kubernetes sebagaimana dijelaskan di sini. Templat reycler pod kustom harus memiliki spesifikasi volumes
, seperti yang ditunjukkan pada contoh di bawah:
apiVersion: v1
kind: Pod
metadata:
name: pv-recycler
namespace: default
spec:
restartPolicy: Never
volumes:
- name: vol
hostPath:
path: /any/path/it/will/be/replaced
containers:
- name: pv-recycler
image: "k8s.gcr.io/busybox"
command: ["/bin/sh", "-c", "test -e /scrub && rm -rf /scrub/..?* /scrub/.[!.]* /scrub/* && test -z \"$(ls -A /scrub)\" || exit 1"]
volumeMounts:
- name: vol
mountPath: /scrub
Namun, alamat yang dispesifikasikan pada templat recycler pod kustom pada bagian volumes
diganti dengan alamat pada volume yang akan didaur ulang.
Memperluas Persistent Volumes Claim
Kubernetes v1.11 [beta]
Dukungan untuk memperluas PersistentVolumeClaim (PVC) sekarang sudah diaktifkan sejak awal. Kamu dapat memperluas tipe-tipe volume berikut:
- gcePersistentDisk
- awsElasticBlockStore
- Cinder
- glusterfs
- rbd
- Azure File
- Azure Disk
- Portworx
- FlexVolumes
- CSI
Kamu hanya dapat memperluas sebuah PVC jika kolom allowVolumeExpansion
dipasang sebagai benar pada storage class miliknya.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gluster-vol-default
provisioner: kubernetes.io/glusterfs
parameters:
resturl: "http://192.168.10.100:8080"
restuser: ""
secretNamespace: ""
secretName: ""
allowVolumeExpansion: true
Untuk meminta volume yang lebih besar pada sebuah PVC, ubah objek PVC dan spesifikasikan ukuran yang lebih
besar. Hal ini akan memicu perluasan dari volume yang berada di balik PersistentVolume
(PV). Sebuah
PersistentVolume
(PV) baru tidak akan dibuat untuk memenuhi klaim tersebut. Sebaliknya, volume yang sudah ada akan diatur ulang ukurannya.
Perluasan Volume CSI
Kubernetes v1.14 [alpha]
Perluasan volume CSI mengharuskan kamu untuk mengaktifkan gerbang fitur ExpandCSIVolumes
dan juga membutuhkan driver CSI yang spesifik untuk mendukung perluasan volume. Silakan merujuk pada dokumentasi driver spesifik CSI untuk informasi lebih lanjut.
Mengubah ukuran sebuah volume yang memiliki file system
Kamu hanya dapat mengubah ukuran volume yang memiliki file system jika file system tersebut adalah XFS, Ext3, atau Ext4.
Ketika sebuah volume memiliki file system, file system tersebut hanya akan diubah ukurannya ketika sebuah pod baru dinyalakan menggunakan
PersistentVolumeClaim
(PVC) dalam mode ReadWrite. Maka dari itu, jika sebuah pod atau deployment menggunakan sebuah volume dan
kamu ingin memperluasnya, kamu harus menghapus atau membuat ulang pod tersebut setelah volume selesai diperluas oleh penyedia cloud dalam controller-manager. Kamu dapat melihat status dari operasi pengubahan ukuran dengan menjalankan perintah kubectl describe pvc
:
kubectl describe pvc <pvc_name>
Jika PersistentVolumeClaim
(PVC) memiliki status FileSystemResizePending
, maka berarti aman untuk membuat ulang pod menggunakan PersistentVolumeClaim (PVC) tersebut.
FlexVolumes mengizinkan pengubahan ukuran jika driver diatur dengan kapabilitas RequiresFSResize
menjadi "true".
FlexVolume dapat diubah ukurannya pada saat pod mengalami restart.
Kubernetes v1.11 [alpha]
Mengubah ukuran PersistentVolumeClaim (PVC) yang sedang digunakan
Memperluas PVC yang sedang digunakan merupakan fitur alfa. Untuk menggunakannya, aktifkan gerbang fitur ExpandInUsePersistentVolumes
.
Pada kasus ini, kamu tidak perlu menghapus dan membuat ulang sebuah Pod atau deployment yang menggunakan PVC yang telah ada.
PVC manapun yang sedang digunakan secara otomatis menjadi tersedia untuk pod yang menggunakannya segera setelah file system miliknya diperluas.
Fitur ini tidak memiliki efek pada PVC yang tidak sedang digunakan oleh Pod atau deployment. Kamu harus membuat sebuah Pod yang
menggunakan PVC sebelum perluasan dapat selesai dilakukan.
Memperluas PVC yang sedang digunakan sudah ditambahkan pada rilis 1.13. Untuk mengaktifkan fitur ini gunakan ExpandInUsePersistentVolumes
dan gerbang fitur ExpandPersistentVolumes
. Gerbang fitur ExpandPersistentVolumes
sudah diaktifkan sejak awal. Jika ExpandInUsePersistentVolumes
sudah terpasang, FlexVolume dapat diubah ukurannya secara langsung tanpa perlu melakukan restart pada pod.
Tipe-tipe Persistent Volume
Tipe-tipe PersistentVolume
(PV) diimplementasikan sebagai plugin. Kubernetes saat ini mendukung plugin berikut:
- GCEPersistentDisk
- AWSElasticBlockStore
- AzureFile
- AzureDisk
- FC (Fibre Channel)
- FlexVolume
- Flocker
- NFS
- iSCSI
- RBD (Ceph Block Device)
- CephFS
- Cinder (OpenStack block storage)
- Glusterfs
- VsphereVolume
- Quobyte Volumes
- HostPath (Hanya untuk pengujian single node -- penyimpanan lokal tidak didukung dan TIDAK AKAN BEKERJA pada klaster multi-node)
- Portworx Volumes
- ScaleIO Volumes
- StorageOS
Persistent Volume
Setiap PV memiliki sebuah spec dan status, yang merupakan spesifikasi dan status dari volume tersebut.
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.17.0.2
Kapasitas
Secara umum, sebuah PV akan memiliki kapasitas storage tertentu. Hal ini ditentukan menggunakan atribut capacity
pada PV. Lihat Model Sumber Daya Kubernetes untuk memahami satuan yang diharapkan pada atribut capacity
.
Saat ini, ukuran storage merupakan satu-satunya sumber daya yang dapat ditentukan atau diminta. Atribut-atribut lainnya di masa depan dapat mencakup IOPS, throughput, dsb.
Mode Volume
Kubernetes v1.13 [beta]
Sebelum Kubernetes 1.9, semua volume plugin akan membuat sebuah filesystem pada PersistentVolume (PV).
Sekarang, kamu dapat menentukan nilai dari volumeMode
menjadi block
untuk menggunakan perangkat raw block, atau filesystem
untuk menggunakan sebuah filesystem. filesystem
menjadi standar yang digunakan jika nilainya dihilangkan. Hal ini merupakan parameter API
opsional.
Mode Akses
Sebuah PersistentVolume
(PV) dapat dipasangkan pada sebuah host dengan cara apapun yang didukung oleh penyedia sumber daya. Seperti ditunjukkan pada tabel di bawah, para penyedia akan memiliki kapabilitas yang berbeda-beda dan setiap mode akses PV akan ditentukan menjadi mode-mode spesifik yang didukung oleh tiap volume tersebut. Sebagai contoh, NFS dapat mendukung banyak klien read/write, tetapi sebuah NFS PV tertentu mungkin diekspor pada server sebagai read-only. Setiap PV memilik seperangkat mode aksesnya sendiri yang menjelaskan kapabilitas dari PV tersebut.
Beberapa mode akses tersebut antara lain:
- ReadWriteOnce -- volume dapat dipasang sebagai read-write oleh satu node
- ReadOnlyMany -- volume dapat dipasang sebagai read-only oleh banyak node
- ReadWriteMany -- volume dapat dipasang sebagai read-write oleh banyak node
Pada CLI, mode-mode akses tersebut disingkat menjadi:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
Penting! Sebuah volume hanya dapat dipasang menggunakan satu mode akses dalam satu waktu, meskipun volume tersebut mendukung banyak mode. Sebagai contoh, sebuah GCEPersistentDisk dapat dipasangkan sebagai ReadWriteOnce oleh satu node atau ReadOnlyMany oleh banyak node, tetapi tidak dalam waktu yang bersamaan.
Volume Plugin | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
---|---|---|---|
AWSElasticBlockStore | ✓ | - | - |
AzureFile | ✓ | ✓ | ✓ |
AzureDisk | ✓ | - | - |
CephFS | ✓ | ✓ | ✓ |
Cinder | ✓ | - | - |
FC | ✓ | ✓ | - |
FlexVolume | ✓ | ✓ | depends on the driver |
Flocker | ✓ | - | - |
GCEPersistentDisk | ✓ | ✓ | - |
Glusterfs | ✓ | ✓ | ✓ |
HostPath | ✓ | - | - |
iSCSI | ✓ | ✓ | - |
Quobyte | ✓ | ✓ | ✓ |
NFS | ✓ | ✓ | ✓ |
RBD | ✓ | ✓ | - |
VsphereVolume | ✓ | - | - (works when pods are collocated) |
PortworxVolume | ✓ | - | ✓ |
ScaleIO | ✓ | ✓ | - |
StorageOS | ✓ | - | - |
Kelas
Sebuah PV bisa memiliki sebuah kelas, yang dispesifikasi dalam pengaturan atribut
storageClassName
menjadi nama
StorageClass.
Sebuah PV dari kelas tertentu hanya dapat terikat dengan PVC yang meminta
kelas tersebut. Sebuah PV tanpa storageClassName
tidak memiliki kelas dan hanya dapat terikat
dengan PVC yang tidak meminta kelas tertentu.
Dahulu, anotasi volume.beta.kubernetes.io/storage-class
digunakan sebagai ganti
atribut storageClassName
. Anotasi ini masih dapat bekerja, namun
akan dihilangkan sepenuhnya pada rilis Kubernetes mendatang.
Kebijakan Reklaim
Kebijakan-kebijakan reklaim saat ini antara lain:
- Retain -- reklamasi manual
- Recycle -- penghapusan dasar (
rm -rf /thevolume/*
) - Delete -- aset storage terasosiasi seperti AWS EBS, GCE PD, Azure Disk, atau OpenStack Cinder volume akan dihapus
Saat ini, hanya NFS dan HostPath yang mendukung daur ulang. AWS EBS, GCE PD, Azure Disk, dan Cinder Volume mendukung penghapusan.
Opsi Pemasangan
Seorang administrator Kubernetes dapat menspesifikasi opsi pemasangan tambahan untuk ketika sebuah Persistent Volume dipasangkan pada sebuah node.
Tipe-tipe volume yang mendukung opsi pemasangan antara lain:
- AWSElasticBlockStore
- AzureDisk
- AzureFile
- CephFS
- Cinder (OpenStack block storage)
- GCEPersistentDisk
- Glusterfs
- NFS
- Quobyte Volumes
- RBD (Ceph Block Device)
- StorageOS
- VsphereVolume
- iSCSI
Opsi pemasangan tidak divalidasi, sehingga pemasangan akan gagal jika salah satunya tidak valid.
Dahulu, anotasi volume.beta.kubernetes.io/mount-options
digunakan sebagai ganti
atribut mountOptions
. Anotasi ini masih dapat bekerja, namun
akan dihilangkan sepenuhnya pada rilis Kubernetes mendatang.
Afinitas Node
Sebuah PV dapat menspesifikasi afinitas node untuk mendefinisikan batasan yang membatasi node mana saja yang dapat mengakses volume tersebut. Pod yang menggunakan sebuah PV hanya akan bisa dijadwalkan ke node yang dipilih oleh afinitas node.
Fase
Sebuah volume akan berada dalam salah satu fase di bawah ini:
- Available -- sumber daya bebas yang belum terikat dengan sebuah klaim
- Bound -- volume sudah terikat dengan sebuah klaim
- Released -- klaim sudah dihapus, tetapi sumber daya masih belum direklaim oleh klaster
- Failed -- volume gagal menjalankan reklamasi otomatis
CLI akan menunjukkan nama dari PVC yang terikat pada PV.
PersistentVolumeClaims
Setiap PVC memiliki spec dan status, yang merupakan spesifikasi dan status dari klaim.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: environment, operator: In, values: [dev]}
Mode Akses
Klaim menggunakan penulisan yang sama dengan volume ketika meminta storage dengan mode akses tertentu.
Mode Volume
Klaim menggunakan penulisan yang sama dengan volume untuk mengindikasikan konsumsi dari volume sebagai filesystem ataupun perangkat block.
Sumber daya
Klaim, seperti pod, bisa meminta sumber daya dengan jumlah tertentu. Pada kasus ini, permintaan untuk storage. Model sumber daya yang sama berlaku untuk baik volume maupun klaim.
Selector
Klaim dapat menspesifikasi label selector untuk memilih serangkaian volume lebih jauh. Hanya volume yang cocok labelnya dengan selector yang dapat terikat dengan klaim. Selector dapat terdiri dari dua kolom:
matchLabels
- volume harus memiliki label dengan nilai inimatchExpressions
- daftar dari persyaratan yang dibuat dengan menentukan kunci, daftar nilai, dan operator yang menghubungkan kunci dengan nilai. Operator yang valid meliputi In, NotIn, Exists, dan DoesNotExist.
Semua persyaratan tersebut, dari matchLabels
dan matchExpressions
akan dilakukan operasi AND bersama – semuanya harus dipenuhi untuk mendapatkan kecocokan.
Kelas
Sebuah klaim dapat meminta kelas tertentu dengan menspesifikasi nama dari
StorageClass
menggunakan atribut storageClassName
.
Hanya PV dari kelas yang diminta, yang memiliki storageClassName
yang sama dengan PVC, yang dapat
terikat dengan PVC.
PVC tidak harus meminta sebuah kelas. Sebuah PVC dengan storageClassName
miliknya bernilai
""
akan selalu diinterpretasikan sebagai meminta PV tanpa kelas, jadi PVC
hanya bisa terikat ke PV tanpa kelas (tanpa anotasi atau bernilai
""
). Sebuah PVC tanpa storageClassName
tidaklah sama dan diperlakukan berbeda
oleh klaster tergantung apakah
admission plugin DefaultStorageClass
dinyalakan.
- Jika admission plugin dinyalakan, administrator bisa menspesifikasi
StorageClass
standar. Seluruh PVC yang tidak memilikistorageClassName
dapat terikat hanya ke PVs standar. MenspesifikasikanStorageClass
standar dapat dilakukan dengan mengatur anotasistorageclass.kubernetes.io/is-default-class
menjadi "true" pada sebuah objekStorageClass
. Jika administrator tidak menspesifikasikan standar apapun, klaster menanggapi pembuatan PVC sekan-akan admission plugin dimatikan. Jika ada lebih dari satu setelan standar dispesifikasikan, admission plugin melarang pembuatan seluruh PVC. - Jika admission plugin dimatikan, tidak ada pilihan menggunakan
StorageClass
standar. Semua PVC yang tidak memilikistorageClassName
hanya dapat diikat ke PV yang tidak memiliki kelas. Pada kasus ini, PVC yang tidak memilikistorageClassName
diperlakukan sama seperti PVC yang memilikistorageClassName
bernilai""
.
Tergantung metode instalasi, sebuah StorageClass dari setelan standar dapat dibuat ke klaster Kubernetes oleh addon manager pada saat instalasi.
Ketika sebuah PVC menspesifikasi sebuah selector
selain meminta StorageClass
,
kebutuhan tersebut akan digabungkan dengan operasi AND bersama: hanya PV dari kelas yang diminta dan dengan
label yang diminta yang dapat terikat ke PVC.
selector
yang tak kosong tidak dapat memiliki PV yang disediakan secara dinamis untuknya.
Dahulu, anotasi volume.beta.kubernetes.io/storage-class
digunakan sebagai ganti
atribut storageClassName
. Anotasi ini masih dapat bekerja, namun
akan dihilangkan sepenuhnya pada rilis Kubernetes mendatang.
Klaim sebagai Volume
Pod mengakses storage dengan menggunakan klaim sebagai volume. Klaim harus berada pada namespace yang sama dengan pod yang menggunakan klaim tersebut. Klaster menemukan klaim pada namespace yang sama dengan pod dan menggunakannya untuk mendapatkan PersistentVolume
(PV) yang ada di baliknya. Volume tersebut kemudian dipasangkan ke host dan lalu ke pod.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
Catatan Mengenai Namespace
Ikatan PersistentVolumes
bersifat eksklusif, dan karena PersistentVolumeClaims
merupakan objek yang berada pada namespace, pemasangan klaim dengan "banyak" mode (ROX
, RWX
) hanya dimungkinkan jika berada dalam satu namespace yang sama.
Dukungan Volume Raw Block
Kubernetes v1.13 [beta]
Volume plugins berikut mendukung volume raw block, termasuk penyediaan dinamis jika mungkin diterapkan.
- AWSElasticBlockStore
- AzureDisk
- FC (Fibre Channel)
- GCEPersistentDisk
- iSCSI
- Local volume
- RBD (Ceph Block Device)
- VsphereVolume (alpha)
Persistent Volume menggunakan Volume Raw Block
apiVersion: v1
kind: PersistentVolume
metadata:
name: block-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
volumeMode: Block
persistentVolumeReclaimPolicy: Retain
fc:
targetWWNs: ["50060e801049cfd1"]
lun: 0
readOnly: false
Persistent Volume Claim meminta Volume Raw Block
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: block-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Block
resources:
requests:
storage: 10Gi
Spesifikasi Pod yang menambahkan alamat Perangkat Raw Block pada kontainer
apiVersion: v1
kind: Pod
metadata:
name: pod-with-block-volume
spec:
containers:
- name: fc-container
image: fedora:26
command: ["/bin/sh", "-c"]
args: [ "tail -f /dev/null" ]
volumeDevices:
- name: data
devicePath: /dev/xvda
volumes:
- name: data
persistentVolumeClaim:
claimName: block-pvc
Mengikat Block Volume
Jika seorang pengguna meminta sebuah volume raw block dengan mengindikasikannya menggunakan kolom volumeMode
pada spec PersistentVolumeClaim
(PVC), aturan pengikatannya sedikit berbeda dibanding rilis-rilis sebelumnya yang tidak memerhatikan mode ini sebagai bagian dari spec.
Di bawah merupakan tabel dari kemungkinan kombinasi yang pengguna dan admin dapat spesifikasikan untuk meminta sebuah perangkat raw block. Tabel tersebut mengindikasikan apakah volume akan terikat atau tidak jika dikombinasikan dengan cara tertentu:
Matriks pengikatan volume untuk volume yang disediakan secara statis:
PV volumeMode | PVC volumeMode | Hasil |
---|---|---|
unspecified | unspecified | TERIKAT |
unspecified | Block | TIDAK TERIKAT |
unspecified | Filesystem | TERIKAT |
Block | unspecified | TIDAK TERIKAT |
Block | Block | TERIKAT |
Block | Filesystem | TIDAK TERIKAT |
Filesystem | Filesystem | TERIKAT |
Filesystem | Block | TIDAK TERIKAT |
Filesystem | unspecified | TERIKAT |
Volume Snapshot dan Dukungan Pemulihan Volume dari Snapshot
Kubernetes v1.12 [alpha]
Fitur volume snapshot ditambahkan hanya untuk mendukung CSI Volume Plugins. Untuk lebih detail, lihat volume snapshots.
Untuk mengaktifkan dukungan pemulihan sebuah volume dari sebuah sumber data volume snapshot, aktifkan
gerbang fitur VolumeSnapshotDataSource
pada apiserver dan controller-manager.
Membuat Persistent Volume Claim dari Volume Snapshot
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: restore-pvc
spec:
storageClassName: csi-hostpath-sc
dataSource:
name: new-snapshot-test
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Menulis Konfigurasi Portabel
Jika kamu menulis templat konfigurasi atau contoh yang dapat berjalan pada berbagai macam klaster dan membutuhkan persistent storage, kami merekomendasikan agar kamu menggunakan pola berikut:
- Masukkan objek PersistentVolumeClaim (PVC) pada kumpulan config (bersamaan dengan Deployments, ConfigMaps, dsb).
- Jangan memasukkan objek PersistentVolume (PV) pada config, karena pengguna yang menginstantiasi config tersebut kemungkinan tidak memiliki izin untuk membuat PersistentVolume (PV).
- Berikan pengguna opsi untuk menyediakan nama storage class ketika menginstantiasi
templat.
- Jika pengguna menyediakan nama storage class, taruh nilai tersebut pada
kolom
persistentVolumeClaim.storageClassName
. Hal ini akan membuat PVC agar sesuai dengan storage class yang tepat jika klaster memiliki banyak StorageClass yang diaktifkan oleh admin. - Jika pengguna tidak menyediakan nama storage class, biarkan
kolom
persistentVolumeClaim.storageClassName
kosong.- Hal ini kakan membuat sebuah PV disediakan secara otomatis untuk pengguna dengan StorageClass standar pada klaster. Banyak lingkungan klaster memiliki StorageClass standar yang sudah terpasang, atau administrator dapat membuat StorageClass standar sendiri.
- Jika pengguna menyediakan nama storage class, taruh nilai tersebut pada
kolom
- Dalam pembuatan, perhatikan PVC yang tidak kunjung terikat setelah beberapa lama dan beritahukan hal ini pada pengguna, karena hal ini dapat mengindikasikan klaster tidak memiliki dukungan penyimpanan dinamis (di mana pengguna harus membuat PV yang sesuai) atau klaster tidak memiliki sistem penyimpanan (di mana penggun tidak dapat membuat PVC yang membutuhkan config).
3.6.3 - VolumeSnapshot
Kubernetes v1.12 [alpha]
Pengenalan
Seperti halnya sumber daya API PersistentVolume dan PersistentVolumeClaim yang digunakan oleh para pengguna dan administrator untuk menyediakan volume, sumber daya API VolumeSnapshotContent dan VolumeSnapshot digunakan mereka untuk membuat snapshot volume.
VolumeSnapshotContent merupakan suatu snapshot yang diambil dari sebuah volume dari dalam klaster yang telah disediakan oleh administrator. Sepert layaknya PersistentVolume, VolumeSnapshotContent juga merupakan bagian dari sumber daya klaster.
VolumeSnapshot merupakan suatu permintaan snapshot dari volume oleh pengguna. Mirip seperti halnya PersistentVolumeClaim.
Walaupun VolumeSnapshot membuat pengguna bisa mengonsumsi abstraksi dari sumber daya penyimpanan, administrator klaster tetap perlu menawarkan berbagai macam tipe VolumeSnapshotContent, tanpa perlu mengekspos pengguna pada detail bagaimana snapshot volume tersebut harus tersediakan. Bagi yang memerlukan hal ini, ada yang namanya sumber daya VolumeSnapshotClass.
Para pengguna tetap perlu mengetahui beberapa hal di bawah ketika menggunakan fitur ini:
- Objek API VolumeSnapshot, VolumeSnapshotContent, dan VolumeSnapshotClass adalah CRD, bukan bagian dari API inti.
- Fitur VolumeSnapshot hanya tersedia untuk CSI driver.
- Sebagai bagian dari proses deploy, tim Kubernetes menyediakan Container sidecar bantuan untuk controller snapshot berrnama
external-snapshotter
. Container ini melakukan watch pada objek VolumeSnapshot dan memicu operasi CreateSnapshot dan DeleteSnapshot terhadap sebuah endpoint CSI. - Driver CSI ada yang telah implementasi fitur VolumeSnapshot, ada juga yang belum. Driver CSI yang telah menyediakan dukungan terhadap fitur VolumeSnapshot kemungkinan besar menggunakan
external-snapshotter
. - Driver CSI yang mendukung VolumeSnapshot akan secara otomatis melakukan instalasi CRD untuk VolumeSnapshot.
Siklus hidup VolumeSnapshot dan VolumeSnapshotContent
VolumeSnapshotContent merupakan bagian dari sumber daya klaster. VolumeSnapshot merupakan permintaan terhadap sumber daya tersebut. Interaksi antara VolumeSnapshotContent dan VolumeSnapshot mengikuti siklus hidup berikut ini:
Penyediaan VolumeSnapshot
Ada dua cara untuk menyediakan snapshot: secara statis maupun dinamis.
Statis
Seorang administrator klaster membuat beberapa VolumeSnapshotContent, yang masing-masing memiliki detail tentang penyimpanan sebenarnya yang dapat dipergunakan oleh para pengguna. VolumeSnapshotContent tersebut dapat dikonsumsi melalui API Kubernetes.
Dinamis
Ketika VolumeSnapshotContent yang dibuat oleh administrator tidak ada yang sesuai dengan VolumeSnapshot yang dibuat pengguna, klaster bisa saja mencoba untuk menyediakan sebuah VolumeSnapshot secara dinamis, khususnya untuk objek VolumeSnapshot. Proses penyediaan ini berdasarkan VolumeSnapshotClasses: VolumeSnapshot harus meminta sebuah VolumeSnapshotClass dan administrator harus membuat serta mengatur class tersebut supaya penyediaan dinamis bisa terjadi.
Ikatan (Binding)
Seorang pengguna akan membuat (atau telah membuat, dalam kasus penyediaan dinamis) sebuah VolumeSnapshot dengan ukuran penyimpanan yang diminta beserta mode akses tertentu. Suatu loop kontrol melakukan watch terhadap VolumeSnapshot baru, mencari VolumeSnapshotContent yang sesuai (jika memungkinkan), dan mengikat (bind) keduanya. Jika VolumeSnapshotContent secara dinamis disediakan untuk VolumeSnapshot yang baru, loop akan terus mengikat VolumeSnapshotContent dengan VolumeSnapshot. Ketika telah terikat (bound), VolumeSnapshot bind bersifat eksklusif, terlepas dari bagaimana proses bind dilakukan. Ikatan (binding) antara suatu VolumeSnapshot dengan VolumeSnapshotContent bersifat 1:1 mapping.
VolumeSnapshot akan tetap tidak terikat (unbound) tanpa ada batas waktu, jika VolumeSnapshotContent yang sesuai tidak ditemukan. VolumeSnapshot akan menjadi terikat (bound) ketika VolumeSnapshotContent yang sesuai menjadi ada.
PersistentVolumeClaim dengan in-Use Protection
Tujuan dari objek PersistentVolumeClaim dengan fitur in Use Protection adalah memastikan objek API PVC yang masih dalam penggunaan (in-use) tidak akan dihilangkan dari sistem (penghilangan akan menyebabkan hilangnya data).
Jika sebuah PVC sedang digunakan secara aktif oleh proses snapshot yang digunakan sebagai sumbernya (source), artinya PVC sedang dalam penggunaan (in-use). Jika seorang pengguna menghapus suatu objek API PVC saat dalam penggunaan sebagai sumber snapshot, objek PVC tidak akan dihilangkan segera. Namun, penghapusan objek PVC akan ditunda sampai PVCC tidak lagi secara aktif digunakan oleh proses snapshot manapun. Suatu PVC tidak lagi diguunakan sebagai suumber snapshot ketika ReadyToUse
dari Status
snapshot menjadi true
.
Penghapusan
Proses penghapusan akan menghilangkan objek VolumeSnapshot dari API Kubernetes, beserta aset penyimpanan terkait pada infrastruktur eksternal.
VolumeSnapshotContent
Setiap VolumeSnapshotContent memiliki sebuah spec, yang merepresentasikan spesifikasi dari snapshot volume tersebut.
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotContent
metadata:
name: new-snapshot-content-test
spec:
snapshotClassName: csi-hostpath-snapclass
source:
name: pvc-test
kind: PersistentVolumeClaim
volumeSnapshotSource:
csiVolumeSnapshotSource:
creationTime: 1535478900692119403
driver: csi-hostpath
restoreSize: 10Gi
snapshotHandle: 7bdd0de3-aaeb-11e8-9aae-0242ac110002
Class
Suatu VolumeSnapshotContent dapat memiliki suatu class, yang didapat dengan mengatur atribut
snapshotClassName
dengan nama dari VolumeSnapshotClass.
VolumeSnapshotContent dari class tertentu hanya dapat terikat (bound) dengan VolumeSnapshot yang
"meminta" class tersebut. VolumeSnapshotContent tanpa snapshotClassName
tidak memiliki class dan hanya dapat
terikat (bound) dengan VolumeSnapshot yang "meminta" untuk tidak menggunakan class.
VolumeSnapshot
Masing-masing VolumeSnapshot memiliki sebuah spec dan status, yang merepresentasikan spesifikasi dan status dari snapshot volume tersebut.
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshot
metadata:
name: new-snapshot-test
spec:
snapshotClassName: csi-hostpath-snapclass
source:
name: pvc-test
kind: PersistentVolumeClaim
Class
Suatu VolumeSnapshot dapat meminta sebuah class tertentu dengan mengatur nama dari
VolumeSnapshotClass
menggunakan atribut snapshotClassName
.
Hanya VolumeSnapshotContent dari class yang diminta, memiliki snapshotClassName
yang sama
dengan VolumeSnapshot, dapat terikat (bound) dengan VolumeSnapshot tersebut.
Penyediaan (Provisioning) Volume dari Snapshot
Kamu dapat menyediakan sebuah volume baru, yang telah terisi dengan data dari suatu snapshot, dengan
menggunakan field dataSource
pada objek PersistentVolumeClaim.
Untuk detailnya bisa dilihat pada VolumeSnapshot and Mengembalikan Volume dari Snapshot.
3.6.4 - Pengklonaan Volume CSI
Kubernetes v1.16 [beta]
Introduction
Fitur CSI Volume Cloning menambahkan dukungan untuk merinci PVC yang telah tersedia pada kolom dataSource
untuk mengindikasikan bahwa seorang pengguna ingin melakukan pengklonaan terhadap sebuah Volume.
Sebuah klona didefinisikan sebagai sebuah duplikat dari sebuah Volume Kubernetes yang telah tersedia yang dapat digunakan sebagai sebuah Volume standar. Perbedaannya hanyalah pada saat penyediaannya, daripada membuat sebuah Volume kosong yang "baru", peranti penyokongnya membuat sebuah duplikat sama persis dari Volume yang dirinci.
Implementasi dari pengklonaan, dari sudut pandang API Kubernetes, secara sederhana menambahkan kemampuan untuk merinci sebuah PVC yang telah tersedia sebagai sebuah dataSource saat pembuatan PVC. PVC sumber harus tertambat (bound) dan tersedia (tidak sedang digunakan).
Pengguna-pengguna mesti menyadari hal-hal berikut saat menggunakan fitur ini:
- Dukungan pengklonaan (
VolumePVCDataSource
) hanya tersedia untuk driver-driver CSI. - Dukungan pengklonaan hanya tersedia untuk penyedia-penyedia dinamis.
- Driver-driver CSI mungkin telah atau belum mengimplementasi fungsi pengklonaan Volume.
- Kamu hanya dapat mengklonakan sebuah PVC saat ia tersedia pada Namespace yang sama dengan PVC tujuan (sumber dan tujuan harus berada pada Namespace yang sama).
- Pengklonaan hanya didukung pada Storage Class yang sama.
- Volume tujuan harus memiliki Storage Class yang sama dengan sumbernya.
- Storage Class bawaan dapat digunakan dan
storageClassName
dihilangkan darispec
Penyediaan
Klona-klona disediakan sama seperti PVC lainnya dengan pengecualian dengan penambahan sebuah dataSource
yang merujuk pada sebuah PVC yang telah tersedia pada Namespace yang sama.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: clone-of-pvc-1
namespace: myns
spec:
accessModes:
- ReadWriteOnce
storageClassName: cloning
resources:
requests:
storage: 5Gi
dataSource:
kind: PersistentVolumeClaim
name: pvc-1
Hasilnya adalah sebuah PVC baru dengan nama clone-of-pvc-1
yang memiliki isi yang sama dengan sumber yang dirinci pvc-1
.
Penggunaan
Setelah tersedianya PVC baru tersebut, PVC baru yang diklonakan tersebut digunakan sama seperti PVC lainnya. Juga diharapkan pada titik ini bahwa PVC baru tersebut adalah sebuah objek terpisah yang independen. Ia dapat digunakan, diklonakan, di-snapshot, atau dihapus secara terpisah dan tanpa perlu memikirkan PVC dataSource aslinya. Hal ini juga berarti bahwa sumber tidak terikat sama sekali dengan klona yang baru dibuat tersebut, dan dapat diubah atau dihapus tanpa memengaruhi klona yang baru dibuat tersebut.
3.6.5 - StorageClass
Dokumen ini mendeskripsikan konsep StorageClass yang ada pada Kubernetes. Sebelum lanjut membaca, sangat dianjurkan untuk memiliki pengetahuan terhadap volumes dan peristent volume terlebih dahulu.
Pengenalan
Sebuah StorageClass menyediakan cara bagi administrator untuk mendeskripsikan "kelas" dari penyimpanan yang mereka sediakan. Kelas yang berbeda bisa saja memiliki perbedaan dari segi kualitas servis yang disediakan, pemulihan (backup) kebijakan, atau kebijakan lain yang ditentukan oleh administrator klaster. Kubernetes sendiri tidak dipengaruhi oleh kelas apakah yang digunakan pada mekanisme penyimpanan yang digunakan. Mekanisme ini seringkali disebut sebagai "profiles" pada sistem penyimpanan yang lain.
Sumber daya StorageClass
Setiap StorageClass (kelas penyimpanan) memiliki field-field mendasar seperti
provisioner
, parameters
, dan reclaimPolicy
, yang digunakan ketika
PersistentVolume
yang dimiliki oleh kelas tersebut perlu disediakan (di-provision).
Nama yang digunakan oleh suatu StorageClass sifatnya penting, karena
ini merupakan cara yang digunakan oleh pengguna untuk meminta
penyimpanan dengan kelas tertentu. Administrator dapat menentukan
nama dan parameter lain dari suatu kelas ketika membuat suatu objek StorageClass
,
dan objek yang sudah dibuat tidak dapat diubah lagi definisinya.
Administrator dapat memberikan spesifikasi StorageClass default bagi
PVC yang tidak membutuhkan kelas tertentu untuk dapat melakukan mekanisme bind:
kamu dapat membaca bagian PersistentVolumeClaim
untuk penjelasan lebih lanjut.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
reclaimPolicy: Retain
mountOptions:
- debug
volumeBindingMode: Immediate
Provisioner
Setiap kelas penyimpanan (storage class) memiliki sebuah provisioner yang menentukan plugin manakah yang digunakan ketika sebuah PV disediakan (di-provision). Field ini haruslah didefinisikan.
Plugin Volume | Provisioner Internal | Contoh Konfigurasi |
---|---|---|
AWSElasticBlockStore | ✓ | AWS EBS |
AzureFile | ✓ | Azure File |
AzureDisk | ✓ | Azure Disk |
CephFS | - | - |
Cinder | ✓ | OpenStack Cinder |
FC | - | - |
Flexvolume | - | - |
Flocker | ✓ | - |
GCEPersistentDisk | ✓ | GCE PD |
Glusterfs | ✓ | Glusterfs |
iSCSI | - | - |
Quobyte | ✓ | Quobyte |
NFS | - | - |
RBD | ✓ | Ceph RBD |
VsphereVolume | ✓ | vSphere |
PortworxVolume | ✓ | Portworx Volume |
ScaleIO | ✓ | ScaleIO |
StorageOS | ✓ | StorageOS |
Local | - | Local |
Kamu tidak dibatasi untuk hanya menggunakan provisioner internal yang disediakan pada list yang tersedia (yang memiliki nama dengan prefix "kubernetes.io" dan didistribusikan bersamaan dengan Kubernetes). Kamu juga dapat menjalankan dan mendefinisikan provisioner eksternal yang merupakan program independen selama program tersebut menerapkan spesifikasi yang didefinisikan oleh Kubernetes. Penulis dari provisioner eksternal Kubernetes memiliki kuasa penuh akan tempat dimana kode sumber yang mereka tulis, bagaimana mekanisme penyediaan (provisioning) dilakukan, serta bagaimana hal tersebut dapat dijalankan, serta plugin volume apakah yang digunakan (termasuk Flex), dkk. Repositori kubernetes-incubator/external-storage menyimpan library yang dibutukan untuk menulis provisioner eksternal yang mengimplementasi spesifikasi serta beberapa provisioner eksternal yang dipelihara oleh komunitas.
Sebagai contoh, NFS tidak menyediakan provisioner internal, tetapi sebuah provisioner eksternal dapat digunakan. Beberapa provisioner eksternal dapat ditemukan di bawah repositori kubernetes-incubator/external-storage. Di sana juga terdapat beberapa kasus dimana vendor penyimpanan 3rd party menyediakan provisioner eksternal yang mereka sediakan sendiri.
Perolehan Kembali untuk Kebijakan (Reclaim Policy)
Persistent Volumes yang secara dinamis dibuat oleh sebuah kelas penyimpanan
akan memiliki reclaim policy yang didefinisikan di dalam field reclaimPolicy
dari kelas tersebut, yang nilainya dapat diisi dengan Delete
atau Retain
.
Jika tidak terdapat reclaimPolicy
yang dispesifikasikan ketika sebuah objek
StorageClass dibuat, maka nilai default bagi kelas tersebut adalah Delete
.
PersistentVolume yang dibuat secara manual dan diatur dengan menggunakan kelas penyimpanan akan menggunakan reclaim policy apapun yang diberikan pada saat objek tersebut dibuat.
Pilihan Mount
PersistentVolume yang secara dinamis dibuat oleh sebuah kelas penyimpanan
akan memiliki pilihan mount yang dapat dispesifikasikan pada field
mountOptions
dari kelas tersebut.
Jika sebuah plugin volume tidak mendukung pilihan mount yang dispesifikasikan, mekanisme penyediaan (provision) akan digagalkan. Pilihan mount yang akan divalidasi pada kelas penyimpanan maupun PV, maka mount tersebut akan gagal apabila salah satu dari keduanya bersifat invalid.
Mode Volume Binding
Field volumeBindingMode
mengontrol kapan mekanisme binding volume dan
provisioning dinamis
harus dilakukan.
Secara default, ketika mode Immediate
yang mengindikasikan
terjadinya volume binding dan provisioning dinamis terjadi ketika
PersistentVolumeClaim dibuat. Untuk backend penyimpanan yang dibatasi oleh
topologi tertentu dan tidak dapat diakses secara global dari semua Node
yang ada di klaster, PersistentVolume akan di-bound atau di-provision
tanpa perlu memenuhi persyaratan scheduling dari Pod. Hal ini dapat menyebabkan
adanya Pod yang tidak mendapatkan mekanisme scheduling.
Seorang administrator klaster dapat mengatasi hal tersebut dengan cara memberikan
spesifikasi mode WaitForFirstConsumer
yang akan memperlambat mekanisme provisioning
dan binding dari sebuah PersistentVolume hingga sebuah Pod yang menggunakan
PersistentVolumeClaim dibuat. PersistentVolume akan dipilih atau di-provisioning
sesuai dengan topologi yang dispesifikasikan oleh limitasi yang diberikan
oleh mekanisme scheduling Pod. Hal ini termasuk, tetapi tidak hanya terbatas pada,
persyaratan sumber daya,
node selector,
afinitas dan
anti-afinitas Pod,
serta taint dan toleration.
Beberapa plugin di bawah ini mendukung WaitForFirstConsumer
dengan provisioning
dinamis:
Beberapa plugin di bawah ini mendukung WaitForFirstConsumer
dengan binding
PersistentVolume yang terlebih dahulu dibuat:
- Semua hal di atas
- Lokal
Kubernetes 1.14 [beta]
CSINodeInfo
haruslah diaktifkan.
Topologi yang Diizinkan
Ketika sebuah operator klaster memberikan spesifikasi WaitForFirstConsumer
pada
mode binding
volume, mekanisme pembatasan (restriksi) provisioning
tidak lagi dibutuhkan
pada sebagian besar kasus. Meskipun begitu, apabila hal tersebut masih dibutuhkan,
field
allowedTopologies
dapat dispesifikasikan.
Contoh ini memberikan demonstrasi bagaimana cara membatasi topologi
dari volume yang di-provision pada suatu zona spesifik serta harus digunakan
sebagai pengganti parameter zone
dam zones
untuk plugin
yang akan digunakan.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
- key: failure-domain.beta.kubernetes.io/zone
values:
- us-central1-a
- us-central1-b
Parameter-Parameter
Kelas-kelas penyimpanan memiliki parameter yang mendeskripsikan
volume yang dimiliki oleh kelas penyimpanan tersebut. Parameter yang berbeda
bisa saja diterima bergantung pada provisioner
. Sebagai contohnya, nilai io1
,
untuk parameter type
, dan parameter iopsPerGB
spesifik terhadap EBS.
Ketika sebuah parameter diabaikan, beberapa nilai default akan digunakan sebagai
gantinya.
AWS EBS
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "10"
fsType: ext4
type
:io1
,gp2
,sc1
,st1
. Lihat dokumentasi AWS untuk detail lebih lanjut. Nilai default:gp2
.zone
(deprecated): zona AWS. Jika tidak terdapat nilaizone
atauzones
yang dispesifikasikan, volume secara generik dijadwalkan dengan menggunakan penjadwalanround-robin-ed
pada semua zona aktif yang ada pada klaster Kubernetes yang memiliki node.zones
(deprecated): Nilai terpisahkan koma yang merupakan barisan zona pada AWS. Jika tidak terdapat nilaizone
atauzones
yang dispesifikasikan, volume secara generik dijadwalkan dengan menggunakan penjadwalanround-robin-ed
pada semua zona aktif yang ada pada klaster Kubernetes yang memiliki node.iopsPerGB
: hanya untuk volumeio1
. Operasi per detik per GiB. Volume plugin AWS mengalikan nilai ini dengan ukuran volume yang dibutuhkan untuk menghitung IOPS dari volume (nilai maksimum yang didukung adalah 20,000 IOPS baca dokumentasi AWS. Nilai masukan yang diharapkan merupakan string, misalnya"10"
, bukan10
.fsType
: fsType yang didukung oleh Kubernetes. Nilai default-nya adalah:"ext4"
.encrypted
: menyatakan dimana volume EBS harus dienkripsi atau tidak. Nilai yang valid adalah"true"
atau"false"
(dalam string bukan boolean i.e."true"
, bukantrue
).kmsKeyId
: opsional. Merupakan nama dari Amazon Resource Name dari key yang digunakan untuk melakukan enkripsi volume. Jika nilai ini tidak disediakan tetapi nilai dari fieldencrypted
adalah true, sebuah key akan dibuat oleh AWS. Perhatikan dokumentasi AWS untuk mengetahui nilai yang valid bagi ARN.
PD GCE
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
replication-type: none
type
:pd-standard
ataupd-ssd
. Nilai default:pd-standard
zone
(deprecated): zona GCE. Jika tidak terdapat nilaizone
atauzones
yang dispesifikasikan, volume secara generik dijadwalkan dengan menggunakan penjadwalanround-robin-ed
pada semua zona aktif yang ada pada klaster Kubernetes yang memiliki node.zones
(deprecated): Nilai terpisahkan koma yang merupakan barisan zona. Jika tidak terdapat nilaizone
atauzones
yang dispesifikasikan, volume secara generik dijadwalkan dengan menggunakan penjadwalanround-robin-ed
pada semua zona aktif yang ada pada klaster Kubernetes yang memiliki node.replication-type
:none
atauregional-pd
. Nilai default:none
.
Jika replication-type
diubah menjadi none
, sebuah PD reguler (zonal) akan
di-provisioning.
Jika replication-type
diubah menjadi regional-pd
, sebuah
Persistent Disk Regional (PD Regional)
akan di-provisioning. Pada kasus ini, pengguna harus menggunakan zones
dan bukan zone
untuk menspesifikasikan zona replikasi yang diinginkan. Jika terdapat
tepat dua zona yang dispesifikasikan, PD Regional akan di-provisioning pada
zona replikasi yang diinginkan. Jika terdapat lebih dari 2 zona yang dispesifikasikan,
Kubernetes akan memilih secara acak zona dari zona-zona yang dispesifikasikan. Jika
parameter zones
tidak diinisialisasi, Kubernetes akan memilih secara acak dari
zona yang diatur oleh klaster Kubernetes.
Glusterfs
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/glusterfs
parameters:
resturl: "http://127.0.0.1:8081"
clusterid: "630372ccdc720a92c681fb928f27b53f"
restauthenabled: "true"
restuser: "admin"
secretNamespace: "default"
secretName: "heketi-secret"
gidMin: "40000"
gidMax: "50000"
volumetype: "replicate:3"
-
resturl
: Servis REST Gluster/URL servis Heketi yang digunakan untuk melakukan provisioning volume gluster sesuai dengan kebutuhan. Format secara umum haruslah dalam bentukIPaddress:Port
dan hal ini merupakan parameter wajib untuk provisioner dinamis GlusterFS. Jika servis Heketi diekspos sebagai servis yang dapat melakukan routing pada pengaturan openshift/kubernetes, ini dapat memiliki format yang sesuai denganhttp://heketi-storage-project.cloudapps.mystorage.com
dimana fqdn yang ada merupakan URL servis Heketi yang dapat di-resolve. -
restauthenabled
: Servis REST Gluster menyediakan nilai boolean yang dapat digunakan untuk mengajukanauthentication
untuk server REST yang ada. Jika nilai yang disediakan adalah"true"
, dengan kondisi dimanarestuser
danrestuserkey
atausecretNamespace
+secretName
harus diisi. Opsi ini sudah_deprecated_, mekanisme otentikasi akan diizinkan apabila salah satu dari fieldrestuser
,restuserkey
,secretName
atausecretNamespace
diterapkan. -
restuser
: Pengguna servis REST Gluster/Heketi yang memiliki akses untuk membuat volume di dalam Trusted Pool Gluster. -
restuserkey
: Password pengguna servis REST Gluster/Heketi yang digunakan untuk mekanisme otentikasi server REST. Parameter ini deprecated dan digantikan dengan parametersecretNamespace
+secretName
. -
secretNamespace
,secretName
: Identifikasi instans Secret yang mengandung password pengguna yang digunakan untuk berkomunikasi dengan servis REST Gluster. Parameter ini dianggap opsional, password kosong dapat digunakan ketika nilai darisecretNamespace
dansecretName
tidak dispesifikasikan. Secret yang disediakan haruslah memiliki tipe"kubernetes.io/glusterfs"
, yang dapat dibuat dengan menggunakan mekanisme dibawah ini:kubectl create secret generic heketi-secret \ --type="kubernetes.io/glusterfs" --from-literal=key='opensesame' \ --namespace=default
Contoh Secret dapat ditemukan pada berkas berikut glusterfs-provisioning-secret.yaml.
-
clusterid
:630372ccdc720a92c681fb928f27b53f
merupakan ID dari klaster yang akan digunakan oleh Heketi ketikan melakukan provisioning volume. ID ini juga dapat berupa serangkaian list, misalnya:"8452344e2becec931ece4e33c4674e4e,42982310de6c63381718ccfa6d8cf397"
. Parameter ini merupakan parameter opsional. -
gidMin
,gidMax
: Nilai minimum dan maksimum dari GID untuk kelas penyimpanan (storage class). Sebuah nilai unik dari GID di dalam range ( gidMin-gidMax ) ini akan digunakan untuk melakukan provisioning volume secara dinamis. Nilai ini bersifat opsional. Jika tidak dispesifikasikan, volume akan secara default di-provisioning dalam range 2000-2147483647 yang merupakan nilai default dari gidMin dan gidMax. -
volumetype
: Tipe volume beserta paremeter-nya dapat diatur dengan menggunakan nilai opsional berikut. Jika tipe dari volume tidak dispesifikasikan, maka provisioner akan memutuskan tipe volume apakah yang akan digunakan.Sebagai contoh:
-
Volume replika:
volumetype: replicate:3
dimana '3' merupakan jumlah replika. -
Persebaran (Disperse)/EC volume:
volumetype: disperse:4:2
dimana'4' merupakan data dan '2' merupakan jumlah redundansi. -
Distribusi volume:
volumetype: none
Untuk tipe volume apa saja yang tersedia dan berbagai opsi administrasi yang ada, kamu dapat membaca Petunjuk Administrasi.
Untuk informasi lebih lanjut, kamu dapat membaca Bagaimana Cara Mengatur Heketi.
Ketika PersistentVolume di-provisioning secara dinamis, plugin Gluster secara otomatis akan membuat endpoint serta sebuah servis headless dengan nama
gluster-dynamic-<claimname>
. Endpoint dinamis dan servis secara otomatis akan dihapus ketika PVC dihapus. -
OpenStack Cinder
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gold
provisioner: kubernetes.io/cinder
parameters:
availability: nova
availability
: Zona Availability. Jika tidak dispesifikasikan, secara umum volume akan diatur dengan menggunakan algoritma round-robin pada semua zona aktif dimana klaster Kubernetes memiliki sebuah node.
Kubernetes 1.11 [deprecated]
Provisioner internal OpenStack ini sudah deprecated. Kamu dapat menggunakan provider eksternal penyedia layanan cloud untuk OpenStack.
vSphere
-
Buatlah sebuah StorageClass dengan menggunakan sebuah format disk yang dispesifikasikan oleh pengguna.
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/vsphere-volume parameters: diskformat: zeroedthick
diskformat
:thin
,zeroedthick
daneagerzeroedthick
. Nilai default:"thin"
. -
Buatlah sebuah StorageClass dengan menggunakan sebuah format disk pada datastore yang dispesifikasikan oleh pengguna.
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/vsphere-volume parameters: diskformat: zeroedthick datastore: VSANDatastore
datastore
: Pengguna juga dapat menspesifikasikan datastore pada StorageClass. Volume akan dibuat pada datastore yang dispesifikasikan pada kelas penyimpanan, dalam hal ini adalahVSANDatastore
. Field ini bersifat opsional. Jika datastore tidak dispesifikasikan, maka volume akan dibuat dengan menggunakan datastore yang dispesifikasikan pada berkas konfigurasi vSphere yang digunakan untuk menginisialisasi penyedia layanan cloud vSphere. -
Manajemen Kebijakan Penyimpanan di dalam Kubernetes
-
Menggunakan kebijakan (policy) yang ada pada vCenter
Salah satu dari fitur paling penting yang ada pada vSphere untuk manajemen penyimpanan adalah manajemen bebasis policy. Storage Policy Based Management (SPBM) adalah framework yang menyediakan sebuah control plane terpadu pada data service yang meluas dan solusi penyimpanannya yang tersedia. SPBM memungkinkan administrator vSphere menghadapi permasalahan yang mungkin muncul seperti capacity planning, membedakan level servis, dan melakukan manajemen headroom capacity.
Policy SPBM dapat dispesifikasikan pada StorageClass menggunakan parameter
storagePolicyName
. -
Dukungan policy SAN virtual di dalam Kubernetes
Administrator Vsphere Infrastructure (VI) akan memiliki kemampuan untuk menspesifikasikan Virtual SAN Storage Capabilities khusus selama masa provisioning volume secara dinamis. Persyaratan kapabilitas penyimpanan diubah menjadi sebuah policy Virtual SAN yang nantinya akan dimasukkan ke dalam lapisan Virtual SAN ketika sebuah persitent volume (penyimpanan virtual) dibuat. Penyimpanan virtual kemudian akan didistribusikan pada semua datastore Virtual SAN untuk memenuhi kebutuhan ini.
Kamu dapat melihat Policy Penyimpanan Berdasarkan Manajemen untuk Provisioning Dinamis Volume untuk detil lebih lanjut mengenai penggunaan policy penyimpanan untuk manajemen persistent volume.
-
Terdapat beberapa contoh vSphere yang dapat kamu gunakan untuk mencoba manajemen persistent volume di dalam Kubernetes untuk vSpehere.
RBD Ceph
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/rbd
parameters:
monitors: 10.16.153.105:6789
adminId: kube
adminSecretName: ceph-secret
adminSecretNamespace: kube-system
pool: kube
userId: kube
userSecretName: ceph-secret-user
userSecretNamespace: default
fsType: ext4
imageFormat: "2"
imageFeatures: "layering"
-
monitors
: Monitor Ceph, merupakan nilai yang dipisahkan oleh koma (csv). Parameter ini dibutuhkan. -
adminId
: ID klien Ceph yang dapat digunakan untuk membuat images di dalam pool. Nilai default-nya adalah "admin". -
adminSecretName
: Nama Secret untukadminId
. Parameter ini dibutuhkan. Secret yang dibutuhkan haruslah memiliki tipe "kubernetes.io/rbd". -
adminSecretNamespace
: Namespace untukadminSecretName
. Nilai default-nya adalah "default". -
pool
: Pool Ceph RBD. Nilai default-nya adalah "rbd". -
userId
: Klien ID Ceph yang digunakan untuk melakukan pemetaan image RBD. Nilai default-nya sama denganadminId
. -
userSecretName
: Nama Secret Ceph untukuserId
yang digunakan untuk memetakan image RBD. Secret ini harus berada pada namespace yang sama dengan PVC. Parameter ini dibutuhkan. Secret yang disediakan haruslah memiliki tipe "kubernetes.io/rbd", dibuat dengan cara:kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" \ --from-literal=key='QVFEQ1pMdFhPUnQrSmhBQUFYaERWNHJsZ3BsMmNjcDR6RFZST0E9PQ==' \ --namespace=kube-system
-
userSecretNamespace
: Namespace untukuserSecretName
. -
fsType
: fsType yang didukung oleh kubernetes. Nilai default-nya adalah:"ext4"
. -
imageFormat
: Format image Ceph RBD, nilai yang mungkin adalah "1" atau "2". Nilai default-nya adalah "2". -
imageFeatures
: Parameter ini bersifat opsional dan hanya dapat digunakan jika kamu mengganti nilai dariimageFormat
ke "2". Saat ini fitur yang didukung hanyalahlayering
. Nilai default-nya adalah "", dan tidak ada fitur yang diaktifkan.
Quobyte
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/quobyte
parameters:
quobyteAPIServer: "http://138.68.74.142:7860"
registry: "138.68.74.142:7861"
adminSecretName: "quobyte-admin-secret"
adminSecretNamespace: "kube-system"
user: "root"
group: "root"
quobyteConfig: "BASE"
quobyteTenant: "DEFAULT"
-
quobyteAPIServer
: API Server dari Quobyte dalam format"http(s)://api-server:7860"
-
registry
: Registri Quobyte yang digunakan untuk melakukan mount volume. Kamu dapat menspesifikasikan registri yang kamu inginkan dengan format pasangan<host>:<port>
atau jika kamu ingin mendefinisikan beberapa registri sekaligus kamu dapat menempatkan koma diantara setiap pasangan<host>:<port>
yang ada, misalnya<host1>:<port>,<host2>:<port>,<host3>:<port>
. Host dapat berupa alamat IP atau DNS. -
adminSecretNamespace
: NamespaceadminSecretName
. Nilai default-nya adalah "default". -
adminSecretName
: Secret yang mengandung informasi mengenai pengguna Quobyte dan password yang digunakan untuk melakukan otentikasi API server. Secret yang digunakan haruslah memiliki tipe "kubernetes.io/quobyte", yang dibuat dengan mekanisme berikut:kubectl create secret generic quobyte-admin-secret \ --type="kubernetes.io/quobyte" --from-literal=key='opensesame' \ --namespace=kube-system
-
user
: Melakukan pemetaan terhadap semua akses yang dimiliki pengguna. Nilai default-nya adalah "root". -
group
: Melakukan pemetaan terhadap semua group. Nilai default-nya adalah "nfsnobody". -
quobyteConfig
: Menggunakan konfigurasi spesifik untuk membuat volume. Kamu dapat membuat sebuah file konfigurasi atau melakukan modifikasi terhadap konfigurasi yang sudah ada dengan menggunakan tatap muka Web atau CLI quobyte. Nilai default-nya adalah "BASE". -
quobyteTenant
: Menggunakan ID tenant yang dispesifikasikan untuk membuat/menghapus volume. Tenant Quobyte haruslah sudah berada di dalam Quobyte. Nilai default-nya adalah "DEFAULT".
Azure Disk
Kelas Penyimpanan Disk Azure yang Tidak Dikelola
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/azure-disk
parameters:
skuName: Standard_LRS
location: eastus
storageAccount: azure_storage_account_name
skuName
: Akun penyimpanan Azure yang ada pada tingkatan Sku. Nilai default-nya adalah kosong.location
: Lokasi akun penyimpanan Azure. Nilai default-nya adalah kosong.storageAccount
: Nama akun penyimpanan Azure. Jika sebuan akun penyimpanan disediakan, akun tersebut haruslah berada pada grup sumber daya yang ada dengan klaster, danlocation
akan diabaikan. Jika sebuah akun penyimpanan tidak disediakan, sebuah akun penyimpanan baru akan dibuat pada grup sumber daya yang ada dengan klaster.
Kelas Penyimpanan Disk Azure yang Baru (mulai versi v1.7.2)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/azure-disk
parameters:
storageaccounttype: Standard_LRS
kind: managed
storageaccounttype
: Akun penyimpanan Azure yang ada pada tingkatan Sku. Nilai default-nya adalah kosong.kind
: Nilai yang mungkin adalahshared
,dedicated
, danmanaged
(default). Ketikakind
yang digunakan adalahshared
, semua disk yang tidak di-manage akan dibuat pada beberapa akun penyimpanan yang ada pada grup sumber daya yang sama dengan klaster. Ketikakind
yang digunakan adalahdedicated
, sebuah akun penyimpanan baru akan dibuat pada grup sumber daya yang ada dengan klaster. Ketikakind
yang digunakan adalahmanaged
, semua disk yang dikelola akan dibuat pada grup sumber daya yang ada dengan klaster.
- VM premium dapat di-attach baik pada Standard_LRS dan Premium_LRS disks, sementara Standard VM hanya dapat di-attach pada disk Standard_LRS.
- VM yang dikelola hanya dapat meng-attach disk yang dikelola dan VM yang tidak dikelola hanya dapat meng-attach disk yang tidak dikelola.
Berkas Azure
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azurefile
provisioner: kubernetes.io/azure-file
parameters:
skuName: Standard_LRS
location: eastus
storageAccount: azure_storage_account_name
skuName
: Akun penyimpanan Azure yang ada pada tingkatan Sku. Nilai default-nya adalah kosong.location
: Lokasi akun penyimpanan Azure. Nilai default-nya adalah kosong.storageAccount
: Nama akun penyimpanan Azure. Nilai default-nya adalah kosong. Jika sebuah penyimpanan tidak memiliki sebuah akun yang disediakan, semua akun penyimpanan yang diasosiasikan dengan grup sumber daya yang ada dan kemudian melakukan pencarian terhadap akun yang sesuai denganskuName
danlocation
. Jika sebuah akun penyimpanan disediakan, akun tersebut haruslah berada di dalam grup sumber daya yang sama dengan klaster, sertaskuName
danlocation
akan diabaikan.
Selama provision, sebuah secret dibuat untuk menyimpan credentials. Jika klaster
menggunakan konsep RBAC dan
Roles Controller,
menambahkan kapabilitas create
untuk sumber daya secret
bagi clusterrole
system:controller:persistent-volume-binder
.
Volume Portworx
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: portworx-io-priority-high
provisioner: kubernetes.io/portworx-volume
parameters:
repl: "1"
snap_interval: "70"
io_priority: "high"
fs
: filesystem yang akan digunakan:none/xfs/ext4
(nilai default-nya:ext4
).block_size
: ukuran block dalam Kbytes (nilai default-nya:32
).repl
: jumlah replika synchronous yang dapat disediakan dalam bentuk faktor replikasi1..3
(nilai default-nya:1
) Nilai yang diharapkan dalam bentuk String"1"
dan bukan1
.io_priority
: menentukan apakah volume yang dibuat akan dari penyimpanan dengan kualitas tinggi atau rendah dengan urutan prioritashigh/medium/low
(nilai default-nya:low
).snap_interval
: interval waktu dalam menit yang digunakan untuk melakukan trigger snapshots. Snapshots dibuat secara inkremen berdasarkan perbedaan yang ada dengan snapshot yang dibuat sebelumnya, nilai perbedaan 0 akan menonaktifkan pembuatan snapshot (nilai default-nya:0
). Sebuah string merupakan nilai yang diharapkan"70"
dan bukan70
.aggregation_level
: menspesifikasikan jumlah chunks dimana volume akan didistribusikan, 0 mengindikasikan volume yang non-aggregate (nilai default-nya:0
). Sebuah string merupakan nilai yang diharapkan"0"
dan bukan0
.ephemeral
: menentukan apakah volume harus dihapus setelah di-unmount atau harus tetap ada. PenggunaanemptyDir
dapat diubah menjadi true dan penggunaanpersistent volumes
untuk basisdata seperti Cassandra harus diubah menjadi false, true/false
(nilai default-nya:false
). Sebuah string merupakan nilai yang diharapkan"true"
dan bukantrue
.
ScaleIO
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/scaleio
parameters:
gateway: https://192.168.99.200:443/api
system: scaleio
protectionDomain: pd0
storagePool: sp1
storageMode: ThinProvisioned
secretRef: sio-secret
readOnly: false
fsType: xfs
provisioner
: atribut yang nilainya merupakankubernetes.io/scaleio
gateway
: alamat gateway ScaleIO (wajib)system
: nama sistem ScaleIO (wajib)protectionDomain
: nama domain proteksi ScaleIO (wajib)storagePool
: nama pool volume penyimpanan (wajib)storageMode
: mode provisioning penyimpanan:ThinProvisioned
(default) atauThickProvisioned
secretRef
: penunjuk pada objek Secret yang dikonfigurasi (wajib)readOnly
: menentukan mode akses terhadap volume yang di-mount (nilai default-nya: false)fsType
: filesystem yang digunakan untuk volume (nilai default-nya: ext4)
Plugin volume ScaleIO Kubernetes membutuhkan objek Secret yang suda dikonfigurasi sebelumnya.
Secret ini harus dibuat dengan tipe kubernetes.io/scaleio
dan menggunakan namespace yang sama
dengan PVC yang dirujuk, seperti ditunjukkan pada contoh yang ada:
kubectl create secret generic sio-secret --type="kubernetes.io/scaleio" \
--from-literal=username=sioadmin --from-literal=password=d2NABDNjMA== \
--namespace=default
StorageOS
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/storageos
parameters:
pool: default
description: Kubernetes volume
fsType: ext4
adminSecretNamespace: default
adminSecretName: storageos-secret
pool
: Nama kapasitas distribusi StorageOS yang digunakan untuk melakukan provisioning volume. Pool default akan digunakan apabila nilainya tidak dispesifikasikan.description
: Deskripsi untuk melakukan assignment volume yang baru dibuat secara dinamis. Semua deskripsi volume akan bernilai sama untuk kelas penyimpanan yang sama, meskipun begitu kelas penyimpanan yang berbeda dapat digunakan untuk membuat deskripsi yang berbeda untuk penggunaan yang berbeda. Nilai default-nya adalahKubernetes volume
.fsType
: Tipe filesystem default yang digunakan. Perhatikan bahwa aturan yang didefinisikan oleh pengguna di dalam StirageOS dapat meng-override nilai ini. Nilai default-nya adalahext4
.adminSecretNamespace
: Namespace dimana konfigurasi secret API berada. Hal ini bersifat wajib apabila adminSecretName diaktifkan.adminSecretName
: Nama secret yang digunakan untuk memperoleh credentials StorageOS API. Jika tidak dispesifikasikan, nilaidefault akan digunakan.
Plugin volume dapat menggunakan objek Secret untuk menspesifikasikan
endpoint dan kredensial yang digunakan untuk mengakses API StorageOS.
Hal ini hanya akan dibutuhkan apabila terdapat perubahan pada nilai default.
Secret ini harus dibuat dengan tipe kubernetes.io/storageos
,
seperti ditunjukkan pada contoh yang ada:
kubectl create secret generic storageos-secret \
--type="kubernetes.io/storageos" \
--from-literal=apiAddress=tcp://localhost:5705 \
--from-literal=apiUsername=storageos \
--from-literal=apiPassword=storageos \
--namespace=default
Secret yang digunakan untuk melakukan provisioning volume secara dinamis
dapat dibuat di namespace apapun dan dirujuk dengan menggunakan parameter adminSecretNamespace
.
Secret yang digunakan oleh volume yang sedang di-provisioning harus dibuat pada namespace yang sama
dengan PVC yang merujuk secret tersebut.
Lokal
Kubernetes v1.14 [stable]
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
Volume lokal tidak mendukung adanya provisioning secara dinamis,
meskipun begitu sebuah StorageClass akan tetap dibuat untuk mencegah terjadinya bind volume
sampai scheduling pod dilakukan. Hal ini dispesifikasikan oleh mode binding volume
WaitForFirstConsumer
.
Memperlambat binding volume mengizinkan scheduler untuk memastikan batasan scheduling semua pod ketika memilih PersistentVolume untuk sebuah PersistentVolumeClaim.
3.6.6 - VolumeSnapshotClass
Laman ini menjelaskan tentang konsep VolumeSnapshotClass pada Kubernetes. Sebelum melanjutkan, sangat disarankan untuk membaca snapshot volume dan kelas penyimpanan (storage class) terlebih dahulu.
Pengenalan
Seperti halnya StorageClass yang menyediakan cara bagi admin untuk mendefinisikan "kelas" penyimpanan yang mereka tawarkan saat proses penyediaan sebuah volume, VolumeSnapshotClass menyediakan cara untuk mendefinisikan "kelas" penyimpanan saat menyediakan snapshot volume.
Sumber Daya VolumeSnapshotClass
Masing-masing VolumeSnapshotClass terdiri dari field snapshotter
dan parameters
,
yang digunakan saat sebuah VolumeSnapshot yang dimiliki kelas tersebut perlu untuk
disediakan secara dinamis.
Nama yang dimiliki suatu objek VolumeSnapshotClass sangatlah penting, karena digunakan oleh pengguna saat meminta sebuah kelas tertentu. Admin dapat mengatur nama dan parameter lainnya dari sebuah kelas saat pertama kali membuat objek VolumeSnapshotClass. Objek tidak dapat diubah setelah dibuat.
Admin dapat mengatur VolumeSnapshotClass default untuk VolumeSnapshot yang tidak memiliki spesifikasi kelas apapun.
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotClass
metadata:
name: csi-hostpath-snapclass
snapshotter: csi-hostpath
parameters:
snapshotter
VolumeSnapshotClass memiliki sebuah snapshotter
yang menentukan plugin volume CSI
apa yang digunakan untuk penyediaan VolumeSnapshot. Field ini wajib diatur.
parameters
VolumeSnapshotClass memiliki parameter-parameter yang menggambarkan snapshot volume
di dalam VolumeSnapshotClass. Parameter-parameter yang berbeda diperbolehkan tergantung
dari shapshotter
.
3.6.7 - Penyediaan Volume Dinamis
Penyediaan volume dinamis memungkinkan volume penyimpanan untuk dibuat sesuai permintaan (on-demand). Tanpa adanya penyediaan dinamis (dynamic provisioning), untuk membuat volume penyimpanan baru, admin klaster secara manual harus memanggil penyedia layanan cloud atau layanan penyimpanan, dan kemudian membuat objek PersistentVolume sebagai representasi di Kubernetes. Fitur penyediaan dinamis menghilangkan kebutuhan admin klaster untuk menyediakan penyimpanan sebelumnya (pre-provision). Dengan demikian, penyimpanan akan tersedia secara otomatis ketika diminta oleh pengguna.
Latar Belakang
Penyediaan volume dinamis diimplementasi berdasarkan objek API StorageClass dari
grup API storage.k8s.io
. Seorang admin klaster dapat mendefinisikan berbagai macam
objek StorageClass sesuai kebutuhan, masing-masing menentukan plugin volume (disebut
juga provisioner) yang menyediakan sebuah volume beserta kumpulan parameter untuk
diteruskan oleh provisioner ketika proses penyediaan.
Seorang klaster admin dapat mendefinisikan dan mengekspos berbagai templat penyimpanan (dari sistem penyimpanan yang sama maupun berbeda) di dalam klaster, masing-masing dengan kumpulan parameter tertentu. Desain ini memastikan bahwa pengguna tidak perlu khawatir betapa rumitnya mekanisme penyediaan penyimpanan, tapi tetap memiliki kemampuan untuk memilih berbagai macam pilihan penyimpanan.
Info lebih lanjut mengenai storage class dapat dilihat di sini.
Mengaktifkan Penyediaan Dinamis (Dynamic Provisioning)
Untuk mengaktifkan penyediaan dinamis, seorang admin klaster perlu untuk terlebih dahulu membuat (pre-create) satu atau beberapa objek StorageClass untuk pengguna. Objek StorageClass mendefinisikan provisioner mana yang seharusnya digunakan dan parameter apa yang seharusnya diberikan pada provisioner tersebut saat penyediaan dinamis dipanggil. Manifestasi berikut ini membuat sebuah StorageClass "slow" yang menyediakan persistent disk standar.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
Manifestasi berikut ini membuat sebuah StorageClass "fast" yang menyediakan SSD persistent disk.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
Menggunakan Penyediaan Dinamis
Pengguna dapat melakukan permintaan untuk penyediaan penyimpanan dinamis dengan
memasukkan StorageClass di dalam PersistentVolumeClaim. Sebelum Kubernetes v1.6,
ini dapat dilakukan melalui anotasi volume.beta.kubernetes.io/storage-class
.
Hanya saja, anotasi ini sudah usang sejak v1.6. Pengguna sekarang dapat dan seharusnya
menggunakan field storageClassName
dari objek PersistentVolumeClaim. Nilai
dari field ini haruslah sesuai dengan nama StorageClass yang dikonfigurasi oleh
admin (lihat bagian di bawah).
Untuk memilih StorageClass "fast", sebagai contoh, pengguna dapat membuat PersistentVolumeClaim seperti ini:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: claim1
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast
resources:
requests:
storage: 30Gi
Klaim ini menghasilkan persistent disk SSD yang disediakan secara otomatis. Ketika klaim dihilangkan, volume akan musnah.
Perilaku Default
Penyediaan dinamis dapat diaktifkan pada setiap klaster supaya semua klaim dapat disediakan secara dinamis jika tidak ada StorageClass yang dispesifikasikan. Seorang klaster admin dapat mengaktifkan perilaku ini dengan cara:
- Menandai satu objek StorageClass sebagai default;
- Memastikan bahwa admission controller
DefaultStorageClass
telah aktif pada API server.
Seorang admin dapat menandai StorageClass yang spesifik sebagai default dengan menambahkan
anotasi storageclass.kubernetes.io/is-default-class
.
Ketika StorageClass default tersebut ada pada klaster dan pengguna membuat PersistentVolumeClaim
tanpa menspesifikasikan storageClassName
, admission controller DefaultStorageClass
secara
otomatis menambahkan field storageClassName
dengan StorageClass default.
Perhatikan bahwa hanya bisa ada satu default StorageClass pada sebuah klaster,
atau PersistentVolumeClaim tanpa menspesifikasikan storageClassName
secara eksplisit
tidak bisa terbuat.
Kesadaran (Awareness) Topologi
Pada klaster Multi-Zona, Pod dapat tersebar di banyak Zona pada sebuah Region. Penyimpanan dengan backend Zona-Tunggal seharusnya disediakan pada Zona-Zona dimana Pod dijalankan. Hal ini dapat dicapai dengan mengatur Mode Volume Binding.
3.6.8 - Limit Volume yang Spesifik terhadap Node
Laman ini menjelaskan soal jumlah volume maksimal yang dapat dihubungkan ke sebuah Node untuk berbagai penyedia layanan cloud.
Penyedia layanan cloud seperti Google, Amazon, dan Microsoft pada umumnya memiliki keterbatasan dalam jumlah volume yang bisa terhubung ke sebuah Node. Keterbatasn ini sangatlah penting untuk diketahui Kubernetes dalam menentukan keputusan. Jika tidak, Pod-pod yang telah dijadwalkan pada sebuah Node akan macet dan menunggu terus-menerus untuk terhubung pada volume.
Limit default pada Kubernetes
Kubernetes scheduler memiliki limit default untuk jumlah volume yang dapat terhubung pada sebuah Node:
Penyedia layanan cloud | Jumlah volume maksimal per Node |
---|---|
Amazon Elastic Block Store (EBS) | 39 |
Google Persistent Disk | 16 |
Microsoft Azure Disk Storage | 16 |
Limit custom
Kamu dapat mengganti limit-limit ini dengan mengkonfigurasi nilai dari
variabel environment KUBE_MAX_PD_VOLS
, lalu menjalankan scheduler.
Berhati-hatilah jika kamu menerapkan limit yang lebih besar dari limit default. Perhatikan dokumentasi penyedia layanan cloud untuk hal ini, dan pastikan Node benar-benar dapat mendukung nilai limit yang kamu inginkan.
Limit ini diterapkan untuk seluruh klaster, jadi akan berdampak pada semua Node.
Limit volume dinamis
Kubernetes v1.12 [beta]
Sebagai fitur Alpha, Kubernetes 1.11 memperkenalkan dukungan untuk limit volume yang dinamis berdasarkan tipe Node. Pada Kubernettes 1.12, fitur ini telah mendapat promosi ke Beta dan akan diaktifkan secara default.
Limit volume dinamis mendukung tipe-tipe volume berikut:
- Amazon EBS
- Google Persistent Disk
- Azure Disk
- CSI
Ketika fitur limit volume dinamis diaktifkan, Kubernetes secara otomatis menentukan tipe Node dan menerapkan jumlah volume dengan tepat, berapa yang bisa terhubung Node. Sebagai contoh:
-
Pada Google Compute Engine, maskimal 128 jumlah volumes dapat terhubung pada sebuah node, tergantung dari tipe node.
-
Untuk Amazon EBS disk pada tipe instans M5,C5,R5,T3 dan Z1D, Kubernetes hanya memperbolehkan 25 volume dapat terhubung pada sebuah Node. Untuk tipe instans lainnya pada Amazon Elastic Compute Cloud (EC2), Kubernetes memperbolehkan 39 jumlah volume dapat terhubung pada sebuah Node.
-
Pada Azure, maksimal 64 jumlah disk dapat terhubung pada suatu node, tergantung dari tipe node. Untuk perinciannya bisa dilihat pada Ukuran mesin virtual (VM) di Azure.
-
Untuk CSI, driver manapun yang memberitahukan (advertise) limit volume terhubung melalui spek CSI akan memiliki limit tersebut yang disediakan sebagai properti Node dan Scheduler tidak akan menjadwalkan Pod dengan volume pada Node manapun yang sudah penuh kapasitasnya. Untuk penjelasan lebih jauh lihat spek CSI.
3.7 - Konfigurasi
3.7.1 - Konfigurasi dan Penerapan Konsep
Dokumen ini menyoroti dan memperkuat pemahaman konsep konfigurasi yang dikenalkan di seluruh panduan pengguna, dokumentasi Memulai, dan contoh-contoh.
Dokumentasi ini terbuka. Jika Anda menemukan sesuatu yang tidak ada dalam daftar ini tetapi mungkin bermanfaat bagi orang lain, jangan ragu untuk mengajukan issue atau mengirimkan PR.
Tip konfigurasi secara umum
-
Saat mendefinisikan konfigurasi, tentukan versi API stabil terbaru.
-
File konfigurasi harus disimpan dalam version control sebelum di push ke cluster. Ini memungkinkan Anda untuk dengan cepat mengembalikan perubahan konfigurasi jika perlu. Ini juga membantu penciptaan dan restorasi cluster.
-
Tulis file konfigurasi Anda menggunakan YAML tidak dengan JSON. Meskipun format ini dapat digunakan secara bergantian di hampir semua skenario, YAML cenderung lebih ramah pengguna.
-
Kelompokkan objek terkait ke dalam satu file yang memungkinkan. Satu file seringkali lebih mudah dikelola daripada beberapa file. Lihat pada guestbook-all-in-one.yaml sebagai contoh file sintaks ini.
-
Perhatikan juga bahwa banyak perintah
kubectl
dapat dipanggil pada direktori. Misalnya, Anda dapat memanggilkubectl apply
pada direktori file konfigurasi. -
Jangan tentukan nilai default yang tidak perlu: sederhana, konfigurasi minimal akan membuat kesalahan lebih kecil.
-
Masukkan deskripsi objek dalam anotasi, untuk memungkinkan introspeksi yang lebih baik.
"Naked" Pods vs ReplicaSets, Deployments, and Jobs
-
Jangan gunakan Pods naked (artinya, Pods tidak terikat dengan a ReplicaSet a Deployment) jika kamu bisa menghindarinya. Pod naked tidak akan dijadwal ulang jika terjadi kegagalan pada node.
Deployment, yang keduanya menciptakan ReplicaSet untuk memastikan bahwa jumlah Pod yang diinginkan selalu tersedia, dan menentukan strategi untuk mengganti Pods (seperti RollingUpdate), hampir selalu lebih disukai daripada membuat Pods secara langsung, kecuali untuk beberapa yang eksplisit
restartPolicy: Never
banyak skenario . A Job mungkin juga sesuai.
Services
-
Buat Service sebelum workloads backend terkait (Penyebaran atau ReplicaSets), dan sebelum workloads apa pun yang perlu mengaksesnya. Ketika Kubernetes memulai sebuah container, ia menyediakan environment variabel yang menunjuk ke semua Layanan yang berjalan ketika container itu dimulai. Misalnya, jika Layanan bernama
foo
ada, semua container akan mendapatkan variabel berikut di environment awalnya:FOO_SERVICE_HOST=<the host the Service is running on> FOO_SERVICE_PORT=<the port the Service is running on>
*Ini menunjukan persyaratan pemesanan * -
Service
apa pun yang ingin diakses olehPod
harus dibuat sebelumPod
itu sendiri, atau environment variabel tidak akan diisi. DNS tidak memiliki batasan ini. -
Opsional (meskipun sangat disarankan) cluster add-on adalah server DNS. Server DNS melihat API Kubernetes untuk
Service
baru dan membuat satu set catatan DNS untuk masing-masing. Jika DNS telah diaktifkan di seluruh cluster maka semuaPods
harus dapat melakukan resolusi namaService
secara otomatis. -
Jangan tentukan
hostPort
untuk Pod kecuali jika benar-benar diperlukan. Ketika Anda bind Pod kehostPort
, hal itu membatasi jumlah tempat Pod dapat dijadwalkan, karena setiap kombinasi <hostIP
,hostPort
,protokol
> harus unik. Jika Anda tidak menentukanhostIP
danprotokol
secara eksplisit, Kubernetes akan menggunakan0.0.0.0
sebagaihostIP
danTCP
sebagai defaultprotokol
.Jika kamu hanya perlu akses ke port untuk keperluan debugging, Anda bisa menggunakan apiserver proxy atau
kubectl port-forward
.Jika Anda secara eksplisit perlu mengekspos port Pod pada node, pertimbangkan untuk menggunakan NodePort Service sebelum beralih ke
hostPort
. -
Hindari menggunakan
hostNetwork
, untuk alasan yang sama sepertihostPort
. -
Gunakan [headless Services](/id/docs/concepts/services-networking/service/#headless- services) (yang memiliki
ClusterIP
dariNone
) untuk Service discovery yang mudah ketika Anda tidak membutuhkankube-proxy
load balancing.
Menggunakan label
- Deklarasi dan gunakan [labels] (/id/docs/concepts/overview/working-with-objects/labels/) untuk identifikasi semantic attributes aplikasi atau Deployment kamu, seperti
{ app: myapp, tier: frontend, phase: test, deployment: v3 }
. Kamu dapat menggunakan label ini untuk memilih Pod yang sesuai untuk sumber daya lainnya; misalnya, Service yang memilih semuatier: frontend
Pods, atau semua komponenphase: test
dariapp: myapp
. Lihat guestbook aplikasi untuk contoh-contoh pendekatan ini.
Service dapat dibuat untuk menjangkau beberapa Penyebaran dengan menghilangkan label khusus rilis dari pemilihnya. Deployments membuatnya mudah untuk memperbarui Service yang sedang berjalan tanpa downtime.
Keadaan objek yang diinginkan dideskripsikan oleh Deployment, dan jika perubahan terhadap spesifikasi tersebut adalah applied, Deployment controller mengubah keadaan aktual ke keadaan yang diinginkan pada tingkat yang terkontrol.
- Kamu dapat memanipulasi label untuk debugging. Karena Kubernetes controller (seperti ReplicaSet) dan Service Match dengan Pods menggunakan label pemilih, menghapus label yang relevan dari Pod akan menghentikannya dari dianggap oleh Controller atau dari lalu lintas yang dilayani oleh Service. Jika Anda menghapus label dari Pod yang ada, Controller akan membuat Pod baru untuk menggantikannya. Ini adalah cara yang berguna untuk men-debug Pod yang sebelumnya "live" di Environment "quarantine". Untuk menghapus atau menambahkan label secara interaktif, gunakan
kubectl label
.
Container Images
Ini imagePullPolicy dan tag dari image mempengaruhi ketika kubelet mencoba menarik image yang ditentukan
-
imagePullPolicy: IfNotPresent
: image ditarik hanya jika belum ada secara lokal. -
imagePullPolicy: Always
: Image ditarik setiap kali pod dimulai. -
imagePullPolicy
dihilangkan dan tag imagenya adalah:latest
atau dihilangkan:always
diterapkan. -
imagePullPolicy
dihilangkan dan tag image ada tetapi tidak:latest
:IfNotPresent
diterapkan. -
imagePullPolicy: Never
: image diasumsikan ada secara lokal. Tidak ada upaya yang dilakukan untuk menarik image.
sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2
. digest mengidentifikasi secara unik versi image tertentu, sehingga tidak pernah diperbarui oleh Kubernetes kecuali Anda mengubah nilai digest.
: latest
saat menempatkan container dalam produksi karena lebih sulit untuk melacak versi image mana yang sedang berjalan dan lebih sulit untuk memutar kembali dengan benar.
imagePullPolicy: Always
efisien. Dengan Docker, misalnya, jika image sudah ada, upaya pull cepat karena semua lapisan image di-cache dan tidak perlu mengunduh image.
Menggunakan kubectl
-
Gunakan
kubectl apply -f <directory>
. Ini mencari konfigurasi Kubernetes di semua file.yaml
,.yml
, dan.json
di<directory>
dan meneruskannya keapply
. -
Gunakan label selector untuk operasi
get
dandelete
alih-alih nama objek tertentu. Lihat bagian di label selectors dan using labels effectively. -
Gunakan
kubectl run
dankubectl expose
untuk dengan cepat membuat Deployment dan Service single-container. Lihat Use a Service to Access an Application in a Cluster untuk Contoh.
3.7.2 - Mengatur Sumber Daya Komputasi untuk Container
Saat kamu membuat spesifikasi sebuah Pod, kamu
dapat secara opsional menentukan seberapa banyak CPU dan memori (RAM) yang dibutuhkan
oleh setiap Container. Saat Container-Container menentukan request (permintaan) sumber daya,
scheduler dapat membuat keputusan yang lebih baik mengenai Node mana yang akan dipilih
untuk menaruh Pod-Pod. Dan saat limit (batas) sumber daya Container-Container telah ditentukan,
maka kemungkinan rebutan sumber daya pada sebuah Node dapat dihindari.
Untuk informasi lebih lanjut mengenai perbedaan request
dan limit
, lihat QoS Sumber Daya.
Jenis-jenis sumber daya
CPU dan memori masing-masing merupakan jenis sumber daya (resource type). Sebuah jenis sumber daya memiliki satuan dasar. CPU ditentukan dalam satuan jumlah core, dan memori ditentukan dalam satuan bytes. Jika kamu menggunakan Kubernetes v1.14 keatas, kamu dapat menentukan sumber daya huge page. Huge page adalah fitur khusus Linux di mana kernel Node mengalokasikan blok-blok memori yang jauh lebih besar daripada ukuran page bawaannya.
Sebagai contoh, pada sebuah sistem di mana ukuran page bawaannya adalah 4KiB, kamu
dapat menentukan sebuah limit, hugepages-2Mi: 80Mi
. Jika kontainer mencoba mengalokasikan
lebih dari 40 huge page berukuran 20MiB (total 80MiB), maka alokasi tersebut akan gagal.
hugepages-*
.
Hal ini berbeda dari sumber daya memory
dan cpu
(yang dapat di-overcommit).
CPU dan memori secara kolektif disebut sebagai sumber daya komputasi, atau cukup sumber daya saja. Sumber daya komputasi adalah jumlah yang dapat diminta, dialokasikan, dan dikonsumsi. Mereka berbeda dengan sumber daya API. Sumber daya API, seperti Pod dan Service adalah objek-objek yang dapat dibaca dan diubah melalui Kubernetes API Server.
Request dan Limit Sumber daya dari Pod dan Container
Setiap Container dari sebuah Pod dapat menentukan satu atau lebih dari hal-hal berikut:
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.limits.hugepages-<size>
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
spec.containers[].resources.requests.hugepages-<size>
Walaupun requests
dan limits
hanya dapat ditentukan pada Container individual, akan
lebih mudah untuk membahas tentang request dan limit sumber daya dari Pod. Sebuah
request/limit sumber daya Pod untuk jenis sumber daya tertentu adalah jumlah dari
request/limit sumber daya pada jenis tersebut untuk semua Container di dalam Pod tersebut.
Arti dari CPU
Limit dan request untuk sumber daya CPU diukur dalam satuan cpu. Satu cpu, dalam Kubernetes, adalah sama dengan:
- 1 vCPU AWS
- 1 Core GCP
- 1 vCore Azure
- 1 vCPU IBM
- 1 Hyperthread pada sebuah prosesor Intel bare-metal dengan Hyperthreading
Request dalam bentuk pecahan diizinkan. Sebuah Container dengan
spec.containers[].resources.requests.cpu
bernilai 0.5
dijamin mendapat
setengah CPU dibandingkan dengan yang meminta 1 CPU. Ekspresi nilai 0.1
ekuivalen
dengan ekspresi nilai 100m
, yang dapat dibaca sebagai "seratus milicpu". Beberapa
orang juga membacanya dengan "seratus milicore", dan keduanya ini dimengerti sebagai
hal yang sama. Sebuah request dengan angka di belakang koma, seperti 0.1
dikonversi
menjadi 100m
oleh API, dan presisi yang lebih kecil lagi dari 1m
tidak dibolehkan.
Untuk alasan ini, bentuk 100m
mungkin lebih disukai.
CPU juga selalu diminta dalam jumlah yang mutlak, tidak sebagai jumlah yang relatif; 0.1 adalah jumlah CPU yang sama pada sebuah mesin single-core, dual-core, atau 48-core.
Arti dari Memori
Limit dan request untuk memory
diukur dalam satuan bytes. Kamu dapat mengekspresikan
memori sebagai plain integer atau sebagai sebuah fixed-point integer menggunakan
satu dari sufiks-sufiks berikut: E, P, T, G, M, K. Kamu juga dapat menggunakan bentuk
pangkat dua ekuivalennya: Ei, Pi, Ti, Gi, Mi, Ki.
Sebagai contoh, nilai-nilai berikut kurang lebih sama:
128974848, 129e6, 129M, 123Mi
Berikut sebuah contoh. Pod berikut memiliki dua Container. Setiap Container memiliki request 0.25 cpu dan 64MiB (226 bytes) memori. Setiap Container memiliki limit 0.5 cpu dan 128MiB memori. Kamu dapat berkata bahwa Pod tersebut memiliki request 0.5 cpu dan 128MiB memori, dan memiliki limit 1 cpu dan 265MiB memori.
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: db
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: wp
image: wordpress
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Bagaimana Pod-Pod dengan request sumber daya dijadwalkan
Saat kamu membuat sebuah Pod, Kubernetes scheduler akan memilih sebuah Node untuk Pod tersebut untuk dijalankan. Setiap Node memiliki kapasitas maksimum untuk setiap jenis sumber daya: jumlah CPU dan memori yang dapat disediakan oleh Node tersebut untuk Pod-Pod. Scheduler memastikan bahwa, untuk setiap jenis sumber daya, jumlah semua request sumber daya dari Container-Container yang dijadwalkan lebih kecil dari kapasitas Node tersebut. Perlu dicatat bahwa walaupun penggunaan sumber daya memori atau CPU aktual/sesungguhnya pada Node-Node sangat rendah, scheduler tetap akan menolak untuk menaruh sebuah Pod pada sebuah Node jika pemeriksaan kapasitasnya gagal. Hal ini adalah untuk menjaga dari kekurangan sumber daya pada sebuah Node saat penggunaan sumber daya meningkat suatu waktu, misalnya pada saat titik puncak traffic harian.
Bagaimana Pod-Pod dengan limit sumber daya dijalankan
Saat Kubelet menjalankan sebuah Container dari sebuah Pod, Kubelet tersebut mengoper limit CPU dan memori ke runtime kontainer.
Ketika menggunakan Docker:
-
spec.containers[].resources.requests.cpu
diubah menjadi nilai core-nya, yang mungkin berbentuk angka pecahan, dan dikalikan dengan 1024. Nilai yang lebih besar antara angka ini atau 2 digunakan sebagai nilai dari flag--cpu-shares
pada perintahdocker run
. -
spec.containers[].resources.limits.cpu
diubah menjadi nilai millicore-nya dan dikalikan dengan 100. Nilai hasilnya adalah jumlah waktu CPU yang dapat digunakan oleh sebuah kontainer setiap 100 milidetik. Sebuah kontainer tidak dapat menggunakan lebih dari jatah waktu CPU-nya selama selang waktu ini.Catatan: Periode kuota bawaan adalah 100ms. Resolusi minimum dari kuota CPU adalah 1 milidetik. -
spec.containers[].resources.limits.memory
diubah menjadi sebuah bilangan bulat, dan digunakan sebagai nilai dari flag--memory
dari perintahdocker run
.
Jika sebuah Container melebihi batas memorinya, Container tersebut mungkin akan diterminasi. Jika Container tersebut dapat diulang kembali, Kubelet akan mengulangnya kembali, sama seperti jenis kegagalan lainnya.
Jika sebuah Container melebihi request memorinya, kemungkinan Pod-nya akan dipindahkan kapanpun Node tersebut kehabisan memori.
Sebuah Container mungkin atau mungkin tidak diizinkan untuk melebihi limit CPU-nya untuk periode waktu yang lama. Tetapi, Container tersebut tidak akan diterminasi karena penggunaan CPU yang berlebihan.
Untuk menentukan apabila sebuah Container tidak dapat dijadwalkan atau sedang diterminasi karena limit sumber dayanya, lihat bagian Penyelesaian Masalah.
Memantau penggunaan sumber daya komputasi
Penggunaan sumber daya dari sebuah Pod dilaporkan sebagai bagian dari kondisi Pod.
Jika monitoring opsional diaktifkan pada klaster kamu, maka penggunaan sumber daya Pod dapat diambil dari sistem monitoring kamu.
Penyelesaian Masalah
Pod-Pod saya berkondisi Pending (tertunda) dengan event message failedScheduling
Jika scheduler tidak dapat menemukan Node manapun yang muat untuk sebuah Pod, Pod tersebut tidak akan dijadwalkan hingga ditemukannya sebuah tempat yang muat. Sebuah event akan muncul setiap kali scheduler gagal menemukan tempat untuk Pod tersebut, seperti berikut:
kubectl describe pod frontend | grep -A 3 Events
Events:
FirstSeen LastSeen Count From Subobject PathReason Message
36s 5s 6 {scheduler } FailedScheduling Failed for reason PodExceedsFreeCPU and possibly others
Pada contoh di atas, Pod bernama "frontend" gagal dijadwalkan karena kekurangan sumber daya CPU pada Node tersebut. Pesan kesalahan yang serupa dapat juga menunjukkan kegagalan karena kekurangan memori (PodExceedsFreeMemroy). Secara umum, jika sebuah Pod berkondisi Pending (tertunda) dengan sebuah pesan seperti ini, ada beberapa hal yang dapat dicoba:
- Tambah lebih banyak Node pada klaster.
- Terminasi Pod-Pod yang tidak dibutuhkan untuk memberikan ruangan untuk Pod-Pod yang tertunda.
- Periksa jika nilai request Pod tersebut tidak lebih besar dari Node-node yang ada.
Contohnya, jika semua Node memiliki kapasitas
cpu: 1
, maka Pod dengan requestcpu: 1.1
tidak akan pernah dijadwalkan.
Kamu dapat memeriksa kapasitas Node-Node dan jumlah-jumlah yang telah dialokasikan
dengan perintah kubectl describe nodes
. Contohnya:
kubectl describe nodes e2e-test-node-pool-4lw4
Name: e2e-test-node-pool-4lw4
[ ... lines removed for clarity ...]
Capacity:
cpu: 2
memory: 7679792Ki
pods: 110
Allocatable:
cpu: 1800m
memory: 7474992Ki
pods: 110
[ ... beberapa baris dihapus untuk kejelasan ...]
Non-terminated Pods: (5 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
kube-system fluentd-gcp-v1.38-28bv1 100m (5%) 0 (0%) 200Mi (2%) 200Mi (2%)
kube-system kube-dns-3297075139-61lj3 260m (13%) 0 (0%) 100Mi (1%) 170Mi (2%)
kube-system kube-proxy-e2e-test-... 100m (5%) 0 (0%) 0 (0%) 0 (0%)
kube-system monitoring-influxdb-grafana-v4-z1m12 200m (10%) 200m (10%) 600Mi (8%) 600Mi (8%)
kube-system node-problem-detector-v0.1-fj7m3 20m (1%) 200m (10%) 20Mi (0%) 100Mi (1%)
Allocated resources:
(Total limit mungkin melebihi 100 persen, misalnya, karena _overcommit_.)
CPU Requests CPU Limits Memory Requests Memory Limits
------------ ---------- --------------- -------------
680m (34%) 400m (20%) 920Mi (12%) 1070Mi (14%)
Pada keluaran di atas, kamu dapat melihat bahwa jika sebuah Pod meminta lebih dari 1120m CPU atau 6.23Gi memori, Pod tersebut tidak akan muat pada Node tersebut.
Dengan melihat pada bagian Pods
, kamu dapat melihat Pod-Pod mana saja yang memakan
sumber daya pada Node tersebut.
Jumlah sumber daya yang tersedia untuk Pod-Pod kurang dari kapasitas Node, karena
daemon sistem menggunakan sebagian dari sumber daya yang ada. Kolom allocatable
pada
NodeStatus
memberikan jumlah sumber daya yang tersedia untuk Pod-Pod. Untuk lebih lanjut, lihat
Sumber daya Node yang dapat dialokasikan.
Fitur kuota sumber daya dapat disetel untuk membatasi jumlah sumber daya yang dapat digunakan. Jika dipakai bersama dengan Namespace, kuota sumber daya dapat mencegah suatu tim menghabiskan semua sumber daya.
Container saya diterminasi
Container kamu mungkin diterminasi karena Container tersebut melebihi batasnya. Untuk
memeriksa jika sebuah Container diterminasi karena ia melebihi batas sumber dayanya,
gunakan perintah kubectl describe pod
pada Pod yang bersangkutan:
kubectl describe pod simmemleak-hra99
Name: simmemleak-hra99
Namespace: default
Image(s): saadali/simmemleak
Node: kubernetes-node-tf0f/10.240.216.66
Labels: name=simmemleak
Status: Running
Reason:
Message:
IP: 10.244.2.75
Replication Controllers: simmemleak (1/1 replicas created)
Containers:
simmemleak:
Image: saadali/simmemleak
Limits:
cpu: 100m
memory: 50Mi
State: Running
Started: Tue, 07 Jul 2015 12:54:41 -0700
Last Termination State: Terminated
Exit Code: 1
Started: Fri, 07 Jul 2015 12:54:30 -0700
Finished: Fri, 07 Jul 2015 12:54:33 -0700
Ready: False
Restart Count: 5
Conditions:
Type Status
Ready False
Events:
FirstSeen LastSeen Count From SubobjectPath Reason Message
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {scheduler } scheduled Successfully assigned simmemleak-hra99 to kubernetes-node-tf0f
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} implicitly required container POD pulled Pod container image "k8s.gcr.io/pause:0.8.0" already present on machine
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} implicitly required container POD created Created with docker id 6a41280f516d
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} implicitly required container POD started Started with docker id 6a41280f516d
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} spec.containers{simmemleak} created Created with docker id 87348f12526a
Pada contoh di atas, Restart Count: 5
menunjukkan bahwa Container simmemleak
pada Pod tersebut diterminasi dan diulang kembali sebanyak lima kali.
Kamu dapat menggunakan perintah kubectl get pod
dengan opsi -o go-template=...
untuk
mengambil kondisi dari Container-Container yang sebelumnya diterminasi:
kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-hra99
Container Name: simmemleak
LastState: map[terminated:map[exitCode:137 reason:OOM Killed startedAt:2015-07-07T20:58:43Z finishedAt:2015-07-07T20:58:43Z containerID:docker://0e4095bba1feccdfe7ef9fb6ebffe972b4b14285d5acdec6f0d3ae8a22fad8b2]]
Kamu dapat lihat bahwa Container tersebut diterminasi karena reason:OOM Killed
, di mana
OOM
merupakan singkatan dari Out Of Memory, atau kehabisan memori.
Penyimpanan lokal sementara
Kubernetes v1.23 [beta]
Kubernetes versi 1.8 memperkenalkan sebuah sumber daya baru, ephemeral-storage untuk mengatur penyimpanan lokal yang bersifat sementara. Pada setiap Node Kubernetes, direktori root dari Kubelet (secara bawaan /var/lib/kubelet) dan direktori log (/var/log) ditaruh pada partisi root dari Node tersebut. Partisi ini juga digunakan bersama oleh Pod-Pod melalui volume emptyDir, log kontainer, lapisan image, dan lapisan kontainer yang dapat ditulis.
Partisi ini bersifat "sementara" dan aplikasi-aplikasi tidak dapat mengharapkan SLA kinerja (misalnya Disk IOPS) dari partisi ini. Pengelolaan penyimpanan lokal sementara hanya berlaku untuk partisi root; partisi opsional untuk lapisan image dan lapisan yang dapat ditulis berada di luar ruang lingkup.
Menyetel request dan limit dari penyimpanan lokal sementara
Setiap Container dari sebuah Pod dapat menentukan satu atau lebih dari hal-hal berikut:
spec.containers[].resources.limits.ephemeral-storage
spec.containers[].resources.requests.ephemeral-storage
Limit dan request untuk ephemeral-storage
diukur dalam satuan bytes. Kamu dapat menyatakan
penyimpanan dalam bilangan bulat biasa, atau sebagai fixed-point integer menggunakan satu dari
sufiks-sufiks ini: E, P, T, G, M, K. Kamu jika dapat menggunakan bentuk pangkat dua ekuivalennya:
Ei, Pi, Ti, Gi, Mi, Ki. Contohnya, nilai-nilai berikut kurang lebih sama:
128974848, 129e6, 129M, 123Mi
Contohnya, Pod berikut memiliki dua Container. Setiap Container memiliki request 2GiB untuk penyimpanan lokal sementara. Setiap Container memiliki limit 4GiB untuk penyimpanan lokal sementara. Maka, Pod tersebut memiliki jumlah request 4GiB penyimpanan lokal sementara, dan limit 8GiB.
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: db
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "4Gi"
- name: wp
image: wordpress
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "4Gi"
Bagaimana Pod-Pod dengan request ephemeral-storage dijadwalkan
Saat kamu membuat sebuah Pod, Kubernetes scheduler memilih sebuah Node di mana Pod tersebut akan dijalankan. Setiap Node memiliki jumlah maksimum penyimpanan lokal sementara yang dapat disediakan. Untuk lebih lanjut, lihat "Hal-hal yang dapat dialokasikan Node".
Scheduler memastikan bahwa jumlah dari request-request sumber daya dari Container-Container yang dijadwalkan lebih kecil dari kapasitas Node.
Bagaimana Pod-Pod dengan limit ephemeral-storage dijalankan
Untuk isolasi pada tingkat kontainer, jika lapisan yang dapat ditulis dari sebuah Container dan penggunaan log melebihi limit penyimpanannya, maka Pod tersebut akan dipindahkan. Untuk isolasi pada tingkat Pod, jika jumlah dari penyimpanan lokal sementara dari semua Container dan juga volume emptyDir milik Pod melebihi limit, maka Pod teresebut akan dipindahkan.
Memantau penggunaan ephemeral-storage
Saat penyimpanan lokal sementara digunakan, ia dipantau terus-menerus oleh Kubelet. Pemantauan dilakukan dengan cara memindai setiap volume emptyDir, direktori log, dan lapisan yang dapat ditulis secara periodik. Dimulai dari Kubernetes 1.15, volume emptyDir (tetapi tidak direktori log atau lapisan yang dapat ditulis) dapat, sebagai pilihan dari operator klaster, dikelola dengan menggunakan project quotas. Project quotas aslinya diimplementasikan dalam XFS, dan baru-baru ini telah diubah ke ext4fs. Project quotas dapat digunakan baik untuk monitoring dan pemaksaan; sejak Kubernetes 1.16, mereka tersedia sebagai fitur alpha untuk monitoring saja.
Quota lebih cepat dan akurat dibandingkan pemindaian direktori. Saat sebuah direktori ditentukan untuk sebuah proyek, semua berkas yang dibuat pada direktori tersebut dibuat untuk proyek tersebut, dan kernel hanya perlu melacak berapa banyak blok yang digunakan oleh berkas-berkas pada proyek tersebut. Jika sebuah berkas dibuat dan dihapus, tetapi tetap dengan sebuah file descriptor yang terbuka, maka berkas tersebut tetap akan memakan ruangan penyimpanan. Ruangan ini akan dilacak oleh quota tersebut, tetapi tidak akan terlihat oleh sebuah pemindaian direktori.
Kubernetes menggunakan ID proyek yang dimulai dari 1048576. ID-ID yang
digunakan akan didaftarkan di dalam /etc/projects
dan /etc/projid
.
Jika ID-ID proyek pada kisaran ini digunakan untuk tujuan lain pada sistem,
ID-ID proyek tersebut harus terdaftar di dalam /etc/projects
dan /etc/projid
untuk mencegah Kubernetes menggunakan ID-ID tersebut.
Untuk mengaktifkan penggunaan project quotas, operator klaster harus melakukan hal-hal berikut:
-
Aktifkan feature gate
LocalStorageCapacityIsolationFSQuotaMonitoring=true
pada konfigurasi Kubelet. Nilainya secara bawaanfalse
pada Kubernetes 1.16, jadi harus secara eksplisit disetel menjaditrue
. -
Pastikan bahwa partisi root (atau partisi opsional runtime) telah dibangun (build) dengan mengaktifkan project quotas. Semua sistem berkas (filesystem) XFS mendukung project quotas, tetapi sistem berkas ext4 harus dibangun secara khusus untuk mendukungnya
-
Pastikan bahwa partisi root (atau partisi opsional runtime) ditambatkan (mount) dengan project quotas yang telah diaktifkan.
Membangun dan menambatkan sistem berkas dengan project quotas yang telah diaktifkan
Sistem berkas XFS tidak membutuhkan tindakan khusus saat dibangun; mereka secara otomatis telah dibangun dengan project quotas yang telah diaktifkan.
Sistem berkas ext4fs harus dibangun dengan mengaktifkan quotas, kemudian mereka harus diaktifkan pada sistem berkas tersebut.
% sudo mkfs.ext4 other_ext4fs_args... -E quotatype=prjquota /dev/block_device
% sudo tune2fs -O project -Q prjquota /dev/block_device
Untuk menambatkan sistem berkasnya, baik ext4fs dan XFS membutuhkan opsi
prjquota
disetel di dalam /etc/fstab
:
/dev/block_device /var/kubernetes_data defaults,prjquota 0 0
Sumber daya yang diperluas
Sumber daya yang diperluas (Extended Resource) adalah nama sumber daya di luar domain kubernetes.io
.
Mereka memungkinkan operator klaster untuk menyatakan dan pengguna untuk menggunakan
sumber daya di luar sumber daya bawaan Kubernetes.
Ada dua langkah untuk menggunakan sumber daya yang diperluas. Pertama, operator klaster harus menyatakan sebuah Extended Resource. Kedua, pengguna harus meminta sumber daya yang diperluas tersebut di dalam Pod.
Mengelola sumber daya yang diperluas
Sumber daya yang diperluas pada tingkat Node
Sumber daya yang diperluas pada tingkat Node terikat pada Node.
Sumber daya Device Plugin yang dikelola
Lihat Device Plugin untuk cara menyatakan sumber daya device plugin yang dikelola pada setiap node.
Sumber daya lainnya
Untuk menyatakan sebuah sumber daya yang diperluas tingkat Node, operator klaster
dapat mengirimkan permintaan HTTP PATCH
ke API server untuk menentukan kuantitas
sumber daya yang tersedia pada kolom status.capacity
untuk Node pada klaster.
Setelah itu, status.capacity
pada Node akan memiliki sumber daya baru tersebut.
Kolom status.allocatable
diperbarui secara otomatis dengan sumber daya baru
tersebut secara asynchrounous oleh Kubelet. Perlu dicatat bahwa karena scheduler
menggunakan nilai status.allocatable
milik Node saat mengevaluasi muat atau tidaknya
Pod, mungkin ada waktu jeda pendek antara melakukan PATCH
terhadap kapasitas Node
dengan sumber daya baru dengan Pod pertama yang meminta sumber daya tersebut untuk
dapat dijadwalkan pada Node tersebut.
Contoh:
Berikut sebuah contoh yang menunjukkan bagaimana cara menggunakan curl
untuk
mengirim permintaan HTTP yang menyatakan lima sumber daya "example.com/foo" pada
Node k8s-node-1
yang memiliki master k8s-master
.
curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "add", "path": "/status/capacity/example.com~1foo", "value": "5"}]' \
http://k8s-master:8080/api/v1/nodes/k8s-node-1/status
~1
adalah encoding untuk karakter /
pada jalur (path) patch.
Nilai jalur operasi tersebut di dalam JSON-Patch diinterpretasikan sebagai sebuah JSON-Pointer.
Untuk lebih lanjut, lihat IETF RFC 6901, bagian 3.
Sumber daya yang diperluas pada tingkat klaster
Sumber daya yang diperluas pada tingkat klaster tidak terikat pada Node. Mereka biasanya dikelola oleh scheduler extender, yang menangani penggunaan sumber daya dan kuota sumber daya.
Kamu dapat menentukan sumber daya yang diperluas yang ditangani oleh scheduler extender pada konfigurasi kebijakan scheduler.
Contoh:
Konfigurasi untuk sebuah kebijakan scheduler berikut menunjukkan bahwa sumber daya yang diperluas pada tingkat klaster "example.com/foo" ditangani oleh scheduler extender.
- Scheduler mengirim sebuah Pod ke scheduler extender hanya jika Pod tersebut meminta "example.com/foo".
- Kolom
ignoredByScheduler
menentukan bahwa scheduler tidak memeriksa sumber daya "example.com/foo" pada predikatPodFitsResources
miliknya.
{
"kind": "Policy",
"apiVersion": "v1",
"extenders": [
{
"urlPrefix":"<extender-endpoint>",
"bindVerb": "bind",
"managedResources": [
{
"name": "example.com/foo",
"ignoredByScheduler": true
}
]
}
]
}
Menggunakan sumber daya yang diperluas
Pengguna dapat menggunakan sumber daya yang diperluas di dalam spesifikasi Pod seperti CPU dan memori. Scheduler menangani akuntansi sumber daya tersebut agar tidak ada alokasi untuk yang melebihi jumlah yang tersedia.
API server membatasi jumlah sumber daya yang diperluas dalam bentuk
bilangan bulat. Contoh jumlah yang valid adalah 3
, 3000m
, dan
3Ki
. Contoh jumlah yang tidak valid adalah 0.5
dan 1500m
.
kubernetes.io
yang sudah dipakai.
Untuk menggunakan sebuah sumber daya yang diperluas di sebuah Pod, masukkan nama
sumber daya tersebut sebagai nilai key dari map spec.containers[].resources.limit
pada spesifikasi Container.
Sebuah Pod hanya dijadwalkan jika semua request sumber dayanya terpenuhi, termasuk
CPU, memori, dan sumber daya yang diperluas manapun. Pod tersebut akan tetap
berada pada kondisi PENDING
selama request sumber daya tersebut tidak terpenuhi.
Contoh:
Pod di bawah meminta 2 CPU dan 1 "example.com/foo" (sebuah sumber daya yang diperluas).
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: myimage
resources:
requests:
cpu: 2
example.com/foo: 1
limits:
example.com/foo: 1
Selanjutnya
-
Dapatkan pengalaman langsung menentukan sumber daya memori untuk Container dan Pod.
-
Dapatkan pengalaman langsung menentukan sumber daya CPU untuk Container dan Pod.
3.7.3 - Secret
Objek secret
pada Kubernetes mengizinkan kamu menyimpan dan mengatur informasi yang sifatnya sensitif, seperti
password, token OAuth, dan ssh keys. Menyimpan informasi yang sifatnya sensitif ini ke dalam secret
cenderung lebih aman dan fleksible jika dibandingkan dengan menyimpan informasi tersebut secara apa adanya pada definisi Pod atau di dalam container image.
Silahkan lihat Dokumen desain Secret untuk informasi yang sifatnya mendetail.
Ikhtisar Secret
Sebuah Secret merupakan sebuah objek yang mengandung informasi yang sifatnya sensitif, seperti password, token, atau key. Informasi tersebut sebenarnya bisa saja disimpan di dalam spesifikasi Pod atau image; meskipun demikian, melakukan penyimpanan di dalam objek Secret mengizinkan pengguna untuk memiliki kontrol lebih lanjut mengenai bagaimana Secret ini disimpan, serta mencegah tereksposnya informasi sensitif secara tidak disengaja.
Baik pengguna dan sistem memiliki kemampuan untuk membuat objek Secret.
Untuk menggunakan Secret, sebuah Pod haruslah merujuk pada Secret tersebut. Sebuah Secret dapat digunakan di dalam sebuah Pod melalui dua cara: sebagai file yang ada di dalam volume volume yang di-mount pada salah satu container Pod, atau digunakan oleh kubelet ketika menarik image yang digunakan di dalam Pod.
Secret Built-in
Sebuah Service Account akan Secara Otomatis Dibuat dan Meng-attach Secret dengan Kredensial API
Kubernetes secara otomatis membuat secret yang mengandung kredensial yang digunakan untuk mengakses API, serta secara otomatis memerintahkan Pod untuk menggunakan Secret ini.
Mekanisme otomatisasi pembuatan secret dan penggunaan kredensial API dapat di nonaktifkan atau di-override jika kamu menginginkannya. Meskipun begitu, jika apa yang kamu butuhkan hanyalah mengakses apiserver secara aman, maka mekanisme default inilah yang disarankan.
Baca lebih lanjut dokumentasi Service Account untuk informasi lebih lanjut mengenai bagaimana cara kerja Service Account.
Membuat Objek Secret Kamu Sendiri
Membuat Secret dengan Menggunakan kubectl
Misalnya saja, beberapa Pod memerlukan akses ke sebuah basis data. Kemudian username
dan password yang harus digunakan oleh Pod-Pod tersebut berada pada mesin lokal kamu
dalam bentuk file-file ./username.txt
dan ./password.txt
.
# Buatlah berkas yang selanjutnya akan digunakan pada contoh-contoh selanjutnya
echo -n 'admin' > ./username.txt
echo -n '1f2d1e2e67df' > ./password.txt
Perintah kubectl create secret
akan mengemas file-file ini menjadi Secret dan
membuat sebuah objek pada Apiserver.
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret "db-user-pass" created
$
, \*
, and !
membutuhkan mekanisme escaping.
Jika password yang kamu gunakan mengandung karakter spesial, kamu perlu melakukan escape karakter dengan menggunakan karakter \\
. Contohnya, apabila password yang kamu miliki adalah S!B\*d$zDsb
, maka kamu harus memanggil perintah kubectl dengan cara berikut:
kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password=S\!B\\*d\$zDsb
Perhatikan bahwa kamu tidak perlu melakukan escape karakter apabila massukan yang kamu berikan merupakan file (--from-file
).
Kamu dapat memastikan apakah suatu Secret sudah dibuat atau belum dengan menggunakan perintah:
kubectl get secrets
NAME TYPE DATA AGE
db-user-pass Opaque 2 51s
kubectl describe secrets/db-user-pass
Name: db-user-pass
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password.txt: 12 bytes
username.txt: 5 bytes
kubectl get
dan kubectl describe
secara default akan
mencegah ditampilkannya informasi yang ada di dalam Secret.
Hal ini dilakukan untuk melindungi agar Secret tidak terekspos secara tidak disengaja oleh orang lain,
atau tersimpan di dalam log terminal.
Kamu dapat membaca bagaimana cara melakukan decode sebuah secret untuk mengetahui bagaimana cara melihat isi dari Secret.
Membuat Secret Secara Manual
Kamu dapat membuat sebuah Secret dengan terlebih dahulu membuat file yang berisikan informasi yang ingin kamu jadikan Secret dalam bentuk yaml atau json dan kemudian membuat objek dengan menggunakan file tersebut. Secret mengandung dua buah map: data dan stringData. Field data digunakan untuk menyimpan sembarang data, yang di-encode menggunakan base64. Sementara itu stringData disediakan untuk memudahkan kamu untuk menyimpan informasi sensitif dalam format yang tidak di-encode.
Sebagai contoh, untuk menyimpan dua buah string di dalam Secret dengan menggunakan field data, ubahlah informasi tersebut ke dalam base64 dengan menggunakan mekanisme sebagai berikut:
echo -n 'admin' | base64
YWRtaW4=
echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm
Buatlah sebuah Secret yang memiliki bentuk sebagai berikut:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
Kemudian buatlah Secret menggunakan perintah kubectl apply
:
kubectl apply -f ./secret.yaml
secret "mysecret" created
Untuk beberapa skenario, kamu bisa saja ingin menggunakan opsi field stringData. Field ini mengizinkan kamu untuk memberikan masukan berupa informasi yang belum di-encode secara langsung pada sebuah Secret, informasi dalam bentuk string ini kemudian akan di-encode ketika Secret dibuat maupun diubah.
Contoh praktikal dari hal ini adalah ketika kamu melakukan proses deploy aplikasi yang menggunakan Secret sebagai penyimpanan file konfigurasi, dan kamu ingin mengisi bagian dari konfigurasi file tersebut ketika aplikasi di_deploy_.
Jika kamu ingin aplikasi kamu menggunakan file konfigurasi berikut:
apiUrl: "https://my.api.com/api/v1"
username: "user"
password: "password"
Kamu dapat menyimpan Secret ini dengan menggunakan cara berikut:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
stringData:
config.yaml: |-
apiUrl: "https://my.api.com/api/v1"
username: {{username}}
password: {{password}}
Alat deployment yang kamu gunakan kemudian akan mengubah templat variabel {{username}}
dan {{password}}
sebelum menjalankan perintah kubectl apply
.
stringData merupakan field yang sifatnya write-only untuk alasan kenyamanan pengguna. Field ini tidak pernah ditampilkan ketika Secret dibaca. Sebagai contoh, misalkan saja kamu menjalankan perintah sebagai berikut:
kubectl get secret mysecret -o yaml
Keluaran yang diberikan kurang lebih akan ditampilkan sebagai berikut:
apiVersion: v1
kind: Secret
metadata:
creationTimestamp: 2018-11-15T20:40:59Z
name: mysecret
namespace: default
resourceVersion: "7225"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: c280ad2e-e916-11e8-98f2-025000000001
type: Opaque
data:
config.yaml: YXBpVXJsOiAiaHR0cHM6Ly9teS5hcGkuY29tL2FwaS92MSIKdXNlcm5hbWU6IHt7dXNlcm5hbWV9fQpwYXNzd29yZDoge3twYXNzd29yZH19
Jika sebuah field dispesifikasikan dalam bentuk data maupun stringData, maka nilai dari stringData-lah yang akan digunakan. Sebagai contoh, misalkan saja terdapat definisi Secret sebagai berikut:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
stringData:
username: administrator
Akan menghasilkan Secret sebagai berikut:
apiVersion: v1
kind: Secret
metadata:
creationTimestamp: 2018-11-15T20:46:46Z
name: mysecret
namespace: default
resourceVersion: "7579"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: 91460ecb-e917-11e8-98f2-025000000001
type: Opaque
data:
username: YWRtaW5pc3RyYXRvcg==
Dimana string YWRtaW5pc3RyYXRvcg==
akan di-decode sebagai administrator
.
Key dari data dan stringData yang boleh tersusun atas karakter alfanumerik, '-', '_' atau '.'.
Catatan Encoding: Value dari JSON dan YAML yang sudah diseriakisasi dari data Secret
akan di-encode ke dalam string base64. Newline dianggap tidak valid pada string ini dan harus
dihilangkan. Ketika pengguna Darwin/macOS menggunakan alat base64
, maka pengguna
tersebut harus menghindari opsi -b
yang digunakan untuk memecah baris yang terlalu panjang.
Sebaliknya pengguna Linux harus menambahkan opsi -w 0
pada perintah base64
atau
melakukan mekanisme pipeline base64 | tr -d '\n'
jika tidak terdapat opsi -w
.
Membuat Secret dengan Menggunakan Generator
Kubectl mendukung mekanisme manajemen objek dengan menggunakan Kustomize
sejak versi 1.14. Dengan fitur baru ini, kamu juga dapat membuat sebuah Secret dari sebuah generator
dan kemudian mengaplikasikannya untuk membuat sebuah objek pada Apiserver. Generator yang digunakan haruslah
dispesifikasikan di dalam sebuah file kustomization.yaml
di dalam sebuah direktori.
Sebagai contoh, untuk menghasilan sebuah Secret dari file-file ./username.txt
dan ./password.txt
# Membuat sebuah berkas kustomization.yaml dengan SecretGenerator
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: db-user-pass
files:
- username.txt
- password.txt
EOF
Gunakan direktori kustomization untuk membuat objek Secret yang diinginkan.
$ kubectl apply -k .
secret/db-user-pass-96mffmfh4k created
Kamu dapat memastikan Secret tersebut sudah dibuat dengan menggunakan perintah berikut:
$ kubectl get secrets
NAME TYPE DATA AGE
db-user-pass-96mffmfh4k Opaque 2 51s
$ kubectl describe secrets/db-user-pass-96mffmfh4k
Name: db-user-pass
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password.txt: 12 bytes
username.txt: 5 bytes
Sebagai contoh, untuk membuat sebuah Secret dari literal username=admin
dan password=secret
,
kamu dapat menspesifikasikan generator Secret pada file kustomization.yaml
sebagai
# Membuat sebuah berkas kustomization.yaml dengan menggunakan SecretGenerator
$ cat <<EOF >./kustomization.yaml
secretGenerator:
- name: db-user-pass
literals:
- username=admin
- password=secret
EOF
Aplikasikan direktori kustomization untuk membuat objek Secret.
$ kubectl apply -k .
secret/db-user-pass-dddghtt9b5 created
Melakukan Proses Decode pada Secret
Secret dapat dibaca dengan menggunakan perintah kubectl get secret
.
Misalnya saja, untuk membaca Secret yang dibuat pada bagian sebelumya:
kubectl get secret mysecret -o yaml
apiVersion: v1
kind: Secret
metadata:
creationTimestamp: 2016-01-22T18:41:56Z
name: mysecret
namespace: default
resourceVersion: "164619"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: cfee02d6-c137-11e5-8d73-42010af00002
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
Kemudian lakukan mekanisme decode field password:
echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
1f2d1e2e67df
Menggunakan Secret
Secret dapat di-mount sebagai volume data atau dapat diekspos sebagai variabel-variabel environment dapat digunakan di dalam Pod. Secret ini juga dapat digunakan secara langsug oleh bagian lain dari sistem, tanpa secara langsung berkaitan dengan Pod. Sebagai contoh, Secret dapat berisikan kredensial bagian suatu sistem lain yang digunakan untuk berinteraksi dengan sistem eksternal yang kamu butuhkan.
Menggunakan Secret sebagai File melalui Pod
Berikut adalah langkah yang harus kamu penuhi agar kamu dapat menggunakan Secret di dalam volume dalam sebuah Pod:
- Buatlah sebuah Secret, atau gunakan sebuah Secret yang sudah kamu buat sebelumnya. Beberapa Pod dapat merujuk pada sebuah Secret yang sama.
- Modifikasi definisi Pod kamu dengan cara menambahkan sebuah volume di bawah
.spec.volumes[]
. Berilah volume tersebut nama, dan pastikan field.spec.volumes[].secret.secretName
merujuk pada nama yang sama dengan objek secret. - Tambahkan field
.spec.containers[].volumeMounts[]
pada setiap container yang membutuhkan Secret. Berikan spesifikasi.spec.containers[].volumeMounts[].readOnly = true
dan.spec.containers[].volumeMounts[].mountPath
pada direktori dimana Secret tersebut diletakkan. - Modifikasi image dan/atau command line kamu agar program yang kamu miliki merujuk pada file di dalam direktori tersebut. Setiap key pada map
data
Secret akan menjadi nama dari sebuah file padamountPath
.
Berikut merupakan salah satu contoh dimana sebuah Pod melakukan proses mount Secret pada sebuah volume:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
Setiap Secret yang ingin kamu gunakan harus dirujuk pada field .spec.volumes
.
Jika terdapat lebih dari satu container di dalam Pod,
maka setiap container akan membutuhkan blok volumeMounts
-nya masing-masing,
meskipun demikian hanya sebuah field .spec.volumes
yang dibutuhkan untuk setiap Secret.
Kamu dapat menyimpan banyak file ke dalam satu Secret, atau menggunakan banyak Secret, hal ini tentunya bergantung pada preferensi pengguna.
Proyeksi key Secret pada Suatu Path Spesifik
Kita juga dapat mengontrol path di dalam volume di mana sebuah Secret diproyeksikan.
Kamu dapat menggunakan field .spec.volumes[].secret.items
untuk mengubah
path target dari setiap key:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
items:
- key: username
path: my-group/my-username
Apa yang akan terjadi jika kita menggunakan definisi di atas:
- Secret
username
akan disimpan pada file/etc/foo/my-group/my-username
dan bukan/etc/foo/username
. - Secret
password
tidak akan diproyeksikan.
Jika field .spec.volumes[].secret.items
digunakan, hanya key-key yang dispesifikan di dalam
items
yang diproyeksikan. Untuk mengonsumsi semua key-key yang ada dari Secret,
semua key yang ada harus didaftarkan pada field items
.
Semua key yang didaftarkan juga harus ada di dalam Secret tadi.
Jika tidak, volume yang didefinisikan tidak akan dibuat.
Permission File-File Secret
Kamu juga dapat menspesifikasikan mode permission dari file Secret yang kamu inginkan.
Jika kamu tidak menspesifikasikan hal tersebut, maka nilai default yang akan diberikan adalah 0644
is used by default.
Kamu dapat memberikan mode default untuk semua Secret yang ada serta melakukan mekanisme override permission
pada setiap key jika memang diperlukan.
Sebagai contoh, kamu dapat memberikan spesifikasi mode default sebagai berikut:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
volumes:
- name: foo
secret:
secretName: mysecret
defaultMode: 256
Kemudian, sebuah Secret akan di-mount pada /etc/foo
, selanjutnya semua file
yang dibuat pada volume secret tersebut akan memiliki permission 0400
.
Perhatikan bahwa spesifikasi JSON tidak mendukung notasi octal, dengan demikian gunakanlah value 256 untuk permission 0400. Jika kamu menggunakan format YAML untuk spesifikasi Pod, kamu dapat menggunakan notasi octal untuk memberikan spesifikasi permission dengan cara yang lebih natural.
Kamu juga dapat melakukan mekanisme pemetaan, seperti yang sudah dilakukan pada contoh sebelumnya, dan kemudian memberikan spesifikasi permission yang berbeda untuk file yang berbeda.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
volumes:
- name: foo
secret:
secretName: mysecret
items:
- key: username
path: my-group/my-username
mode: 511
Pada kasus tersebut, file yang dihasilkan pada /etc/foo/my-group/my-username
akan memiliki
permission 0777
. Karena terdapat batasan pada representasi JSON, maka kamu
harus memberikan spesifikasi mode permission dalam bentuk notasi desimal.
Perhatikan bahwa permission ini bida saja ditampilkan dalam bentuk notasi desimal, hal ini akan ditampilkan pada bagian selanjutnya.
Mengonsumsi Value dari Secret melalui Volume
Di dalam sebuah container dimana volume secret di-mount, key dari Secret akan ditampilkan sebagai file dan value dari Secret yang berada dalam bentuk base64 ini akan di-decode dam disimpan pada file-file tadi. Berikut merupakan hasil dari eksekusi perintah di dalam container berdasarkan contoh yang telah dipaparkan di atas:
ls /etc/foo/
username
password
cat /etc/foo/username
admin
cat /etc/foo/password
1f2d1e2e67df
Program di dalam container bertanggung jawab untuk membaca Secret dari file-file yang ada.
Secret yang di-mount Akan Diubah Secara Otomatis
Ketika sebuah Secret yang sedang digunakan di dalam volume diubah,
maka key yang ada juga akan diubah. Kubelet akan melakukan mekanisme pengecekan secara periodik
apakah terdapat perubahan pada Secret yang telah di-mount. Meskipun demikian,
proses pengecekan ini dilakukan dengan menggunakan cache lokal untuk mendapatkan value saat ini
dari sebuah Secret. Tipe cache yang ada dapat diatur dengan menggunakan
(field ConfigMapAndSecretChangeDetectionStrategy
pada
struct KubeletConfiguration).
Mekanisme ini kemudian dapat diteruskan dengan mekanisme watch(default), ttl, atau melakukan pengalihan semua
request secara langsung pada kube-apiserver.
Sebagai hasilnya, delay total dari pertama kali Secret diubah hingga dilakukannya mekanisme
proyeksi key yang baru pada Pod berlangsung dalam jangka waktu sinkronisasi periodik kubelet +
delay propagasi cache, dimana delay propagasi cache bergantung pada jenis cache yang digunakan
(ini sama dengan delay propagasi watch, ttl dari cache, atau nol).
Menggunakan Secret sebagai Variabel Environment
Berikut merupakan langkah-langkah yang harus kamu terapkan, untuk menggunakan secret sebagai variabel _environment_ pada sebuah Pod:
- Buatlah sebuah Secret, atau gunakan sebuah Secret yang sudah kamu buat sebelumnya. Beberapa Pod dapat merujuk pada sebuah Secret yang sama.
- Modifikasi definisi Pod pada setiap container dimana kamu menginginkan container tersebut dapat mengonsumsi your Pod definition in each container that you wish to consume the value of a secret key to add an environment variabele for each secret key you wish to consume. The environment variabele that consumes the secret key should populate the secret's name and key in
env[].valueFrom.secretKeyRef
. - Modifikasi image dan/atau command line kamu agar program yang kamu miliki merujuk pada value yang sudah didefinisikan pada variabel environment.
Berikut merupakan contoh dimana sebuah Pod menggunakan Secret sebagai variabel environment:
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: redis
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
restartPolicy: Never
Menggunakan Secret dari Variabel Environment
Di dalam sebuah container yang mengkonsumsi Secret pada sebuah variabel environment, key dari sebuah secret akan ditampilkan sebagai variabel environment pada umumnya dengan value berupa informasi yang telah di-decode ke dalam base64. Berikut merupakan hasil yang didapatkan apabila perintah-perintah di bawah ini dijalankan dari dalam container yang didefinisikan di atas:
echo $SECRET_USERNAME
admin
echo $SECRET_PASSWORD
1f2d1e2e67df
Menggunakan imagePullSecrets
Sebuah imagePullSecret
merupakan salah satu cara yang dapat digunakan untuk menempatkan secret
yang mengandung password dari registri Docker (atau registri image lainnya)
pada Kubelet, sehingga Kubelet dapat mengunduh image dan menempatkannya pada Pod.
Memberikan spesifikasi manual dari sebuah imagePullSecret
Penggunaan imagePullSecrets dideskripsikan di dalam dokumentasi image
Mekanisme yang Dapat Diterapkan agar imagePullSecrets dapat Secara Otomatis Digunakan
Kamu dapat secara manual membuat sebuah imagePullSecret, serta merujuk imagePullSecret yang sudah kamu buat dari sebuah serviceAccount. Semua Pod yang dibuat dengan menggunakan serviceAccount tadi atau serviceAccount default akan menerima field imagePullSecret dari serviceAccount yang digunakan. Bacalah Cara menambahkan ImagePullSecrets pada sebuah service account untuk informasi lebih detail soal proses yang dijalankan.
Mekanisme Mounting Otomatis dari Secret yang Sudah Dibuat
Secret yang dibuat secara manual (misalnya, secret yang mengandung token yang dapat digunakan untuk mengakses akun GitHub) dapat di-mount secara otomatis pada sebuah Pod berdasarkan service account yang digunakan oleh Pod tadi. Baca Bagaimana Penggunaan PodPreset untuk Memasukkan Informasi ke Dalam Pod untuk informasi lebih lanjut.
Detail
Batasan-Batasan
Sumber dari secret volume akan divalidasi untuk menjamin rujukan pada
objek yang dispesifikasikan mengarah pada objek dengan type Secret
.
Oleh karenanya, sebuah secret harus dibuat sebelum Pod yang merujuk pada secret
tersebut dibuat.
Sebuah objek API Secret berada di dalam sebuah namespace. Objek-objek ini hanya dapat dirujuk oleh Pod-Pod yang ada pada namespace yang sama.
Secret memiliki batasi dalam hal ukuran maksimalnya yaitu hanya sampai 1MiB per objek. Oleh karena itulah, pembuatan secret dalam ukuran yang sangat besar tidak dianjurkan karena dapat menghabiskan sumber daya apiserver dan memori kubelet. Meskipun demikian, pembuatan banyak secret dengan ukuran kecil juga dapat menhabiskan memori. Pembatasan sumber daya yang diizinkan untuk pembuatan secret merupakan salah satu fitur tambahan yang direncanakan kedepannya.
Kubelet hanya mendukung penggunaan secret oleh Pod apabila Pod tersebut
didapatkan melalui apiserver. Hal ini termasuk Pod yang dibuat dengan menggunakan
kubectl, atau secara tak langsung melalui replication controller. Hal ini tidak
termasuk Pod yang dibuat melalui flag --manifest-url
yang ada pada kubelet,
maupun REST API yang disediakan (hal ini bukanlah merupakan mekanisme umum yang dilakukan
untuk membuat sebuah Pod).
Secret harus dibuat sebelum digunakan oleh Pod sebagai variabel environment, kecuali apabila variabel environment ini dianggap opsional. Rujukan pada Secret yang tidak dapat dipenuhi akan menyebabkan Pod gagal start.
Rujukan melalui secretKeyRef
pada key yang tidak ada pada named Secret
akan akan menyebabkan Pod gagal start.
Secret yang digunakan untuk memenuhi variabel environment melalui envFrom
yang
memiliki key yang dianggap memiliki penamaan yang tidak valid akan diabaikan.
Hal ini akan akan menyebabkan Pod gagal start. Selanjutnya akan terdapat event
dengan alasan InvalidvariabeleNames
dan pesan yang berisikan list dari
key yang diabaikan akibat penamaan yang tidak valid. Contoh yang ada akan menunjukkan
sebuah pod yang merujuk pada secret default/mysecret
yang mengandung dua buah key
yang tidak valid, yaitu 1badkey dan 2alsobad.
kubectl get events
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON
0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentvariabeleNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variabele names.
Interaksi Secret dan Pod Lifetime
Ketika sebuah pod dibuat melalui API, tidak terdapat mekanisme pengecekan yang digunakan untuk mengetahui apakah sebuah Secret yang dirujuk sudah dibuat atau belum. Ketika sebuah Pod di-schedule, kubelet akan mencoba mengambil informasi mengenai value dari secret tadi. Jika secret tidak dapat diambil value-nya dengan alasan temporer karena hilangnya koneksi ke API server atau secret yang dirujuk tidak ada, kubelet akan melakukan mekanisme retry secara periodik. Kubelet juga akan memberikan laporan mengenai event yang terjadi pada Pod serta alasan kenapa Pod tersebut belum di-start. Apabila Secret berhasil didapatkan, kubelet akan membuat dan me-mount volume yang mengandung secret tersebut. Tidak akan ada container dalam pod yang akan di-start hingga semua volume pod berhasil di-mount.
Contoh-Contoh Penggunaan
Contoh Penggunaan: Pod dengan ssh key
Buatlah sebuah kustomization.yaml dengan SecretGenerator yang mengandung beberapa ssh key:
kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub
secret "ssh-key-secret" created
Sekarang, kita dapat membuat sebuah pod yang merujuk pada secret dengan ssh key yang sudah dibuat tadi serta menggunakannya melalui sebuah volume yang di-mount:
apiVersion: v1
kind: Pod
metadata:
name: secret-test-pod
labels:
name: secret-test
spec:
volumes:
- name: secret-volume
secret:
secretName: ssh-key-secret
containers:
- name: ssh-test-container
image: mySshImage
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
Ketika sebuah perintah dijalankan di dalam container, bagian dari key tadi akan terdapat pada:
/etc/secret-volume/ssh-publickey
/etc/secret-volume/ssh-privatekey
container kemudian dapat menggunakan secret secara bebas untuk membuat koneksi ssh.
Contoh Penggunaan: Pod dengan kredensial prod / test
Contoh ini memberikan ilustrasi pod yang mengonsumsi secret yang mengandung kredensial dari environment production atau environment test.
Buatlah suatu kustomization.yaml dengan SecretGenerator
kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
secret "prod-db-secret" created
kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests
secret "test-db-secret" created
Karakter spesial seperti $
, \*
, dan !
membutuhkan mekanisme escaping.
Jika password yang kamu gunakan memiliki karakter spesial, kamu dapat melakukan mekanisme escape
dengan karakter \\
character. Sebagai contohnya, jika password kamu yang sebenarnya adalah
S!B\*d$zDsb
, maka kamu harus memanggil perintah eksekusi dengan cara sebagai berikut:
kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password=S\\!B\\\*d\\$zDsb
Kamu tidak perlu melakukan mekanisme escape karakter apabila menggunakan opsi melalui file (--from-file
).
Kemudian buatlah Pod-Pod yang dibutuhkan:
$ cat <<EOF > pod.yaml
apiVersion: v1
kind: List
items:
- kind: Pod
apiVersion: v1
metadata:
name: prod-db-client-pod
labels:
name: prod-db-client
spec:
volumes:
- name: secret-volume
secret:
secretName: prod-db-secret
containers:
- name: db-client-container
image: myClientImage
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
- kind: Pod
apiVersion: v1
metadata:
name: test-db-client-pod
labels:
name: test-db-client
spec:
volumes:
- name: secret-volume
secret:
secretName: test-db-secret
containers:
- name: db-client-container
image: myClientImage
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
EOF
Tambahkan Pod-Pod terkait pada file kustomization.yaml yang sama
$ cat <<EOF >> kustomization.yaml
resources:
- pod.yaml
EOF
Terapkan semua perubahan pada objek-objek tadi ke Apiserver dengan menggunakan
kubectl apply --k .
Kedua container kemudian akan memiliki file-file berikut ini di dalam filesystem keduanya dengan value sebagai berikut untuk masing-masing environment:
/etc/secret-volume/username
/etc/secret-volume/password
Perhatikan bahwa specs untuk kedua pod berbeda hanya pada satu field saja; hal ini bertujuan untuk memfasilitasi adanya kapabilitas yang berbeda dari templat konfigurasi umum yang tersedia.
Kamu dapat mensimplifikasi spesifikasi dasar Pod dengan menggunakan dua buah service account yang berbeda:
misalnya saja salah satunya disebut sebagai prod-user
dengan prod-db-secret
, dan satunya lagi disebut
test-user
dengan test-db-secret
. Kemudian spesifikasi Pod tadi dapat diringkas menjadi:
apiVersion: v1
kind: Pod
metadata:
name: prod-db-client-pod
labels:
name: prod-db-client
spec:
serviceAccount: prod-db-client
containers:
- name: db-client-container
image: myClientImage
Contoh Penggunaan: Dotfiles pada volume secret
Dengan tujuan membuat data yang ada 'tersembunyi' (misalnya, di dalam sebuah file dengan nama yang dimulai dengan karakter titik), kamu dapat melakukannya dengan cara yang cukup sederhana, yaitu cukup dengan membuat karakter awal key yang kamu inginkan dengan titik. Contohnya, ketika sebuah secret di bawah ini di-mount pada sebuah volume:
apiVersion: v1
kind: Secret
metadata:
name: dotfile-secret
data:
.secret-file: dmFsdWUtMg0KDQo=
---
apiVersion: v1
kind: Pod
metadata:
name: secret-dotfiles-pod
spec:
volumes:
- name: secret-volume
secret:
secretName: dotfile-secret
containers:
- name: dotfile-test-container
image: k8s.gcr.io/busybox
command:
- ls
- "-l"
- "/etc/secret-volume"
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
Volume secret-volume
akan mengandung sebuah file, yang disebut sebagai .secret-file
, serta
container dotfile-test-container
akan memiliki file konfigurasinya pada path
/etc/secret-volume/.secret-file
.
ls -l
;
kamu harus menggunakan perintah ls -la
untuk melihat file-file tadi dari sebuah direktori.
Contoh Penggunaan: Secret yang dapat diakses hanya pada salah satu container di dalam pod
Misalkan terdapat sebuah program yang memiliki kebutuhan untuk menangani request HTTP, melakukan logika bisnis yang kompleks, serta kemudian menandai beberapa message yang ada dengan menggunakan HMAC. Karena program ini memiliki logika aplikasi yang cukup kompleks, maka bisa jadi terdapat beberapa celah terjadinya eksploitasi remote file pada server, yang nantinya bisa saja mengekspos private key yang ada pada attacker.
Hal ini dapat dipisah menjadi dua buah proses yang berbeda di dalam dua container: sebuah container frontend yang menangani interaksi pengguna dan logika bisnis, tetapi tidak memiliki kapabilitas untuk melihat private key; container lain memiliki kapabilitas melihat private key yang ada dan memiliki fungsi untuk menandai request yang berasal dari frontend (melalui jaringan localhost).
Dengan strategi ini, seorang attacker harus melakukan teknik tambahan untuk memaksa aplikasi melakukan hal yang acak, yang kemudian menyebabkan mekanisme pembacaan file menjadi lebih susah.
Best practices
Klien yang menggunakan API secret
Ketika men-deploy aplikasi yang berinteraksi dengan API secret, akses yang dilakukan haruslah dibatasi menggunakan policy autorisasi seperti RBAC.
Secret seringkali menyimpan value yang memiliki jangkauan spektrum
kepentingan, yang mungkin saja dapat menyebabkan terjadinya eskalasi baik
di dalam Kubernetes (misalnya saja token dari sebuah service account) maupun
sistem eksternal. Bahkan apabila setiap aplikasi secara individual memiliki
kapabilitas untuk memahami tingkatan yang dimilikinya untuk berinteraksi dengan secret tertentu,
aplikasi lain dalam namespace itu bisa saja menyebabkan asumsi tersebut menjadi tidak valid.
Karena alasan-alasan yang sudah disebutkan tadi request watch
dan list
untuk sebuah
secret di dalam suatu namespace merupakan kapabilitas yang sebisa mungkin harus dihindari,
karena menampilkan semua secret yang ada berimplikasi pada akses untuk melihat isi yang ada
pada secret yang ada. Kapabilitas untuk melakukan request watch
dan list
pada semua secret di kluster
hanya boleh dimiliki oleh komponen pada sistem level yang paling previleged.
Aplikasi yang membutuhkan akses ke API secret harus melakukan request get
pada
secret yang dibutuhkan. Hal ini memungkinkan administrator untuk membatasi
akses pada semua secret dengan tetap memberikan akses pada instans secret tertentu
yang dibutuhkan aplikasi.
Untuk meningkatkan performa dengan menggunakan iterasi get
, klien dapat mendesain
sumber daya yang merujuk pada suatu secret dan kemudian melakukan watch
pada secret tersebut,
serta melakukan request secret ketika terjadi perubahan pada rujukan tadi. Sebagai tambahan, API "bulk watch"
yang dapat memberikan kapabilitas watch
individual pada sumber daya melalui klien juga sudah direncanakan,
dan kemungkinan akan diimplementasikan dirilis Kubernetes selanjutnya.
Properti Keamanan
Proteksi
Karena objek secret
dapat dibuat secara independen dengan pod
yang menggunakannya,
risiko tereksposnya secret di dalam workflow pembuatan, pemantauan, serta pengubahan pod.
Sistem yang ada juga dapat memberikan tindakan pencegahan ketika berinteraksi dengan secret
,
misalnya saja tidak melakukan penulisan isi secret
ke dalam disk apabila hal tersebut
memungkinkan.
Sebuah secret hanya diberikan pada node apabila pod yang ada di dalam node
membutuhkan secret tersebut. Kubelet menyimpan secret yang ada pada tmpfs
sehingga secret tidak ditulis pada disk. Setelah pod yang bergantung pada secret tersebut dihapus,
maka kubelet juga akan menghapus salinan lokal data secret.
Di dalam sebuah node bisa saja terdapat beberapa secret yang dibutuhkan oleh pod yang ada di dalamnya. Meskipun demikian, hanya secret yang di-request oleh sebuah pod saja yang dapat dilihat oleh container yang ada di dalamnya. Dengan demikian, sebuah Pod tidak memiliki akses untuk melihat secret yang ada pada pod yang lain.
Di dalam sebuah pod bisa jadi terdapat beberapa container.
Meskipun demikian, agar sebuah container bisa mengakses volume secret, container
tersebut haruslah mengirimkan request volumeMounts
yang ada dapat diakses dari
container tersebut. Pengetahuan ini dapat digunakan untuk membentuk partisi security
pada level pod.
Pada sebagian besar distribusi yang dipelihara projek Kubernetes, komunikasi antara pengguna dan apiserver serta apisserver dan kubelet dilindungi dengan menggunakan SSL/TLS. Dengan demikian, secret dalam keadaan dilindungi ketika ditransmisi.
Kubernetes v1.13 [beta]
Kamu dapat mengaktifkan enkripsi pada rest untuk data secret, sehingga secret yang ada tidak akan ditulis ke dalam etcd dalam keadaan tidak terenkripsi.
Resiko
- Pada API server, data secret disimpan di dalam etcd;
dengan demikian:
- Administrator harus mengaktifkan enkripsi pada rest untuk data kluster (membutuhkan versi v1.13 atau lebih)
- Administrator harus membatasi akses etcd pada pengguna dengan kapabilitas admin
- Administrator bisa saja menghapus data disk yang sudah tidak lagi digunakan oleh etcd
- Jika etcd dijalankan di dalam kluster, administrator harus memastikan SSL/TLS digunakan pada proses komunikasi peer-to-peer etcd.
- Jika kamu melakukan konfigurasi melalui sebuah file manifest (JSON or YAML) yang menyimpan data secret dalam bentuk base64, membagi atau menyimpan secret ini dalam repositori kode sumber sama artinya dengan memberikan informasi mengenai data secret. Mekanisme encoding base64 bukanlah merupakan teknik enkripsi dan nilainya dianggap sama saja dengan plain text.
- Aplikasi masih harus melindungi value dari secret setelah membaca nilainya dari suatu volume dengan demikian risiko terjadinya logging secret secara tidak engaja dapat dihindari.
- Seorang pengguna yang dapat membuat suatu pod yang menggunakan secret, juga dapat melihat value secret. Bahkan apabila policy apiserver tidak memberikan kapabilitas untuk membaca objek secret, pengguna dapat menjalankan pod yang mengekspos secret.
- Saat ini, semua orang dengan akses root pada node dapat membaca secret apapun dari apiserver,
dengan cara meniru kubelet. Meskipun begitu, terdapat fitur yang direncanakan pada rilis selanjutnya yang memungkinkan pengiriman secret hanya dapat mengirimkan secret pada node yang membutuhkan secret tersebut untuk membatasi adanya eksploitasi akses root pada node ini.
Selanjutnya
3.7.4 - Mengatur Akses Klaster Menggunakan Berkas kubeconfig
Gunakan berkas kubeconfig untuk mengatur informasi mengenai klaster, pengguna,
namespace, dan mekanisme autentikasi. Perintah kubectl
menggunakan berkas
kubeconfig untuk mencari informasi yang dibutuhkan untuk memilih klaster dan
berkomunikasi dengan API server dari suatu klaster.
kubeconfig
.
Secara default, kubectl
mencari berkas dengan nama config
pada direktori
$HOME/.kube
. Kamu bisa mengatur lokasi berkas kubeconfig dengan mengatur
nilai KUBECONFIG
pada variabel environment atau dengan mengatur menggunakan
tanda --kubeconfig
.
Instruksi langkah demi langkah untuk membuat dan menentukan berkas kubeconfig, bisa mengacu pada [Mengatur Akses Pada Beberapa Klaster] (/id/docs/tasks/access-application-cluster/configure-access-multiple-clusters).
Mendukung beberapa klaster, pengguna, dan mekanisme autentikasi
Misalkan kamu memiliki beberapa klaster, pengguna serta komponen dapat melakukan autentikasi dengan berbagai cara. Sebagai contoh:
- Kubelet yang berjalan dapat melakukan autentikasi dengan menggunakan sertifikat
- Pengguna bisa melakukan autentikasi dengan menggunakan token
- Administrator bisa memiliki beberapa sertifikat yang diberikan kepada pengguna individu.
Dengan berkas kubeconfig, kamu bisa mengatur klaster, pengguna, dan namespace. Kamu juga bisa menentukan konteks untuk mempercepat dan mempermudah perpindahan antara klaster dan namespace.
Konteks
Sebuah elemen konteks pada berkas kubeconfig digunakan untuk mengelompokkan
parameter akses dengan nama yang mudah. Setiap konteks akan memiliki 3 parameter:
klaster, pengguna, dan namespace. Secara default, perintah kubectl
menggunakan
parameter dari konteks yang aktif untuk berkomunikasi dengan klaster.
Untuk memilih konteks yang aktif, bisa menggunakan perintah berikut:
kubectl config use-context
Variabel environment KUBECONFIG
Variabel environment KUBECONFIG
berisikan beberapa berkas kubeconfig. Untuk
Linux dan Mac, beberapa berkas tersebut dipisahkan dengan tanda titik dua (:).
Untuk Windows, dipisahkan dengan menggunakan tanda titik koma (;). Variabel
environment KUBECONFIG
tidak diwajibkan untuk ada. Jika variabel environment
KUBECONFIG
tidak ada, maka kubectl
akan menggunakan berkas kubeconfig pada
$HOME/.kube/config
.
Jika variabel environment KUBECONFIG
ternyata ada, maka kubectl
akan menggunakan
konfigurasi yang merupakan hasil gabungan dari berkas-berkas yang terdapat pada
variabel environment KUBECONFIG
.
Menggabungkan berkas-berkas kubeconfig
Untuk melihat konfigurasimu, gunakan perintah berikut ini:
kubectl config view
Seperti yang dijelaskan sebelumnya, hasil perintah diatas bisa berasal dari sebuah berkas kubeconfig, atau bisa juga merupakan hasil gabungan dari beberapa berkas kubeconfig.
Berikut adalah aturan yang digunakan kubectl
ketika menggabungkan beberapa berkas
kubeconfig:
-
Jika menggunakan tanda
--kubeconfig
, maka akan menggunakan berkas yang ditentukan. Tidak digabungkan. Hanya 1 tanda--kubeconfig
yang diperbolehkan.Sebaliknya, jika variabel environment
KUBECONFIG
digunakan, maka akan menggunakan ini sebagai berkas-berkas yang akan digabungkan. Penggabungan berkas-berkas yang terdapat pada variabel environmentKUBECONFIG
akan mengikuti aturan sebagai berikut:- Mengabaikan berkas tanpa nama.
- Mengeluarkan pesan kesalahan untuk berkas dengan isi yang tidak dapat dideserialisasi.
- Berkas pertama yang menentukan nilai atau key pada map maka akan digunakan pada map tersebut.
- Tidak pernah mengubah nilai atau key dari suatu map.
Contoh: Pertahankan konteks pada berkas pertama yang mengatur
current-context
. Contoh: Jika terdapat dua berkas yang menentukan nilaired-user
, maka hanya gunakan nilaired-user
dari berkas pertama. Meskipun berkas kedua tidak memiliki entri yang bertentangan padared-user
, abaikan mereka.
Beberapa contoh pengaturan variabel environment
KUBECONFIG
, bisa melihat pada pengaturan vaiabel environment KUBECONFIG.Sebaliknya, bisa menggunakan berkas kubeconfig default,
$HOME/.kube/config
, tanpa melakukan penggabungan. -
Konteks ditentukan oleh yang pertama sesuai dari pilihan berikut:
- Menggunakan tanda
--context
pada perintah - Menggunakan nilai
current-context
dari hasil gabungan berkas kubeconfig.
Konteks yang kosong masih diperbolehkan pada tahap ini.
- Menggunakan tanda
-
Menentukan klaster dan pengguna. Pada tahap ini, mungkin akan ada atau tidak ada konteks. Menentukan klaster dan pengguna berdasarkan yang pertama sesuai dengan pilihan berikut, yang mana akan dijalankan dua kali: sekali untuk pengguna dan sekali untuk klaster:
- Jika ada, maka gunakan tanda pada perintah:
--user
atau--cluster
. - Jika konteks tidak kosong, maka pengguna dan klaster didapat dari konteks.
Pengguna dan klaster masih diperbolehkan kosong pada tahap ini.
- Jika ada, maka gunakan tanda pada perintah:
-
Menentukan informasi klaster sebenarnya yang akan digunakan. Pada tahap ini, mungkin akan ada atau tidak ada informasi klaster. Membentuk informasi klaster berdasarkan urutan berikut dan yang pertama sesuai akan digunakan:
- Jika ada, maka gunakan tanda pada perintah:
--server
,--certificate-authority
,--insecure-skip-tls-verify
. - Jika terdapat atribut informasi klaster dari hasil gabungan berkas kubeconfig, maka gunakan itu.
- Jika tidak terdapat informasi mengenai lokasi server, maka dianggap gagal.
- Jika ada, maka gunakan tanda pada perintah:
-
Menentukan informasi pengguna sebenarnya yang akan digunakan. Membentuk informasi pengguna dengan aturan yang sama dengan pembentukan informasi klaster, namun hanya diperbolehkan ada satu teknik autentikasi untuk setiap pengguna:
- Jika ada, gunakan tanda pada perintah:
--client-certificate
,--client-key
,--username
,--password
,--token
. - Menggunakan field
user
dari hasil gabungan berkas kubeconfig. - Jika terdapat dua teknik yang bertentangan, maka dianggap gagal.
- Jika ada, gunakan tanda pada perintah:
-
Untuk setiap informasi yang masih belum terisi, akan menggunakan nilai
default
dan kemungkinan akan meminta informasi autentikasi.
Referensi berkas
Referensi file dan path pada berkas kubeconfig adalah bernilai relatif terhadap
lokasi dari berkas kubeconfig.
Referensi file pada perintah adalah relatif terhadap direktori kerja saat ini.
Dalam $HOME/.kube/config
, relative path akan disimpan secara relatif, dan
absolute path akan disimpan secara mutlak.
Selanjutnya
3.7.5 - Prioritas dan Pemindahan Pod
Kubernetes 1.14 [stable]
Pod dapat memiliki priority (prioritas). Priority mengindikasikan lebih penting atau tidaknya sebuah Pod dibandingkan dengan Pod-pod lainnya. Jika sebuah Pod tidak dapat dijadwalkan (tertunda/pending), penjadwal akan mencoba untuk melakukan preemption/pemindahan (mengusir/evict) Pod-pod dengan prioritas lebih rendah agar penjadwalan Pod yang tertunda sebelumnya dapat dilakukan.
Pada Kubernetes 1.9 dan sesudahnya, Priority juga memengaruhi urutan penjadwalan Pod-pod dan urutan pengusiran Pod-pod dari Node pada kasus kehabisan sumber daya.
Priority dan Pemindahan Pod lulus menjadi beta pada Kubernetes 1.11 dan menjadi GA (Generally Available) pada Kubernetes 1.14. Mereka telah dihidupkan secara bawaan sejak versi 1.11.
Pada versi-versi Kubernetes di mana Priority dan pemindahan Pod masih berada pada tingkat fitur alpha, kamu harus menghidupkannya secara eksplisit. Untuk menggunakan fitur-fitur pada versi-versi lama Kubernetes, ikuti petunjuk di dokumentasi versi Kubernetes kamu, melalui arsip versi dokumentasi untuk versi Kubernetes kamu.
Versi Kubernetes | Keadaan Priority and Pemindahan | Dihidupkan secara Bawaan |
---|---|---|
1.8 | alpha | tidak |
1.9 | alpha | tidak |
1.10 | alpha | tidak |
1.11 | beta | ya |
1.14 | stable | ya |
Bagaimana cara menggunakan Priority dan pemindahan Pod
Untuk menggunakan Priority dan pemindahan Pod pada Kubernetes 1.11 dan sesudahnya, ikuti langkah-langkah berikut:
-
Tambahkan satu atau lebih PriorityClass.
-
Buat Pod-pod dengan
priorityClassName
disetel menjadi salah satu dari PriorityClass yang ditambahkan. Tentu saja kamu tidak perlu membuat Pod-pod tersebut secara langsung; Biasanya kamu akan menambahkanpriorityClassName
padatemplate
Pod dari sebuah objek kumpulan seperti sebuah Deployment.
Teruslah membaca untuk lebih banyak informasi mengenai langkah-langkah tersebut.
Jika kamu mencoba fitur ini dan memutuskan untuk mematikannya, kamu harus menghapus command-line flag PodPriority atau menyetelnya menjadi false
, kemudian melakukan pengulangan kembali terhadap API Server dan Scheduler. Setelah fitur ini dimatikan, Pod-pod yang sudah ada tetap akan memiliki kolom priority mereka, tetapi pemindahan Pod akan dimatikan, dan kolom-kolom priority tersebut diabaikan. Jika fitur tersebut telah dimatikan, kamu tidak dapat menyetel kolom priorityClassName
pada Pod-pod baru.
Cara mematikan pemindahan Pod
NonPreemptingPriority
diaktifkan, PriorityClass memiliki pilihan untuk menyetel preemptionPolicy: Never
.
Hal ini akan mencegah Pod-pod dari PriorityClass tersebut untuk memicu pemindahan Pod-pod lainnya.
Pada Kubernetes 1.11 dan sesudahnya, pemindahan Pod dikontrol oleh sebuah flag kube-scheduler yaitu disablePreemption
, yang disetel menjadi false
secara bawaan. Jika kamu ingin mematikan pemindahan Pod meskipun ada catatan di atas, kamu dapat menyetel disablePreemption
menjadi true
.
Opsi ini hanya tersedia pada (berkas) konfigurasi komponen saja, dan tidak tersedia pada cara lama melalui command line options. Berikut contoh konfigurasi komponen untuk mematikan pemindahan (preemption) Pod:
apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
algorithmSource:
provider: DefaultProvider
...
disablePreemption: true
PriorityClass
Sebuah PriorityClass adalah sebuah objek tanpa Namespace yang mendefinisikan pemetaan dari sebuah nama kelas prioritas menjadi nilai integer dari prioritas tersebut. Nama tersebut dirinci pada kolom name
dari metadata
objek PriorityClass tersebut. Nilainya dirinci pada kolom value
yang diperlukan. Semakin tinggi nilainya, maka semakin tinggi juga prioritasnya.
Sebuah objek PriorityClass dapat memiliki nilai integer 32-bit apa pun yang kurang dari atau sama dengan 1 miliar. Angka-angka yang lebih besar dicadangkan untuk Pod-pod pada sistem yang sangat penting yang secara normal sebaiknya tidak dipindahkan atau diusir. Seorang admin klaster sebaiknya membuat sebuah objek PriorityClass untuk setiap pemetaan seperti ini yang ia inginkan.
PriorityClass juga memiliki dua kolom opsional: globalDefault
dan description
. Kolom globalDefault
mengindikasikan bahwa nilai PriorityClass ini sebaiknya digunakan tanpa sebuah priorityClassName
. Hanya sebuah PriorityClass dengan globalDefault
disetel menjadi true
dapat berada pada sistem/klaster. Jika tidak ada PriorityClass dengan globalDefault
yang telah disetel, prioritas Pod-pod tanpa priorityClassName
adalah nol.
Kolom description
adalah string yang sembarang. Kolom ini diperuntukkan untuk memberitahukan pengguna-pengguna klaster kapan mereka harus menggunakan PriorityClass ini.
Catatan mengenai PodPriority dan Klaster-klaster yang sudah ada
-
Jika kamu meningkatkan versi klaster kamu dan menghidupkan fitur ini, prioritas Pod-pod kamu yang sudah ada akan secara efektif menjadi nol.
-
Penambahan dari sebuah PriorityClass dengan
globalDefault
yang disetel menjaditrue
tidak mengubah prioritas-prioritas Pod-pod yang sudah ada. Nilai dari PriorityClass semacam ini digunakan hanya untuk Pod-pod yang dibuat setelah PriorityClass tersebut ditambahkan. -
Jika kamu menghapus sebuah PriorityClass, Pod-pod yang sudah ada yang menggunakan nama dari PriorityClass yang dihapus tersebut tidak akan berubah, tetapi kamu tidak dapat membuat lebih banyak Pod yang menggunakan nama dari PriorityClass yang telah dihapus tersebut.
Contoh PriorityClass
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "Kelas prioritas ini sebaiknya hanya digunakan untuk Pod-pod layanan XYZ saja."
PriorityClass yang Non-preempting (alpha)
Kubernetes 1.15 menambahkan kolom PreemptionPolicy
sebagai sebuah fitur alpha. Fitur ini dimatikan secara bawaan pada 1.15, dan membutuhkan diaktifkannya feature gate NonPreemptingPriority
.
Pod-pod dengan PreemptionPolicy: Never
akan ditaruh pada antrean penjadwalkan mendahului Pod-pod dengan prioritas rendah, tetapi mereka tidak dapat memicu pemindahan Pod-pod lainnya (disebut juga Pod yang non-preempting).
Sebuah Pod yang non-preempting yang sedang menunggu untuk dijadwalkan akan tetap berada pada antrean penjadwalan, hingga sumber daya yang cukup tersedia, dan ia dapat dijadwalkan. Pod yang non-preempting, seperti Pod-pod lainnya, tunduk kepada back-off dari Scheduler. Hal ini berarti bahwa jika Scheduler mencoba untuk menjadwalkan Pod-pod ini dan mereka tidak dapat dijadwalkan, mereka akan dicoba kembali dengan frekuensi (percobaan) yang lebih rendah, memungkinkan Pod-pod lain dengan prioritas yang lebih rendah untuk dijadwalkan sebelum mereka dijadwalkan.
Pod yang non-preempting tetap dapat dipicu untuk dipindahkan oleh Pod lainnya yang memiliki prioritas yang lebih tinggi.
PreemptionPolicy
secara bawaan nilainya PreemptionLowerPriority
, yang memungkinkan Pod-pod dengan PriorityClass tersebut untuk memicu pemindahan Pod-pod dengan prioritas lebih rendah (sama seperti sifat bawaan). Jika PreemptionPolicy
disetel menjadi Never
, Pod-pod pada PriorityClass tersebut akan menjadi Pod yang non-preempting.
Sebuah contoh kasus misalnya pada beban kerja data science.
Seorang pengguna dapat memasukkan sebuah beban kerja yang mereka ingin prioritaskan di atas beban kerja lainnya, tetapi tidak ingin menghapus beban kerja yang sudah ada melalui pemicuan pemindahan Pod-pod yang sedang berjalan.
Beban kerja prioritas tinggi dengan PreemptionPolicy: Never
akan dijadwalkan mendahului Pod-pod lainnya yang berada dalam antrean, segera setelah sumber daya klaster "secara alami" menjadi cukup.
Contoh PriorityClass yang Non-preempting
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority-nonpreempting
value: 1000000
preemptionPolicy: Never
globalDefault: false
description: "Kelas prioritas ini tidak akan memicu pemindahan Pod-pod lainnya."
Prioritas Pod
Setelah kamu memiliki satu atau lebih PriorityClass, kamu dapat membuat Pod-pod yang merinci satu dari nama-nama PriorityClass tersebut pada spesifikasi mereka. Admission Controller prioritas menggunakan kolom priorityClassName
dan mengumpulkan nilai integer dari prioritasnya. Jika PriorityClass-nya tidak ditemukan, maka Pod tersebut akan ditolak.
YAML berikut adalah contoh sebuah konfigurasi Pod yang menggunakan PriorityClass yang telah dibuat pada contoh sebelumnya. Admission Controller prioritas akan memeriksa spesifikasi tersebut dan memetakan prioritas Pod tersebut menjadi nilai 1000000.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: high-priority
Efek prioritas Pod terhadap urutan penjadwalan
Pada Kubernetes 1.9 dan sesudahnya, saat prioritas Pod dihidupkan, Scheduler mengurutkan Pod-pod yang tertunda berdasarkan prioritas mereka dan sebuah Pod yang tertunda diletakkan mendahului Pod-pod tertunda lainnya yang memiliki prioritas yang lebih rendah pada antrean penjadwalan. Sebagai hasilnya, Pod dengan prioritas lebih tinggi dapat dijadwalkan lebih awal daripada Pod-pod dengan prioritas yang lebih rendah jika syarat penjadwalan terpenuhi. Jika Pod ini tidak dapat dijadwalkan, Scheduler akan melewatkannya dan mencoba untuk menjadwalkan Pod-pod lain dengan prioritas yang lebih rendah.
Pemindahan Pod
Saat Pod-pod dibuat, mereka masuk ke sebuah antrean dan menunggu untuk dijadwalkan. Scheduler memilih sebuah Pod dari antrean dan mencoba untuk menjadwalkannya pada sebuah Node. Jika tidak ditemukan Node yang memenuhi semua kebutuhan Pod tersebut, logika program pemindahan Pod dipicu untuk Pod yang tertunda tersebut. Kita akan menyebut Pod tertunda tersebut dengan P. Logika program pemindahan Pod mencoba untuk menemukan sebuah Node di mana penghapusan dari satu atau lebih Pod dengan prioritas yang lebih rendah daripada P dapat memungkinkan P untuk dijadwalkan pada Node tersebut. Jika Node tersebut ditemukan, satu atau lebih Pod dengan prioritas lebih rendah akan dipindahkan dari Node tersebut. Setelah Pod-pod tersebut dihapus, P dapat dijadwalkan pada Node tersebut.
Informasi yang diekspos pengguna
Saat Pod P memicu pemindahan satu atau lebih Pod pada Node N, kolom nominatedNodeName
pada status Pod P disetel menjadi nama dari node N. Kolom ini membantu Scheduler untuk melacak sumber daya yang dicadangkan untuk Pod P dan juga memberikan informasi mengenai pemindahan Pod pada klaster untuk pengguna-pengguna.
Harap catat bahwa Pod P tidak harus dijadwalkan pada "nominated Node" (Node yang dicalonkan) tersebut. Setelah Pod-pod yang terpilih telah dipindahkan, mereka akan mendapatkan periode penghentian secara sopan (graceful) mereka. Jika Node lain menjadi tersedia saat Scheduler sedang menunggu penghentian Pod-pod yang terpilih untuk dipindahkan, Scheduler akan menggunakan Node lain tersebut untuk menjadwalkan Pod P. Sebagai hasilnya nominatedNodeName
dan nodeName
dari spesifikasi Pod belum tentu selalu sama. Juga, jika Scheduler memindahkan Pod-pod pada Node N, tapi kemudian sebuah Pod lain dengan prioritas lebih tinggi daripada Pod P tiba, Scheduler boleh memberikan Node N kepada Pod dengan prioritas lebih tinggi tersebut. Pada kasus demikian, Scheduler menghapus nominatedPodName
dari Pod P. Dengan melakukan ini, Scheduler membuat Pod P berhak untuk memicu pemindahan Pod-pod lain pada Node lain.
Batasan-batasan pemindahan Pod
Penghentian secara sopan dari korban-korban pemindahan Pod
Saat Pod-pod dipindahkan, korban-korbannya mendapatkan periode penghentian secara sopan. Mereka memiliki waktu sebanyak itu untuk menyelesaikan pekerjaan merekan dan berhenti. Jika mereka tidak menyelesaikannya sebelum waktu tersebut, mereka akan dihentikan secara paksa. Periode penghentian secara sopan ini membuat sebuah jarak waktu antara saat di mana Scheduler memindahkan Pod-pod dengan waktu saat Pod yang tertunda tersebut (P) dapat dijadwalkan pada Node tersebut (N). Sementara itu, Scheduler akan terus menjadwalkan Pod-pod lain yang tertunda. Oleh karena itu, biasanya ada jarak waktu antara titik di mana Scheduler memindahkan korban-korban dan titik saat Pod P dijadwalkan. Untuk meminimalkan jarak waktu ini, kamu dapat menyetel periode penghentian secara sopan dari Pod-pod dengan prioritas lebih rendah menjadi nol atau sebuah angka yang kecil.
PodDisruptionBudget didukung, tapi tidak dijamin!
Sebuah Pod Disruption Budget (PDB) memungkinkan pemilik-pemilik aplikasi untuk membatasi jumlah Pod-pod dari sebuah aplikasi yang direplikasi yang mati secara bersamaan dikarenakan disrupsi yang disengaja. Kubernetes 1.9 mendukung PDB saat memindahkan Pod-pod, tetapi penghormatan terhadap PDB ini bersifat "usaha terbaik" (best-effort). Scheduler akan mencoba mencari korban-korban yang PDB-nya tidak dilanggar oleh pemindahan, tetapi jika tidak ada korban yang ditemukan, pemindahan akan tetap terjadi, dan Pod-pod dengan prioritas lebih rendah akan dihapus/dipindahkan meskipun PDB mereka dilanggar.
Afinitas antar-Pod pada Pod-pod dengan prioritas lebih rendah
Sebuah Node akan dipertimbangkan untuk pemindahan Pod hanya jika jawaban pertanyaan berikut adalah "ya": "Jika semua Pod-pod dengan prioritas lebih rendah dari Pod yang tertunda dipindahkan dari Node, dapatkan Pod yang tertunda tersebut dijadwalkan (secara sukses) ke Node tersebut?"
Jika sebuah Pod yang tertunda memiliki afinitas antar-Pod terhadap satu atau lebih dari Pod-pod dengan prioritas lebih rendah pada Node tersebut, maka aturan afinitas antar-Pod tersebut tidak dapat terpenuhi tanpa hadirnya Pod-pod dengan prioritas lebih rendah tersebut. Pada kasus ini, Scheduler tidak melakukan pemindahan terhadap Pod-pod manapun pada Node tersebut. Sebagai gantinya, ia mencari Node lainnya. Scheduler mungkin mendapatkan Node yang cocok atau tidak. Tidak ada jaminan bahwa Pod yang tertunda tersebut dapat dijadwalkan.
Solusi yang direkomendasikan untuk masalah ini adalah dengan cara membuat afinitas antar-Pod hanya terhadap Pod-pod dengan prioritas yang sama atau lebih tinggi.
Pemindahan Pod antar Node
Misalnya sebuah Node N sedang dipertimbangkan untuk pemindahan Pod sehingga sebuah Pod P yang tertunda dapat dijadwalkan pada N. P mungkin menjadi layak untuk N hanya jika sebuah Pod pada Node lain dipindahkan. Berikut sebuah contoh:
- Pod P dipertimbangkan untuk Node N.
- Pod Q sedang berjalan pada Node lain pada Zona yang sama dengan Node N.
- Pod P memiliki anti-afinitas yang berlaku pada seluruh Zona terhadap Pod Q (
topologyKey: topology.kubernetes.io/zone
). - Tidak ada kasus anti-afinitas lain antara Pod P dengan Pod-pod lainnya pada Zona tersebut.
- Untuk dapat menjadwalkan Pod P pada Node N, Pod Q dapat dipindahkan, tetapi Scheduler tidak melakukan pemindahan Pod antar Node. Jadi, Pod P akan dianggap tidak dapat dijadwalkan pada Node N.
Jika Pod Q dihapus dari Node-nya, pelanggaran terhadap anti-afinitas Pod tersebut akan hilang, dan Pod P dapat dijadwalkan pada Node N.
Kita mungkin mempertimbangkan untuk menambahkan pemindahan Pod antar Node pada versi-versi yang akan datang jika ada permintaan yang cukup dari pengguna, dan kami menemukan algoritma dengan kinerja yang layak.
Memecahkan masalah pada Prioritas dan Pemindahan Pod
Prioritas dan Pemindahan Pod adalah sebuah fitur besar yang berpotensi dapat mengganggu penjadwalan Pod jika fitur ini memiliki kesalahan (bug).
Masalah yang berpotensi diakibatkan oleh Prioritas dan Pemindahan Pod
Berikut adalah beberapa masalah yang dapat diakibatkan oleh kesalahan-kesalahan pada implementasi fitur ini. Daftar ini tidak lengkap.
Pod-pod dipindahkan secara tidak perlu
Pemindahan Pod menghapus Pod-pod yang sudah ada dari sebuah klaster yang sedang mengalami kekurangan sumber daya untuk menyediakan ruangan untuk Pod-pod tertunda yang memiliki prioritas yang lebih tinggi. Jika seorang pengguna memberikan prioritas-prioritas tinggi untuk Pod-pod tertentu dengan tidak semestinya (karena kesalahan), Pod-pod prioritas tinggi yang tidak disengaja tersebut dapat mengakibatkan pemindahan Pod-pod pada klaster tersebut. Seperti disebutkan di atas, prioritas Pod dispesifikasikan dengan menyetel kolom priorityClassName
dari podSpec
. Nilai integer dari prioritas tersebut kemudian dipetakan dan diisi pada kolom priority
dari podSpec
.
Untuk menyelesaikan masalah tersebut, priorityClassName
dari Pod-pod tersebut harus diubah untuk menggunakan kelas dengan prioritas yang lebih rendah, atau dibiarkan kosong saja. Kolom priorityClassName
yang kosong dipetakan menjadi nol secara bawaan.
Saat sebuah Pod dipindahkan, akan ada Event yang direkam untuk Pod yang dipindahkan tersebut. Pemindahan seharusnya hanya terjadi saat sebuah klaster tidak memiliki sumber daya yang cukup untuk sebuah Pod. Pada kasus seperti ini, pemindahan terjadi hanya saat prioritas dari Pod yang tertunda tersebut lebih tinggi daripada Pod-pod korban. Pemindahan tidak boleh terjadi saat tidak ada Pod yang tertunda (preemptor), atau saat Pod-pod yang tertunda memiliki prioritas yang sama atau lebih rendah dari korban-korbannya. Jika pemindahan terjadi pada skenario demikian, mohon daftarkan sebuah Issue.
Pod-pod dipindahkan, tetapi preemptor tidak dijadwalkan
Saat Pod-pod dijadwalkan, mereka menerima periode penghentian secara sopan mereka, yang secara bawaan bernilai 30 detik, tetapi dapat bernilai apa pun sesuai dengan yang disetel pada PodSpec. Jika Pod-pod korban tidak berhenti sebelum periode ini, mereka akan dihentikan secara paksa. Saat semua korban telah pergi, Pod preemptor dapat dijadwalkan.
Saat Pod preemptor sedang menunggu korban-korban dipindahkan, sebuah Pod dengan prioritas lebih tinggi boleh dibuat jika muat pada Node yang sama. Pada kasus ini, Scheduler akan menjadwalkan Pod dengan prioritas lebih tinggi tersebut alih-alih menjadwalkan Pod preemptor.
Dalam ketidakhadiran Pod dengan prioritas lebih tinggi tersebut, kita mengharapkan Pod preemptor dijadwalkan setelah periode penghentian secara sopan korban-korbannya telah berakhir.
Pod-pod dengan prioritas lebih tinggi dipindahkan karena Pod-pod dengan prioritas lebih rendah
Saat Scheduler mencoba mencari Node-node yang dapat menjalankan sebuah Pod yang tertunda, dan tidak ada Node yang ditemukan, ia akan mencoba untuk memindahkan Pod-pod dengan prioritas lebih rendah dari salah satu Node untuk menyediakan ruangan untuk Pod yang tertunda tersebut. Jika sebuah Node dengan Pod-pod dengan prioritas lebih rendah tidak layak untuk menjalankan Pod yang tertunda tersebut, Scheduler mungkin memilih Node lain dengan Pod yang memiliki prioritas lebih tinggi (dibandingkan dengan Pod-pod pada Node lain tadi) untuk dipindahkan. Korban-korban tersebut harus tetap memiliki prioritas yang lebih rendah dari Pod preemptor.
Saat ada beberapa Node yang tersedia untuk pemindahan, Scheduler mencoba untuk memilih Node dengan kumpulan Pod yang memiliki prioritas paling rendah. Namun, jika Pod-pod tersebut memiliki PodDisruptionBudget yang akan dilanggar apabila mereka dipindahkan, maka Scheduler akan memilih Node lain dengan Pod-pod yang memiliki prioritas lebih tinggi.
Saat ada beberapa Node tersedia untuk pemindahan dan tidak ada satupun skenario di atas yang berlaku, kita mengharapkan Scheduler memilih Node dengan prioritas paling rendah. Apabila hal tersebut tidak terjadi, hal ini mungkin menunjukkan bahwa terdapat kesalahan pada Scheduler.
Interaksi-interaksi prioritas Pod dan QoS
Prioritas Pod dan QoS adalah dua fitur terpisah dengan interaksi yang sedikit dan tidak ada batasan bawaan terhadap penyetelan prioritas Pod berdasarkan kelas QoS-nya. Logika program pemindahan Scheduler tidak mempertimbangkan QoS saat memilih sasaran-sasaran pemindahan. Pemindahan mempertimbangkan prioritas Pod dan mencoba memilih kumpulan sasaran dengan prioritas terendah. Pod-pod dengan prioritas lebih tinggi dipertimbangkan untuk pemindahan hanya jika penghapusan Pod-pod dengan prioritas terendah tidak cukup untuk memungkinkan Scheduler untuk menjadwalkan Pod preemptor, atau jika Pod-pod dengan prioritas terendah tersebut dilindungi oleh PodDisruptionBudget
.
Komponen satu-satunya yang mempertimbangkan baik QoS dan prioritas Pod adalah pengusiran oleh Kubelet karena kehabisan sumber daya.
Kubelet menggolongkan Pod-pod untuk pengusiran pertama-tama berdasarkan apakah penggunaan sumber daya mereka melebihi requests
mereka atau tidak, kemudian berdasarkan Priority, dan kemudian berdasarkan penggunaan sumber daya yang terbatas tersebut relatif terhadap requests
dari Pod-pod tersebut.
Lihat Mengusir Pod-pod pengguna untuk lebih detail. Pengusiran oleh Kubelet karena kehabisan sumber daya tidak mengusir Pod-pod yang memiliki penggunaan sumber daya yang tidak melebihi requests
mereka. Jika sebuah Pod dengan prioritas lebih rendah tidak melebihi requests
-nya, ia tidak akan diusir. Pod lain dengan prioritas lebih tinggi yang melebihi requests
-nya boleh diusir.
3.8 - Keamanan
3.8.1 - Ikhtisar Keamanan Cloud Native
Keamanan Kubernetes (dan keamanan secara umum) adalah sebuah topik sangat luas yang memiliki banyak bagian yang sangat berkaitan satu sama lain. Pada masa sekarang ini di mana perangkat lunak open source telah diintegrasi ke dalam banyak sistem yang membantu berjalannya aplikasi web, ada beberapa konsep menyeluruh yang dapat membantu intuisimu untuk berpikir tentang konsep keamanan secara menyeluruh. Panduan ini akan mendefinisikan sebuah cara/model berpikir untuk beberapa konsep umum mengenai Keamanan Cloud Native. Cara berpikir ini sepenuhnya subjektif dan kamu sebaiknya hanya menggunakannya apabila ini membantumu berpikir tentang di mana harus mengamankan stack perangkat lunakmu.
4C pada Keamanan Cloud Native
Mari memulainya dengan sebuah diagram yang dapat membantumu mengerti bagaimana berpikir tentang keamanan dalam bentuk beberapa lapisan.
Seperti yang dapat kamu lihat dari gambar di atas, setiap dari 4C tersebut bergantung pada keamanan dari kotak yang lebih besar di mana mereka berada. Hampir tidak mungkin untuk mengamankan sistem terhadap standar-standar keamanan yang buruk pada Cloud, Container, dan Code hanya dengan menangani keamanan pada lapisan kode. Akan tetapi, apabila semua area tersebut ditangani dengan baik, maka menambahkan keamanan ke dalam kode kamu akan memperkuat landasan yang sudah kuat. Area-area yang menjadi perhatian ini akan dideskripsikan lebih mendalam di bawah.
Cloud
Dalam banyak hal, Cloud (atau server-server co-located, atau pusat data/data center korporat) adalah trusted computing base (basis komputasi yang dipercaya) dari sebuah klaster Kubernetes. Jika komponen-komponen tersebut rentan secara keamanan (atau dikonfigurasi dengan cara yang rentan), maka sesungguhnya tidak ada cara untuk menjamin keamanan dari komponen-komponen apa pun yang dibangun di atas basis komputasi ini. Memberikan rekomendasi untuk keamanan cloud berada di luar lingkup panduan ini, karena setiap penyedia layanan cloud dan beban kerja pada dasarnya berbeda-beda. Berikut beberapa tautan menuju beberapa dokumentasi penyedia layanan cloud yang populer untuk keamanan maupun untuk memberikan panduan umum untuk mengamankan infrastruktur yang menjadi basis sebuah klaster Kubernetes.
Tabel Keamanan Penyedia Layanan Cloud
IaaS Provider | Link |
---|---|
Alibaba Cloud | https://www.alibabacloud.com/trust-center |
Amazon Web Services | https://aws.amazon.com/security/ |
Google Cloud Platform | https://cloud.google.com/security/ |
IBM Cloud | https://www.ibm.com/cloud/security |
Microsoft Azure | https://docs.microsoft.com/en-us/azure/security/azure-security |
Oracle Cloud Infrastructure | https://www.oracle.com/security/ |
VMWare VSphere | https://www.vmware.com/security/hardening-guides.html |
Jika kamu mengoperasikan perangkat keras kamu sendiri, atau penyedia layanan cloud yang berbeda, kamu perlu merujuk pada dokumentasi penyedia layanan cloud yang kamu pakai untuk praktik keamanan terbaik.
Tabel Panduan Umum Infrastruktur
Area yang Menjadi Perhatian untuk Infrastruktur Kubernetes | Rekomendasi |
---|---|
Akses Jaringan terhadap API Server (Master-master) | Secara Ideal, semua akses terhadap Master-master Kubernetes tidak diizinkan secara publik pada internet, dan dikontrol oleh daftar kendali akses (network ACL) yang dibatasi untuk kumpulan alamat IP yang dibutuhkan untuk mengelola klaster. |
Akses Jaringan terhadap Node-node (Server-server Worker) | Node-node harus dikonfigurasikan untuk hanya menerima koneksi-koneksi (melalui daftar kendali akses) dari Master-master pada porta-porta (port) yang telah ditentukan, dan menerima koneksi-koneksi dari Service-service Kubernetes dengan tipe NodePort dan LoadBalancer. Apabila memungkinkan, Node-node tersebut sebaiknya tidak diekspos pada internet publik sama sekali. |
Akses Kubernetes terhadap API Penyedia Layanan Cloud | Setiap penyedia layanan cloud perlu memberikan kumpulan izin yang berbeda-beda untuk Master-master dan Node-node Kubernetes, sehingga rekomendasi ini sifatnya lebih umum. Praktik terbaiknya adalah untuk memberikan klaster akses terhadap penyedia layanan cloud yang mengikuti principle of least privilege (prinsip hak istimewa paling sedikit) untuk sumber daya yang klaster tersebut perlukan untuk dikelola. Sebuah contoh untuk Kops di AWS dapat ditemukan di sini: https://github.com/kubernetes/kops/blob/master/docs/iam_roles.md#iam-roles |
Akses terhadap etcd | Akses terhadap etcd (tempat penyimpanan data Kubernetes) harus dibatasi hanya untuk Master-master saja. Bergantung pada konfigurasimu, kamu sebaiknya juga mengusahakan koneksi etcd menggunakan TLS. Informasi lebih lanjut dapat ditemukan di sini: https://github.com/etcd-io/etcd/tree/master/Documentation#security |
Enkripsi etcd | Di mana pun kita dapat melakukannya, mengenkripsi semua data saat diam (at rest) pada semua drive, dan sejak etcd menyimpan keadaan seluruh klaster (termasuk Secret-secret), disk-nya sebaiknya kita enkripsi saat diam. |
Cluster
Bagian ini akan memberikan tautan-tautan untuk mengamankan beban-beban kerja di dalam Kubernetes. Ada dua area yang menjadi perhatian untuk mengamankan Kubernetes:
- Mengamankan komponen-komponen yang dapat dikonfigurasi yang membentuk klaster
- Mengamankan komponen-komponen yang dijalankan di dalam klaster
Komponen-komponen dari Cluster
Jika kamu ingin menjaga klastermu dari akses yang tidak disengaja atau yang bersifat serangan, dan mengadopsi praktik yang baik, baca dan ikutilah nasihat untuk mengamankan klastermu.
Komponen-komponen di dalam Cluster (aplikasimu)
Bergantung pada permukaan yang dapat diserang dari aplikasimu, kamu mungkin ingin berfokus pada aspek keamanan yang spesifik. Sebagai contoh, jika kamu menjalankan sebuah layanan (kita sebut Layanan A) yang kritikal di dalam rantai sumber daya lainnya dan sebuah beban kerja terpisah (kita sebut Layanan B) yang rentan terhadap serangan resource exhaustion, dengan tidak menyetel limit untuk sumber daya maka kamu juga menaruh risiko terhadap Layanan A. Berikut tabel tautan-tautan menuju hal-hal yang perlu diperhatikan untuk mengamankan beban-beban kerja yang berjalan di dalam Kubernetes.
Area yang Menjadi Perhatian untuk Keamanan Beban Kerja | Rekomendasi |
---|---|
Otorisasi RBAC (Akses terhadap API Kubernetes) | https://kubernetes.io/docs/reference/access-authn-authz/rbac/ |
Autentikasi | https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/ |
Manajemen Secret Aplikasi (dan mengenkripsi mereka di etcd) | https://kubernetes.io/docs/concepts/configuration/secret/ https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/ |
Pod Security Policy | https://kubernetes.io/docs/concepts/policy/pod-security-policy/ |
Quality of Service (dan manajemen sumber daya klaster) | https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/ |
Network Policy | https://kubernetes.io/docs/concepts/services-networking/network-policies/ |
TLS untuk Ingress Kubernetes | https://kubernetes.io/docs/concepts/services-networking/ingress/#tls |
Container
Untuk menjalankan perangkat lunak di dalam Kubernetes, perangkat lunak tersebut haruslah berada di dalam sebuah Container. Karenanya, ada beberapa pertimbangan keamanan yang harus diperhitungkan untuk mengambil manfaat dari fitur-fitur keamanan beban kerja Kubernetes. Keamanan Container berada di luar lingkup panduan ini, tetapi berikut disediakan sebuah tabel rekomendasi-rekomendasi umum dan tautan menuju eksplorasi lebih dalam pada topik ini.
Area yang Menjadi Perhatian untuk Container | Rekomendasi |
---|---|
Pemindaian Kerentanan Container dan Dependensi Keamanan OS | Sebagai bagian dari tahap membangun sebuah image atau dilakukan secara teratur, kamu sebaiknya memindai Container-container terhadap kerentanan yang telah diketahui dengan peralatan seperti CoreOS's Clair |
Penandatanganan Image dan Penegakan Aturan | Dua dari Proyek-proyek CNCF (TUF dan Notary) adalah alat-alat yang berguna untuk menandatangani image Container dan memelihara sistem kepercayaan untuk konten dari Container-container kamu. Jika kamu menggunakan Docker, ia dibangun di dalam Docker Engine sebagai Docker Content Trust. Pada bagian penegakan aturan, proyek Portieris dari IBM adalah sebuah alat yang berjalan sebagai sebuah Dynamic Admission Controller Kubernetes untuk memastikan bahwa image-image ditandatangani dengan tepat oleh Notary sebelum dimasukkan ke dalam Cluster. |
Larang pengguna-pengguna dengan hak istimewa | Saat membangun Container-container, rujuklah dokumentasimu untuk cara membuat pengguna-pengguna di dalam Container-container yang memiliki hak istimewa sistem operasi yang paling sedikit yang dibutuhkan untuk mencapai tujuan Container tersebut. |
Code
Akhirnya pada lapisan kode aplikasi, hal ini adalah satu dari permukaan-permukaan serangan utama yang paling dapat kamu kontrol. Hal ini juga berada di luar lingkup Kubernetes, tetapi berikut beberapa rekomendasi:
Tabel Panduan Umum Keamanan Kode
Area yang Menjadi Perhatian untuk Kode | Rekomendasi |
---|---|
Akses hanya melalui TLS | Jika kode kamu perlu berkomunikasi via TCP, idealnya ia melakukan TLS handshake dengan klien sebelumnya. Dengan pengecualian pada sedikit kasus, kelakuan secara bawaan sebaiknya adalah mengenkripsi semuanya (data) pada saat transit (encryption at transit). Lebih jauh lagi, bahkan "di belakang dinding api" di dalam VPC kita sebaiknya kita melakukan enkripsi lalu lintas jaringan di antara layanan-layanan. Hal ini dapat dilakukan melalui sebuah proses yang dikenal dengan mutual TLS atau mTLS yang melakukan verifikasi dua sisi terhadap komunikasi antara layanan-layanan yang memiliki sertifikat digital. Ada banyak alat-alat yang dapat digunakan untuk mencapai hal ini, seperti Linkerd dan Istio. |
Membatasi cakupan porta komunikasi | Rekomendasi ini sepertinya cukup jelas, tetapi di mana pun dapat dilakukan sebaiknya kamu hanya membuka porta-porta pada layananmu yang benar-benar diperlukan untuk komunikasi sistem atau pengambilan metrik. |
Keamanan Dependensi Pihak ke-3 | Karena aplikasi-aplikasi kita cenderung memiliki dependensi-dependensi di luar kode kita sendiri, merupakan praktik yang baik untuk memastikan hasil pemindaian rutin dependensi-dependensi kode kita masih aman tanpa CVE yang masih ada terhadap mereka. Setiap bahasa pemrograman memiliki alat untuk melakukan pemindaian ini secara otomatis. |
Analisis Statis Kode | Kebanyakan bahasa pemrograman menyediakan cara agar potongan kode dapat dianalisis terhadap praktik-praktik penulisan kode yang berpotensi tidak aman. Kapan pun dapat dilakukan, kamu sebaiknya melakukan pemeriksaan menggunakan peralatan otomatis yang dapat memindai kode terhadap kesalahan keamanan yang umum terjadi. Beberapa dari peralatan tersebut dapat ditemukan di sini: https://www.owasp.org/index.php/Source_Code_Analysis_Tools |
Serangan Pengamatan (probing) Dinamis | Ada sedikit peralatan otomatis yang dapat dijalankan terhadap layanan/aplikasi kamu untuk mencoba beberapa serangan yang terkenal dan umumnya memengaruhi layanan-layanan. Serangan-serangan tersebut termasuk SQL injection, CSRF, dan XSS. Satu dari alat analisis dinamis yang terkenal adalah OWASP Zed Attack Proxy https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project |
Otomasi yang Kokoh
Kebanyakan dari saran yang disebut di atas dapat diotomasi di dalam delivery pipeline kode kamu sebagai bagian dari rangkaian pemeriksaan keamanan. Untuk mempelajari lebih lanjut tentang pendekatan "Continuous Hacking" terhadap delivery perangkat lunak, artikel ini menyediakan lebih banyak detail.
Selanjutnya
- Pelajari tentang Network Policy untuk Pod
- Pelajari tentang mengamankan klaster kamu
- Pelajari tentang kontrol akses API
- Pelajari tentang enkripsi data saat transit for the control plane
- Pelajari tentang enkripsi data saat diam
- Pelajari tentang Secret (data sensitif) pada Kubernetes
3.9 - Penjadwalan dan Pengusiran
3.9.1 - Bin Packing Sumber Daya untuk Sumber Daya Tambahan
Kubernetes 1.16 [alpha]
Kube-scheduler dapat dikonfigurasikan untuk mengaktifkan pembungkusan rapat
(bin packing) sumber daya bersama dengan sumber daya tambahan melalui fungsi prioritas
RequestedToCapacityRatioResourceAllocation
. Fungsi-fungsi prioritas dapat digunakan
untuk menyempurnakan kube-scheduler sesuai dengan kebutuhan.
Mengaktifkan Bin Packing menggunakan RequestedToCapacityRatioResourceAllocation
Sebelum Kubernetes 1.15, kube-scheduler digunakan untuk memungkinkan mencetak
skor berdasarkan rasio permintaan terhadap kapasitas sumber daya utama seperti
CPU dan Memori. Kubernetes 1.16 menambahkan parameter baru ke fungsi prioritas
yang memungkinkan pengguna untuk menentukan sumber daya beserta dengan bobot
untuk setiap sumber daya untuk memberi nilai dari Node berdasarkan rasio
permintaan terhadap kapasitas. Hal ini memungkinkan pengguna untuk bin pack
sumber daya tambahan dengan menggunakan parameter yang sesuai untuk meningkatkan
pemanfaatan sumber daya yang langka dalam klaster yang besar. Perilaku
RequestedToCapacityRatioResourceAllocation
dari fungsi prioritas dapat
dikontrol melalui pilihan konfigurasi yang disebut RequestToCapacityRatioArguments
.
Argumen ini terdiri dari dua parameter yaitu shape
dan resources
. Shape
memungkinkan pengguna untuk menyempurnakan fungsi menjadi yang paling tidak
diminta atau paling banyak diminta berdasarkan nilai utilization
dan score
.
Sumber daya terdiri dari name
yang menentukan sumber daya mana yang dipertimbangkan
selama penilaian dan weight
yang menentukan bobot masing-masing sumber daya.
Di bawah ini adalah contoh konfigurasi yang menetapkan requestedToCapacityRatioArguments
pada perilaku bin packing untuk sumber daya tambahan intel.com/foo
dan intel.com/bar
{
"kind" : "Policy",
"apiVersion" : "v1",
...
"priorities" : [
...
{
"name": "RequestedToCapacityRatioPriority",
"weight": 2,
"argument": {
"requestedToCapacityRatioArguments": {
"shape": [
{"utilization": 0, "score": 0},
{"utilization": 100, "score": 10}
],
"resources": [
{"name": "intel.com/foo", "weight": 3},
{"name": "intel.com/bar", "weight": 5}
]
}
}
}
],
}
Fitur ini dinonaktifkan secara default
Tuning RequestedToCapacityRatioResourceAllocation Priority Function
shape
digunakan untuk menentukan perilaku dari fungsi RequestedToCapacityRatioPriority
.
{"utilization": 0, "score": 0},
{"utilization": 100, "score": 10}
Argumen di atas memberikan Node nilai 0 jika utilisasi 0% dan 10 untuk utilisasi 100%, yang kemudian mengaktfikan perilaku bin packing. Untuk mengaktifkan dari paling yang tidak diminta, nilainya harus dibalik sebagai berikut.
{"utilization": 0, "score": 100},
{"utilization": 100, "score": 0}
resources
adalah parameter opsional yang secara default diatur ke:
"resources": [
{"name": "CPU", "weight": 1},
{"name": "Memory", "weight": 1}
]
Ini dapat digunakan untuk menambahkan sumber daya tambahan sebagai berikut:
"resources": [
{"name": "intel.com/foo", "weight": 5},
{"name": "CPU", "weight": 3},
{"name": "Memory", "weight": 1}
]
Parameter weight
adalah opsional dan diatur ke 1 jika tidak ditentukan.
Selain itu, weight
tidak dapat diatur ke nilai negatif.
Bagaimana Fungsi Prioritas RequestedToCapacityRatioResourceAllocation Menilai Node
Bagian ini ditujukan bagi kamu yang ingin memahami secara detail internal dari fitur ini. Di bawah ini adalah contoh bagaimana nilai dari Node dihitung untuk satu kumpulan nilai yang diberikan.
Sumber daya yang diminta
intel.com/foo : 2
Memory: 256MB
CPU: 2
Bobot dari sumber daya
intel.com/foo : 5
Memory: 1
CPU: 3
FunctionShapePoint {{0, 0}, {100, 10}}
Spesifikasi dari Node 1
Tersedia:
intel.com/foo : 4
Memory : 1 GB
CPU: 8
Digunakan:
intel.com/foo: 1
Memory: 256MB
CPU: 1
Nilai Node:
intel.com/foo = resourceScoringFunction((2+1),4)
= (100 - ((4-3)*100/4)
= (100 - 25)
= 75
= rawScoringFunction(75)
= 7
Memory = resourceScoringFunction((256+256),1024)
= (100 -((1024-512)*100/1024))
= 50
= rawScoringFunction(50)
= 5
CPU = resourceScoringFunction((2+1),8)
= (100 -((8-3)*100/8))
= 37.5
= rawScoringFunction(37.5)
= 3
NodeScore = (7 * 5) + (5 * 1) + (3 * 3) / (5 + 1 + 3)
= 5
Spesifikasi dari Node 2
Tersedia:
intel.com/foo: 8
Memory: 1GB
CPU: 8
Digunakan:
intel.com/foo: 2
Memory: 512MB
CPU: 6
Nilai Node:
intel.com/foo = resourceScoringFunction((2+2),8)
= (100 - ((8-4)*100/8)
= (100 - 25)
= 50
= rawScoringFunction(50)
= 5
Memory = resourceScoringFunction((256+512),1024)
= (100 -((1024-768)*100/1024))
= 75
= rawScoringFunction(75)
= 7
CPU = resourceScoringFunction((2+6),8)
= (100 -((8-8)*100/8))
= 100
= rawScoringFunction(100)
= 10
NodeScore = (5 * 5) + (7 * 1) + (10 * 3) / (5 + 1 + 3)
= 7
3.9.2 - Overhead Pod
Kubernetes v1.16 [alpha]
Ketika kamu menjalankan Pod pada Node, Pod itu akan mengambil sejumlah sumber daya sistem. Sumber daya ini adalah tambahan terhadap sumber daya yang diperlukan untuk menjalankan Container di dalam Pod (overhead). Pod Overhead adalah fitur yang berfungsi untuk menghitung sumber daya digunakan oleh infrastruktur Pod selain permintaan dan limit Container.
Overhead Pod
Pada Kubernetes, Overhead Pod ditentukan pada saat admisi sesuai dengan Overhead yang ditentukan di dalam RuntimeClass milik Pod.
Ketika Overhead Pod diaktifkan, Overhead akan dipertimbangkan sebagai tambahan terhadap jumlah permintaan sumber daya Container saat menjadwalkan Pod. Begitu pula Kubelet, yang akan memasukkan Overhead Pod saat menentukan ukuran cgroup milik Pod, dan saat melakukan pemeringkatan pengusiran (eviction) Pod.
Yang perlu disiapkan
Kamu harus memastikan bahwa
feature gate PodOverhead
telah diaktifkan (secara bawaan dinonaktifkan)
di seluruh klaster kamu, yang berarti:
- Pada kube-scheduler
- Pada kube-apiserver
- Pada kubelet di setiap Node
- Pada peladen API khusus (custom) apa pun yang menggunakan feature gate
Selanjutnya
3.9.3 - Menetapkan Pod ke Node
Kamu dapat memaksa sebuah pod untuk hanya dapat berjalan pada node tertentu atau mengajukannya agar berjalan pada node tertentu. Ada beberapa cara untuk melakukan hal tersebut. Semua cara yang direkomendasikan adalah dengan menggunakan selector label untuk menetapkan pilihan yang kamu inginkan. Pada umumnya, pembatasan ini tidak dibutuhkan, sebagaimana scheduler akan melakukan penempatan yang proporsional dengan otomatis (seperti contohnya menyebar pod di node-node, tidak menempatkan pod pada node dengan sumber daya yang tidak memadai, dst.) tetapi ada keadaan-keadaan tertentu yang membuat kamu memiliki kendali lebih terhadap node yang menjadi tempat pod dijalankan, contohnya untuk memastikan pod dijalankan pada mesin yang telah terpasang SSD, atau untuk menempatkan pod-pod dari dua servis yang berbeda yang sering berkomunikasi bersamaan ke dalam zona ketersediaan yang sama.
Kamu dapat menemukan semua berkas untuk contoh-contoh berikut pada dokumentasi yang kami sediakan di sini
nodeSelector
Penggunaan nodeSelector
adalah cara pembatasan pemilihan node paling sederhana yang direkomendasikan. nodeSelector
adalah sebuah field pada PodSpec. nodeSelector
memerinci sebuah map berisi pasangan kunci-nilai. Agar pod dapat dijalankan pada sebuah node yang memenuhi syarat, node tersebut harus memiliki masing-masing dari pasangan kunci-nilai yang dinyatakan sebagai label (namun node juga dapat memiliki label tambahan diluar itu). Penggunaan paling umum adalah satu pasang kunci-nilai.
Mari kita telusuri contoh dari penggunaan nodeSelector
.
Langkah Nol: Prasyarat
Contoh ini mengasumsikan bahwa kamu memiliki pemahaman dasar tentang pod Kubernetes dan kamu telah membuat klaster Kubernetes.
Langkah Satu: Menyematkan label pada node
Jalankan kubectl get nodes
untuk mendapatkan nama dari node-node yang ada dalam klaster kamu. Temukan node yang akan kamu tambahkan label, kemudian jalankan perintah kubectl label nodes <node-name> <label-key>=<label-value>
untuk menambahkan label pada node yang telah kamu pilih. Sebagai contoh, jika nama node yang saya pilih adalah 'kubernetes-foo-node-1.c.a-robinson.internal' dan label yang ingin saya tambahkan adalah 'disktype=ssd', maka saya dapat menjalankan kubectl label nodes kubernetes-foo-node-1.c.a-robinson.internal disktype=ssd
.
Jika terjadi kegagalan dengan kesalahan perintah yang tidak valid ("invalid command"), kemungkinan besar kamu menggunakan kubectl dengan versi lebih lama yang tidak memiliki perintah label
. Dalam hal ini, lihat [versi sebelumnya] (https://github.com/kubernetes/kubernetes/blob/a053dbc313572ed60d89dae9821ecab8bfd676dc/examples/node-selection/README.md) dari petunjuk ini untuk instruksi tentang cara menetapkan label pada node.
Kamu dapat memastikan perintah telah berhasil dengan menjalankan ulang perintah kubectl get nodes --show-labels
and memeriksa bahwa node yang dipilih sekarang sudah memiliki label yang ditambahkan. Kamu juga dapat menggunakan kubectl describe node "nodename"
untuk melihat daftar lengkap label yang dimiliki sebuah node.
Langkah Dua: Menambahkan sebuah nodeSelector ke konfigurasi pod kamu
Ambil berkas konfigurasi pod manapun yang akan kamu jalankan, dan tambahkan sebuah bagian nodeSelector
pada berkas tersebut, seperti berikut. Sebagai contoh, jika berikut ini adalah konfigurasi pod saya:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
Kemudian tambahkan sebuah nodeSelector
seperti berikut:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
Ketika kamu menjalankan perintah kubectl apply -f https://k8s.io/examples/pods/pod-nginx.yaml
, pod tersebut akan dijadwalkan pada node yang memiliki label yang dirinci. Kamu dapat memastikan penambahan nodeSelector berhasil dengan menjalankan kubectl get pods -o wide
dan melihat "NODE" tempat Pod ditugaskan.
Selingan: label node built-in
Sebagai tambahan dari label yang kamu sematkan, node sudah terisi dengan satu set label standar. Pada Kubernetes v1.4 label tersebut adalah
kubernetes.io/hostname
failure-domain.beta.kubernetes.io/zone
failure-domain.beta.kubernetes.io/region
beta.kubernetes.io/instance-type
kubernetes.io/os
kubernetes.io/arch
kubernetes.io/hostname
bisa saja sama dengan nama node pada beberapa lingkungan dan berbeda pada lingkungan lain.
Isolasi/pembatasan Node
Menambahkan label pada objek node memungkinkan penargetan pod pada node atau grup node yang spesifik. Penambahan label ini dapat digunakan untuk memastikan pod yang spesifik hanya berjalan pada node dengan isolasi, keamanan, atau pengaturan tertentu. Saat menggunakan label untuk tujuan tersebut, memilih kunci label yang tidak bisa dimodifikasi oleh proses kubelet pada node sangat direkomendasikan. Hal ini mencegah node yang telah diubah untuk menggunakan kredensial kubelet-nya untuk mengatur label-label pada objek nodenya sediri, dan mempengaruhi scheduler untuk menjadwalkan workload ke node yang telah diubah tersebut.
Plugin penerimaan NodeRestriction
mencegah kubeletes untuk megatur atau mengubah label dengan awalan node-restriction.kubernetes.io/
.
Untuk memanfaatkan awalan label untuk isolasi node:
-
Pastikan kamu menggunakan authorizer node dan mengaktifkan [plugin admission NodeRestriction(/docs/reference/access-authn-authz/admission-controllers/#noderestriction).
-
Tambah label dengan awalan
node-restriction.kubernetes.io/
ke objek node kamu, dan gunakan label tersebut pada node selector kamu. Contohnya,example.com.node-restriction.kubernetes.io/fips=true
orexample.com.node-restriction.kubernetes.io/pci-dss=true
.
Afinitas dan anti-afinitas
_Field_ nodeSelector
menyediakan cara yang sangat sederhana untuk membatasi pod ke node dengan label-label tertentu. Fitur afinitas/anti-afinitas saat ini bersifat beta dan memperluas tipe pembatasan yang dapat kamu nyatakan. Peningkatan kunci dari fitur ini adalah
- Bahasa yang lebih ekspresif (tidak hanya "AND of exact match")
- Kamu dapat memberikan indikasi bahwa aturan yang dinyatakan bersifat rendah/preferensi dibanding dengan persyaratan mutlak sehingga jika scheduler tidak dapat memenuhinya, pod tetap akan dijadwalkan
- Kamu dapat membatasi dengan label pada pod-pod lain yang berjalan pada node (atau domain topological lain), daripada dengan label pada node itu sendiri, yang memungkinkan pengaturan tentang pod yang dapat dan tidak dapat dilokasikan bersama.
Fitur afinitas terdiri dari dua tipe afinitas yaitu "node afinitas" dan "inter-pod afinitas/anti-afinitas"
Node afinitas adalah seperti nodeSelector
yang telah ada (tetapi dengam dua kelebihan pertama yang terdaftar di atas), sementara inter-pod afinitas/anti-afinitas membatasi pada label pod daripada label node, seperti yang dijelaskan pada item ketiga pada daftar di atas, sebagai tambahan dari item pertama dan kedua.
Field nodeSelector
tetap berjalan seperti biasa, namun pada akhirnya akan ditinggalkan karena afinitas node dapat menyatakan semua yang nodeSelector
dapat nyatakan.
Afinitas node (fitur beta)
Afinitas node diperkenalkan sebagai fitur alfa pada Kubernetes 1.2.
Afinitas node secara konseptual mirip dengan nodeSelector
yang memungkinkan kamu untuk membatasi node yang memenuhi syarat untuk penjadwalan pod, berdasarkan label pada node.
Saat ini ada dia tipe afinitas node, yaitu requiredDuringSchedulingIgnoredDuringExecution
dan
preferredDuringSchedulingIgnoredDuringExecution
. Kamu dapat menganggap dua tipe ini sebagai "kuat" dan "lemah" secara berurutan, dalam arti tipe pertama menyatakan peraturan yang harus dipenuhi agar pod dapat dijadwalkan pada node (sama seperti nodeSelector
tetapi menggunakan sintaksis yang lebih ekpresif), sementara tipe kedua menyatakan preferensi yang akan dicoba dilaksanakan tetapi tidak akan dijamin oleh scheduler. Bagian "IgnoredDuringExecution" dari nama tipe ini berarti, mirip dengan cara kerja nodeSelector
, jika label pada node berubah pada runtime yang menyebabkan aturan afinitas pada pod tidak lagi terpenuhi, pod akan tetap berjalan pada node. Pada masa yang akan datang kami berencana menawarkan requiredDuringSchedulingRequiredDuringExecution
yang akan berjalan seperti requiredDuringSchedulingIgnoredDuringExecution
hanya saja tipe ini akan mengeluarkan pod dari node yang gagal untuk memenuhi persyaratan afinitas node pod.
Dengan denikian, contoh dari requiredDuringSchedulingIgnoredDuringExecution
adalah "hanya jalankan pod pada node dengan Intel CPU" dan contoh dari preferredDuringSchedulingIgnoredDuringExecution
adalah "coba jalankan set pod ini dalam zona ketersediaan XYZ, tetapi jika tidak memungkinkan, maka biarkan beberapa pod berjalan di tempat lain".
Afinitas node dinyatakan sebagai field nodeAffinity
dari field affinity
pada PodSpec.
Berikut ini contoh dari pod yang menggunakan afinitas node:
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0
Aturan afinitas node tersebut menyatakan pod hanya bisa ditugaskan pada node dengan label yang memiliki kunci kubernetes.io/e2e-az-name
dan bernilai e2e-az1
atau e2e-az2
. Selain itu, dari semua node yang memenuhi kriteria tersebut, mode dengan label dengan kunci another-node-label-key
and bernilai another-node-label-value
harus lebih diutamakan.
Kamu dapat meilhat operator In
digunakan dalam contoh berikut. Sitaksis afinitas node yang baru mendukung operator-operator berikut: In
, NotIn
, Exists
, DoesNotExist
, Gt
, Lt
. Kamu dapat menggunakan NotIn
dan DoesNotExist
untuk mewujudkan perilaku node anti-afinitas, atau menggunakan node taints untuk menolak pod dari node tertentu.
Jika kamu menyatakan nodeSelector
dan nodeAffinity
. keduanya harus dipenuhi agar pod dapat dijadwalkan pada node kandidat.
Jika kamu menyatakan beberapa nodeSelectorTerms
yang terkait dengan tipe nodeAffinity
, maka pod akan dijadwalkan pada node jika salah satu dari nodeSelectorTerms
dapat terpenuhi.
Jika kamu menyatakan beberapa matchExpressions
yang terkait dengan nodeSelectorTerms
, makan pod dapat dijadwalkan pada node hanya jika semua matchExpressions
dapat terpenuhi.
Jika kamu menghapus atau mengubah label pada node tempat pod dijadwalkan, pod tidak akan dihapus. Dengan kata lain, pemilihan afinitas hanya bekerja pada saat waktu penjadwalan pod.
Field weight
pada preferredDuringSchedulingIgnoredDuringExecution
berada pada rentang nilai 1-100. Untuk setiap node yang memenuhi semua persyaratan penjadwalan (permintaan sumber daya, pernyataan afinitas RequiredDuringScheduling, dll.), scheduler akan menghitung nilai jumlah dengan melakukan iterasi pada elemen-elemen dari field ini dan menambah "bobot" pada jumlah jika node cocok dengan MatchExpressions yang sesuai. Nilai ini kemudian digabungkan dengan nilai dari fungsi prioritas lain untuk node. Node dengan nilai tertinggi adalah node lebih diutamakan.
Untuk informasi lebih lanjut tentang afinitas node kamu dapat melihat design doc.
Afinitas and anti-afinitas antar pod (fitur beta)
Afinitas and anti-afinitas antar pod diperkenalkan pada Kubernetes 1.4. Afinitas and anti-afinitas antar pod memungkinkan kamu untuk membatasi node yang memenuhi syarat untuk penjadwalan pod berdasarkan label-label pada pod yang sudah berjalan pada node daripada berdasarkan label-label pada node. Aturan tersebut berbentuk "pod ini harus (atau, dalam kasus
anti-afinitas, tidak boleh) berjalan dalam X jika X itu sudah menjalankan satu atau lebih pod yang memenuhi aturan Y". Y dinyatakan sebagai sebuah LabelSelector dengan daftar namespace terkait; tidak seperti node, karena pod are namespaced (maka dari itu label-label pada pod diberi namespace secara implisit), sebuah label selector di atas label-label pod harus menentukan namespace yang akan diterapkan selector. Secara konsep X adalah domain topologi seperti node, rack, zona penyedia cloud, daerah penyedia cloud, dll. Kamu dapat menyatakannya menggunakan topologyKey
yang merupakan kunci untuk label node yang digunakan sistem untuk menunjukkan domain topologi tersebut, contohnya lihat kunci label yang terdaftar di atas pada bagian Selingan: label node built-in.
topologyKey
. Jika sebagian atau semua node tidak memiliki label topologyKey
yang dinyatakan, hal ini dapat menyebabkan perilaku yang tidak diinginkan.
Seperti afinitas node, ada dua tipe afinitas dan anti-afinitas pod, yaitu requiredDuringSchedulingIgnoredDuringExecution
dan
preferredDuringSchedulingIgnoredDuringExecution
yang menunjukan persyaratan "kuat" vs. "lemah". Lihat deskripsi pada bagian afinitas node sebelumnya.
Sebuah contoh dari afinitas requiredDuringSchedulingIgnoredDuringExecution
adalah "Tempatkan bersamaan pod layanan A dan layanan B di zona yang sama, karena mereka banyak berkomunikasi satu sama lain"
dan contoh preferDuringSchedulingIgnoredDuringExecution
anti-afinitas akan menjadi "sebarkan pod dari layanan ini di seluruh zona" (persyaratan kuat tidak masuk akal, karena kamu mungkin memiliki lebih banyak pod daripada zona).
Afinitas antar pod dinyatakan sebagai field podAffinity
dari field affinity
pada PodSpec dan anti-afinitas antar pod dinyatakan sebagai field podAntiAffinity
dari field affinity
pada PodSpec.
Contoh pod yang menggunakan pod affinity:
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: failure-domain.beta.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: failure-domain.beta.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: k8s.gcr.io/pause:2.0
Afinitas pada pod tersebut menetapkan sebuah aturan afinitas pod dan aturan anti-afinitas pod. Pada contoh ini, podAffinity
adalah requiredDuringSchedulingIgnoredDuringExecution
sementara podAntiAffinity
adalah preferredDuringSchedulingIgnoredDuringExecution
. Aturan afinitas pod menyatakan bahwa pod dapat dijadwalkan pada node hanya jika node tersebut berada pada zona yang sama dengan minimal satu pod yang sudah berjalan yang memiliki label dengan kunci "security" dan bernilai "S1". (Lebih detail, pod dapat berjalan pada node N jika node N memiliki label dengan kunci failure-domain.beta.kubernetes.io/zone
dan nilai V sehingga ada minimal satu node dalam klaster dengan kunci failure-domain.beta.kubernetes.io/zone
dan bernilai V yang menjalankan pod yang memiliki label dengan kunci "security" dan bernilai "S1".) Aturan anti-afinitas pod menyatakan bahwa pod memilih untuk tidak dijadwalkan pada sebuah node jika node tersebut sudah menjalankan pod yang memiliki label dengan kunci "security" dan bernilai "S2". (Jika topologyKey
adalah failure-domain.beta.kubernetes.io/zone
maka dapat diartikan bahwa pod tidak dapat dijadwalkan pada node jika node berada pada zona yang sama dengan pod yang memiliki label dengan kunci "security" dan bernilai "S2".) Lihat design doc untuk lebih banyak contoh afinitas dan anti-afinitas pod, baik requiredDuringSchedulingIgnoredDuringExecution
maupun preferredDuringSchedulingIgnoredDuringExecution
.
Operator yang sah untuk afinitas dan anti-afinitas pod adalah In
, NotIn
, Exists
, DoesNotExist
.
Pada dasarnya, topologyKey
dapat berupa label-kunci apapun yang sah. Namun, untuk alasan performa dan keamanan, ada beberapa batasan untuk topologyKey
:
- Untuk afinitas and anti-afinitas pod
requiredDuringSchedulingIgnoredDuringExecution
,topologyKey
tidak boleh kosong. - Untuk anti-afinitas pod
requiredDuringSchedulingIgnoredDuringExecution
, pengontrol penerimaanLimitPodHardAntiAffinityTopology
diperkenalkan untuk membatasitopologyKey
padakubernetes.io/hostname
. Jika kamu menginginkan untuk membuatnya tersedia untuk topologi khusus, kamu dapat memodifikasi pengontrol penerimaan, atau cukup menonaktifkannya saja. - Untuk anti-afinitas pod
preferredDuringSchedulingIgnoredDuringExecution
,topologyKey
yang kosong diinterpretasikan sebagai "semua topologi" ("semua topologi" sekarang dibatasi pada kombinasi darikubernetes.io/hostname
,failure-domain.beta.kubernetes.io/zone
danfailure-domain.beta.kubernetes.io/region
). - Kecuali untuk kasus-kasus di atas,
topologyKey
dapat berupa label-kunci apapun yang sah.
Sebagai tambahan untuk labelSelector
and topologyKey
, kamu secara opsional dapat menyatakan daftar namespaces
dari namespaces yang akan digunakan untuk mencocokan labelSelector
(daftar ini berjalan pada level definisi yang sama dengan labelSelector
dan topologyKey
)
Jika dihilangkan atau kosong, daftar ini sesuai standar akan merujuk pada namespace dari pod tempat definisi afinitas/anti-afinitas dinyatakan.
Semua matchExpressions
berkaitan dengan afinitas and anti-afinitas requiredDuringSchedulingIgnoredDuringExecution
harus dipenuhi agar pod dapat dijadwalkan pada node.
Penggunaan yang lebih praktikal
Afinitas and anti-afinitas antar pod dapat menjadi lebih berguna saat digunakan bersamaan dengan koleksi dengan level yang lebih tinggi seperti ReplicaSets, StatefulSets, Deployments, dll. Pengguna dapat dengan mudah mengkonfigurasi bahwa satu set workload harus ditempatkan bersama dalam topologi yang didefinisikan sama, misalnya, node yang sama.
Selalu ditempatkan bersamaan pada node yang sama
Dalam klaster berisi 3 node, sebuah aplikasi web memiliki in-memory cache seperti redis. Kita menginginkan agar web-server dari aplikasi ini sebisa mungkin ditempatkan bersamaan dengan cache.
Berikut ini kutipan yaml dari deployment redis sederhana dengan 3 replika dan label selector app=store
, Deployment memiliki konfigurasi PodAntiAffinity
untuk memastikan scheduler tidak menempatkan replika bersamaan pada satu node.
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cache
spec:
selector:
matchLabels:
app: store
replicas: 3
template:
metadata:
labels:
app: store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: redis-server
image: redis:3.2-alpine
Kutipan yaml dari deployment webserver berikut ini memiliki konfigurasi podAntiAffinity
dan podAffinity
. Konfigurasi ini menginformasikan scheduler bahwa semua replika harus ditempatkan bersamaan dengan pod yang memiliki label selector app=store
. Konfigurasi ini juga memastikan bahwa setiap replika webserver tidak ditempatkan bersamaan pada satu node.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
selector:
matchLabels:
app: web-store
replicas: 3
template:
metadata:
labels:
app: web-store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: web-app
image: nginx:1.12-alpine
Jika kita membuat kedua dployment di atas, klaster berisi 3 node kita seharusnya menjadi seperti berikut.
node-1 | node-2 | node-3 |
---|---|---|
webserver-1 | webserver-2 | webserver-3 |
cache-1 | cache-2 | cache-3 |
st
Seperti yang kamu lihat, semua 3 replika dari web-server
secara otomatis ditempatkan bersama dengan cache seperti yang diharapkan.
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
redis-cache-1450370735-6dzlj 1/1 Running 0 8m 10.192.4.2 kube-node-3
redis-cache-1450370735-j2j96 1/1 Running 0 8m 10.192.2.2 kube-node-1
redis-cache-1450370735-z73mh 1/1 Running 0 8m 10.192.3.1 kube-node-2
web-server-1287567482-5d4dz 1/1 Running 0 7m 10.192.2.3 kube-node-1
web-server-1287567482-6f7v5 1/1 Running 0 7m 10.192.4.3 kube-node-3
web-server-1287567482-s330j 1/1 Running 0 7m 10.192.3.2 kube-node-2
Tidak akan pernah ditempatkan bersamaan dalam node yang sama
Contoh di atas menggunakan aturan PodAntiAffinity
dengan topologyKey: "kubernetes.io/hostname"
untuk melakukan deploy klaster redis sehingga tidak ada dua instance terletak pada hos yang sama.
Lihat tutorial ZooKeeper untuk contoh dari konfigurasi StatefulSet dengan anti-afinitas untuk ketersediaan tinggi, menggunakan teknik yang sama.
Untuk informasi lebih lanjut tentang afinitas/anti-afinitas antar pod, lihat design doc.
Kamu juga dapat mengecek Taints, yang memungkinkan sebuah node untuk menolak sekumpulan pod.
nodeName
nodeName
adalah bentuk paling sederhana dari pembatasan pemilihan node, tetapi karena
keterbatasannya biasanya tidak digunakan. nodeName
adalah sebuah field dari
PodSpec. Jika tidak kosong, scheduler mengabaikan pod dan
kubelet yang berjalan pada node tersebut yang mencoba menjalankan pod. Maka, jika
nodeName
disediakan dalam PodSpec, ia memiliki hak yang lebih tinggi dibanding metode-metode di atas untuk pemilihan node.
Beberapa keterbatasan dari penggunaan nodeName
untuk memilih node adalah:
- Jika node yang disebut tidak ada, maka pod tidak akan dijalankan, dan dalam beberapa kasus akan dihapus secara otomatis.
- Jika node yang disebut tidak memiliki resource yang cukup untuk mengakomodasi pod, pod akan gagal dan alasannya akan mengindikasikan sebab kegagalan, misalnya OutOfmemory atau OutOfcpu.
- Nama node pada lingkungan cloud tidak selalu dapat diprediksi atau stabil.
Berikut ini contoh konfigurasi pod menggunakan field nodeName
:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: kube-01
Pod di atas akan berjalan pada node kube-01.
Selanjutnya
3.9.4 - Taint dan Toleration
Afinitas Node, seperti yang dideskripsikan di sini, adalah salah satu properti dari Pod yang menyebabkan pod tersebut memiliki preferensi untuk ditempatkan di sekelompok Node tertentu (preferensi ini dapat berupa soft constraints atau hard constraints yang harus dipenuhi). Taint merupakan kebalikan dari afinitas -- properti ini akan menyebabkan Pod memiliki preferensi untuk tidak ditempatkan pada sekelompok Node tertentu.
Taint dan toleration bekerja sama untuk memastikan Pod dijadwalkan pada Node yang sesuai. Satu atau lebih taint akan diterapkan pada suatu node; hal ini akan menyebabkan node tidak akan menerima pod yang tidak mengikuti taint yang sudah diterapkan.
Konsep
Kamu dapat menambahkan taint pada sebuah node dengan menggunakan perintah kubectl taint. Misalnya,
kubectl taint nodes node1 key=value:NoSchedule
akan menerapkan taint pada node node1
. Taint tersebut memiliki key key
, value value
,
dan effect taint NoSchedule
. Hal ini artinya pod yang ada tidak akan dapat dijadwalkan pada node1
kecuali memiliki taint yang sesuai.
Untuk menghilangkan taint yang ditambahkan dengan perintah di atas, kamu dapat menggunakan perintah di bawah ini:
kubectl taint nodes node1 key:NoSchedule-
Kamu dapat memberikan spesifikasi toleration untuk pod pada bagian PodSpec.
Kedua toleration yang diterapkan di bawa ini "sesuai" dengan taint yang
taint yang dibuat dengan perintah kubectl taint
di atas, sehingga sebuah pod
dengan toleration yang sudah didefinisikan akan mampu di-schedule ke node node
:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
tolerations:
- key: "key"
operator: "Exists"
effect: "NoSchedule"
Sebuah toleration "sesuai" dengan sebuah taint jika key dan efek yang ditimbulkan sama:
operator
dianggapExists
(pada kasus dimana tidak adavalue
yang diberikan), atauoperator
dianggapEqual
danvalue
yang ada sama
Operator
bernilai Equal
secara default jika tidak diberikan spesifikasi khusus.
Terdapat dua kasus khusus:
- Sebuah
key
dengan operatorExists
akan sesuai dengan semua key, value, dan effect yang ada. Dengan kata lain, tolaration ini akan menerima semua hal yang diberikan.
tolerations:
- operator: "Exists"
- Sebuah
effect
yang kosong akan dianggap sesuai dengan semua effect dengan keykey
.
tolerations:
- key: "key"
operator: "Exists"
Contoh yang diberikan di atas menggunakan effect
untuk NoSchedule
.
Alternatif lain yang dapat digunakan adalah effect
untuk PreferNoSchedule
.
PreferNoSchedule
merupakan "preferensi" yang lebih fleksibel dari NoSchedule
--
sistem akan mencoba untuk tidak menempatkan pod yang tidak menoleransi taint
pada node, tapi hal ini bukan merupakan sesuatu yang harus dipenuhi. Jenis ketiga
dari effect
adalah NoExecute
, akan dijelaskan selanjutnya.
Kamu dapat menerapkan beberapa taint sekaligus pada node atau beberapa toleration sekaligus pada sebuah pod. Mekanisme Kubernetes dapat memproses beberapa taint dan toleration sekaligus sama halnya seperti sebuah filter: memulai dengan taint yang ada pada node, kemudian mengabaikan taint yang sesuai pada pod yang memiliki toleration yang sesuai; kemudian taint yang diterapkan pada pod yang sudah disaring tadi akan menghasilkan suatu effect pada pod. Secara khusus:
- jika terdapat taint yang tidak tersaring dengan effect
NoSchedule
maka Kubernetes tidak akan menempatkan pod pada node tersebut - jika tidak terdapat taint yang tidak tersaring dengan effect
NoSchedule
tapi terdapat setidaknya satu taint yang tidak tersaring dengan effectPreferNoSchedule
maka Kubernetes akan mencoba untuk tidak akan menempatkan pod pada node tersebut - jika terdapat taint yang tidak tersaring dengan effect
NoExecute
maka pod akan berada dalam kondisi evicted dari node (jika pod tersebut sudah terlanjur ditempatkan pada node tersebut), dan tidak akan di-schedule lagi pada node tersebut.
Sebagai contoh, bayangkan kamu memberikan taint pada node sebagai berikut:
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule
Dan pod memiliki dua toleration:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
Pada kasus ini, pod tidak akan di-schedule pada node, karena tidak ada toleration yang sesuai dengan taint ketiga. Akan tetapi, pod yang sebelumnya sudah dijalankan di node dimana taint ditambahkan akan tetap jalan, karena taint ketiga merupakan taint yang tidak ditoleransi oleh pod.
Pada umumnya, jika sebuah taint memiliki effect NoExecute
ditambahkan pada node,
maka semua pod yang tidak menoleransi taint tersebut akan berada dalam state
evicted secara langsung, dan semua pod yang menoleransi taint tersebut
tidak akan berjalan seperti biasanya (tidak dalam state evicted). Meskipun demikian,
toleration dengan effect NoExecute
dapat dispesfikasikan sebagai field opsional
tolerationSeconds
yang memberikan perintah berapa lama suatu pod akan berada
pada node apabila sebuah taint ditambahkan. Contohnya:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
ini berarti apabila sebuah pod sedang dalam berada dalam state running, kemudian sebuah taint yang sesuai ditambahkan pada node, maka pod tersebut akan tetap berada di dalam node untuk periode 3600 detik sebelum state-nya berubah menjadi evicted. Jika taint dihapus sebelum periode tersebut, maka pod tetap berjalan sebagaimana mestinya.
Contoh Penggunaan
Taint dan toleration adalah mekanisme fleksibel yang digunakan untuk memaksa pod agar tidak dijadwalkan pada node-node tertentu atau mengubah state pod menjadi evicted. Berikut adalah beberapa contoh penggunaannya:
-
Node-Node yang Sifatnya Dedicated: Jika kamu ingin menggunakan sekumpulan node dengan penggunaan eksklusif dari sekumpulan pengguna, kamu dapat menambahkan taint pada node-node tersebut (misalnya,
kubectl taint nodes nodename dedicated=groupName:NoSchedule
) dan kemudian menambahkan toleration yang sesuai pada pod-pod yang berada di dalamnya (hal ini dapat dilakukan dengan mudah dengan cara menulis admission controller yang bersifat khusus). Pod-pod dengan toleration nantinya akan diperbolehkannya untuk menggunakan node yang sudah di-taint (atau dengan kata lain didedikasikan penggunaannya) maupun node lain yang ada di dalam klaster. Jika kamu ingin mendedikasikan node khusus yang hanya digunakan oleh pod-pod tadi serta memastikan pod-pod tadi hanya menggunakan node yang didedikasikan, maka kamu harus menambahkan sebuah label yang serupa dengan taint yang diberikan pada sekelompok node (misalnya,dedicated=groupName
), dan admission controller sebaiknya menambahkan afininitas node untuk memastikan pod-pod tadi hanya dijadwalkan pada node dengan labeldedicated=groupName
. -
Node-Node dengan Perangkat Keras Khusus: Pada suatu klaster dimana sebagian kecuali node memiliki perangkat keras khusus (misalnya GPU), kita ingin memastikan hanya pod-pod yang membutuhkan GPU saja yang dijadwalkan di node dengan GPU. Hal ini dapat dilakukan dengan memberikan taint pada node yang memiliki perangkat keras khusus (misalnya,
kubectl taint nodes nodename special=true:NoSchedule
ataukubectl taint nodes nodename special=true:PreferNoSchedule
) serta menambahkan toleration yang sesuai pada pod yang menggunakan node dengan perangkat keras khusus. Seperti halnya pada kebutuhan dedicated node, hal ini dapat dilakukan dengan mudah dengan cara menulis admission controller yang bersifat khusus. Misalnya, kita dapat menggunakan Extended Resource untuk merepresentasikan perangkat keras khusus, kemudian taint node dengan perangkat keras khusus dengan nama extended resource dan jalankan admission controller ExtendedResourceToleration. Setelah itu, karena node yang ada sudah di-taint, maka tidak akan ada pod yang tidak memiliki toleration yang akan dijadwalkan pada node tersebut_. Meskipun begitu, ketika kamu membuat suatu pod yang membutuhkan extended resource, maka admission controller dariExtendedResourceToleration
akan mengoreksi toleration sehingga pod tersebut dapat dijadwalkan pada node dengan perangkat keras khusus. Dengan demikian, kamu tidak perlu menambahkan toleration secara manual pada pod yang ada. -
Eviction berbasis Taint (fitur beta): Konfigurasi eviction per pod yang terjadi ketika pod mengalami gangguan, hal ini akan dibahas lebih lanjut di bagian selanjutnya.
Eviction berbasis Taint
Sebelumnya, kita sudah pernah membahas soal effect taint NoExecute
,
yang memengaruhi pod yang sudah dijalankan dengan cara sebagai berikut:
- pod yang tidak menoleransi taint akan segera diubah state-nya menjadi evicted
- pod yang menoleransi taint yang tidak menspesifikasikan
tolerationSeconds
pada spesifikasi toleration yang ada akan tetap berada di dalam node tanpa adanya batas waktu tertentu - pod yang menoleransi taint yang menspesifikasikan
tolerationSeconds
spesifikasi toleration yang ada akan tetap berada di dalam node hingga batas waktu tertentu
Sebagai tambahan, Kubernetes 1.6 memperkenalkan dukungan alfa untuk merepresentasikan node yang bermasalah. Dengan kata lain, node controller akan secara otomatis memberikan taint pada sebuah node apabila node tersebut memenuhi kriteria tertentu. Berikut merupakan taint yang secara default disediakan:
node.kubernetes.io/not-ready
: Node berada dalam state not ready. Hal ini terjadi apabila value dari NodeConditionReady
adalah "False
".node.kubernetes.io/unreachable
: Node berada dalam state unreachable dari node controller Hal ini terjadi apabila value dari NodeConditionReady
adalah "Unknown
".node.kubernetes.io/out-of-disk
: Node kehabisan kapasitas disk.node.kubernetes.io/memory-pressure
: Node berada diambang kapasitas memori.node.kubernetes.io/disk-pressure
: Node berada diambang kapasitas disk.node.kubernetes.io/network-unavailable
: Jaringan pada Node bersifat unavailable.node.kubernetes.io/unschedulable
: Node tidak dapat dijadwalkan.node.cloudprovider.kubernetes.io/uninitialized
: Ketika kubelet dijalankan dengan penyedia layanan cloud "eksternal", taint ini akan diterapkan pada node untuk menandai node tersebut tidak digunakan. Setelah kontroler dari cloud-controller-manager melakukan inisiasi node tersebut, maka kubelet akan menghapus taint yang ada.
Pada versi 1.13, fitur TaintBasedEvictions
diubah menjadi beta dan diaktifkan secara default,
dengan demikian taint-taint tersebut secara otomatis ditambahkan oleh NodeController (atau kubelet)
dan logika normal untuk melakukan eviction pada pod dari suatu node tertentu berdasarkan value
dari Ready yang ada pada NodeCondition dinonaktifkan.
Fitur beta ini, bersamaan dengan tolerationSeconds
, mengizinkan sebuah pod
untuk menspesifikasikan berapa lama pod harus tetap sesuai dengan sebuah node
apabila node tersebut bermasalah.
Misalnya, sebuah aplikasi dengan banyak state lokal akan lebih baik untuk tetap berada di suatu node pada saat terjadi partisi jaringan, dengan harapan partisi jaringan tersebut dapat diselesaikan dan mekanisme eviction pod tidak akan dilakukan. Toleration yang ditambahkan akan berbentuk sebagai berikut:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000
Perhatikan bahwa Kubernetes secara otomatis menambahkan toleration untuk
node.kubernetes.io/not-ready
dengan tolerationSeconds=300
kecuali konfigurasi lain disediakan oleh pengguna.
Kubernetes juga secara otomatis menambahkan toleration untuk
node.kubernetes.io/unreachable
dengan tolerationSeconds=300
kecuali konfigurasi lain disediakan oleh pengguna.
Toleration yang ditambahkan secara otomatis ini menjamin bahwa perilaku default dari suatu pod adalah tetap bertahan selama 5 menit pada node apabila salah satu masalah terdeteksi. Kedua toleration default tadi ditambahkan oleh DefaultTolerationSeconds admission controller.
Pod-pod pada DaemonSet dibuat dengan toleration
NoExecute
untuk taint tanpa tolerationSeconds
:
node.kubernetes.io/unreachable
node.kubernetes.io/not-ready
Hal ini menjamin pod-pod yang merupakan bagian dari DaemonSet tidak pernah berada di dalam state evicted apabila terjadi permasalahan pada node.
Taint pada Node berdasarkan Kondisi Tertentu
Pada versi 1.12, fitur TaintNodesByCondition
menjadi fitur beta, dengan demikian lifecycle
dari kontroler node akan secara otomatis menambahkan taint sesuai dengan kondisi node.
Hal yang sama juga terjadi pada scheduler, scheduler tidak bertugas memeriksa kondisi node
tetapi kondisi taint. Hal ini memastikan bahwa kondisi node tidak memengaruhi apa
yang dijadwalkan di node. Pengguna dapat memilih untuk mengabaikan beberapa permasalahan yang
ada pada node (yang direpresentasikan oleh kondisi Node) dengan menambahkan toleration Pod NoSchedule
.
Sedangkan taint dengan effect NoExecute
dikendalikan oleh TaintBasedEviction
yang merupakan
fitur beta yang diaktifkan secara default oleh Kubernetes sejak versi 1.13.
Sejak Kubernetes versi 1.8, kontroler DaemonSet akan secara otomatis
menambahkan toleration NoSchedule
pada semua daemon untuk menjaga
fungsionalitas DaemonSet.
node.kubernetes.io/memory-pressure
node.kubernetes.io/disk-pressure
node.kubernetes.io/out-of-disk
(hanya untuk pod yang bersifat critical)node.kubernetes.io/unschedulable
(versi 1.10 atau yang lebih baru)node.kubernetes.io/network-unavailable
(hanya untuk jaringan host)
Menambahkan toleration ini menjamin backward compatibility. Kamu juga dapat menambahkan toleration lain pada DaemonSet.
3.9.5 - Penjadwal Kubernetes
Dalam Kubernetes, scheduling atau penjadwalan ditujukan untuk memastikan Pod mendapatkan Node sehingga Kubelet dapat menjalankannya.
Ikhtisar Penjadwalan
Sebuah penjadwal mengawasi Pod yang baru saja dibuat dan belum ada Node yang dialokasikan untuknya. Untuk setiap Pod yang ditemukan oleh penjadwal, maka penjadwal tersebut bertanggung jawab untuk menemukan Node terbaik untuk menjalankan Pod. Penjadwal dapat menetapkan keputusan penempatan ini dengan mempertimbangkan prinsip-prinsip penjadwalan yang dijelaskan di bawah ini.
Jika kamu ingin memahami mengapa Pod ditempatkan pada Node tertentu, atau jika kamu berencana untuk mengimplementasikan penjadwal kustom sendiri, halaman ini akan membantu kamu belajar tentang penjadwalan.
Kube-scheduler
Kube-scheduler adalah penjadwal standar untuk Kubernetes dan dijalankan sebagai bagian dari _control plane_. Kube-scheduler dirancang agar jika kamu mau dan perlu, kamu bisa menulis komponen penjadwalan kamu sendiri dan menggunakannya.
Untuk setiap Pod yang baru dibuat atau Pod yang tak terjadwal lainnya, kube-scheduler memilih Node yang optimal untuk menjalankannya. Namun, setiap kontainer masuk Pod memiliki persyaratan sumber daya yang berbeda dan setiap Pod juga memiliki persyaratan yang berbeda juga. Oleh karena itu, Node yang ada perlu dipilih sesuai dengan persyaratan khusus penjadwalan.
Dalam sebuah Klaster, Node yang memenuhi persyaratan penjadwalan untuk suatu Pod disebut Node feasible. Jika tidak ada Node yang cocok, maka Pod tetap tidak terjadwal sampai penjadwal yang mampu menempatkannya.
Penjadwal menemukan Node-Node yang layak untuk sebuah Pod dan kemudian menjalankan sekumpulan fungsi untuk menilai Node-Node yang layak dan mengambil satu Node dengan skor tertinggi di antara Node-Node yang layak untuk menjalankan Pod. Penjadwal kemudian memberi tahu server API tentang keputusan ini dalam proses yang disebut dengan binding.
Beberapa faktor yang perlu dipertimbangkan untuk keputusan penjadwalan termasuk persyaratan sumber daya individu dan kolektif, aturan kebijakan / perangkat keras / lunak, spesifikasi persamaan dan anti-persamaan, lokalitas data, interferensi antar Workloads, dan sebagainya.
Pemilihan node pada kube-scheduler
Kube-scheduler memilih node untuk pod dalam 2 langkah operasi:
- Filtering
- Scoring
Langkah filtering menemukan sekumpulan Nodes yang layak untuk menjadwalkan Pod. Misalnya, penyarin PodFitsResources memeriksa apakah Node kandidat memiliki sumber daya yang cukup untuk memenuhi permintaan spesifik sumber daya dari Pod. Setelah langkah ini, daftar Node akan berisi Node-node yang sesuai; seringkali, akan terisi lebih dari satu. Jika daftar itu kosong, maka Pod itu tidak (belum) dapat dijadwalkan.
Pada langkah scoring, penjadwal memberi peringkat pada Node-node yang tersisa untuk memilih penempatan paling cocok untuk Pod. Penjadwal memberikan skor untuk setiap Node yang sudah tersaring, memasukkan skor ini pada aturan penilaian yang aktif.
Akhirnya, kube-scheduler memberikan Pod ke Node dengan peringkat tertinggi. Jika ada lebih dari satu node dengan skor yang sama, maka kube-scheduler memilih salah satunya secara acak.
Ada dua cara yang didukung untuk mengkonfigurasi perilaku penyaringan dan penilaian oleh penjadwal:
- Aturan Penjadwalan yang memungkinkan kamu untuk mengkonfigurasi Predicates untuk pemfilteran dan Priorities untuk penilaian.
- Profil Penjadwalan yang memungkinkan
kamu mengkonfigurasi Plugin yang menerapkan tahapan penjadwalan berbeda,
termasuk:
QueueSort
,Filter
,Score
,Bind
,Reserve
,Permit
, dan lainnya. Kamu juga bisa mengonfigurasi kube-scheduler untuk menjalankan profil yang berbeda.
Selanjutnya
- Baca tentang penyetelan performa penjadwal
- Baca tentang pertimbangan penyebarang topologi pod
- Baca referensi dokumentasi untuk kube-scheduler
- Pelajari tentang mengkonfigurasi beberapa penjadwal
- Pelajari tentang aturan manajemen topologi
- Pelajari tentang pengeluaran tambahan Pod
3.9.6 - Kerangka Kerja Penjadwalan (Scheduling Framework)
Kubernetes 1.15 [alpha]
Kerangka kerja penjadwalan (Scheduling Framework) adalah arsitektur yang dapat dipasang (pluggable) pada penjadwal Kubernetes untuk membuat kustomisasi penjadwal lebih mudah. Hal itu dilakukan dengan menambahkan satu kumpulan "plugin" API ke penjadwal yang telah ada. Plugin dikompilasi ke dalam penjadwal. Beberapa API memungkinkan sebagian besar fitur penjadwalan diimplementasikan sebagai plugin, sambil tetap mempertahankan penjadwalan "inti" sederhana dan terpelihara. Silahkan merujuk pada [proposal desain dari kerangka penjadwalan] kep untuk informasi teknis lebih lanjut tentang desain kerangka kerja tersebut.
Alur kerja kerangka kerja
Kerangka kerja penjadwalan mendefinisikan beberapa titik ekstensi. Plugin penjadwal mendaftar untuk dipanggil di satu atau lebih titik ekstensi. Beberapa plugin ini dapat mengubah keputusan penjadwalan dan beberapa hanya bersifat informasi.
Setiap upaya untuk menjadwalkan satu Pod dibagi menjadi dua fase, Siklus Penjadwalan (Scheduling Cycle) dan Siklus Pengikatan (Binding Cycle).
Siklus Penjadwalan dan Siklus Pengikatan
Siklus penjadwalan memilih sebuah Node untuk Pod, dan siklus pengikatan menerapkan keputusan tersebut ke klaster. Secara bersama-sama, siklus penjadwalan dan siklus pengikatan diartikan sebagai sebuah "konteks penjadwalan (scheduling context)".
Siklus penjadwalan dijalankan secara serial, sementara siklus pengikatan dapat berjalan secara bersamaan.
Siklus penjadwalan atau pengikatan dapat dibatalkan jika Pod telah ditentukan untuk tidak terjadwalkan atau jika terdapat kesalahan internal. Pod akan dikembalikan ke antrian dan dicoba lagi.
Titik-titik ekstensi
Gambar berikut menunjukkan konteks penjadwalan Pod dan titik-titik ekstensi yang diperlihatkan oleh kerangka penjadwalan. Dalam gambar ini "Filter" setara dengan "Predicate" dan "Scoring" setara dengan "Priority Function".
Satu plugin dapat mendaftar di beberapa titik ekstensi untuk melakukan pekerjaan yang lebih kompleks atau stateful.
QueueSort
Plugin ini digunakan untuk mengurutkan Pod-Pod dalam antrian penjadwalan. Plugin
QueueSort pada dasarnya menyediakan fungsi Less (Pod1, Pod2)
. Hanya satu jenis
plugin QueueSort yang dapat diaktifkan dalam waktu yang bersamaan.
PreFilter
Plugin ini digunakan untuk melakukan pra-proses informasi tentang Pod, atau untuk memeriksa tertentu kondisi yang harus dipenuhi oleh klaster atau Pod. Jika plugin PreFilter menghasilkan hasil yang salah, siklus penjadwalan dibatalkan.
Filter
Plugin ini digunakan untuk menyaring Node yang tidak dapat menjalankan Pod. Untuk setiap Node, penjadwal akan memanggil plugin Filter sesuai dengan urutan mereka dikonfigurasi. Jika ada plugin Filter menandai Node menjadi infeasible, maka plugin yang lainnya tidak akan dipanggil untuk Node itu. Node-Node dapat dievaluasi secara bersamaan.
PostFilter
Plugin ini disebut setelah fase Filter, tetapi hanya ketika tidak ada node yang layak ditemukan untuk pod. Plugin dipanggil dalam urutan yang dikonfigurasi. Jika plugin postFilter menandai node sebagai 'Schedulable', plugin yang tersisa tidak akan dipanggil. Implementasi PostFilter yang khas adalah preemption, yang mencoba membuat pod dapat di menjadwalkan dengan mendahului Pod lain.
PreScore
Plugin ini digunakan untuk melakukan pekerjaan "pra-penilaian", yang menghasilkan keadaan yang dapat dibagi untuk digunakan oleh plugin-plugin Score. Jika plugin PreScore mengeluarkan hasil salah, maka siklus penjadwalan dibatalkan.
Score
Plugin ini digunakan untuk menentukan peringkat Node yang telah melewati fase penyaringan. Penjadwal akan memanggil setiap plugin Score untuk setiap Node. Akan ada kisaran bilangan bulat yang telah ditetapkan untuk mewakili skor minimum dan maksimum. Setelah fase NormalizeScore, penjadwal akan menggabungkan skor Node dari semua plugin sesuai dengan bobot plugin yang telah dikonfigurasi.
NormalizeScore
Plugin ini digunakan untuk memodifikasi skor sebelum penjadwal menghitung peringkat akhir Node-Node. Plugin yang mendaftar untuk titik ekstensi ini akan dipanggil dengan hasil Score dari plugin yang sama. Hal ini dilakukan sekali untuk setiap plugin dan setiap siklus penjadwalan.
Sebagai contoh, anggaplah sebuah plugin BlinkingLightScorer
memberi peringkat
pada Node-Node berdasarkan berapa banyak kedipan lampu yang mereka miliki.
func ScoreNode(_ *v1.pod, n *v1.Node) (int, error) {
return getBlinkingLightCount(n)
}
Namun, jumlah maksimum kedipan lampu mungkin kecil jika dibandingkan dengan
NodeScoreMax
. Untuk memperbaikinya, BlinkingLightScorer
juga harus mendaftar
untuk titik ekstensi ini.
func NormalizeScores(scores map[string]int) {
highest := 0
for _, score := range scores {
highest = max(highest, score)
}
for node, score := range scores {
scores[node] = score*NodeScoreMax/highest
}
}
Jika ada plugin NormalizeScore yang menghasilkan hasil yang salah, maka siklus penjadwalan dibatalkan.
Reserve
Ini adalah titik ekstensi yang bersifat informasi. Plugin yang mempertahankan keadaan runtime (alias "stateful plugins") harus menggunakan titik ekstensi ini untuk diberitahukan oleh penjadwal ketika sumber daya pada suatu Node dicadangkan untuk Pod yang telah disiapkan. Proses ini terjadi sebelum penjadwal benar-benar mengikat Pod ke Node, dan itu ada untuk mencegah kondisi balapan (race conditions) ketika penjadwal menunggu agar pengikatan berhasil.
Ini adalah langkah terakhir dalam siklus penjadwalan. Setelah Pod berada dalam status dicadangkan, maka itu akan memicu plugin Unreserve (apabila gagal) atau plugin PostBind (apabila sukses) di akhir siklus pengikatan.
Permit
Plugin Permit dipanggil pada akhir siklus penjadwalan untuk setiap Pod untuk mencegah atau menunda pengikatan ke Node kandidat. Plugin Permit dapat melakukan salah satu dari ketiga hal ini:
-
approve
Setelah semua plugin Permit menyetujui sebuah Pod, Pod tersebut akan dikirimkan untuk diikat. -
deny
Jika ada plugin Permit yang menolak sebuah Pod, Pod tersebut akan dikembalikan ke antrian penjadwalan. Hal ini akan memicu plugin Unreserve. -
wait (dengan batas waktu)
Jika plugin Permit menghasilkan "wait", maka Pod disimpan dalam daftar Pod "yang menunggu" internal, dan siklus pengikatan Pod ini dimulai tetapi akan langsung diblokir sampai mendapatkan approved. Jika waktu tunggu habis, ** wait ** menjadi ** deny ** dan Pod dikembalikan ke antrian penjadwalan, yang memicu plugin Unreserve.
FrameworkHandle
), kami hanya mengharapkan
plugin Permit untuk menyetujui pengikatan Pod dalam kondisi "menunggu" yang
telah dipesan. Setelah Pod disetujui, akan dikirim ke fase PreBind.
PreBind
Plugin ini digunakan untuk melakukan pekerjaan apa pun yang diperlukan sebelum Pod terikat. Sebagai contoh, plugin PreBind dapat menyediakan network volume dan melakukan mounting pada Node target sebelum mengizinkan Pod berjalan di sana.
Jika ada plugin PreBind yang menghasilkan kesalahan, maka Pod ditolak dan kembali ke antrian penjadwalan.
Bind
Plugin ini digunakan untuk mengikat Pod ke Node. Plugin-plugin Bind tidak akan dipanggil sampai semua plugin PreBind selesai. Setiap plugin Bind dipanggil sesuai urutan saat dikonfigurasi. Plugin Bind dapat memilih untuk menangani atau tidak Pod yang diberikan. Jika plugin Bind memilih untuk menangani Pod, ** plugin Bind yang tersisa dilewati **.
PostBind
Ini adalah titik ekstensi bersifat informasi. Plugin-plugin PostBind dipanggil setelah sebuah Pod berhasil diikat. Ini adalah akhir dari siklus pengikatan, dan dapat digunakan untuk membersihkan sumber daya terkait.
Unreserve
Ini adalah titik ekstensi bersifat informasi. Jika sebuah Pod telah dipesan dan kemudian ditolak di tahap selanjutnya, maka plugin-plugin Unreserve akan diberitahu. Plugin Unreserve harus membersihkan status yang terkait dengan Pod yang dipesan.
Plugin yang menggunakan titik ekstensi ini sebaiknya juga harus digunakan Reserve.
Plugin API
Ada dua langkah untuk plugin API. Pertama, plugin harus mendaftar dan mendapatkan konfigurasi, kemudian mereka menggunakan antarmuka titik ekstensi. Antarmuka (interface) titik ekstensi memiliki bentuk sebagai berikut.
type Plugin interface {
Name() string
}
type QueueSortPlugin interface {
Plugin
Less(*v1.pod, *v1.pod) bool
}
type PreFilterPlugin interface {
Plugin
PreFilter(context.Context, *framework.CycleState, *v1.pod) error
}
// ...
Konfigurasi plugin
Kamu dapat mengaktifkan atau menonaktifkan plugin dalam konfigurasi penjadwal. Jika kamu menggunakan Kubernetes v1.18 atau yang lebih baru, kebanyakan plugin-plugin penjadwalan sudah digunakan dan diaktifkan secara bawaan.
Selain plugin-plugin bawaan, kamu juga dapat mengimplementasikan plugin-plugin penjadwalan kamu sendiri dan mengonfigurasinya bersama-sama dengan plugin-plugin bawaan. Kamu bisa mengunjungi plugin-plugin penjadwalan untuk informasi lebih lanjut.
Jika kamu menggunakan Kubernetes v1.18 atau yang lebih baru, kamu dapat mengonfigurasi sekumpulan plugin sebagai profil penjadwal dan kemudian menetapkan beberapa profil agar sesuai dengan berbagai jenis beban kerja. Pelajari lebih lanjut di multi profil.
3.9.7 - Penyetelan Kinerja Penjadwal
Kubernetes v1.14 [beta]
kube-scheduler merupakan penjadwal (scheduler) Kubernetes bawaan yang bertanggung jawab terhadap penempatan Pod-Pod pada seluruh Node di dalam sebuah klaster.
Node-Node di dalam klaster yang sesuai dengan syarat-syarat penjadwalan dari sebuah Pod disebut sebagai Node-Node layak (feasible). Penjadwal mencari Node-Node layak untuk sebuah Pod dan kemudian menjalankan fungsi-fungsi untuk menskor Node-Node tersebut, memilih sebuah Node dengan skor tertinggi di antara Node-Node layak lainnya, di mana Pod akan dijalankan. Penjadwal kemudian memberitahu API server soal keputusan ini melalui sebuah proses yang disebut Binding.
Laman ini menjelaskan optimasi penyetelan (tuning) kinerja yang relevan untuk klaster Kubernetes berskala besar.
Pada klaster berskala besar, kamu bisa menyetel perilaku penjadwal untuk menyeimbangkan hasil akhir penjadwalan antara latensi (seberapa cepat Pod-Pod baru ditempatkan) dan akurasi (seberapa akurat penjadwal membuat keputusan penjadwalan yang tepat).
Kamu bisa mengonfigurasi setelan ini melalui pengaturan percentageOfNodesToScore
pada kube-scheduler.
Pengaturan KubeSchedulerConfiguration ini menentukan sebuah ambang batas untuk
penjadwalan Node-Node di dalam klaster kamu.
Pengaturan Ambang Batas
Opsi percentageOfNodesToScore
menerima semua angka numerik antara 0 dan 100.
Angka 0 adalah angka khusus yang menandakan bahwa kube-scheduler harus menggunakan
nilai bawaan.
Jika kamu mengatur percentageOfNodesToScore
dengan angka di atas 100, kube-scheduler
akan membulatkan ke bawah menjadi 100.
Untuk mengubah angkanya, sunting berkas konfigurasi kube-scheduler (biasanya /etc/kubernetes/config/kube-scheduler.yaml
),
lalu ulang kembali kube-scheduler.
Setelah kamu selesai menyunting, jalankan perintah
kubectl get componentstatuses
untuk memverifikasi komponen kube-scheduler berjalan dengan baik (healthy). Keluarannya kira-kira seperti ini:
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
...
Ambang Batas Penskoran Node
Untuk meningkatan kinerja penjadwalan, kube-scheduler dapat berhenti mencari Node-Node yang layak saat sudah berhasil menemukannya. Pada klaster berskala besar, hal ini menghemat waktu dibandingkan dengan pendekatan awam yang mengecek setiap Node.
Kamu bisa mengatur ambang batas untuk menentukan berapa banyak jumlah Node minimal yang dibutuhkan, sebagai persentase bagian dari seluruh Node di dalam klaster kamu. kube-scheduler akan mengubahnya menjadi bilangan bulat berisi jumlah Node. Saat penjadwalan, jika kube-scheduler mengidentifikasi cukup banyak Node-Node layak untuk melewati jumlah persentase yang diatur, maka kube-scheduler akan berhenti mencari Node-Node layak dan lanjut ke [fase penskoran] (/id/docs/concepts/scheduling-eviction/kube-scheduler/#kube-scheduler-implementation).
Bagaimana penjadwal mengecek Node menjelaskan proses ini secara detail.
Ambang Batas Bawaan
Jika kamu tidak mengatur sebuah ambang batas, maka Kubernetes akan menghitung sebuah nilai menggunakan pendekatan linier, yaitu 50% untuk klaster dengan 100 Node, serta 10% untuk klaster dengan 5000 Node.
Artinya, kube-scheduler selalu menskor paling tidak 5% dari klaster kamu, terlepas dari
seberapa besar klasternya, kecuali kamu secara eksplisit mengatur percentageOfNodesToScore
menjadi lebih kecil dari 5.
Jika kamu ingin penjadwal untuk memasukkan seluruh Node di dalam klaster ke dalam penskoran,
maka aturlah percentageOfNodesToScore
menjadi 100.
Contoh
Contoh konfigurasi di bawah ini mengatur percentageOfNodesToScore
menjadi 50%.
apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
algorithmSource:
provider: DefaultProvider
...
percentageOfNodesToScore: 50
Menyetel percentageOfNodesToScore
percentageOfNodesToScore
merupakan angka 1 sampai 100 dengan
nilai bawaan yang dihitung berdasarkan ukuran klaster. Di sini juga terdapat
batas bawah yang telah ditetapkan, yaitu 50 Node.
Pada klaster dengan kurang dari 50 Node layak, penjadwal masih terus memeriksa seluruh Node karena Node-Node layak belum mencukupi supaya penjadwal dapat menghentikan proses pencarian lebih awal.
Pada klaster kecil, jika kamu mengatur percentageOfNodesToScore
dengan angka kecil,
pengaturan ini hampir atau sama sekali tidak berpengaruh, karena alasan yang sama.
Jika klaster kamu punya ratusan Node, gunakan angka bawaan untuk opsi konfigurasi ini. Mengubah angkanya kemungkinan besar tidak akan mengubah kinerja penjadwal secara berarti.
Sebuah catatan penting yang perlu dipertimbangkan saat mengatur angka ini adalah ketika klaster dengan jumlah Node sedikit diperiksa untuk kelayakan, beberapa Node tidak dikirim untuk diskor bagi sebuah Pod. Hasilnya, sebuah Node yang mungkin memiliki nilai lebih tinggi untuk menjalankan Pod tersebut bisa saja tidak diteruskan ke fase penskoran. Hal ini berdampak pada penempatan Pod yang kurang ideal.
Kamu sebaiknya menghindari pengaturan percentageOfNodesToScore
menjadi sangat rendah,
agar kube-scheduler tidak seringkali membuat keputusan penempatan Pod yang buruk.
Hindari pengaturan persentase di bawah 10%, kecuali throughput penjadwal sangat penting
untuk aplikasi kamu dan skor dari Node tidak begitu penting. Dalam kata lain, kamu
memilih untuk menjalankan Pod pada Node manapun selama Node tersebut layak.
Bagaimana Penjadwal Mengecek Node
Bagian ini ditujukan untuk kamu yang ingin mengerti bagaimana fitur ini bekerja secara internal.
Untuk memberikan semua Node di dalam klaster sebuah kesempatan yang adil untuk
dipertimbangkan dalam menjalankan Pod, penjadwal mengecek Node satu persatu
secara round robin. Kamu dapat membayangkan Node-Node ada di dalam sebuah array.
Penjadwal mulai dari indeks array pertama dan mengecek kelayakan dari Node sampai
jumlahnya telah mencukupi sesuai dengan percentageOfNodesToScore
. Untuk Pod berikutnya,
penjadwal melanjutkan dari indeks array Node yang terhenti ketika memeriksa
kelayakan Node-Node untuk Pod sebelumnya.
Jika Node-Node berada di beberapa zona, maka penjadwal akan mengecek Node satu persatu pada seluruh zona untuk memastikan bahwa Node-Node dari zona berbeda masuk dalam pertimbangan kelayakan. Sebagai contoh, ada 6 Node di dalam 2 zona:
Zona 1: Node 1, Node 2, Node 3, Node 4
Zona 2: Node 5, Node 6
Penjadwal mempertimbangkan kelayakan dari Node-Node tersebut dengan urutan berikut:
Node 1, Node 5, Node 2, Node 6, Node 3, Node 4
Setelah semua Node telah dicek, penjadwal akan kembali pada Node 1.
3.10 - Policies
3.10.1 - LimitRange
Secara bawaan, Container berjalan dengan sumber daya komputasi tanpa batas pada klaster Kubernetes. Dengan ResourceQuota (kuota sumber daya), administrator klaster dapat membatasi konsumsi dan pembuatan sumber daya berbasis Namespace. Di dalam Namespace, Pod atau Container dapat mengkonsumsi CPU dan memori sesuai dengan yang ditentukan oleh ResourceQuota pada Namespace tersebut. Ada kekhawatiran bahwa satu Pod atau Container dapat memonopoli semua sumber daya yang tersedia. LimitRange (Batas Rentang) adalah kebijakan untuk membatasi alokasi sumber daya (bagi Pod atau Container) pada Namespace.
LimitRange memberikan batasan (limit) yang dapat:
- Menerapkan penggunaan sumber daya komputasi minimum dan maksimum untuk setiap Pod atau Container dalam Namespace.
- Menerapkan permintaan (request) tempat penyimpanan minimum dan maksimum untuk setiap PersistentVolumeClaim dalam Namespace.
- Menerapkan rasio antara permintaan dan batas untuk sumber daya dalam Namespace.
- Menetapkan permintaan/batas bawaan untuk menghitung sumber daya dalam Namespace dan memasukkannya secara otomatis ke Container pada runtime.
Mengaktifkan LimitRange
Dukungan LimitRange diaktifkan secara bawaan untuk banyak distribusi Kubernetes. Hal ini
diaktifkan ketika tanda --enable-admission-plugins=
pada apiserver memiliki admission controller LimitRanger
sebagai
salah satu argumennya.
LimitRange diberlakukan pada Namespace tertentu ketika ada sebuah objek LimitRange pada Namespace tersebut.
Nama dari objek LimitRange harus merupakan sebuah nama subdomain DNS.
Gambaran Umum LimitRange
- Administrator membuat sebuah LimitRange dalam sebuah Namespace.
- Pengguna membuat sumber daya seperti Pod, Container, dan PersistentVolumeClaim pada namespace.
- Admission controller
LimitRanger
memberlakukan bawaan dan batas untuk semua Pod dan Container yang tidak menetapkan persyaratan sumber daya komputasi dan melacak penggunaannya untuk memastikan agar tidak melebihi minimum, maksimum dan rasio sumber daya yang ditentukan dalam LimitRange yang ada pada Namespace. - Apabila permintaan membuat atau memperbarui sumber daya (Pod, Container, PersistentVolumeClaim) yang melanggar batasan LimitRange, maka permintaan ke server API akan gagal dengan kode status HTTP
403 FORBIDDEN
dan sebuah pesan yang menjelaskan batasan yang telah dilanggar. - Apabila LimitRange diaktifkan pada Namespace untuk menghitung sumber daya seperti
cpu
danmemory
, pengguna harus menentukan permintaan atau batasan untuk nilai-nilai itu. Jika tidak, sistem dapat menolak pembuatan Pod. - Pelanggaran terhadap LimitRange hanya terjadi pada tahap penerimaan Pod, bukan pada saat Pod sedang berjalan.
Contoh dari kebijakan yang dapat dibuat dengan menggunakan LimitRange yaitu:
- Dalam klaster dua Node dengan kapasitas 8 GiB RAM dan 16 core, batasan Pod dalam Namespace meminta 100m untuk CPU dengan batas maksimum 500m untuk CPU dan minta 200Mi untuk Memori dengan batas maksimum 600Mi untuk Memori.
- Tetapkan batas bawaan dan permintaan pada 150m untuk CPU dan permintaan standar memori pada 300Mi untuk Container yang dimulai tanpa cpu dan permintaan memori dalam spesifikasi mereka.
Dalam kasus di mana batas total Namespace kurang dari jumlah batas Pod/Container, mungkin akan ada perebutan untuk sumber daya. Dalam hal ini, maka Container atau Pod tidak akan dibuat.
Baik perebutan maupun perubahan pada LimitRange tidak akan mempengaruhi sumber daya yang sudah dibuat.
Selanjutnya
Silahkan merujuk pada Dokumen perancangan LimitRanger untuk informasi lebih lanjut.
Untuk contoh tentang penggunaan batas, lihatlah:
- Bagaimana cara mengonfigurasi batasan CPU minimum dan maksimum untuk setiap Namespace.
- Bagaimana cara mengonfigurasi batasan memori minimum dan maksimum untuk setiap Namespace.
- Bagaimana cara mengonfigurasi permintaan dan batas bawaan CPU untuk setiap Namespace.
- Bagaimana cara mengonfigurasi permintaan dan batas bawaan memori untuk setiap Namespace.
- Bagaimana cara mengonfigurasi konsumsi tempat penyimpanan minimum dan maksimum untuk setiap Namespace.
- Contoh terperinci tentang mengonfigurasi kuota untuk setiap Namespace.
3.10.2 - Resource Quota
Saat beberapa pengguna atau tim berbagi sebuah klaster dengan jumlah Node yang tetap, ada satu hal yang perlu diperhatikan yaitu suatu tim dapat menggunakan sumber daya lebih dari jatah yang mereka perlukan.
Resource Quota (kuota sumber daya) adalah sebuah alat yang dapat digunakan oleh administrator untuk mengatasi hal ini.
Sebuah Resource Quota, didefinisikan oleh objek API ResourceQuota
, menyediakan batasan-batasan
yang membatasi konsumsi gabungan sumber daya komputasi untuk tiap Namespace. Resource Quota dapat
membatasi jumlah objek yang dapat dibuat dalam sebuah Namespace berdasarkan tipenya, maupun jumlah
seluruh sumber daya komputasi yang dapat dipakai oleh sumber daya API (misalnya Pod) di Namespace
tersebut.
Resource Quota bekerja sebagai berikut:
- Tim-tim berbeda bekerja pada Namespace yang berbeda pula. Sekarang hal ini belum diwajibkan, tetapi dukungan untuk mewajibkannya melalui ACL sedang direncanakan.
- Administrator membuat sebuah
ResourceQuota
untuk setiap Namespace. - Para pengguna membuat sumber daya (Pod, Service, dll.) di dalam Namespace tersebut, kemudian
sistem kuota memantau penggunaan untuk memastikan bahwa penggunaannya tidak melebihi batas
sumber daya yang ditentukan di
ResourceQuota
. - Jika pembuatan atau pembaruan sebuah sumber daya melanggar sebuah batasan kuota, maka permintaan
tersebut akan gagal dengan kode status
403 FORBIDDEN
dengan sebuah pesan yang menjelaskan batasan yang akan dilanggar. - Jika kuota diaktifkan di sebuah Namespace untuk sumber daya komputasi seperti
cpu
danmemory
, pengguna-pengguna harus menentukanrequests
ataulimits
untuk sumber daya tersebut; atau sistem kuota akan menolak pembuatan Pod tersebut. Petunjuk: Gunakan Admission ControllerLimitRanger
untuk memaksa nilai-nilai bawaan untuk Pod-Pod yang tidak menentukan kebutuhan sumber daya komputasi. Lihat petunjuknya untuk contoh bagaimana cara menghindari masalah ini.
Contoh-contoh kebijakan yang dapat dibuat menggunakan Namespace dan kuota adalah:
- Dalam sebuah klaster dengan kapasitas RAM 32 GiB, dan CPU 16 core, misalkan tim A menggunakan 20GiB dan 10 core, dan tim B menggunakan 10GiB dan 4 core, dan menyimpan 2GiB dan 2 core untuk cadangan penggunaan di masa depan.
- Batasi Namespace "testing" dengan batas 1 core dan RAM 1GiB. Biarkan Namespace "production" menggunakan berapapun jumlah yang diinginkan.
Pada kasus di mana total kapasitas klaster lebih sedikit dari jumlah seluruh kuota di seluruh Namespace, dapat terjadi perebutan sumber daya komputasi. Masalah ini akan ditangani dengan cara siapa-cepat-dia-dapat.
Perebutan sumber daya komputasi maupun perubahan kuota tidak akan memengaruhi sumber daya yang sudah dibuat sebelumnya.
Mengaktifkan Resource Quota
Dukungan untuk Resource Quota diaktifkan secara bawaan pada banyak distribusi Kubernetes. Resource Quota
diaktifkan saat flag --enable-admission-plugins=
pada apiserver memiliki ResourceQuota
sebagai
salah satu nilainya.
Sebuah Resource Quota akan dipaksakan pada sebuah Namespace tertentu saat ada sebuah objek ResourceQuota
di dalam Namespace tersebut.
Resource Quota Komputasi
Kamu dapat membatasi jumlah total sumber daya komputasi yang dapat diminta di dalam sebuah Namespace.
Berikut jenis-jenis sumber daya yang didukung:
Nama Sumber Daya | Deskripsi |
---|---|
limits.cpu |
Pada seluruh Pod yang berada pada kondisi non-terminal, jumlah limits CPU tidak dapat melebihi nilai ini. |
limits.memory |
Pada seluruh Pod yang berada pada kondisi non-terminal, jumlah limits memori tidak dapat melebihi nilai ini. |
limits.cpu |
Pada seluruh Pod yang berada pada kondisi non-terminal, jumlah requests CPU tidak dapat melebihi nilai ini. |
limits.memory |
Pada seluruh Pod yang berada pada kondisi non-terminal, jumlah requests memori tidak dapat melebihi nilai ini. |
Resource Quota untuk sumber daya yang diperluas
Sebagai tambahan untuk sumber daya yang disebutkan di atas, pada rilis 1.10, dukungan kuota untuk sumber daya yang diperluas ditambahkan.
Karena overcommit tidak diperbolehkan untuk sumber daya yang diperluas, tidak masuk akal untuk menentukan
keduanya; requests
dan limits
untuk sumber daya yang diperluas yang sama pada sebuah kuota. Jadi, untuk
sumber daya yang diperluas, hanya kuota dengan prefiks requests.
saja yang diperbolehkan untuk sekarang.
Mari kita ambil contoh sumber daya GPU. Jika nama sumber dayanya adalah nvidia.com/gpu
, dan kamu ingin
membatasi jumlah total GPU yang diminta pada sebuah Namespace menjadi 4, kamu dapat menentukan sebuah kuota
sebagai berikut:
requests.nvidia.com/gpu: 4
Lihat Melihat dan Menyetel Kuota untuk informasi lebih lanjut.
Resource Quota untuk penyimpanan
Kamu dapat membatasi jumlah total sumber daya penyimpanan yang dapat diminta pada sebuah Namespace.
Sebagai tambahan, kamu dapat membatasi penggunaan sumber daya penyimpanan berdasarkan storage class sumber daya penyimpanan tersebut.
Nama Sumber Daya | Deskripsi |
---|---|
requests.storage |
Pada seluruh Persistent Volume Claim, jumlah requests penyimpanan tidak dapat melebihi nilai ini. |
persistentvolumeclaims |
Jumlah kuantitas Persistent Volume Claim yang dapat ada di dalam sebuah Namespace. |
<storage-class-name>.storageclass.storage.k8s.io/requests.storage |
Pada seluruh Persistent Volume Claim yang dikaitkan dengan sebuah nama storage-class (melalui kolom storageClassName ), jumlah permintaan penyimpanan tidak dapat melebihi nilai ini. |
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims |
Pada seluruh Persistent Volume Claim yang dikaitkan dengan sebuah nama storage-class (melalui kolom storageClassName ), jumlah kuantitas Persistent Volume Claim yang dapat ada di dalam sebuah Namespace. |
Sebagai contoh, jika sebuah operator ingin membatasi penyimpanan dengan Storage Class gold
yang berbeda dengan Storage Class bronze
, maka operator tersebut dapat menentukan kuota sebagai berikut:
gold.storageclass.storage.k8s.io/requests.storage: 500Gi
bronze.storageclass.storage.k8s.io/requests.storage: 100Gi
Pada rilis 1.8, dukungan kuota untuk penyimpanan lokal sementara (local ephemeral storage) ditambahkan sebagai sebuah fitur alpha:
Nama Sumber Daya | Deskripsi |
---|---|
requests.ephemeral-storage |
Pada seluruh Pod di sebuah Namespace, jumlah requests penyimpanan lokal sementara tidak dapat melebihi nilai ini. |
limits.ephemeral-storage |
Pada seluruh Pod di sebuah Namespace, jumlah limits penyimpanan lokal sementara tidak dapat melebihi nilai ini. |
Kuota Kuantitas Objek
Rilis 1.9 menambahkan dukungan untuk membatasi semua jenis sumber daya standar yang berada pada sebuah Namespace dengan sintaksis sebagai berikut:
count/<sumber-daya>.<grup>
Berikut contoh-contoh sumber daya yang dapat ditentukan pengguna pada kuota kuantitas objek:
count/persistentvolumeclaims
count/services
count/secrets
count/configmaps
count/replicationcontrollers
count/deployments.apps
count/replicasets.apps
count/statefulsets.apps
count/jobs.batch
count/cronjobs.batch
count/deployments.extensions
Rilis 1.15 menambahkan dukungan untuk sumber daya custom menggunakan sintaksis yang sama.
Contohnya, untuk membuat kuota pada sumber daya custom widgets
pada grup API example.com
, gunakan
count/widgets.example.com
.
Saat menggunakan Resource Quota count/*
, sebuah objek akan menggunakan kuotanya jika ia berada pada penyimpanan Apiserver.
Tipe-tipe kuota ini berguna untuk menjaga dari kehabisan sumber daya penyimpanan. Misalnya, kamu mungkin
ingin membatasi kuantitas objek Secret pada sebuah Apiserver karena ukuran mereka yang besar. Terlalu banyak
Secret pada sebuah klaster bahkan dapat membuat Server dan Controller tidak dapat dijalankan! Kamu dapat membatasi
jumlah Job untuk menjaga dari CronJob yang salah dikonfigurasi sehingga membuat terlalu banyak Job pada sebuah
Namespace yang mengakibatkan denial of service.
Sebelum rilis 1.9, kita tidak dapat melakukan pembatasan kuantitas objek generik pada kumpulan sumber daya yang terbatas. Sebagai tambahan, kita dapat membatasi lebih lanjut sumber daya tertentu dengan kuota berdasarkan jenis mereka.
Berikut jenis-jenis yang telah didukung:
Nama Sumber Daya | Deskripsi |
---|---|
configmaps |
Jumlah total ConfigMap yang dapat berada pada suatu Namespace. |
persistentvolumeclaims |
Jumlah total PersistentVolumeClaimpersistent volume claims yang dapat berada pada suatu Namespace. |
pods |
Jumlah total Pod yang berada pada kondisi non-terminal yang dapat berada pada suatu Namespace. Sebuah Pod berada kondisi terminal yaitu jika .status.phase in (Failed, Succeded) adalah true . |
replicationcontrollers |
Jumlah total ReplicationController yang dapat berada pada suatu Namespace. |
resourcequotas |
Jumlah total ResourceQuota yang dapat berada pada suatu Namespace. |
services |
Jumlah total Service yang dapat berada pada suatu Namespace. |
services.loadbalancers |
Jumlah total Service dengan tipe LoadBalancer yang dapat berada pada suatu Namespace. |
services.nodeports |
Jumlah total Service dengan tipe NodePort yang dapat berada pada suatu Namespace. |
secrets |
Jumlah total Secret yang dapat berada pada suatu Namespace. |
Sebagai contoh, pods
membatasi kuantitas dan memaksa kuantitas maksimum pods
yang
berada pada kondisi non-terminal yang dibuat pada sebuah Namespace. Kamu mungkin ingin
menyetel kuota pods
pada sebuah Namespace untuk menghindari kasus di mana pengguna membuat
banyak Pod kecil dan menghabiskan persediaan alamat IP Pod pada klaster.
Lingkup Kuota
Setiap kuota dapat memiliki kumpulan lingkup yang dikaitkan. Sebuah kuota hanya akan mengukur penggunaan sebuah sumber daya jika sumber daya tersebut cocok dengan irisan dari lingkup-lingkup yang ditentukan.
Saat sebuah lingkup ditambahkan kepada kuota, lingkup itu akan membatasi kuantitas sumber daya yang didukung menjadi yang berkaitan dengan lingkup tersebut. Sumber daya yang ditentukan pada kuota di luar kumpulan yang diizinkan akan menghasilkan kesalahan validasi.
Lingkup | Deskripsi |
---|---|
Terminating |
Mencocokkan dengan Pod-Pod yang memiliki .spec.activeDeadlineSeconds >= 0 |
NotTerminating |
Mencocokkan dengan Pod-Pod yang memiliki .spec.activeDeadlineSeconds is nil |
BestEffort |
Mencocokkan dengan Pod-Pod yang memiliki quality of service bertipe best effort. |
NotBestEffort |
Mencocokkan dengan Pod-Pod yang tidak memiliki quality of service bertipe best effort. |
Lingkup BestEffort
membatasi sebuah kuota untuk memantau sumber daya berikut: pods
Lingkup Terminating
, NotTerminating
, dan NotBestEffort
membatasi sebuah kuota untuk memantau sumber daya berikut:
cpu
limits.cpu
limits.memory
memory
pods
requests.cpu
requests.memory
Resource Quota Per PriorityClass
Kubernetes 1.12 [beta]
Pod-Pod dapat dibuat dengan sebuah Priority (prioritas) tertentu.
Kamu dapat mengontrol konsumsi sumber daya sistem sebuah Pod berdasarkan Priority Pod tersebut, menggunakan
kolom scopeSelector
pada spesifikasi kuota tersebut.
Sebuah kuota dicocokkan dan digunakan hanya jika scopeSelector
pada spesifikasi kuota tersebut memilih Pod tersebut.
Contoh ini membuat sebuah objek kuota dan mencocokkannya dengan Pod-Pod pada Priority tertentu. Contoh tersebut bekerja sebagai berikut:
- Pod-Pod di dalam klaster memiliki satu dari tiga Priority Class, "low", "medium", "high".
- Satu objek kuota dibuat untuk setiap Priority.
Simpan YAML berikut ke sebuah berkas bernama quota.yml
.
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-high
spec:
hard:
cpu: "1000"
memory: 200Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["high"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-medium
spec:
hard:
cpu: "10"
memory: 20Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["medium"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-low
spec:
hard:
cpu: "5"
memory: 10Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["low"]
Terapkan YAML tersebut dengan kubectl create
.
kubectl create -f ./quota.yml
resourcequota/pods-high created
resourcequota/pods-medium created
resourcequota/pods-low created
Pastikan bahwa kuota Used
adalah 0
dengan kubectl describe quota
.
kubectl describe quota
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 1k
memory 0 200Gi
pods 0 10
Name: pods-low
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 5
memory 0 10Gi
pods 0 10
Name: pods-medium
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 10
memory 0 20Gi
pods 0 10
Buat sebuah Pod dengan Priority "high". Simpan YAML berikut ke sebuah
berkas bernama high-priority-pod.yml
.
apiVersion: v1
kind: Pod
metadata:
name: high-priority
spec:
containers:
- name: high-priority
image: ubuntu
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
resources:
requests:
memory: "10Gi"
cpu: "500m"
limits:
memory: "10Gi"
cpu: "500m"
priorityClassName: high
Terapkan dengan kubectl create
.
kubectl create -f ./high-priority-pod.yml
Pastikan bahwa status "Used" untuk kuota dengan Priority "high", pods-high
, telah berubah
dan dua kuota lainnya tidak berubah.
kubectl describe quota
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 500m 1k
memory 10Gi 200Gi
pods 1 10
Name: pods-low
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 5
memory 0 10Gi
pods 0 10
Name: pods-medium
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 10
memory 0 20Gi
pods 0 10
scopeSelector
mendukung nilai-nilai berikut pada kolom operator
:
In
NotIn
Exist
DoesNotExist
Request vs Limit
Saat mengalokasikan sumber daya komputasi, setiap Container dapat menentukan sebuah nilai request (permintaan) dan limit untuk CPU atau memori. Kuota tersebut dapat dikonfigurasi untuk membatasi nilai salah satunya.
Jika kuota tersebut memiliki sebuah nilai yang ditentukan untuk requests.cpu
atau requests.memory
, maka kuota
tersebut mengharuskan setiap Container yang akan dibuat untuk menentukan request eksplisit untuk sumber daya tersebut.
Jika kuota tersebut memiliki sebuah nilai yang ditentukan untuk limits.cpu
atau limits.memory
, maka kuota tersebut
mengharuskan setiap Container yang akan dibuat untuk menentukan limit eksplisit untuk sumber daya tersebut.
Melihat dan Menyetel kuota
Kubectl mendukung membuat, membarui, dan melihat kuota:
kubectl create namespace myspace
cat <<EOF > compute-resources.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
requests.nvidia.com/gpu: 4
EOF
kubectl create -f ./compute-resources.yaml --namespace=myspace
cat <<EOF > object-counts.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts
spec:
hard:
configmaps: "10"
persistentvolumeclaims: "4"
pods: "4"
replicationcontrollers: "20"
secrets: "10"
services: "10"
services.loadbalancers: "2"
EOF
kubectl create -f ./object-counts.yaml --namespace=myspace
kubectl get quota --namespace=myspace
NAME AGE
compute-resources 30s
object-counts 32s
kubectl describe quota compute-resources --namespace=myspace
Name: compute-resources
Namespace: myspace
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
requests.cpu 0 1
requests.memory 0 1Gi
requests.nvidia.com/gpu 0 4
kubectl describe quota object-counts --namespace=myspace
Name: object-counts
Namespace: myspace
Resource Used Hard
-------- ---- ----
configmaps 0 10
persistentvolumeclaims 0 4
pods 0 4
replicationcontrollers 0 20
secrets 1 10
services 0 10
services.loadbalancers 0 2
Kubectl juga mendukung kuota kuantitas objek untuk semua sumber daya standar yang berada pada Namespace
menggunakan sintaksis count/<resource>.<group>
:
kubectl create namespace myspace
kubectl create quota test --hard=count/deployments.extensions=2,count/replicasets.extensions=4,count/pods=3,count/secrets=4 --namespace=myspace
kubectl run nginx --image=nginx --replicas=2 --namespace=myspace
kubectl describe quota --namespace=myspace
Name: test
Namespace: myspace
Resource Used Hard
-------- ---- ----
count/deployments.extensions 1 2
count/pods 2 3
count/replicasets.extensions 1 4
count/secrets 1 4
Kuota dan Kapasitas Klaster
ResourceQuota
tidak tergantung pada kapasitas klaster. ResourceQuota
ditentukan dalam
satuan-satuan absolut. Jadi, jika kamu menambahkan Node ke klaster kamu, penambahan ini
bukan berarti secara otomatis memberikan setiap Namespace kemampuan untuk menggunakan
lebih banyak sumber daya.
Terkadang kebijakan yang lebih kompleks mungkin lebih diinginkan, seperti:
- Secara proporsional membagi sumber daya total klaster untuk beberapa tim.
- Mengizinkan setiap tim untuk meningkatkan penggunaan sumber daya sesuai kebutuhan, tetapi tetap memiliki batas yang cukup besar untuk menghindari kehabisan sumber daya.
- Mendeteksi permintaan dari sebuah Namespace, menambah Node, kemudian menambah kuota.
Kebijakan-kebijakan seperti itu dapat diterapkan dengan ResourceQuota
sebagai dasarnya,
dengan membuat sebuah "pengontrol" yang memantau penggunaan kuota dan menyesuaikan batas
keras kuota untuk setiap Namespace berdasarkan sinyal-sinyal lainnya.
Perlu dicatat bahwa Resource Quota membagi agregat sumber daya klaster, tapi Resource Quota tidak membuat batasan-batasan terhadap Node: Pod-Pod dari beberapa Namespace boleh berjalan di Node yang sama.
Membatasi konsumsi Priority Class secara bawaan
Mungkin saja diinginkan untuk Pod-Pod pada kelas prioritas tertentu, misalnya "cluster-services", sebaiknya diizinkan pada sebuah Namespace, jika dan hanya jika terdapat sebuah objek kuota yang cocok.
Dengan mekanisme ini, operator-operator dapat membatasi penggunaan Priority Class dengan prioritas tinggi pada Namespace-Namespace tertentu saja dan tidak semua Namespace dapat menggunakan Priority Class tersebut secara bawaan.
Untuk memaksa aturan ini, flag kube-apiserver --admission-control-config-file
sebaiknya digunakan untuk memberikan path menuju berkas konfigurasi berikut:
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
configuration:
apiVersion: apiserver.config.k8s.io/v1
kind: ResourceQuotaConfiguration
limitedResources:
- resource: pods
matchScopes:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
# Kedaluwarsa pada v1.17 digantikan oleh apiserver.config.k8s.io/v1
apiVersion: apiserver.k8s.io/v1alpha1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
configuration:
# Kedaluwarsa pada v1.17 digantikan oleh apiserver.config.k8s.io/v1, ResourceQuotaConfiguration
apiVersion: resourcequota.admission.k8s.io/v1beta1
kind: Configuration
limitedResources:
- resource: pods
matchScopes:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
Sekarang, Pod-Pod "cluster-services" akan diizinkan hanya pada Namespace di mana ada sebuah objek kuota dengan sebuah scopeSelector
yang cocok.
Contohnya:
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
Lihat LimitedResources dan dokumen desain dukungan Quota untuk Priority Class untuk informasi lebih lanjut.
Contoh
Lihat contoh detail cara menggunakan sebuah Resource Quota.
Selanjutnya
Lihat dokumen desain ResourceQuota untuk informasi lebih lanjut.
3.10.3 - Pod Security Policy
Kubernetes v1.23 [beta]
Pod Security Policies (kebijakan keamanan Pod) memungkinkan otorisasi secara detil dari pembuatan dan pembaruan Pod.
Apa itu Pod Security Policy?
Pod Security Policy adalah sebuah sumber daya pada tingkat klaster yang mengatur aspek-aspek spesifikasi Pod yang sensitif terhadap keamanan. Objek-objek PodSecurityPolicy
mendefinisikan sebuah kumpulan kondisi yang harus dijalankan oleh Pod untuk dapat diterima oleh sistem, dan juga sebagai nilai-nilai bawaan untuk kolom-kolom yang bersangkutan. Mereka memungkinkan administrator untuk mengatur hal-hal berikut:
Aspek yang diatur | Nama Kolom |
---|---|
Menjalankan Container-container yang privileged | privileged |
Penggunaan namespace-namespace milik host | hostPID , hostIPC |
Penggunaan jaringan dan port milik host | hostNetwork , hostPorts |
Penggunaan jenis-jenis Volume | volumes |
Penggunaan filesystem milik host | allowedHostPaths |
Daftar putih untuk driver-driver Flexvolume | allowedFlexVolumes |
Mengalokasi FSGroup yang memiliki Volume milik Pod | fsGroup |
Mengharuskan penggunaan read-only root filesystem | readOnlyRootFilesystem |
User dan Grop ID dari Container | runAsUser , runAsGroup , supplementalGroups |
Membatasi eskalasi ke kemampuan root | allowPrivilegeEscalation , defaultAllowPrivilegeEscalation |
Kemampuan-kemampuan Linux | defaultAddCapabilities , requiredDropCapabilities , allowedCapabilities |
Konteks SELinux dari Container ainer | seLinux |
Jenis tambatan Proc yang diizinkan untuk Container | allowedProcMountTypes |
Profil AppArmor yang digunakan oleh Container | annotations |
Profil seccomp yang digubakan oleh Container | annotations |
Profil sysctl yang digunakan oleh Container | forbiddenSysctls ,allowedUnsafeSysctls |
Mengaktifkan Pod Security Policy
Pengaturan Pod Security Policy diimplementasi sebagai sebuah opsi (tapi direkomendasikan untuk digunakan) dari admission controller. PodSecurityPolicy dilaksanakan dengan mengaktifkan admission controller-nya, tetapi melakukan hal ini tanpa mengizinkan kebijakan apapun akan menghalangi Pod apapun untuk dibuat di dalam klaster.
Sejak API dari Pod Security Policy (policy/v1beta1/podsecuritypolicy
) diaktifkan secara independen dari admission controller, untuk klaster-klaster yang sudah ada direkomendasikan untuk menambahkan dan mengizinkan kebijakan yang bersangkutan sebelum mengaktifkan admission controller tersebut.
Mengizinkan Kebijakan
Saat sebuah sumber daya PodSecurityPolicy dibuat, ia tidak melakukan apa-apa. Untuk menggunakannya, Service Account dari pengguna yang memintanya atau target Pod-nya harus diizinkan terlebih dahulu untuk menggunakan kebijakan tersebut, dengan membolehkan kata kerja use
terhadap kebijakan tersebut.
Kebanyakan Pod Kubernetes tidak dibuat secara langsung oleh pengguna. Sebagai gantinya, mereka biasanya dibuat secara tidak langsung sebagai bagian dari sebuah Deployment, ReplicaSet, atau pengontrol yang sudah ditemplat lainnya melalui Controller Manager. Memberikan akses untuk pengontrol terhadap kebijakan tersebut akan mengizinkan akses untuk semua Pod yang dibuat oleh pengontrol tersebut, sehingga metode yang lebih baik untuk mengizinkan kebijakan adalah dengan memberikan akses pada Service Account milik Pod (lihat contohnya).
Melalui RBAC
RBAC adalah mode otorisasi standar Kubernetes, dan dapat digunakan dengan mudah untuk mengotorisasi penggunaan kebijakan-kebijakan.
Pertama-tama, sebuah Role
atau ClusterRole
perlu memberikan akses pada kata kerja use
terhadap kebijakan-kebijakan yang diinginkan. rules
yang digunakan untuk memberikan akses tersebut terlihat seperti berikut:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: <role name>
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames:
- <list of policies to authorize>
Kemudian, Role
atau ClusterRole
tersebut diikat ke pengguna-pengguna yang diberikan otoritas.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: <binding name>
roleRef:
kind: ClusterRole
name: <role name>
apiGroup: rbac.authorization.k8s.io
subjects:
# Mengotorisasi ServiceAccount spesifik
- kind: ServiceAccount
name: <authorized service account name>
namespace: <authorized pod namespace>
# Mengotorisasi User spesifik (tidak direkomendasikan)
- kind: User
apiGroup: rbac.authorization.k8s.io
name: <authorized user name>
Jika sebuah RoleBinding
(bukan ClusterRoleBinding
) digunakan, maka ia hanya akan memberi akses penggunaan untuk Pod-Pod yang dijalankan pada Namespace yang sama dengan RoleBinding
tersebut. Hal ini dapat dipasangkan dengan grup sistem untuk memberi akses pada semua Pod yang berjalan di Namespace tersebut:
# Mengotorisasi semua ServiceAccount di dalam sebuah Namespace
- kind: Group
apiGroup: rbac.authorization.k8s.io
name: system:serviceaccounts
# Atau secara ekuivalen, semua pengguna yang telah terotentikasi pada sebuah Namespace
- kind: Group
apiGroup: rbac.authorization.k8s.io
name: system:authenticated
Untuk lebih banyak contoh pengikatan RBAC, lihat Contoh Role Binding. Untuk contoh lengkap untuk mengotorisasi sebuah PodSecurityPolicy, lihat di bawah.
Mengatasi Masalah
- Controller Manager harus dijalankan terhadap port API yang telah diamankan, dan tidak boleh memiliki izin superuser, atau semua permintaan akan melewati modul-modul otentikasi dan otorisasi, semua objek PodSecurityPolicy tidak akan diizinkan, dan semua pengguna dapat membuat Container-container yang privileged. Untuk lebih detil tentang mengkonfigurasi otorisasi Controller Manager, lihat Controller Roles.
Urutan Kebijakan
Sebagai tambahan terhadap membatasi pembuatan dan pembaruan Pod, Pod Security Policy dapat digunakan juga untuk menyediakan nilai-nilai bawaan untuk banyak kolom yang dikontrol olehnya. Saat banyak kebijakan tersedia, pengatur Pod Security Policy memilih kebijakan-kebijakan berdasarkan kriteria berikut:
- PodSecurityPolicy yang mengizinkan Pod apa adanya, tanpa mengganti nilai-nilai bawaan atau memutasi Pod tersebut, akan lebih dipilih. Urutan PodSecurityPolicy yang tidak mengubah Pod ini tidak dipermasalahkan.
- Jika Pod-nya harus diberi nilai bawaan atau dimutasi, maka PodSecurityPolicy pertama (diurutkan berdasarkan namanya) untuk mengizinkan Pod tersebut akan dipilih.
Contoh
Contoh ini mengasumsikan kamu telah memiliki klaster yang berjalan dengan admission controller PodSecurityPolicy diaktifkan, dan kamu mempunyai akses admin.
Persiapan
Mempersiapkan sebuah Namespace dan ServiceAccount untuk digunakan pada contoh ini. Kita akan menggunakan ServiceAccount ini untuk meniru sebuah pengguna bukan admin.
kubectl create namespace psp-example
kubectl create serviceaccount -n psp-example fake-user
kubectl create rolebinding -n psp-example fake-editor --clusterrole=edit --serviceaccount=psp-example:fake-user
Untuk memperjelas kita bertindak sebagai pengguna yang mana dan mempersingkat ketikan, kita akan membuat 2 alias:
alias kubectl-admin='kubectl -n psp-example'
alias kubectl-user='kubectl --as=system:serviceaccount:psp-example:fake-user -n psp-example'
Membuat sebuah kebijakan dan sebuah Pod
Beri definisi objek contoh PodSecurityPolicy dalam sebuah berkas. Ini adalah kebijakan yang mencegah pembuatan Pod-Pod yang privileged.
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: example
spec:
privileged: false # Jangan izinkan Pod-Pod yang _privileged_!
# Sisanya isi kolom-kolom yang dibutuhkan
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
Dan buatlah PodSecurityPolicy tersebut dengan kubectl
:
kubectl-admin create -f example-psp.yaml
Sekarang, sebagai pengguna bukan admin, cobalah membuat Pod sederhana:
kubectl-user create -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: pause
spec:
containers:
- name: pause
image: k8s.gcr.io/pause
EOF
Error from server (Forbidden): error when creating "STDIN": pods "pause" is forbidden: unable to validate against any pod security policy: []
Apa yang terjadi? Walaupun PodSecurityPolicy tersebut telah dibuat, ServiceAccount dari Pod tersebut maupun fake-user
tidak memikiki izin untuk menggunakan kebijakan tersebut:
kubectl-user auth can-i use podsecuritypolicy/example
no
Membuat RoleBinding untuk memberikan fake-user
akses terhadap kata kerja use
pada kebijakan contoh kita:
kubectl-admin create role psp:unprivileged \
--verb=use \
--resource=podsecuritypolicy \
--resource-name=example
role "psp:unprivileged" created
kubectl-admin create rolebinding fake-user:psp:unprivileged \
--role=psp:unprivileged \
--serviceaccount=psp-example:fake-user
rolebinding "fake-user:psp:unprivileged" created
kubectl-user auth can-i use podsecuritypolicy/example
yes
Sekarang, ulangi membuat Pod tersebut
kubectl-user create -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: pause
spec:
containers:
- name: pause
image: k8s.gcr.io/pause
EOF
pod "pause" created
Bekerja seperti yang diharapkan! Tapi percobaan apapun untuk membuat Pod yang privileged seharusnya masih ditolak:
kubectl-user create -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: privileged
spec:
containers:
- name: pause
image: k8s.gcr.io/pause
securityContext:
privileged: true
EOF
Error from server (Forbidden): error when creating "STDIN": pods "privileged" is forbidden: unable to validate against any pod security policy: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
Hapus Pod tersebut sebelum melanjutkan:
kubectl-user delete pod pause
Menjalankan Pod lainnya
Mari coba lagi, dengan cara yang sedikit berbeda:
kubectl-user run pause --image=k8s.gcr.io/pause
deployment "pause" created
kubectl-user get pods
No resources found.
kubectl-user get events | head -n 2
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
1m 2m 15 pause-7774d79b5 ReplicaSet Warning FailedCreate replicaset-controller Error creating: pods "pause-7774d79b5-" is forbidden: no providers available to validate pod request
Apa yang terjadi? Kita telah mengikat Role psp:unprivileged
untuk fake-user
kita, kenapa kita mendapatkan kesalahan Error creating: pods "pause-7774d79b5-" is forbidden: no providers available to validate pod request
? Jawabannya berada pada sumbernya - replicaset-controller
. Fake-user berhasil membuat Deployment tersebut (yang berhasil membuat sebuah ReplicaSet), tetapi saat ReplicaSet tersebut akan membuat Pod, ia tidak terotorisasi untuk menggunakan PodSecurityPolicy contoh tersebut.
Untuk memperbaikinya, ikatlah Role psp:unprivileged
pada ServiceAccount Pod tersebut. Pada kasus ini (karena kita tidak menspesifikasikannya) ServiceAccount-nya adalah default
:
kubectl-admin create rolebinding default:psp:unprivileged \
--role=psp:unprivileged \
--serviceaccount=psp-example:default
rolebinding "default:psp:unprivileged" created
Sekarang, jika kamu memberi waktu ReplicaSet-nya untuk mencoba kembali, pengatur ReplicaSet tersebut seharusnya akan berhasil membuat Pod tersebut.
kubectl-user get pods --watch
NAME READY STATUS RESTARTS AGE
pause-7774d79b5-qrgcb 0/1 Pending 0 1s
pause-7774d79b5-qrgcb 0/1 Pending 0 1s
pause-7774d79b5-qrgcb 0/1 ContainerCreating 0 1s
pause-7774d79b5-qrgcb 1/1 Running 0 2s
Membersihkan
Hapus Namespace tersebut untuk membersihkan sebagian besar sumber daya yang digunakan dalam contoh ini:
kubectl-admin delete ns psp-example
namespace "psp-example" deleted
Perlu diperhatikan bahwa sumber daya PodSecurityPolicy
tidak diberi Namespace, dan harus dibersihkan secara terpisah:
kubectl-admin delete psp example
podsecuritypolicy "example" deleted
Contoh-contoh Kebijakan
Berikut adalah kebijakan dengan batasan paling sedikit yang dapat kamu buat, ekuivalen dengan tidak menggunakan admission controller Pod Security Policy:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: privileged
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
spec:
privileged: true
allowPrivilegeEscalation: true
allowedCapabilities:
- '*'
volumes:
- '*'
hostNetwork: true
hostPorts:
- min: 0
max: 65535
hostIPC: true
hostPID: true
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
Berikut adalah sebuah contoh kebijakan yang restriktif yang mengharuskan pengguna-pengguna untuk berjalan sebagai pengguna yang unprivileged, memblokir kemungkinan eskalasi menjadi root, dan mengharuskan penggunaan beberapa mekanisme keamanan.
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default'
apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
seccomp.security.alpha.kubernetes.io/defaultProfileName: 'runtime/default'
apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'
spec:
privileged: false
# Dibutuhkan untuk menghindari eskalasi ke _root_.
allowPrivilegeEscalation: false
# Hal ini berlebihan dengan _non-root_ + melarang eskalasi _privilege_,
# tetapi kita dapat menyediakannya untuk _defense in depth_
requiredDropCapabilities:
- ALL
# Izinkan tipe-tipe volume inti.
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
# Berasumsi bahwa persistentVolumes yang disetel oleh admin klaster aman untuk digunakan.
- 'persistentVolumeClaim'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
# Mengharuskan container untuk berjalan tanpa hak sebagai _root_.
rule: 'MustRunAsNonRoot'
seLinux:
# Kebijakan ini mengasumsikan bahwa node-node menggunakan AppArmor daripada SELinux.
rule: 'RunAsAny'
supplementalGroups:
rule: 'MustRunAs'
ranges:
# Larang menambahkan grup _root_.
- min: 1
max: 65535
fsGroup:
rule: 'MustRunAs'
ranges:
# Larang menambahkan grup _root_.
- min: 1
max: 65535
readOnlyRootFilesystem: false
Referensi Kebijakan
Privileged
Privileged - menentukan bila Container manapun di dalam sebuah Pod dapat mengaktifkan mode privileged. Secara bawaan, sebuah Container tidak diizinkan untuk mengakses perangkat apapun pada host-nya, tapi sebuah Container yang "privileged" akan diberikan akses untuk semua perangkat pada host-nya. Hal ini mengizinkan hampir semua akses yang sama dengan proses yang berjalan pada host kepada Container tersebut. Hal ini berfungsi untuk Container-container yang ingin menggunakan kemampuan Linux seperti memanipulasi network stack atau mengakses perangkat-perangkat. determines if any container in a pod can enable privileged mode.
Namespace Host
HostPID - Mengatur jika Container-container pada Pod dapat berbagi namespace process ID pada host. Catatlah bahwa saat dipasangkan dengan ptrace, hal ini dapat digunakan untuk eskalasi privilege di luar kontainer (ptrace secara bawaan tidak diizinkan).
HostIPC - Mengatur jika container-container pada Pod dapat berbagi namespace IPC pada host.
HostNetwork - Mengatur jika Pod dapat menggunakan namespace jaringan pada host. Melakukan hal ini akan memberikan Pod akses pada perangkat loopback, service yang sedang listening pada localhost, dan dapat digunakan untuk mengintai aktivitas jaringan pada Pod-Pod lain pada Node yang sama.
HostPorts - Memberikan daftar putih dari berbagai port yang diizinkan pada namespace jaringan pada host. Hal ini didefinisikan sebagai sebuah daftar HostPortRange
, dengan min
(inklusif) dan max
(inklusif). Nilai bawaannya adalah tidak ada host port yang diizinkan.
AllowedHostPaths - Lihat Volume dan file systems.
Volume dan file system
Volume - Menyediakan sebuah daftar putih dari tipe-tipe Volume yang diizinkan. Nilai-nilai yang diizinkan sesuai dengan sumber Volume yang didefinisikan saat membuat sebuah Volume. Untuk daftar lengkap tipe-tipe Volume, lihat tipe-tipe Volume. Sebagai tambahan, *
dapat digunakan untuk mengizinkan semua tipe Volume.
Kumpulan Volume-volume minimal yang direkomendasikan untuk PodSecurityPolicy baru adalah sebagai berikut:
- configMap
- downwardAPI
- emptyDir
- persistentVolumeClaim
- secret
- projected
PersistentVolume
yang dapat direferensikan oleh PersistentVolumeClaim
. Hanya pengguna-pengguna yang dipercaya yang boleh diberikan izin untuk membuat objek-objek PersistentVolume
.
FSGroup - Mengatur grup tambahan yang dipasang ke beberapa volume.
- MustRunAs - Membutuhkan setidaknya satu
range
untuk dapat ditentukan. Menggunakan semua nilai minimum darirange
yang pertama sebagai nilai bawaannya. Memvalidasikan terhadap semuarange
. - MayRunAs - Membutuhkan setidaknya satu
range
untuk dapat ditentukan. MengizinkanFSGroups
dibiarkan kosong tanpa memberikan nilai bawaan. Memvalidasikan terhadap semuarange
jika nilaiFSGroups
disetel. - RunAsAny - Tidak ada nilai bawaan yang diberikan. Mengizinkan ID
fsGroup
apapun untuk digunakan.
AllowedHostPaths - Memperinci sebuah daftar putih dari host path yang diizinkan untuk digunakan oleh volume-volume hostPath
. Sebuah daftar kosong berarti tidak ada pembatasan pada host path yang digunakan. Hal ini didefinisikan sebagai sebuah daftar objek-objek dengan sebuah kolom pathPrefix
, yang mengizinkan volume-volume hostPath
untuk menambatkan sebuah path yang dimulai dengan sebuah prefiks yang diizinkan, dan sebuah kolom readOnly
yang menunjukkan bahwa ia harus ditambatkan sebagai read-only.
Misalnya:
allowedHostPaths:
# Hal ini mengizinkan "/foo", "/foo/", "/foo/bar" dll., tetapi
# melarang "/fool", "/etc/foo" dll.
# "/foo/../" tidak sah.
- pathPrefix: "/foo"
readOnly: true # Izinkan hanya tambatan _read-only_
Ada banyak cara bagi sebuah Container dengan akses yang tidak dibatasi terhadap host filesystem-nya untuk dapat melakukan eskalasi privilege, termasuk membaca data dari Container-container lain, dan menyalahgunakan kredensial dari service-service sistem, misalnya Kubelet.
Direktori volume hostPath
yang dapat ditulis mengizinkan container-container untuk menulis ke filesystem melalui cara-cara yang membiarkan mereka melintasi host filesystem di luar pathPrefix
yang bersangkutan.
readOnly: true
, tersedia pada Kubernetes 1.11 ke atas, harus digunakan pada semua allowedHostPaths
untuk secara efektif membatasi akses terhadap pathPrefix
yang diperinci.
ReadOnlyRootFilesystem - Mengharuskan container-container berjalan dengan sebuah root filesystem yang bersifat read-only (yaitu, tanpa lapisan yang dapat ditulis)
Driver-driver Flexvolume
Hal ini memperinci sebuah daftar putih dari driver-driver Flexvolume yang diizinkan untuk digunakan oleh Flexvolume. Sebuah daftar kosong atau nil
berarti tidak ada batasan terhadap driver-driver tersebut.
Pastikan kolom volumes
berisi tipe volumenya; Jika tidak, tidak ada driver Flexvolume yang diizinkan.
Misalnya:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: allow-flex-volumes
spec:
# ... kolom kolom lainnya
volumes:
- flexVolume
allowedFlexVolumes:
- driver: example/lvm
- driver: example/cifs
Pengguna dan Grup
RunAsUser - Mengatur ID pengguna mana yang digunakan untuk menjalankan container-container.
- MustRunAs - Membutuhkan setidaknya satu
range
untuk dapat ditentukan. Menggunakan semua nilai minimum darirange
yang pertama sebagai nilai bawaannya. Memvalidasikan terhadap semuarange
. - MustRunAsNonRoot - Mengharuskan Pod diajukan dengan nilai
runAsUser
yang bukan nol, atau memiliki petunjukUSER
didefinisikan (dengan UID numerik) di dalam image. Pod-Pod yang belum memperincirunAsNonRoot
ataurunAsUser
akan dimutasikan untuk menyetelrunAsNonRoot=true
sehingga membutuhkan petunjukUSER
dengan nilai numerik bukan nol di dalam Container. Tidak ada nilai bawaan yang diberikan. MenyetelallowPrivilegeEscalation=false
sangat disarankan dengan strategi ini. - RunAsAny - Tidak ada nilai bawaan yang diberikan. Mengizinkan
runAsUser
apapun untuk digunakan.
RunAsGroup - Mengatur ID grup primer mana yang digunakan untuk menjalankan Container-container.
- MustRunAs - Membutuhkan setidaknya satu
range
untuk dapat ditentukan. Menggunakan semua nilai minimum darirange
yang pertama sebagai nilai bawaannya. Memvalidasikan terhadap semuarange
. - MayRunAs - Tidak memerlukan
RunAsGroup
untuk diperinci. Tetapi, saatRunAsGroup
diperinci, mereka harus berada padarange
yang didefinisikan. - RunAsAny - Tidak ada nilai bawaan yang diberikan. Mengizinkan
runAsGroup
apapun untuk digunakan.
SupplementalGroups - Mengatur ID grup mana saja yang ditambah ke Container-container.
- MustRunAs - Membutuhkan setidaknya satu
range
untuk dapat ditentukan. Menggunakan semua nilai minimum darirange
yang pertama sebagai nilai bawaannya. Memvalidasikan terhadap semuarange
. - MayRunAs - Membutuhkan setidaknya satu
range
untuk dapat ditentukan. MengizinkansupplementalGroups
dibiarkan kosong tanpa memberikan nilai bawaan. Memvalidasikan terhadap semuarange
jika nilaisupplementalGroup
disetel. - RunAsAny - Tidak ada nilai bawaan yang diberikan. Mengizinkan ID
supplementalGroups
apapun untuk digunakan.
Eskalasi Privilege
Opsi ini mengatur opsi Container allowPrivilegeEscalation
. Nilai bool
ini secara langsung mengatur apakah flag no_new_privs
disetel pada proses Container tersebut. Flag ini akan mencegah program setuid
mengganti ID pengguna efektif, dan mencegah berkas-berkas untuk memungkinkan kemampuan tambahan (misalnya, ini akan mencagah penggunaan peralatan ping
). Perilaku ini dibutuhkan untuk memaksakan MustRunAsNonRoot
.
AllowPrivilegeEscalation - Membatasi apakah seorang pengguna diizinkan untuk menyetel konteks keamanan dari sebuah Container menjadi allowPrivilegeEscalation=true
. Hal ini memiliki nilai bawaan untuk diizinkan, agar tidak merusak program setuid
. Menyetel ini menjadi false
memastikan bahwa tidak ada proses child dari sebuah Container dapat memperoleh lebih banyak privilege dari parent-nya.
DefaultAllowPrivilegeEscalation - Menyetel nilai bawaan untuk opsi allowPrivilegeEscalation
. Perilaku bawaan tanpa hal ini adalah untuk mengizinkan eskalasi privilege agar tidak merusak program setuid
. Jika perilaku ini tidak diinginkan, kolom ini dapat digunakan untuk menyetel nilai bawaan allowPrivilegeEscalation
agar melarang eskalasi, sementara masih mengizinkan Pod-Pod untuk meminta allowPrivilegeEscalation
secara eksplisit.
Kemampuan-kemampuan
Kemampuan-kemampuan Linux menyediakan perincian yang detail dari privilege-privilege yang biasa dikaitkan dengan superuser
. Beberapa dari kemampuan-kemampuan ini dapat digunakan untuk mengeskalasi privilege-privilege atau untuk container breakout, dan dapat dibatasi oleh PodSecurityPolicy. Untuk lebih lanjut tentang kemampuan-kemampuan Linux, lihat capabilities(7).
Kolom-kolom berikut mengambil daftar kemampuan-kemampuan, diperincikan sebagai nama kemampuannya dalam ALL_CAPS tanpa awalan CAP_
.
AllowedCapabilities - Menyediakan sebuah daftar putih dari kemampuan-kemampuan yang dapat ditambahkan pada sebuah Container. Kumpulan kemampuan bawaan secara implisit diizinkan. Kumpulan kosong berarti tidak ada kemampuan tambahan yang dapat ditambahkan selain bawaannya. *
dapat digunakan untuk mengizinkan semua kemampuan.
RequiredDropCapabilities - Kemampuan-kemampuan yang harus dihapus dari Container-container. Kemampuan-kemampuan ini dihapus dari kumpulan bawaan, dan tidak boleh ditambahkan. Kemampuan-kemampuan yang terdaftar di RequiredDropCapabilities
tidak boleh termasuk di dalam AllowedCapabilities
atau DefaultAddCapabilities
.
DefaultAddCapabilities - Kemampuan-kemampuan yang ditambahkan pada Container-container secara bawaan, sebagai tambahan untuk bawaan runtime. Lihat dokumentasi Docker untuk daftar kemampuan bawaan saat menggunakan runtime Docker.
SELinux
- MustRunAs - Mengharuskan penyetelan
seLinuxOptions
. MenggunakanseLinuxOptions
sebagai nilai bawaannya. Memvalidasi terhadapseLinuxOptions
. - RunAsAny - Tidak ada nilai bawaan yang disediakan. Mengizinkan nilai
seLinuxOptions
apapun untuk diberikan.
AllowedProcMountTypes
allowedProcMountTypes
adalah sebuah daftar putih dari ProcMountType yang diizinkan. Nilai kosong atau nil
menunjukkan bahwa hanya DefaultProcMountType
yang boleh digunakan.
DefaultProcMount
menggunakan nilai bawaan container runtime untuk readonly dan masked paths untuk /proc
. Kebanyakan runtime Container melakukan mask terhadap beberapa path di dalam /proc
untuk menghindari security exposure dari perangkat-perangkat atau informasi khusus yang tidak disengaja. Hal ini ditandai dengan nilai string Default
.
Satu-satunya ProcMountType lainnya adalah UnmaskedProcMount
, yang melangkahi perilaku masking bawaan dari runtime Container dan memastikan bahwa /proc
yang baru dibuat tetap utuh tanpa perubahan. Hal ini ditandai dengan nilai string Unmasked
.
AppArmor
Diatur melalui anotasi pada PodSecurityPolicy. Lihat dokumentasi AppArmor.
Seccomp
Penggunaan profil-profil seccomp di dalam Pod-Pod dapat diatur melalui anotasi pada PodSecurityPolicy. Seccomp adalah fitur Alpha di Kubernetes.
seccomp.security.alpha.kubernetes.io/defaultProfileName - Anotasi yang menunjukkan profil seccomp bawaan untuk diterapkan kepada container-container. Nilai-nilai yang mungkin adalah:
unconfined
- Seccomp tidak diterapkan pada proses-proses di container (ini adalah bawaan di Kubernetes), jika tidak ada alternatif yang diberikan.runtime/default
- Profil runtime container bawaan digunakan.docker/default
- Profil bawaan seccomp Docker digunakan. Sudah kedaluwarsa sejak Kubernetes 1.11. Gunakanruntime/default
sebagai gantinya.localhost/<path>
- Menentukan sebuah profil sebagai sebuah berkas pada Node yang berlokasi pada<seccomp_root>/<path>
, di mana<seccomp_root>
didefinisikan melalui flag--seccomp-profile-root
pada Kubelet.
seccomp.security.alpha.kubernetes.io/allowedProfileNames - Anotasi yang menunjukkan nilai-nilai mana yang diizinkan untuk anotasi seccomp pada Pod. Ditentukan sebagai sebuah daftar nilai yang diizinkan yang dibatasi dengan tanda koma. Nilai-nilai yang dimungkinkan adalah yang terdaftar di atas, ditambah dengan *
untuk mengizinkan semua profil. Ketiadaan anotasi ini berarti nilai bawaannya tidak dapat diubah.
Sysctl
Secara bawaan, semua sysctl yang aman diizinkan.
forbiddenSysctls
- mengecualikan sysctl-sysctl tertentu. Kamu dapat melarang kombinasi dari sysctl-sysctl yang aman maupun tidak aman pada daftar ini. Untuk melarang menyetel sysctl apapun, gunakan nilai*
.allowedUnsafeSysctls
- mengizinkan sysctl-sysctl tertentu yang telah dilarang oleh daftar bawaan, selama nilainya tidak terdaftar di dalamforbiddenSysctls
.
Lihat dokumentasi Sysctl.
3.11 - Administrasi Klaster
3.11.1 - Ikhtisar Administrasi Klaster
Ikhtisar administrasi klaster ini ditujukan untuk siapapun yang akan membuat atau mengelola klaster Kubernetes. Diharapkan untuk memahami beberapa konsep dasar Kubernetes sebelumnya.
Perencanaan Klaster
Lihat panduan di Persiapan untuk mempelajari beberapa contoh tentang bagaimana merencanakan, mengatur dan mengonfigurasi klaster Kubernetes. Solusi yang akan dipaparkan di bawah ini disebut distro.
Sebelum memilih panduan, berikut adalah beberapa hal yang perlu dipertimbangkan:
- Apakah kamu hanya ingin mencoba Kubernetes pada komputermu, atau kamu ingin membuat sebuah klaster dengan high-availability, multi-node? Pilihlah distro yang paling sesuai dengan kebutuhanmu.
- Jika kamu merencanakan klaster dengan high-availability, pelajari bagaimana cara mengonfigurasi klaster pada multiple zone.
- Apakah kamu akan menggunakan Kubernetes klaster di hosting, seperti Google Kubernetes Engine, atau hosting sendiri klastermu?
- Apakah klastermu berada pada on-premises, atau di cloud (IaaS)? Kubernetes belum mendukung secara langsung klaster hibrid. Sebagai gantinya, kamu dapat membuat beberapa klaster.
- Jika kamu ingin mengonfigurasi Kubernetes on-premises, pertimbangkan model jaringan yang paling sesuai.
- Apakah kamu ingin menjalankan Kubernetes pada "bare metal" hardware atau pada virtual machines (VM)?
- Apakah kamu hanya ingin mencoba klaster Kubernetes, atau kamu ingin ikut aktif melakukan pengembangan kode dari proyek Kubernetes? Jika jawabannya yang terakhir, pilihlah distro yang aktif dikembangkan. Beberapa distro hanya menggunakan rilis binary, namun menawarkan lebih banyak variasi pilihan.
- Pastikan kamu paham dan terbiasa dengan beberapa komponen yang dibutuhkan untuk menjalankan sebuah klaster.
Catatan: Tidak semua distro aktif dikelola. Pilihlah distro yang telah diuji dengan versi terkini dari Kubernetes.
Mengelola Klaster
-
Mengelola klaster akan menjabarkan beberapa topik terkait lifecycle dari klaster: membuat klaster baru, melakukan upgrade pada node master dan worker, melakukan pemeliharaan node (contoh: upgrade kernel), dan melakukan upgrade versi Kubernetes API pada klaster yang sedang berjalan.
-
Pelajari bagaimana cara mengatur node.
-
Pelajari bagaimana cara membuat dan mengatur kuota resource (resource quota) untuk shared klaster.
Mengamankan Klaster
-
Sertifikat (certificate) akan menjabarkan langkah-langkah untuk membuat sertifikat menggunakan beberapa tool chains.
-
Kubernetes Container Environment akan menjelaskan environment untuk kontainer yang dikelola oleh Kubelet pada Kubernetes node.
-
Mengontrol Akses ke Kubernetes API akan menjabarkan bagaimana cara mengatur izin (permission) untuk akun pengguna dan service account.
-
Autentikasi akan menjelaskan autentikasi di Kubernetes, termasuk ragam pilihan autentikasi.
-
Otorisasi dibedakan dari autentikasi, digunakan untuk mengontrol bagaimana HTTP call ditangani.
-
Menggunakan Admission Controllers akan menjelaskan plug-in yang akan melakukan intersep permintaan sebelum menuju ke server Kubernetes API, setelah autentikasi dan otorisasi dilakukan.
-
Menggunakan Sysctls pada Klaster Kubernetes akan menjabarkan tentang cara menggunakan perintah
sysctl
pada command-line untuk mengatur parameter kernel. -
Audit akan menjelaskan bagaimana cara berinteraksi dengan log audit Kubernetes.
Mengamankan Kubelet
Layanan Tambahan Klaster
-
Integrasi DNS akan menjelaskan bagaimana cara resolve suatu nama DNS langsung pada service Kubernetes.
-
Logging dan Monitoring Aktivitas Klaster akan menjelaskan bagaimana cara logging bekerja di Kubernetes serta bagaimana cara mengimplementasikannya.
3.11.2 - Sertifikat
Saat menggunakan autentikasi sertifikat klien, kamu dapat membuat sertifikat
secara manual melalui easyrsa
, openssl
atau cfssl
.
easyrsa
easyrsa dapat digunakan untuk menghasilkan sertifikat klaster kamu secara manual.
-
Unduh, buka paket, dan inisialisasi versi tambal easyrsa3.
curl -LO https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gz tar xzf easy-rsa.tar.gz cd easy-rsa-master/easyrsa3 ./easyrsa init-pki
-
Hasilkan CA. (
--batch
untuk atur mode otomatis.--req-cn
untuk menggunakan default CN.)./easyrsa --batch "--req-cn=${MASTER_IP}@`date +%s`" build-ca nopass
-
Hasilkan sertifikat dan kunci server. Argumen
--subject-alt-name
digunakan untuk mengatur alamat IP dan nama DNS yang dapat diakses oleh server API.MASTER_CLUSTER_IP
biasanya merupakan IP pertama dari CIDR service cluster yang diset dengan argumen--service-cluster-ip-range
untuk server API dan komponen manajer pengontrol. Argumen--days
digunakan untuk mengatur jumlah hari masa berlaku sertifikat. Sampel di bawah ini juga mengasumsikan bahwa kamu menggunakancluster.local
sebagai nama domain DNS default../easyrsa --subject-alt-name="IP:${MASTER_IP},"\ "IP:${MASTER_CLUSTER_IP},"\ "DNS:kubernetes,"\ "DNS:kubernetes.default,"\ "DNS:kubernetes.default.svc,"\ "DNS:kubernetes.default.svc.cluster,"\ "DNS:kubernetes.default.svc.cluster.local" \ --days=10000 \ build-server-full server nopass
-
Salin
pki/ca.crt
,pki/issued/server.crt
, danpki/private/server.key
ke direktori kamu. -
Isi dan tambahkan parameter berikut ke dalam parameter mulai server API:
--client-ca-file=/yourdirectory/ca.crt --tls-cert-file=/yourdirectory/server.crt --tls-private-key-file=/yourdirectory/server.key
openssl
openssl secara manual dapat menghasilkan sertifikat untuk klaster kamu.
-
Hasilkan ca.key dengan 2048bit:
openssl genrsa -out ca.key 2048
-
Hasilkan ca.crt berdasarkan ca.key (gunakan -days untuk mengatur waktu efektif sertifikat):
openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt
-
Hasilkan server.key dengan 2048bit:
openssl genrsa -out server.key 2048
-
Buat file konfigurasi untuk menghasilkan Certificate Signing Request (CSR). Pastikan untuk mengganti nilai yang ditandai dengan kurung sudut (mis.
<MASTER_IP>
) dengan nilai sebenarnya sebelum menyimpan ke file (mis.csr.conf
). Perhatikan bahwa nilaiMASTER_CLUSTER_IP
adalah layanan IP klaster untuk server API seperti yang dijelaskan dalam subbagian sebelumnya. Sampel di bawah ini juga mengasumsikan bahwa kamu menggunakancluster.local
sebagai nama domain DNS default.[ req ] default_bits = 2048 prompt = no default_md = sha256 req_extensions = req_ext distinguished_name = dn [ dn ] C = <country> ST = <state> L = <city> O = <organization> OU = <organization unit> CN = <MASTER_IP> [ req_ext ] subjectAltName = @alt_names [ alt_names ] DNS.1 = kubernetes DNS.2 = kubernetes.default DNS.3 = kubernetes.default.svc DNS.4 = kubernetes.default.svc.cluster DNS.5 = kubernetes.default.svc.cluster.local IP.1 = <MASTER_IP> IP.2 = <MASTER_CLUSTER_IP> [ v3_ext ] authorityKeyIdentifier=keyid,issuer:always basicConstraints=CA:FALSE keyUsage=keyEncipherment,dataEncipherment extendedKeyUsage=serverAuth,clientAuth subjectAltName=@alt_names
-
Hasilkan permintaan penandatanganan sertifikat berdasarkan file konfigurasi:
openssl req -new -key server.key -out server.csr -config csr.conf
-
Hasilkan sertifikat server menggunakan ca.key, ca.crt dan server.csr:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out server.crt -days 10000 \ -extensions v3_ext -extfile csr.conf
-
Lihat sertifikat:
openssl x509 -noout -text -in ./server.crt
Terakhir, tambahkan parameter yang sama ke dalam parameter mulai server API.
cfssl
cfssl adalah alat lain untuk pembuatan sertifikat.
-
Unduh, buka paket dan siapkan command line tools seperti yang ditunjukkan di bawah ini. Perhatikan bahwa kamu mungkin perlu menyesuaikan contoh perintah berdasarkan arsitektur perangkat keras dan versi cfssl yang kamu gunakan.
curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o cfssl chmod +x cfssl curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o cfssljson chmod +x cfssljson curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o cfssl-certinfo chmod +x cfssl-certinfo
-
Buat direktori untuk menyimpan artifacts dan inisialisasi cfssl:
mkdir cert cd cert ../cfssl print-defaults config > config.json ../cfssl print-defaults csr > csr.json
-
Buat file konfigurasi JSON untuk menghasilkan file CA, misalnya,
ca-config.json
:{ "signing": { "default": { "expiry": "8760h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "8760h" } } } }
-
Buat file konfigurasi JSON untuk CA certificate signing request (CSR), misalnya,
ca-csr.json
. Pastikan untuk mengganti nilai yang ditandai dengan kurung sudut dengan nilai sebenarnya yang ingin kamu gunakan.{ "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names":[{ "C": "<country>", "ST": "<state>", "L": "<city>", "O": "<organization>", "OU": "<organization unit>" }] }
-
Hasilkan kunci CA (
ca-key.pem
) dan sertifikat (ca.pem
):../cfssl gencert -initca ca-csr.json | ../cfssljson -bare ca
-
Buat file konfigurasi JSON untuk menghasilkan kunci dan sertifikat untuk API server, misalnya,
server-csr.json
. Pastikan untuk mengganti nilai dalam kurung sudut dengan nilai sebenarnya yang ingin kamu gunakan.MASTER_CLUSTER_IP
adalah layanan klaster IP untuk server API seperti yang dijelaskan dalam subbagian sebelumnya. Sampel di bawah ini juga mengasumsikan bahwa kamu menggunakancluster.local
sebagai nama domain DNS default.{ "CN": "kubernetes", "hosts": [ "127.0.0.1", "<MASTER_IP>", "<MASTER_CLUSTER_IP>", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [{ "C": "<country>", "ST": "<state>", "L": "<city>", "O": "<organization>", "OU": "<organization unit>" }] }
-
Buat kunci dan sertifikat untuk server API, yang mana awalnya di simpan masing-masing ke dalam file
server-key.pem
danserver.pem
:../cfssl gencert -ca=ca.pem -ca-key=ca-key.pem \ --config=ca-config.json -profile=kubernetes \ server-csr.json | ../cfssljson -bare server
Distribusi Sertifikat Self-Signed CA
Node klien dapat menolak untuk mengakui sertifikat CA yang ditandatangani sendiri sebagai valid. Untuk deployment non-produksi, atau untuk deployment yang berjalan di belakang firewall perusahaan, kamu dapat mendistribusikan sertifikat CA yang ditandatangani sendiri untuk semua klien dan refresh daftar lokal untuk sertifikat yang valid.
Pada setiap klien, lakukan operasi berikut:
sudo cp ca.crt /usr/local/share/ca-certificates/kubernetes.crt
sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....
done.
Sertifikat API
Kamu dapat menggunakan API Certificate.k8s.io
untuk menyediakan
sertifikat x509 yang digunakan untuk autentikasi seperti yang didokumentasikan
di sini.
3.11.3 - Penyedia Layanan Cloud
Laman ini akan menjelaskan bagaimana cara mengelola Kubernetes yang berjalan pada penyedia layanan cloud tertentu.
Kubeadm
Kubeadm merupakan salah satu cara yang banyak digunakan untuk membuat klaster Kubernetes. Kubeadm memiliki beragam opsi untuk mengatur konfigurasi spesifik untuk penyedia layanan cloud. Salah satu contoh yang biasa digunakan pada penyedia cloud in-tree yang dapat diatur dengan kubeadm adalah sebagai berikut:
apiVersion: kubeadm.k8s.io/v1beta1
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
cloud-provider: "openstack"
cloud-config: "/etc/kubernetes/cloud.conf"
---
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.13.0
apiServer:
extraArgs:
cloud-provider: "openstack"
cloud-config: "/etc/kubernetes/cloud.conf"
extraVolumes:
- name: cloud
hostPath: "/etc/kubernetes/cloud.conf"
mountPath: "/etc/kubernetes/cloud.conf"
controllerManager:
extraArgs:
cloud-provider: "openstack"
cloud-config: "/etc/kubernetes/cloud.conf"
extraVolumes:
- name: cloud
hostPath: "/etc/kubernetes/cloud.conf"
mountPath: "/etc/kubernetes/cloud.conf"
Penyedia layanan cloud in-tree biasanya membutuhkan --cloud-provider
dan --cloud-config
yang ditentukan sebelumnya pada command lines untuk kube-apiserver, kube-controller-manager dan
kubelet. Konten dari file yang ditentukan pada --cloud-config
untuk setiap provider akan dijabarkan di bawah ini.
Untuk semua penyedia layanan cloud eksternal, silakan ikuti instruksi pada repositori masing-masing penyedia layanan.
AWS
Bagian ini akan menjelaskan semua konfigurasi yang dapat diatur saat menjalankan Kubernetes pada Amazon Web Services.
Nama Node
Penyedia layanan cloud AWS menggunakan nama DNS privat dari instance AWS sebagai nama dari objek Kubernetes Node.
Load Balancer
Kamu dapat mengatur load balancers eksternal sehingga dapat menggunakan fitur khusus AWS dengan mengatur anotasi seperti di bawah ini.
apiVersion: v1
kind: Service
metadata:
name: example
namespace: kube-system
labels:
run: example
annotations:
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:xx-xxxx-x:xxxxxxxxx:xxxxxxx/xxxxx-xxxx-xxxx-xxxx-xxxxxxxxx #ganti nilai ini
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
spec:
type: LoadBalancer
ports:
- port: 443
targetPort: 5556
protocol: TCP
selector:
app: example
Pengaturan lainnya juga dapat diaplikasikan pada layanan load balancer di AWS dengan menggunakan anotasi-anotasi. Berikut ini akan dijelaskan anotasi yang didukung oleh AWS ELB:
service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval
: Digunakan untuk menentukan interval pengeluaran log akses.service.beta.kubernetes.io/aws-load-balancer-access-log-enabled
: Digunakan untuk mengaktifkan atau menonaktifkan log akses.service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name
: Digunakan untuk menentukan nama bucket S3 log akses.service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix
: Digunakan untuk menentukan prefix bucket S3 log akses.service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
: Digunakan untuk menentukan daftar tag tambahan pada ELB dengan menggunakan parameter key-value. Contoh:"Key1=Val1,Key2=Val2,KeyNoVal1=,KeyNoVal2"
.service.beta.kubernetes.io/aws-load-balancer-backend-protocol
: Digunakan untuk menentukan protokol yang digunakan oleh backend (pod) di belakang listener. Jika diset kehttp
(default) atauhttps
, maka akan dibuat HTTPS listener yang akan mengakhiri koneksi dan meneruskan header. Jika diset kessl
atautcp
, maka akan digunakan "raw" SSL listener. Jika diset kehttp
danaws-load-balancer-ssl-cert
tidak digunakan, maka akan digunakan HTTP listener.service.beta.kubernetes.io/aws-load-balancer-ssl-cert
: Digunakan untuk meminta secure listener. Nilai yang dimasukkan adalah sertifikat ARN yang valid. Info lebih lanjut lihat ELB Listener Config CertARN merupakan IAM atau CM certificate ARN, contoh:arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012
.service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled
: Digunakan untuk mengaktifkan atau menonaktfkan connection draining.service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout
: Digunakan untuk menentukan connection draining timeout.service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout
: Digunakan untuk menentukan idle connection timeout.service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled
: Digunakan untuk mengaktifkan atau menonaktifkan cross-zone load balancing.service.beta.kubernetes.io/aws-load-balancer-extra-security-groups
: Digunakan untuk menentukan grup keamanan yang akan ditambahkan pada ELB yang dibuat.service.beta.kubernetes.io/aws-load-balancer-internal
: Digunakan sebagai indikasi untuk menggunakan internal ELB.service.beta.kubernetes.io/aws-load-balancer-proxy-protocol
: Digunakan untuk mengaktifkan proxy protocol pada ELB. Saat ini hanya dapat menerima nilai*
yang berarti mengaktifkan proxy protocol pada semua ELB backends. Di masa mendatang kamu juga dapat mengatur agar proxy protocol hanya aktif pada backends tertentu..service.beta.kubernetes.io/aws-load-balancer-ssl-ports
: Digunakan untuk menentukan daftar port--yang dipisahkan koma-- yang akan menggunakan SSL/HTTPS listeners. Nilai default yaitu*
(semua).
Informasi anotasi untuk AWS di atas diperoleh dari komentar pada aws.go
Azure
Nama Node
Penyedia layanan cloud Azure menggunakan hostname dari node (yang ditentukan oleh kubelet atau menggunakan --hostname-override
) sebagai nama dari objek Kubernetes Node.
Perlu diperhatikan bahwa nama Kubernetes Node harus sesuai dengan nama Azure VM.
CloudStack
Nama Node
Penyedia layanan cloud CloudStack menggunakan hostname dari node (yang ditentukan kubelet atau menggunakan --hostname-override
) sebagai nama dari objek Kubernetes Node.
Perlu diperhatikan bahwa nama Kubernetes Node harus sesuai dengan nama Cloudstack VM.
GCE
Nama Node
Penyedia layanan cloud GCE menggunakan hostname dari node (yang ditentukan kubelet atau menggunakan --hostname-override
) sebagai nama dari objek Kubernetes Node.
Perlu diperhatikan bahwa segmen pertama dari nama Kubernetes Node harus sesuai dengan nama instance GCE (contoh: sebuah node dengan nama kubernetes-node-2.c.my-proj.internal
harus sesuai dengan instance yang memiliki nama kubernetes-node-2
).
OpenStack
Bagian ini akan menjelaskan semua konfigurasi yang dapat diatur saat menggunakan OpenStack dengan Kubernetes.
Nama Node
Penyedia layanan cloud OpenStack menggunakan nama instance (yang diperoleh dari metadata OpenStack) sebagai nama objek Kubernetes Node. Perlu diperhatikan bahwa nama instance harus berupa nama Kubernetes Node yang valid agar kubelet dapat mendaftarkan objek Node-nya.
Layanan
Penyedia layanan cloud OpenStack menggunakan beragam layanan OpenStack yang tersedia sebagai underlying cloud agar dapat mendukung Kubernetes:
Layanan | Versi API | Wajib |
---|---|---|
Block Storage (Cinder) | V1†, V2, V3 | Tidak |
Compute (Nova) | V2 | Tidak |
Identity (Keystone) | V2‡, V3 | Ya |
Load Balancing (Neutron) | V1§, V2 | Tidak |
Load Balancing (Octavia) | V2 | Tidak |
† Block Storage V1 API tidak lagi didukung, dukungan Block Storage V3 API telah ditambahkan pada Kubernetes 1.9.
‡ Identity V2 API tidak lagi didukung dan akan dihapus oleh penyedia layanan pada rilis mendatang. Pada rilis "Queens", OpenStack tidak lagi mengekspos Identity V2 API.
§ Dukungan Load Balancing V1 API telah dihapus pada Kubernetes 1.9.
Service discovery dilakukan dengan menggunakan katalog layanan/servis (service catalog) yang diatur oleh
OpenStack Identity (Keystone) menggunakan auth-url
yang ditentukan pada konfigurasi
penyedia layanan. Penyedia layanan akan menurunkan fungsionalitas secara perlahan saat layanan OpenStack selain Keystone tidak tersedia dan akan menolak dukungan fitur yang terdampak. Beberapa fitur tertentu dapat diaktifkan atau dinonaktfikan tergantung dari ekstensi yang diekspos oleh Neutron pada underlying cloud.
cloud.conf
Kubernetes berinteraksi dengan OpenStack melalui file cloud.conf. File ini akan menyuplai Kubernetes dengan kredensial dan lokasi dari Openstack auth endpoint. Kamu dapat membuat file cloud.conf dengan menambahkan rincian berikut ini di dalam file:
Konfigurasi pada umumnya
Berikut ini merupakan contoh dan konfigurasi yang biasa digunakan dan akan mencakup semua pilihan yang paling sering dibutuhkan. File ini akan merujuk pada endpoint dari Keystone OpenStack, serta menyediakan rincian bagaimana cara mengautentikasi dengannya, termasuk cara mengatur load balancer:
[Global]
username=user
password=pass
auth-url=https://<keystone_ip>/identity/v3
tenant-id=c869168a828847f39f7f06edd7305637
domain-id=2a73b8f597c04551a0fdc8e95544be8a
[LoadBalancer]
subnet-id=6937f8fa-858d-4bc9-a3a5-18d2c957166a
Global
Konfigurasi untuk penyedia layanan OpenStack berikut ini akan membahas bagian konfigurasi global sehingga harus berada pada bagian [Global]
dari file cloud.conf
:
auth-url
(Wajib): URL dari API keystone digunakan untuk autentikasi. ULR ini dapat ditemukan pada bagian Access dan Security > API Access > Credentials di laman panel kontrol OpenStack.username
(Wajib): Merujuk pada username yang dikelola keystone.password
(Wajib): Merujuk pada kata sandi yang dikelola keystone.tenant-id
(Wajib): Digunakan untuk menentukan id dari project tempat kamu membuat resources.tenant-name
(Opsional): Digunakan untuk menentukan nama dari project tempat kamu ingin membuat resources.trust-id
(Opsional): Digunakan untuk menentukan identifier of the trust untuk digunakan sebagai otorisasi. Suatu trust merepresentasikan otorisasi dari suatu pengguna (the trustor) untuk didelegasikan pada pengguna lain (the trustee), dan dapat digunakan oleh trustee berperan sebagai the trustor. Trust yang tersedia dapat ditemukan pada endpoint/v3/OS-TRUST/trusts
dari Keystone API.domain-id
(Opsional): Digunakan untuk menentukan id dari domain tempat user kamu berada.domain-name
(Opsional): Digunakan untuk menentukan nama dari domain tempat user kamu berada.region
(Opsional): Digunakan untuk menentukan identifier dari region saat digunakan pada multi-region OpenStack cloud. Sebuah region merupakan pembagian secara umum dari deployment OpenStack. Meskipun region tidak wajib berkorelasi secara geografis, suatu deployment dapat menggunakan nama geografis sebagai region identifier sepertius-east
. Daftar region yang tersedia dapat ditemukan pada endpoint/v3/regions
dari Keystone API.ca-file
(Optional): Digunakan untuk menentukan path dari file custom CA.
Saat menggunakan Keystone V3 - yang mengganti istilah tenant menjadi project - nilai tenant-id
akan secara otomatis dipetakan pada project yang sesuai di API.
Load Balancer
Konfigurasi berikut ini digunakan untuk mengatur load
balancer dan harus berada pada bagian [LoadBalancer]
dari file cloud.conf
:
lb-version
(Opsional): Digunakan untuk menonaktifkan pendeteksian versi otomatis. Nilai yang valid yaituv1
atauv2
. Jika tidak ditentukan, maka pendeteksian otomatis akan memilih versi tertinggi yang didukung dari underlying OpenStack cloud.use-octavia
(Opsional): Digunakan untuk menentukan apakah akan menggunakan endpoint dari layanan Octavia LBaaS. Nilai yang valid yaitutrue
ataufalse
. Jika diset nilaitrue
namun Octavia LBaaS V2 tidak dapat ditemukan, maka load balancer akan kembali menggunakan endpoint dari Neutron LBaaS V2. Nilai default adalahfalse
.subnet-id
(Opsional): Digunakan untuk menentukan id dari subnet yang ingin kamu buat load balancer di dalamnya. Nilai id ini dapat dilihat pada Network > Networks. Klik pada jaringan yang sesuai untuk melihat subnet di dalamnya.floating-network-id
(Opsional): Jika diset, maka akan membuat floating IP untuk load balancer.lb-method
(Opsional): Digunakan untuk menentukan algoritma pendistribusian yang akan digunakan. Nilai yang valid yaituROUND_ROBIN
,LEAST_CONNECTIONS
, atauSOURCE_IP
. Jika tidak diset, maka akan menggunakan algoritma default yaituROUND_ROBIN
.lb-provider
(Opsional): Digunakan untuk menentukan penyedia dari load balancer. Jika tidak ditentukan, maka akan menggunakan penyedia default yang ditentukan pada Neutron.create-monitor
(Opsional): Digunakan untuk menentukan apakah akan membuat atau tidak monitor kesehatan untuk Neutron load balancer. Nilai yang valid yaitutrue
danfalse
. Nilai default adalahfalse
. Jika diset nilaitrue
makamonitor-delay
,monitor-timeout
, danmonitor-max-retries
juga harus diset.monitor-delay
(Opsional): Waktu antara pengiriman probes ke anggota dari load balancer. Mohon pastikan kamu memasukkan waktu yang valid. Nilai waktu yang valid yaitu "ns", "us" (atau "µs"), "ms", "s", "m", "h"monitor-timeout
(Opsional): Waktu maksimum dari monitor untuk menunggu balasan ping sebelum timeout. Nilai ini harus lebih kecil dari nilai delay. Mohon pastikan kamu memasukkan waktu yang valid. Nilai waktu yang valid yaitu "ns", "us" (atau "µs"), "ms", "s", "m", "h"monitor-max-retries
(Opsional): Jumlah gagal ping yang diizinkan sebelum mengubah status anggota load balancer menjadi INACTIVE. Harus berupa angka antara 1 dan 10.manage-security-groups
(Opsional): Digunakan untuk menentukan apakah load balancer akan mengelola aturan grup keamanan sendiri atau tidak. Nilai yang valid adalahtrue
danfalse
. Nilai default adalahfalse
. Saat diset ketrue
maka nilainode-security-group
juga harus ditentukan.node-security-group
(Opsional): ID dari grup keamanan yang akan dikelola.
Block Storage
Konfigurasi untuk penyedia layanan OpenStack berikut ini digunakan untuk mengatur penyimpanan blok atau block storage
dan harus berada pada bagian [BlockStorage]
dari file cloud.conf
:
bs-version
(Opsional): Digunakan untuk menonaktifkan fitur deteksi versi otomatis. Nilai yang valid yaituv1
,v2
,v3
danauto
. Jika diset keauto
maka pendeteksian versi otomatis akan memilih versi tertinggi yang didukung oleh underlying OpenStack cloud. Nilai default jika tidak diset adalahauto
.trust-device-path
(Opsional): Pada umumnya nama block device yang ditentukan oleh Cinder (contoh:/dev/vda
) tidak dapat diandalkan. Opsi ini dapat mengatur hal tersebut. Jika diset ketrue
maka akan menggunakan nama block device yang ditentukan oleh Cinder. Nilai default adalahfalse
yang berarti path dari device akan ditentukan oleh nomor serialnya serta pemetaan dari/dev/disk/by-id
, dan ini merupakan cara yang direkomendasikan.ignore-volume-az
(Opsional): Digunakan untuk mengatur penggunaan availability zone saat menautkan volumes Cinder. Jika Nova dan Cinder memiliki availability zones yang berbeda, opsi ini harus disettrue
. Skenario seperti ini yang umumnya terjadi, yaitu saat terdapat banyak Nova availability zones namun hanya ada satu Cinder availability zone. Nilai default yaitufalse
digunakan untuk mendukung penggunaan pada rilis terdahulu, tetapi nilai ini dapat berubah pada rilis mendatang.
Jika menjalankan Kubernetes dengan versi <= 1.8 pada OpenStack yang menggunakan paths alih-alih
menggunakan port untuk membedakan antara endpoints, maka mungkin dibutuhkan untuk
secara eksplisit mengatur parameter bs-version
. Contoh endpoint yang berdasarkan path yaitu
http://foo.bar/volume
sedangkan endpoint yang berdasarkan port memiliki bentuk seperti ini
http://foo.bar:xxx
.
Pada lingkungan yang menggunakan endpoint berdasarkan path dan Kubernetes menggunakan logika deteksi-otomatis yang lama, maka error BS API version autodetection failed.
akan muncul saat mencoba
melepaskan volume. Untuk mengatasi isu ini, dimungkinkan
untuk memaksa penggunaan Cinder API versi 2 dengan menambahkan baris berikut ini pada konfigurasi penyedia cloud:
[BlockStorage]
bs-version=v2
Metadata
Konfigurasi untuk OpenStack berikut ini digunakan untuk mengatur metadata dan
harus berada pada bagian [Metadata]
dari file cloud.conf
:
-
search-order
(Opsional): Konfigurasi berikut ini digunakan untuk mengatur bagaimana cara provider mengambil metadata terkait dengan instance yang dijalankannya. Nilai default yaituconfigDrive,metadataService
yang berarti provider akan mengambil metadata terkait instance dari config drive terlebih dahulu jika tersedia, namun jika tidak maka akan menggunakan layanan metadata. Nilai alternatif lainnya yaitu:configDrive
- Hanya mengambil metadata instance dari config drive.metadataService
- Hanya mengambil data instance dari layanan metadata.metadataService,configDrive
- Mengambil metadata instance dari layanan metadata terlebih dahulu jika tersedia, jika tidak maka akan mengambil dari config drive.
Pengaturan ini memang sebaiknya dilakukan sebab metadata pada config drive bisa saja lambat laun akan kedaluwarsa, sedangkan layanan metadata akan selalu menyediakan metadata yang paling mutakhir. Tidak semua penyedia layanan cloud OpenStack menyediakan kedua layanan config drive dan layanan metadata dan mungkin hanya salah satu saja yang tersedia. Oleh sebab itu nilai default diatur agar dapat memeriksa keduanya.
Router
Konfigurasi untuk Openstack berikut ini digunakan untuk mengatur plugin jaringan Kubernetes kubenet
dan harus berada pada bagian [Router]
dari file cloud.conf
:
router-id
(Opsional): Jika Neutron pada underlying cloud mendukung ekstensiextraroutes
maka gunakanrouter-id
untuk menentukan router mana yang akan ditambahkan rute di dalamnya. Router yang dipilih harus menjangkau jaringan privat tempat node klaster berada (biasanya hanya ada satu jaringan node, dan nilai ini harus nilai dari default router pada jaringan node). Nilai ini dibutuhkan untuk dapat menggunakan kubenet pada OpenStack.
OVirt
Nama Node
Penyedia layanan cloud OVirt menggunakan hostname dari node (yang ditentukan kubelet atau menggunakan --hostname-override
) sebagai nama dari objek Kubernetes Node.
Perlu diperhatikan bahwa nama Kubernetes Node harus sesuai dengan VM FQDN (yang ditampilkan oleh OVirt di bawah <vm><guest_info><fqdn>...</fqdn></guest_info></vm>
)
Photon
Nama Node
Penyedia layanan cloud Photon menggunakan hostname dari node (yang ditentukan kubelet atau menggunakan --hostname-override
) sebagai nama dari objek Kubernetes Node.
Perlu diperhatikan bahwa nama Kubernetes Node name harus sesuai dengan nama Photon VM (atau jika overrideIP
diset ke true pada --cloud-config
, nama Kubernetes Node harus sesuai dengan alamat IP Photon VM).
VSphere
Nama Node
Penyedia layanan cloud VSphere menggunakan hostname yang terdeteksi dari node (yang ditentukan oleh kubelet) sebagai nama dari objek Kubernetes Node.
Parameter --hostname-override
diabaikan oleh penyedia layanan cloud VSphere.
IBM Cloud Kubernetes Service
Node Komputasi
Saat menggunakan layanan IBM Cloud Kubernetes Service, kamu dapat membuat klaster yang terdiri dari campuran antara mesin virtual dan fisik (bare metal) sebagai node di single zone atau multiple zones pada satu region. Untuk informasi lebih lanjut, lihat Perencanaan klaster dan pengaturan worker node.
Nama dari objek Kubernetes Node yaitu alamat IP privat dari IBM Cloud Kubernetes Service worker node instance.
Jaringan
Penyedia layanan IBM Cloud Kubernetes Service menyediakan VLAN untuk membuat jaringan node yang terisolasi dengan kinerja tinggi. Kamu juga dapat membuat custom firewall dan policy jaringan Calico untuk menambah lapisan perlindungan ekstra bagi klaster kamu, atau hubungkan klaster kamu dengan on-prem data center via VPN. Untuk informasi lebih lanjut, lihat Perencanaan jaringan privat dan in-cluster.
Untuk membuka aplikasi ke publik atau di dalam klaster, kamu dapat menggunakan NodePort, LoadBalancer, atau Ingress. Kamu juga dapat menyesuaikan aplikasi load balancer Ingress dengan anotasi. Untuk informasi lebih lanjut, lihat Perencanaan untuk membuka aplikasi dengan jaringan eksternal.
Penyimpanan
Penyedia layanan IBM Cloud Kubernetes Service memanfaatkan Kubernetes-native persistent volumes agar pengguna dapat melakukan mount file, block, dan penyimpanan objek cloud ke aplikasi mereka. Kamu juga dapat menggunakan database-as-a-service dan add-ons pihak ketiga sebagai penyimpanan persistent untuk data kamu. Untuk informasi lebih lanjut, lihat Perencanaan penyimpanan persistent yang selalu tersedia (highly available).
Baidu Cloud Container Engine
Nama Node
Penyedia layanan cloud Baidu menggunakan alamat IP privat dari node (yang ditentukan oleh kubelet atau menggunakan --hostname-override
) sebagai nama dari objek Kubernetes Node.
Perlu diperhatikan bahwa nama Kubernetes Node harus sesuai dengan alamat IP privat dari Baidu VM.
3.11.4 - Mengelola Resource
Kamu telah melakukan deploy pada aplikasimu dan mengeksposnya melalui sebuah service. Lalu? Kubernetes menyediakan berbagai peralatan untuk membantu mengatur mekanisme deploy aplikasi, termasuk pengaturan kapasitas dan pembaruan. Diantara fitur yang akan didiskusikan lebih mendalam yaitu berkas konfigurasi dan label.
Mengelola konfigurasi resource
Banyak aplikasi memerlukan beberapa resource, seperti Deployment dan Service. Pengelolaan beberapa resource dapat disederhanakan dengan mengelompokkannya dalam berkas yang sama (dengan pemisah ---
pada YAML). Contohnya:
apiVersion: v1
kind: Service
metadata:
name: my-nginx-svc
labels:
app: nginx
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Beberapa resource dapat dibuat seolah-olah satu resource:
kubectl apply -f https://k8s.io/examples/application/nginx-app.yaml
service/my-nginx-svc created
deployment.apps/my-nginx created
Resource akan dibuat dalam urutan seperti pada berkas. Oleh karena itu, lebih baik menyalakan service lebih dahulu agar menjamin scheduler dapat menyebar pod yang terkait service selagi pod dibangkitkan oleh controller, seperti Deployment.
kubectl apply
juga dapat menerima beberapa argumen -f
:
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-svc.yaml -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
Selain berkas, kita dapat juga memasukkan direktori sebagai argumen:
kubectl apply -f https://k8s.io/examples/application/nginx/
kubectl
akan membaca berkas apapun yang berakhiran .yaml
, .yml
, or .json
.
Sangat disarankan untuk meletakkan sumber daya yang ada dalam microservice atau tier aplikasi yang sama dalam satu berkas, dan mengelompokkan semua berkas terkait aplikasimu dalam satu direktori. Jika tier masing-masing aplikasi terikat dengan DNS, maka kamu dapat melakukan deploy semua komponen teknologi yang dibutuhkan bersama-sama.
Lokasi konfigurasi dapat juga diberikan dalam bentuk URL. Ini berguna ketika ingin menjalankan berkas konfigurasi dari Github:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx created
Operasi majemuk dalam kubectl
Pembuatan resource bukanlah satu-satunya operasi yang bisa dijalankan kubectl
secara majemuk. Contoh lainnya adalah mengekstrak nama resource dari berkas konfigurasi untuk menjalankan operasi lainnya, seperti untuk menghapus resource yang telah dibuat:
kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
Pada kasus dua resource, mudah untuk memasukkan keduanya pada command line menggunakan sintaks resource/nama:
kubectl delete deployments/my-nginx services/my-nginx-svc
Namun, untuk resource yang lebih banyak, memasukkan selektor (label query) menggunakan -l
atau --selector
untuk memfilter resource berdasarkan label akan lebih mudah:
kubectl delete deployment,services -l app=nginx
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
Karena kubectl
mengembalikan nama resource yang sama dengan sintaks yang diterima, mudah untuk melanjutkan operasi menggunakan $()
atau xargs
:
kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service)
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx-svc LoadBalancer 10.0.0.208 <pending> 80/TCP 0s
Dengan perintah di atas, pertama kita buat resource di dalam examples/application/nginx/
. Lalu tampilkan resources yang terbentuk dengan format keluaran -o name
(menampilkan tiap resource dalam format resource/nama). Kemudian lakukan grep
hanya pada "service", dan tampilkan dengan kubectl get
.
Untuk dapat menggunakan perintah di atas pada direktori yang bertingkat, kamu dapat memberi argumen --recursive
atau -R
bersama dengan argumen --filename,-f
.
Misalnya ada sebuah direktori project/k8s/development
memuat semua manifests yang berkaitan dengan development environment. Manifest akan tersusun berdasarkan tipe resource:
project/k8s/development
├── configmap
│ └── my-configmap.yaml
├── deployment
│ └── my-deployment.yaml
└── pvc
└── my-pvc.yaml
Secara default, menjalankan operasi majemuk pada project/k8s/development
hanya akan terbatas pada direktori terluar saja. Sehingga ketika kita menjalankan operasi pembuatan dengan perintah berikut, kita akan mendapatkan pesan kesalahan:
kubectl apply -f project/k8s/development
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)
Solusinya, tambahkan argumen --recursive
atau -R
bersama dengan --filename,-f
, seperti:
kubectl apply -f project/k8s/development --recursive
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
Argumen --recursive
berjalan pada operasi apapun yang menerima argumen --filename,-f
seperti: kubectl {create,get,delete,describe,rollout} etc.
Argumen --recursive
juga berjalan saat beberapa argumen -f
diberikan:
kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive
namespace/development created
namespace/staging created
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
Jika kamu tertarik mempelajari lebih lanjut tentang kubectl
, silahkan baca Ikhtisar kubectl.
Memakai label secara efektif
Contoh yang kita lihat sejauh ini hanya menggunakan paling banyak satu label pada resource. Ada banyak skenario ketika membutuhkan beberapa label untuk membedakan sebuah kelompok dari yang lainnya.
Sebagai contoh, aplikasi yang berbeda akan menggunakan label app
yang berbeda, tapi pada aplikasi multitier, seperti pada contoh buku tamu, tiap tier perlu dibedakan. Misal untuk menandai tier frontend bisa menggunakan label:
labels:
app: guestbook
tier: frontend
sementara itu Redis master dan slave memiliki label tier
yang berbeda. Bisa juga menggunakan label tambahan role
:
labels:
app: guestbook
tier: backend
role: master
dan
labels:
app: guestbook
tier: backend
role: slave
Label memungkinkan kita untuk memilah resource dengan pembeda berupa label:
kubectl apply -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
NAME READY STATUS RESTARTS AGE APP TIER ROLE
guestbook-fe-4nlpb 1/1 Running 0 1m guestbook frontend <none>
guestbook-fe-ght6d 1/1 Running 0 1m guestbook frontend <none>
guestbook-fe-jpy62 1/1 Running 0 1m guestbook frontend <none>
guestbook-redis-master-5pg3b 1/1 Running 0 1m guestbook backend master
guestbook-redis-slave-2q2yf 1/1 Running 0 1m guestbook backend slave
guestbook-redis-slave-qgazl 1/1 Running 0 1m guestbook backend slave
my-nginx-divi2 1/1 Running 0 29m nginx <none> <none>
my-nginx-o0ef1 1/1 Running 0 29m nginx <none> <none>
kubectl get pods -lapp=guestbook,role=slave
NAME READY STATUS RESTARTS AGE
guestbook-redis-slave-2q2yf 1/1 Running 0 3m
guestbook-redis-slave-qgazl 1/1 Running 0 3m
Deploy dengan Canary
Skenario lain yang menggunakan beberapa label yaitu saat membedakan deployment komponen yang sama namun dengan rilis atau konfigurasi yang berbeda. Adalah praktik yang umum untuk mendeploy sebuah canary dari rilis aplikasi yang baru (berdasarkan tag image dalam templat pod) bersamaan dengan rilis sebelumnya. Ini memungkinkan rilis yang baru dapat menerima live traffic sebelum benar-benar menggantikan rilis yang lama.
Salah satu alternatif yaitu kamu dapat memakai label track
untuk membedakan antar rilis.
Rilis primer dan stabil akan memiliki label track
yang berisi stable
:
name: frontend
replicas: 3
...
labels:
app: guestbook
tier: frontend
track: stable
...
image: gb-frontend:v3
kemudian kamu buat lagi rilis frontend buku tamu yang membawa label track
yang berbeda (misal canary
), sehingga pod dalam kedua rilis tidak beririsan:
name: frontend-canary
replicas: 1
...
labels:
app: guestbook
tier: frontend
track: canary
...
image: gb-frontend:v4
Servis frontend akan meliputi kedua set replika dengan menentukan subset bersama dari para labelnya (tanpa track
). Sehingga traffic akan diarahkan ke kedua aplikasi:
selector:
app: guestbook
tier: frontend
Kamu dapat mengatur jumlah replika rilis stable dan canary untuk menentukan rasio dari tiap rilis yang akan menerima traffic production live (dalam kasus ini 3:1). Ketika telah yakin, kamu dapat memindahkan track stable ke rilis baru dan menghapus canary.
Untuk contoh yang lebih jelas, silahkan cek tutorial melakukan deploy Ghost.
Memperbarui label
Kadang, pod dan resource lain yang sudah ada harus dilabeli ulang sebelum membuat resource baru. Hal ini dapat dilakukan dengan perintah kubectl label
.
Contohnya jika kamu ingin melabeli ulang semua pod nginx sebagai frontend tier, tinggal jalankan:
kubectl label pods -l app=nginx tier=fe
pod/my-nginx-2035384211-j5fhi labeled
pod/my-nginx-2035384211-u2c7e labeled
pod/my-nginx-2035384211-u3t6x labeled
Perintah ini melakukan filter pada semua pod dengan label "app=nginx", lalu melabelinya dengan "tier=fe". Untuk melihat pod yang telah dilabeli, jalankan:
kubectl get pods -l app=nginx -L tier
NAME READY STATUS RESTARTS AGE TIER
my-nginx-2035384211-j5fhi 1/1 Running 0 23m fe
my-nginx-2035384211-u2c7e 1/1 Running 0 23m fe
my-nginx-2035384211-u3t6x 1/1 Running 0 23m fe
Akan muncul semua pod dengan "app=nginx" dan sebuah kolom label tambahan yaitu tier (ditentukan dengan -L
atau --label-columns
).
Untuk informasi lebih lanjut, silahkan baca label dan kubectl label.
Memperbarui anotasi
Kadang resource perlu ditambahkan anotasi. Anotasi adalah metadata sembarang yang tidak unik, seperti tools, libraries, dsb yang digunakan oleh klien API . Ini dapat dilakukan dengan kubectl annotate
. Sebagai contoh:
kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
kubectl get pods my-nginx-v4-9gw19 -o yaml
apiVersion: v1
kind: pod
metadata:
annotations:
description: my frontend running nginx
...
Untuk informasi lebih lanjut, silahkan lihat laman annotations dan kubectl annotate.
Memperbesar dan memperkecil aplikasi kamu
Saat beban aplikasi naik maupun turun, mudah untuk mengubah kapasitas dengan kubectl
. Contohnya, untuk menurunkan jumlah replika nginx dari 3 ke 1, lakukan:
kubectl scale deployment/my-nginx --replicas=1
deployment.extensions/my-nginx scaled
Sekarang kamu hanya memiliki satu pod yang dikelola oleh deployment.
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
my-nginx-2035384211-j5fhi 1/1 Running 0 30m
Agar sistem dapat menyesuaikan jumlah replika nginx yang dibutuhkan secara otomatis dari 1 hingga 3, lakukan:
kubectl autoscale deployment/my-nginx --min=1 --max=3
horizontalpodautoscaler.autoscaling/my-nginx autoscaled
Sekarang jumlah replika nginx akan secara otomatis naik dan turun sesuai kebutuhan.
Informasi tambahan dapat dilihat pada dokumen kubectl scale, kubectl autoscale dan horizontal pod autoscaler.
Pembaruan resource di tempat
Kadang kita perlu membuat pembaruan kecil, yang tidak mengganggu pada resource yang telah dibuat.
kubectl apply
Disarankan untuk menyimpan berkas-berkas konfigurasi dalam source control (lihat konfigurasi sebagai kode). Sehingga berkas dapat dipelihara dan diatur dalam versi bersama dengan kode milik resource yang diatur oleh konfigurasi tersebut. Berikutnya, kamu dapat menggunakan kubectl apply
untuk membarui perubahan konfigurasi ke klaster.
Perintah ini akan membandingkan versi konfigurasi yang disuplai dengan versi sebelumnya yang telah berjalan dan memasang perubahan yang kamu buat tanpa mengganti properti yang tidak berubah sama sekali.
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx configured
Perhatikan bahwa kubectl apply
memasang anotasi pada resource untuk menentukan perubahan pada konfigurasi sejak terakhir dipanggil. Ketika dijalankan, kubectl apply
melakukan pembandingan three-way antara konfigurasi sebelumnya, masukan yang disuplai, dan konfigurasi resource sekarang, untuk dapat menentukan cara memodifikasi resource.
Saat ini, resource dibuat tanpa ada anotasi. Jadi pemanggilan pertama pada kubectl apply
akan dikembalikan pada perbandingan two-way antara masukan pengguna dan konfigurasi resource sekarang. Saat pemanggilan pertama ini, tidak ada penghapusan set properti yang terdeteksi saat resource dibuat. Sehingga, tidak ada yang dihapus.
Tiap kubectl apply
, atau perintah lain yang memodifikasi konfigurasi seperti kubectl replace
dan kubectl edit
dijalankan, anotasi akan diperbarui. Sehingga memungkinkan operasi kubectl apply
untuk mendeteksi dan melakukan penghapusan secara perbandingan three-way.
kubectl edit
Sebagai alternatif, kamu juga dapat membarui resource dengan kubectl edit
:
kubectl edit deployment/my-nginx
Ini sama dengan melakukan get
pada resource, mengubahnya di text editor, kemudian menjalankanapply
pada resource dengan versi terkini:
kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
vi /tmp/nginx.yaml
# lakukan pengubahan, lalu simpan berkas
kubectl apply -f /tmp/nginx.yaml
deployment.apps/my-nginx configured
rm /tmp/nginx.yaml
Cara demikian memungkinkan kamu membuat perubahan signifikan dengan mudah. Lihat bahwa kamu juga dapat menentukan editor dengan variabel environment EDITOR
atau KUBE_EDITOR
.
Untuk informasi tambahan, silahkan lihat laman kubectl edit.
kubectl patch
Kamu dapat menggunakan kubectl patch
untuk membarui obyek API di tempat. Perintah ini mendukung patch JSON, patch gabungan JSON, dan strategic merge patch. Lihat
Update API Objects in Place Using kubectl patch
dan
kubectl patch.
Pembaruan disruptif
Pada kasus tertentu, kamu mungkin perlu memperbarui field resource yang tidak dapat diperbarui setelah diinisiasi atau kamu ingin membuat perubahan rekursif segera, seperti memperbaiki pod yang rusak saat menjalankan Deployment. Untuk mengubah field seperti itu, gunakan replace --force
yang akan menghapus dan membuat ulang resource. Dalam kasus ini kamu dapat mengubah berkas konfigurasi awalnya:
kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced
Membarui aplikasi tanpa memadamkan servis
Suatu saat, kamu akan perlu untuk membarui aplikasi yang telah terdeploy, biasanya dengan mengganti image atau tag sebagaimana dalam skenario canary deployment di atas. kubectl
mendukung beberapa operasi pembaruan, masing-masing dapat digunakan pada skenario berbeda.
Kami akan memandumu untuk membuat dan membarui aplikasi melalui Deployment.
Misal kamu telah menjalankan nginx versi 1.7.9:
kubectl run my-nginx --image=nginx:1.7.9 --replicas=3
deployment.apps/my-nginx created
Untuk memperbarui versi ke 1.9.1, ganti .spec.template.spec.containers[0].image
dari nginx:1.7.9
ke nginx:1.9.1
, dengan perintah kubectl yang telah dipelajari di atas.
kubectl edit deployment/my-nginx
Selesai! Deployment akan memperbarui aplikasi nginx yang terdeploy secara berangsur di belakang. Dia akan menjamin hanya ada sekian replika lama yang akan down selagi pembaruan berjalan dan hanya ada sekian replika baru akan dibuat melebihi jumlah pod. Untuk mempelajari lebih lanjut, kunjungi laman Deployment.
Selanjutnya
3.11.5 - Jaringan Kluster
Jaringan adalah bagian utama dari Kubernetes, tetapi bisa menjadi sulit untuk memahami persis bagaimana mengharapkannya bisa bekerja. Ada 4 masalah yang berbeda untuk diatasi:
- Komunikasi antar kontainer yang sangat erat: hal ini diselesaikan oleh
Pod dan komunikasi
localhost
. - Komunikasi antar Pod: ini adalah fokus utama dari dokumen ini.
- Komunikasi Pod dengan Service: ini terdapat di Service.
- Komunikasi eksternal dengan Service: ini terdapat di Service.
Kubernetes adalah tentang berbagi mesin antar aplikasi. Pada dasarnya, saat berbagi mesin harus memastikan bahwa dua aplikasi tidak mencoba menggunakan port yang sama. Mengkoordinasikan port di banyak pengembang sangat sulit dilakukan pada skala yang berbeda dan memaparkan pengguna ke masalah tingkat kluster yang di luar kendali mereka.
Alokasi port yang dinamis membawa banyak komplikasi ke sistem - setiap aplikasi harus menganggap port sebagai flag, server API harus tahu cara memasukkan nomor port dinamis ke dalam blok konfigurasi, Service-Service harus tahu cara menemukan satu sama lain, dll. Sebaliknya daripada berurusan dengan ini, Kubernetes mengambil pendekatan yang berbeda.
Model jaringan Kubernetes
Setiap Pod mendapatkan alamat IP sendiri. Ini berarti kamu tidak perlu secara langsung membuat tautan antara Pod dan kamu hampir tidak perlu berurusan dengan memetakan port kontainer ke port pada host. Ini menciptakan model yang bersih, kompatibel dengan yang sebelumnya dimana Pod dapat diperlakukan seperti halnya VM atau host fisik dari perspektif alokasi port, penamaan, service discovery, load balancing, konfigurasi aplikasi, dan migrasi.
Kubernetes memberlakukan persyaratan mendasar berikut pada setiap implementasi jaringan (kecuali kebijakan segmentasi jaringan yang disengaja):
- Pod pada suatu Node dapat berkomunikasi dengan semua Pod pada semua Node tanpa NAT
- agen pada suatu simpul (mis. daemon sistem, kubelet) dapat berkomunikasi dengan semua Pod pada Node itu
Catatan: Untuk platform yang mendukung Pod yang berjalan di jaringan host (mis. Linux):
- Pod di jaringan host dari sebuah Node dapat berkomunikasi dengan semua Pod pada semua Node tanpa NAT
Model ini tidak hanya sedikit kompleks secara keseluruhan, tetapi pada prinsipnya kompatibel dengan keinginan Kubernetes untuk memungkinkan low-friction porting dari aplikasi dari VM ke kontainer. Jika pekerjaan kamu sebelumnya dijalankan dalam VM, VM kamu memiliki IP dan dapat berbicara dengan VM lain di proyek yang sama. Ini adalah model dasar yang sama.
Alamat IP Kubernetes ada di lingkup Pod - kontainer dalam Pod berbagi jaringan namespace mereka - termasuk alamat IP mereka. Ini berarti bahwa kontainer dalam Pod semua dapat mencapai port satu sama lain di _localhost_
. Ini juga berarti bahwa kontainer dalam Pod harus mengoordinasikan penggunaan port, tetapi ini tidak berbeda dari proses di VM. Ini disebut model "IP-per-pod".
Bagaimana menerapkan model jaringan Kubernetes
Ada beberapa cara agar model jaringan ini dapat diimplementasikan. Dokumen ini bukan studi lengkap tentang berbagai metode, tetapi semoga berfungsi sebagai pengantar ke berbagai teknologi dan berfungsi sebagai titik awal.
Opsi jaringan berikut ini disortir berdasarkan abjad - urutan tidak menyiratkan status istimewa apa pun.
ACI
Infrastruktur Sentral Aplikasi Cisco menawarkan solusi SDN overlay dan underlay terintegrasi yang mendukung kontainer, mesin virtual, dan bare metal server. ACI menyediakan integrasi jaringan kontainer untuk ACI. Tinjauan umum integrasi disediakan di sini.
AOS dari Apstra
AOS adalah sistem Jaringan Berbasis Intent yang menciptakan dan mengelola lingkungan pusat data yang kompleks dari platform terintegrasi yang sederhana. AOS memanfaatkan desain terdistribusi sangat scalable untuk menghilangkan pemadaman jaringan sambil meminimalkan biaya.
Desain Referensi AOS saat ini mendukung host yang terhubung dengan Lapis-3 yang menghilangkan masalah peralihan Lapis-2 yang lama. Host Lapis-3 ini bisa berupa server Linux (Debian, Ubuntu, CentOS) yang membuat hubungan tetangga BGP secara langsung dengan top of rack switches (TORs). AOS mengotomatisasi kedekatan perutean dan kemudian memberikan kontrol yang halus atas route health injections (RHI) yang umum dalam deployment Kubernetes.
AOS memiliki banyak kumpulan endpoint REST API yang memungkinkan Kubernetes dengan cepat mengubah kebijakan jaringan berdasarkan persyaratan aplikasi. Peningkatan lebih lanjut akan mengintegrasikan model Grafik AOS yang digunakan untuk desain jaringan dengan penyediaan beban kerja, memungkinkan sistem manajemen ujung ke ujung untuk layanan cloud pribadi dan publik.
AOS mendukung penggunaan peralatan vendor umum dari produsen termasuk Cisco, Arista, Dell, Mellanox, HPE, dan sejumlah besar sistem white-box dan sistem operasi jaringan terbuka seperti Microsoft SONiC, Dell OPX, dan Cumulus Linux.
Detail tentang cara kerja sistem AOS dapat diakses di sini: http://www.apstra.com/products/how-it-works/
AWS VPC CNI untuk Kubernetes
AWS VPC CNI menawarkan jaringan AWS Virtual Private Cloud (VPC) terintegrasi untuk kluster Kubernetes. Plugin CNI ini menawarkan throughput dan ketersediaan tinggi, latensi rendah, dan jitter jaringan minimal. Selain itu, pengguna dapat menerapkan jaringan AWS VPC dan praktik keamanan terbaik untuk membangun kluster Kubernetes. Ini termasuk kemampuan untuk menggunakan catatan aliran VPC, kebijakan perutean VPC, dan grup keamanan untuk isolasi lalu lintas jaringan.
Menggunakan plugin CNI ini memungkinkan Pod Kubernetes memiliki alamat IP yang sama di dalam Pod seperti yang mereka lakukan di jaringan VPC. CNI mengalokasikan AWS Elastic Networking Interfaces (ENIs) ke setiap node Kubernetes dan menggunakan rentang IP sekunder dari setiap ENI untuk Pod pada Node. CNI mencakup kontrol untuk pra-alokasi ENI dan alamat IP untuk waktu mulai Pod yang cepat dan memungkinkan kluster besar hingga 2.000 Node.
Selain itu, CNI dapat dijalankan bersama Calico untuk penegakan kebijakan jaringan. Proyek AWS VPC CNI adalah open source dengan dokumentasi di GitHub.
Big Cloud Fabric dari Big Switch Networks
Big Cloud Fabric adalah arsitektur jaringan asli layanan cloud, yang dirancang untuk menjalankan Kubernetes di lingkungan cloud pribadi / lokal. Dengan menggunakan SDN fisik & virtual terpadu, Big Cloud Fabric menangani masalah yang sering melekat pada jaringan kontainer seperti penyeimbangan muatan, visibilitas, pemecahan masalah, kebijakan keamanan & pemantauan lalu lintas kontainer.
Dengan bantuan arsitektur multi-penyewa Pod virtual pada Big Cloud Fabric, sistem orkestrasi kontainer seperti Kubernetes, RedHat OpenShift, Mesosphere DC/OS & Docker Swarm akan terintegrasi secara alami bersama dengan sistem orkestrasi VM seperti VMware, OpenStack & Nutanix. Pelanggan akan dapat terhubung dengan aman berapa pun jumlah klusternya dan memungkinkan komunikasi antar penyewa di antara mereka jika diperlukan.
Terbaru ini BCF diakui oleh Gartner sebagai visioner dalam Magic Quadrant. Salah satu penyebaran BCF Kubernetes di tempat (yang mencakup Kubernetes, DC/OS & VMware yang berjalan di beberapa DC di berbagai wilayah geografis) juga dirujuk di sini.
Cilium
Cilium adalah perangkat lunak open source untuk menyediakan dan secara transparan mengamankan konektivitas jaringan antar kontainer aplikasi. Cilium mengetahui L7/HTTP dan dapat memberlakukan kebijakan jaringan pada L3-L7 menggunakan model keamanan berbasis identitas yang dipisahkan dari pengalamatan jaringan.
CNI-Genie dari Huawei
CNI-Genie adalah plugin CNI yang memungkinkan Kubernetes [secara bersamaan memiliki akses ke berbagai implementasi](https://github.com/Huawei-PaaS /CNI-Genie/blob/master/docs/multiple-cni-plugins/README.md#what-cni-genie-feature-1-multiple-cni-plugins-enables) dari [model jaringan Kubernetes] (https://git.k8s.io/website/docs/concepts/cluster-administration/networking.md#kubernetes-model) dalam runtime. Ini termasuk setiap implementasi yang berjalan sebagai plugin CNI, seperti Flannel, Calico, Romana, Weave-net.
CNI-Genie juga mendukung menetapkan beberapa alamat IP ke sebuah Pod, masing-masing dari plugin CNI yang berbeda.
cni-ipvlan-vpc-k8s
cni-ipvlan-vpc-k8s berisi satu set plugin CNI dan IPAM untuk menyediakan kemudahan, host-lokal, latensi rendah, throughput tinggi , dan tumpukan jaringan yang sesuai untuk Kubernetes dalam lingkungan Amazon Virtual Private Cloud (VPC) dengan memanfaatkan Amazon Elastic Network Interfaces (ENI) dan mengikat IP yang dikelola AWS ke Pod-Pod menggunakan driver IPvlan kernel Linux dalam mode L2.
Plugin ini dirancang untuk secara langsung mengkonfigurasi dan deploy dalam VPC. Kubelet melakukan booting dan kemudian mengkonfigurasi sendiri dan memperbanyak penggunaan IP mereka sesuai kebutuhan tanpa memerlukan kompleksitas yang sering direkomendasikan untuk mengelola jaringan overlay, BGP, menonaktifkan pemeriksaan sumber/tujuan, atau menyesuaikan tabel rute VPC untuk memberikan subnet per instance ke setiap host (yang terbatas hingga 50-100 masukan per VPC). Singkatnya, cni-ipvlan-vpc-k8s secara signifikan mengurangi kompleksitas jaringan yang diperlukan untuk menggunakan Kubernetes yang berskala di dalam AWS.
Contiv
Contiv menyediakan jaringan yang dapat dikonfigurasi (native l3 menggunakan BGP, overlay menggunakan vxlan, classic l2, atau Cisco-SDN / ACI) untuk berbagai kasus penggunaan. Contiv semuanya open sourced.
Contrail / Tungsten Fabric
Contrail, berdasarkan Tungsten Fabric, adalah platform virtualisasi jaringan dan manajemen kebijakan multi-cloud yang benar-benar terbuka. Contrail dan Tungsten Fabric terintegrasi dengan berbagai sistem orkestrasi seperti Kubernetes, OpenShift, OpenStack dan Mesos, dan menyediakan mode isolasi yang berbeda untuk mesin virtual, banyak kontainer / banyak Pod dan beban kerja bare metal.
DANM
[DANM] (https://github.com/nokia/danm) adalah solusi jaringan untuk beban kerja telco yang berjalan di kluster Kubernetes. Dibangun dari komponen-komponen berikut:
- Plugin CNI yang mampu menyediakan antarmuka IPVLAN dengan fitur-fitur canggih
- Modul IPAM built-in dengan kemampuan mengelola dengan jumlah banyak, cluster-wide, discontinous jaringan L3 dan menyediakan skema dinamis, statis, atau tidak ada permintaan skema IP
- Metaplugin CNI yang mampu melampirkan beberapa antarmuka jaringan ke kontainer, baik melalui CNI sendiri, atau mendelegasikan pekerjaan ke salah satu solusi CNI populer seperti SRI-OV, atau Flannel secara paralel
- Pengontrol Kubernetes yang mampu mengatur secara terpusat antarmuka VxLAN dan VLAN dari semua host Kubernetes
- Pengontrol Kubernetes lain yang memperluas konsep service discovery berbasis servis untuk bekerja di semua antarmuka jaringan Pod
Dengan toolset ini, DANM dapat memberikan beberapa antarmuka jaringan yang terpisah, kemungkinan untuk menggunakan ujung belakang jaringan yang berbeda dan fitur IPAM canggih untuk Pod.
Flannel
[Flannel] (https://github.com/coreos/flannel#flannel) adalah jaringan overlay yang sangat sederhana yang memenuhi persyaratan Kubernetes. Banyak orang telah melaporkan kesuksesan dengan Flannel dan Kubernetes.
Google Compute Engine (GCE)
Untuk skrip konfigurasi kluster Google Compute Engine, perutean lanjutan digunakan untuk menetapkan setiap VM subnet (standarnya adalah /24
- 254 IP). Setiap lalu lintas yang terikat untuk subnet itu akan dialihkan langsung ke VM oleh fabric jaringan GCE. Ini adalah tambahan untuk alamat IP "utama" yang ditugaskan untuk VM, yang NAT'ed untuk akses internet keluar. Sebuah linux bridge (disebut cbr0
) dikonfigurasikan untuk ada pada subnet itu, dan diteruskan ke flag -bridge
milik docker.
Docker dimulai dengan:
DOCKER_OPTS="--bridge=cbr0 --iptables=false --ip-masq=false"
Jembatan ini dibuat oleh Kubelet (dikontrol oleh flag --network-plugin=kubenet
) sesuai dengan .spec.podCIDR
yang dimiliki oleh Node.
Docker sekarang akan mengalokasikan IP dari blok cbr-cidr
. Kontainer dapat menjangkau satu sama lain dan Node di atas jembatan cbr0
. IP-IP tersebut semuanya dapat dirutekan dalam jaringan proyek GCE.
GCE sendiri tidak tahu apa-apa tentang IP ini, jadi tidak akan NAT untuk lalu lintas internet keluar. Untuk mencapai itu aturan iptables digunakan untuk menyamar (alias SNAT - untuk membuatnya seolah-olah paket berasal dari lalu lintas Node
itu sendiri) yang terikat untuk IP di luar jaringan proyek GCE (10.0.0.0/8).
iptables -t nat -A POSTROUTING ! -d 10.0.0.0/8 -o eth0 -j MASQUERADE
Terakhir IP forwarding diaktifkan di kernel (sehingga kernel akan memproses paket untuk kontainer yang dijembatani):
sysctl net.ipv4.ip_forward=1
Hasil dari semua ini adalah bahwa semua Pod dapat saling menjangkau dan dapat keluar lalu lintas ke internet.
Jaguar
Jaguar adalah solusi open source untuk jaringan Kubernetes berdasarkan OpenDaylight. Jaguar menyediakan jaringan overlay menggunakan vxlan dan Jaguar CNIPlugin menyediakan satu alamat IP per Pod.
Knitter
Knitter adalah solusi jaringan yang mendukung banyak jaringan di Kubernetes. Solusi ini menyediakan kemampuan manajemen penyewa dan manajemen jaringan. Knitter mencakup satu set solusi jaringan kontainer NFV ujung ke ujung selain beberapa pesawat jaringan, seperti menjaga alamat IP untuk aplikasi, migrasi alamat IP, dll.
Kube-OVN
Kube-OVN adalah fabric jaringan kubernetes berbasis OVN untuk enterprises. Dengan bantuan OVN/OVS, solusi ini menyediakan beberapa fitur jaringan overlay canggih seperti subnet, QoS, alokasi IP statis, mirroring traffic, gateway, kebijakan jaringan berbasis openflow, dan proksi layanan.
Kube-router
Kube-router adalah solusi jaringan yang dibuat khusus untuk Kubernetes yang bertujuan untuk memberikan kinerja tinggi dan kesederhanaan operasional. Kube-router menyediakan Linux LVS/IPVS berbasis proksi layanan, solusi jaringan berbasis penerusan pod-to-pod Linux kernel tanpa overlay, dan penegak kebijakan jaringan berbasis iptables/ipset.
L2 networks and linux bridging
Jika Anda memiliki jaringan L2 yang "bodoh", seperti saklar sederhana di environment "bare-metal", kamu harus dapat melakukan sesuatu yang mirip dengan pengaturan GCE di atas. Perhatikan bahwa petunjuk ini hanya dicoba dengan sangat sederhana - sepertinya berhasil, tetapi belum diuji secara menyeluruh. Jika kamu menggunakan teknik ini dan telah menyempurnakan prosesnya, tolong beri tahu kami.
Ikuti bagian "With Linux Bridge devices" dari tutorial yang sangat bagus ini dari Lars Kellogg-Stedman.
Multus (plugin Multi-Jaringan)
Multus adalah plugin Multi CNI untuk mendukung fitur Banyak Jaringan di Kubernetes menggunakan objek jaringan berbasis CRD di Kubernetes.
Multus mendukung semua plugin referensi (mis. Flannel, DHCP, [Macvlan](https://github.com/containernetworking/plugins/tree/master/plugins/main / macvlan)) yang mengimplementasikan spesifikasi CNI dan plugin pihak ke-3 (mis. Calico, Weave, Cilium, Contiv). Selain itu, Multus mendukung SRIOV, DPDK, OVS- DPDK & VPP beban kerja di Kubernetes dengan aplikasi cloud asli dan aplikasi berbasis NFV di Kubernetes.
NSX-T
VMware NSX-T adalah virtualisasi jaringan dan platform keamanan. NSX-T dapat menyediakan virtualisasi jaringan untuk lingkungan multi-cloud dan multi-hypervisor dan berfokus pada kerangka kerja dan arsitektur aplikasi yang muncul yang memiliki titik akhir dan tumpukan teknologi yang heterogen. Selain hypervisor vSphere, lingkungan ini termasuk hypervisor lainnya seperti KVM, wadah, dan bare metal.
NSX-T Container Plug-in (NCP) menyediakan integrasi antara NSX-T dan pembuat wadah seperti Kubernetes, serta integrasi antara NSX-T dan platform CaaS / PaaS berbasis-kontainer seperti Pivotal Container Service (PKS) dan OpenShift.
Nuage Networks VCS (Layanan Cloud Virtual)
Nuage menyediakan platform SDN (Software-Defined Networking) berbasis kebijakan yang sangat skalabel. Nuage menggunakan Open vSwitch open source untuk data plane bersama dengan SDN Controller yang kaya fitur yang dibangun pada standar terbuka.
Platform Nuage menggunakan overlay untuk menyediakan jaringan berbasis kebijakan yang mulus antara Kubernetes Pod-Pod dan lingkungan non-Kubernetes (VM dan server bare metal). Model abstraksi kebijakan Nuage dirancang dengan mempertimbangkan aplikasi dan membuatnya mudah untuk mendeklarasikan kebijakan berbutir halus untuk aplikasi. Mesin analisis real-time platform memungkinkan pemantauan visibilitas dan keamanan untuk aplikasi Kubernetes.
OpenVSwitch
OpenVSwitch adalah cara yang agak lebih dewasa tetapi juga rumit untuk membangun jaringan overlay. Ini didukung oleh beberapa "Toko Besar" untuk jaringan.
OVN (Open Virtual Networking)
OVN adalah solusi virtualisasi jaringan opensource yang dikembangkan oleh komunitas Open vSwitch. Ini memungkinkan seseorang membuat switch logis, router logis, ACL stateful, load-balancers dll untuk membangun berbagai topologi jaringan virtual. Proyek ini memiliki plugin dan dokumentasi Kubernetes spesifik di ovn-kubernetes.
Project Calico
Project Calico adalah penyedia jaringan wadah sumber terbuka dan mesin kebijakan jaringan.
Calico menyediakan solusi jaringan dan kebijakan kebijakan jaringan yang sangat berskala untuk menghubungkan Pod Kubernetes berdasarkan prinsip jaringan IP yang sama dengan internet, untuk Linux (open source) dan Windows (milik - tersedia dari Tigera). Calico dapat digunakan tanpa enkapsulasi atau overlay untuk menyediakan jaringan pusat data skala tinggi yang berkinerja tinggi. Calico juga menyediakan kebijakan keamanan jaringan berbutir halus, berdasarkan niat untuk Pod Kubernetes melalui firewall terdistribusi.
Calico juga dapat dijalankan dalam mode penegakan kebijakan bersama dengan solusi jaringan lain seperti Flannel, alias kanal, atau jaringan GCE, AWS atau Azure asli.
Romana
Romana adalah jaringan sumber terbuka dan solusi otomasi keamanan yang memungkinkan kamu menggunakan Kubernetes tanpa jaringan hamparan. Romana mendukung Kubernetes Kebijakan Jaringan untuk memberikan isolasi di seluruh ruang nama jaringan.
Weave Net dari Weaveworks
Weave Net adalah jaringan yang tangguh dan mudah digunakan untuk Kubernetes dan aplikasi yang dihostingnya. Weave Net berjalan sebagai plug-in CNI atau berdiri sendiri. Di kedua versi, itu tidak memerlukan konfigurasi atau kode tambahan untuk dijalankan, dan dalam kedua kasus, jaringan menyediakan satu alamat IP per Pod - seperti standar untuk Kubernetes.
Selanjutnya
Desain awal model jaringan dan alasannya, dan beberapa rencana masa depan dijelaskan secara lebih rinci dalam dokumen desain jaringan.
3.11.6 - Arsitektur Logging
Log aplikasi dan sistem dapat membantu kamu untuk memahami apa yang terjadi di dalam klaster kamu. Log berguna untuk mengidentifikasi dan menyelesaikan masalah serta memonitor aktivitas klaster. Hampir semua aplikasi modern mempunyai sejenis mekanisme log sehingga hampir semua mesin kontainer didesain untuk mendukung suatu mekanisme logging. Metode logging yang paling mudah untuk aplikasi dalam bentuk kontainer adalah menggunakan standard output dan standard error.
Namun, fungsionalitas bawaan dari mesin kontainer atau runtime biasanya tidak cukup memadai sebagai solusi log. Contohnya, jika sebuah kontainer gagal, sebuah pod dihapus, atau suatu node mati, kamu biasanya tetap menginginkan untuk mengakses log dari aplikasimu. Oleh sebab itu, log sebaiknya berada pada penyimpanan dan lifecyle yang terpisah dari node, pod, atau kontainer. Konsep ini dinamakan sebagai logging pada level klaster. Logging pada level klaster ini membutuhkan backend yang terpisah untuk menyimpan, menganalisis, dan mengkueri log. Kubernetes tidak menyediakan solusi bawaan untuk penyimpanan data log, namun kamu dapat mengintegrasikan beragam solusi logging yang telah ada ke dalam klaster Kubernetes kamu.
Arsitektur logging pada level klaster yang akan dijelaskan berikut mengasumsikan bahwa sebuah logging backend telah tersedia baik di dalam maupun di luar klastermu. Meskipun kamu tidak tertarik menggunakan logging pada level klaster, penjelasan tentang bagaimana log disimpan dan ditangani pada node di bawah ini mungkin dapat berguna untukmu.
Hal dasar logging pada Kubernetes
Pada bagian ini, kamu dapat melihat contoh tentang dasar logging pada Kubernetes yang mengeluarkan data pada standard output. Demonstrasi berikut ini menggunakan sebuah spesifikasi pod dengan kontainer yang akan menuliskan beberapa teks ke standard output tiap detik.
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
args: [/bin/sh, -c,
'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
Untuk menjalankan pod ini, gunakan perintah berikut:
kubectl apply -f https://k8s.io/examples/debug/counter-pod.yaml
Keluarannya adalah:
pod/counter created
Untuk mengambil log, gunakan perintah kubectl logs
sebagai berikut:
kubectl logs counter
Keluarannya adalah:
0: Mon Jan 1 00:00:00 UTC 2001
1: Mon Jan 1 00:00:01 UTC 2001
2: Mon Jan 1 00:00:02 UTC 2001
...
Kamu dapat menambahkan parameter --previous
pada perintah kubectl logs
untuk mengambil log dari kontainer sebelumnya yang gagal atau crash. Jika pod kamu memiliki banyak kontainer, kamu harus menspesifikasikan kontainer mana yang kamu ingin akses lognya dengan menambahkan nama kontainer pada perintah tersebut. Lihat dokumentasi kubectl logs
untuk informasi lebih lanjut.
Node-level logging
Semua hal yang ditulis oleh aplikasi dalam kontainer ke stdout
dan stderr
akan ditangani dan diarahkan ke suatu tempat oleh mesin atau engine kontainer. Contohnya,mesin kontainer Docker akan mengarahkan kedua aliran tersebut ke suatu logging driver, yang akan dikonfigurasi pada Kubernetes untuk menuliskan ke dalam berkas dalam format json.
Secara default, jika suatu kontainer restart, kubelet akan menjaga kontainer yang mati tersebut beserta lognya. Namun jika suatu pod dibuang dari node, maka semua hal dari kontainernya juga akan dibuang, termasuk lognya.
Hal lain yang perlu diperhatikan dalam logging pada level node adalah implementasi rotasi log, sehingga log tidak menghabiskan semua penyimpanan yang tersedia pada node. Kubernetes saat ini tidak bertanggung jawab dalam melakukan rotasi log, namun deployment tool seharusnya memberikan solusi terhadap masalah tersebut.
Contohnya, pada klaster Kubernetes, yang di deployed menggunakan kube-up.sh
, terdapat alat bernama logrotate
yang dikonfigurasi untuk berjalan tiap jamnya. Kamu juga dapat menggunakan runtime kontainer untuk melakukan rotasi log otomatis, misalnya menggunakan log-opt
Docker.
Pada kube-up.sh
, metode terakhir digunakan untuk COS image pada GCP, sedangkan metode pertama digunakan untuk lingkungan lainnya. Pada kedua metode, secara default akan dilakukan rotasi pada saat berkas log melewati 10MB.
Sebagai contoh, kamu dapat melihat informasi lebih rinci tentang bagaimana kube-up.sh
mengatur logging untuk COS image pada GCP yang terkait dengan script.
Saat kamu menjalankan perintah kubectl logs
seperti pada contoh tadi, kubelet di node tersebut akan menangani permintaan untuk membaca langsung isi berkas log sebagai respon.
kubectl logs
. Contoh, jika terdapat sebuah berkas 10MB, logrotate
akan melakukan rotasi sehingga akan ada dua buah berkas, satu dengan ukuran 10MB, dan satu berkas lainnya yang kosong. Maka kubectl logs
akan mengembalikan respon kosong.
Komponen sistem log
Terdapat dua jenis komponen sistem: yaitu yang berjalan di dalam kontainer dan komponen lain yang tidak berjalan di dalam kontainer. Sebagai contoh:
- Kubernetes scheduler dan kube-proxy berjalan di dalam kontainer.
- Kubelet dan runtime kontainer, contohnya Docker, tidak berjalan di dalam kontainer.
Pada mesin yang menggunakan systemd, kubelet dan runtime runtime menulis ke journald. Jika systemd tidak tersedia, keduanya akan menulis ke berkas .log
pada folder /var/log
.
Komponen sistem di dalam kontainer akan selalu menuliskan ke folder /var/log
, melewati mekanisme default logging. Mereka akan menggunakan logging library klog.
Kamu dapat menemukan konvensi tentang tingkat kegawatan logging untuk komponen-komponen tersebut pada dokumentasi development logging.
Seperti halnya pada log kontainer, komponen sistem yang menuliskan log pada folder /var/log
juga harus melakukan rotasi log. Pada klaster Kubernetes yang menggunakan kube-up.sh
, log tersebut telah dikonfigurasi dan akan dirotasi oleh logrotate
secara harian atau saat ukuran log melebihi 100MB.
Arsitektur klaster-level logging
Meskipun Kubernetes tidak menyediakan solusi bawaan untuk logging level klaster, ada beberapa pendekatan yang dapat kamu pertimbangkan. Berikut beberapa diantaranya:
- Menggunakan agen logging pada level node yang berjalan pada setiap node.
- Menggunakan kontainer sidecar khusus untuk logging aplikasi di dalam pod.
- Mengeluarkan log langsung ke backend dari dalam aplikasi
Menggunakan agen node-level logging
Kamu dapat mengimplementasikan klaster-level logging dengan menggunakan agen yang berjalan pada setiap node. Agen logging merupakan perangkat khusus yang akan mengekspos log atau mengeluarkan log ke backend. Umumnya agen logging merupakan kontainer yang memiliki akses langsung ke direktori tempat berkas log berada dari semua kontainer aplikasi yang berjalan pada node tersebut.
Karena agen logging harus berjalan pada setiap node, umumnya dilakukan dengan menggunakan replika DaemonSet, manifest pod, atau menjalankan proses khusus pada node. Namun dua cara terakhir sudah dideprekasi dan sangat tidak disarankan.
Menggunakan agen logging pada level node merupakan cara yang paling umum dan disarankan untuk klaster Kubernetes. Hal ini karena hanya dibutuhkan satu agen tiap node dan tidak membutuhkan perubahan apapun dari sisi aplikasi yang berjalan pada node. Namun, node-level logging hanya dapat dilakukan untuk aplikasi yang menggunakan standard output dan standard error.
Kubernetes tidak menspesifikasikan khusus suatu agen logging, namun ada dua agen logging yang dimasukkan dalam rilis Kubernetes: Stackdriver Logging untuk digunakan pada Google Cloud Platform, dan Elasticsearch. Kamu dapat melihat informasi dan instruksi pada masing-masing dokumentasi. Keduanya menggunakan fluentd dengan konfigurasi kustom sebagai agen pada node.
Menggunakan kontainer sidecar dengan agen logging
Kamu dapat menggunakan kontainer sidecar dengan salah satu cara berikut:
- Kontainer sidecar mengeluarkan log aplikasi ke
stdout
miliknya sendiri. - Kontainer sidecar menjalankan agen logging yang dikonfigurasi untuk mengambil log dari aplikasi kontainer.
Kontainer streaming sidecar
Kamu dapat memanfaatkan kubelet dan agen logging yang telah berjalan pada tiap node dengan menggunakan kontainer sidecar. Kontainer sidecar dapat membaca log dari sebuah berkas, socket atau journald. Tiap kontainer sidecar menuliskan log ke stdout
atau stderr
mereka sendiri.
Dengan menggunakan cara ini kamu dapat memisahkan aliran log dari bagian-bagian yang berbeda dari aplikasimu, yang beberapa mungkin tidak mendukung log ke stdout
dan stderr
. Perubahan logika aplikasimu dengan menggunakan cara ini cukup kecil, sehingga hampir tidak ada overhead. Selain itu, karena stdout
dan stderr
ditangani oleh kubelet, kamu juga dapat menggunakan alat bawaan seperti kubectl logs
.
Sebagai contoh, sebuah pod berjalan pada satu kontainer tunggal, dan kontainer menuliskan ke dua berkas log yang berbeda, dengan dua format yang berbeda pula. Berikut ini file konfigurasi untuk Pod:
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
Hal ini akan menyulitkan untuk mengeluarkan log dalam format yang berbeda pada aliran log yang sama, meskipun kamu dapat me-redirect keduanya ke stdout
dari kontainer. Sebagai gantinya, kamu dapat menggunakan dua buah kontainer sidecar. Tiap kontainer sidecar dapat membaca suatu berkas log tertentu dari shared volume kemudian mengarahkan log ke stdout
-nya sendiri.
Berikut file konfigurasi untuk pod yang memiliki dua buah kontainer sidecard:
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-1
image: busybox
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-2
image: busybox
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/2.log']
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
Saat kamu menjalankan pod ini, kamu dapat mengakses tiap aliran log secara terpisah dengan menjalankan perintah berikut:
kubectl logs counter count-log-1
0: Mon Jan 1 00:00:00 UTC 2001
1: Mon Jan 1 00:00:01 UTC 2001
2: Mon Jan 1 00:00:02 UTC 2001
...
kubectl logs counter count-log-2
Mon Jan 1 00:00:00 UTC 2001 INFO 0
Mon Jan 1 00:00:01 UTC 2001 INFO 1
Mon Jan 1 00:00:02 UTC 2001 INFO 2
...
Agen node-level yang terpasang di klastermu akan mengambil aliran log tersebut secara otomatis tanpa perlu melakukan konfigurasi tambahan. Bahkan jika kamu mau, kamu dapat mengonfigurasi agen untuk melakukan parse baris log tergantung dari kontainer sumber awalnya.
Sedikit catatan, meskipun menggunakan memori dan CPU yang cukup rendah (sekitar beberapa milicore untuk CPU dan beberapa megabytes untuk memori), penulisan log ke file kemudian mengalirkannya ke stdout
dapat berakibat penggunaan disk yang lebih besar. Jika kamu memiliki aplikasi yang menuliskan ke file tunggal, umumnya lebih baik menggunakan /dev/stdout
sebagai tujuan daripada menggunakan pendekatan dengan kontainer sidecar.
Kontainer sidecar juga dapat digunakan untuk melakukan rotasi berkas log yang tidak dapat dirotasi oleh aplikasi itu sendiri. Contoh dari pendekatan ini adalah sebuah kontainer kecil yang menjalankan rotasi log secara periodik. Namun, direkomendasikan untuk menggunakan stdout
dan stderr
secara langsung dan menyerahkan kebijakan rotasi dan retensi pada kubelet.
Kontainer sidecar dengan agen logging
Jika agen node-level logging tidak cukup fleksible untuk kebutuhanmu, kamu dapat membuat kontainer sidecar dengan agen logging yang terpisah, yang kamu konfigurasi spesifik untuk berjalan dengan aplikasimu.
kubectl logs
, karena mereka tidak dikontrol oleh kubelet.
Sebagai contoh, kamu dapat menggunakan Stackdriver, yang menggunakan fluentd sebagai agen logging. Berikut ini dua file konfigurasi yang dapat kamu pakai untuk mengimplementasikan cara ini. File yang pertama berisi sebuah ConfigMap untuk mengonfigurasi fluentd.
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentd-config
data:
fluentd.conf: |
<source>
type tail
format none
path /var/log/1.log
pos_file /var/log/1.log.pos
tag count.format1
</source>
<source>
type tail
format none
path /var/log/2.log
pos_file /var/log/2.log.pos
tag count.format2
</source>
<match **>
type google_cloud
</match>
File yang kedua mendeskripsikan sebuah pod yang memiliki kontainer sidecar yang menjalankan fluentd. Pod ini melakukan mount sebuah volume yang akan digunakan fluentd untuk mengambil data konfigurasinya.
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-agent
image: k8s.gcr.io/fluentd-gcp:1.30
env:
- name: FLUENTD_ARGS
value: -c /etc/fluentd-config/fluentd.conf
volumeMounts:
- name: varlog
mountPath: /var/log
- name: config-volume
mountPath: /etc/fluentd-config
volumes:
- name: varlog
emptyDir: {}
- name: config-volume
configMap:
name: fluentd-config
Setelah beberapa saat, kamu akan mendapati pesan log pada interface Stackdriver.
Ingat, ini hanya contoh saja dan kamu dapat mengganti fluentd dengan agen logging lainnya, yang dapat membaca sumber apa saja dari dalam kontainer aplikasi.
Mengekspos log langsung dari aplikasi
Kamu dapat mengimplementasikan klaster-level logging dengan mengekspos atau mengeluarkan log langsung dari tiap aplikasi; namun cara implementasi mekanisme logging tersebut diluar cakupan dari Kubernetes.
3.11.7 - Metrik untuk Komponen Sistem Kubernetes
Metrik dari komponen sistem dapat memberikan gambaran yang lebih baik tentang apa yang sedang terjadi di dalam sistem. Metrik sangat berguna untuk membuat dasbor (dashboard) dan peringatan (alert).
Komponen Kubernetes mengekspos metrik dalam format Prometheus. Format ini berupa teks biasa yang terstruktur, dirancang agar orang dan mesin dapat membacanya.
Metrik-metrik dalam Kubernetes
Dalam kebanyakan kasus, metrik tersedia pada endpoint /metrics
dari server HTTP.
Untuk komponen yang tidak mengekspos endpoint secara bawaan, endpoint tersebut dapat diaktifkan
dengan menggunakan opsi --bind-address
.
Contoh-contoh untuk komponen tersebut adalah:
Di dalam lingkungan produksi, kamu mungkin ingin mengonfigurasi Server Prometheus atau pengambil metrik (metrics scraper) lainnya untuk mengumpulkan metrik-metrik ini secara berkala dan membuatnya tersedia dalam semacam pangkalan data deret waktu (time series database).
Perlu dicatat bahwa kubelet
juga mengekspos metrik pada endpoint-endpoint seperti /metrics/cadvisor
,
/metrics/resource
dan /metrics/probes
. Metrik-metrik tersebut tidak memiliki
siklus hidup yang sama.
Jika klastermu menggunakan RBAC,
maka membaca metrik memerlukan otorisasi melalui user, group, atau
ServiceAccount dengan ClusterRole yang memperbolehkan untuk mengakses /metrics
.
Sebagai contoh:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- nonResourceURLs:
- "/metrics"
verbs:
- get
Siklus hidup metrik
Metrik alfa (alpha) → Metrik stabil → Metrik usang (deprecated) → Metrik tersembunyi → Metrik terhapus
Metrik alfa tidak memiliki jaminan stabilitas. Metrik ini dapat dimodifikasi atau dihapus kapan saja.
Metrik stabil dijamin tidak akan mengalami perubahan. Hal ini berarti:
- Metrik stabil tanpa penanda usang (deprecated signature) tidak akan dihapus ataupun diganti namanya
- Jenis metrik stabil tidak akan dimodifikasi
Metrik usang dijadwalkan untuk dihapus, tetapi masih tersedia untuk digunakan. Metrik ini mencakup anotasi versi di mana metrik ini dianggap menjadi usang.
Sebagai contoh:
-
Sebelum menjadi usang
# HELP some_counter this counts things # TYPE some_counter counter some_counter 0
-
Setelah menjadi usang
# HELP some_counter (Deprecated since 1.15.0) this counts things # TYPE some_counter counter some_counter 0
Metrik tersembunyi tidak lagi dipublikasikan untuk pengambilan metrik (scraping), tetapi masih tersedia untuk digunakan. Untuk menggunakan metrik tersembunyi, lihat bagian Menampilkan metrik tersembunyi.
Metrik yang terhapus tidak lagi dipublikasikan dan tidak dapat digunakan lagi.
Menampilkan metrik tersembunyi
Seperti yang dijelaskan di atas, admin dapat mengaktifkan metrik tersembunyi melalui opsi baris perintah pada biner (program) tertentu. Ini dimaksudkan untuk digunakan sebagai jalan keluar bagi admin jika mereka melewatkan migrasi metrik usang dalam rilis terakhir.
Opsi show-hidden-metrics-for-version
menerima input versi yang kamu inginkan untuk menampilkan metrik usang dalam rilis tersebut. Versi tersebut dinyatakan sebagai x.y, di mana x adalah versi mayor, y adalah versi minor. Versi patch tidak diperlukan meskipun metrik dapat menjadi usang dalam rilis patch, alasannya adalah kebijakan penandaan metrik usang dijalankan terhadap rilis minor.
Opsi tersebut hanya dapat menerima input versi minor sebelumnya sebagai nilai. Semua metrik yang disembunyikan di versi sebelumnya akan dikeluarkan jika admin mengatur versi sebelumnya ke show-hidden-metrics-for-version
. Versi yang terlalu lama tidak diperbolehkan karena melanggar kebijakan untuk metrik usang.
Ambil metrik A
sebagai contoh, di sini diasumsikan bahwa A
sudah menjadi usang di versi 1.n. Berdasarkan kebijakan metrik usang, kita dapat mencapai kesimpulan berikut:
- Pada rilis
1.n
, metrik menjadi usang, dan dapat dikeluarkan secara bawaan. - Pada rilis
1.n+1
, metrik disembunyikan secara bawaan dan dapat dikeluarkan dengan baris perintahshow-hidden-metrics-for-version=1.n
. - Pada rilis
1.n+2
, metrik harus dihapus dari codebase. Tidak ada jalan keluar lagi.
Jika kamu meningkatkan versi dari rilis 1.12
ke 1.13
, tetapi masih bergantung pada metrik A
yang usang di 1.12
, kamu harus mengatur metrik tersembunyi melalui baris perintah: --show-hidden-metrics = 1.12
dan ingatlah untuk menghapus ketergantungan terhadap metrik ini sebelum meningkatkan versi rilis ke 1.14
.
Menonaktifkan metrik akselerator
kubelet mengumpulkan metrik akselerator melalui cAdvisor. Untuk mengumpulkan metrik ini, untuk akselerator seperti GPU NVIDIA, kubelet membuka koneksi dengan driver GPU. Ini berarti untuk melakukan perubahan infrastruktur (misalnya, pemutakhiran driver), administrator klaster perlu menghentikan agen kubelet.
Pengumpulkan metrik akselerator sekarang menjadi tanggung jawab vendor dibandingkan kubelet. Vendor harus menyediakan sebuah kontainer untuk mengumpulkan metrik dan mengeksposnya ke layanan metrik (misalnya, Prometheus).
Gerbang fitur DisableAcceleratorUsageMetrics
menonaktifkan metrik yang dikumpulkan oleh kubelet, dengan lini masa (timeline) untuk mengaktifkan fitur ini secara bawaan.
Metrik komponen
Metrik kube-controller-manager
Metrik controller manager memberikan gambaran penting tentang kinerja dan kesehatan controller manager. Metrik ini mencakup metrik runtime bahasa Go yang umum seperti jumlah go_routine dan metrik khusus pengontrol seperti latensi permintaan etcd atau latensi API Cloudprovider (AWS, GCE, OpenStack) yang dapat digunakan untuk mengukur kesehatan klaster.
Mulai dari Kubernetes 1.7, metrik Cloudprovider yang detail tersedia untuk operasi penyimpanan untuk GCE, AWS, Vsphere, dan OpenStack. Metrik ini dapat digunakan untuk memantau kesehatan operasi persistent volume.
Misalnya, untuk GCE metrik-metrik berikut ini dipanggil:
cloudprovider_gce_api_request_duration_seconds { request = "instance_list"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_insert"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_delete"}
cloudprovider_gce_api_request_duration_seconds { request = "attach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "detach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "list_disk"}
Metrik kube-scheduler
Kubernetes v1.20 [alpha]
Penjadwal mengekspos metrik opsional yang melaporkan sumber daya yang diminta dan limit yang diinginkan dari semua pod yang berjalan. Metrik ini dapat digunakan untuk membangun dasbor perencanaan kapasitas, mengevaluasi limit penjadwalan yang digunakan saat ini atau secara historis, dengan cepat mengidentifikasi beban kerja yang tidak dapat dijadwalkan karena kurangnya sumber daya, dan membandingkan permintaan sumber daya oleh pod dengan penggunaannya yang aktual.
kube-scheduler mengidentifikasi permintaan dan limit sumber daya yang dikonfigurasi untuk setiap Pod; jika permintaan atau limit bukan nol, kube-scheduler akan melaporkan deret waktu (timeseries) metrik. Deret waktu diberi label dengan:
- namespace
- nama pod
- node di mana pod dijadwalkan atau string kosong jika belum dijadwalkan
- prioritas
- penjadwal yang ditugaskan untuk pod itu
- nama dari sumber daya (misalnya,
cpu
) - satuan dari sumber daya jika diketahui (misalnya,
cores
)
Setelah pod selesai (memiliki restartPolicy
Never
atau OnFailure
dan berada dalam fase pod Succeeded
atau Failed
, atau telah dihapus dan semua kontainer dalam keadaan Terminated) deret metrik tidak lagi dilaporkan karena penjadwal sekarang sudah dibebaskan untuk menjadwalkan pod lain untuk dijalankan. Metrik yang dibahas pada bagian ini dikenal sebagai kube_pod_resource_request
dan kube_pod_resource_limit
.
Metrik diekspos melalui endpoint HTTP /metrics/resources
dan memerlukan otorisasi yang sama seperti endpoint /metrics
pada penjadwal. Kamu harus menggunakan opsi --show-hidden-metrics-for-version=1.20
untuk mengekspos metrik-metrik stabilitas alfa ini.
Selanjutnya
- Baca tentang format teks Prometheus untuk berbagai metrik
- Baca tentang kebijakan deprecation Kubernetes
3.11.8 - Konfigurasi Garbage Collection pada kubelet
Garbage collection merupakan fitur kubelet yang sangat bermanfaat, yang akan membersihkan image-image dan juga kontainer-kontainer yang tidak lagi digunakan. Kubelet akan melakukan garbage collection untuk kontainer setiap satu menit dan garbage collection untuk image setiap lima menit.
Perangkat garbage collection eksternal tidak direkomendasikan karena perangkat tersebut berpotensi merusak perilaku kubelet dengan menghilangkan kontainer-kontainer yang sebenarnya masih diperlukan.
Garbage Collection untuk Image
Kubernetes mengelola lifecycle untuk seluruh image melalui imageManager, dengan bantuan cadvisor.
Policy untuk melakukan garbage collection memperhatikan dua hal: HighThresholdPercent
dan LowThresholdPercent
.
Penggunaan disk yang melewati batas atas (high threshold) akan men-trigger garbage collection.
Garbage collection akan mulai menghapus dari image-image yang paling jarang digunakan (least recently used)
sampai menemui batas bawah (low threshold) kembali.
Garbage Collection untuk Kontainer
Policy untuk melakukan garbage collection pada kontainer memperhatikan tiga variabel yang ditentukan oleh pengguna (user-defined).
MinAge
merupakan umur minimal dimana suatu kontainer dapat terkena garbage collection.
MaxPerPodContainer
merupakan jumlah maksimum yang diperbolehkan untuk setiap pod (UID, container name) pair memiliki
kontainer-kontainer yang sudah mati (dead containers). MaxContainers
merupakan jumlah maksimal total dari seluruh kontainer yang sudah mati.
Semua variabel ini dapat dinonaktifkan secara individual, dengan mengatur MinAge
ke angka nol serta mengatur MaxPerPodContainer
dan MaxContainers
ke angka di bawah nol.
Kubelet akan mengambil tindakan untuk kontainer-kontainer yang tidak dikenal, sudah dihapus, atau diluar batasan-batasan yang diatur
sebelumnya melalui flag. Kontainer-kontainer yang paling lama (tertua) biasanya akan dihapus terlebih dahulu. MaxPerPodContainer
dan MaxContainer
berpotensi mengalami konflik satu sama lain pada situasi saat menjaga jumlah maksimal kontainer per pod (MaxPerPodContainer
) akan melebihi
jumlah kontainer mati (dead containers) yang diperbolehkan (MaxContainers
).
MaxPerPodContainer
dapat diatur sedemikian rupa dalam situasi ini: Seburuk-buruhknya dengan melakukan downgrade MaxPerPodContainer
ke angka 1
dan melakukan evict kontainer-kontainer yang paling lama. Selain itu, kontainer-kontainer milik Pod yang telah dihapus akan dihilangkan
saat umur mereka telah melebihi MinAge
.
Kontainer-kontainer yang tidak dikelola oleh kubelet akan terbebas dari garbage collection.
Konfigurasi Pengguna
Para pengguna dapat mengatur threshold-threshold untuk melakukan tuning pada garbage collection image melalui flag-flag kubelet sebagai berikut:
image-gc-high-threshold
, persentase dari penggunaan disk yang men-trigger proses garbage collection untuk image. Default-nya adalah 85%.image-gc-low-threshold
, persentase dari penggunaan disk dimana garbage collection berusaha menghapus image. Default-nya adalah 80%.
Kami juga memperbolehkan para pengguna untuk menyesuaikan policy garbage collection melalui flag-flag kubelet sebagai berikut:
minimum-container-ttl-duration
, umur minimal untuk setiap kontainer yang sudah selesai (finished) sebelum terkena garbage collection. Default-nya adalah 0 menit, yang berarti setiap kontainer yang telah selesai akan terkena garbage collection.maximum-dead-containers-per-container
, jumlah maksimal dari kontainer-kontainer lama yang diperbolehkan ada secara global. Default-nya adalah -1, yang berarti tidak ada batasannya untuk global.
Kontainer-kontainer dapat berpotensi terkena garbage collection sebelum kegunaannya telah usang. Kontainer-kontainer
ini memliki log dan data lainnya yang bisa saja berguna saat troubleshoot. Sangat direkomendasikan untuk menetapkan
angka yang cukup besar pada maximum-dead-containers-per-container
, untuk memperbolehkan paling tidak 1 kontainer mati
untuk dijaga (retained) per jumlah kontainer yang diharapkan. Angka yang lebih besar untuk maximum-dead-containers
juga direkomendasikan untuk alasan serupa.
Lihat isu ini untuk penjelasan lebih lanjut.
Deprecation
Beberapa fitur Garbage Collection pada kubelet di laman ini akan digantikan oleh fitur eviction nantinya, termasuk:
Flag Existing | Flag Baru | Alasan |
---|---|---|
--image-gc-high-threshold |
--eviction-hard atau --eviction-soft |
sinyal eviction yang ada (existing) dapat men-trigger garbage collection |
--image-gc-low-threshold |
--eviction-minimum-reclaim |
hal serupa dapat diperoleh dengan eviction reclaim |
--maximum-dead-containers |
deprecated saat log yang telah usang tersimpan di luar konteks kontainer | |
--maximum-dead-containers-per-container |
deprecated saat log yang telah usang tersimpan di luar konteks kontainer | |
--minimum-container-ttl-duration |
deprecated saat log yang telah usang tersimpan di luar konteks kontainer | |
--low-diskspace-threshold-mb |
--eviction-hard atau eviction-soft |
eviction memberi generalisasi threshold disk untuk resource-resource lainnya |
--outofdisk-transition-frequency |
--eviction-pressure-transition-period |
eviction memberi generalisasi transisi tekanan disk (disk pressure)untuk resource-resource lainnya |
Selanjutnya
Lihat Konfigurasi untuk Menangani Kehabisan Resource untuk penjelasan lebih lanjut.
3.11.9 - Federation
Sudah usang
Penggunaan
Federation V1
sangat tidak disarankan.Federation V1
tidak pernah masuk dalam GA dan tidak lagi dikembangkan secara aktif. Dokumentasi hanya disediakan sebatas data artefak saja.Untuk informasi lebih lanjut mengenai hal ini dan penggantinya kamu dapat membaca Kubernetes Federation v2.
Laman ini menjelaskan alasan dan cara penggunaan federation untuk melakukan manajemen klaster Kubernetes.
Kenapa Federation ?
Federation membuat proses manajemen klaster multipel menjadi lebih mudah. Federation mencapai hal ini dengan cara menyediakan 2 buah fondasi:
- Melakukan sinkronisasi resource di seluruh klaster: Federation menyediakan kemampuan untuk melakukan sinkronisasi resources pada multiple klaster. Sebagai contoh, kamu dapat memastikan Deployment yang sama tersedia pada klaster multipel.
- Cross cluster Discovery: Federation menyediakan kemampuan untuk melakukan konfigurasi otomatis server DNS dan load balancer dari semua klaster. Misalnya, kamu dapat memastikan bahwa sebuah VIP atau DNS global dapat digunakan untuk mengakses backend dari klaster multipel.
Beberapa penggunaan federation adalah sebagai berikut:
- High Availability: Melakukan load balance di seluruh klaster serta melakukan konfigurasi otomatis server DNS dan load balancer, federation meminimalisasi dampak yang terjadi apabila terjadi kegagalan klaster.
- Mencegah lock-in yang terjadi akibat penyedia layanan: Dengan cara mempermudah proses migrasi antar klaster.
Manfaat federation tidak akan terlalu kelihatan kecuali kamu memiliki beberapa klaster. Beberapa alasan kenapa kamu butuh beberapa klaster adalah:
- Latency yang rendah: Memiliki klaster yang berada di region yang berbeda meminimalisasi latency dengan cara menyajikan konten ke pengguna berdasarkan region yang paling dekat dengan pengguna tersebut.
- Isolasi fault: Akan lebih baik apabila kita memiliki beberapa klaster kecil dibandingkan sebuah klaster besar untuk melakukan isolasi fault (misalnya saja klaster ini bisa saja berada di availability zona dan penyedia layanan cloud yang berbeda).
- Skalabilitas: Terdapat batasan skalabilitas untuk sebuah klaster Kubernetes, hal ini sebenarnya tidak menjadi masalah bagi sebagian besar pengguna. Untuk informasi lebih lanjut kamu bisa membaca Kubernetes Scaling dan Perencanaan Performa).
- Hybrid cloud: Kamu dapat memiliki multiple klsuter pada penyedia layanan cloud yang berbeda ataupun menggunakan on-premsie.
Kekurangan
Meskipun terdapat banyak kelebihan dari penggunaan federation, terdapat beberapa kekurangan federation yang dijabarkan sebagai berikut:
- Peningkatan bandwidth dan biaya untuk jaringan: control plane federation bertugas mengawasi semua kulster yang ada untuk menjamin state yang ada saat ini sesuai dengan state yang diinginkan. Hal ini dapat menyebabkan peningkatan biaya jaringan apabila klaster yang ada dijalankan pada region yang berbeda baik pada penyedia layanan cloud yang sama maupun berbeda.
- Berkurangnya isolasi antar klaster: Sebuah bug yang ada pada control plane federation dapat berdampak pada semua klaster. Hal ini dapat dihindari dengan cara mejaga logika yang ada pada control plane federation seminimum mungkin.
- Kematangan: Proyek federation ini tergolong baru dan belum cukup matang. Tidak semua resource yang ada tersedia dan masih banyak feature alpha. Issue 88 memberikan detail isu-isu terkait sistem yang masih berusaha dicari solusinya.
Kemampuan Hybrid Penggunaan Layanan Penyedian Cloud
Federation pada Kubernetes memungkinkan klaster untuk dijalankan pada penyedia layanan cloud yang berbeda (misalnya Google Cloud, AWS), dan on-premise (misalnya OpenStack). Kubefed adalah salah satu cara yang direkomendasikan untuk melakukan proses deploy klaster federation.
Dengan demikian, resources API yang kamu miliki dapat berada di klaster atau bahkan penyedia layanan cloud yang berbeda.
Mengaktifkan Federation
Untuk bisa melakukan federation pada klaster yang berbeda, pertama kamu harus mengaktifkan control plane federation. Ikuti petunjuk mengaktifkan control plane federation untuk informasi lebih lanjut.
Resources
API
Setelah kamu mengaktifkan control plane, kamu dapat menggunakan resource API federation. Berikut merupakan panduan yang akan menjelaskan masing-masing resource secara mendetail:
- Cluster
- ConfigMap
- DaemonSets
- Deployment
- Events
- Hpa
- Ingress
- Jobs
- Namespaces
- ReplicaSets
- Secrets
- Services
Referensi Dokumentasi API memberikan semua daftar resources yang disediakan apiserver federation.
Penghapusan Berantai
Kubernetes versi 1.6 menyediakan mekanisme penghapusan berantai untuk resource yang ada pada federation. Dengan penghapusan berantai, ketika kamu menghapus sebuah resource dari control plane federation, kamu juga akan menghapus segala resource tersebut pada semua klaster yang ada.
Mekanisme penghapusan berantai ini tidak diaktifkan secara default
ketika menggunakan REST API. Untuk mengaktifkannya, ubah nilai dari opsi
DeleteOptions.orphanDependents=false
ketika kamu menghapus sebuah resource
dari control plane federation dengan menggunakan REST API.
Penggunaan kubectl delete
mengaktifkan penhapusan berantai secara default.
Kamu dapat menonaktifkannya dengan menggunakan kubectl delete --cascade=false
Catatan: Kubernetes versi 1.5 menyediakan penghapusan berantai untuk sebagian resource federation.
Cakupan dari Sebuah Klaster
Pada penyedia IaaS seperti Google Compute Engine atau Amazon Web Services, sebuah VM ada di dalam zona atau availability zone. Kami menyarankan agar semua VM pada klaster Kubernetes berada pada availability zona yang sama, karena:
- dibandingkan dengan sebuah klaster global Kubernetes, terdapat lebih sedikit single-points of failure.
- dibandingkan dengan sebuah klaster yang tersebar pada availability zone yang mungkin berbeda, akan lebih mudah untuk merencanakan properti availability dari sebuah klaster yang berada pada satu zona.
- ketika pengembang Kubernetes mendesain sistem (misalnya, memperkirakan latency, bandwidth, atau failure yang mungkin terjadi) pengembang tersebut memperkirakan semua mesin akan berada pada sebuah data center yang sama, atau setidaknya masih terdapat pada satu wilayah.
Sangat direkomendasikan untuk menjalankan sedikit klaster dengan lebih banyak VM pada setiap availability zona; meskipun begitu hal ini tidak menutup kemungkinan untuk menjalankan klaster multipel pada setiap availability zona.
Alasan kenapa menjalankan lebih sedikit klaster pada setiap availability zona lebih dianjurkan:
- meningkatkan bin packing Pod pada beberapa kasus dimana terdapat lebih banyak node dalam sebuah klaster (mengurangi terjadinya fragmentation resource).
- mengurangi overhead operasional (meskipun keuntungan ini akan berkurang seiring bertambah matangnya proses dan tooling operasional).
- mengurangi biaya resource tetap per klaster, misalnya VM apiserver.
Alasan untuk memiliki klaster multipel:
- policy kemananan yang ketat membutuhkan isolasi antar work class (baca Partisi Klaster di bawah).
- melakukan penerapan Kubernetes dan/atau perangkat lunak lain yang versi baru ke salah satu klaster.
Memilih jumlah klaster yang tepat
Pemilihan jumlah klaster yang tepat merupakan pilihan yang relatif statis, dan hanya akan ditinjau kembali sewaktu-waktu. Sebaliknya, jumlah node dan pod dalam suatu service dapat berubah secara cepat seiring bertambahnya workload.
Untuk memilih jumlah klaster, pertama, pilih region yang memiliki latency yang masih dapat dimaklumi untuk semua pengguna aplikasi kamu
(jika kamu menggunakan Content Distribution Network, kebutuhan informasi nilai latency CDN tidak perlu diperhatikan).
Masalah legal juga perlu diperhitungkan. Misalnya sebuah perusahaan dengan pelanggan global bisa jadi memilih klaster di region
US, EU, AP, dan SA. Jumlah region ini dimisalkan dengan R
.
Kedua, pilih berapa banyak klaster yang bisa jadi unavailable secara bersamaan tanpa membuat service menjadi unavailable.
Misalkan jumlah klaster unavailable ini sebagai U
. Jika kamu tidak yakin, maka 1 merupakan pilihan yang tergolong
dapat diterima.
Jika aplikasimu memungkinkan trafik untuk di-load balance ke region mana saja ketika terjadi failure pada klaster,
maka kamu setidaknya membutuhkan nilai yang lebih banyak dari jumlah R
atau U + 1
klaster. Jika tidak (misalnya, kamu
ingin menjamin stabilnya latency ketika terjadi failure pada klaster) maka kamu membutuhkan R * (U + 1)
klaster
(U + 1
di setiap region yang ada pada R
). Pada kasus lain, cobalah untuk menerapkan satu klaster
pada zona yang berbeda.
Terakhir, jika klaster yang kamu miliki membutuhkan jumlah node yang melebihi nilai yang direkomendasikan untuk sebuah klaster Kubernetes, maka kamu membutuhkan lebih banyak klaster. Kubernetes v1.3 mampu menangani hingga 1000 node untuk setiap klaster. Kubernetes v1.8 mampu menangani hingga 5000 node untuk tiap klaster. Baca Membangun Klaster Besar untuk petunjuk lebih lanjut.
Selanjutnya
- Pelajari lebih lanjut tentang proposal Federation.
- Baca petunjuk pengaktifan klaster federation.
- Lihat seminar tentang federation pada Kubecon2016
- Lihat update federation pada Kubecon2017 Eropa
- Lihat update sig-multicluster pada Kubecon2018 Eropa
- Lihat presentasi prototipe Federation-v2 pada Kubecon2018 Eropa
- Lihat petunjuk penggunaan Federation-v2
3.11.10 - Berbagai Proxy di Kubernetes
Laman ini menjelaskan berbagai proxy yang ada di dalam Kubernetes.
Berbagai Jenis Proxy
Ada beberapa jenis proxy yang akan kamu temui saat menggunakan Kubernetes:
-
- dijalankan pada desktop pengguna atau di dalam sebuah Pod
- melakukan proxy dari alamat localhost ke apiserver Kubernetes
- dari klien menuju proxy menggunakan HTTP
- dari proxy menuju apiserver menggunakan HTTPS
- mencari lokasi apiserver
- menambahkan header autentikasi
-
- merupakan sebuah bastion yang ada di dalam apiserver
- menghubungkan pengguna di luar klaster ke alamat-alamat IP di dalam klaster yang tidak bisa terjangkau
- dijalankan bersama process-process apiserver
- dari klien menuju proxy menggunakan HTTPS (atau http jika dikonfigurasi pada apiserver)
- dari proxy menuju target menggunakan HTTP atau HTTPS, tergantung pilihan yang diambil oleh proxy melalui informasi yang ada
- dapat digunakan untuk menghubungi Node, Pod, atau Service
- melakukan load balancing saat digunakan untuk menjangkau sebuah Service
-
- dijalankan pada setiap Node
- melakukan proxy untuk UDP, TCP dan SCTP
- tidak mengerti HTTP
- menyediakan load balancing
- hanya digunakan untuk menjangkau berbagai Service
-
Sebuah Proxy/Load-balancer di depan satu atau banyak apiserver:
- keberadaan dan implementasinya bervariasi tergantung pada klaster (contohnya nginx)
- ada di antara seluruh klien dan satu/banyak apiserver
- jika ada beberapa apiserver, berfungsi sebagai load balancer
-
Cloud Load Balancer pada servis eksternal:
- disediakan oleh beberapa penyedia layanan cloud, seperti AWS ELB, Google Cloud Load Balancer
- dibuat secara otomatis ketika Service dari Kubernetes dengan tipe
LoadBalancer
- biasanya hanya tersedia untuk UDP/TCP
- support untuk SCTP tergantung pada load balancer yang diimplementasikan oleh penyedia cloud
- implementasi bervariasi tergantung pada penyedia cloud
Pengguna Kubernetes biasanya hanya cukup perlu tahu tentang kubectl proxy dan apiserver proxy. Untuk proxy-proxy lain di luar ini, admin klaster biasanya akan memastikan konfigurasinya dengan benar.
Melakukan request redirect
Proxy telah menggantikan fungsi redirect. Redirect telah terdeprekasi.
3.11.11 - Metrik controller manager
Metrik controller manager memberikan informasi penting tentang kinerja dan kesehatan dari controller manager.
Tentang metrik controller manager
Metrik controller manager ini berfungsi untuk memberikan informasi penting tentang kinerja dan kesehatan dari controller manager. Metrik ini juga berisi tentang metrik umum dari runtime bahasa pemrograman Go seperti jumlah go_routine dan metrik spesifik dari controller seperti latensi dari etcd request atau latensi API dari penyedia layanan cloud (AWS, GCE, OpenStack) yang dapat digunakan untuk mengukur kesehatan dari klaster.
Mulai dari Kubernetes 1.7, metrik yang lebih mendetil tentang operasi penyimpanan dari penyedia layanan cloud juga telah tersedia. Metrik-metrik ini dapat digunakan untuk memonitor kesehatan dari operasi persistent volume.
Berikut merupakan contoh nama metrik yang disediakan GCE:
cloudprovider_gce_api_request_duration_seconds { request = "instance_list"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_insert"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_delete"}
cloudprovider_gce_api_request_duration_seconds { request = "attach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "detach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "list_disk"}
Konfigurasi
Pada sebuah klaster, informasi metrik controller manager dapat diakses melalui http://localhost:10252/metrics
dari host tempat controller manager dijalankan.
Metrik ini dikeluarkan dalam bentuk format prometheus serta mudah untuk dibaca manusia.
Pada environment produksi, kamu mungkin juga ingin mengonfigurasi prometheus atau pengumpul metrik lainnya untuk mengumpulkan metrik-metrik ini secara berkala dalam bentuk basis data time series.
3.11.12 - Instalasi Add-ons
Add-ons berfungsi untuk menambah serta memperluas fungsionalitas dari Kubernetes.
Laman ini akan menjabarkan beberapa add-ons yang tersedia serta tautan instruksi bagaimana cara instalasi masing-masing add-ons.
Add-ons pada setiap bagian akan diurutkan secara alfabet - pengurutan ini tidak dilakukan berdasarkan status preferensi atau keunggulan.
Jaringan dan Policy Jaringan
- ACI menyediakan integrasi jaringan kontainer dan keamanan jaringan dengan Cisco ACI.
- Calico merupakan penyedia jaringan L3 yang aman dan policy jaringan.
- Canal menggabungkan Flannel dan Calico, menyediakan jaringan serta policy jaringan.
- Cilium merupakan plugin jaringan L3 dan policy jaringan yang dapat menjalankan policy HTTP/API/L7 secara transparan. Mendukung mode routing maupun overlay/encapsulation.
- CNI-Genie memungkinkan Kubernetes agar dapat terkoneksi dengan beragam plugin CNI, seperti Calico, Canal, Flannel, Romana, atau Weave dengan mulus.
- Contiv menyediakan jaringan yang dapat dikonfigurasi (native L3 menggunakan BGP, overlay menggunakan vxlan, klasik L2, dan Cisco-SDN/ACI) untuk berbagai penggunaan serta policy framework yang kaya dan beragam. Proyek Contiv merupakan proyek open source. Laman instalasi ini akan menjabarkan cara instalasi, baik untuk klaster dengan kubeadm maupun non-kubeadm.
- Contrail, yang berbasis dari Tungsten Fabric, merupakan sebuah proyek open source yang menyediakan virtualisasi jaringan multi-cloud serta platform manajemen policy. Contrail dan Tungsten Fabric terintegrasi dengan sistem orkestrasi lainnya seperti Kubernetes, OpenShift, OpenStack dan Mesos, serta menyediakan mode isolasi untuk mesin virtual (VM), kontainer/pod dan bare metal.
- Flannel merupakan penyedia jaringan overlay yang dapat digunakan pada Kubernetes.
- Knitter merupakan solusi jaringan yang mendukung multipel jaringan pada Kubernetes.
- Multus merupakan sebuah multi plugin agar Kubernetes mendukung multipel jaringan secara bersamaan sehingga dapat menggunakan semua plugin CNI (contoh: Calico, Cilium, Contiv, Flannel), ditambah pula dengan SRIOV, DPDK, OVS-DPDK dan VPP pada workload Kubernetes.
- NSX-T Container Plug-in (NCP) menyediakan integrasi antara VMware NSX-T dan orkestrator kontainer seperti Kubernetes, termasuk juga integrasi antara NSX-T dan platform CaaS/PaaS berbasis kontainer seperti Pivotal Container Service (PKS) dan OpenShift.
- Nuage merupakan platform SDN yang menyediakan policy-based jaringan antara Kubernetes Pods dan non-Kubernetes environment dengan monitoring visibilitas dan keamanan.
- Romana merupakan solusi jaringan Layer 3 untuk jaringan pod yang juga mendukung NetworkPolicy API. Instalasi Kubeadm add-on ini tersedia di sini.
- Weave Net menyediakan jaringan serta policy jaringan, yang akan membawa kedua sisi dari partisi jaringan, serta tidak membutuhkan basis data eksternal.
Service Discovery
- CoreDNS merupakan server DNS yang fleksibel, mudah diperluas yang dapat diinstal sebagai in-cluster DNS untuk pod.
Visualisasi & Kontrol
- Dashboard merupakan antarmuka web dasbor untuk Kubernetes.
- Weave Scope merupakan perangkat untuk visualisasi grafis dari kontainer, pod, service dll milikmu. Gunakan bersama dengan akun Weave Cloud atau host UI-mu sendiri.
Add-ons Terdeprekasi
Ada beberapa add-on lain yang didokumentasikan pada direktori deprekasi cluster/addons.
Add-on lain yang dipelihara dan dikelola dengan baik dapat ditulis di sini. Ditunggu PR-nya!
3.11.13 - Prioritas dan Kesetaraan API (API Priority and Fairness)
Kubernetes v1.18 [alpha]
Mengontrol perilaku server API dari Kubernetes pada situasi beban berlebih
merupakan tugas utama dari administrator klaster. kube-apiserver memiliki beberapa kontrol yang tersedia
(seperti opsi --max-request-inflight
dan --max-mutating-request-inflight
pada baris perintah atau command-line) untuk membatasi jumlah pekerjaan luar biasa yang akan
diterima, untuk mencegah banjirnya permintaan masuk dari beban berlebih
yang berpotensi untuk menghancurkan server API. Namun opsi ini tidak cukup untuk memastikan
bahwa permintaan yang paling penting dapat diteruskan pada saat kondisi lalu lintas (traffic) yang cukup tinggi.
Fitur Prioritas dan Kesetaraan API atau API Priority and Fairness (APF) adalah alternatif untuk meningkatkan batasan max-inflight seperti yang disebutkan di atas. APF mengklasifikasi dan mengisolasi permintaan dengan cara yang lebih halus. Fitur ini juga memperkenalkan jumlah antrian yang terbatas, sehingga tidak ada permintaan yang ditolak pada saat terjadi lonjakan permintaan dalam waktu yang sangat singkat. Permintaan dibebaskan dari antrian dengan menggunakan teknik antrian yang adil (fair queuing) sehingga, sebagai contoh, perilaku buruk dari satu controller tidak seharusnya mengakibatkan controller yang lain menderita (meskipun pada tingkat prioritas yang sama).
--max-request-inflight
tanpa mengaktifkan APF.
Mengaktifkan prioritas dan kesetaraan API
Fitur APF dikontrol oleh sebuah gerbang fitur (feature gate)
dan fitur ini tidak diaktifkan secara bawaan. Silahkan lihat
gerbang fitur
untuk penjelasan umum tentang gerbang fitur dan bagaimana cara mengaktifkan dan menonaktifkannya.
Nama gerbang fitur untuk APF adalah "APIPriorityAndFairness".
Fitur ini melibatkan sebuah Grup API yang harus juga diaktifkan. Kamu bisa melakukan ini dengan
menambahkan opsi pada baris perintah berikut pada permintaan ke kube-apiserver
kamu:
kube-apiserver \
--feature-gates=APIPriorityAndFairness=true \
--runtime-config=flowcontrol.apiserver.k8s.io/v1alpha1=true \
# …dan opsi-opsi lainnya seperti biasa
Opsi pada baris perintah --enable-priority-and-fairness=false
akan menonaktifkan fitur
APF, bahkan ketika opsi yang lain telah mengaktifkannya.
Konsep
Ada beberapa fitur lainnya yang terlibat dalam fitur APF. Permintaan yang masuk diklasifikasikan berdasarkan atribut permintaan dengan menggunakan FlowSchema, dan diserahkan ke tingkat prioritas. Tingkat prioritas menambahkan tingkat isolasi dengan mempertahankan batas konkurensi yang terpisah, sehingga permintaan yang diserahkan ke tingkat prioritas yang berbeda tidak dapat membuat satu sama lain menderita. Dalam sebuah tingkat prioritas, algoritma fair-queuing mencegah permintaan dari flows yang berbeda akan memberikan penderitaan kepada yang lainnya, dan memperbolehkan permintaan untuk dimasukkan ke dalam antrian untuk mencegah pelonjakan lalu lintas yang akan menyebabkan gagalnya permintaan, walaupun pada saat beban rata-ratanya cukup rendah.
Tingkat prioritas (Priority Level)
Tanpa pengaktifan APF, keseluruhan konkurensi dalam
server API dibatasi oleh opsi pada kube-apiserver
--max-request-inflight
dan --max-mutating-request-inflight
. Dengan pengaktifan APF,
batas konkurensi yang ditentukan oleh opsi ini akan dijumlahkan dan kemudian jumlah tersebut dibagikan
untuk sekumpulan tingkat prioritas (priority level) yang dapat dikonfigurasi. Setiap permintaan masuk diserahkan
ke sebuah tingkat prioritas, dan setiap tingkat prioritas hanya akan meneruskan sebanyak mungkin
permintaan secara bersamaan sesuai dengan yang diijinkan dalam konfigurasi.
Konfigurasi bawaan, misalnya, sudah mencakup tingkat prioritas terpisah untuk permintaan dalam rangka pemilihan pemimpin (leader-election), permintaan dari controller bawaan, dan permintaan dari Pod. Hal ini berarti bahwa Pod yang berperilaku buruk, yang bisa membanjiri server API dengan permintaan, tidak akan mampu mencegah kesuksesan pemilihan pemimpin atau tindakan yang dilakukan oleh controller bawaan.
Antrian (Queuing)
Bahkan dalam sebuah tingkat prioritas mungkin akan ada sumber lalu lintas yang berbeda dalam jumlah besar. Dalam situasi beban berlebih, sangat penting untuk mencegah satu aliran permintaan dari penderitaan karena aliran yang lainnya (khususnya, dalam kasus yang relatif umum dari sebuah klien tunggal bermasalah (buggy) yang dapat membanjiri kube-apiserver dengan permintaan, klien bermasalah itu idealnya tidak memiliki banyak dampak yang bisa diukur terhadap klien yang lainnya). Hal ini ditangani dengan menggunakan algoritma fair-queuing untuk memproses permintaan yang diserahkan oleh tingkat prioritas yang sama. Setiap permintaan diserahkan ke sebuah flow, yang diidentifikasi berdasarkan nama FlowSchema yang sesuai, ditambah dengan flow distinguisher - yang bisa saja didasarkan pada pengguna yang meminta, sumber daya Namespace dari target, atau tidak sama sekali - dan sistem mencoba untuk memberikan bobot yang hampir sama untuk permintaan dalam flow yang berbeda dengan tingkat prioritas yang sama.
Setelah mengklasifikasikan permintaan ke dalam sebuah flow, fitur APF kemudian dapat menyerahkan permintaan ke dalam sebuah antrian. Penyerahan ini menggunakan teknik yang dikenal sebagai _shuffle sharding_, yang membuat penggunaan antrian yang relatif efisien untuk mengisolasi flow dengan intensitas rendah dari flow dengan intensitas tinggi.
Detail dari algoritma antrian dapat disesuaikan untuk setiap tingkat prioritas, dan memperbolehkan administrator untuk menukar (trade off) dengan penggunaan memori, kesetaraan (properti dimana flow yang independen akan membuat semua kemajuan ketika total dari lalu lintas sudah melebihi kapasitas), toleransi untuk lonjakan lalu lintas, dan penambahan latensi yang dihasilkan oleh antrian.
Permintaan yang dikecualikan (Exempt Request)
Beberapa permintaan dianggap cukup penting sehingga mereka tidak akan mengikuti salah satu batasan yang diberlakukan oleh fitur ini. Pengecualian ini untuk mencegah konfigurasi flow control yang tidak terkonfigurasi dengan baik sehingga tidak benar-benar menonaktifkan server API.
Bawaan (Default)
Fitur APF dikirimkan dengan konfigurasi yang disarankan dimana konfigurasi itu seharusnya cukup untuk bereksperimen; jika klaster kamu cenderung mengalami beban berat maka kamu harus mempertimbangkan konfigurasi apa yang akan bekerja paling baik. Kelompok konfigurasi yang disarankan untuk semua permintaan terbagi dalam lima prioritas kelas:
-
Tingkat prioritas
system
diperuntukkan bagi permintaan dari grupsystem:nodes
, mis. Kubelet, yang harus bisa menghubungi server API agar mendapatkan workload untuk dijadwalkan. -
Tingkat prioritas
leader-election
diperuntukkan bagi permintaan dalam pemilihan pemimpin (leader election) dari controller bawaan (khususnya, permintaan untukendpoint
,configmaps
, atauleases
yang berasal darisystem:kube-controller-manager
atau penggunasystem:kube-scheduler
dan akun Service di Namespacekube-system
). Hal ini penting untuk mengisolasi permintaan ini dari lalu lintas yang lain karena kegagalan dalam pemilihan pemimpin menyebabkan controller akan gagal dan memulai kembali (restart), yang pada akhirnya menyebabkan lalu lintas yang lebih mahal karena controller yang baru perlu menyinkronkan para informannya. -
Tingkat prioritas
workload-high
diperuntukkan bagi permintaan yang lain dari controller bawaan. -
Tingkat prioritas
workload-low
diperuntukkan bagi permintaan dari akun Service yang lain, yang biasanya mencakup semua permintaan dari controller yang bekerja didalam Pod. -
Tingkat prioritas
global-default
menangani semua lalu lintas lainnya, mis. perintah interaktifkubectl
yang dijalankan oleh pengguna yang tidak memiliki hak khusus.
Kemudian, ada dua PriorityLevelConfiguration dan dua FlowSchema yang telah dibangun dan tidak mungkin ditimpa ulang:
-
Tingkat prioritas khusus
exempt
diperuntukkan bagi permintaan yang tidak akan dikenakan flow control sama sekali: permintaan itu akan selalu diteruskan sesegera mungkin. FlowSchemaexempt
khusus mengklasifikasikan semua permintaan dari kelompoksystem:masters
ke dalam tingkat prioritas khusus ini. Kamu juga dapat menentukan FlowSchema lain yang mengarahkan permintaan lain ke tingkat prioritas ini juga, apabila permintaan tersebut sesuai. -
Tingkat prioritas khusus
catch-all
digunakan secara kombinasi dengan spesial FlowSchemacatch-all
untuk memastikan bahwa setiap permintaan mendapatkan proses klasifikasi. Biasanya kamu tidak harus bergantung pada konfigurasi catch-all ini, dan kamu seharusnya membuat FlowSchema catch-all dan PriorityLevelConfiguration kamu sendiri (atau gunakan konfigurasiglobal-default
yang sudah diinstal secara bawaan) secara benar. Untuk membantu menemukan kesalahan konfigurasi yang akan melewatkan beberapa klasifikasi permintaan, maka tingkat prioritascatch-all
hanya wajib mengijinkan satu konkurensi bersama dan tidak melakukan memasukkan permintaan dalam antrian, sehingga membuat lalu lintas yang secara relatif hanya sesuai dengan FlowSchemacatch-all
akan ditolak dengan kode kesalahan HTTP 429.
Sumber daya (Resource)
Flow control API melibatkan dua jenis sumber daya. PriorityLevelConfiguration yang menentukan kelas isolasi yang tersedia, bagian dari konkurensi anggaran yang tersedia yang masing-masing dapat menangani bagian tersebut, dan memperbolehkan untuk melakukan fine-tuning terhadap perilaku antrian. FlowSchema yang digunakan untuk mengklasifikasikan permintaan individu yang masuk, mencocokkan masing-masing dengan setiap PriorityLevelConfiguration.
PriorityLevelConfiguration
Sebuah PriorityLevelConfiguration merepresentasikan sebuah kelas isolasi tunggal. Setiap PriorityLevelConfiguration memiliki batas independensi dalam hal jumlah permintaan yang belum diselesaikan, dan batasan dalam hal jumlah permintaan yang mengantri.
Batas konkurensi untuk PriorityLevelConfiguration tidak disebutkan dalam
jumlah permintaan secara mutlak, melainkan dalam "concurrency shares." Total batas konkurensi
untuk server API didistribusikan di antara PriorityLevelConfiguration yang ada
secara proporsional dengan "concurrency shares" tersebut. Ini mengizinkan seorang
administrator klaster untuk meningkatkan atau menurunkan jumlah total lalu lintas ke sebuah
server dengan memulai kembali kube-apiserver
dengan nilai opsi
--max-request-inflight
(atau --max-mutating-request-inflight
) yang berbeda, dan semua
PriorityLevelConfiguration akan melihat konkurensi maksimum yang diizinkan kepadanya untuk menaikkan (atau
menurunkan) dalam fraksi yang sama.
--max-request-inflight
dan
--max-mutating-request-inflight
. Tidak akan ada lagi perbedaan
antara permintaan yang bermutasi dan permintaan yang tidak bermutasi; jika kamu ingin melayaninya
secara terpisah untuk suatu sumber daya yang ada, maka perlu membuat FlowSchema terpisah yang sesuai dengan
masing-masing kata kerja dari permintaan yang bermutasi dan yang tidak bermutasi tersebut.
Ketika jumlah permintaan masuk yang diserahkan kepada sebuah
PriorityLevelConfiguration melebihi dari tingkat konkurensi yang diizinkan,
bagian type
dari spesifikasinya menentukan apa yang akan terjadi pada permintaan selanjutnya.
Tipe Reject
berarti bahwa kelebihan lalu lintas akan segera ditolak
dengan kode kesalahan HTTP 429 (yang artinya terlalu banyak permintaan). Tipe Queue
berarti permintaan
di atas batas tersebut akan mengantri, dengan teknik sharding shuffle dan fair queuing yang digunakan
untuk menyelaraskan kemajuan antara flow permintaan.
Konfigurasi antrian memungkinkan mengatur algoritma fair queuing untuk sebuah tingkat prioritas. Detail algoritma dapat dibaca di proposal pembaharuan, namun secara singkat:
-
Meningkatkan
queue
(antrian) berarti mengurangi tingkat tabrakan antara flow yang berbeda, sehingga berakibat pada biaya untuk meningkatkan penggunaan memori. Nilai 1 di sini secara efektif menonaktifkan logika fair-queuing, tetapi masih mengizinkan permintaan untuk dimasukkan kedalam antrian. -
Meningkatkan
queueLengthLimit
berarti memperbolehkan lonjakan yang lebih besar dari lalu lintas untuk berkelanjutan tanpa menggagalkan permintaan apa pun, dengan konsekuensi akan meningkatkan latensi dan penggunaan memori. -
Mengubah
handSize
berarti memperbolehkan kamu untuk menyesuaikan probabilitas tabrakan antara flow yang berbeda dan keseluruhan konkurensi yang tersedia untuk satu flow tunggal dalam situasi beban berlebih.Catatan:HandSize
yang lebih besar membuat dua flow individual berpeluang kecil untuk bertabrakan (dan dimana flow yang satu bisa membuat flow yang lain menderita), tetapi akan lebih memungkinkan bahwa flow dalam jumlah kecil akan dapat mendominasi apiserver.HandSize
yang lebih besar juga berpotensi meningkatkan jumlah latensi yang diakibatkan oleh satu flow lalu lintas tunggal yang tinggi. Jumlah maksimum permintaan dalam antrian yang diijinkan dari sebuah flow tunggal adalahhandSize * queueLengthLimit
.
Berikut ini adalah tabel yang menunjukkan koleksi konfigurasi shuffle sharding yang menarik, dimana setiap probabilitas mouse (flow dengan intensitas rendah) yang diberikan akan dimampatkan oleh elephant (flow dengan intensitas tinggi) dalam sebuah koleksi ilustratif dari jumlah elephant yang berbeda. Silahkan lihat pada https://play.golang.org/p/Gi0PLgVHiUg, yang digunakan untuk menghitung nilai-nilai dalam tabel ini.
HandSize | Queues | 1 elephant | 4 elephants | 16 elephants |
---|---|---|---|---|
12 | 32 | 4.428838398950118e-09 | 0.11431348830099144 | 0.9935089607656024 |
10 | 32 | 1.550093439632541e-08 | 0.0626479840223545 | 0.9753101519027554 |
10 | 64 | 6.601827268370426e-12 | 0.00045571320990370776 | 0.49999929150089345 |
9 | 64 | 3.6310049976037345e-11 | 0.00045501212304112273 | 0.4282314876454858 |
8 | 64 | 2.25929199850899e-10 | 0.0004886697053040446 | 0.35935114681123076 |
8 | 128 | 6.994461389026097e-13 | 3.4055790161620863e-06 | 0.02746173137155063 |
7 | 128 | 1.0579122850901972e-11 | 6.960839379258192e-06 | 0.02406157386340147 |
7 | 256 | 7.597695465552631e-14 | 6.728547142019406e-08 | 0.0006709661542533682 |
6 | 256 | 2.7134626662687968e-12 | 2.9516464018476436e-07 | 0.0008895654642000348 |
6 | 512 | 4.116062922897309e-14 | 4.982983350480894e-09 | 2.26025764343413e-05 |
6 | 1024 | 6.337324016514285e-16 | 8.09060164312957e-11 | 4.517408062903668e-07 |
FlowSchema
FlowSchema mencocokkan beberapa permintaan yang masuk dan menetapkan permintaan ke dalam sebuah
tingkat prioritas. Setiap permintaan masuk diuji dengan setiap
FlowSchema secara bergiliran, dimulai dari yang terendah secara numerik ---
yang kita anggap sebagai yang tertinggi secara logis --- matchingPrecedence
dan
begitu seterusnya. FlowSchema yang cocok pertama kali akan menang.
matchingPrecedence
tertinggi. Jika ada beberapa FlowSchema dengan nilai
matchingPrecedence
yang sama dan cocok dengan permintaan yang sama juga, permintaan dengan leksikografis
name
yang lebih kecil akan menang, tetapi akan lebih baik untuk tidak mengandalkan metode ini, dan sebaiknya
perlu memastikan bahwa tidak ada dua FlowSchema yang memiliki matchingPrecedence
yang sama.
Sebuah FlowSchema dianggap cocok dengan sebuah permintaan yang diberikan jika setidaknya salah satu dari rules
nya
ada yang cocok. Sebuah aturan (rule) cocok jika setidaknya satu dari subject
dan
ada salah satu dari resourceRules
atau nonResourceRules
(tergantung dari apakah permintaan
yang masuk adalah untuk URL sumber daya atau non-sumber daya) yang cocok dengan permintaan tersebut.
Untuk bagian name
dalam subjek, dan bagian verbs
, apiGroups
, resources
,
namespaces
, dan nonResourceURLs
dalam aturan sumber daya dan non-sumber daya,
wildcard *
mungkin bisa ditetapkan untuk mencocokkan semua nilai pada bagian yang diberikan,
sehingga secara efektif menghapusnya dari pertimbangan.
Sebuah DistinguisherMethod.type
dari FlowSchema menentukan bagaimana permintaan
yang cocok dengan Skema itu akan dipisahkan menjadi flow. Nilai tipe itu bisa jadi ByUser
, dalam
hal ini satu pengguna yang meminta tidak akan bisa menghabiskan kapasitas dari pengguna lain,
atau bisa juga ByNamespace
, dalam hal ini permintaan sumber daya
di salah satu Namespace tidak akan bisa menyebabkan penderitaan bagi permintaan akan sumber daya
dalam kapasitas Namespace yang lain, atau bisa juga kosong (atau distinguisherMethod
dihilangkan seluruhnya), dalam hal ini semua permintaan yang cocok dengan FlowSchema ini akan
dianggap sebagai bagian dari sebuah flow tunggal. Pilihan yang tepat untuk FlowSchema yang diberikan
akan bergantung pada sumber daya dan lingkungan khusus kamu.
Diagnosis
Setiap respons HTTP dari server API dengan fitur prioritas dan kesetaraan
yang diaktifkan memiliki dua header tambahan: X-Kubernetes-PF-FlowSchema-UID
dan
X-Kubernetes-PF-PriorityLevel-UID
, yang mencatat skema flow yang cocok dengan permintaan
dan tingkat prioritas masing-masing. Name Objek API tidak termasuk dalam header ini jika pengguna peminta tidak
memiliki izin untuk melihatnya, jadi ketika melakukan debugging kamu dapat menggunakan perintah seperti ini
kubectl get flowschema -o custom-columns="uid:{metadata.uid},name:{metadata.name}"
kubectl get prioritylevelconfiguration -o custom-columns="uid:{metadata.uid},name:{metadata.name}"
untuk mendapatkan pemetaan UID ke names baik untuk FlowSchema maupun PriorityLevelConfiguration.
Observabilitas
Saat kamu mengaktifkan fitur Prioritas dan Kesetaraan API atau APF, kube-apiserver akan mengeluarkan metrik tambahan. Dengan memantau metrik ini dapat membantu kamu untuk menentukan apakah konfigurasi kamu tidak tepat dalam membatasi lalu lintas yang penting, atau menemukan beban kerja yang berperilaku buruk yang dapat membahayakan kesehatan dari sistem.
-
apiserver_flowcontrol_rejected_requests_total
menghitung permintaan yang ditolak, mengelompokkannya berdasarkan nama dari tingkat prioritas yang ditetapkan, nama FlowSchema yang ditetapkan, dan alasan penolakan tersebut. Alasan penolakan akan mengambil dari salah satu alasan-alasan berikut:queue-full
, yang mengindikasikan bahwa sudah terlalu banyak permintaan yang menunggu dalam antrian,concurrency-limit
, yang mengindikasikan bahwa PriorityLevelConfiguration telah dikonfigurasi untuk menolak, bukan untuk memasukan permintaan berlebih ke dalam antrian, atautime-out
, yang mengindikasikan bahwa permintaan masih dalam antrian ketika batas waktu antriannya telah berakhir.
-
apiserver_flowcontrol_dispatched_requests_total
menghitung permintaan yang sudah mulai dieksekusi, mengelompokkannya berdasarkan nama dari tingkat prioritas yang ditetapkan, dan nama dari FlowSchema yang ditetapkan. -
apiserver_flowcontrol_current_inqueue_requests
memberikan jumlah total sesaat secara instan dari permintaan dalam antrian (bukan yang dieksekusi), dan mengelompokkannya berdasarkan tingkat prioritas dan FlowSchema. -
apiserver_flowcontrol_current_executing_requests
memberikan jumlah total yang instan dari permintaan yang dieksekusi, dan mengelompokkannya berdasarkan tingkat prioritas dan FlowSchema. -
apiserver_flowcontrol_request_queue_length_after_enqueue
memberikan histogram dari panjang antrian untuk semua antrian yang ada, mengelompokkannya berdasarkan tingkat prioritas dan FlowSchema, berdasarkan pengambilan sampel oleh permintaan enqueued. Setiap permintaan yang mendapatkan antrian berkontribusi ke satu sampel dalam histogramnya, pelaporan panjang antrian dilakukan setelah permintaan yang mengantri tersebut ditambahkan. Perlu dicatat bahwa ini akan menghasilkan statistik yang berbeda dengan survei yang tidak bias.Catatan: Nilai asing atau tidak biasa dalam histogram akan berarti ada kemungkinan sebuah flow(misalnya, permintaan oleh satu pengguna atau untuk satu namespace, tergantung pada konfigurasinya) telah membanjiri server API, dan sedang dicekik. Sebaliknya, jika histogram dari satu tingkat prioritas menunjukkan bahwa semua antrian dalam prioritas level itu lebih panjang daripada level prioritas yang lainnya, mungkin akan sesuai untuk meningkatkan concurrency shares dari PriorityLevelConfiguration itu.
-
apiserver_flowcontrol_request_concurrency_limit
memberikan hasil perhitungan batas konkurensi (berdasarkan pada batas konkurensi total dari server API dan concurrency share dari PriorityLevelConfiguration) untuk setiap PriorityLevelConfiguration. -
apiserver_flowcontrol_request_wait_duration_seconds
memberikan histogram tentang bagaimana permintaan yang panjang dihabiskan dalam antrian, mengelompokkannya berdasarkan FlowSchema yang cocok dengan permintaan, tingkat prioritas yang ditetapkan, dan apakah permintaan tersebut berhasil dieksekusi atau tidak.Catatan: Karena setiap FlowSchema selalu memberikan permintaan untuk satuPriorityLevelConfiguration, kamu dapat menambahkan histogram untuk semua FlowSchema dalam satu tingkat prioritas untuk mendapatkan histogram yang efektif dari permintaan yang ditetapkan ke tingkat prioritas tersebut.
apiserver_flowcontrol_request_execution_seconds
memberikan histogram tentang bagaimana caranya permintaan yang panjang diambil untuk benar-benar dieksekusi, mengelompokkannya berdasarkan FlowSchema yang cocok dengan permintaan dan tingkat prioritas yang ditetapkan pada permintaan tersebut.
Selanjutnya
Untuk latar belakang informasi mengenai detail desain dari prioritas dan kesetaraan API, silahkan lihat proposal pembaharuan. Kamu juga dapat membuat saran dan permintaan akan fitur melalui SIG API Machinery.
-
3.12 - Memperluas Kubernetes
3.12.1 - Memperluas Klaster Kubernetes Kamu
Kubernetes sangat mudah dikonfigurasi dan diperluas. Sehingga, jarang membutuhkan fork atau menambahkan patch ke kode proyek Kubernetes.
Panduan ini menjelaskan pilihan untuk menyesuaikan klaster Kubernetes. Dokumen ini ditujukan kepada operator klaster yang ingin memahami bagaimana menyesuaikan klaster Kubernetes dengan kebutuhan lingkungan kerja mereka.
Developer yang prospektif Developer Platform atau Kontributor Proyek Kubernetes juga mendapatkan manfaat dari dokumen ini sebagai pengantar apa saja poin-poin dan pola-pola perluasan yang ada, untung-rugi, dan batasan-batasannya.
Ikhtisar
Pendekatan-pendekatan kostumisasi secara umum dapat dibagi atas konfigurasi, yang hanya melibatkan perubahan flag, konfigurasi berkas lokal, atau objek-objek sumber daya API; dan perluasan, yang melibatkan berjalannya program atau layanan tambahan. Dokumen ini sebagian besar membahas tentang perluasan.
Konfigurasi
Flag-flag dan berkas-berkas konfigurasi didokumentasikan di bagian Referensi dari dokumentasi daring, didalam setiap binary:
Flag-flag dan berkas-berkas konfigurasi mungkin tidak selalu dapat diubah pada layanan Kubernetes yang hosted atau pada distribusi dengan instalasi yang dikelola. Ketika mereka dapat diubah, mereka biasanya hanya dapat diubah oleh Administrator Klaster. Dan juga, mereka dapat sewaktu-waktu diubah dalam versi Kubernetes di masa depan, dan menyetel mereka mungkin memerlukan proses pengulangan kembali. Oleh karena itu, mereka harus digunakan hanya ketika tidak ada pilihan lain.
API kebijakan bawaan, seperti ResourceQuota, PodSecurityPolicy, NetworkPolicy dan Role-based Access Control (RBAC), adalah API bawaan Kubernetes. API biasanya digunakan oleh layanan Kubernetes yang hosted dan diatur oleh instalasi Kubernetes. Mereka bersifat deklaratif dan menggunakan konvensi yang sama dengan sumber daya Kubernetes lainnya seperti pod-pod, jadi konfigurasi klaster baru dapat diulang-ulang dan dapat diatur dengan cara yang sama dengan aplikasi. Dan, ketika mereka stabil, mereka mendapatkan keuntungan dari kebijakan pendukung yang jelas seperti API Kubernetes lainnya. Oleh karena itu, mereka lebih disukai daripada berkas konfigurasi dan flag-flag saat mereka cocok dengan situasi yang dibutuhkan.
Perluasan
Perluasan adalah komponen perangkat lunak yang memperluas dan berintegrasi secara mendalam dengan Kubernetes. Mereka mengadaptasi Kubernetes untuk mendukung perangkat keras tipe baru dan jenis baru.
Kebanyakan administrator klaster akan menggunakan instansi Kubernetes yang didistribusikan atau yang hosted. Sebagai hasilnya, kebanyakan pengguna Kubernetes perlu menginstal perluasan dan lebih sedikit yang perlu untuk membuat perluasan-perluasan yang baru.
Pola-pola Perluasan
Kubernetes didesain untuk dapat diotomasi dengan menulis program-program klien. Program apapun yang membaca dan/atau menulis ke API Kubernetes dapat menyediakan otomasi yang berguna.
Otomasi dapat berjalan di dalam klaster atau di luar klaster. Dengan mengikuti panduan di dalam dokumen ini, kamu dapat menulis otomasi yang sangat tersedia dan kuat. Otomasi pada umumnya dapat bekerja dengan berbagai macam klaster Kubernetes, termasuk klaster yang hosted dan instalasi yang dikelola.
Ada pola spesifik untuk menulis program klien yang bekerja dengan baik bersama Kubernetes yang disebut pola Controller. Controller-controller biasanya membaca kolom .spec
milik sebuah objek, kemungkinan melakukan sesuatu, dan kemudian memperbarui objek milik .status
.
Controller adalah klien dari Kubernetes. Ketika Kubernetes adalah klien dan memanggil layanan terpisah, hal tersebut disebut Webhook. Layanan terpisah tersebut disebut sebuah Webhook Backend. Seperti Controller-controller, Webhook-webhook memang menambah sebuah titik untuk terjadinya kegagalan.
Di dalam model Webhook, Kubernetes membuat sebuah network request kepada sebuah layanan terpisah.
Di dalam model Binary Plugin, Kubernetes mengeksekusi sebuah program. Binary Plugin digunakan oleh kubelet (misalnya Plugin Flex Volume dan oleh Plugin Jaringan) dan oleh kubectl.
Berikut ini adalah diagram yang menunjukkan bagaimana titik-titik perluasan berinteraksi dengan control plane Kubernetes.
Titik-titik Perluasan
Diagram berikut menunjukkan titik-titik perluasan di sebuah Kubernetes.
- Pengguna biasanya berinteraksi dengan API Kubernetes menggunakan
kubectl
. Plugin-plugin Kubectl memperluas binari kubectl. Mereka hanya memengaruhi lingkungan lokal pengguna, dan tidak dapat memaksakan kebijakan yang menyeluruh di seluruh situs. - apiserver menangani semua permintaan. Beberapa tipe titik perluasan di apiserver memperbolehkan otentikasi permintaan, atau memblokir mereka berdasarkan konten mereka, menyunting konten, dan menangani penghapusan. Hal ini dideskripsikan di bagian Perluasan Akses API
- apiserver melayani berbagai macam sumber daya, tipe-tipe sumber daya bawaan, seperti
pod
, didefinisikan oleh proyek kubernetes dan tidak dapat diubah. kamu juga dapat menambahkan sumber daya yang kamu definisikan sendiri, atau yang proyek lain definisikan, disebut Custom Resources, seperti dijelaskan di bagian Sumber Daya Custom. Sumber daya Custom sering digunakan dengan Perluasan Akses API. - Penjadwal Kubernetes memutuskan ke Node mana Pod akan ditempatkan. Ada beberapa cara untuk memperluas penjadwalan. Hal ini dibahas pada bagian Perluasan-perluasan Penjadwal.
- Sebagian besar perilaku Kubernetes diimplementasi oleh program yang disebut Controller-controller yang merupakan klien dari API-Server. Controller-controller sering digunakan bersama dengan Sumber Daya Custom.
- Kubelet berjalan di server, dan membantu Pod-pod terlihat seperti server virtual dengan IP mereka sendiri di jaringan klaster. Plugin Jaringan memungkinkan adanya perbedaan implementasi pada jaringan Pod.
- Kubelet juga melakukan penambatan dan pelepasan tambatan volume untuk kontainer. Tipe-tipe penyimpanan baru dapat didukung via Plugin Penyimpanan.
Jika kamu tidak yakin untuk memulai dari mana, diagram alir di bawah ini dapat membantu kamu. Ingat lah bahwa beberapa solusi mungkin melibatkan beberapa tipe perluasan.
Perluasan API
Tipe-tipe yang Ditentukan Pengguna
Pertimbangkan untuk menambahkan Sumber Daya Custom ke Kubernetes jika kamu ingin mendefinisikan pengontrol baru, objek konfigurasi aplikasi atau API deklaratif lainnya, dan untuk mengelolanya menggunakan alat Kubernetes, seperti kubectl
.
Jangan menggunakan Sumber Daya Custom sebagai penyimpanan data untuk aplikasi, pengguna, atau untuk memonitor data.
Untuk lebih jelasnya tentang Sumber Daya Custom, lihat Panduan Konsep Sumber Daya Custom.
Menggabungkan API Baru dengan Otomasi
Kombinasi antara sebuah API sumber daya custom dan loop kontrol disebut Pola Operator. Pola Operator digunakan untuk mengelola aplikasi yang spesifik dan biasanya stateful. API-API custom dan loop kontrol ini dapat digunakan untuk mengatur sumber daya lainnya, seperti penyimpanan dan kebijakan-kebijakan.
Mengubah Sumber Daya Bawaan
Ketika kamu memperluas API Kubernetes dengan menambahkan sumber daya custom, sumber daya yang ditambahkan akan selalu masuk ke Grup API baru. Kamu tidak dapat mengganti atau mengubah Grup API yang sudah ada. Menambah sebuah API tidak secara langsung membuat kamu memengaruhi perilaku API yang sudah ada (seperti Pod), tetapi Perluasan Akses API dapat memengaruhinya secara langsung.
Perluasan-Perluasan Akses API
Ketika sebuah permintaan sampai ke Server API Kubernetes, permintaan tersebut diotentikasi terlebih dahulu, kemudian diotorisasi, kemudian diarahkan ke berbagai jenis Admission Control. Lihat dokumentasi Mengatur Akses ke API Kubernetes untuk lebih jelasnya tentang alur ini.
Setiap langkah berikut menawarkan titik-titik perluasan.
Kubernetes memiliki beberapa metode otentikasi bawaan yang didukungnya. Metode ini bisa berada di belakang proksi yang mengotentikasi, dan metode ini dapat mengirim sebuah token dari header Otorisasi ke layanan terpisah untuk verifikasi (sebuah webhook). Semua metode ini tercakup dalam Dokumentasi Otentikasi.
Otentikasi
Otentikasi memetakan header atau sertifikat dalam semua permintaan ke username untuk klien yang mebuat permintaan.
Kubernetes menyediakan beberapa metode otentikasi bawaan, dan sebuah metode Webhook Otentikasi jika metode bawaan tersebut tidak mencukupi kebutuhan kamu.
Otorisasi
Otorisasi menentukan apakah pengguna tertentu dapat membaca, menulis, dan melakukan operasi lainnya terhadap sumber daya API. Hal ini hanya bekerja pada tingkat sumber daya secara keseluruhan -- tidak membeda-bedakan berdasarkan field objek sembarang. Jika pilihan otorisasi bawaan tidak mencukupi kebutuhan kamu, Webhook Otorisasi memungkinkan pemanggilan kode yang disediakan pengguna untuk membuat keputusan otorisasi.
Kontrol Admisi Dinamis
Setalah permintaan diotorisasi, jika ini adalah operasi penulisan, permintaan ini akan melalui langkah Kontrol Admisi. Sebagai tambahan untuk step bawaan, ada beberapa perluasan:
- Webhook Kebijakan Image membatasi image mana saja yang dapat berjalan di kontainer.
- Untuk membuat keputusan kontrol admisi sembarang, Webhook Admisi umum dapat digunakan. Webhook Admisi dapat menolak pembuatan atau pembaruan.
Perluasan Infrastruktur
Plugin-plugin Penyimpanan
Flex Volume memungkinkan pengguna untuk memasang tipe-tipe volume tanpa dukungan bawaan dengan cara membiarkan Kubelet memanggil sebuah Plugin Binary untuk menambatkan volume.
Plugin Perangkat
Plugin perangkat memungkinkan sebuah node untuk menemukan sumber daya Node baru (sebagai tambahan dari bawaannya seperti CPU dan memori) melalui sebuah Plugin Perangkat.
Plugin-plugin Jaringan
Struktur-struktur jaringan yang berbeda dapat didukung melalui Plugin Jaringan pada tingkat Node.
Perluasan-perluasan Penjadwal
Penjadwal adalah jenis pengatur spesial yang mengawasi Pod, dan menempatkan Pod ke Node. Penjadwal bawaan dapat digantikan seluruhnya, sementara terus menggunakan komponen Kubernetes lainnya, atau penjadwal ganda dapat berjalan dalam waktu yang bersamaan.
Ini adalah usaha yang signifikan, dan hampir semua pengguna Kubernetes merasa mereka tidak perlu memodifikasi penjadwal tersebut.
Penjadwal juga mendukung webhook yang memperbolehkan sebuah webhook backend (perluasan penjadwal) untuk menyaring dan memprioritaskan Node yang terpilih untuk sebuah Pod.
Selanjutnya
- Pelajari lebih lanjut tentang Sumber Daya Custom
- Pelajari tentang Kontrol Admisi Dinamis
- Pelajari lebih lanjut tentang perluasan Infrastruktur
- Pelajari tentang Plugin kubectl
- Pelajari tentang Pola Operator
3.12.2 - Memperluas API Kubernetes
3.12.2.1 - Memperluas Kubernetes API dengan Lapisan Agregasi
Lapisan agregasi memungkinkan Kubernetes untuk diperluas dengan API tambahan, selain dari yang ditawarkan oleh API inti Kubernetes.
Ikhtisar
Lapisan agregasi memungkinkan instalasi tambahan beragam API Kubernetes-style di kluster kamu. Tambahan-tambahan ini dapat berupa solusi-solusi yang sudah dibangun (prebuilt) oleh pihak ke-3 yang sudah ada, seperti service-catalog, atau API yang dibuat oleh pengguna seperti apiserver-builder, yang dapat membantu kamu memulainya.
Lapisan agregasi berjalan di dalam proses bersama dengan kube-apiserver. Hingga sebuah sumber daya ekstensi terdaftar, lapisan agregasi tidak akan melakukan apapun. Untuk mendaftarkan sebuah API, pengguna harus menambahkan sebuah objek APIService, yang "mengklaim" jalur URL di API Kubernetes. Pada titik tersebut, lapisan agregasi akan mem-proxy apapun yang dikirim ke jalur API tersebut (misalnya /apis/myextension.mycompany.io/v1/…) ke APIService yang terdaftar.
Biasanya, APIService akan diimplementasikan oleh sebuah ekstensi-apiserver di dalam sebuah Pod yang berjalan di kluster. Ekstensi-apiserver ini biasanya perlu di pasangkan dengan satu atau lebih controller apabila manajemen aktif dari sumber daya tambahan diperlukan. Sebagai hasilnya, apiserver-builder sebenarnya akan memberikan kerangka untuk keduanya. Sebagai contoh lain, ketika service-catalog diinstal, ia menyediakan ekstensi-apiserver dan controller untuk layanan-layanan yang disediakannya.
Ekstensi-apiserver harus memiliki latensi koneksi yang rendah dari dan ke kube-apiserver.
Secara Khusus, permintaan pencarian diperlukan untuk bolak-balik dari kube-apiserver dalam 5 detik atau kurang.
Jika implementasi kamu tidak dapat menyanggupinya, kamu harus mempertimbangkan cara mengubahnya. Untuk sekarang, menyetel
feature-gate EnableAggregatedDiscoveryTimeout=false
di kube-apiserver
akan menonaktifkan batasan waktu tersebut. Fitur ini akan dihapus dalam rilis mendatang.
Selanjutnya
- Untuk mengaktifkan agregator di lingkungan kamu, aktifkankonfigurasi lapisan agregasi.
- Kemudian, siapkan ekstensi api-server untuk bekerja dengan lapisan agregasi.
- Selain itu, pelajari caranya mengembangkan API Kubernetes menggunakan Custom Resource Definition.
3.12.2.2 - Custom Resource
Custom Resource adalah ekstensi dari Kubernetes API. Laman ini mendiskusikan kapan kamu melakukan penambahan sebuah Custom Resource ke klaster Kubernetes dan kapan kamu menggunakan sebuah layanan mandiri. Laman ini mendeskripsikan dua metode untuk menambahkan Custom Resource dan bagaimana cara memilihnya.
Custom Resource
Sebuah sumber daya adalah sebuah endpoint pada Kubernetes API yang menyimpan sebuah koleksi objek API dari sebuah jenis tertentu. Sebagai contoh, sumber daya bawaan Pod mengandung sebuah koleksi objek-objek Pod.
Sebuah Custom Resource adalah sebuah ekstensi dari Kubernetes API yang tidak seharusnya tersedia pada pemasangan default Kubernetes. Namun, banyak fungsi-fungsi inti Kubernetes yang sekarang dibangun menggunakan Custom Resource, membuat Kubernetes lebih modular.
Custom Resource bisa muncul dan menghilang dalam sebuah klaster yang berjalan melalui registrasi dinamis (dynamic registration), dan admin-admin klaster bisa memperbaharui Custom Resource secara independen dari klaster itu sendiri. Ketika sebuah Custom Resource dipasang, pengguna dapat membuat dan mengakses objek-objek Custom Resource menggunakan kubectl, seperti yang mereka lakukan untuk sumber daya bawaan seperti Pod.
Controller Khusus
Dengan sendirinya, Custom Resource memungkinkan kamu untuk menyimpan dan mengambil data terstruktur. Ketika kamu menggabungkan sebuah Custom Resource dengan controller khusus, Custom Resource akan memberikan sebuah API deklaratif yang sebenarnya.
Sebuah API deklaratif memungkinkan kamu untuk mendeklarasikan atau menspesifikasikan keadaan dari sumber daya kamu dan mencoba untuk menjaga agar keadaan saat itu tersinkronisasi dengan keadaan yang diinginkan. Controller menginterpretasikan data terstruktur sebagai sebuah rekaman dari keadaan yang diinginkan pengguna, dan secara kontinu menjaga keadaan ini.
Kamu bisa men-deploy dan memperbaharui sebuah controller khusus pada sebuah klaster yang berjalan, secara independen dari siklus hidup klaster itu sendiri. Controller khusus dapat berfungsi dengan sumber daya jenis apapun, tetapi mereka sangat efektif ketika dikombinasikan dengan Custom Resource. Operator pattern mengkombinasikan Custom Resource dan controller khusus. Kamu bisa menggunakan controller khusus untuk menyandi pengetahuan domain untuk aplikasi spesifik menjadi sebuah ekstensi dari Kubernetes API.
Haruskah Custom Resource ditambahkan ke dalam klaster Kubernetes saya?
Ketika membuat sebuah API baru, pikirkan apakah kamu ingin mengagregasikan API kamu dengan API klaster Kubernetes atau membiarkan API kamu berdiri sendiri.
Pilih agregasi API jika: | Pilih sebuah API yang berdiri sendiri jika: |
---|---|
API kamu bersifat Deklaratif. | API kamu tidak cocok dengan model Deklaratif. |
Kamu mau tipe baru yang dapat dibaca dan ditulis dengan kubectl . |
Dukungan kubectl tidak diperlukan |
Kamu mau melihat tipe baru pada sebuah Kubernetes UI, seperti dasbor, bersama dengan tipe-tipe bawaan. | Dukungan Kubernetes UI tidak diperlukan. |
Kamu mengembangkan sebuah API baru. | Kamu memiliki sebuah program yang melayani API kamu dan dapat berkerja dengan baik. |
Kamu bersedia menerima pembatasan format yang Kubernetes terapkan pada jalur sumber daya API (Lihat Ikhtisar API.) | Kamu perlu memiliki jalur REST spesifik agar menjadi cocok dengan REST API yang telah didefinisikan. |
Sumber daya kamu secara alami mencakup hingga sebuah klaster atau sebuah namespace dari sebuah klaster. | Sumber daya yang mencakup klaster atau namespace adalah sebuah ketidakcocokan; kamu perlu mengendalikan jalur sumber daya spesifik. |
Kamu ingin menggunakan kembali dukungan fitur Kubernetes API. | Kamu tidak membutuhkan fitur tersebut. |
API Deklaratif
Dalam sebuah API Deklaratif, biasanya:
- API kamu terdiri dari sejumlah kecil dari objek yang berukuran relatif kecil (sumber daya).
- Objek-objek mendefinisikan pengaturan dari aplikasi atau infrastruktur.
- Objek-objek relatif tidak sering diperbaharui.
- Manusia sering diperlukan untuk membaca dan menulis objek-objek tersebut.
- Operasi utama terhadap objek bersifat CRUD (creating, reading, updating, dan deleting).
- Transaksi antar objek tidak dibutuhkan; API merepresentasikan sebuah keadaan yang diinginkan, bukan keadaan yang eksak.
API imperatif bersifat tidak deklaratif. Tanda-tanda apabila API kamu tidak deklaratif termasuk:
- klien berkata "lakukan ini", dan kemudian mendapat sebuah respon serempak ketika selesai.
- klien berkata "lakukan ini", dan kemudian mendapat sebuah ID operasi kembali, dan harus melakukan sebuah cek terhadap objek Operation terpisah untuk menentukan selesainya sebuah permintaan.
- Kamu berbicara tentang Remote Procedure Call (RPC).
- Menyimpan secara langsung sejumlah data (mis. > beberapa kB per objek, atau >1000-an objek).
- Membutuhkan akses dengan bandwidth tinggi (10-an permintaan per detik dapat ditopang).
- Menyimpan data pengguna (seperti gambar, PII, dll) atau data berskala besar yang diproses oleh aplikasi.
- Operasi-operasi natural terhadap objek yang tidak bersifat CRUD.
- API yang tidak mudah dimodelkan dengan objek.
- Kamu memilih untuk merepresentasikan operasi tertunda dengan sebuah ID operasi atau sebuah objek operasi.
Apakah saya harus menggunakan sebuah ConfigMap atau sebuah Custom Resource?
Gunakan ConfigMap jika salah satu hal berikut berlaku:
- Terdapat sebuah format berkas pengaturan yang sudah ada, yang terdokumentasi dengan baik seperti sebuah
mysql.cnf
ataupom.xml
. - Kamu ingin menaruh seluruh berkas pengaturan kedalam sebuah key dari sebuah ConfigMap.
- Kegunaan utama dari berkas pengaturan adalah untuk dikonsumsi sebuah program yang berjalan di dalam sebuah Pod di dalam klaster kamu untuk mengatur dirinya sendiri.
- Konsumen dari berkas lebih suka untuk mengkonsumsi lewat berkas dalam sebuah Pod atau variabel lingkungan dalam sebuah Pod, dibandingkan melalui Kubernetes API.
- Kamu ingin melakukan pembaharuan bergulir lewat Deployment, dll, ketika berkas diperbaharui.
Gunakan sebuah Custom Resource (CRD atau Aggregated API) jika kebanyakan dari hal berikut berlaku:
- Kamu ingin menggunakan pustaka klien Kubernetes dan CLI untuk membuat dan memperbaharui sumber daya baru.
- Kamu ingin dukungan tingkat tinggi dari kubectl (sebagai contoh:
kubectl get my-object object-name
). - Kamu ingin membangun sebuah otomasi baru yang mengawasi pembaharuan terhadap objek baru, dan kemudian melakukan CRUD terhadap objek lainnya, atau sebaliknya.
- Kamu ingin menulis otomasi yang menangani pembaharuan untuk objek.
- Kamu ingin menggunakan kesepakatan API Kubernetes seperti
.spec
,.status
, dan.metadata
. - Kamu ingin objek tersebut untuk menjadi sebuah abstraksi terhadap sebuah kumpulan dari sumber daya terkontrol, atau peringkasan dari sumber daya lainnya.
Menambahkan Custom Resource
Kubernetes menyediakan dua cara untuk menambahkan sumber daya ke klaster kamu:
- CRD cukup sederhana dan bisa diciptakan tanpa pemrograman apapun.
- Agregasi API membutuhkan pemrograman, tetapi memungkinkan kendali lebih terhadap perilaku API seperti bagaimana data disimpan dan perubahan antar versi API.
Kubernetes menyediakan kedua opsi tersebut untuk memenuhi kebutuhan pengguna berbeda, jadi tidak ada kemudahan penggunaan atau fleksibilitas yang dikompromikan.
Aggregated API adalah bawahan dari APIServer yang duduk dibelakang API server utama, yang bertindak sebagai sebuah proxy. Pengaturan ini disebut Agregasi API (AA). Untuk pengguna, yang terlihat adalah Kubernetes API yang diperluas.
CRD memungkinkan pengguna untuk membuat tipe baru sumber daya tanpa menambahkan APIserver lain. Kamu tidak perlu mengerti Agregasi API untuk menggunakan CRD.
Terlepas dari bagaimana cara mereka dipasang, sumber daya baru disebut sebagai Custom Resource untuk memisahkan mereka dari sumber daya bawaan Kubernetes (seperti Pod).
CustomResourceDefinition
Sumber daya API CustomResourceDefinition memungkinkan kamu untuk medefinisikan Custom Resource. Mendefinisikan sebuah objek CRD akan membuat sebuah Custom Resource dengan sebuah nama dan skema yang kamu spesifikasikan. Kubernetes API melayani dan menangani penyimpanan dari Custom Resource kamu.
Ini membebaskan kamu dari menulis server API kamu sendiri untuk menangani Custom Resource, tetapi sifat dasar dari implementasi menyebabkan kamu memiliki fleksibilitas yang berkurang dibanding agregasi server API).
Lihat contoh controller khusus sebagai sebuah contoh dari bagaimana cara untuk mendaftarkan sebuah Custom Resource, bekerja dengan instans dari tipe baru sumber daya kamu, dan menggunakan sebuah controller untuk menangani event.
Agregasi server API
Biasanya, tiap sumber daya di API Kubernetes membutuhkan kode yang menangani permintaan REST dan mengatur peyimpanan tetap dari objek-objek. Server Kubernetes API utama menangani sumber daya bawaan seperti Pod dan Service, dan juga menangani Custom Resource dalam sebuah cara yang umum melalui CRD.
Lapisan agregasi memungkinkan kamu untuk menyediakan implementasi khusus untuk Custom Resource dengan menulis dan men-deploy API server kamu yang berdiri sendiri. API server utama menlimpahkan permintaan kepada kamu untuk Custom Resource yang kamu tangani, membuat mereka tersedia untuk semua kliennya.
Memilih sebuah metode untuk menambahkan Custom Resource
CRD lebih mudah digunakan. Aggregated API lebih fleksibel. Pilih metode yang paling baik untuk kebutuhan kamu.
Biasanya, CRD cocok jika:
- Kamu memiliki field yang banyak
- Kamu menggunakan sumber daya dalam perusahaan kamu, atau sebagai bagian dari proyek open-source kecil (berlawanan dengan sebuah produk komersil)
Membandingkan kemudahan penggunaan
CRD lebih mudah dibuat dibandingkan dengan Aggregated API.
CRD | Aggregated API |
---|---|
Tidak membutuhkan pemrograman. Pengguna dapat memilih bahasa apapun untuk sebuah controller CRD. | Membutuhkan pemrograman dalam Go dan membangun binary dan image. Pengguna dapat memilih bahasa apapun untuk sebuah CRD controller. |
Tidak ada servis tambahan yang dijalankan; CR ditangani oleh server API. | Sebuah servis tambahan untuk menciptakan dan dapat gagal. |
Todal ada dukungan berjalan ketika CRD dibuat. Perbaikan bug apapun akan dianggap sebagai bagian dari peningkatan Kubernetes Master normal. | Mungkin dibutuhkan untuk secara berkala mengambil perbaikan bug dari sumber dan membangun ulang dan memeperbaharui APIserver teragregasi. |
Tidak butuh untuk menangani banyak versi dari API kamu. Sebagai contoh: ketika kamu mengendalikan klien untuk sumber daya ini, kamu bisa meningkatkannya selaras dengan API. | Kamu perlu menangani banyak versi dari API kamu, sebagai contoh: ketika mengembangkan sebuah ekstensi untuk dibagikan kepada dunia. |
Fitur lanjutan dan fleksibilitas
Aggregated API menawarkan fitur API lebih lanjut dan kustomisasi dari fitur lain, sebagai contoh: lapisan penyimpanan.
Fitur | Deskripsi | CRD | Aggregated API |
---|---|---|---|
Validation | Membantu pengguna-pengguna mencegah error dan memungkinkan kamu untuk mengembangkan API kamu secara independen dari klien-klien kamu. Fitur ini sangan berguna ketika ada banyak klien yang tidak semua bisa memperbaharui secara bersamaan pada waktu yang sama. | Ya. Sebagian besar validasi dapat dipesifikasikan di dalam CRD OpenAPI v3.0 validation. Validasi bentuk lainnya didukung dengan penambahan sebuah Validating Webhook. | Ya, cek validasi secara arbitrer |
Defaulting | Lihat diatas | Ya, baik melalui OpenAPI v3.0 validation default keyword (GA in 1.17), maupun melalui sebuah Mutating Webhook (meskipun tidak akan dijalankan ketika membaca dari etcd untuk objek-objek lama) |
Ya |
Multi-versioning | Memungkinkan menyajikan objek yang sama lwat dua versi API. Bisa membantu memudahkan perubahan API seperti menamai ulang field-field. Tidak terlalu penting jika kamu mengendalikan versi-versi klien kamu. | Ya | Ya |
Custom Storage | Jika kamu membutuhkan penyimpanan dengan sebuah mode performa (sebagai contoh, basis data time-series dibanding penyimpanan key-value) atau isolasi untuk keamanan (sebagau contoh, rahasia penyandian atau berkas berbeda) | Tidak | Ya |
Custom Business Logic | Melakukan cek arbitrer atau tindakan-tindakan ketika membuat, membaca, atau memperbaharui sebuah objek | Ya, menggunakan Webhooks. | Ya |
Scale Subresource | Memungkinkan sistem-sistem seperti HorizontalPodAutoscaler dan PodDisruptionBudget untuk berinteraksi dengan sumber daya baru | Ya | Ya |
Status Subresource |
|
Ya | Ya |
Other Subresources | Menambahkan operasi selain CRUD, seperti "logs" atau "exec". | Tidak | Ya |
strategic-merge-patch | Endpoint-endpoint baru yang mendukung PATCH dengan Content-Type: application/strategic-merge-patch+json . Berguna untuk memperbaharui objek-objek yang mungkin dapat dimodifikasi baik secara lokal, dan maupun lewat server. Untuk informasi lebih lanjut, lihat "Update API Objects in Place Using kubectl patch" |
Tidak | Ya |
Protocol Buffers | sumber daya baru mendukung klien-klien yang ingin menggunakan Protocol Buffer | Tidak | Ya |
OpenAPI Schema | Apakah ada sebuah skema OpenAPI (swagger) untuk tipe yang bisa secara dinamis diambil dari server? Apakah pengguna terlindungi dari kesalahan pengejaan nama-nama field dengan memastikan bahwa hanya field yang diperbolehkan yang boleh diisi? Apakah tipe-tipe diberlakukan (dengan kata lain, jangan menaruh sebuah int di dalam field string ?) |
Ya, berdasarkan pada skema OpenAPI v3.0 validation (GA pada 1.16) | Ya |
Fitur Umum
Ketika kamu membuat sebuah Custom Resource, baik melalui sebuah CRD atau sebuah AA, kamu mendapat banyak fitur untuk API kamu, dibandingkan dengan mengimplementasikannya diluar platform Kubernetes.
Fitur | Apa yang dilakukannya |
---|---|
CRUD | Endpoint-endpoint baru yang mendukung operasi dasar melalui HTTP dan kubectl |
Watch | Endpoint-endpoint baru yang mendukung operasi Kubernetes Watch melalui HTTP |
Discovery | Klien seperti kubectl dan dasbor yang secara otomatis menawarkan operasi list, display, dan pembaharuan field pada sumber daya kamu. |
json-patch | Endpoint-endpoint baru yang mendukung PATCH dengan Content-Type: application/json-patch+json |
merge-patch | Endpoint-endpoint baru yang mendukung PATCH dengan Content-Type: application/merge-patch+json |
HTTPS | Endpoint-endpoint menggunakan HTTPS |
Built-in Authentication | Akses ke ekstensi yang menggunakan apiserver inti (lapisan agregasi) untuk otentikasi |
Built-in Authorization | Akses ke ekstensi dapat menggunakan ulang otorisasi yang digunakan oleh apiserver inti (mis. RBAC) |
Finalizers | Penghapusan blok dari ekstensi sumber daya hingga pembersihan eksternal terjadi. |
Admission Webhooks | Menentukan nilai default dan memvalidasi ekstensi sumber daya saat terjadi operasi create/update/delete apapun. |
UI/CLI Display | Kubectl, dasbor dapat menampilkan ekstensi sumber daya |
Unset vs Empty | Klien-klien dapat membedakan field-field yang tidak diisi dari field-field yang memiliki nilai nol. |
Client Libraries Generation | Kubernetes menyediakan pustaka klien dasar, juga alat-alat untuk membuat pustaka klien dengan tipe spesifik. |
Labels and annotations | Metadata umum lintas objek yang cara untuk memperbaharui sumber daya inti dan Custom Resource-nya diketahui oleh alat-alat. |
Persiapan pemasangan sebuah Custom Resource
Ada beberapa poin yang harus diperhatikan sebelum menambahkan sebuah Custom Resource ke klaster kamu.
Kode pihak ketiga dan poin kegagalan baru
Saat membuat sebuah CRD tidak secara otomatis menambahkan titik-titik kegagalan baru (sebagai contoh, dengan menyebabkan kode pihak ketiga untuk berjalan di API server kamu), paket-paket (sebagai contoh, Chart) atau bundel pemasangan lain seringkali sudah termasuk CRD dan juga sebagai Deployment dari kode pihak ketiga yang mengimplementasi logika bisnis untuk sebuah Custom Resource.
Memasang sebuah APIserver teragregasi selalu melibatkan tindakan menjalankan Deployment baru.
Penyimpanan
Custom Resource mengkonsumsi ruang penyimpanan dengan cara yang sama dengan ConfigMap. Membuat terlalu banyak sumber daya mungkin akan memenuhi ruang penyimpanan server API kamu.
Server Aggregated API dapat menggunakan penyimpanan yang sama dengan server API utama, dimana peringatan yang sama berlaku.
Authentication, authorization, and auditing
CRD selalu menggunakan otentikasi, otorisasi, dan audit pencatatan yang sama sebagai sumber daya bawaan dari server API kamu.
Jika kamu menggunakan RBAC untuk otorisasi, sebagian besar role RBAC tidak akan mengizinkan akses ke sumber daya baru (kecuali role cluster-admin atau role apapun yang dibuat menggunakan aturan wildcard). Kamu akan dibutuhkan untuk secara eksplisit mengizinkan akses ke sumber daya baru. CRD dan Aggregated API seringkali dibundel dengan definisi role baru untuk tipe yang mereka tambahkan.
API server teragregasi dapat atau tidak dapat menggunakan otentikasi, otorisasi, dan pengauditan yang sama dengan server API utama.
Mengakses sebuah Custom Resource
Pustaka klien Kubernetes dapat digunakan untuk mengakses Custom Resource. Tidak semua pustaka klien mendukung Custom Resource. Pustaka klien go dan python melakukannya.
Ketika kamu menambahkan sebuah Custom Resource, kamu dapat mengaksesnya dengan menggunakan:
- kubectl
- Klien dinamis kubernetes.
- Sebuah klien REST yang kamu tulis
- Sebuah klien yang dibuat menggunakan Kubernetes client generation tools (membuat satu adalah usaha lanjutan, tetapi beberapa proyek mungkin menyajikan sebuah klien bersama dengan CRD atau AA).
Selanjutnya
-
Belajar bagaimana untuk Memperluas Kubernetes API dengan lapisan agregasi.
-
Belajar bagaimana untuk Memperluas Kubernetes API dengan CustomResourceDefinition.
3.12.3 - Ekstensi Komputasi, Penyimpanan, dan Jaringan
3.12.3.1 - Plugin Jaringan
Kubernetes v1.23 [alpha]
Plugin jaringan di Kubernetes hadir dalam beberapa varian:
- Plugin CNI : mengikuti spesifikasi appc / CNI, yang dirancang untuk interoperabilitas.
- Plugin Kubenet : mengimplementasi
cbr0
sederhana menggunakan pluginbridge
danhost-local
CNI
Instalasi
Kubelet memiliki plugin jaringan bawaan tunggal, dan jaringan bawaan umum untuk seluruh kluster. Plugin ini memeriksa plugin-plugin ketika dijalankan, mengingat apa yang ditemukannya, dan mengeksekusi plugin yang dipilih pada waktu yang tepat dalam siklus pod (ini hanya berlaku untuk Docker, karena rkt mengelola plugin CNI sendiri). Ada dua parameter perintah Kubelet yang perlu diingat saat menggunakan plugin:
cni-bin-dir
: Kubelet memeriksa direktori ini untuk plugin-plugin saat startupnetwork-plugin
: Plugin jaringan untuk digunakan daricni-bin-dir
. Ini harus cocok dengan nama yang dilaporkan oleh plugin yang diperiksa dari direktori plugin. Untuk plugin CNI, ini (nilainya) hanyalah "cni".
Persyaratan Plugin Jaringan
Selain menyediakan antarmuka NetworkPlugin
untuk mengonfigurasi dan membersihkan jaringan Pod, plugin ini mungkin juga memerlukan dukungan khusus untuk kube-proxy. Proksi iptables jelas tergantung pada iptables, dan plugin ini mungkin perlu memastikan bahwa lalu lintas kontainer tersedia untuk iptables. Misalnya, jika plugin menghubungkan kontainer ke bridge Linux, plugin harus mengatur nilai sysctl net/bridge/bridge-nf-call-iptables
menjadi 1
untuk memastikan bahwa proksi iptables berfungsi dengan benar. Jika plugin ini tidak menggunakan bridge Linux (melainkan sesuatu seperti Open vSwitch atau mekanisme lainnya), plugin ini harus memastikan lalu lintas kontainer dialihkan secara tepat untuk proksi.
Secara bawaan jika tidak ada plugin jaringan Kubelet yang ditentukan, plugin noop
digunakan, yang menetapkan net/bridge/bridge-nf-call-iptables=1
untuk memastikan konfigurasi sederhana (seperti Docker dengan sebuah bridge) bekerja dengan benar dengan proksi iptables.
CNI
Plugin CNI dipilih dengan memberikan opsi command-line --network-plugin=cni
pada Kubelet. Kubelet membaca berkas dari --cni-conf-dir
(bawaan /etc/cni/net.d
) dan menggunakan konfigurasi CNI dari berkas tersebut untuk mengatur setiap jaringan Pod. Berkas konfigurasi CNI harus sesuai dengan spesifikasi CNI, dan setiap plugin CNI yang diperlukan oleh konfigurasi harus ada di --cni-bin-dir
(nilai bawaannya adalah /opt/cni/bin
).
Jika ada beberapa berkas konfigurasi CNI dalam direktori, Kubelet menggunakan berkas yang pertama dalam urutan abjad.
Selain plugin CNI yang ditentukan oleh berkas konfigurasi, Kubernetes memerlukan plugin CNI standar lo
plugin , minimal pada versi 0.2.0.
Dukungan hostPort
Plugin jaringan CNI mendukung hostPort
. Kamu dapat menggunakan plugin portmap resmi yang ditawarkan oleh tim plugin CNI atau menggunakan plugin kamu sendiri dengan fungsionalitas portMapping.
Jika kamu ingin mengaktifkan dukungan hostPort
, kamu harus menentukan portMappings capability
di cni-conf-dir
kamu.
Contoh:
{
"name": "k8s-pod-network",
"cniVersion": "0.3.0",
"plugins": [
{
"type": "calico",
"log_level": "info",
"datastore_type": "kubernetes",
"nodename": "127.0.0.1",
"ipam": {
"type": "host-local",
"subnet": "usePodCidr"
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
},
{
"type": "portmap",
"capabilities": {"portMappings": true}
}
]
}
Dukungan pembentukan lalu-lintas
Plugin jaringan CNI juga mendukung pembentukan lalu-lintas yang masuk dan keluar dari Pod. Kamu dapat menggunakan plugin resmi bandwidth yang ditawarkan oleh tim plugin CNI atau menggunakan plugin kamu sendiri dengan fungsionalitas kontrol bandwidth.
Jika kamu ingin mengaktifkan pembentukan lalu-lintas, kamu harus menambahkan plugin bandwidth
ke berkas konfigurasi CNI kamu (nilai bawaannya adalah /etc/cni/ net.d
).
{
"name": "k8s-pod-network",
"cniVersion": "0.3.0",
"plugins": [
{
"type": "calico",
"log_level": "info",
"datastore_type": "kubernetes",
"nodename": "127.0.0.1",
"ipam": {
"type": "host-local",
"subnet": "usePodCidr"
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
},
{
"type": "bandwidth",
"capabilities": {"bandwidth": true}
}
]
}
Sekarang kamu dapat menambahkan anotasi kubernetes.io/ingress-bandwidth
dan kubernetes.io/egress-bandwidth
ke Pod kamu.
Contoh:
apiVersion: v1
kind: Pod
metadata:
annotations:
kubernetes.io/ingress-bandwidth: 1M
kubernetes.io/egress-bandwidth: 1M
...
Kubenet
Kubenet adalah plugin jaringan yang sangat mendasar dan sederhana, hanya untuk Linux. Ia, tidak dengan sendirinya, mengimplementasi fitur-fitur yang lebih canggih seperti jaringan cross-node atau kebijakan jaringan. Ia biasanya digunakan bersamaan dengan penyedia layanan cloud yang menetapkan aturan routing untuk komunikasi antar Node, atau dalam lingkungan Node tunggal.
Kubenet membuat bridge Linux bernama cbr0
dan membuat pasangan veth untuk setiap Pod dengan ujung host dari setiap pasangan yang terhubung ke cbr0
. Ujung Pod dari pasangan diberi alamat IP yang dialokasikan dari rentang yang ditetapkan untuk Node baik melalui konfigurasi atau oleh controller-manager. cbr0
memiliki MTU yang cocok dengan MTU terkecil dari antarmuka normal yang diaktifkan pada host.
Plugin ini memerlukan beberapa hal:
- Plugin CNI
bridge
,lo
danhost-local
standar diperlukan, minimal pada versi 0.2.0. Kubenet pertama-tama akan mencari mereka di/opt/cni/bin
. Tentukancni-bin-dir
untuk menyediakan lokasi pencarian tambahan. Hasil pencarian pertama akan digunakan. - Kubelet harus dijalankan dengan argumen
--network-plugin=kubenet
untuk mengaktifkan plugin - Kubelet juga harus dijalankan dengan argumen
--non-masquerade-cidr=<clusterCidr>
untuk memastikan lalu-lintas ke IP-IP di luar rentang ini akan menggunakan masquerade IP. - Node harus diberi subnet IP melalui perintah kubelet
--pod-cidr
atau perintah controller-manager--allocate-node-cidrs=true --cluster-cidr=<cidr>
.
Menyesuaikan MTU (dengan kubenet)
MTU harus selalu dikonfigurasi dengan benar untuk mendapatkan kinerja jaringan terbaik. Plugin jaringan biasanya akan mencoba membuatkan MTU yang masuk akal, tetapi terkadang logika tidak akan menghasilkan MTU yang optimal. Misalnya, jika bridge Docker atau antarmuka lain memiliki MTU kecil, kubenet saat ini akan memilih MTU tersebut. Atau jika kamu menggunakan enkapsulasi IPSEC, MTU harus dikurangi, dan perhitungan ini di luar cakupan untuk sebagian besar plugin jaringan.
Jika diperlukan, kamu dapat menentukan MTU secara eksplisit dengan opsi network-plugin-mtu
kubelet. Sebagai contoh, pada AWS eth0
MTU biasanya adalah 9001, jadi kamu dapat menentukan --network-plugin-mtu=9001
. Jika kamu menggunakan IPSEC, kamu dapat menguranginya untuk memungkinkan/mendukung overhead enkapsulasi pada IPSEC, contoh: --network-plugin-mtu=8873
.
Opsi ini disediakan untuk plugin jaringan; Saat ini hanya kubenet yang mendukung network-plugin-mtu
.
Ringkasan Penggunaan
--network-plugin=cni
menetapkan bahwa kita menggunakan plugin jaringancni
dengan binary-binary plugin CNI aktual yang terletak di--cni-bin-dir
(nilai bawaannya/opt/cni/bin
) dan konfigurasi plugin CNI yang terletak di--cni-conf-dir
(nilai bawaannya/etc/cni/net.d
).--network-plugin=kubenet
menentukan bahwa kita menggunakan plugin jaringankubenet
denganbridge
CNI dan plugin-pluginhost-local
yang terletak di/opt/cni/bin
ataucni-bin-dir
.--network-plugin-mtu=9001
menentukan MTU yang akan digunakan, saat ini hanya digunakan oleh plugin jaringankubenet
.
Selanjutnya
3.12.3.2 - Plugin Perangkat
Kubernetes v1.10 [beta]
Kubernetes menyediakan kerangka kerja plugin perangkat sehingga kamu dapat memakainya untuk memperlihatkan sumber daya perangkat keras sistem ke dalam Kubelet.
Daripada menkustomisasi kode Kubernetes itu sendiri, vendor dapat mengimplementasikan plugin perangkat yang di-deploy secara manual atau sebagai DaemonSet. Perangkat yang dituju termasuk GPU, NIC berkinerja tinggi, FPGA, adaptor InfiniBand, dan sumber daya komputasi sejenis lainnya yang perlu inisialisasi dan setelan spesifik vendor.
Pendaftaran plugin perangkat
Kubelet mengekspor servis gRPC Registration
:
service Registration {
rpc Register(RegisterRequest) returns (Empty) {}
}
Plugin perangkat bisa mendaftarkan dirinya sendiri dengan kubelet melalui servis gRPC. Dalam pendaftaran, plugin perangkat perlu mengirim:
- Nama Unix socket-nya.
- Versi API Plugin Perangkat yang dipakai.
ResourceName
yang ingin ditunjukkan.ResourceName
ini harus mengikuti skema penamaan sumber daya ekstensi sebagaivendor-domain/tipe-sumber-daya
. (Contohnya, NVIDIA GPU akan dinamainvidia.com/gpu
.)
Setelah registrasi sukses, plugin perangkat mengirim daftar perangkat yang diatur
ke kubelet, lalu kubelet kemudian bertanggung jawab untuk mengumumkan sumber daya tersebut
ke peladen API sebagai bagian pembaruan status node kubelet.
Contohnya, setelah plugin perangkat mendaftarkan hardware-vendor.example/foo
dengan kubelet
dan melaporkan kedua perangkat dalam node dalam kondisi sehat, status node diperbarui
untuk menunjukkan bahwa node punya 2 perangkat “Foo” terpasang dan tersedia.
Kemudian, pengguna dapat meminta perangkat dalam spesifikasi Kontainer seperti meminta tipe sumber daya lain, dengan batasan berikut:
- Sumber daya ekstensi hanya didukung sebagai sumber daya integer dan tidak bisa overcommitted.
- Perangkat tidak bisa dibagikan antar Kontainer.
Semisal klaster Kubernetes menjalankan plugin perangkat yang menunjukkan sumber daya hardware-vendor.example/foo
pada node tertentu. Berikut contoh Pod yang meminta sumber daya itu untuk menjalankan demo beban kerja:
---
apiVersion: v1
kind: Pod
metadata:
name: demo-pod
spec:
containers:
- name: demo-container-1
image: k8s.gcr.io/pause:2.0
resources:
limits:
hardware-vendor.example/foo: 2
#
# Pod ini perlu 2 perangkat perangkat-vendor.example/foo
# dan hanya dapat menjadwalkan ke Node yang bisa memenuhi
# kebutuhannya.
#
# Jika Node punya lebih dari 2 perangkat tersedia,
# maka kelebihan akan dapat digunakan Pod lainnya.
Implementasi plugin perangkat
Alur kerja umum dari plugin perangkat adalah sebagai berikut:
-
Inisiasi. Selama fase ini, plugin perangkat melakukan inisiasi spesifik vendor dan pengaturan untuk memastikan perangkat pada status siap.
-
Plugin memulai servis gRPC, dengan Unix socket pada lokasi
/var/lib/kubelet/device-plugins/
, yang mengimplementasi antarmuka berikut:service DevicePlugin { // ListAndWatch mengembalikan aliran dari List of Devices // Kapanpun Device menyatakan perubahan atau kehilangan Device, ListAndWatch // mengembalikan daftar baru rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {} // Allocate dipanggil saat pembuatan kontainer sehingga Device // Plugin dapat menjalankan operasi spesifik perangkat dan menyuruh Kubelet // dari operasi untuk membuat Device tersedia di kontainer rpc Allocate(AllocateRequest) returns (AllocateResponse) {} }
-
Plugin mendaftarkan dirinya sendiri dengan kubelet melalui Unix socket pada lokasi host
/var/lib/kubelet/device-plugins/kubelet.sock
. -
Seteleh sukses mendaftarkan dirinya sendiri, plugin perangkat berjalan dalam mode peladen, dan selama itu dia tetap mengawasi kesehatan perangkat dan melaporkan balik ke kubelet terhadap perubahan status perangkat. Dia juga bertanggung jawab untuk melayani request gRPC
Allocate
. SelamaAllocate
, plugin perangkat dapat membuat persiapan spesifik-perangkat; contohnya, pembersihan GPU atau inisiasi QRNG. Jika operasi berhasil, plugin perangkat mengembalikanAllocateResponse
yang memuat konfigurasi runtime kontainer untuk mengakses perangkat teralokasi. Kubelet memberikan informasi ini ke runtime kontainer.
Menangani kubelet yang restart
Plugin perangkat diharapkan dapat mendeteksi kubelet yang restart dan mendaftarkan dirinya sendiri kembali dengan
instance kubelet baru. Pada implementasi sekarang, sebuah instance kubelet baru akan menghapus semua socket Unix yang ada
di dalam /var/lib/kubelet/device-plugins
ketika dijalankan. Plugin perangkat dapat mengawasi penghapusan
socket Unix miliknya dan mendaftarkan dirinya sendiri kembali ketika hal tersebut terjadi.
Deployment plugin perangkat
Kamu dapat melakukan deploy sebuah plugin perangkat sebagai DaemonSet, sebagai sebuah paket untuk sistem operasi node-mu, atau secara manual.
Direktori canonical /var/lib/kubelet/device-plugins
membutuhkan akses berprivilese,
sehingga plugin perangkat harus berjalan dalam konteks keamanan dengan privilese.
Jika kamu melakukan deploy plugin perangkat sebagai DaemonSet, /var/lib/kubelet/device-plugins
harus dimuat sebagai Volume pada
PodSpec
plugin.
Jika kamu memilih pendekatan DaemonSet, kamu dapat bergantung pada Kubernetes untuk meletakkan Pod plugin perangkat ke Node, memulai-ulang Pod daemon setelah kegagalan, dan membantu otomasi pembaruan.
Kecocokan API
Dukungan pada plugin perangkat Kubernetes sedang dalam beta. API dapat berubah hingga stabil, dalam cara yang tidak kompatibel. Sebagai proyek, Kubernetes merekomendasikan para developer plugin perangkat:
- Mengamati perubahan pada rilis mendatang.
- Mendukung versi API plugin perangkat berbeda untuk kompatibilitas-maju/mundur.
Jika kamu menyalakan fitur DevicePlugins dan menjalankan plugin perangkat pada node yang perlu diperbarui ke rilis Kubernetes dengan versi API plugin yang lebih baru, perbarui plugin perangkatmu agar mendukung kedua versi sebelum membarui para node ini. Memilih pendekatan demikian akan menjamin fungsi berkelanjutan dari alokasi perangkat selama pembaruan.
Mengawasi Sumber Daya Plugin Perangkat
Kubernetes v1.15 [beta]
Dalam rangka mengawasi sumber daya yang disediakan plugin perangkat, agen monitoring perlu bisa
menemukan kumpulan perangkat yang terpakai dalam node dan mengambil metadata untuk mendeskripsikan
pada kontainer mana metrik harus diasosiasikan. Metrik prometheus
diekspos oleh agen pengawas perangkat harus mengikuti
Petunjuk Instrumentasi Kubernetes,
mengidentifikasi kontainer dengan label prometheus pod
, namespace
, dan container
.
Kubelet menyediakan servis gRPC untuk menyalakan pencarian perangkat yang terpakai, dan untuk menyediakan metadata untuk perangkat berikut:
// PodResourcesLister adalah layanan yang disediakan kubelet untuk menyediakan informasi tentang
// sumber daya node yang dikonsumsi Pod dan kontainer pada node
service PodResourcesLister {
rpc List(ListPodResourcesRequest) returns (ListPodResourcesResponse) {}
}
Servis gRPC dilayani lewat socket unix pada /var/lib/kubelet/pod-resources/kubelet.sock
.
Agen pengawas untuk sumber daya plugin perangkat dapat di-deploy sebagai daemon, atau sebagai DaemonSet.
Direktori canonical /var/lib/kubelet/pod-resources
perlu akses berprivilese,
sehingga agen pengawas harus berjalan dalam konteks keamanan dengan privilese. Jika agen pengawas perangkat berjalan
sebagai DaemonSet, /var/lib/kubelet/pod-resources
harus dimuat sebagai
Volume pada plugin
PodSpec.
Dukungan untuk "servis PodResources" butuh gerbang fitur
KubeletPodResources
untuk dinyalakan. Mulai dari Kubernetes 1.15 nilai bawaannya telah dinyalakan.
Integrasi Plugin Perangkat dengan Topology Manager
Kubernetes v1.17 [alpha]
Topology Manager adalah komponen Kubelet yang membolehkan sumber daya untuk dikoordinasi secara selaras dengan Topology. Untuk melakukannya, API Plugin Perangkat telah dikembangkan untuk memasukkan struct TopologyInfo
.
message TopologyInfo {
repeated NUMANode nodes = 1;
}
message NUMANode {
int64 ID = 1;
}
Plugin Perangkat yang ingin memanfaatkan Topology Manager dapat mengembalikan beberapa struct TopologyInfo sebagai bagian dari pendaftaran perangkat, bersama dengan ID perangkat dan status kesehatan perangkat. Manajer perangkat akan memakai informasi ini untuk konsultasi dengan Topology Manager dan membuat keputusan alokasi sumber daya.
TopologyInfo
mendukung kolom nodes
yang bisa nil
(sebagai bawaan) atau daftar node NUMA. Ini membuat Plugin Perangkat mengumumkan apa saja yang bisa meliputi node NUMA.
Contoh struct TopologyInfo
untuk perangkat yang dipopulate oleh Plugin Perangkat:
pluginapi.Device{ID: "25102017", Health: pluginapi.Healthy, Topology:&pluginapi.TopologyInfo{Nodes: []*pluginapi.NUMANode{&pluginapi.NUMANode{ID: 0,},}}}
Contoh plugin perangkat
Berikut beberapa contoh implementasi plugin perangkat:
- Plugin perangkat AMD GPU
- Plugin perangkat Intel untuk perangkat GPU, FPGA, dan QuickAssist Intel
- Plugin perangkat KubeVirt untuk virtualisasi hardware-assisted
- Plugin perangkat NVIDIA GPU
- Perlu nvidia-docker versi 2.0 yang memungkinkan untuk menjalakan kontainer Docker yang memuat GPU.
- Plugin perangkat NVIDIA GPU untuk Container-Optimized OS
- Plugin perangkat RDMA
- Plugin perangkat Solarflare
- Plugin perangkat SR-IOV Network
- Plugin perangkat Xilinx FPGA untuk perangkat Xilinx FPGA
Selanjutnya
- Pelajari bagaimana menjadwalkan sumber daya GPU dengan plugin perangkat
- Pelajari bagaimana mengumumkan sumber daya ekstensi pada node
- Baca tentang penggunaan akselerasi perangkat keras untuk ingress TLS dengan Kubernetes
- Pelajari tentang [Topology Manager] (/docs/tasks/adminster-cluster/topology-manager/)
3.12.4 - Pola Operator
Operator adalah ekstensi perangkat lunak untuk Kubernetes yang memanfaatkan custom resource untuk mengelola aplikasi dan komponen-komponennya. Operator mengikuti prinsip Kubernetes, khususnya dalam hal control loop.
Motivasi
Pola dari Operator bertujuan untuk menangkap tujuan utama dari Operator manusia yang mengelola layanan atau suatu kumpulan layanan. Operator manusia yang menjaga spesifik aplikasi dan layanan memiliki pengetahuan yang mendalam tentang bagaimana sistem harus berperilaku, bagaimana cara menyebarkannya, dan bagaimana bereaksi jika ada masalah.
Orang-orang yang menjalankan workload-workload di Kubernetes pada umumnya suka menggunakan otomatisasi untuk menangani tugas-tugas yang berulang. Pola Operator menangkap bagaimana kamu dapat menulis kode untuk mengotomatiskan sebuah tugas di luar batas apa yang dapat disediakan oleh Kubernetes itu sendiri.
Operator di Kubernetes
Kubernetes didesain untuk otomasi. Secara di luar nalar, kamu mendapatkan banyak otomatisasi bawaan dari komponen inti Kubernetes. Kamu dapat menggunakan Kubernetes untuk mengotomasikan penyebaran dan menjalankan workload-workload, dan kamu juga dapat mengotomasikan cara Kubernetes melakukan pekerjaan itu.
Konsep dari controller Kubernetes memungkinkan kamu memperluas perilaku klaster tanpa harus mengubah kode dari Kubernetes itu sendiri.
Operator adalah klien API dari Kubernetes yang bertindak sebagai controller untuk custome resource.
Contoh Operator
Beberapa hal yang dapat kamu gunakan untuk mengotomasi Operator meliputi:
- menyebarkan aplikasi sesuai dengan permintaan
- mengambil dan memulihkan backup status dari sebuah aplikasi
- menangani pembaruan kode aplikasi termasuk dengan perubahan terkait seperti skema basis data atau pengaturan konfigurasi tambahan
- mempublikasikan layanan ke sebuah aplikasi yang tidak mendukung API Kubernetes untuk menemukan mereka
- mensimulasikan kegagalan pada seluruh atau sebagian klaster kamu untuk menguji resiliensinya
- memilih suatu pemimpin untuk aplikasi yang terdistribusi tanpa adanya proses pemilihan anggota secara internal
Seperti apa sebuah Operator dalam kasus yang lebih terperinci? Berikut ini adalah contoh yang lebih detail:
- Sebuah custom resource bernama SampleDB, bisa kamu konfigurasi ke dalam klaster.
- Sebuah Deployment memastikan sebuah Pod berjalan dimana didalamnya berisi bagian controller dari Operator.
- Kontainer Image dari kode Operator.
- Kode controller yang menanyakan pada control-plane untuk mencari tahu apakah itu sumber daya SampleDB telah dikonfigurasi.
- Inti dari Operator adalah kode untuk memberi tahu server API bagaimana membuatnya kondisi sebenarnya sesuai dengan sumber daya yang dikonfigurasi. * Jika kamu menambahkan SampleDB baru, Operator menyiapkan PersistentVolumeClaims untuk menyediakan penyimpanan basis data yang tahan lama, sebuah StatefulSet untuk menjalankan SampleDB dan pekerjaan untuk menangani konfigurasi awal. * Jika kamu menghapusnya, Operator mengambil snapshot, lalu memastikannya StatefulSet dan Volume juga dihapus.
- Operator juga mengelola backup basis data yang reguler. Untuk setiap resource SampleDB, Operator menentukan kapan membuat Pod yang dapat terhubung ke database dan mengambil backup. Pod-Pod ini akan bergantung pada ConfigMap dan / atau sebuah Secret yang memiliki basis data koneksi dan kredensial.
- Karena Operator bertujuan untuk menyediakan otomatisasi yang kuat untuk resource yang dikelola, maka akan ada kode pendukung tambahan. Sebagai contoh , kode memeriksa untuk melihat apakah basis data menjalankan versi yang lama dan, jika demikian, kode membuat objek Job yang melakukan pembaruan untuk kamu.
Menyebarkan Operator
Cara paling umum untuk menyebarkan Operator adalah dengan menambahkan CustomResourceDefinition dan controller yang berkaitan ke dalam klaster kamu. Controller biasanya akan berjalan di luar control plane, seperti kamu akan menjalankan aplikasi apa pun yang dikontainerisasi. Misalnya, kamu bisa menjalankan controller di klaster kamu sebagai sebuah Deployment.
Menggunakan Operator {#menggunakan operator}
Setelah Operator disebarkan, kamu akan menggunakannya dengan menambahkan, memodifikasi, atau menghapus jenis sumber daya yang digunakan Operator tersebut. Melanjutkan contoh diatas, kamu akan menyiapkan Deployment untuk Operator itu sendiri, dan kemudian:
kubectl get SampleDB # find configured databases
kubectl edit SampleDB/example-database # manually change some settings
…dan itu saja! Operator akan berhati-hati dalam menerapkan perubahan serta menjaga layanan yang ada dalam kondisi yang baik.
Menulis Operator Kamu Sendiri
Jika tidak ada Operator dalam ekosistem yang mengimplementasikan perilaku kamu inginkan, kamu dapat kode kamu sendiri. Dalam Selanjutnya kamu akan menemukan beberapa tautan ke library dan perangkat yang dapat kamu gunakan untuk menulis Operator Cloud Native kamu sendiri.
Kamu juga dapat mengimplementasikan Operator (yaitu, Controller) dengan menggunakan bahasa / runtime yang dapat bertindak sebagai klien dari API Kubernetes.
Selanjutnya
- Memahami lebih lanjut tentang custome resources
- Temukan "ready-made" operators dalam OperatorHub.io untuk memenuhi use case kamu
- Menggunakan perangkat yang ada untuk menulis Operator kamu sendiri, misalnya:
- menggunakan KUDO (Kubernetes Universal Declarative Operator)
- menggunakan kubebuilder
- menggunakan Metacontroller bersama dengan
WebHooks
yang kamu implementasikan sendiri - menggunakan the Operator Framework
- Terbitkan Operator kamu agar dapat digunakan oleh orang lain
- Baca artikel asli dari CoreOS yang memperkenalkan pola Operator
- Baca sebuah artikel dari Google Cloud soal panduan terbaik membangun Operator
3.12.5 - Service Catalog
Service Catalog adalah sebuah ekstensi API yang memungkinkan aplikasi berjalan pada klaster Kubernetes untuk mempermudah penggunaan perangkat lunak yang dikelola eksternal, seperti servis penyimpanan data yang ditawarkan oleh penyedia layanan komputasi awan.
Ini menyediakan cara untuk membuat daftar, melakukan pembuatan, dan mengikat dengan servis terkelola eksternal dari makelar servis tanpa membutuhkan pengetahuan mendalam mengenai cara servis tersebut dibuat dan diatur.
Sebuah makelar servis (service broker), seperti yang didefinisikan oleh [spesifikasi API makelar servis terbuka] (https://github.com/openservicebrokerapi/servicebroker/blob/v2.13/spec.md), adalah sebuah endpoint untuk beberapa layanan terkelola yang ditawarkan dan dikelola oleh pihak ketiga, yang bisa jadi sebuah penyedia layanan cloud seperti AWS, GCP atau Azure.
Beberapa contoh dari servis terkelola adalah Microsoft Azure Cloud Queue, Amazon Simple Queue Service, dan Google Cloud Pub/Sub, selain itu, bisa juga penawaran perangkat lunak apa pun yang dapat digunakan oleh suatu aplikasi.
Dengan menggunakan Service Catalog, seorang pengelola klaster dapat melihat daftar servis terkelola yang ditawarkan oleh makelar servis, melakukan pembuatan terhadap sebuah servis terkelola, dan menghubungkan (bind) untuk membuat tersedia terhadap aplikasi pada suatu klaster Kubernetes.
Contoh kasus penggunaan
Seorang pengembang aplikasi ingin menggunakan sistem antrian pesan sebagai bagian dari aplikasinya yang berjalan dalam klaster Kubernetes. Namun, mereka tidak ingin berurusan dengan kesulitan dalam pengaturan, misalnya menjaga servis tetap berjalan dan mengatur itu oleh mereka sendiri. Beruntungnya, sudah tersedia penyedia layanan cloud yang menawarkan sistem antrian pesan sebagai servis terkelola melalui makelar servisnya.
Seorang pengelola klaster dapat membuat Service Catalog dan menggunakannya untuk berkomunikasi dengan makelar servis milik penyedia layanan cloud untuk menyediakan sebuah servis antrian pesan dan membuat servis ini tersedia kepada aplikasi dalam klaster Kubernetes. Seorang pengembang aplikasi tidak perlu memikirkan detail implementasi atau mengatur sistem antrian pesan tersebut. Aplikasi dapat langsung menggunakan servis tersebut.
Arsitektur
Service Catalog menggunakan API dari Open Service Broker untuk berkomunikasi dengan makelar servis, bertindak sebagai perantara untuk API Server Kubernetes untuk merundingkan penyediaan awal dan mengambil kredensial untuk aplikasi bisa menggunakan servis terkelola tersebut.
Ini terimplementasi sebagai ekstensi API Server dan pengontrol, menggunakan etcd sebagai media penyimpanan. Ini juga menggunakan lapisan agregasi yang tersedia pada Kubernetes versi 1.7+ untuk menampilkan API-nya.
Sumber Daya API
Service Catalog memasang API servicecatalog.k8s.io
dan menyediakan beberapa sumber daya Kubernetes berikut:
ClusterServiceBroker
: Sebuah representasi dalam klaster untuk makelar servis, membungkus detail koneksi peladen. Ini dibuat dan dikelola oleh pengelola klaster yang berharap untuk menggunakan makelar peladen untuk membuat tipe baru dari sebuah servis terkelola yang tersedia dalam klaster mereka.ClusterServiceClass
: Sebuah servis terkelola ditawarkan oleh beberapa makelar servis. Ketika sumber dayaClusterServiceBroker
ditambahkan ke dalam klaster, kontroler Service Catalog terhubung ke makelar servis untuk mendapatkan daftar servis terkelola yang tersedia. Kemudian membuat sumber dayaClusterServiceClass
sesuai dengan masing-masing servis terkelola.ClusterServicePlan
: Sebuah penawaran khusus dari servis terkelola. Sebagai contoh, sebuah servis terkelola bisa memiliki model harga, yaitu gratis atau berbayar, atau ini mungkin juga memiliki konfigurasi pilihan berbeda, misal menggunakan penyimpanan SSD atau memiliki sumber daya lebih. Mirip denganClusterServiceClass
, ketikaClusterServiceBroker
baru ditambahkan ke dalam klaster, Service Catalog akan membuat sumber dayaClusterServicePlan
sesuai dengan Service Plan yang tersedia untuk masing-masing servis terkelola.ServiceInstance
: Sebuah objek dariClusterServiceClass
. Ini dibuat oleh operator klaster untuk membuat bentuk spesifik dari servis terkelola yang tersedia untuk digunakan oleh salah satu atau lebih aplikasi dalam klaster. Ketika sumber dayaServiceInstance
baru terbuat, pengontrol Service Catalog terhubung ke makelar servis yang sesuai dan menginstruksikan untuk menyediakan sebuah objek servis.ServiceBinding
: Kredensial untuk mengakses suatuServiceInstance
. Ini dibuat oleh operator klaster yang ingin aplikasinya untuk menggunakan sebuahServiceInstance
. Saat dibuat, kontroler Service Catalog membuat sebuahSecret
Kubernetes yang berisikan detail koneksi dan kredensial untuk objek servis, yang bisa dimuat ke dalam Pod.
Autentikasi
Service Catalog mendukung beberapa metode autentikasi, yaitu:
- Basic (nama pengguna/kata sandi)
- OAuth 2.0 Bearer Token
Penggunaan
Seorang operator klaster dapat menggunakan API sumber daya Service Catalog untuk membuat servis terkelola dan membuatnya tersedia dalam klaster Kubernetes. Langkah yang dilalui adalah sebagai berikut:
- Membuat daftar servis terkelola dan model pembayaran yang tersedia dari makelar servis.
- Membuat sebuah objek dari suatu servis terkelola.
- Menghubungkan ke servis terkelola, yang mengembalikan kredensial koneksi.
- Memetakan kredensial koneksi ke dalam aplikasi.
Membuat daftar servis terkelola dan model pembayaran
Pertama, seorang operator klaster harus membuat sumber daya ClusterServiceBroker
dalam kelompok
servicecatalog.k8s.io
. Sumber daya ini memiliki URL dan detail koneksi untuk mengakses makelar servis.
Ini ada contoh dari suatu sumber daya ClusterServiceBroker
:
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ClusterServiceBroker
metadata:
name: cloud-broker
spec:
# Merujuk pada titik akhir dari makelar servis. (Ini adalah contoh URL yang tidak nyata)
url: https://servicebroker.somecloudprovider.com/v1alpha1/projects/service-catalog/brokers/default
#####
# Nilai tambahan dapat ditambahkan disini, yang mungkin bisa digunakan untuk berkomunikasi
# dengan makelar servis, misalnya saja informasi bearer token atau sebuah caBundle untuk TLS.
#####
Berikut adalah sebuah diagram urutan yang mengilustrasikan langkah-langkah dalam mendaftarkan servis terkelola dan model pembayaran yang tersedia dari makelar servis:
-
Setelah sumber daya
ClusterServiceBroker
ditambahkan ke dalam Service Catalog, ini membuat panggilan makelar servis luar untuk membuat daftar servis yang tersedia. -
Makelar servis akan mengembalikan daftar servis terkelola yang tersedia dan daftar model pembayaran, yang akan disimpan sementara sebagai
ClusterServiceClass
danClusterServicePlan
. -
Seorang operator klaster bisa mendapatkan daftar servis terkelola dengan menggunakan perintah berikut ini:
kubectl get clusterserviceclasses -o=custom-columns=SERVICE\ NAME:.metadata.name,EXTERNAL\ NAME:.spec.externalName
Itu seharusnya memberikan daftar nama servis dengan format yang mirip dengan berikut:
SERVICE NAME EXTERNAL NAME 4f6e6cf6-ffdd-425f-a2c7-3c9258ad2468 cloud-provider-service ... ...
Mereka juga dapat melihat model pembayaran yang tersedia menggunakan perintah berikut:
kubectl get clusterserviceplans -o=custom-columns=PLAN\ NAME:.metadata.name,EXTERNAL\ NAME:.spec.externalName
Itu seharusnya memberikan daftar nama model pembayaran dengan format mirip dengan berikut:
PLAN NAME EXTERNAL NAME 86064792-7ea2-467b-af93-ac9694d96d52 service-plan-name ... ...
Pembuatan sebuah objek
Seorang operator klaster dapat memulai pembuatan sebuah objek dengan membuat sumber daya ServiceInstance
.
Ini adalah contoh dari sumber daya ServiceInstance
:
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceInstance
metadata:
name: cloud-queue-instance
namespace: cloud-apps
spec:
# Referensi untuk salah satu servis yang pernah dikembalikan
clusterServiceClassExternalName: cloud-provider-service
clusterServicePlanExternalName: service-plan-name
#####
# Parameter tambahan dapat ditambahkan disini,
# yang mungkin akan digunakan oleh makelar servis.
#####
Berikut adalah diagram urutan yang mengilustrasikan langkah-langkah dalam pembuatan sebuah objek dari servis terkelola:
- Ketika sumber daya
ServiceInstance
sudah terbuat, Service Catalog memulai pemanggilan ke makelar servis luar untuk membuat sebuah objek dari suatu servis. - Makelar servis membuat sebuah objek baru dari suatu servis terkelola dan mengembalikan sebuah respons HTTP.
- Seorang operator klaster dapat mengecek status dari objek untuk melihat apakah sudah siap atau belum.
Menghubungkan ke servis terkelola
Setelah sebuah objek terbuat, klaster operator harus menghubungkan ke servis terkelola untuk mendapatkan
kredensial koneksi dan detail pengguna servis untuk aplikasi bisa mengguakan servis tersebut. Ini dilakukan
dengan membuat sebuah sumber daya ServiceBinding
.
Berikut adalah contoh dari sumber daya ServiceBinding
:
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceBinding
metadata:
name: cloud-queue-binding
namespace: cloud-apps
spec:
instanceRef:
name: cloud-queue-instance
#####
# Informasi tambahan dapat ditambahkan disini, seperti misalnya secretName atau
# parameter pengguna servis, yang mungkin akan digunakan oleh makelar servis.
#####
Berikut ada diagram urutan yang mengilustrasikan langkah-langkah dalam menghubungkan objek servis terkelola.
- Setelah
ServiceBinding
terbuat, Service Catalog memanggil makelar servis luar untuk meminta informasi yang dibutuhkan untuk terhubung dengan objek servis. - Makelar servis memberikan izin atau peran kepada aplikasi sesuai dengan pengguna servis.
- Makelar servis mengembalikan informasi untuk bisa terhubung dan mengakses servis terkelola. Ini tergantung pada penyedia layanan dan servis, sehingga informasi yang dikembalikan mungkin berbeda antara suatu penyedia layanan dan servis terkelolanya.
Memetakan kredensial koneksi
Setelah menghubungkan, langkah terakhir melibatkan pemetaan kredensial koneksi dan informasi spesifik mengenai servis kedalam aplikasi. Informasi ini disimpan dalam Secrets yang mana aplikasi dalam klaster dapat mengakses dan menggunakan untuk bisa terkoneksi secara langsung dengan servis terkelola.
Berkas konfigurasi Pod
Salah satu metode untuk melakukan pemetaan ini adalah dengan menggunakan deklarasi konfigurasi Pod.
Berikut adalah contoh yang mendekripsikan bagaimana pemetaan kredensial pengguna servis ke dalam aplikasi.
Sebuah kunci yang disebut sa-key
disimpan dalam media bernama provider-cloud-key
, dan aplikasi memasang
media ini pada /var/secrets/provider/key.json
. Environment variable PROVIDER_APPLICATION_CREDENTIALS
dipetakan dari nilai pada berkas yang dipasang.
...
spec:
volumes:
- name: provider-cloud-key
secret:
secretName: sa-key
containers:
...
volumeMounts:
- name: provider-cloud-key
mountPath: /var/secrets/provider
env:
- name: PROVIDER_APPLICATION_CREDENTIALS
value: "/var/secrets/provider/key.json"
Berikut adalah contoh yang mendeskripsikan cara memetakan nilai rahasia ke dalam environment variable aplikasi.
Dalam contoh ini, nama topik dari sistem antrian pesan dipetakan dari secret bernama provider-queue-credentials
dengan nama topic
ke dalam environment variable TOPIC
.
...
env:
- name: "TOPIC"
valueFrom:
secretKeyRef:
name: provider-queue-credentials
key: topic
Selanjutnya
- Jika kamu terbiasa dengan Helm Charts, pasang Service Catalog menggunakan Helm ke dalam klaster Kubernetes. Alternatif lain, kamu dapat memasang Service Catalog dengan SC tool.
- Lihat contoh makelar servis.
- Pelajari mengenai kubernetes-incubator/service-catalog proyek.
- Lihat svc-cat.io.
3.12.6 - Poseidon-Firmament - Sebuah Penjadwal Alternatif
Rilis saat ini dari Penjadwal Poseidon-Firmament adalah rilis alpha
.
Penjadwal Poseidon-Firmament adalah penjadwal alternatif yang dapat digunakan bersama penjadwal Kubernetes bawaan.
Pengenalan
Poseidon adalah sebuah layanan yang berperan sebagai pemersatu antara Penjadwal Firmament dengan Kubernetes. Penjadwal Poseidon-Firmament menambah kapabilitas penjadwal Kubernetes saat ini. Penjadwal ini menggabungkan kemampuan penjadwalan berbasis grafik jaringan grafis (flow network graph) baru bersama penjadwal Kubernetes bawaan. Penjadwal Firmament memodelkan beban-beban kerja dan klaster-klaster sebagai jaringan aliran dan menjalankan optimisasi aliran biaya-minimum kepada jaringan ini untuk membuat keputusan penjadwalan.
Penjadwal ini memodelkan masalah penjadwalan sebagai optimasi berbasis batasan atas grafik jaringan aliran. Hal ini dicapai dengan mengurangi penjadwalan ke masalah optimisasi biaya-minimum aliran-maksimum. Penjadwal Poseidon-Firmament secara dinamis memperbaiki penempatan beban kerja.
Penjadwal Poseidon-Firmament berjalan bersamaan dengan penjadwal Kubernetes bawaan sebagai penjadwal alternatif, sehingga beberapa penjadwal dapat berjalan secara bersamaan.
Keuntungan Utama
Penjadwalan grafik jaringan (network graph) berbasis penjadwalan Poseidon-Firmament memberikan beberapa keuntungan utama sebagai berikut:
- Beban kerja (Pod) dijadwalkan secara kolektif untuk memungkinkan penjadwalan dalam skala besar.
- Berdasarkan hasil tes kinerja yang ekstensif, skala Poseidon-Firmament jauh lebih baik daripada penjadwal bawaan Kubernetes dilihat dari jumlah node meningkat dalam sebuah klaster. Hal ini disebabkan oleh fakta bahwa Poseidon-Firmament mampu mengamortisasi lebih banyak pekerjaan di seluruh beban kerja.
- Penjadwal Poseidon-Firmament mengungguli penjadwal bawaan Kubernetes dengan margin lebar ketika menyangkut jumlah kinerja throughput untuk skenario di mana kebutuhan sumber daya komputasi agak seragam di seluruh pekerjaan (Replicaset / Deployment / Job). Angka kinerja throughput end-to-end penjadwal Poseidon-Firmament , termasuk waktu bind, secara konsisten menjadi lebih baik seiring jumlah Node dalam sebuah klaster meningkat. Misalnya, untuk klaster 2.700 Node (ditampilkan dalam grafik di sini), penjadwal Poseidon-Firmament berhasil mencapai 7X atau lebih throughput end-to-end yang lebih besar dibandingkan dengan penjadwal bawaan Kubernetes, yang mencakup waktu bind.
- Tersedianya pembatasan aturan yang kompleks.
- Penjadwalan dalam Poseidon-Firmament bersifat dinamis; ini membuat sumber daya klaster dalam keadaan optimal secara global selama setiap berjalannya penjadwalan.
- Pemanfaatan sumber daya yang sangat efisien.
Penjadwal Poseidon-Firmament - Bagaimana cara kerjanya
Sebagai bagian dari pendukung penjadwal-penjadwal Kubernetes, setiap Pod baru biasanya dijadwalkan oleh penjadwal bawaan. Kubernetes dapat diinstruksikan untuk menggunakan penjadwal lain dengan menentukan nama penjadwal custom lain ("poseidon" dalam kasus ini) di field schedulerName dari PodSpec pada saat pembuatan pod. Dalam kasus ini, penjadwal bawaan akan mengabaikan Pod itu dan memungkinkan penjadwal Poseidon untuk menjadwalkan Pod pada Node yang relevan.
apiVersion: v1
kind: Pod
...
spec:
schedulerName: poseidon
Kemungkinan Skenario Kasus Penggunaan - Kapan menggunakannya
Seperti yang disebutkan sebelumnya, penjadwal Poseidon-Firmament memungkinkan lingkungan penjadwalan dengan throughput yang sangat tinggi bahkan pada ukuran klaster dengan beban kerja besar, dikarenakan pendekatan penjadwalannya yang sekaligus dalam jumlah besar, dibandingkan dengan pendekatan bawaan pod-at-a-time Kubernetes. Dalam pengujian ekstensif kami, kami telah mengamati manfaat throughput substansial selama kebutuhan sumber daya (CPU / Memori) untuk Pod yang masuk seragam di seluruh tugas (Replicaset / Deployment / Job), terutama karena amortisasi pekerjaan yang efisien di seluruh tugas.
Meskipun penjadwal Poseidon-Firmament mampu menjadwalkan berbagai jenis beban kerja, seperti layanan-layanan, batch, dll., berikut ini adalah beberapa kasus penggunaan yang paling unggul:
- Untuk pekerjaan "Big Data / AI" yang terdiri dari sejumlah besar tugas, manfaat dari throughput luar biasa.
- Pekerjaan layanan atau batch job di mana kebutuhan sumber dayanya seragam di seluruh pekerjaan (Replicaset / Deployment / Job).
Tahap Proyek Saat Ini
- Rilis Alpha - Repo Inkubasi. di https://github.com/kubernetes-sigs/poseidon.
- Saat ini, penjadwal Poseidon-Firmament tidak memberikan dukungan untuk ketersediaan tinggi, implementasi kami mengasumsikan bahwa penjadwal tidak mungkin gagal. Dokumen desain menjelaskan cara-cara yang memungkinkan untuk mengaktifkan ketersediaan tinggi, tetapi kami membiarkannya untuk pekerjaan mendatang.
- Kami tidak mengetahui adanya production deployment dari penjadwal Poseidon-Firmament saat ini.
- Poseidon-Firmament didukung dari rilis Kubernetes 1.6 dan bekerja dengan semua rilis berikutnya.
- Proses rilis untuk repo Poseidon dan Firmament berjalan secara serentak. Rilis Poseidon saat ini dapat ditemukan di sini dan rilis Firmament yang sesuai dapat ditemukan di sini.
Matriks Perbandingan Fitur
Fitur | Penjadwal Bawaan Kubernetes | Penjadwal Poseidon-Firmament | Catatan |
---|---|---|---|
Node Affinity/Anti-Affinity | Y | Y | |
Pod Affinity / Anti-Affinity - termasuk dukungan untuk simetri anti-affinity Pod | Y | Y | Saat ini penjadwal bawaan mengungguli penjadwal Poseidon-Firmament Pod dalam segi fungsionalitas affinity/anti-affinity. Kami sedang berupaya menyelesaikan ini. |
Taints & Toleration | Y | Y | |
Kemampuan Penjadwalan Dasar sesuai dengan sumber daya komputasi yang tersedia (CPU & Memori) pada sebuah Node | Y | Y** | Tidak semua Predikat & Prioritas sudah didukung saat ini. |
Throughput ekstrim pada skala besar | Y** | Y | Pendekatan penjadwalan massal mengukur atau meningkatkan penempatan beban kerja. Manfaat throughput substansial menggunakan penjadwal Firmament selama persyaratan sumber daya (CPU / Memori) untuk Pod yang masuk seragam di seluruh Replicaset / Deployment / Job. Hal ini terutama disebabkan oleh amortisasi pekerjaan yang efisien di seluruh Replicaset / Deployment / Job. 1) Untuk pekerjaan "Big Data / AI" yang terdiri dari jumlah tugas yang besar, manfaat throughput yang luar biasa. 2) Manfaat throughput substansial juga untuk skenario layanan atau sekumpulan pekerjaan di mana persyaratan sumber daya beban kerja seragam di seluruh Replicaset / Deployment / Job. |
Penjadwalan Optimal | Penjadwalan Pod-by-Pod, memproses satu Pod pada satu waktu (dapat mengakibatkan penjadwalan sub-optimal) | Penjadwalan Massal (Penjadwalan optimal) | Penjadwal bawaan Pod-by-Pod Kubernetes dapat menetapkan tugas ke mesin sub-optimal. Sebaliknya, Firmament mempertimbangkan semua tugas yang tidak terjadwal pada saat yang bersamaan bersama dengan batasan lunak dan kerasnya. |
Penghindaran Gangguan Kolokasi | N | N** | Direncanakan di Poseidon-Firmament. |
Pre-emption Prioritas | Y | N** | Tersedia secara parsial pada Poseidon-Firmament, dibandingkan dengan dukungan ekstensif di penjadwal bawaan Kubernetes. |
Penjadwalan Ulang yang Inheren | N | Y** | Penjadwal Poseidon-Firmament mendukung penjadwalan ulang beban kerja. Dalam setiap penjadwalan, penjadwal Poseidon-Firmament mempertimbangkan semua Pod, termasuk Pod yang sedang berjalan, dan sebagai hasilnya dapat melakukan migrasi atau mengeluarkan Pod - sebuah lingkungan penjadwalan yang optimal secara global. |
Penjadwalan Berkelompok | N | Y | |
Dukungan untuk Penjadwalan Volume Persisten Pra-terikat | Y | Y | |
Dukungan untuk Volume Lokal & Penjadwalan Binding Volume Persisten Dinamis | Y | N** | Direncanakan. |
Ketersediaan Tinggi | Y | N** | Direncanakan. |
Penjadwalan berbasis metrik real-time | N | Y** | Awalnya didukung menggunakan Heapster (sekarang tidak digunakan lagi) untuk menempatkan Pod menggunakan statistik penggunaan klaster aktual ketimbang reservasi. Rencananya akan dialihkan ke "server metrik". |
Dukungan untuk Max-Pod per Node | Y | Y | Penjadwal Poseidon-Firmament secara mulus berdampingan dengan penjadwal bawaan Kubernetes. |
Dukungan untuk Penyimpanan Ephemeral, selain CPU / Memori | Y | Y |
Instalasi
Untuk instalasi Poseidon dalam-klaster, silakan mulai dari Petunjuk Instalasi.
Pengembangan
Untuk developer, silakan merujuk ke Instruksi Setup Developer.
Hasil Pengujian Kinerja Throughput Terbaru
Penjadwal pod-by-pod, seperti penjadwal bawaan Kubernetes, biasanya memproses satu Pod pada satu waktu. Penjadwal ini memiliki kelemahan penting berikut:
- Penjadwal berkomitmen untuk penempatan Pod lebih awal dan membatasi pilihan untuk Pod lain yang menunggu untuk ditempatkan.
- Ada peluang terbatas untuk amortisasi pekerjaan lintas Pod karena mereka dipertimbangkan untuk ditempatkan secara individual.
Kelemahan dari penjadwal pod-by-pod ini diatasi dengan penjadwalan secara terkumpul atau dalam jumlah banyak secara bersamaan di penjadwal Poseidon-Firmament. Memproses beberapa Pod dalam satu kumpulan memungkinkan penjadwal untuk bersama-sama mempertimbangkan penempatan mereka, dan dengan demikian untuk menemukan untung-rugi terbaik untuk seluruh kumpulan ketimbang satu Pod saja. Pada saat yang sama, amortisasi berfungsi lintas Pod yang menghasilkan throughput yang jauh lebih tinggi.
4 - 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.
4.1 - Menginstal Peralatan
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.
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.
4.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
-
Unduh versi terbarunya dengan perintah:
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
Untuk mengunduh versi spesifik, ganti bagian
curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt
dengan versi yang diinginkan.Misalnya, untuk mengunduh versi v1.23.0 di Linux, ketik:
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.23.0/bin/linux/amd64/kubectl
-
Jadikan program
kubectl
dapat dieksekusi.chmod +x ./kubectl
-
Pindahkan ke PATH kamu.
sudo mv ./kubectl /usr/local/bin/kubectl
-
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 gnupg2
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubectl
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubectl
Menginstal dengan manajer paket lain
Menginstal kubectl pada macOS
Menginstal program kubectl dengan curl pada macOS
-
Unduh versi terbarunya dengan perintah:
curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"
Untuk mengunduh versi spesifik, ganti bagian
curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt
dengan versi yang diinginkan.Misalnya, untuk mengunduh versi v1.23.0 pada macOS, ketik:
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.23.0/bin/darwin/amd64/kubectl
-
Buat agar program
kubectl
dapat dijalankan.chmod +x ./kubectl
-
Pindahkan ke PATH kamu.
sudo mv ./kubectl /usr/local/bin/kubectl
-
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.
-
Jalankan perintah:
brew install kubectl
atau
brew install kubernetes-cli
-
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.
-
Jalankan perintah:
sudo port selfupdate sudo port install kubectl
-
Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:
kubectl version --client
Menginstal kubectl pada Windows
Menginstal program kubectl dengan curl pada Windows
-
Unduh versi terbarunya v1.23.0 dari tautan ini.
Atau jika sudah ada
curl
pada mesin kamu, jalankan perintah ini:curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.23.0/bin/windows/amd64/kubectl.exe
Untuk mendapatkan versi stabil terakhir (misalnya untuk scripting), lihat di https://storage.googleapis.com/kubernetes-release/release/stable.txt.
-
Tambahkan program yang sudah diunduh tersebut ke PATH kamu.
-
Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:
kubectl version --client
kubectl
-nya sendiri ke PATH. Jika kamu sudah menginstal Docker Desktop, kamu harus menambahkan entrinya ke PATH sebelum yang ditambahkan oleh penginstal (installer) Docker Desktop atau kamu dapat menghapus kubectl
bawaan dari Docker Desktop.
Menginstal dengan Powershell dari PSGallery
Jika kamu menggunakan Windows dan manajer paket Powershell Gallery, kamu dapat menginstal dan melakukan pembaruan kubectl
dengan Powershell.
-
Jalankan perintah berikut (jangan lupa untuk memasukkan
DownloadLocation
):Install-Script -Name install-kubectl -Scope CurrentUser -Force install-kubectl.ps1 [-DownloadLocation <path>]
Catatan: Jika kamu tidak menambahkanDownloadLocation
,kubectl
akan diinstal di dalam direktori temp pengguna.Penginstal akan membuat
$HOME/.kube
dan membuat berkas konfigurasi -
Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:
kubectl version --client
Catatan: Proses pembaruan dapat dilakukan dengan menjalankan ulang dua perintah yang terdapat pada langkah 1.
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
-
Pastikan instalasinya sudah berhasil dengan melakukan pengecekan versi:
kubectl version --client
-
Pindah ke direktori utama:
cd %USERPROFILE%
-
Buat direktori
.kube
:mkdir .kube
-
Pindah ke direktori
.kube
yang baru saja dibuat:cd .kube
-
Lakukan konfigurasi
kubectl
untuk menggunakan klaster Kubernetes remote:New-Item config -type file
Catatan: Ubah berkas konfigurasi dengan penyunting (editor) teks pilihanmu, misalnya Notepad.
Mengunduh sebagai bagian dari Google Cloud SDK
Kamu dapat menginstal kubectl
sebagai bagian dari Google Cloud SDK.
-
Instal Google Cloud SDK.
-
Jalankan perintah instalasi
kubectl
:gcloud components install kubectl
-
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
```
/etc/bash_completion.d
.
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.
kubectl
tidak kompatibel dengan bash-completion v1 dan Bash 3.2. Dibutuhkan bash-completion v2 dan Bash 4.1+ agar skrip penyelesaian kubectl
dapat bekerja dengan baik. Maka dari itu, kamu harus menginstal dan menggunakan Bash 4.1+ (panduan) untuk dapat menggunakan fitur penyelesaian otomatis dari kubectl
. Ikuti panduan di bawah setelah kamu menginstal Bash 4.1+ (yaitu, Bash versi 4.1 atau lebih baru).
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
kubectl
tidak kompatibel dengan Bash 3.2 dan bash-completion v1).
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 untukkubectl
sudah berada di/usr/local/etc/bash_completion.d/kubectl
. Kamu tidak perlu melakukan apa-apa lagi.
BASH_COMPLETION_COMPAT_DIR
, itulah alasannya dua cara terakhir dapat bekerja.
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
- Menginstal Minikube.
- Lihat panduan persiapan untuk mencari tahu tentang pembuatan klaster.
- Pelajari cara untuk menjalankan dan mengekspos aplikasimu.
- Jika kamu membutuhkan akses ke klaster yang tidak kamu buat, lihat dokumen Berbagi Akses Klaster.
- Baca dokumen referensi kubectl
4.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: "*/1 * * * *"
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.
Menulis Speifikasi Sebuah Cron
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
.
.spec
, akan diterapkan pada proses berikut.
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 adalah0,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
.
?
) dalam penjadwalan memiliki makna yang sama dengan tanda bintang *
, yaitu, singkatan dari nilai apa pun yang tersedia untuk field tertentu.
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 concurrentForbid
: 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 berjalanReplace
: 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.
.spec.suspend
diubah dari true
ke false
pada CronJob yang memiliki konfigurasi tanpa batas waktu, Job yang terlewat akan dijadwalkan segera.
Batas Riwayat Pekerjaan
Field .spec.successfulJobHistoryLimit
dan .spec.failedJobHistoryLimit
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.
4.3 - Mengatur Pod dan Kontainer
4.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, tekankubectl 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
4.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, tekankubectl 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
4.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, tekankubectl 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: {}
-
Membuat Pod:
kubectl apply -f https://k8s.io/examples/pods/storage/redis.yaml
-
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
-
Pada terminal lain, buka shell untuk masuk ke Container yang sedang berjalan:
kubectl exec -it redis -- /bin/bash
-
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
-
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
-
Di dalam shell, matikan proses Redis:
root@redis:/data/redis# kill <pid>
dengan
<pid>
adalah ID proses Redis (PID). -
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
.
-
Gunakan shell untuk masuk ke dalam Container yang telah dimuat ulang:
kubectl exec -it redis -- /bin/bash
-
Di dalam shell, pergi ke
/data/redis
, dan verifikasi apakahtest-file
masih ada.root@redis:/data/redis# cd /data/redis/ root@redis:/data/redis# ls test-file
-
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.
4.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:
-
Kamu, sebagai seorang administrator klaster, membuat sebuah PersistentVolume yang didukung oleh penyimpanan fisik. Kamu tidak mengaitkan volume dengan Pod apapun.
-
Kamu, sekarang mengambil peran sebagai seorang developer / pengguna klaster, membuat sebuah PersistentVolumeClaim yang secara otomatis terikat dengan PersistentVolume yang sesuai.
-
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"
sudo
, kamu dapat
membuat ini bekerja jika mengganti sudo
dengan nama dari alat lainnya.
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
- Belajar lebih lanjut tentang PersistentVolume.
- Baca dokumen perancangan Penyimpanan Persistent.
Referensi
4.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) memilikiCAP_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, tekankubectl 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
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.
secret
,
configMap
,
dan emptydir
.
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.
CAP_XXX
. Tetapi ketika kamu memasukkan daftar kemampuan dalam manifes Container kamu, kamu harus menghilangkan bagian CAP_
dari konstantanya. Misalnya, untuk menambahkan CAP_SYS_TIME
, masukkan SYS_TIME
ke dalam daftar kapabilitas Container kamu.
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 dalamfsGroup
. 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 padaseLinuxOptions
. Biasanya kamu hanya perlu mengatur bagianlevel
. 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
4.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 klustermu 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, tekankubectl 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: ...
token
tidak dirinci di sini.
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=DUMMY_SERVER \ --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=nginx --restart=Never
kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'
Keluarannya adalah:
myregistrykey
ServiceAccountTokenVolumeProjection
Kubernetes v1.12 [beta]
ServiceAccountTokenVolumeProjection masih dalam tahap beta untuk versi 1.12 dan diaktifkan dengan memberikan flag berikut ini ke API server:
--service-account-issuer
--service-account-signing-key-file
--service-account-api-audiences
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
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.
URL issuer harus sesuai dengan OIDC Discovery Spec. Pada implementasinya, hal ini berarti URL harus menggunakan skema https
dan harus menyediakan konfigurasi penyedia OpenID pada {service-account-issuer}/.well-known/openid-configuration
.
Jika URL tidak sesuai dengan aturan, endpoint ServiceAccountIssuerDiscovery
tidak akan didaftarkan meskipun fitur telah diaktifkan.
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.
/.well-known/openid-configuration
dan/openid/v1/jwks
dirancang untuk kompatibel dengan OIDC, tetapi tidak sepenuhnya sesuai dengan ketentuan OIDC. Dokumen tersebut hanya berisi parameter yang dibutuhkan untuk melakukan validasi terhadap token ServiceAccount Kubernetes.
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:
4.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, tekankubectl 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"
}
}
}
auth
tetapi entri credsStore
dengan nama tempat penyimpanan sebagai nilainya.
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
menjadikubernetes.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
.
kubectl
sedang berjalan.
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":"[email protected]","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
- Pelajari lebih lanjut tentang Secret.
- Pelajari lebih lanjut tentang menggunakan register pribadi.
- Pelajari lebih lanjut tentang menambahkan Secret untuk menarik image ke dalam sebuah akun service.
- Lihatlah kubectl create secret docker-registry.
- Lihatlah Secret.
- Lihatlah bidang
imagePullSecrets
dari PodSpec.
4.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, tekankubectl 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
k8s.gcr.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: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /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 -rf /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 "k8s.gcr.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.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 "k8s.gcr.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.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 k8s.gcr.io/liveness
.
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
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: k8s.gcr.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
hostPort: 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
hostPort: 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 nilaifailureThreshold
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
- Pelajari lebih lanjut tentang Probe Container.
Kamu juga dapat membaca rujukan API untuk:
4.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, tekankubectl version
.
Menambahkan sebuah Label pada sebuah Node
-
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
-
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. -
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 labeldisktype=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
-
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
-
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
-
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
-
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.
4.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, tekankubectl 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"
--from-env-file
beberapa kali untuk membuat sebuah ConfigMap dari beberapa sumber data, hanya env-file terakhir yang akan digunakan.
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
-
Menentukan sebuah variabel environment sebagai sepasang kunci-nilai pada ConfigMap:
kubectl create configmap special-config --from-literal=special.how=very
-
Memberikan nilai
special.how
yang sudah terdapat pada ConfigMap pada variabel environmentSPECIAL_LEVEL_KEY
di spesifikasi Pod.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.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: k8s.gcr.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: k8s.gcr.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: k8s.gcr.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:
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: k8s.gcr.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
/etc/config/
, berkas-berkas tersebut akan dihapus.
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: k8s.gcr.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
/etc/config/
akan dihapus.
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.
/etc
beserta isinya pada Linux. Sebagai contoh, jika kamu membuat sebuah Volume Kubernetes dari ConfigMap, tiap butir data pada ConfigMap direpresentasikan sebagai sebuah berkas pada volume.
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
- Ikuti contoh penerapan pada dunia nyata Mengatur Redis menggunakan ConfigMap.
4.3.11 - Pembagian Namespace Proses antar Container pada sebuah Pod
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, tekankubectl version
.
Mengatur sebuah Pod
Pembagian namespace proses (Process Namespace Sharing) diaktifkan menggunakan field shareProcessNamespace
v1.PodSpec
. Sebagai contoh:
-
Buatlah sebuah Pod
nginx
di dalam klaster kamu:kubectl apply -f https://k8s.io/examples/pods/share-process-namespace.yaml
-
Tempelkan kontainer
shell
dan jalankan perintahps
:kubectl attach -it nginx -c shell
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:
-
Proses kontainer tidak lagi memiliki PID 1. Beberapa image kontainer akan menolak untuk dijalankan (contohnya, kontainer yang menggunakan
systemd
) atau menjalankan perintah sepertikill -HUP 1
untuk memberikan sinyal pada proses kontainer. Di dalam Pod dengan sebuah namespace process terbagi, sinyalkill -HUP 1
akan diberikan pada sandbox Pod. (/pause
pada contoh di atas.) -
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. -
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.
4.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, tekankubectl version
.
Laman ini mengasumsikan kamu menggunakan Docker 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:
-
Pilih Node yang kamu pilih untuk menjalankan Pod statis. Dalam contoh ini adalah
my-node1
.ssh my-node1
-
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
-
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. -
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:
-
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
-
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>"
-
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
docker 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-my-node1 1/1 Running 0 2m
Label dari Pod statis akan dibuat juga pada Pod mirror. Kamu dapat menggunakan label tersebut seperti biasa menggunakan selector-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-my-node1
pod "static-web-my-node1" deleted
Kamu akan melihat bahwa Pod tersebut tetap berjalan:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 12s
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
docker stop f6d05272b57e # ganti dengan ID pada Container-mu
sleep 20
docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
5b920cbaf8b1 nginx:latest "nginx -g 'daemon of 2 seconds ago ...
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/kubelet.d/static-web.yaml /tmp
sleep 20
docker ps
# Kamu mendapatkan bahwa tidak ada Container nginx yang berjalan
mv /tmp/static-web.yaml /etc/kubelet.d/
sleep 20
docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
e7a62e3427f1 nginx:latest "nginx -g 'daemon of 27 seconds ago
4.4 - Mengelola Sebuah Klaster
4.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.
-
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
-
Untuk memverifikasi penggelaran, gunakanlah perintah berikut ini.
kubectl get pods --namespace=kube-system
Pod Calico dimulai dengan kata
calico
. Periksa untuk memastikan bahwa statusnyaRunning
.
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
Selanjutnya
Setelah klaster kamu berjalan, kamu dapat mengikuti Mendeklarasikan Kebijakan Jaringan untuk mencoba NetworkPolicy Kubernetes.
4.4.2 - Mengelola Memori, CPU, dan Sumber Daya API
4.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, tekankubectl 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
-
Mengatur Permintaan dan Limit Memori Bawaan untuk Sebuah Namespace
-
Mengatur Permintaan dan Limit CPU Bawaan untuk Sebuah Namespace
-
Mengatur Batas Minimum dan Maksimum CPU untuk Sebuah Namespace
Untuk pengembang aplikasi
4.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: k8s.gcr.io/e2e-test-images/jessie-dnsutils:1.3
command:
- sleep
- "3600"
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
...
k8s-app
adalah kube-dns
baik untuk CoreDNS maupun kube-dns.
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
...
kube-dns
baik untuk CoreDNS maupun kube-dns.
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.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.
kube-dns
pada field metadata.name
.
Hal ini agar ada interoperabilitas yang lebih besar dengan beban kerja yang bergantung pada nama Service kube-dns
lama untuk me-resolve alamat internal ke dalam klaster. Dengan menggunakan sebuah Service yang bernama kube-dns
mengabstraksi detail implementasi yang dijalankan oleh penyedia DNS di belakang nama umum tersebut.
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 diperluaslameduck
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.
Opsipods insecure
disediakan untuk kompatibilitas dengan Service kube-dns sebelumnya. Kamu dapat menggunakan opsipods verified
, yang mengembalikan record A hanya jika ada Pod pada Namespace yang sama untuk alamat IP yang sesuai. Opsipods 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.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, tekankubectl 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
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 menjadicpu=1,memory=2Gi,ephemeral-storage=1Gi
--system-reserved
diatur menjadicpu=500m,memory=1Gi,ephemeral-storage=1Gi
--eviction-hard
diatur menjadimemory.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.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
- Memiliki Klaster Kubernetes.
- Memiliki pemahaman dasar Pod, Service, dan Deployment dalam Kubernetes.
Melihat Namespace
- 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 lainkube-system
Namespace untuk objek-objek yang dibuat oleh sistem Kuberneteskube-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 digunakanTerminating
Namespace sedang dihapus dan tidak dapat digunakan untuk objek-objek baru
Lihat dokumentasi desain untuk detil lebih lanjut.
Membuat sebuah Namespace baru
kube-
, karena awalan ini dicadangkan untuk Namespace dari sistem Kubernetes.
-
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
-
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
-
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
-
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
danproduction
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
-
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=k8s.gcr.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 lainNamespace
production
seharusnya kosong, dan perintah berikut ini seharusnya tidak menghasilkan apapun.kubectl get deployment -n=production kubectl get pods -n=production
Production
Namespace ingin menjalankancattle
, mari kita buat beberapa Podcattle
.kubectl create deployment cattle --image=k8s.gcr.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:
- Cakupan untuk Names.
- 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:
- sumber daya (Pod, Service, ReplicationController, dll.)
- kebijakan (siapa yang bisa atau tidak bisa melakukan hal tertentu dalam komunitasnya)
- 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:
- penamaan sumber daya (untuk menghindari benturan penamaan dasar)
- pendelegasian otoritas pengelolaan untuk pengguna yang dapat dipercaya
- kemampuan untuk membatasi konsumsi sumber daya komunitas
Contoh penggunaan mencakup
- Sebagai operator klaster, aku ingin mendukung beberapa komunitas pengguna dalam sebuah klaster.
- Sebagai operator klaster, aku ingin mendelegasikan otoritas untuk mempartisi klaster ke pengguna terpercaya di komunitasnya.
- 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.
- 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
- Pelajari lebih lanjut mengenai pengaturan preferensi Namespace.
- Pelajari lebih lanjut mengenai pengaturan namespace untuk sebuah permintaan
- Baca desain Namespace.
4.4.7 - Mengatur Control Plane Kubernetes dengan Ketersediaan Tinggi (High-Availability)
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, tekankubectl 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. Jikatrue
, bacaan akan diarahkan ke replika pemimpin dari etcd. Menetapkan nilai ini menjaditrue
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:
- Menghapus replika yang gagal:
KUBE_DELETE_NODES=false KUBE_GCE_ZONE=replica_zone KUBE_REPLICA_NAME=replica_name ./cluster/kube-down.sh
- 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
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
4.4.8 - Menggunakan sysctl dalam Sebuah Klaster Kubernetes
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, tekankubectl 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).
Contoh net.ipv4.tcp_syncookies
bukan merupakan Namespace pada kernel Linux versi 4.4 atau lebih rendah.
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 (sepertinet.netfilter.nf_conntrack_max
dannet.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.
allowUnsafeSysctls
pada PodSecurityPolicy, Pod apa pun yang menggunakan sysctl seperti itu akan gagal dimulai
jika sysctl unsafe tidak diperbolehkan dalam flag kubelet --allowed-unsafe-sysctls
pada Node tersebut.
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.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, tekankubectl 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
-
Jalankan perintah berikut ini:
./etcd --listen-client-urls=http://$PRIVATE_IP:2379 --advertise-client-urls=http://$PRIVATE_IP:2379
-
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:
-
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
-
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:
- Siapkan sebuah klaster etcd.
- Konfigurasikan sebuah load balancer di depan klaster etcd.
Sebagai contoh, anggap saja alamat load balancer adalah
$LB
. - 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.
-
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
-
Hapus anggota yang gagal:
etcdctl member remove 8211f1d0f64f3269
Akan tampil pesan berikut:
Removed member 8211f1d0f64f3269 from cluster
-
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
-
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]
-
Lakukan salah satu dari yang berikut:
- Perbarui flag
--etcd-server
untuk membuat Kubernetes mengetahui perubahan konfigurasi, lalu start ulang server API Kubernetes. - Perbarui konfigurasi load balancer jika load balancer digunakan dalam Deployment.
- Perbarui flag
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, dankube-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 pesanetcd2 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 kluster 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".
4.5 - Mengelola Objek Kubernetes
4.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:
- Pengelolaan Objek Kubernetes Menggunakan Perintah Imperatif
- Pengelolaan Objek Kubernetes Menggunakan Berkas Konfigurasi Imperatif
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.
-R
untuk memproses seluruh direktori secara rekursif.
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:
- Menyimpan nilai field-field yang ada di file konfigurasi ke konfigurasi live.
- Menghapus field-field yang dihapus di file konfigurasi dari konfigurasi live.
kubectl diff -f <directory>/
kubectl apply -f <directory>/
-R
untuk memproses seluruh direktori secara rekursif.
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 perintahkubectl scale
. Hal ini karena fieldreplicas
dihapuskan dari file konfigurasi. - Nilai field
image
telah diperbarui menjadinginx:1.11.9
daringinx:1.7.9
. - Anotasi
last-applied-configuration
telah diperbari dengan image terbaru. - Field
minReadySeconds
telah dihapus. - Anotasi
last-applied-configuration
tidak lagi memuat fieldminReadySeconds
.
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
# ...
# ...
# ...
# ...
kubectl apply
dengan perintah imperatif untuk konfigurasi objek seperti create
dan replace
tidak dimungkinkan. Hal ini karena create
dan replace
tidak menyimpan anotasi kubectl.kubernetes.io/last-applied-configuration
yang diperlukan oleh kubectl aplly
untuk melakukan pembaruan.
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.
kubectl apply --prune
masih dalam versi alpha dan perubahan-perubahan yang tidak memiliki kompatibilitas dengan versi sebelumnya mungkin akan diperkenalkan pada rilis-rilis berikutnya.
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>
kubectl apply
dengan argumen --prune
sebaiknya hanya dijalankan terhadap direktori root yang berisi file-file konfigurasi objek. Menjalankan perintah tadi terhadap sub direktori bisa menyebabkan terhapusnya objek-objek lain secara tidak disengaja jika objek-objek tersebut memenuhi kriteria selektor label yang dispesifikasikan oleh argumen -l <label>
dan tidak muncul di sub direktori.
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:
- Hitung field-field yang perlu dihapus. Ini mencakup field-field yang ada di
last-applied-configuration
tapi tidak ada di file konfigurasi. - 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
:
- 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 anotasilast-applied-configuration
atau tidak. Pada contoh di atas, fieldminReadySeconds
muncul pada anotasilast-applied-configuration
, tapi tidak ada di file konfigurasi. Aksi: HapusminReadySeconds
dari konfigurasi live. - 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 nilaiimage
pada konfigurasi live. - Ubah anotasi
last-applied-configuration
agar sesuai dengan nilai yang ada di file konfigurasi. - 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
danreplicas
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
, danmetadata
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
, danargs
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.
-
digunakan untuk menandai sebuah nilai "not applicable" karena nilai tersebut tidak digunakan.
Field pada file konfigurasi objek | Field pada objek konfigurasi live | Field pada last-applied-configuration | Aksi |
---|---|---|---|
Ya | Ya | - | Ubah nilai di konfigurasi live mengikuti nilai pada file konfigurasi. |
Ya | Tidak | - | Ubah nilai di konfigurasi live mengikuti nilai pada konfigurasi lokal. |
Tidak | - | Ya | Hapus dari konfigurasi live. |
Tidak | - | Tidak | Tidak 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:
-
digunakan untuk menandai sebuah nilai "not applicable" karena nilai tersebut tidak digunakan.
Key pada file konfigurasi objek | Key pada objek konfigurasi live | Field pada last-applied-configuration | Aksi |
---|---|---|---|
Ya | Ya | - | Bandingkan nilai tiap sub field. |
Ya | Tidak | - | Ubah nilai pada konfigurasi live mengikuti nilai pada konfigurasi lokal. |
Tidak | - | Ya | Hapus dari konfigurasi live. |
Tidak | - | Tidak | Tidak 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. Perintahkubectl 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 adaargs
pada file konfigurasi). Ini karena nilaipatchMergeKey
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.
patchStrategy
pada types.go. Jika patchStrategy
tidak ditentukan untuk sebuah field yang bertipe list, maka list tersebut akan diubah nilainya secara keseluruhan.
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:
- Pengguna sebelumnya sudah membuat sebuah Deployment tanpa mendefinisikan
strategy.type
(seperti yang bisa dilihat padalast-applied-configuration
). - Server mengisi
strategy.type
dengan nilai defaultRollingUpdate
dan mengisistrategy.rollingUpdate
dengan nilai default pada konfigurasi live. - Pengguna mengubah nilai field
strategy.type
menjadiRecreate
pada file konfigurasi. Nilaistrategy.rollingUpdate
tidak berubah dari nilai default, meskipun server sekarang berekspektasi nilai tersebut dihapus. Jika nilaistrategy.rollingUpdate
didefinisikan di awal pada file konfigurasi, akan jelas bagi server bahwa field tersebut perlu dihapus. - Perintah
kubect apply
gagal karenastrategy.rollingUpdate
tidak dihapus. Fieldstrategy.rollingUpdate
tidak bisa didefinisikan jika fieldstrategy.type
berisiRecreate
.
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:
-
Ekspor objek live ke file konfigurasi lokal:
kubectl get <kind>/<name> -o yaml > <kind>_<name>.yaml
-
Hapus secara manual field
status
dari file konfigurasi.Catatan: Tahap ini opsional, karenakubectl apply
tidak memperbarui field status meskipun field tersebut ada di file konfigurasi. -
Ubah anotasi
kubectl.kubernetes.io/last-applied-configuration
pada objek:kubectl replace --save-config -f <kind>_<name>.yaml
-
Selanjutnya gunakan
kubectl apply
secara eksklusif untuk mengelola objek.
Migrasi dari konfigurasi objek imperatif ke konfigurasi objek deklaratif
-
Atur anotasi
kubectl.kubernetes.io/last-applied-configuration
pada objek:kubectl replace --save-config -f <kind>_<name>.yaml
-
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
4.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, tekankubectl 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-8mbdf7882g
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
bases:
- ../base
namePrefix: dev-
EOF
mkdir prod
cat <<EOF > prod/kustomization.yaml
bases:
- ../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
Field | Tipe | Deskripsi |
---|---|---|
namespace | string | menambahkan Namespace untuk semua sumber daya |
namePrefix | string | nilai dari field ini ditambahkan di awal pada nama dari semua sumber daya |
nameSuffix | string | nilai dari field ini ditambahkan di akhir pada nama dari semua sumber daya |
commonLabels | map[string]string | label untuk ditambahkan pada semua sumber daya dan selektor |
commonAnnotations | map[string]string | anotasi untuk ditambahkan pada semua sumber daya |
resources | []string | setiap entri di dalam daftar ini harus diselesaikan pada berkas konfigurasi sumber daya yang sudah ada |
configmapGenerator | []ConfigMapArgs | setiap entri di dalam daftar ini membangkitkan ConfigMap |
secretGenerator | []SecretArgs | setiap entri di dalam daftar ini membangkitkan Secret |
generatorOptions | GeneratorOptions | memodifikasi perilaku dari semua generator ConfigMap dan Secret |
bases | []string | setiap entri di dalam daftar ini harus diselesaikan ke dalam sebuah direktori yang berisi berkas kustomization.yaml |
patchesStrategicMerge | []string | setiap entri di dalam daftar ini harus diselesaikan dengan strategic merge patch dari sebuah objek Kubernetes |
patchesJson6902 | []Json6902 | setiap entri di dalam daftar ini harus diselesaikan ke suatu objek Kubernetes atau patch Json |
vars | []Var | setiap entri digunakan untuk menangkap teks yang berasal dari field sebuah sumber daya |
images | []Image | setiap entri digunakan untuk memodifikasi nama, tag dan/atau digest untuk sebuah image tanpa membuat patch |
configurations | []string | setiap entri di dalam daftar ini harus diselesaikan ke sebuah berkas yang berisi konfigurasi transformer Kustomize |
crds | []string | setiap entri di dalam daftar ini harus diselesaikan ke sebuah berkas definisi OpenAPI untuk tipe Kubernetes |
Selanjutnya
4.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 mengenaipatch 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
baik untuk perintah imperatif maupun konfigurasi objek imperatif. Perbedaannya hanya pada argumen yang diberikan ke perintah tersebut. Untuk menggunakan kubectl delete
sebagai perintah imperatif, argumen yang diberikan adalah objek yang hendak dihapus. Berikut adalah sebuah contoh perintah kubectl delete
dengan sebuah objek Deployment bernama nginx sebagai argumen:
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. Gunakanget -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 -
- 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. - Perintah
kubectl set selector --local -f - -o yaml
membaca konfigurasi dari stdin, dan menuliskan pembaruan konfigurasi ke stdout dalam format YAML. - 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
- Perintah
kubectl create service
membuat konfigurasi untuk objek Service dan menyimpannya di/tmp/srv.yaml
. - Perintah
kubectl create --edit
membuka berkas konfigurasi untuk disunting sebelum objek dibuat.
Selanjutnya
4.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
replace
akan menghilangkan semua bagian dari spesifikasi objek yang tidak dispesifikasikan pada file konfigurasi. Oleh karena itu, perintah ini sebaiknya tidak digunakan terhadap objek-objek yang spesifikasinya sebagian dikelola oleh klaster, misalnya Service dengan tipe LoadBalancer
, di mana field externalIPs
dikelola secara terpisah dari file konfigurasi. Field-field yang dikelola secara terpisah harus disalin ke file konfigurasi untuk mencegah terhapus oleh perintah replace
.
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:
- Kamu membuat sebuah objek dari sebuah file konfigurasi.
- Sebuah sumber lain memperbarui objek tersebut dengan mengubah beberapa field.
- 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.
- Ekspor objek live ke sebuah file konfigurasi objek lokal:
kubectl get <kind>/<name> -o yaml --export > <kind>_<name>.yaml
-
Hapus secara manual field status dari file konfigurasi objek.
-
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
4.6 - Memasukkan Data ke dalam Aplikasi
4.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, tekankubectl 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.
command
menyerupai entrypoint
di beberapa runtime Container.
Merujuk pada catatan di bawah.
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
-
Buat sebuah Pod dengan berkas konfigurasi YAML:
kubectl apply -f https://k8s.io/examples/pods/commands.yaml
-
Daftar Pod yang sedang berjalan
kubectl get pods
Keluaran menunjukkan bahwa Container yang berjalan di dalam Pod command-demo telah selesai.
-
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.
"$(VAR)"
. Ini
dibutuhkan untuk variabel yang akan diperuluas di bidang command
atau args
.
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.
Deskripsi | Nama bidang pada Docker | Nama bidang pada Kubernetes |
---|---|---|
Perintah yang dijalankan oleh Container | Entrypoint | command |
Argumen diteruskan ke perintah | Cmd | args |
Saat kamu mengesampingkan Entrypoint dan Cmd standar, aturan-aturan ini berlaku:
-
Jika kamu tidak menyediakan
command
atauargs
untuk sebuah Container, makacommand
danargs
yang didefinisikan di dalam image Docker akan digunakan. -
Jika kamu menyediakan
command
tetapi tidak menyediakanargs
untuk sebuah Container, akan digunakancommand
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 denganargs
yang kamu sediakan. -
Jika kamu menyediakan
command
danargs
, Entrypoint dan Cmd standar yang didefinisikan di dalam image Docker diabaikan.command
kamu akan dijalankan denganargs
kamu.
Berikut ini beberapa contoh:
Image Entrypoint | Image Cmd | Container command | Container args | Command 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
- Pelajari lebih lanjut tentang mengatur Pod and Container.
- Pelajari lebih lanjut tentang menjalankan perintah di dalam sebuah Container.
- Lihat Container.
4.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, tekankubectl 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"
-
Buatlah sebuah Pod berdasarkan berkas konfigurasi YAML tersebut:
kubectl apply -f https://k8s.io/examples/pods/inject/envars.yaml
-
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
-
Dapatkan sebuah shell ke Container yang sedang berjalan di Pod kamu:
kubectl exec -it envar-demo -- /bin/bash
-
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
-
Untuk keluar dari shell tersebut, masukkan perintah
exit
.
env
atau envFrom
akan mengesampingkan
variabel-variabel lingkungan yang ditentukan di dalam image kontainer.
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
- Pelajari lebih lanjut tentang variabel lingkungan.
- Pelajari tentang menggunakan informasi rahasia sebagai variabel lingkungan.
- Lihat EnvVarSource.
4.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
-
Membuat Secret
kubectl apply -f https://k8s.io/examples/pods/inject/secret.yaml
-
Melihat informasi dari Secret:
kubectl get secret test-secret
Hasil keluaran:
NAME TYPE DATA AGE test-secret Opaque 2 1m
-
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
-
Membuat Pod:
kubectl apply -f https://k8s.io/examples/pods/inject/secret-pod.yaml
-
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
-
Gunakan shell untuk masuk ke dalam Container yang berjalan di dalam Pod kamu:
kubectl exec -i -t secret-test-pod -- /bin/bash
-
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
-
Di dalam shell kamu, tampilkan konten dari berkas
username
danpassword
:# 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 lingkunganSECRET_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 Containerkubectl 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
danpassword
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
4.7 - Menjalankan
4.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, tekankubectl 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
-
Buatlah sebuah Deployment berdasarkan berkas YAML:
kubectl apply -f https://k8s.io/examples/application/deployment.yaml
-
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.
-
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
-
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
-
Terapkan berkas YAML yang baru:
kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml
-
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.14.2
ports:
- containerPort: 80
-
Terapkan berkas YAML:
kubectl apply -f https://k8s.io/examples/application/deployment-scale.yaml
-
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
- Pelajari lebih lanjut mengenai objek Deployment.
4.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.
4.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?
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.
Kubernetes v1.11 [deprecated]
Pengambian metrik dari Heapster tidak didukung lagi pada Kubernetes versi 1.11.
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
adalahtrue
atau tidak ada. Ubah nilai tersebut menjadifalse
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
- Dokumentasi desain Horizontal Pod Autoscaling.
- Perintah kubectl autoscale kubectl autoscale.
- Contoh penggunaan HorizontalPodAutoscaler.
4.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
replicas: 1
template:
metadata:
labels:
run: php-apache
spec:
containers:
- name: php-apache
image: k8s.gcr.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-percent=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
4.8 - Mengakes Aplikasi-aplikasi di sebuah Klaster
4.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..
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.
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
danversion
aplikasi. Kamu dapat menentukan label lain untuk diterapkan ke Deployment, Service (jika ada), dan Pod, sepertirelease
,environment
,tier
,partition
, dantrack
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.
Navigation
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.
Selanjutnya
Untuk informasi lebih lanjut, lihat Laman proyek Kubernetes Dashboard.
4.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()
dankubernetes.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
atauLoadBalancer
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.
- Gunakan Service dengan tipe
- 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 HTTPhttps:<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:
-
- 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
-
- 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
-
- berjalan di setiap Node
- memproksi UDP dan TCP
- tidak mengerti HTTP
- menyediakan load balancing
- hanya digunakan untuk menjangkau Service
-
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.
-
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.
4.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
.
kubeconfig
.
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, tekankubectl 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
- Untuk menghapus sebuah pengguna, kamu dapat menjalankan perintah
kubectl --kubeconfig=config-demo config unset users.<name>
- Untuk menghapus sebuah klaster, kamu dapat menjalankan perintah
kubectl --kubeconfig=config-demo config unset clusters.<name>
- Untuk menghapus sebuah konteks, kamu dapat menjalankan perintah
kubectl --kubeconfig=config-demo config unset contexts.<name>
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
4.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, tekankubectl version
.
- Install redis-cli.
Membuat Deployment dan Service Redis
-
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
-
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
-
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
-
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
-
Memulai antarmuka baris perintah (command line) Redis:
redis-cli -p 7000
-
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.
kubectl port-forward
hanya bisa diimplementasikan untuk porta TCP saja.
Dukungan untuk protokol UDP bisa dilihat di
issue 47862.
Selanjutnya
Belajar lebih tentang kubectl port-forward.
4.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, tekankubectl 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) danLocal
.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 keduaLoadBalancer
dan Service dengan tipeNodePort
, namun resiko berpotensi penyebaran lalu lintas yang tidak merata.service.spec.healthCheckNodePort
- menentukan pemeriksaan kesehatan porta dari sebuah Node (angka porta numerik) untuk Service. JikahealthCheckNodePort
tidak ditentukan, pengendali Service mengalokasi porta dari rentangNodePort
dari klaster kamu. Kamu dapat mengonfigurasi rentangan tersebut dari pengaturan opsi barisan perintah API server,--service-node-port-range
. Hal itu menggunakan nilaihealthCheckNodePort
pengguna spesifik jika ditentukan oleh klien. Hal itu dapat berefek hanya ketikatype
diset keLoadBalancer
danexternalTrafficPolicy
diset keLocal
.
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
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.
4.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, tekankubectl 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 fieldimage
dari keluaran json yang dihasilkan.- Silakan lihat referensi jsonpath
untuk informasi lebih lanjut tentang cara menggunakan
jsonpath
.
- Silakan lihat referensi jsonpath
untuk informasi lebih lanjut tentang cara menggunakan
- 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
- Gunakan
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
kubectl get pod nginx
,
bagian .items[*]
dari jalur harus dihilangkan karena hanya akan menghasilkan sebuah Pod
sebagai keluarannya, bukan daftar dari semua Pod.
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
- Referensi panduan Jsonpath.
- Referensi panduan Go template.
4.9 - Pemantauan, Pencatatan, and Debugging
4.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:
4.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, tekankubectl 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
Menulis halaman utama (root) untuk 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
4.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.
4.10 - TLS
4.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.
certificates.k8s.io
ditandatangani oleh CA
khusus. Ini memungkinkan untuk mengkonfigurasi klaster kamu agar menggunakan CA root klaster untuk tujuan ini,
namun jangan pernah mengandalkan ini. Jangan berasumsi bahwa sertifikat ini akan melakukan validasi
dengan CA root 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, tekankubectl 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: [email protected]
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 [email protected] 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:
- 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.
- 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.
4.11 - Mengelola Daemon Klaster
4.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, tekankubectl 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
melaluikubectl
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
--to-revision
tidak diberikan, maka kubectl akan memilihkan revisi yang terakhir.
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
.
.revision
) yang sedang di-rollback akan maju ke depan.
Misalnya, jika kamu memiliki revisi 1 dan 2 pada sistem, lalu rollback dari revisi 2 ke revisi 1,
ControllerRevision dengan .revision: 1
akan menjadi .revision: 3
.
Troubleshoot
- Lihat cara untuk melakukan troubleshoot rolling update pada DaemonSet.
5 - Tutorial
Bagian ini membahas tentang tutorial Kubernetes. Tutorial berfungsi untuk memperlihatkan bagaimana caranya mencapai suatu tujuan yang lebih dari sekedar task sederhana. Biasanya, sebuah tutorial punya beberapa bagian, masing-masing bagian terdiri dari langkah-langkah yang berurutan. Sebelum melangkah lebih lanjut ke tutorial, sebaiknya tandai dulu halaman Kamus Istilah untuk referensi nanti.
Prinsip Dasar
-
Prinsip Dasar Kubernetes merupakan tutorial yang sangat interaktif, membantu kamu mengerti apa itu sistem Kubernetes dan beberapa fitur Kubernetes yang umum digunakan.
Konfigurasi
Aplikasi Stateless
Aplikasi Stateful
Klaster
Servis
Selanjutnya
Tertarik menulis tutorial? Lihat Menggunakan Template Halaman untuk info mengenai template dan ragam halaman tutorial.
5.1 - Halo Minikube
Tutorial ini menunjukkan bagaimana caranya menjalankan aplikasi sederhana Node.js Halo Dunia di Kubernetes, dengan minikube
dan Katacoda.
Katacoda menyediakan environment Kubernetes secara gratis di dalam browser.
minikube
untuk instruksi instalasi.
Tujuan
- Deploy aplikasi halo dunia pada minikube.
- Jalankan aplikasinya.
- Melihat log aplikasi.
Sebelum kamu memulai
Tutorial ini menyediakan image Kontainer yang dibuat melalui barisan kode berikut:
var http = require('http');
var handleRequest = function(request, response) {
console.log('Received request for URL: ' + request.url);
response.writeHead(200);
response.end('Hello World!');
};
var www = http.createServer(handleRequest);
www.listen(8080);
FROM node:6.14.2
EXPOSE 8080
COPY server.js .
CMD node server.js
Untuk info lebih lanjut tentang perintah docker build
, baca dokumentasi Docker.
Membuat sebuah klaster Minikube
-
Tekan Launch Terminal
Catatan: Kalau kamu memilih instalasi minikube secara lokal, jalankanminikube start
. -
Buka dasbor Kubernetes di dalam browser:
minikube dashboard
-
Hanya untuk environment Katacoda: Di layar terminal paling atas, tekan tombol plus, lalu lanjut tekan Select port to view on Host 1.
-
Hanya untuk environment Katacoda: Ketik
30000
, lalu lanjut tekan Display Port.
Membuat sebuah Deployment
Sebuah Kubernetes Pod adalah kumpulan dari satu atau banyak Kontainer, saling terhubung untuk kebutuhan administrasi dan jaringan. Pod dalam tutorial ini hanya punya satu Kontainer. Sebuah Kubernetes Deployment selalu memeriksa kesehatan Pod kamu dan melakukan restart saat Kontainer di dalam Pod tersebut mati. Deployment adalah cara jitu untuk membuat dan mereplikasi Pod.
-
Gunakan perintah
kubectl create
untuk membuat Deployment yang dapat mengatur Pod. Pod menjalankan Kontainer sesuai dengan image Docker yang telah diberikan.kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4
-
Lihat Deployment:
kubectl get deployments
Keluaran:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-node 1 1 1 1 1m
-
Lihat Pod:
kubectl get pods
Keluaran:
NAME READY STATUS RESTARTS AGE hello-node-5f76cf6ccf-br9b5 1/1 Running 0 1m
-
Lihat event klaster:
kubectl get events
-
Lihat konfigurasi
kubectl
:kubectl config view
Catatan: Untuk info lebih lanjut tentang perintahkubectl
, lihat ringkasan kubectl.
Membuat sebuah Servis
Secara default, Pod hanya bisa diakses melalui alamat IP internal di dalam klaster Kubernetes.
Supaya Kontainer hello-node
bisa diakses dari luar jaringan virtual Kubernetes, kamu harus ekspos Pod sebagai Servis Kubernetes.
-
Ekspos Pod pada internet publik menggunakan perintah
kubectl expose
:kubectl expose deployment hello-node --type=LoadBalancer --port=8080
Tanda
--type=LoadBalancer
menunjukkan bahwa kamu ingin ekspos Servis keluar dari klaster. -
Lihat Servis yang baru kamu buat:
kubectl get services
Keluaran:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-node LoadBalancer 10.108.144.78 <pending> 8080:30369/TCP 21s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23m
Untuk penyedia cloud yang memiliki load balancer, sebuah alamat IP eksternal akan disediakan untuk mengakses Servis tersebut. Pada minikube, tipe
LoadBalancer
membuat Servis tersebut dapat diakses melalui perintahminikube service
. -
Jalankan perintah berikut:
minikube service hello-node
-
Hanya untuk environment Katacoda: Tekan tombol plus, lalu lanjut tekan Select port to view on Host 1.
-
Hanya untuk environment Katacoda: Ketik
30369
(lihat port di samping8080
pada keluaran servis), lalu lanjut tekanIni akan membuka jendela browser yang menjalankan aplikasimu dan memperlihatkan pesan "Halo Dunia".
Aktifkan addons
Perangkat minikube meliputi sekumpulan addons bawaan yang bisa diaktifkan, dinonaktifkan, maupun dibuka di dalam environment Kubernetes lokal.
-
Daftar addons yang ada saat ini:
minikube addons list
Keluaran:
addon-manager: enabled coredns: disabled dashboard: enabled default-storageclass: enabled efk: disabled freshpod: disabled heapster: disabled ingress: disabled kube-dns: enabled metrics-server: disabled nvidia-driver-installer: disabled nvidia-gpu-device-plugin: disabled registry: disabled registry-creds: disabled storage-provisioner: enabled
-
Aktifkan sebuah addon, misalnya
heapster
:minikube addons enable heapster
Keluaran:
heapster was successfully enabled
-
Lihat Pod dan Servis yang baru saja kamu buat:
kubectl get pod,svc -n kube-system
Keluaran:
NAME READY STATUS RESTARTS AGE pod/heapster-9jttx 1/1 Running 0 26s pod/influxdb-grafana-b29w8 2/2 Running 0 26s pod/kube-addon-manager-minikube 1/1 Running 0 34m pod/kube-dns-6dcb57bcc8-gv7mw 3/3 Running 0 34m pod/kubernetes-dashboard-5498ccf677-cgspw 1/1 Running 0 34m pod/storage-provisioner 1/1 Running 0 34m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/heapster ClusterIP 10.96.241.45 <none> 80/TCP 26s service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 34m service/kubernetes-dashboard NodePort 10.109.29.1 <none> 80:30000/TCP 34m service/monitoring-grafana NodePort 10.99.24.54 <none> 80:30002/TCP 26s service/monitoring-influxdb ClusterIP 10.111.169.94 <none> 8083/TCP,8086/TCP 26s
-
Non-aktifkan
heapster
:minikube addons disable heapster
Keluaran:
heapster was successfully disabled
Bersih-bersih
Sekarang, mari kita bersihkan semua resource yang kamu buat di klaster:
kubectl delete service hello-node
kubectl delete deployment hello-node
Kamu juga boleh mematikan mesin virtual atau virtual machine (VM) untuk minikube:
minikube stop
Kamu juga boleh menghapus minikube VM:
minikube delete
Selanjutnya
- Pelajari lebih lanjut tentang Deployment.
- Pelajari lebih lanjut tentang Deploy aplikasi.
- Pelajari lebih lanjut tentang Servis.
5.2 - Mempelajari Panduan Dasar Kubernetes
Panduan Dasar Kubernetes
Tutorial ini menyediakan panduan dasar mekanisme orkestrasi klaster Kubernetes. Setiap modul memliki beberapa informasi mengenai latar belakang bagi konsep mendasar dan feature Kubernetes, termasuk mode interaktif yang dapat digunakan sebagai metode pembelajaran online. Mode tutorial interaktif ini memberikan kesempatan pengguna untuk melakukan manajemen klaster sederhana beserta aplikasi terkontainerisasi yang kamu miliki.
Dengan menggunakan mode tutorial interaktif ini, pengguna diharapkan dapat memahami:
- Deploy sebuah aplikasi yang sudah dikontainerisasi pada klaster
- Melakukan scale deployment
- Memperbarui aplikasi yang sudah dikontainerisasi dengan menggunakan versi aplikasi terbaru
- Men-debug aplikasi yang sudah dikontainerisasi
Tutorial ini menggunakan Katakoda untuk menjalankan terminal virtual diatas Minikube pada web browser kamu. Dengan demikian, kamu tidak perlu melakukan instalasi perangkat lunak apa pun, segala modul yang ada dijalankan secara langsung melalui web browser yang kamu miliki.
Apa yang dapat dilakukan oleh Kubernetes untuk kamu?
Seiring berkembangnya web servis modern, pengguna memiliki ekspektasi agar aplikasi selalu dapat diakses 24/7, selain itu developers juga memiliki harapan agar mereka dapat melakukan deployment aplikasi dengan versi terbaru yang mereka miliki berulang per hari. Mekanisme kontainerisasi mengepak perangkat lunak agar memenuhi kebutuhan yang ada, memudahkan serta mempercepat proses rilis dan pembaharuan aplikasi tanpa adanya downtime proses ini dapat dilakukan berulang per hari. Kubernetes membantu kamu menjaga aplikasi yang kamu buat untuk dapat dijalankan dimana pun dan kapan pun kamu menginginkannya, serta menjamin segala kebutuhan dan peralatan yang dibutuhkan oleh aplikasi kamu tersedia. Kubernetes merupakan platform open source yang sudah matang yang didesain berdasarkan pengalaman Google serta ide yang brilian dari komunitas yang ada.
5.2.1 - Membuat Klaster
5.2.1.1 - Menggunakan Minikube Untuk Membuat Klaster
Objectives
- Belajar apa itu klaster Kubernetes.
- Belajar apa itu Minikube.
- Memulai klaster Kubernetes menggunakan terminal _online_.
Klaster Kubernetes
Kubernetes mengoordinasikan klaster komputer ketersediaan tinggi (_highly available_) yang saling terhubung sebagai unit tunggal. Abstraksi pada Kubernetes mengizinkan kamu untuk men-_deploy_ aplikasi terkemas (_containerized_) ke sebuah klaster tanpa perlu membalutnya secara spesifik pada setiap mesin. Untuk menggunakan model baru _deployment_ ini, aplikasi perlu dikemas dengan cara memisahkan mereka dari hos individu: mereka perlu dikemas. Aplikasi terkemas lebih fleksibel dan tersedia dibanding model _deployment_ lama, dimana aplikasi dipasang secara langsung didalam mesin spesifik sebagai paket yang sangat terintegrasi dengan hos. Kubernetes mengotomasisasikan distribusi dan penjadwalan kontainer aplikasi sebuah klaster secara menyeluruh dengan cara yang lebih efisien. Kubernetes merupakan platform _open-source_ dan siap produksi.
Klaster Kubernetes terdiri dari 2 tipe sumber daya:
- Master mengoordinasikan klaster
- Node adalah pekerja (_worker_) yang menjalankan aplikasi
Summary:
- Klaster Kubernetes
- Minikube
Kubernetes merupakan platform _open-source_ tingkat produksi yang mengatur penjadwalan dan eksekusi kontainer aplikasi didalam dan keseluruhan klaster komputer.
Diagram Klaster
Master mempunyai kewajiban untuk mengelola klaster. Master mengoordinasikan semua aktifitas di klaster kamu, seperti penjadwalan aplikasi, pemeliharaan keadaan (_state_) aplikasi yang diinginkan, _scaling_ aplikasi, dan _roll-out_ pembaharuan.
Node merupakan VM atau komputer fisik yang berfungsi sebagai mesin pekerja dalam klaster Kubernetes. Setiap node mempunyai Kubelet, sebuah agen untuk mengatur Node dan komunikasi dengan Kubernetes master. Node juga harus mempunyai alat untuk menangani operasi kontainer, seperti Docker atau rkt. Sebuah klaster Kubernetes yang menangani trafik produksi harus mempunyai minimal 3 Node.
Master mengatur klaster dan Node yang digunakan sebagai hos dari aplikasi yang berjalan.
Ketika kamu men-_deploy_ aplikasi pada Kubernetes, kamu memberitahu master untuk memulai kontainer aplikasi. Master melakukan penjadwalan kontainer untuk berjalan diatas klaster Node. Node berkomunikasi dengan master menggunakan Kubernetes API, yang disediakan oleh master. Pengguna akhir juga dapat menggunakan Kubernetes API secara langsung untuk berinteraksi dengan klaster.
Klaster Kubernetes dapat di-_deploy_ ke mesik fisik maupun virtual. Untuk memulai pengembangan Kubernetes, kamu dapat menggunakan Minikube. Minikube merupakan implementasi Kubernetes ringan yang membuat VM padi mesin lokal kamu dan men-_deploy_ klaster sederhanya yang terdiri atas 1 Node. Minikube tersedia untuk Linux, macOS, dan sistem Windows. Minikube CLI menyediakan operasi _bootstraping_ dasar untuk bekerja dengan klaster kamu. Namun untuk tutorial ini, kamu akan menggunakan online terminal yang sudah disediakan dengan Minikube yang sudah diinstall sebelumnya.
Sekarang kamu telah mengetahui apa itu Kubernetes, mari kita pergi ke tutorial online dan memulai klaster pertama kita!
5.2.1.2 - Tutorial Interaktif - Membuat Klaster
5.2.2 - Menyebarkan (Deploy) Aplikasi
5.2.2.1 - Menggunakan kubectl untuk membuat Deployment
Tujuan
- Belajar tentang menyebarkan (deploy) aplikasi.
- Menyebarkan aplikasi pertama kamu di Kubernetes dengan kubectl.
Deployment Kubernetes
Ketika klaster Kubernetes kamu sudah berjalan, kamu dapat menyebarkan aplikasi terkontainerisasi di atasnya. Untuk melakukannya, kamu perlu membuat konfigurasi Deployment. Deployment menginstruksikan Kubernetes tentang bagaimana cara membuat dan memperbarui instance aplikasi kamu. Ketika kamu selesai membuat Deployment, Kubernetes control plane melakukan penjadwalan instance aplikasi yang terlibat dalam Deployment untuk berjalan di Node individu pada klaster.
Setelah instance aplikasi telah dibuat, Kubernetes Deployment Controller akan melakukan monitoring instance tersebut secara kontinu. Jika instance pada hos Node mati atau terhapus, Deployment Controller akan mengganti instance tersebut dengan instance Node lain dalam klaster. Ia menyediakan mekanisme penyembuhan diri (self-healing) untuk mengatasi kegagalan mesin atau pemeliharaan (maintenance)
Pada masa pra-orkestrasi, instalasi script sering digunakan untuk memulai aplikasi, namun cara ini tidak memberikan mekanisme pemulihan ketika terjadi kegagalan mesin. Dengan kemampuan membuat instance aplikasi dan menjaganya tetap berjalan pada Node, Deployment Kubernetes menyediakan manajemen aplikasi dengan pendekatan fundamental yang berbeda.
Ringkasan:
- Deployment
- Kubectl
Sebuah Deployment bertanggung jawab untuk membuat dan memperbarui instance dari aplikasi kamu
Menyebarkan aplikasi pertama kamu dalam Kubernetes
Kamu dapat membuat dan mengatur Deployment dengan menggunakan antar muka baris perintah (CLI) Kubernetes, Kubectl. Kubectl menggunakan Kubernetes API untuk berinteraksi dengan klaster. Pada modul ini, kamu akan belajar perintah-perintah yang sering digunakan Kubectl untuk membuat Deployment untuk menjalankan aplikasi kamu pada klaster Kubernetes.
Ketika kamu membuat Deployment, kamu perlu mendefinisikan Container image untuk aplikasi kamu dan jumlah replika yang kamu inginkan. Kamu dapat mengganti informasi tersebut nanti dengan melakukan pembaharuan Deployment kamu; Modul 5 dan 6 pada bootcamp ini mendiskusikan bagaimana cara melakukan perluasan (scale) dan pembaruan Deployment kamu.
Aplikasi perlu dikemas menjadi satu dengan format Container yang didukung supaya tersebar pada Kubernetes
Pada Deployment pertama kamu, kamu akan menggunakan aplikasi Node.js yang terkemas dalam Container Docker. (Jika kamu belum pernah mencoba membuat aplikasi Node.js dan menyebarkannya dengan Container, kamu dapat melakukannya dengan mengikuti instruksi pada tutorial Hello Minikube).
Sekarang kamu tahu apa itu Deployment, mari kita ke tutorial online dan menyebarkan aplikasi pertama kita!
5.2.2.2 - Tutorial Interaktif - Menyebarkan (Deploy) Aplikasi
Pod merupakan unit eksekusi utama pada aplikasi Kubernetes. Setiap Pod mewakili sebagian dari beban kerja (workload) yang berjalan pada klaster kamu. Learn more about Pods.
5.2.3 - Menjelajahi Aplikasimu
5.2.3.1 - Melihat Pod dan Node
Tujuan
- Belajar tentang Pod Kubernetes.
- Belajar tentang Node Kubernetes.
- Mengatasi masalah pada aplikasi-aplikasi yang digelar.
Pod Kubernetes
Ketika kamu membuat sebuah Deployment pada Modul 2, Kubernetes membuatkan sebuah Pod untuk menempatkan instans aplikasimu. Pod merupakan sebuah abstraksi Kubernetes yang merepresentasikan sebuah grup yang terdiri dari satu atau lebih kontainer (seperti Docker), dan beberapa sumber daya bersama untuk kontainer-kontainer itu. Sumber daya tersebut termasuk:
- Penyimpanan bersama, disebut Volume
- Jaringan, sebagai satu alamat IP klaster unik
- Informasi tentang bagaimana mejalankan tiap kontainer, seperti versi image atau porta spesifik yang digunakan oleh kontainer
Pod memodelkan sebuah "logical host" spesifik aplikasi dan dapat berisi beberapa kontainer aplikasi berbeda yang relatif terkait erat. Contohnya, sebuah Pod mungkin terdiri atas kontainer aplikasi Node.js dan juga kontainer berbeda yang bertugas menyediakan data untuk dipublikasikan ke server web Node.js. Kontainer-kontainer dalam sebuah Pod berbagi satu alamat IP dan ruang porta, selalu terletak bersama dan terjadwal bersama, dan berjalankan dalam satu konteks bersama (shared context) pada Node yang sama.
Pod merupakan unit terkecil dalam platform Kubernetes. Ketika kita membuat sebuat Deployment, Deployment tersebut membuat Pod dengan kontainer-kontainer di dalamnya (bukannya dengan membuat kontainer secara langsung). Tiap Pod terikat langsung dengan Node di mana dia dijadwalkan dan tetap di sana sampai diterminasi (berdasarkan restart policy) atau penghapusan. Jika terjadi kegagalan pada sebuah Node, Pod indentik akan dijadwalkan di Node lain dalam klaster.
Ringkasan:
- Pod
- Node
- Perintah utama kubectl
Pod merupakan sebuah grup yang terdiri dari satu atau lebih kontainer aplikasi (seperti Docker) dan berisi penyimpanan bersama (volume), alamat IP dan informasi tentang bagaimana menjalankan mereka.
Ikhtisar Pod
Node
Sebuah Pod selalu berjalan dalam sebuah Node. Node merupakan sebuah mesin pekerja (worker) di Kubernetes dan mungkin merupakan mesin virtual ataupun fisik, tergantung dari klaster. Tiap Node dikelola oleh control plane. Satu Node dapat memiliki beberapa Pod, dan control plane Kubernetes yang otomatis menangani penjadwalan pod seluruh Node-Node dalam klaster. Penjadwalan otomatis oleh control plane memperhitungkan tersedianya sumber daya tiap Node.
Tiap Node Kuberbetes menjalankan setidaknya:
- Kubelet, satu proses yang bertanggung jawab untuk berkomunikasi antara control plane Kuberneter dan Node; ini juga mengelola Pod-Pod dan kontainer-kontainer yang berjalan di sebuah mesin.
- Satu container runtime, seperti Docker, bertanggung jawab untuk menarik image kontainer dari register, membuka kontainer, dan menjalankan aplikasi.
Kontainer seharusnya hanya dijadwalkan bersama di satu Pod jika terkait erat dan membutuhkan sumber daya bersama seperti diska.
Ikhtisar Node
Mengatasi masalah dengan kubectl
Dalam Modul 2, kamu menggunakan antarmuka baris perintah kubectl. Kamu akan lanjut menggunakannya pada modul 3 untuk mendapatkan informasi tentang aplikasi-aplikasi yang digelar dan lingkungannya. Operasi yang paling umum dapat dilakukan dengan perintah kubectl berikut:
- kubectl get - melihat daftar sumber daya
- kubectl describe - menampilkan detil informasi tentang suatu sumber daya
- kubectl logs - mencetak log-log dari satu kontainer dalam sebuah Pod
- kubectl exec - eksekusi sebuah perintah pada satu kontainer dalam sebuah Pod
Kamu dapat menggunakan perintah ini kapan aplikasi-aplikasi digelar, apa status mereka saat ini, di mana mereka berjalan, dan apa konfigurasi mereka.
Sekarang karena kita lebih mengetahui tentang klaster kita dan baris perintahnya, mari kita menjelajah aplikasi kita.
Node merupakan mesin pekerja di Kubernetes dan bisa berupa VM ataupun mesin fisik, tergantung pada klaster. Beberapa Pod dapat berjalan dalam satu Node.
5.2.3.2 - Tutorial Interaktif - Menjelajahi Aplikasimu
5.2.4 - Mengekspos Aplikasimu Secara Publik
5.2.4.1 - Menggunakan Service untuk Mengekspos Aplikasimu
Tujuan
- Belajar tentang Service di Kubernetes
- Memahami bagaimana label dan objek LabelSelector berhubungan dengan sebuah Service
- Mengekspos sebuah aplikasi keluar klaster Kubernetes menggunakan sebuah Service
Ikhtisar Service Kubernetes
Pod-Pod Kubernetes itu fana. Pod pada kenyataannya punya siklus hidup. Ketika sebuah Node pekerja mati, Pod yang berjalan dalam Node itu juga hilang. ReplicaSet mungkin kemudian secara dinamis mendorong klaster kembali ke keadaan yang diinginkan melalui penciptaan Pod baru untuk memastikan aplikasimu berjalan. Contoh lainnya, katakanlah ada backend pengolahan citra dengan 3 replika. Replika tersebut dapat ditukar; sistem front-end seharusnya tidak peduli tentang replika backend atau bahkan jika Pod hilang dan dibuat ulang. Walaupun demikian, tiap Pod dalam sebuah klaster Kubernetes memiliki alamat IP unik, meskipun Pod-Pod itu berada dalam satu Node yang sama, sehingga seharusnya ada jalan untuk mencocokan perubahan antara Pod-Pod itu sehingga aplikasimu tetap berfungsi.
Service di Kubernetes merupakan abstraksi yang mendefinisikan satu set Pod secara logis dan aturan untuk mengakses mereka. Service memungkinkan keterkaitan renggang antara Pod-Pod. Sebuah Service didefinisikan menggunakan YAML (lebih disukai) atau JSON, sebagaimana semua objek Kubernetes. Kumpulan Pod yang ditargetkan oleh Service biasanya ditentukan oleh LabelSelector (lihat di bawah mengapa kamu mungkin ingin Service tanpa selector
dalam spec).
Meskipun tiap Pod memiliki alamat IP unik, IP tersebut tidak diekpos ke luar klaster tanpa sebuah Service. Service memperbolehkan aplikasimu untuk menerima kunjungan. Service dapat diekspos dengan cara yang berbeda menggunakan type
di ServiceSpec:
- ClusterIP (bawaan) - Mengekspos Service dengan internal IP dalam klaster. Type ini membuat Service hanya bisa diakses dalam klaster.
- NodePort - Mengekspos Service dengan porta yang sama untuk tiap Node dalam klaster menggunakan NAT. Ini membuat Service dapat diakses dari luar dengan
<NodeIP>:<NodePort>
. Superset dari ClusterIP. - LoadBalancer - Membuat load balancer eksternal di cloud saat ini (jika didukung) dan memberikan IP eksternal tetap kepada Service. Superset dari NodePort.
- ExternalName - Mengekpos Service menggunakan nama sesuai keinginan (ditentukan oleh
externalName
dalam spec) dengan mengembalikan catatan CNAME dengan nama tersebut. Tidak menggunakan proksi. Type ini membutuhkankube-dns
versi v1.7 atau lebih tinggi.
Informasi lebih tentang type Service berbeda dapat ditemukan di tutorial Menggunakan IP pengirim. Lihat juga Menghubungkan aplikasi dengan Service.
Selain itu, catat bahwa ada kasus penggunaan Service yang tidak mendefinisikan selector
di spec. Sebuah Service yang dibuat tanpa selector
juga tidak akan membuat objek Endpoint yang sesuai. Ini mengizinkan pengguna untuk memetakan Service secara manual ke endpoint spesifik. Kemungkinan lain kenapa dimungkinan tanpa selector adalah kamu dengan tegas menggunakan type: ExternalName
.
Ringkasan
- Mengekspos Pod ke kunjungan eksternal
- Load balancing kunjungan melintasi beberapa Pod
- Menggunakan label
Service Kubernetes adalah lapisan abstraksi yang mendefinisikan kumpulan Pod secara logis dan mengijinkan paparan kunjungan eksternal, load balancing, dan service discovery untuk Pod-Pod tersebut.
Service dan Label
Service mengarahkan kunjungan melintasi sekumpulan Pod. Service merupakan abstraksi yang mengizinkan Pod-Pod untuk mati dan replikasi dalam Kubernetes tanpa memengaruhi aplikasimu. Menemukan dan routing antara Pod dependen (seperti komponen frontend dan backend) yang ditangani oleh Service Kubernetes.
Service mencocokan satu set Pod menggunakan label dan selektor, mengelompokan primitif yang mengizinkan operasi logika pada objek-objek dalam Kubernetes. Label adalah pasangan key/value yang melekat pada objek-objek dan dapat digunakan untuk beberapa tujuan:
- Menandai objek-objek untuk lingkungan development, test, dan production
- Melekatkan label versi
- Klasifikasi sebuah objek dengan label-label
Label-label dapat dilekatkan pada objek-objek pada waktu pembuatan ataupun setelahnya. Mereka dapat diubah kapanpun. Mari kita ekspos aplikasi kita sekarang dengan sebuah Service dan menerapkan beberapa label.
5.2.4.2 - Tutorial Interaktif - Mengekspos Aplikasimu
5.2.5 - Penyekalaan Aplikasimu
5.2.5.1 - Menjalankan Multipel Instans dari Aplikasimu
Tujuan
- Penyekalaan aplikasi menggunakan kubectl.
Penyekalaan sebuah Aplikasi
Di modul-modul sebelumnya kita telah membuat Deployment, dan mengeksposnya secara publik via Service. Deployment tersebut hanya membuat satu Pod untuk menjalankan aplikasi kita. Ketika kunjungan meningkat, kita perlu melakukan penyekalaan (scale) aplikasi kita untuk mengikuti tingkat permintaan pengguna.
Penyekalaan dapat dicapai dengan mengubah nilai replicas dalam Deployment
Ringkasan:
- Penyekalaan sebuah Deployment
Kamu dapat membuat Deployment dengan beberapa instans sekaligus dari awal dengan menggunakan parameter --replicas pada perintah kubectl create deployment
Ikhtisar Penyekalaan
Perluasan skala Deployment akan memastikan Pod baru dibuat dan dijadwalkan ke Node-Node dengan sumber daya yang tersedia. Penyekalaan akan meningkatkan jumlah Pod ke keadaan yang diinginkan. Kubernetes juga mendukung autoscaling Pod, tetapi itu di luar cakupan tutorial ini. Penyekalaan ke nol juga dimungkinkan, dan tindakan ini akan mengakhiri semua Pod pada Deployment tersebut.
Menjalankan beberapa instans dari aplikasi akan membutuhkan cara untuk mendistribusikan trafik ke semuanya. Service memiliki penyeimbang beban terintegrasi yang akan mendistribusikan trafik jaringan ke semua Pod dari sebuah Deployment yang diekspos. Service akan terus memonitor Pod-Pod yang berjalan menggunakan Endpoints, untuk memastikan trafik hanya dikirim ke Pod yang tersedia.
Penyekalaan dapat dicapai dengan mengubah jumlah replicas pada sebuah Deployment.
Sewaktu kamu memiliki multipel instans dari aplikasi yang berjalan, kamu akan bisa melakukan pembaruan bertahap tanpa henti. Kita akan akan membahas hal tersebut pada modul selanjutnya. Sekarang, mari kita pergi ke terminal daring dan melakukan penyekalaan terhadap aplikasi kita.
5.2.5.2 - Tutorial Interaktif - Penyekalaan Aplikasimu
5.2.6 - Memperbarui Aplikasimu
5.2.6.1 - Melakukan Pembaruan Bertahap
Tujuan
- Melakukan pembaruan bertahap (rolling update) menggunakan kubectl.
Memperbarui suatu aplikasi
Pengguna mengharapkan aplikasi tersedia sepanjang waktu dan pengembang bisa jadi diharapkan untuk men-deploy versi terbaru dari aplikasi tersebut beberapa kali dalam suatu waktu. Di Kubernetes hal ini dilakukan melalui pembaruan bertahap. Pembaruan bertahap memungkinkan pembaruan Deployment terjadi tanpa berhenti dengan memperbarui instans Pod secara bertahap dengan versi yang baru. Pod yang baru akan dijadwalkan pada Node dengan sumber daya yang tersedia.
Dalam modul sebelumnya kita telah melakukan penyekalaan aplikasi kita untuk menjalankan beberapa instans. Hal ini dibutuhkan untuk menjalankan pembaruan tanpa mempengaruhi ketersediaan aplikasi. Secara bawaan, jumlah maksimum dari Pod lama yang akan digantikan (menjadi tidak tersedia) selama pembaruan dan jumlah maksimum Pod baru yang dapat dibuat adalah satu. Kedua opsi ini dapat dikonfigurasi dengan angka atau persentase (dari Pod). Di Kubernetes, setiap pembaruan diberi versi masing-masing dan suatu pembaruan Deployment dapat dikembalikan ke versi sebelumnya (yang stabil).
Ringkasan:
- Memperbarui aplikasi
Pembaruan bertahap memungkinkan pembaruan Deployment terjadi tanpa berhenti dengan memperbarui instans Pod secara bertahap dengan versi yang baru.
Gambaran pembaruan bertahap
Seperti penyekalaan aplikasi, jika suatu Deployment terekspos secara publik, maka Service akan menyeimbangkan beban trafik hanya ke Pod yang tersedia saat pembaruan berlangsung. Pod yang tersedia adalah instans yang dapat diakses oleh pengguna aplikasi.
Pembaruan bertahap memungkinan dilakukannya aktivitas-aktivitas berikut:
- Mempromosikan suatu aplikasi dari satu environment yang ke environment yang lain (via pembaruan kontainer image)
- Kembali (rollback) ke versi-versi sebelumnya
- Continuous Integration dan Continuous Delivery (CI/CD) dari aplikasi tanpa henti
Jika suatu Deployment terekspos secara publik, maka Service akan menyeimbangkan beban trafik hanya ke Pod yang tersedia saat pembaruan berlangsung.
Pada tutorial interaktif berikut ini, kita akan mencoba untuk memperbarui aplikasi kita ke versi terbaru dan kemudian melakukan rollback.
5.2.6.2 - Tutorial Interaktif - Memperbarui Aplikasimu
5.3 - Aplikasi Stateless
5.3.1 - Mengekspos Alamat IP Eksternal untuk Mengakses Aplikasi di dalam Klaster
Dokumen ini menjelaskan bagaimana cara membuat objek Service Kubernetes yang mengekspos alamat IP eksternal.
Sebelum kamu memulai
-
Instal kubectl.
-
Gunakan sebuah penyedia layanan cloud seperti Google Kubernetes Engine atau Amazon Web Services untuk membuat sebuah klaster Kubernetes. Tutorial ini membuat sebuah load balancer eksternal, yang membutuhkan sebuah penyedia layanan cloud.
-
Konfigurasi
kubectl
agar dapat berkomunikasi dengan Kubernetes API Server kamu. Untuk informasi lebih lanjut, kamu dapat merujuk pada dokumentasi penyedia layanan cloud yang kamu gunakan.
Tujuan
- Jalankan lima buah instans dari aplikasi Hello World.
- Buatlah sebuah objek Service yang mengekspos sebuah alamat IP eksternal.
- Gunakan sebuah objek Service untuk mengakses aplikasi yang sedang dijalankan.
Membuat sebuah objek Service untuk sebuah aplikasi yang dijalankan pada lima buah Pod
- Jalankan sebuah aplikasi Hello World pada klaster kamu:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: load-balancer-example
name: hello-world
spec:
replicas: 5
selector:
matchLabels:
app.kubernetes.io/name: load-balancer-example
template:
metadata:
labels:
app.kubernetes.io/name: load-balancer-example
spec:
containers:
- image: gcr.io/google-samples/node-hello:1.0
name: hello-world
ports:
- containerPort: 8080
kubectl apply -f https://k8s.io/examples/service/load-balancer-example.yaml
Perintah di atas akan membuat sebuah objek Deployment dan sebuah objek ReplicaSet yang diasosiasikan dengan Deployment yang dibuat. ReplicaSet memiliki lima buah Pod, yang masing-masing dari Pod tersebut menjalankan aplikasi Hello World.
-
Tampilkan informasi mengenai Deployment:
kubectl get deployments hello-world kubectl describe deployments hello-world
-
Tampilkan informasi mengenai objek ReplicaSet:
kubectl get replicasets kubectl describe replicasets
-
Buatlah sebuah objek Service yang mengekspos deployment:
kubectl expose deployment hello-world --type=LoadBalancer --name=my-service
-
Tampilkan informasi mengenai Service:
kubectl get services my-service
Keluaran dari perintah di atas akan menyerupai tampilan berikut:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-service LoadBalancer 10.3.245.137 104.198.205.71 8080/TCP 54s
Catatan: Service dengantype=LoadBalancer
didukung oleh penyedia layanan cloud eksternal, yang tidak tercakup dalam contoh ini, silahkan merujuk pada laman berikut untuk informasi lebih lanjut.Catatan: Jika sebuah alamat IP eksternal yang ditunjukkan dalam status <pending>, tunggulah hingga satu menit kemudian masukkan perintah yang sama lagi. -
Tampilkan informasi detail mengenai Service:
kubectl describe services my-service
Perintah di atas akan menampilkan keluaran sebagai berikut:
Name: my-service Namespace: default Labels: app.kubernetes.io/name=load-balancer-example Annotations: <none> Selector: app.kubernetes.io/name=load-balancer-example Type: LoadBalancer IP: 10.3.245.137 LoadBalancer Ingress: 104.198.205.71 Port: <unset> 8080/TCP NodePort: <unset> 32377/TCP Endpoints: 10.0.0.6:8080,10.0.1.6:8080,10.0.1.7:8080 + 2 more... Session Affinity: None Events: <none>
Pastikan nilai dari alamat IP eksternal (
LoadBalancer Ingress
) diekspos pada Service yang kamu buat. Pada contoh ini, alamat IP eksternal yang diberikan adalah 104.198.205.71. Kemudian pastikan nilai dariPort
danNodePort
. Pada contoh ini,Port
yang digunakan adalah 8080 danNodePort
adalah 32377. -
Pada keluaran perintah sebelumnya, kamu dapat melihat beberapa Service dengan beberapa endpoint: 10.0.0.6:8080,10.0.1.6:8080,10.0.1.7:8080 + 2 lainnya. Berikut ini merupakan alamat IP dari Pod dimana aplikasi tersebut dijalankan. Untuk melakukan verifikasi alamat-alamat IP yang digunakan oleh Pod, masukkan perintah berikut:
kubectl get pods --output=wide
Keluaran yang diberikan akan menyerupai:
NAME ... IP NODE hello-world-2895499144-1jaz9 ... 10.0.1.6 gke-cluster-1-default-pool-e0b8d269-1afc hello-world-2895499144-2e5uh ... 10.0.1.8 gke-cluster-1-default-pool-e0b8d269-1afc hello-world-2895499144-9m4h1 ... 10.0.0.6 gke-cluster-1-default-pool-e0b8d269-5v7a hello-world-2895499144-o4z13 ... 10.0.1.7 gke-cluster-1-default-pool-e0b8d269-1afc hello-world-2895499144-segjf ... 10.0.2.5 gke-cluster-1-default-pool-e0b8d269-cpuc
-
Gunakan alamat IP eksternal (
LoadBalancer Ingress
) untuk mengakses aplikasi Hello World:curl http://<external-ip>:<port>
dimana
<external-ip>
adalah alamat IP eksternal (LoadBalancer Ingress
) dari Service kamu, dan<port>
adalah nilai dariPort
dari deskripsi Service kamu. Jika kamu menggunakan minikube, menuliskan perintahminikube service my-service
akan secara otomatis membuka aplikasi Hello World pada browser.Respons yang diberikan apabila permintaan ini berhasil adalah sebuah pesan sapaan:
Hello Kubernetes!
Bersihkan
Untuk menghapus Service, kamu dapat menggunakan perintah ini:
kubectl delete services my-service
Untuk menghapus Deployment, ReplicaSet, dan Pod-Pod yang digunakan untuk menjalankan aplikasi Hello World, kamu dapat memasukkan perintah berikut:
kubectl delete deployment hello-world
Selanjutnya
Pelajari lebih lanjut cara untuk menghubungkan aplikasi dengan berbagai Service.
5.4 - Aplikasi Stateful
5.4.1 - Dasar-dasar StatefulSet
Tutorial ini memberikan pengantar untuk manajemen aplikasi dengan StatefulSet. Di sini dicontohkan bagaimana cara untuk membuat, menghapus, melakukan penyekalaan, dan memperbarui Pod dari StatefulSet.
Sebelum kamu memulai
Sebelum memulai tutorial ini, kamu harus mengakrabkan dirimu dengan konsep-konsep Kubernetes sebagai berikut:
- Pod
- DNS klaster
- Service headless
- PersistentVolume
- Penyediaan PersistentVolume
- StatefulSet
- Alat baris perintah (command line tool) kubectl
Tujuan
StatefulSet ditujukan untuk digunakan dengan aplikasi-aplikasi stateful dan sistem terdistribusi. Akan tetapi, tata kelola aplikasi-aplikasi stateful dan sistem terdistribusi pada Kubernetes merupakan topik yang luas dan kompleks. Untuk menunjukkan fitur-fitur dasar dari StatefulSet dan tidak mencampuradukkan topik sebelum dan terakhir, kamu akan menggelar sebuah aplikasi web sederhana menggunakan StatefulSet.
Setelah tutorial ini, kamu akan akrab hal-hal berikut:
- Bagaimana cara membuat sebuah StatefulSet
- Bagaimana suatu StatefulSet mengelola Pod
- Bagaimana cara menghapus StatefulSet
- Bagaimana cara melakukan penyekalaan terhadap suatu StatefulSet
- Bagaimana cara memperbarui Pod dari StatefulSet
Membuat Sebuah StatefulSet
Mulailah dengan membuat sebuah Statefulset dengan menggunakan contoh di bawah ini.
Hal ini mirip dengan contoh yang ditunjukkan di dalam konsep
StatefulSet.
Contoh ini menciptakan sebuah
Service headless,
nginx
, untuk mempublikasikan alamat IP Pod di dalam StatefulSet, web
.
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
Unduh contoh di atas, dan simpan ke dalam berkas dengan nama web.yaml
.
Kamu perlu menggunakan dua jendela terminal. Pada terminal yang pertama, gunakan perintah
kubectl get
untuk mengamati
pembuatan Pod dari StatefulSet.
kubectl get pods -w -l app=nginx
Pada terminal yang kedua, gunakan
kubectl apply
untuk membuat
Service headless dan StatefulSet yang didefinisikan di dalam web.yaml
.
kubectl apply -f web.yaml
service/nginx created
statefulset.apps/web created
Perintah di atas menciptakan dua Pod, masing-masing menjalankan server web
NGINX. Dapatkan Service nginx
...
kubectl get service nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None <none> 80/TCP 12s
...kemudian dapatkan StatefulSet web
, untuk memastikan keduanya berhasil dibuat:
kubectl get statefulset web
NAME DESIRED CURRENT AGE
web 2 1 20s
Pembuatan Pod Berurutan
Untuk StatefulSet dengan n replika, ketika Pod sedang digelar, kesemuanya
akan dibuat secara berurutan, terurut dari {0..n-1}. Periksa keluaran dari
perintah kubectl get
pada terminal pertama. Pada akhirnya, keluaran yang dihasilkan
akan seperti contoh di bawah ini.
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 19s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 18s
Perhatikan Pod web-1
tidak dijalankan hingga web-0
berganti status menjadi Running
(lihat Fase Pod) dan Ready
(lihat type
di Kondisi Pod).
Pod pada StatefulSet
Pod pada StatefulSet memiliki satu indeks urutan unik dan satu identitas jaringan yang tetap.
Memeriksa Indeks Urutan Pod
Dapatkan Pod dari StatefulSet:
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 1m
web-1 1/1 Running 0 1m
Sebagaimana telah disebutkan di dalam konsep
StatefulSet,
Pod pada StatefulSet memiliki suatu identitas yang melekat (sticky) dan unik.
Identitas ini didasarkan pada sebuah indeks urutan yang unik yang di tetapkan
ke masing-masing Pod oleh pengontrol StatefulSet.
Nama Pod memiliki format <nama statefulset>-<indeks urutan>
.
Karena StatefulSet web
memiliki dua replika, maka ada dua Pod yang tercipta, web-0
dan web-1
.
Menggunakan Identitas Jaringan yang Tetap
Setiap Pod memiliki nama hos yang tetep berdasarkan indeks urutannya. Gunakan perintah
kubectl exec
untuk menjalankan
perintah hostname
di tiap Pod:
for i in 0 1; do kubectl exec "web-$i" -- sh -c 'hostname'; done
web-0
web-1
Gunakan perintah kubectl run
untuk
menjalankan sebuah Container yang menyediakan perintah nslookup
dari paket dnsutils
.
Dengan menjalankan perintah nslookup
dengan nama hos dari Pod, kamu dapat memeriksa alamat
DNS mereka di dalam klaster:
kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm
perintah itu akan memulai sebuah shell baru. Pada shell tersebut, jalankan:
# Jalankan ini di dalam shell Container dns-test
nslookup web-0.nginx
Keluarannya akan seperti:
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.6
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.6
(dan selanjutnya keluarlah dari shell Container dengan menjalankan: exit
)
CNAME dari headless service mengarah ke SRV record (satu untuk tiap Pod yang Running dan Ready). SRC record mengarah ke entri A record yang memuat alamat IP Pod.
Pada salah satu terminal, amati Pod dari StatefulSet:
kubectl get pod -w -l app=nginx
Pada terminal yang lain, gunakan perintah
kubectl delete
untuk menghapus
semua Pod pada StatefulSet:
kubectl delete pod -l app=nginx
pod "web-0" deleted
pod "web-1" deleted
Tunggu sampai StatefulSet menjalankan mereka kembali, dan untuk keduanya menjadi Running dan Ready:
kubectl get pod -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 ContainerCreating 0 0s
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 34s
Gunakan perintah kubectl exec
dan kubectl run
untuk menampilkan nama hos Pod
dan entri DNS mereka dalam klaster. Pertama-tama, tampilkan nama hos Pod:
for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done
web-0
web-1
selanjutnya, jalankan:
kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm /bin/sh
perintah itu akan menjalankan shell baru. Di dalam shell yang baru jalankan:
# Jalankan ini di dalam shell Container dns-test
nslookup web-0.nginx
Keluarannya akan seperti:
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.7
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.8
(dan selanjutnya keluarlah dari shell Container dengan menjalankan: exit
)
Urutan, nama hos, SRV record, dan nama A record dari Pod tidak berubah, akan tetapi alamat IP yang terkait dengan Pod bisa jadi mengalami perubahan. Pada klaster yang digunakan dalam tutorial ini terjadi perubahan. Karena itulah mengapa sangat penting untuk menghindari pengaturan terhadap aplikasi lain yang terhubung ke Pod di dalam StatefulSet menggunakan alamat IP.
Jika kamu ingin mencari dan terhubung dengan anggota aktif dari StatefulSet, kamu
perlu melakukan kueri CNAME dari Service headless (nginx.default.svc.cluster.local
).
SRV record yang terkait dengan CNAME hanya akan memuat Pod dari StatefulSet yang
Running dan Ready.
Jika aplikasimu telah menerapkan logika koneksi yang menguji keaktifan
(liveness) dan kesiapan (readiness), kamu dapat menggunakan SRV record dari Pod (
web-0.nginx.default.svc.cluster.local
,
web-1.nginx.default.svc.cluster.local
), karena mereka tidak akan berubah, dan
aplikasimu akan bisa menemukan alamat-alamat Pod ketika mereka mengalami peralihan
ke Running dan Ready.
Menulis ke Penyimpanan Tetap
Dapatkan PersistentVolumeClaim untuk web-0
dan web-1
:
kubectl get pvc -l app=nginx
Keluarannya akan seperti:
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO 48s
www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 48s
Pengontrol StatefulSet membuat dua PersistentVolumeClaim yang terikat ke dua PersistentVolume.
Karena klaster yang digunakan dalam tutorial ini dikonfigurasi untuk melakukan penyediaan PersistentVolume secara dinamis, maka PersistentVolume dibuat dan terikat secara otomatis.
Server web NGINX, secara bawaan, menyajikan berkas indeks dari
/usr/share/nginx/html/index.html
. Field volumeMounts
pada spec
StatefulSet
memastikan direktori /usr/share/nginx/html
didukung oleh sebuah PersistentVolume.
Tulis nama hos Pod ke dalam berkas index.html
mereka masing-masing dan periksa
apakah server web NGINX menyajikan nama hos tersebut:
for i in 0 1; do kubectl exec "web-$i" -- sh -c 'echo "$(hostname)" > /usr/share/nginx/html/index.html'; done
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
web-0
web-1
Jika kamu melihat respon 403 Forbidden untuk perintah curl di atas,
kamu perlu untuk memperbaiki izin (permission) dari direktori yang dipasang
oleh volumeMounts
(disebabkan oleh sebuah
bug ketika menggunakan volume hostPath),
dengan menjalankan:
for i in 0 1; do kubectl exec web-$i -- chmod 755 /usr/share/nginx/html; done
sebelum mencoba kembali perintah curl
di atas.
Di salah satu terminal, amati Pod dari StatefulSet:
kubectl get pod -w -l app=nginx
Di terminal yang lain, hapus semua Pod dari StatefulSet:
kubectl delete pod -l app=nginx
pod "web-0" deleted
pod "web-1" deleted
Periksa keluaran dari perintah kubectl get
pada terminal yang pertama dan tunggu
semua Pod berubah menjadi Running dan Ready.
kubectl get pod -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 ContainerCreating 0 0s
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 34s
Periksa apakah server web masih terus menyajikan nama hosnya:
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
web-0
web-1
Walaupun web-0
dan web-1
telah dijadwalkan ulang, mereka masih menyajikan
nama hos masing-masing karena PersistentVolume yang terkait dengan
PersistentVolumeClaim-nya dipasang kembali (remounted) ke setiap volumeMounts
.
Di Node manapun web-0
dan web-1
dijadwalkan, PersistentVolume-nya akan
dipasangkan ke titik pasang (mount point) yang sesuai.
Penyekalaan StatefulSet
Melakukan penyekalaan pada StatefulSet berarti meningkatkan atau mengurangi jumlah
replika. Hal ini dicapai dengan memperbarui field replicas
. Kamu dapat menggunakan
kubectl scale
atau
kubectl patch
untuk
melakukan penyekalaan terhadap StatefulSet.
Penyekalaan Naik
Pada salah satu jendela terminal, amati Pod pada StatefulSet:
kubectl get pods -w -l app=nginx
Di jendela terminal yang lain gunakan perintah kubectl scale
untuk melakukan
penyekalaan jumlah replika menjadi 5:
kubectl scale sts web --replicas=5
statefulset.apps/web scaled
Periksa keluaran dari perintah kubectl get
pada terminal pertama dan tunggu
tambahan tiga Pod yang baru berubah menjadi Running dan Ready.
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2h
web-1 1/1 Running 0 2h
NAME READY STATUS RESTARTS AGE
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 19s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 ContainerCreating 0 0s
web-3 1/1 Running 0 18s
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 1/1 Running 0 19s
Pengontrol StatefulSet telah melakukan penyekalaan terhadap jumlah replika. Sama seperti pembuatan StatefulSet, pengontrol StatefulSet membuat tiap Pod berurutan sesuai dengan indeks urutan masing-masing dan menunggu setiap Pod yang dibuat sebelumnya menjadi Running dan Ready sebelum menjalankan Pod berikutnya.
Penyekalaan Turun
Di salah satu terminal, amati Pod pada StatefulSet:
kubectl get pods -w -l app=nginx
Di terminal yang lain, gunakan perintah kubectl patch
untuk melakukan penyekalaan
StatefulSet turun menjadi tiga replika:
kubectl patch sts web -p '{"spec":{"replicas":3}}'
statefulset.apps/web patched
Tunggu hingga web-4
dan web-3
berubah menjadi Terminating.
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 3h
web-1 1/1 Running 0 3h
web-2 1/1 Running 0 55s
web-3 1/1 Running 0 36s
web-4 0/1 ContainerCreating 0 18s
NAME READY STATUS RESTARTS AGE
web-4 1/1 Running 0 19s
web-4 1/1 Terminating 0 24s
web-4 1/1 Terminating 0 24s
web-3 1/1 Terminating 0 42s
web-3 1/1 Terminating 0 42s
Penghentian Pod Berurutan
Pengontrol menghapus satu Pod dalam satu waktu, dengan urutan terbalik dari indeks urutannya, dan setiap Pod akan ditunggu sampai benar-benar mati terlebih dahulu sebelum menghapus Pod berikutnya.
Dapatkan PersistentVolumeClaim dari StatefulSet:
kubectl get pvc -l app=nginx
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-2 Bound pvc-e1125b27-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-3 Bound pvc-e1176df6-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-4 Bound pvc-e11bb5f8-b508-11e6-932f-42010a800002 1Gi RWO 13h
Di sana masih ada lima PersistentVolumeClaim dan lima PersistentVolume. Ketika mengeksplorasi penyimpanan tetap pada Pod, kita dapat melihat bahwa PersistentVolume yang terpasang pada Pod dari suatu StatefulSet tidak terhapus ketika Pod-nya dihapus. Hal ini tetap berlaku ketika penghapusan Pod terjadi karena penyekalaan turun pada suatu StatefulSet.
Memperbarui StatefulSet
Di Kubernetes 1.7 dan yang lebih baru, pengontrol StatefulSet mendukung
pembaruan otomatis. Strategi yang digunakan ditentukan oleh field
spec.updateStrategy
dari objek API StatefulSet. Fitur ini dapat digunakan untuk
memperbarui image Container, permintaan sumber daya dan/atau pembatasan, label,
dan anotasi Pod dalam suatu StatefulSet. Ada dua strategi pembaruan yang berlaku,
RollingUpdate
dan OnDelete
.
Pembaruan dengan RollingUpdate
adalah strategi bawaan untuk StatefulSet.
Pembaruan Bertahap (RollingUpdate)
Pembaruan dengan strategi RollingUpdate
akan memperbarui semua Pod di dalam
StatefulSet dalam urutan indeks terbalik, dengan tetap memperhatikan
jaminan dari StatefulSet.
Lakukan patch pada StatefulSet web
dengan menerapkan RollingUpdate
:
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}'
statefulset.apps/web patched
Pada salah satu jendela terminal, patch StatefulSet web
untuk mengubah
image Container lagi:
kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.8"}]'
statefulset.apps/web patched
Pada terminal yang lain, amati Pod pada StatefulSet:
kubectl get pod -l app=nginx -w
Keluarannya akan seperti:
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 7m
web-1 1/1 Running 0 7m
web-2 1/1 Running 0 8m
web-2 1/1 Terminating 0 8m
web-2 1/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 19s
web-1 1/1 Terminating 0 8m
web-1 0/1 Terminating 0 8m
web-1 0/1 Terminating 0 8m
web-1 0/1 Terminating 0 8m
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 6s
web-0 1/1 Terminating 0 7m
web-0 1/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 10s
Pod dalam StatefulSet diperbarui dengan urutan indeks terbalik. Pengontrol StatefulSet mengakhiri setiap Pod, dan menunggunya beralih menjadi Running dan Ready sebelum melakukan pembaruan ke Pod berikutnya. Sebagai catatan, walaupun pengontrol StatefulSet tidak akan melanjutkan pembaruan terhadap Pod berikutnya hingga penggantinya Running dan Ready, pengontrol akan memulihkan Pod apa pun yang mengalami kegagalan selama proses pembaruan berlangsung.
Pod yang telah menerima pembaruan akan dipulihkan ke versi yang diperbarui, sedangkan Pod yang belum menerima pembaruan akan dipulihkan ke versi sebelumnya. Dengan cara inilah pengontrol mencoba untuk terus mempertahankan kesehatan aplikasi dan pembaruan tetap konsisten ditengah adanya kemungkinan kegagalan intermiten.
Dapatkan Pod untuk melihat image Container-nya:
for p in 0 1 2; do kubectl get pod "web-$p" --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'; echo; done
k8s.gcr.io/nginx-slim:0.8
k8s.gcr.io/nginx-slim:0.8
k8s.gcr.io/nginx-slim:0.8
Semua Pod pada StatefulSet saat ini sedang menjalankan image Container sebelumnya.
kubectl rollout status sts/<name>
untuk menampilkan status pembaruan bertahap terhadap sebuah StatefulSet
Pembaruan dengan Staging
Kamu dapat melakukan staging terhadap suatu pembaruan StatefulSet dengan
menggunakan parameter partition
dari strategi pembaruan RollingUpdate
. Suatu
pembaruan yang di-staging akan akan mempertahankan semua Pod dalam StatefulSet
tersebut pada versi yang digunakan saat ini sembari mengizinkan terjadinya
perubahan pada .spec.template
dari StatefulSet.
Lakukan patch terhadap StatefulSet web
untuk menambahkan partisi pada
field updateStrategy
:
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}'
statefulset.apps/web patched
Lakukan patch terhadap StatefulSet lagi, untuk mengubah image Container:
kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"k8s.gcr.io/nginx-slim:0.7"}]'
statefulset.apps/web patched
Hapus sebuah Pod dari StatefulSet:
kubectl delete pod web-2
pod "web-2" deleted
Tunggu hingga Pod menjadi Running dan Ready.
kubectl get pod -l app=nginx -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 4m
web-1 1/1 Running 0 4m
web-2 0/1 ContainerCreating 0 11s
web-2 1/1 Running 0 18s
Dapatkan image Container Pod:
kubectl get pod web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
k8s.gcr.io/nginx-slim:0.8
Perhatikan, walaupun strategi pembaruan yang digunakan adalah RollingUpdate
,
StatefulSet mengembalikan Pod dengan Container-nya yang semula. Hal ini karena
urutan Pod kurang dari nilai partition
yang ditetapkan pada updateStrategy
.
Meluncurkan Canary
Kamu dapat meluncurkan canary untuk mencoba suatu perubahan dengan mengurangi
partition
yang kamu tentukan sebelumnya di atas.
Lakukan patch terhadap StatefulSet untuk mengurangi jumlah partisi:
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":2}}}}'
statefulset.apps/web patched
Tunggu hingga web-2
menjadi Running dan Ready.
kubectl get pod -l app=nginx -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 4m
web-1 1/1 Running 0 4m
web-2 0/1 ContainerCreating 0 11s
web-2 1/1 Running 0 18s
Dapatkan image Container Pod:
kubectl get pod web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
k8s.gcr.io/nginx-slim:0.7
Ketika kamu mengubah partition
, pengontrol StatefulSet secara otomatis memperbarui Pod
web-2
karena urutan dari Pod tersebut lebih besar dari atau sama dengan
nilai partition
.
Hapus Pod web-1
:
kubectl delete pod web-1
pod "web-1" deleted
Tunggu sampai Pod web-1
menjadi Running dan Ready.
kubectl get pod -l app=nginx -w
Keluarannya akan seperti:
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 6m
web-1 0/1 Terminating 0 6m
web-2 1/1 Running 0 2m
web-1 0/1 Terminating 0 6m
web-1 0/1 Terminating 0 6m
web-1 0/1 Terminating 0 6m
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 18s
Dapatkan image Container dari Pod web-1
:
kubectl get pod web-1 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
k8s.gcr.io/nginx-slim:0.8
web-1
dikembalikan ke konfigurasinya yang semula karena urutan Pod lebih kecil
dari partisi. Ketika partisi ditentukan, semua Pod dengan urutan yang lebih besar
dari atau sama dengan jumlah partisi akan diperbarui ketika .spec.template
dari
StatefulSet diubah. Jika suatu Pod yang memiliki urutan lebih kecil dari partisi
dihapus atau diakhiri, Pod tersebut akan dikembalikan ke konfigurasinya yang semula.
Peluncuran Bertahap
Kamu dapat melakukan peluncuran bertahap (misalkan peluncuran: linier, geometris, atau eksponensial)
dengan menggunakan pembaruan bertahap yang terpartisi dengan cara yang serupa
ketika kamu meluncurkan canary. Untuk melakukan peluncuran bertahap,
atur partition
ke urutan di mana kamu menginginkan pengontrol untuk melakukan
pause terhadap pembaruan.
Saat ini partisi sedang di atur menjadi 2
. Ganti partisi menjadi 0
:
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":0}}}}'
statefulset.apps/web patched
Tunggu semua Pod pada StatefulSet menjadi Running dan Ready.
kubectl get pod -l app=nginx -w
Keluarannya akan seperti:
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 3m
web-1 0/1 ContainerCreating 0 11s
web-2 1/1 Running 0 2m
web-1 1/1 Running 0 18s
web-0 1/1 Terminating 0 3m
web-0 1/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 3s
Dapatkan detail image Container dari Pod pada StatefulSet:
for p in 0 1 2; do kubectl get pod "web-$p" --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'; echo; done
k8s.gcr.io/nginx-slim:0.7
k8s.gcr.io/nginx-slim:0.7
k8s.gcr.io/nginx-slim:0.7
Dengan mengubah nilai partition
menjadi 0
, kamu mengizinkan StatefulSet
untuk melanjutkan proses pembaruan.
Pembaruan OnDelete
Strategi pembaruan OnDelete
menerapkan mekanisme lama (versi 1.6 dan sebelumnya).
Ketika kamu memilih strategi pembaruan ini, pengontrol StatefulSet tidak akan secara
otomatis melakukan pembaruan terhadap Pod ketika suatu perubahan terjadi pada field
.spec.template
pada StatefulSet. Strategi ini dapat dipilih dengan mengatur
.spec.template.updateStrategy.type
menjadi OnDelete
.
Menghapus StatefulSet
StatefulSet mendukung penghapusan tidak berjenjang (non-cascading) dan berjenjang (cascading). Dalam penghapusan tidak berjenjang (non-cascading delete), Pod pada StatefulSet tidak dihapus ketika StatefulSet terhapus. Pada penghapusan berjenjang (Cascading Delete), StatefulSet bersama Pod-nya dihapus semua.
Penghapusan Tidak Berjenjang (Non-Cascading)
Pada salah satu jendela terminal, amati Pod pada StatefulSet.
kubectl get pods -w -l app=nginx
Gunakan perintah kubectl delete
untuk menghapus StatefulSet. Pastikan kamu menambahkan parameter --cascade=orphan
ke
perintah tersebut. Parameter ini memberitahukan Kubernetes untuk hanya menghapus StatefulSet
dan agar tidak menghapus Pod yang ada padanya.
kubectl delete statefulset web --cascade=orphan
statefulset.apps "web" deleted
Dapatkan Pod untuk melihat statusnya masing-masing:
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 6m
web-1 1/1 Running 0 7m
web-2 1/1 Running 0 5m
Walaupun web
telah dihapus, semua Pod masih Running dan Ready.
Hapus web-0
:
kubectl delete pod web-0
pod "web-0" deleted
Dapatkan Pod dari StatefulSet:
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-1 1/1 Running 0 10m
web-2 1/1 Running 0 7m
Karena StatefulSet web
telah dihapus, maka web-0
tidak dijalankan lagi.
Di salah satu terminal, amati Pod pada StatefulSet.
kubectl get pods -w -l app=nginx
Pada terminal yang lain, buat kembali StatefulSet. Perhatikan, terkecuali
jika kamu telah menghapus Service ngingx
(yang seharusnya belum kamu lakukan),
kamu akan melihat sebuah galat yang mengindikasikan bahwa Service tersebut sudah ada.
kubectl apply -f web.yaml
statefulset.apps/web created
service/nginx unchanged
Abaikan galat yang terjadi. Hal itu hanya menunjukkan bahwa suatu upaya telah dilakukan
untuk membuat Service headless nginx
walaupun Service tersebut sebenarnya sudah ada.
Perhatikan keluaran dari perintah kubectl get
yang dijalankan pada terminal
yang pertama.
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-1 1/1 Running 0 16m
web-2 1/1 Running 0 2m
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 18s
web-2 1/1 Terminating 0 3m
web-2 0/1 Terminating 0 3m
web-2 0/1 Terminating 0 3m
web-2 0/1 Terminating 0 3m
Ketika StatefulSet web
dibuat ulang, yang dijalankan pertama kali adalah web-0
.
Karena web-1
telah menjadi Running dan Ready, ketika web-0
berubah menjadi
Running dan Ready, web-0
mengadopsi Pod tersebut. Karena kamu membuat ulang
StatefulSet dengan replicas
sama dengan 2, ketika web-0
selesai dibuat ulang, dan
ketika web-1
telah ditetapkan menjadi Running dan Ready, maka web-2
diakhiri.
Mari kita lihat kembali konten dari berkas index.html
yang disajikan oleh server
web Pod:
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
web-0
web-1
Walaupun kamu sebelumnya pernah menghapus StatefulSet dan Pod web-0
, server web
masih terus menyajikan nama hos sebelumnya yang dimasukkan ke dalam berkas
index.html
. Hal ini terjadi karena StatefulSet tidak menghapus PersistentVolume
yang terkait dengan Pod. Ketika kamu membuat ulang StatefulSet dan menjalankan
kembali web-0
, PersistentVolume yang digunakan sebelumnya akan dipasang kembali.
Penghapusan Berjenjang (Cascading)
Pada salah satu jendela terminal, amati Pod pada StatefulSet.
kubectl get pods -w -l app=nginx
Pada terminal yang lain, hapus StatefulSet lagi. Kali ini, hilangkan parameter
--cascade=orphan
.
kubectl delete statefulset web
statefulset.apps "web" deleted
Perhatikan keluaran dari perintah kubectl get
yang dijalankan di terminal
yang pertama, dan tunggu semua status Pod berubah menjadi Terminating.
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 11m
web-1 1/1 Running 0 27m
NAME READY STATUS RESTARTS AGE
web-0 1/1 Terminating 0 12m
web-1 1/1 Terminating 0 29m
web-0 0/1 Terminating 0 12m
web-0 0/1 Terminating 0 12m
web-0 0/1 Terminating 0 12m
web-1 0/1 Terminating 0 29m
web-1 0/1 Terminating 0 29m
web-1 0/1 Terminating 0 29m
Seperti yang telah kamu saksikan pada bagian Penyekalaan Turun, Pod diakhiri satu demi satu dengan urutan terbalik dari indeks urutan mereka. Sebelum mengakhiri suatu Pod, pengontrol StatefulSet menunggu Pod pengganti hingga benar-benar berakhir.
nginx
secara manual.
kubectl delete service nginx
service "nginx" deleted
Buat ulang StatefulSet dan Service headless sekali lagi:
kubectl apply -f web.yaml
service/nginx created
statefulset.apps/web created
Saat semua Pod StatefulSet mengalami transisi ke Running dan Ready, dapatkan
konten dari berkas index.html
masing-masing:
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
web-0
web-1
Walaupun kamu telah menghapus StatefulSet dan semua Pod di dalamnya, Pod dibuat
lagi dengan PersistentVolume yang sama terpasang, dan web-0
dan web-1
masih
menyajikan nama hos masing-masing.
Akhirnya, hapus Service nginx
...
kubectl delete service nginx
service "nginx" deleted
...dan StatefulSet web
:
kubectl delete statefulset web
statefulset "web" deleted
Kebijakan Manajemen Pod
Untuk beberapa sistem terdistribusi, jaminan pengurutan StatefulSet tidak
penting dan/atau tidak diharapkan. Sistem-sistem tersebut hanya membutuhkan
keunikan dan identitas. Untuk mengatasi ini, pada Kubernetes 1.7, kami
memperkenalkan .spec.podManagementPolicy
pada objek API StatefulSet.
Manajemen Pod OrderedReady
Manajemen Pod OrderedReady
adalah bawaan dari StatefulSet. Manajemen
dengan cara ini memberitahukan pengontrol StatefulSet untuk menghormati
jaminan pengurutan yang sudah ditunjukkan sebelumnya.
Manajemen Pod Parallel
Manajemen Pod Parallel
memberitahukan pengontrol StatefulSet untuk
menjalankan atau mengakhiri semua Pod secara bersamaan (paralel), dan tidak menunggu
suatu Pod menjadi Running dan Ready atau benar-benar berakhir sebelum menjalankan atau
mengakhiri Pod yang lain.
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
podManagementPolicy: "Parallel"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
Unduh contoh di atas, dan simpan ke sebuah berkas dengan nama web-parallel.yaml
.
Manifes ini serupa dengan yang telah kamu unduh sebelumnya kecuali .spec.podManagementPolicy
dari StatefulSet web
diatur ke Parallel
.
Di salah satu terminal, amati Pod pada StatefulSet.
kubectl get pod -l app=nginx -w
Pada terminal yang lain, buat StatefulSet dan Service dari manifes tadi:
kubectl apply -f web-parallel.yaml
service/nginx created
statefulset.apps/web created
Perhatikan keluaran dari perintah kubectl get
yang kamu jalankan pada
terminal yang pertama.
kubectl get pod -l app=nginx -w
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-1 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 10s
web-1 1/1 Running 0 10s
Pengontrol StatefulSet menjalankan web-0
dan web-
berbarengan.
Biarkan terminal kedua tetap terbuka, kemudian, di jendela terminal yang lain lakukan penyekalaan terhadap StatefulSet:
kubectl scale statefulset/web --replicas=4
statefulset.apps/web scaled
Perhatikan keluaran terminal di mana perintah kubectl get
dijalankan.
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 7s
web-3 0/1 ContainerCreating 0 7s
web-2 1/1 Running 0 10s
web-3 1/1 Running 0 26s
StatefulSet menjalankan dua Pod baru dan tidak menunggu Pod pertama menjadi Running dan Ready terlebih dahulu sebelum menjalankan Pod yang kedua.
Bersihkan
Kamu harus membuka dua terminal yang siap untuk menjalankan perintah kubectl
sebagai bagian dari pembersihan.
kubectl delete sts web
# sts adalah singkatan dari statefulset
Kamu dapat mengamati kubectl get
untuk melihat semua Pod yang sedang dihapus.
kubectl get pod -l app=nginx -w
web-3 1/1 Terminating 0 9m
web-2 1/1 Terminating 0 9m
web-3 1/1 Terminating 0 9m
web-2 1/1 Terminating 0 9m
web-1 1/1 Terminating 0 44m
web-0 1/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-3 0/1 Terminating 0 9m
web-2 0/1 Terminating 0 9m
web-1 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-2 0/1 Terminating 0 9m
web-2 0/1 Terminating 0 9m
web-2 0/1 Terminating 0 9m
web-1 0/1 Terminating 0 44m
web-1 0/1 Terminating 0 44m
web-1 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-3 0/1 Terminating 0 9m
web-3 0/1 Terminating 0 9m
web-3 0/1 Terminating 0 9m
Selama penghapusan, StatefulSet menghapus semua Pod secara serentak; tidak menghentikan Pod berdasarkan urutan indeksnya terlebih dahulu sebelum menghapus Pod tersebut.
Tutup terminal di mana perintah kubectl get
dijalankan dan hapus Service nginx
:
kubectl delete svc nginx
Kamu juga perlu menghapus media penyimpanan persisten untuk PersistentVolume yang digunakan dalam tutorial ini.
Ikuti langkah-langkah yang dibutuhkan, berdasarkan lingkungan yang kamu gunakan, konfigurasi penyimpanan, dan metode penyediaannya, untuk memastikan semua penyimpanan dapat dimanfaatkan lagi.
6 - Referensi
Bagian dari dokumentasi Kubernetes ini berisi referensi-referensi.
6.1 - Glosarium
6.2 - Mengakses API
6.2.1 - Menggunakan Otorisasi RBAC
Role-based access control (RBAC) atau kontrol akses berbasis rol adalah metode pengaturan akses ke sumber daya komputer atau jaringan berdasarkan rol pengguna individu dalam organisasimu.
Otorisasi RBAC menggunakan grup API rbac.authorization.k8s.io
untuk mengendalikan keputusan
otorisasi. Hal ini memungkinkanmu untuk mengonfigurasi kebijakan secara dinamis melalui
API Kubernetes.
Untuk mengaktifkan RBAC, jalankan server API dengan flag --authorization-mode
diatur
dengan daftar yang dipisahkan koma yang menyertakan RBAC
;
sebagai contoh:
kube-apiserver --authorization-mode=Example,RBAC --other-options --more-options
Objek API
API RBAC mendeklarasikan empat jenis objek Kubernetes: Role, ClusterRole,
RoleBinding dan ClusterRoleBinding. kamu bisa mendeskripsikan beberapa objek, atau mengubahnya menggunakan alat seperti kubectl
, seperti objek Kubernetes lain.
Role dan ClusterRole
Sebuah Role RBAC atau ClusterRole memuat aturan yang mewakili sekumpulan izin. Izin bersifat aditif (tidak ada aturan "tolak").
Sebuah Role selalu mengatur izin dalam Namespace tertentu; ketika kamu membuat Role, kamu harus menentukan Namespace tempat Role tersebut berada.
ClusterRole, sebaliknya, adalah sumber daya tanpa Namespace. Sumber daya tersebut memiliki nama yang berbeda (Role dan ClusterRole) karena objek Kubernetes selalu harus menggunakan Namespace atau tanpa Namespace; tidak mungkin keduanya.
ClusterRole memiliki beberapa kegunaan. Kamu bisa menggunakan ClusterRole untuk:
- mendefinisikan izin pada sumber daya dalam Namespace dan diberikan dalam sebuah Namespace atau lebih
- mendefinisikan izin pada sumber daya dalam Namespace dan diberikan dalam seluruh Namespace
- mendefinisikan izin pada sumber daya dalam lingkup klaster
Jika kamu ingin mendefinisikan sebuah rol dalam Namespace, gunakan Role; jika kamu ingin mendefinisikan rol di level klaster, gunakan ClusterRole.
Contoh Role
Berikut adalah contoh Role dalam Namespace bawaan yang dapat digunakan untuk memberikan akses baca pada Pod:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
Namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" mengindikasikan grup API inti
resources: ["pods"]
verbs: ["get", "watch", "list"]
Contoh ClusterRole
ClusterRole dapat digunakan untuk memberikan izin yang sama dengan Role. Karena ClusterRole memiliki lingkup klaster, kamu juga dapat menggunakannya untuk memberikan akses ke:
- sumber daya lingkup klaster (seperti Node)
- berbagai endpoint non-sumber daya (seperti
/healthz
) - sumber daya Namespace (seperti Pod), di semua Namespace
Sebagai contoh: kamu bisa menggunakan ClusterRole untuk memungkinkan pengguna tertentu untuk menjalankan
kubectl get pods --all-namespaces
.
Berikut adalah contoh ClusterRole yang dapat digunakan untuk memberikan akses baca pada Secret di Namespace tertentu, atau di semua Namespace (tergantung bagaimana keterikatannya):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" dihilangkan karena ClusterRole tidak menggunakan Namespace
name: secret-reader
rules:
- apiGroups: [""]
#
# di tingkat HTTP, nama sumber daya untuk mengakses objek Secret
# adalah "secrets"
resources: ["secrets"]
verbs: ["get", "watch", "list"]
Nama objek Role dan ClusterRole harus menggunakan nama path segment yang valid.
RoleBinding dan ClusterRoleBinding
Sebuah RoleBinding memberikan izin yang ditentukan dalam sebuah Role kepada pengguna atau sekelompok pengguna. Ini menyimpan daftar subjek (pengguna, grup, atau ServiceAccount), dan referensi ke Role yang diberikan. RoleBinding memberikan izin dalam Namespace tertentu sedangkan ClusterRoleBinding memberikan akses tersebut pada lingkup klaster.
RoleBinding dapat merujuk Role apa pun di Namespace yang sama. Atau, RoleBinding dapat mereferensikan ClusterRole dan memasangkan ClusterRole tersebut ke Namespace dari RoleBinding. Jika kamu ingin memasangkan ClusterRole ke semua Namespace di dalam klastermu, kamu dapat menggunakan ClusterRoleBinding.
Nama objek RoleBinding atau ClusterRoleBinding harus valid menggunakan nama path segment yang valid.
Contoh RoleBinding
Berikut adalah contoh dari RoleBinding yang memberikan Role "pod-reader" kepada pengguna "jane" pada Namespace "default". Ini memungkinkan "jane" untuk membaca Pod di Namespace "default".
apiVersion: rbac.authorization.k8s.io/v1
# RoleBinding memungkinkan "jane" untuk membaca Pod di Namespace "default"
# Kamu harus sudah memiliki Role bernama "pod-reader" di Namespace tersebut.
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# Kamu bisa mencantumkan lebih dari satu "subjek"
- kind: User
name: jane # "name" peka huruf besar-kecil
apiGroup: rbac.authorization.k8s.io
roleRef:
# "roleRef" menentukan pengikatan (binding) ke Role / ClusterRole
kind: Role # ini harus Role atau ClusterRole
name: pod-reader # ini harus sesuai dengan nama Role atau ClusterRole yang ingin kamu gunakan
apiGroup: rbac.authorization.k8s.io
RoleBinding juga bisa mereferensikan ClusterRole untuk memberikan izin yang didefinisikan di dalam ClusterRole ke sumber daya di dalam Namespace RoleBinding. Referensi semacam ini memungkinkan kamu menentukan sekumpulan Role yang umum di seluruh klastermu, lalu menggunakannya kembali di dalam beberapa Namespace.
Sebagai contoh, meskipun RoleBinding berikut merujuk ke ClusterRole, "dave" (subjek, peka kapital) hanya akan dapat membaca Secret di dalam Namespace "development", karena Namespace RoleBinding (di dalam metadatanya) adalah "development".
apiVersion: rbac.authorization.k8s.io/v1
# RoleBinding memungkinkan "dave" untuk membaca Secret di Namespace "development".
# Kamu sudah harus memiliki ClusterRole bernama "secret-reader".
kind: RoleBinding
metadata:
name: read-secrets
#
# Namespace dari RoleBinding menentukan di mana izin akan diberikan.
# Ini hanya memberikan izin di dalam Namespace "development".
namespace: development
subjects:
- kind: User
name: dave # Nama peka huruf besar-kecil
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
Contoh ClusterRoleBinding
Untuk memberikan izin di seluruh klaster, kamu dapat menggunakan ClusterRoleBinding. ClusterRoleBinding berikut memungkinkan seluruh pengguna di dalam kelompok "manager" untuk membaca Secret di berbagai Namespace.
apiVersion: rbac.authorization.k8s.io/v1
# ClusterRoleBinding ini memungkinkan siapapun di dalam kelompok "manager" untuk membaca Secret di berbagai Namespace.
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager # Nama peka kapital
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
Setelah kamu membuat ClusterRoleBinding, kamu tidak dapat mengganti Role atau ClusterRole yang dirujuk.
Jika kamu mencoba mengganti roleRef
dari sebuah ClusterRoleBinding, kamu akan mendapatkan galat validasi. Jika kamu
tidak ingin mengganti roleRef
untuk sebuah ClusterRoleBinding, kamu harus menghapus objek ClusterRoleBinding tersebut dan membuat
sebuah pengganti.
Ada dua alasan untuk pembatasan tersebut:
-
Membuat
roleRef
menjadi tidak dapat diubah (immutable) memungkinkan pemberian izinupdate
kepada seseorang pada objek ClusterRoleBinding yang ada, sehingga mereka dapat mengelola daftar subjek, tanpa bisa berubah Role yang diberikan kepada subjek tersebut. -
ClusterRoleBinding dengan Role yang berbeda adalah ClusterRoleBinding yang berbeda secara fundamental. Mengharuskan sebuah ClusterRoleBinding untuk dihapus/diciptakan kembali untuk mengubah
roleRef
akan memastikan daftar lengkap subjek dalam ClusterRoleBinding akan diberikan Role baru (sebagai langkah untuk mencegah modifikasi secara tidak sengaja hanya padaroleRef
tanpa memastikan semua subjek yang seharusnya diberikan izin pada Role baru).
Utilitas baris perintah kubectl auth reconcile
membuat atau memperbarui berkas manifes yang mengandung objek RBAC,
dan menangani penghapusan dan pembuatan objek ikatan jika dibutuhkan untuk mengganti Role yang dirujuk.
Lihat penggunaan perintah dan contoh untuk informasi tambahan.
Mengacu pada sumber daya
Pada API Kubernetes, sebagian besar sumber daya diwakili dan diakses menggunakan representasi
nama objek, seperti pods
untuk Pod. RBAC mengacu pada sumber daya yang menggunakan nama yang persis sama
dengan yang muncul di URL untuk berbagai endpoint API yang relevan.
Beberapa Kubernetes APIs melibatkan
subresource, seperti log untuk Pod. Permintaan untuk log Pod terlihat seperti:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
Dalam hal ini, pods
adalah sumber daya Namespace untuk sumber daya Pod, dan log
adalah sebuah
sub-sumber daya pods
. Untuk mewakili ini dalam sebuah Role RBAC, gunakan garis miring (/
) untuk
membatasi sumber daya dan sub-sumber daya. Untuk memungkinkan subjek membaca pods
dan
juga mengakses sub-sumber daya log
untuk masing-masing Pod tersebut, kamu dapat menulis:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list"]
Kamu juga dapat merujuk ke sumber daya dengan nama untuk permintaan tertentu melalui daftar resourceNames
.
Ketika nama dicantumkan, permintaan dapat dibatasi untuk setiap objek sumber daya.
Berikut adalah contoh yang membatasi subjeknya hanya untuk melakukan get
atau update
pada sebuah
ConfigMap bernama my-configmap
:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
#
# pada level HTTP, nama sumber daya untuk mengakses objek ConfigMap
# adalah "configmaps"
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]
create
atau deletecollection
dengan nama sumber daya. Untuk create
,
keterbatasan ini dikarenakan nama objek tidak diketahui pada waktu otorisasi.
ClusterRole gabungan
Kamu dapat mengumpulkan beberapa ClusterRole menjadi satu ClusterRole gabungan.
Pengontrol, yang berjalan sebagai bagian dari control plane klaster, mengamati objek ClusterRole
dengan aggregationRule
. AggregationRule
mendefinisikan
Selector label yang digunakan oleh pengontrol untuk mencocokkan objek ClusterRole lain
yang harus digabungkan ke dalam rules
.
Berikut adalah contoh ClusterRole gabungan:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # Control plane secara otomatis mengisi rules
Jika kamu membuat ClusterRole baru yang cocok dengan label Selector dari ClusterRole gabungan yang ada,
maka perubahan itu akan memicu penambahan aturan baru ke dalam ClusterRole gabungan.
Berikut adalah contoh yang menambahkan aturan ke ClusterRole "monitoring", dengan membuat sebuah
ClusterRole lain berlabel rbac.example.com/aggregate-to-monitoring: true
.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-endpoints
labels:
rbac.example.com/aggregate-to-monitoring: "true"
# ketika kamu membuat ClusterRole "monitoring-endpoints",
# aturan di bawah ini akan ditambahkan ke ClusterRole "monitoring".
rules:
- apiGroups: [""]
resources: ["services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
Role bawaan pengguna menggunakan agregasi ClusterRole. Ini memungkinkan kamu, sebagai administrator klaster, menambahkan aturan untuk sumber daya ubah suai, seperti yang dilayani oleh CustomResourceDefinitions atau server API gabungan, untuk memperluas Role bawaan.
Sebagai contoh: ClusterRole berikut mengizinkan Role bawaan "admin" dan "edit" mengelola sumber daya ubah suai
bernama CronTab, sedangkan Role "view" hanya dapat membaca sumber daya CronTab.
Kamu dapat mengasumsikan bahwa objek CronTab dinamai "crontab"
dalam URL yang terlihat oleh server API.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: aggregate-cron-tabs-edit
labels:
# Tambahkan izin berikut ke Role bawaan "admin" and "edit".
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rules:
- apiGroups: ["stable.example.com"]
resources: ["crontabs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: aggregate-cron-tabs-view
labels:
# Tambahkan izin berikut ke Role bawaan "view"
rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["stable.example.com"]
resources: ["crontabs"]
verbs: ["get", "list", "watch"]
Contoh Role
Contoh berikut adalah potongan dari objek Role atau ClusterRole yang hanya menampilkan
bagian rules
.
Mengizinkan pembacaan sumber daya "pods"
pada grup API inti:
rules:
- apiGroups: [""]
#
# pada tingkat HTTP, nama dari sumber daya untuk mengakses objek Pod
# adalah "pods"
resources: ["pods"]
verbs: ["get", "list", "watch"]
Mengizinkan pembacaan/penulisan Deployment (pada tingkat HTTP: objek dengan "deployments"
di bagian sumber daya dari URL) pada masing-masing grup API "extensions"
dan "apps"
:
rules:
- apiGroups: ["extensions", "apps"]
#
# pada tingkat HTTP, nama dari sumber daya untuk mengakses objek Deployment
# adalah "deployments"
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
Mengizinkan pembacaan pada Pods pada grup API inti, dan juga serta pembacaan atau penulisan Job
di grup API "batch"
atau "extensions"
:
rules:
- apiGroups: [""]
#
# pada tingkat HTTP, nama dari sumber daya untuk mengakses objek Pod
# adalah "pods"
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
#
# pada tingkat HTTP, nama dari sumber daya untuk mengakses objek Job
# adalah "jobs"
resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
Mengizinkan pembacaan ConfigMap bernama "my-config" (harus terikat dengan suatu RoleBinding untuk membatasi ke satu ConfigMap di satu Namespace):
rules:
- apiGroups: [""]
#
# pada tingkat HTTP, nama dari sumber daya untuk mengakses objek ConfigMap
# adalah "configmaps"
resources: ["configmaps"]
resourceNames: ["my-config"]
verbs: ["get"]
Mengizinkan pembacaan sumber daya "nodes"
pada grup API inti (karena sebuah node
ada pada lingkup-klaster, ini harus berupa ClusterRole yang terikat dengan ClusterRoleBinding
agar efektif):
rules:
- apiGroups: [""]
#
# pada tingkat HTTP, nama dari sumber daya untuk mengakses objek Node
# adalah "nodes"
resources: ["nodes"]
verbs: ["get", "list", "watch"]
Mengizinkan permintaan GET dan POST kepada endpoint non-sumber daya /healthz
dan seluruh subpath
(harus berada di dalam ClusterRole yang terikat dengan ClusterRoleBinding agar efektif):
rules:
- nonResourceURLs: ["/healthz", "/healthz/*"] # '*' in a nonResourceURL is a suffix glob match
verbs: ["get", "post"]
Mengacu pada subjek
RoleBinding atau ClusterRoleBinding mengikat sebuah Role ke subjek. Subjek dapat berupa kelompok, pengguna atau ServiceAccounts.
Kubernetes merepresentasikan username sebagai string. Ini bisa berupa: nama sederhana, seperti "alice"; email, seperti "[email protected]"; atau ID pengguna numerik yang direpresentasikan sebagai string. Terserah kamu sebagai administrator klaster untuk mengonfigurasi modul otentikasi sehingga otentikasi menghasilkan username dalam format yang kamu inginkan.
system:
direservasi untuk sistem Kubernetes, jadi kamu harus memastikan
bahwa kamu tidak memiliki pengguna atau grup dengan nama yang dimulai dengan system:
secara tidak sengaja.
Selain prefiks khusus ini, sistem otorisasi RBAC tidak memerlukan format apa pun
untuk nama pengguna.
Di Kubernetes, modul otentikasi menyediakan informasi grup.
Grup, seperti halnya pengguna, direpresentasikan sebagai string, dan string tersebut tidak memiliki format tertentu,
selain prefiks system:
yang sudah direservasi.
ServiceAccount memiliki nama yang diawali dengan system:serviceaccount:
, dan menjadi milik grup yang diawali dengan nama system:serviceaccounts:
.
system:serviceaccount:
(tunggal) adalah prefiks untuk username ServiceAccount.system:serviceaccounts:
(jamak) adalah prefiks untuk grup ServiceAccount.
Contoh RoleBinding
Contoh-contoh berikut ini hanya potongan RoleBinding yang hanya memperlihatkan
bagian subjects
.
Untuk pengguna bernama [email protected]
:
subjects:
- kind: User
name: "[email protected]"
apiGroup: rbac.authorization.k8s.io
Untuk grup bernama frontend-admins
:
subjects:
- kind: Group
name: "frontend-admins"
apiGroup: rbac.authorization.k8s.io
Untuk ServiceAccount bawaan di Namespace "kube-system":
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
Untuk seluruh ServiceAccount di Namespace qa:
subjects:
- kind: Group
name: system:serviceaccounts:qa
apiGroup: rbac.authorization.k8s.io
Untuk seluruh ServiceAccount di Namespace apapun:
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
Untuk seluruh pengguna yang terotentikasi:
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
Untuk seluruh pengguna yang tidak terotentikasi:
subjects:
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
Untuk seluruh pengguna:
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
Role dan RoleBinding bawaan
API membuat satu set objek ClusterRole dan ClusterRoleBinding bawaan.
Sebagian besar dari objek dengan prefiks system:
menunjukkan bahwa sumber daya tersebut
secara langsung dikelola oleh control plane klaster. Seluruh ClusterRole dan ClusterRoleBinding dilabeli dengan
kubernetes.io/bootstrapping=rbac-defaults
.
system:
.
Modifikasi sumber daya ini dapat mengakibatkan malfungsi klaster.
Rekonsiliasi otomatis
Pada setiap penyalaan (start-up), server API memperbarui ClusterRole bawaan dengan berbagai izin yang hilang, dan memperbarui ClusterRoleBinding bawaan dengan subjek yang hilang. Ini memungkinkan klaster untuk memperbaiki modifikasi yang tidak disengaja, dan membantu menjaga Role dan RoleBinding selalu terkini karena izin dan subjek berubah pada rilis terbaru Kubernetes.
Untuk menonaktifkan rekonsiliasi ini, atur anotasi rbac.authorization.kubernetes.io/autoupdate
pada ClusterRole bawaan atau RoleBinding bawaan menjadi false
.
Ingat bahwa hilangnya izin dan subjek bawaan dapat mengakibatkan malfungsi klaster.
Rekonsiliasi otomatis diaktifkan secara bawaan jika pemberi otorisasi RBAC aktif.
Role diskoveri API
RoleBinding bawaan memberi otorisasi kepada pengguna yang tidak terotentikasi untuk membaca informasi API yang dianggap aman
untuk diakses publik (termasuk CustomResourceDefinitions). Untuk menonaktifkan akses anonim, tambahkan --anonymous-auth=false
ke konfigurasi server API.
Untuk melihat konfigurasi Role ini melalui kubectl
jalankan perintah:
kubectl get clusterroles system:discovery -o yaml
ClusterRole Bawaan | ClusterRoleBinding Bawaan | Deskripsi |
---|---|---|
system:basic-user | Grup system:authenticated | Mengizinkan pengguna hanya dengan akses baca untuk mengakses informasi dasar tentang diri mereka sendiri. Sebelum v1.14, Role ini juga terikat pada system:unauthenticated secara bawaan. |
system:discovery | Grup system:authenticated | Mengizinkan akses baca pada berbagai endpoint diskoveri API yang dibutuhkan untuk menemukan dan melakukan negosiasi pada tingkat API. Sebelum v1.14, Role ini juga terikat pada system:unauthenticated secara bawaan. |
system:public-info-viewer | Grup system:authenticated dan system:unauthenticated | Mengizinkan akses baca pada informasi yang tidak sensitif tentang klaster. Diperkenalkan pada Kubernetes v1.14. |
Role pengguna
Beberapa ClusterRole bawaan tidak diawali dengan system:
. Ini dimaksudkan untuk Role pengguna.
Ini termasuk Role super-user (cluster-admin
), Role yang dimaksudkan untuk diberikan akses seluruh klaster dengan
menggunakan ClusterRoleBinding, dan Role yang dimaksudkan untuk diberikan pada Namespace tertentu
dengan menggunakan RoleBinding (admin
, edit
, view
).
ClusterRole menggunakan ClusterRole gabungan untuk mengizinkan administrator untuk memasukan peraturan untuk sumber daya khusus pada ClusterRole ini. Untuk menambahkan aturan kepada Role admin
, edit
, atau view
, buatlah sebuah CLusterRole
dengan satu atau lebih label berikut:
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
ClusterRole Bawaan | ClusterRoleBinding Bawaan | Deskripsi |
---|---|---|
cluster-admin | Grup system:masters | Mengizinkan akses super-user untuk melakukan berbagai aksi pada berbagai sumber daya. Ketika digunakan pada ClusterRoleBinding, Role ini akan memberikan kendali penuh terhadap semua sumber daya pada klaster dan seluruh Namespace. Ketika digunakan pada RoleBinding, Role ini akan memberikan kendali penuh terhadap setiap sumber daya pada Namespace RoleBinding, termasuk Namespace itu sendiri. |
admin | Tidak ada | mengizinkan akses administrator, yang dimaksudkan untuk diberikan dalam sebuah Namespace menggunakan RoleBinding. Jika digunakan dalam RoleBinding, ini memungkikan akses baca/tulis ke sebagian besar sumber daya di sebuah Namespace, termasuk kemampuan untuk membuat Role dan RoleBinding dalam Namespace. Role ini tidak memungkinkan akses tulis pada kuota sumber daya atau ke Namespace itu sendiri. |
edit | Tidak ada | Mengizinkan akses baca/tulis pada seluruh objek dalam Namespace.
Role ini tidak memungkinkan untuk melihat dan mengubah Role dan RoleBinding. Namun, Role ini memungkinkan untuk mengakses Secret dan menjalankan Pod seperti ServiceAccount dalam Namespace, sehingga dapat digunakan untuk mendapatkan tingkat akses API dari setiap ServiceAccount di Namespace. |
view | Tidak ada | Mengizinkan akses baca untuk melihat hampir seluruh objek dalam Namespace.
Ini tidak memungkinkan untuk melihat Role dan RoleBinding. Role ini tidak memungkikan melihat Secret, karena pembacaan konten Secret memungkinkan akses ke kredensial ServiceAccount dalam Namespace, yang akan memungkinkan akses API sebagai ServiceAccount apapun di Namespace (bentuk eskalasi privilese). |
Role komponen inti
ClusterRole Bawaan | ClusterRoleBinding Bawaan | Deskripsi |
---|---|---|
system:kube-scheduler | Pengguna system:kube-scheduler | Mengizinkan akses ke sumber daya yang dibutuhkan oleh komponen kube-scheduler. |
system:volume-scheduler | Pengguna system:kube-scheduler | Mengizinkan akses ke sumber daya volume yang dibutuhkan oleh komponen kube-scheduler. |
system:kube-controller-manager | Pengguna system:kube-controller-manager | Mengizinkan akses ke sumber daya yang dibutuhkan oleh komponen kube-controller-manager. Izin yang diperlukan oleh masing-masing pengontrol dirincikan di Role pengontrol. |
system:node | Tidak ada | Mengizinkan akses ke sumber daya yang dibutuhkan oleh kubelet, termasuk akses baca ke semua Secret, dan akses rulis ke semua objek status Pod.
Kamu dapat menggunakan pemberi otorisasi Node dan pugasan admisi NodeRestriction daripada Role system:node, dan mengizinkan pemberian akses API ke kubelet berdasarkan Pod yang dijadwalkan untuk berjalan di atasnya. Role system:node hanya ada untuk kompatibilitas dengan klaster Kubernetes yang ditingkatkan dari versi sebelum v1.8. |
system:node-proxier | Pengguna system:kube-proxy | Mengizinkan akses ke sumber daya yang dibutuhkan oleh komponen kube-proxy. |
Role komponen lainnya
ClusterRole Bawaan | ClusterRoleBinding Bawaan | Deskripsi |
---|---|---|
system:auth-delegator | Tidak ada | Mengizinkan pemeriksaan otentikasi dan otorisasi yang didelegasikan. Hal ini umumnya digunakan oleh pugasan server API untuk otentikasi dan otorisasi terpadu. |
system:heapster | Tidak ada | Role untuk komponen Heapster (usang). |
system:kube-aggregator | Tidak ada | Role untuk komponen kube-aggregator. |
system:kube-dns | ServiceAccount kube-dns dalam Namespace kube-system | Role untuk komponen kube-dns. |
system:kubelet-api-admin | Tidak ada | Mengizinkan akses penuh ke API kubelet. |
system:node-bootstrapper | Tidak ada | Mengizinkan akses ke sumber daya yang dibutuhkan untuk melakukan bootstrapping TLS kubelet. |
system:node-problem-detector | Tidak ada | Role untuk komponen node-problem-detector. |
system:persistent-volume-provisioner | Tidak ada | Mengizinkan akses ke sumber daya yang dibutuhkan oleh kebanyakan penyedia volume dinamis. |
Role untuk pengontrol bawaan
kube-controller-manager
pada Kubernetes menjalankan pengontrol
yang merupakan bawaan dari control plane Kubernetes. Ketika dijalankan dengan
--use-service-account-credentials
, kube-controller-manager memulai setiap pengontrol
menggunakan ServiceAccount yang terpisah. Role yang sesuai tersedia untuk setiap
pengontrol bawaan, dengan prefiks system:controller:
. Jika manajer pengontrol tidak
dimulai dengan --use-service-account-credentials
, maka manajer pengontrol akan menjalankan
semua kontrol tertutup (control loop) menggunakan kredensialnya sendiri, yang harus
diberikan semua Role yang relevan. Role yang dimaksud termasuk:
system:controller:attachdetach-controller
system:controller:certificate-controller
system:controller:clusterrole-aggregation-controller
system:controller:cronjob-controller
system:controller:daemon-set-controller
system:controller:deployment-controller
system:controller:disruption-controller
system:controller:endpoint-controller
system:controller:expand-controller
system:controller:generic-garbage-collector
system:controller:horizontal-pod-autoscaler
system:controller:job-controller
system:controller:namespace-controller
system:controller:node-controller
system:controller:persistent-volume-binder
system:controller:pod-garbage-collector
system:controller:pv-protection-controller
system:controller:pvc-protection-controller
system:controller:replicaset-controller
system:controller:replication-controller
system:controller:resourcequota-controller
system:controller:root-ca-cert-publisher
system:controller:route-controller
system:controller:service-account-controller
system:controller:service-controller
system:controller:statefulset-controller
system:controller:ttl-controller
Pencegahan eskalasi privilese dan bootstrapping
API RBAC mencegah pengguna dari mengeskalasikan privilese dengan mengubah Role atau RoleBinding. Karena hal ini diberlakukan pada level API, maka hal ini berlaku bahkan ketika pemberi otorisasi RBAC tidak digunakan.
Pembatasan pada pembuatan dan pembaruan Role
Kamu hanya bisa membuat/memperbaru suatu Role jika setidaknya satu dari beberapa hal di bawah ini terpenuhi:
- Kamu telah mempunyai semua izin yang termuat dalam Role tersebut, pada lingkup yang sama dengan objek yang diubah (di seluruh klaster untuk sebuah ClusterRole, di dalam Namespace yang sama atau keseluruhan klaster untuk sebuah Role).
- Kamu diberikan izin eksplisit untuk melakukan
escalate
pada sumber dayaroles
atauclusterroles
di dalam grup APIrbac.authorization.k8s.io
.
Sebagai contoh, jika user-1
tidak memiliki kemampuan untuk mendaftar Secret di seluruh klaster,
maka user-1
tidak akan bisa membuat suatu ClusterRole yang memuat izin tersebut. Agar pengguna
bisa membuat/memperbaru Role:
- Berikan sebuah Role yang memungkinkan mereka untuk membuat/memperbarui objek Role atau CLusterRole, sesuai keinginan.
- Berikan mereka izin untuk menyertakan izin tertentu dalam Role yang mereka buat/perbarui:
- secara implisit, dengan memberikan mereka izin tersebut (jika mereka mencoba untuk membuat atau mengubah sebuah Role atau ClusterRole dengan izin yang tidak mereka miliki, permintaan API akan dilarang)
- atau secara eksplisit mengizinkan penentuan izin apa pun dalam sebuah
Role
atauClusterRole
dengan memberikan mereka izin untuk melakukanescalate
pada sumber dayaroles
atauclusterroles
di dalam grup APIrbac.authorization.k8s.io
Pembatasan pada pembuatan dan pembaruan RoleBinding
Kamu hanya bisa membuat/memperbarui suatu RoleBinding jika kamu telah mempunyai semua izin yang
terdapat pada Role yang diacu (di dalam lingkup yang sama dengan RoleBinding) atau jika
kamu telah terotorisasi untuk melakukan bind
pada role yang diacu.
Sebagai contoh, jika user-1
tidak mempunyai kemampuan untuk mendaftar Secret di seluruh klaster,
maka user-1
tidak akan bisa membuat sebuah ClusterRoleBinding dengan Role yang memberikan
izin tersebut. Agar pengguna bisa membuat/memperbarui RoleBinding:
- Berikan sebuah Role yang mengizinkan mereka untuk membuat/memperbarui objek RoleBinding atau ClusterRoleBinding, sesuai keinginan.
- Berikan mereka izin yang dibutuhkan untuk RoleBinding tertentu:
- secara implisit, dengan memberikan mereka izin yang yang termuat pada Role yang dimaksud
- secara eksplisit, dengan memberikan mereka izin untuk melakukan
bind
pada Role (atau ClusterRole) tertentu
Sebagai contoh, ClusterRole dan RoleBinding berikut akan memungkinkan user-1
untuk memberikan Role admin
, edit
, dan view
kepada pengguna lain di dalam Namespace user-1-namespace
:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: role-grantor
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["rolebindings"]
verbs: ["create"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles"]
verbs: ["bind"]
resourceNames: ["admin","edit","view"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: role-grantor-binding
namespace: user-1-namespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: role-grantor
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: user-1
Ketika melakukan bootstrapping Role dan RoleBinding yang pertama, pengguna awal perlu memberikan izin yang belum mereka miliki. Untuk melakukan bootstrapping Role dan RoleBinding awal:
- Gunakan kredensial dengan grup "system:masters" yang terikat ke Role super-user "cluster-admin" oleh RoleBinding bawaan.
- Jika server API dijalankan dengan porta tidak aman diaktifkan (
--insecure-port
), kamu juga bisa membuat panggilan API via porta tersebut, yang tidak memberlakukan otentikasi atau otorisasi.
Utilitas baris perintah
kubectl create role
Membuat sebuah objek Role yang mendefinisikan izin di dalam sebuah Namespace. Contoh:
-
Membuat sebuah Role bernama "pod-reader" yang memungkinkan pengguna untuk melakukan
get
,watch
danlist
pada Pod:kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
-
Membuat sebuah Role bernama "pod-reader" dengan resourceNames yang ditentukan:
kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
-
Membuat sebuah Role bernama "foo" dengan apiGroups yang ditentukan:
kubectl create role foo --verb=get,list,watch --resource=replicasets.apps
-
Membuat sebuah Role bernama "foo" dengan izin sub-sumber daya:
kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
-
Membuat sebuah Role bernama "my-component-lease-holder" dengan izin untuk mendapatkan/memperbarui suatu sumber daya dengan nama tertentu:
kubectl create role my-component-lease-holder --verb=get,list,watch,update --resource=lease --resource-name=my-component
kubectl create clusterrole
Membuat sebuah ClusterRole. Contoh:
-
Membuat sebuah ClusterRole bernama "pod-reader" yang memungkinkan pengguna untuk merlakukan
get
,watch
danlist
pada Pod:kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods
-
Membuat sebuah ClusterRole bernama "pod-reader" dengan recourceNames yang ditentukan:
kubectl create clusterrole pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
-
Membuat sebuah ClusterRole bernama "foo" dengan apiGroups yang ditentukan:
kubectl create clusterrole foo --verb=get,list,watch --resource=replicasets.apps
-
Membuat sebuah ClusterRole bernama "foo" dengan izin sub-sumber daya:
kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status
-
Membuat sebuah ClusterRole bernama "foo" dengan nonResourceURL yang ditentukan:
kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*
-
Membuat sebuah ClusterRole bernama "monitoring" dengan aggregationRule yang ditentukan:
kubectl create clusterrole monitoring --aggregation-rule="rbac.example.com/aggregate-to-monitoring=true"
kubectl create rolebinding
Memberikan sebuah Role atau ClusterRole di dalam Namespace tertentu. Contoh:
-
Di dalam Namespace "acme", memberikan izin dalam ClusterRole "admin" kepada pengguna bernama "bob":
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
-
Di dalam Namespace "acme", memberikan izin dalam ClusterRole "view" ke ServiceAccount di dalam Namespace "acme" yang bernama "myapp":
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
-
Di dalam Namespace "acme", memberikan izin dalam ClusterRole "view" ke ServiceAccount di dalam Namespace "myappnamespace" yang bernama "myapp":
kubectl create rolebinding myappnamespace-myapp-view-binding --clusterrole=view --serviceaccount=myappnamespace:myapp --namespace=acme
kubectl create clusterrolebinding
Memberikan sebuah ClusterRole di seluruh klaster (semua Namespace). Contoh:
-
Di seluruh klaster, memberikan izin dalam ClusterRole "cluster-admin" kepada pengguna bernama "root":
kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
-
Di seluruh klaster, memberikan izin dalam ClusterRole "system:node-proxier" kepada user bernama "system:kube-proxy":
kubectl create clusterrolebinding kube-proxy-binding --clusterrole=system:node-proxier --user=system:kube-proxy
-
Di seluruh klaster, memberikan izin dalam ClusterRole "view" ke ServiceAccount bernama "myapp" di dalam Namespace "acme":
kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
kubectl auth reconcile
Membuat atau memperbarui objek API rbac.authorization.k8s.io/v1
dari suatu berkas manifes.
Objek yang hilang dibuat, dan Namespace dibuat untuk objek dengan Namespace jika diperlukan.
Role yang sudah ada diperbarui untuk menyertakan izin pada objek masukan,
dan menghilangkan izin tambahan jika --remove-extra-permissions
ditetapkan.
RoleBinding yang sudah ada diperbarui untuk menyertakan subjek pada objek masukan,
dan menghapus subjek tambahan jika --remove-extra-subjects
ditetapkan.
Contoh:
-
Mencoba menerapkan sebuah berkas manifes dari objek RBAC, menampilkan perubahan yang akan dibuat:
kubectl auth reconcile -f my-rbac-rules.yaml --dry-run=client
-
Menerapkan sebuah berkas manifes dari objek RBAC, mempertahankan izin tambahan (dalam Role) dan subjek tambahan (dalam RoleBinding):
kubectl auth reconcile -f my-rbac-rules.yaml
-
Menerapkan sebuah berkas manifes dari objek RBAC, menghapus izin tambahan (dalam Role) dan subjek tambahan (dalam RoleBinding):
kubectl auth reconcile -f my-rbac-rules.yaml --remove-extra-subjects --remove-extra-permissions
Izin ServiceAccount
Kebijakan RBAC bawaan memberikan izin terbatas ke komponen control plane, Node, dan pengontrol,
akan tetapi tidak memberikan izin ke ServiceAccount di luar Namespace kube-system
(di luar izin diskoveri yang diberikan kepada semua pengguna terotentikasi).
Hal ini memungkinkan kamu untuk memberika Role tertentu ke ServiceAccount tertentu sesuai kebutuhan. RoleBinding yang sangat detail memberikan keamanan yang lebih baik, akan tetapi membutuhkan lebih banyak usaha untuk pengaturannya. Pemberian izin yang lebih luas dapat memberikan akses API yang tidak perlu (dan berpotensi tereskalasi) ke ServiceAccount, akan tetapi pengaturannya lebih mudah.
Dalam urutan dari yang paling aman ke yang paling tidak aman, pendekatannya adalah:
-
Memberikan sebuah Role ke ServiceAccount aplikasi tertentu (praktik terbaik)
Hal ini membutuhkan aplikasi untuk menentukan sebuah
serviceAccountName
di dalam spesifikasi Pod-nya, dan untuk ServiceAccount yang akan dibuat (via API, manifes aplikasi,kubectl create serviceaccount
, dan lain-lain).Sebagai contoh, untuk memberikan izin hanya baca (read-only) di dalam "my-namespace" ke ServiceAccount "my-sa":
kubectl create rolebinding my-sa-view \ --clusterrole=view \ --serviceaccount=my-namespace:my-sa \ --namespace=my-namespace
-
Memberikan sebuah Role ke ServiceAccount "default" di dalam suatu Namespace
Jika sebuah aplikasi tidak menetapkan
serviceAccountName
, aplikasi tersebut akan menggunakan ServiceAccount "default".Catatan: Izin yang diberikan ke ServiceAccount "default" tersedia ke Pod apa pun di dalam Namespace yang tidak menetapkanserviceAccountName
.Sebagai contoh, untuk memberikan izin hanya baca di dalam "my-namespace" ke ServiceAccount "default":
kubectl create rolebinding default-view \ --clusterrole=view \ --serviceaccount=my-namespace:default \ --namespace=my-namespace
Banyak pugasan berjalan sebagai ServiceAccount "default" di dalam Namespace
kube-system
. Untuk mengizinkan pugasan tersebut berjalan dengan akses super-user, berikan izincluster-admin
kepada ServiceAccount "default" di dalam Namespacekube-system
.Perhatian: Mengaktifkan ini berarti Namespacekube-system
memuat Secret yang memberikan akses super-user ke API klastermu.kubectl create clusterrolebinding add-on-cluster-admin \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:default
-
Memberikan Role ke semua ServiceAccount dalam suatu Namespace
Jika kamu ingin semua aplikasi di dalam satu Namespace untuk memiliki Role, apa pun ServiceAccount yang digunakan, maka kamu dapat memberikan Role ke grup ServiceAccount untuk Namespace tersebut.
Sebagai contoh, untuk memberikan izin hanya baca di dalam "my-namespace" ke semua ServiceAccount di dalam Namespace tersebut:
kubectl create rolebinding serviceaccounts-view \ --clusterrole=view \ --group=system:serviceaccounts:my-namespace \ --namespace=my-namespace
-
Memberikan Role terbatas ke semua ServiceAccount di seluruh klaster (tidak disarankan)
Jika kamu tidak ingin untuk mengelola izin per Namespace, kamu bisa memberikan Role yang berlaku di seluruh klaster kepada semua ServiceAccount.
Sebagai contoh, untuk memberikan akses hanya baca di semua Namespace untuk semua ServiceAccount yang ada di klaster:
kubectl create clusterrolebinding serviceaccounts-view \ --clusterrole=view \ --group=system:serviceaccounts
-
Memberikan akses super-user ke semua ServiceAccount di seluruh klaster (sangat tidak disarankan)
Jika kamu tidak peduli untuk melakukan partisi terhadap izin sama sekali, maka kamu bisa memberikan akses super-user ke semua ServiceAccount.
Peringatan: Hal ini akan memberikan akses penuh untuk aplikasi apapun ke klastermu, dan juga memberikan pengguna manapun dengan akses baca ke Secret (atau kemampuan untuk membuat Pod apa pun) akses penuh ke klastermu.kubectl create clusterrolebinding serviceaccounts-cluster-admin \ --clusterrole=cluster-admin \ --group=system:serviceaccounts
Melakukan peningkatan dari ABAC
Klaster yang awalnya menjalankan versi Kubernetes lawas sering kali menggunakan kebijakan ABAC yang permisif, termasuk memberikan akses API penuh ke semua ServiceAccount.
Kebijakan RBAC bawaan memberikan izin yang terbatas ke komponen control plane, Node,
dan pengontrol, akan tetapi tidak memberikan izin ke ServiceAccount di luar Namespace
kube-system
(di luar izin diskoveri yang diberikan kepada semua pengguna terotentikasi).
Meskipun jauh lebih aman, hal ini dapat mengganggu beban kerja yang sudah ada yang mengharapkan untuk menerima izin API secara otomatis. Berikut adalah dua pendekatan untuk mengelola transisi ini:
Pemberi otorisasi paralel
Jalankan pemberi otorisasi RBAC dan ABAC bersamaan, dan tentukan berkas kebijakan yang memuat kebijakan ABAC lama:
--authorization-mode=...,RBAC,ABAC --authorization-policy-file=mypolicy.json
Untuk menjelaskan opsi baris perintah yang pertama secara detail: jika pemberi otorisasi sebelumnya, seperti Node, menolak permintaan, maka pemberi otorisasi RBAC mencoba untuk mengotorisasi permintaan API tersebut. Jika RBAC juga menolak permintaan API tersebut, maka pemberi otorisasi ABAC akan dijalankan. Hal ini berarti permintaan apa pun yang diizinkan oleh salah satu kebijakan RBAC atau ABAC akan diizinkan.
Ketika kube-apiserver dijalankan dengan level log 5 atau lebih tinggi untuk komponen
RBAC (--vmodule=rbac*=5
atau --v=5
), kamu dapat melihat penolakan RBAC di log
server API (dengan prefiks RBAC
). Kamu dapat menggunakan informasi tersebut untuk
menentukan Role mana yang perlu diberikan ke pengguna, grup, atau ServiceAccount yang mana.
Jika kamu telah memberikan Role ke ServiceAccount dan beban kerja sedang berjalan tanpa pesan penolakan RBAC dalam log server, maka kamu dapat menghapus pemberi otorisasi ABAC.
Izin RBAC permisif
Kamu dapat mereplikasi kebijakan ABAC yang permisif dengan menggunakan RoleBinding RBAC.
Kebijakan berikut mengizinkan SEMUA ServiceAccount bentindak sebagai administrator klaster. Aplikasi apa pun yang berjalan di dalam Container akan menerima kredensial ServiceAccount secara otomatis, dan dapat melakukan tindakan apa pun terhadap API, termasuk menampilkan Secret dan mengubah izin. Hal ini bukan kebijakan yang direkomendasikan.
kubectl create clusterrolebinding permissive-binding \
--clusterrole=cluster-admin \
--user=admin \
--user=kubelet \
--group=system:serviceaccounts
Setelah kamu beralih menggunakan RBAC, kamu harus menyesuaikan kontrol akses untuk klastermu untuk memastikan bahwa kesemuanya memenuhi kebutuhanmu terkait keamanan informasi.
6.3 - Baris Perintah kubectl
6.3.1 - Contekan kubectl
Lihat juga: Ikhitsar Kubectl dan Panduan JsonPath.
Laman ini merupakan ikhitisar dari perintah kubectl
.
kubectl - Contekan
Autocomplete Kubectl
BASH
source <(kubectl completion bash) # menyiapkan autocomplete untuk bash ke dalam shell saat ini, paket bash-completion harus diinstal terlebih dahulu.
echo "source <(kubectl completion bash)" >> ~/.bashrc # menambahkan autocomplete secara permanen ke dalam bash shell kamu.
Kamu juga dapat menggunakan alias singkatan untuk kubectl
yang juga bisa berfungsi dengan completion:
alias k=kubectl
complete -F __start_kubectl k
ZSH
source <(kubectl completion zsh) # menyiapkan autocomplete untuk zsh ke dalam shell saat ini.
echo "[[ $commands[kubectl] ]] && source <(kubectl completion zsh)" >> ~/.zshrc # menambahkan autocomplete secara permanen ke dalam zsh shell kamu.
Konteks Kubectl dan Konfigurasinya
Memilih klaster Kubernetes yang mana yang ditembak oleh kubectl
untuk berkomunikasi dan
diubah konfigurasinya. Lihat dokumentasi Otentikasi ke berbagai Klaster dengan kubeconfig untuk mengetahui informasi tentang berkas konfigurasi ini secara detail.
kubectl config view # memperlihatkan setelan kubeconfig yang sudah digabung (merged)
# menggunakan beberapa berkas kubeconfig sekaligus dan melihat semua konfigurasinya sekaligus (merged)
KUBECONFIG=~/.kube/config:~/.kube/kubconfig2
kubectl config view
# mendapatkan kata sandi untuk pengguna e2e
kubectl config view -o jsonpath='{.users[?(@.name == "e2e")].user.password}'
kubectl config view -o jsonpath='{.users[].name}' # memperlihatkan pengguna pertama
kubectl config view -o jsonpath='{.users[*].name}' # mendapatkan daftar pengguna
kubectl config get-contexts # memperlihatkan daftar konteks
kubectl config current-context # memperlihatkan konteks saat ini
kubectl config use-context my-cluster-name # menyetel konteks bawaan menjadi my-cluster-name
# menambahkan seorang pengguna baru ke dalam kubeconf kamu yang mendukung basic auth
kubectl config set-credentials kubeuser/foo.kubernetes.com --username=kubeuser --password=kubepassword
# menyimpan Namespace secara permanen untuk semua perintah kubectl pada konteks tersebut
kubectl config set-context --current --namespace=ggckad-s2
# menyetel konteks yang menggunakan pengguna dan namespace yang spesifik
kubectl config set-context gce --user=cluster-admin --namespace=foo \
&& kubectl config use-context gce
kubectl config unset users.foo # menghapus pengguna foo
Menerapkan
apply
(menerapkan) mengelola aplikasi melalui berkas-berkas yang berisi definisi tentang sumber daya Kubernetes. Perintah ini membuat dan memperbarui
sumber daya di dalam sebuah klaster dengan menjalankan kubectl apply
. Ini merupakan cara yang disarankan untuk mengelola aplikasi di dalam production.
Lihat Buku Kubectl.
Membuat Objek
Manifes Kubernetes dapat didefinisikan ke dalam YAML atau JSON. Gunakan berkas dengan ekstensi .yaml
,
.yml
, dan .json
.
kubectl apply -f ./my-manifest.yaml # membuat sumber daya
kubectl apply -f ./my1.yaml -f ./my2.yaml # membuat sumber daya dari beberapa berkas
kubectl apply -f ./dir # membuat sumber daya dari berbagai berkas manifes yang ada di dalam direktori
kubectl apply -f https://git.io/vPieo # membuat sumber daya dari sebuah tautan
kubectl create deployment nginx --image=nginx # memulai sebuah instans tunggal nginx
kubectl explain pods # mendapatkan dokumentasi untuk manifes Pod
# membuat beberapa objek YAML dari masukan (stdin)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: busybox-sleep
spec:
containers:
- name: busybox
image: busybox
args:
- sleep
- "1000000"
---
apiVersion: v1
kind: Pod
metadata:
name: busybox-sleep-less
spec:
containers:
- name: busybox
image: busybox
args:
- sleep
- "1000"
EOF
# membuat sebuah Secret dengan beberapa kunci (key)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: $(echo -n "s33msi4" | base64 -w0)
username: $(echo -n "jane" | base64 -w0)
EOF
Melihat, Mencari Sumber Daya
# mendapatkan berbagai perintah dengan keluaran dasar
kubectl get services # mendapatkan semua Service di dalam Namespace saat ini
kubectl get pods --all-namespaces # mendapatkan semua Pod di dalam semua Namespace
kubectl get pods -o wide # mendapatkan semua Pod di dalam Namespace saat ini, dengan informasi tambahan
kubectl get deployment my-dep # mendapatkan Deployment tertentu
kubectl get pods # mendapatkan semua Pod di dalam Namespace saat ini
kubectl get pod my-pod -o yaml # mendapatkan spesifikasi YAML dari Pod tertentu
# menggambarkan berbagai perintah dengan keluaran yang lengkap (verbose)
kubectl describe nodes my-node
kubectl describe pods my-pod
# mendapatkan semua Service yang diurutkan berdasar nama
kubectl get services --sort-by=.metadata.name
# mendapatkan semua Pod yang diurut berdasarkan jumlah restart
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'
# mendapatkan PersistentVolume yang diurut berdasarkan kapasitas
kubectl get pv --sort-by=.spec.capacity.storage
# mendapatkan label versi dari semua Pod dengan label app=cassandra
kubectl get pods --selector=app=cassandra -o \
jsonpath='{.items[*].metadata.labels.version}'
# mendapatkan semua Node pekerja (worker) (selektor digunakan untuk tidak memasukkan
# Node yang memiliki label 'node-role.kubernetes.io/master' ke dalam keluaran)
kubectl get node --selector='!node-role.kubernetes.io/master'
# mendapatkan semua Pod yang sedang berjalan di dalam Namespace saat ini
kubectl get pods --field-selector=status.phase=Running
# mendapatkan ExternalIP dari semua Node
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="ExternalIP")].address}'
# mendapatkan nama dari semua Pod yang termasuk ke dalam RC tertentu
# perintah "jq" berguna untuk mentransformasi keluaran yang terlalu rumit untuk diproses oleh jsonpath, lihat https://stedolan.github.io/jq/
sel=${$(kubectl get rc my-rc --output=json | jq -j '.spec.selector | to_entries | .[] | "\(.key)=\(.value),"')%?}
echo $(kubectl get pods --selector=$sel --output=jsonpath={.items..metadata.name})
# memperlihatkan label yang dimiliki semua Pod (atau objek Kubernetes lainnya yang mendukung label)
kubectl get pods --show-labels
# memeriksa Node mana yang sudah dalam kondisi siap (ready)
JSONPATH='{range .items[*]}{@.metadata.name}:{range @.status.conditions[*]}{@.type}={@.status};{end}{end}' \
&& kubectl get nodes -o jsonpath="$JSONPATH" | grep "Ready=True"
# mendapatkan semua Secret yang sedang digunakan oleh Pod
kubectl get pods -o json | jq '.items[].spec.containers[].env[]?.valueFrom.secretKeyRef.name' | grep -v null | sort | uniq
# mendapatkan semua containerID dari initContainer yang ada di semua Pod,
# berguna untuk membersihkan kontainer yang telah berhenti, tetapi menghindari terhapusnya initContainer
kubectl get pods --all-namespaces -o jsonpath='{range .items[*].status.initContainerStatuses[*]}{.containerID}{"\n"}{end}' | cut -d/ -f3
# mendapatkan Event yang diurut berdasarkan cap waktu (timestamp)
kubectl get events --sort-by=.metadata.creationTimestamp
# membandingkan antara keadaan saat ini dengan keadaan yang diinginkan pada klaster, jika manifes diterpakan
kubectl diff -f ./my-manifest.yaml
Memperbarui Sumber Daya
kubectl set image deployment/frontend www=image:v2 # memperbarui kontainer "www" secara bergilir dari sebuah Deployment "frontend", memperbarui image-nya
kubectl rollout history deployment/frontend # memeriksa sejarah (history) Deployment, termasuk revisinya
kubectl rollout undo deployment/frontend # mengembalikan (rollback) ke Deployment sebelumnya
kubectl rollout undo deployment/frontend --to-revision=2 # mengembalikan (rollback) ke revisi tertentu
kubectl rollout status -w deployment/frontend # melakukan watch terhadap status pembaruan bergilir dari Deployment "frontend" sampai selesai
kubectl rollout restart deployment/frontend # melakukan restart secara bergilir untuk Deployment "frontend"
cat pod.json | kubectl replace -f - # menggantikan sebuah Pod berdasarkan JSON yang dilewatkan melalui std
# menggantikan, menghapus, dan membuat ulang sumber daya secara paksa, dapat menyebabkan gagalnya layanan
kubectl replace --force -f ./pod.json
# membuat sebuah Service untuk nginx yang terreplikasi, melayani pada porta 80 dan menghubungkan kontainer pada porta 8000
kubectl expose rc nginx --port=80 --target-port=8000
# memperbarui versi image (tag) yang dimiliki kontainer Pod menjadi versi v4
kubectl get pod mypod -o yaml | sed 's/\(image: myimage\):.*$/\1:v4/' | kubectl replace -f -
kubectl label pods my-pod new-label=awesome # menambahkan sebuah label
kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq # menambahkan sebuah anotasi
kubectl autoscale deployment foo --min=2 --max=10 # menskalakan sebuah Deployment "foo" secara otomatis
Menambal (Patch) Sumber Daya
# memperbarui sebuah Node secara parsial
kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}'
# memperbarui image dari kontainer; spec.containers[*].name diperlukan karena menggunakan kunci merge
kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'
# memperbarui image dari kontainer menggunakan patch json dengan array posisi
kubectl patch pod valid-pod --type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'
# menonaktifkan sebuah Deployment livenessProbe menggunakan patch json dengan array posisi
kubectl patch deployment valid-deployment --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/livenessProbe"}]'
# menambahkan elemen baru ke dalam array posisi
kubectl patch sa default --type='json' -p='[{"op": "add", "path": "/secrets/1", "value": {"name": "whatever" } }]'
Menyunting Sumber Daya
Menyunting sumber daya API menggunakan penyunting (editor) yang biasa kamu gunakan.
kubectl edit svc/docker-registry # menyunting Service yang bernama docker-registry
KUBE_EDITOR="nano" kubectl edit svc/docker-registry # menggunakan penyunting alternatif
Menskalakan Sumber Daya
kubectl scale --replicas=3 rs/foo # menskalakan ReplicaSet bernama 'foo' menjadi 3
kubectl scale --replicas=3 -f foo.yaml # menskalakan sebuah sumber daya yang dispesifikasikan di dalam "foo.yaml" menjadi 3
kubectl scale --current-replicas=2 --replicas=3 deployment/mysql # jika Deployment bernama mysql saat ini memiliki ukuran 2, skalakan mysql menjadi 3
kubectl scale --replicas=5 rc/foo rc/bar rc/baz # menskalakan beberapa ReplicationController sekaligus
Menghapus Sumber Daya
kubectl delete -f ./pod.json # menghapus Pod menggunakan tipe dan nama yang dispesifikan di dalam pod.json
kubectl delete pod,service baz foo # menghapus Pod dan Service dengan nama yang sama, yaitu "baz" dan "foo"
kubectl delete pods,services -l name=myLabel # menghapus semua Pod dan Service yang memiliki label name=myLabel
kubectl -n my-ns delete pod,svc --all # menghapus semua Pod dan Service di dalam Namespace my-ns
# menghapus semua Pod yang sesuai dengan pattern1 atau pattern2 dari awk
kubectl get pods -n mynamespace --no-headers=true | awk '/pattern1|pattern2/{print $1}' | xargs kubectl delete -n mynamespace pod
Berinteraksi dengan Pod yang sedang berjalan
kubectl logs my-pod # memperlihatkan log dari Pod (keluaran stdout)
kubectl logs -l name=myLabel # memperlihatkan log dari Pod dengan label name=myLabel (keluaran stdout)
kubectl logs my-pod --previous # memperlihatkan log dari Pod (keluaran stdout) untuk kontainer yang dijalankan sebelumnya
kubectl logs my-pod -c my-container # memperlihatkan log dari kontainer di dalam Pod (keluaran stdout, kasus banyak kontainer)
kubectl logs -l name=myLabel -c my-container # memperlihatkan log dari Pod, dengan label name=myLabel (keluaran stdout)
kubectl logs my-pod -c my-container --previous # memperlihatkan log dari kontainer di dalam Pod (keluaran stdout, kasus banyak kontainer) untuk kontainer yang dijalankan sebelumnya
kubectl logs -f my-pod # memperlihatkan aliran log dari Pod (keluaran stdout)
kubectl logs -f my-pod -c my-container # memperlihatkan aliran log dari kontainer di dalam Pod (keluaran stdout, kasus banyak kontainer)
kubectl logs -f -l name=myLabel --all-containers # memperlihatkan aliran log dari Pod dengan label name=myLabel (keluaran stdout)
kubectl run -i --tty busybox --image=busybox -- sh # menjalankan Pod sebagai shell interaktif
kubectl run nginx --image=nginx --restart=Never -n
mynamespace # menjalankan Pod nginx ke dalam Namespace tertentu
kubectl run nginx --image=nginx --restart=Never # menjalankan Pod nginx dan menulis spesifikasinya ke dalam sebuah berkas bernama pod.yaml
--dry-run -o yaml > pod.yaml
kubectl attach my-pod -i # melekatkan (meng-attach) ke dalam kontainer yang sedang berjalan
kubectl port-forward my-pod 5000:6000 # mendengar (listen) pada porta 5000 di mesin lokal dan meneruskan ke porta 6000 di Pod my-pod
kubectl exec my-pod -- ls / # menjalankan perintah pada Pod my-pod (kasus 1 kontainer)
kubectl exec my-pod -c my-container -- ls / # menjalankan peirntah pada Pod my-pod (kasus banyak kontainer)
kubectl top pod POD_NAME --containers # memperlihatkan metrik yang dimiliki Pod bersama kontainernya
Berinteraksi dengan Node dan Klaster
kubectl cordon my-node # menandai my-node supaya tidak bisa dijadwalkan dengan Pod (unschedulable)
kubectl drain my-node # mengeringkan (drain) my-node sebagai bagian dari persiapan untuk pemeliharaan
kubectl uncordon my-node # menandai my-node supaya bisa dijadwalkan dengan Pod (schedulable)
kubectl top node my-node # memperlihatkan metrik dari Node my-node
kubectl cluster-info # memperlihatkan alamaat dari master dan layanan
kubectl cluster-info dump # memperlihatkan state klaster saat ini pada keluaran stdout
kubectl cluster-info dump --output-directory=/path/to/cluster-state # memperlihatkan state klaster saat ini pada /path/to/cluster-state
# jika sebuah taint dengan sebuah kunci dan efek di bawah pernah diterapkan, maka nilainya akan tergantikan dengan yang baru
kubectl taint nodes foo dedicated=special-user:NoSchedule
Berbagai Tipe Sumber Daya
Mendapatkan seluruh daftar tipe sumber daya yang didukung lengkap dengan singkatan pendeknya, grup API, apakah sumber daya merupakan sumber daya yang berada di dalam Namespace atau tidak, serta Kind:
kubectl api-resources
Operasi lainnya yang berkaitan dengan sumber daya API (api-resources):
kubectl api-resources --namespaced=true # semua sumber daya yang berada di dalam Namespace
kubectl api-resources --namespaced=false # semua sumber daya yang tidak berada di dalam Namespace
kubectl api-resources -o name # semua sumber daya dengan keluaran sederhana (hanya nama sumber daya)
kubectl api-resources -o wide # semua sumber daya dengan keluaran tambahan ("wide")
kubectl api-resources --verbs=list,get # semua sumber daya yang mendukung verb permintaan "list" dan "get"
kubectl api-resources --api-group=extensions # semua sumber daya di dalam grup API "extensions"
Memformat Keluaran
Untuk mengeluarkan detail ke dalam jendela terminal kamu dengan format tertentu, tambahkan flag -o
(atau --output
)
dengan perintah kubectl
yang didukung.
Format keluaran | Deskripsi |
---|---|
-o=custom-columns=<spec> |
Mencetak sebuah tabel dengan daftar kolom khas (custom) yang dipisahkan dengan koma |
-o=custom-columns-file=<filename> |
Mencetak sebuah tabel dengan templat kolom khas pada berkas <filename> |
-o=json |
Memberikan keluaran objek API dengan format JSON |
-o=jsonpath=<template> |
Mencetak bagian-bagian yang didefinisikan di dalam sebuah ekspresi jsonpath |
-o=jsonpath-file=<filename> |
Mencetak bagian-bagian yang didefinisikan dengan ekspresi jsonpath ke dalam berkas <filename> |
-o=name |
Mencetak hanya nama dari sumber daya, tidak dengan informasi yang lainnya |
-o=wide |
Memberikan keluaran dengan format teks polos (plain-text) dengan informasi tambahan, dan nama dari Node akan juga termasuk ke dalam informasi untuk Pod |
-o=yaml |
Memberikan keluaran objek API dengan format YAML |
Contoh-contoh yang menggunakan -o=custom-columns
:
# All images running in a cluster
kubectl get pods -A -o=custom-columns='DATA:spec.containers[*].image'
# All images excluding "k8s.gcr.io/coredns:1.6.2"
kubectl get pods -A -o=custom-columns='DATA:spec.containers[?(@.image!="k8s.gcr.io/coredns:1.6.2")].image'
# All fields under metadata regardless of name
kubectl get pods -A -o=custom-columns='DATA:metadata.*'
More examples in the kubectl reference documentation.
Tingkat Kelengkapan Keluaran dan Debugging Kubectl
Tingkat kelengkapan keluaran (verbosity) dari kubectl dikendalikan oleh flag -v
atau --v
diikuti dengan bilangan bulat yang merepresentasikan
tingkatan log. Ketentuan logging Kubernetes secara umum dan keterkaitannya dengan tingkatan log dijelaskan di sini.
Tingkat kelengkapan keluaran | Deskripsi |
---|---|
--v=0 |
Umumnya berguna untuk selalu bisa dilihat oleh seorang operator klaster. |
--v=1 |
Tingkatan log bawaan yang layak jika kamu tidak ingin log yang terlalu lengkap. |
--v=2 |
Berisi informasi yang steady state tentang layanan dan berbagai pesan log penting yang berhubungan dengan perubahan besar pada sistem. Tingkat ini yang paling disarankan pada sistem kebanyakan. |
--v=3 |
Informasi tambahan tentang perubahan pada sistem. |
--v=4 |
Tingkat kelengkapan debug. |
--v=6 |
Memperlihatkan sumber daya yang diminta. |
--v=7 |
Memperlihatkan header dari permintaan HTTP. |
--v=8 |
Memperlihatkan konten dari permintan HTTP. |
--v=9 |
Memperlihatkan kontek dari permintaan HTTP tanpa dipotong. |
Selanjutnya
-
Pelajari lebih lanjut tentang Ikhitsar kubectl.
-
Lihat berbagai pilihan opsi dari kubectl.
-
Pelajari juga Ketentuan Penggunaan kubectl untuk mengetahui bagaimana cara memakainya di dalam skrip yang bisa dipergunakan berulangkali (reusable).
-
Pelajari contekan kubectl dari komunitas.
7 - Berkontribusi ke Dokumentasi Kubernetes
Jika kamu ingin membantu dengan berkontribusi ke dokumentasi atau situs web Kubernetes, kami dengan senang hati menerima bantuan kamu! Siapapun bisa berkontribusi, baik kamu yang masih baru atau sudah lama di proyek ini, maupun jika kamu adalah seorang developer, seorang pengguna, atau bahkan seorang yang tidak tahan melihat saltik (typo)!
Untuk informasi mengenai isi dan gaya (penulisan) dokumentasi Kubernetes, lihat ikhtisar gaya penulisan dokumentasi.
Jenis-jenis kontributor dokumentasi
- Seorang member dari organisasi Kubernetes yang telah menandatangani CLA dan berkontribusi waktu dan usahanya untuk proyek ini. Lihat Keanggotaan komunitas untuk kriteria spesifik untuk keanggotaan.
- Seorang SIG Docs reviewer adalah seorang anggota organisasi Kubernetes yang telah
menunjukkan ketertarikannya untuk memeriksa pull request dokumentasi dan telah
ditambahkan ke dalam grup GitHub yang sesuai dan berkas-berkas
OWNERS
di dalam repositori GitHub, oleh seorang SIG Docs Approver. - Seorang SIG Docs approver adalah seorang anggota yang memiliki predikat yang baik dan telah menunjukkan komitmen berkelanjutan terhadap proyek ini. Seorang approver dapat melakukan merge terhadap pull request dan mempublikasi konten atas nama organisasi Kubernetes. Para approver juga dapat mewakili SIG Docs dalam komunitas Kubernetes yang lebih besar. Beberapa tugas seorang SIG Docs approver, seperti mengkoordinasi sebuah perilisan, membutuhkan komitmen waktu yang signifikan.
Cara-cara untuk berkontribusi ke dokumentasi
Daftar ini dibagi menjadi hal-hal yang dapat dilakukan oleh siapapun, hal-hal yang dapat dilakukan oleh anggota-anggota organisasi Kubernetes, dan hal-hal yang memerlukan tingkat akses yang lebih tinggi serta pengetahuan terhadap proses-proses SIG Docs. Berkontribusi secara konsisten dari waktu ke waktu dapat membantumu mengerti beberapa peralatan dan keputusan organisasi yang telah dibuat.
Daftar ini bukanlah daftar lengkap mengenai cara-cara kamu dapat berkontribusi terhadap dokumentasi Kubernetes, tetapi daftar ini dapat membantumu memulainya.
- Siapapun
- Membuka issue untuk ditindaklanjuti
- Member
- Memutakhirkan dokumentasi yang sudah ada
- Menyampaikan ide-ide untuk pembaruan di Slack atau [milis SIG docs]SIG docs mailing list
- Meningkatkan aksesibilitas dokumentasi
- Memberikan umpan balik yang tidak memikat terhadap PR-PR
- Menulis blog atau studi kasus
- Reviewer
- Mendokumentasikan fitur-fitur baru
- Menyortir dan mengkategorisasi masalah-masalah
- Memeriksa PR-PR
- Membuat diagram-diagram, aset grafis, dan screencast atau video yang dapat di-embed
- Lokalisasi/penerjemahan
- Berkontribusi pada repositori-repositori lain sebagai seorang wakil dokumentasi
- Menyunting user-facing strings di dalam kode
- Memutakhirkan komentar-komentar pada kode, Godoc
- Approver
- Mempublikasi konten kontributor dengan menyetujui dan melakukan merge terhadap PR-PR
- Berpartisipasi di dalam sebuah tim rilis Kubernetes sebagai seorang wakil dokumentasi
- Mengusulkan pemutakhiran terhadap petunjuk gaya penulisan
- Mengusulkan pemutakhiran terhadap test-test dokumentasi
- Mengusulkan pemutakhiran terhadap situs web Kubernetes atau peralatan lainnya
Cara-cara tambahan untuk berkontribusi
- Untuk berkontribusi ke komunitas Kubernetes melalui forum-forum daring seperti Twitter atau Stack Overflow, atau mengetahui tentang pertemuan komunitas (meetup) lokal dan acara-acara Kubernetes, kunjungi situs komunitas Kubernetes.
- Untuk mulai berkontribusi ke pengembangan fitur, baca cheatseet kontributor.
- Untuk kontribusi khusus ke halaman Bahasa Indonesia, baca Dokumentasi Khusus Untuk Translasi Bahasa Indonesia
7.1 - Menyarankan peningkatan kualitas konten
Jika kamu menemukan masalah pada dokumentasi Kubernetes, atau mempunyai ide untuk konten baru, maka silakan untuk membuat isu pada Github. Kamu hanya membutuhkan sebuah akun Github dan sebuah web browser.
Pada kebanyakan kasus, pekerjaan dalam dokumentasi Kubernetes diawali dengan sebuah isu pada Github. Kontributor Kubernetes akan mengkaji, mengkategorisasi dan menandai isu sesuai kebutuhan. Selanjutnya, kamu atau anggota lain dari komunitas Kubernetes dapat membuat pull request dengan perubahan yang akan menyelesaikan masalahnya.
Membuka sebuah issue
Jika kamu mau menyarankan peningkatan kualitas pada konten yang sudah ada, atau menemukan kesalahan, maka silakan membuka sebuah isu.
- Turun ke bagian bawah dari suatu halaman dan klik pada tombol Buat Isu. Ini akan mengantarmu pada halaman Github isu dengan beberapa tajuk yang telah diisi.
- Deskripsikan isu atau saran untuk peningkatan kualitas. Sediakan detail sebanyak mungkin yang kamu bisa.
- Klik Submit new issue
Setelah dikirim, cek isu yang kamu buat secara berkala atau hidupkan notifikasi Github. Pengulas (reviewer) atau anggota komunitas lainnya mungkin akan menanyakan pertanyaan sebelum mereka mengambil suatu tindakan terhadap isumu.
Menyarankan konten baru
Jika kamu memiliki ide untuk konten baru, tapi kamu tidak yakin dimana mengutarakannya, kamu tetap dapat membuat sebuah isu. Antara lain:
- Pilih halaman pada bagian yang menurutmu konten tersebut berhubungan dan klik Buat Isu.
- Pergi ke Github dan langsung membuat isu.
Bagaimana cara membuat isu yang bagus
Perhatikan hal berikut ketika membuat sebuah isu:
- Memberikan deskripsi isu yang jelas. Deskripsikan apa yang memang kurang, tertinggal, salah atau konten mana yang memerlukan peningkatan kualitas.
- Jelaskan dampak spesifik dari isu terhadap pengguna.
- Batasi cakupan dari sebuah isu menjadi ukuran pekerjaan yang masuk akal. Untuk masalah dengan cakupan yang besar, pecah isu itu menjadi beberapa isu lebih kecil. Misal, "Membenahi dokumentasi keamanan" masih sangat luas cakupannya, tapi "Penambahan detail pada topik 'Pembatasan akses jaringan'" adalah lebih spesifik untuk dikerjakan.
- Mencari isu yang sudah ada untuk melihat apakah ada sesuatu yang berhubungan atau mirip dengan isu yang baru.
- Jika isu yang baru berhubungan dengan isu lain atau pull request, tambahkan rujukan
dengan menuliskan URL lengkap atau dengan nomor isu atau pull request yang diawali dengan
karakter
#
. Contohnya,Diajukan oleh #987654
. - Mengikuti Kode Etik Komunitas. Menghargai kontributor lain. Misalnya, "Dokumentasi ini sangat jelek" adalah contoh yang tidak membantu dan juga bukan masukan yang sopan.
7.2 - Berpartisipasi dalam SIG Docs
SIG Docs merupakan salah satu kelompok peminatan khusus (special interest groups) dalam proyek Kubernetes, yang berfokus pada penulisan, pembaruan, dan pemeliharaan dokumentasi untuk Kubernetes secara keseluruhan. Lihatlah SIG Docs dari repositori github komunitas untuk informasi lebih lanjut tentang SIG.
SIG Docs menerima konten dan ulasan dari semua kontributor. Siapa pun dapat membuka pull request (PR), dan siapa pun boleh mengajukan isu tentang konten atau komen pada pull request yang sedang berjalan.
Kamu juga bisa menjadi anggota (member), pengulas (reviewer, atau pemberi persetujuan (approver). Peran tersebut membutuhkan akses dan mensyaratkan tanggung jawab tertentu untuk menyetujui dan melakukan perubahan. Lihatlah keanggotaan-komunitas (community-membership) untuk informasi lebih lanjut tentang cara kerja keanggotaan dalam komunitas Kubernetes.
Selebihnya dari dokumen ini akan menguraikan beberapa cara unik dari fungsi peranan tersebut dalam SIG Docs, yang bertanggung jawab untuk memelihara salah satu aspek yang paling berhadapan dengan publik dalam Kubernetes - situs web dan dokumentasi dari Kubernetes.
Ketua umum (chairperson) SIG Docs
Setiap SIG, termasuk SIG Docs, memilih satu atau lebih anggota SIG untuk bertindak sebagai ketua umum. Mereka merupakan kontak utama antara SIG Docs dan bagian lain dari organisasi Kubernetes. Mereka membutuhkan pengetahuan yang luas tentang struktur proyek Kubernetes secara keseluruhan dan bagaimana SIG Docs bekerja di dalamnya. Lihatlah Kepemimpinan (leadership) untuk daftar ketua umum yang sekarang.
Tim dan automasi dalam SIG Docs
Automasi dalam SIG Docs bergantung pada dua mekanisme berbeda: Tim GitHub dan berkas OWNERS.
Tim GitHub
Terdapat dua kategori tim dalam SIG Docs tim (teams) dalam GitHub:
@sig-docs-{language}-owners
merupakan pemberi persetujuan (approver) dan pemimpin (lead)@sig-docs-{language}-reviewers
merupakan pengulas (reviewer)
Setiap tim dapat direferensikan dengan @name
mereka dalam komen GitHub untuk berkomunikasi dengan setiap orang di dalam grup.
Terkadang tim Prow dan GitHub tumpang tindih (overlap) tanpa kecocokan sama persis. Untuk penugasan masalah, pull request, dan untuk mendukung persetujuan PR,
otomatisasi menggunakan informasi dari berkas OWNERS
.
Berkas OWNERS dan bagian yang utama (front-matter)
Proyek Kubernetes menggunakan perangkat otomatisasi yang disebut prow untuk melakukan automatisasi yang terkait dengan isu dan pull request dalam GitHub. Repositori situs web Kubernetes menggunakan dua buah prow plugin:
- blunderbuss
- approve
Kedua plugin menggunakan berkas
OWNERS dan
OWNERS_ALIASES
dalam level teratas dari repositori GitHub kubernetes/website
untuk mengontrol
bagaimana prow bekerja di dalam repositori.
Berkas OWNERS berisi daftar orang-orang yang menjadi pengulas dan pemberi persetujuan di dalam SIG Docs. Berkas OWNERS juga bisa terdapat di dalam subdirektori, dan dapat menimpa peranan karena dapat bertindak sebagai pengulas atau pemberi persetujuan berkas untuk subdirektori itu dan apa saja yang ada di dalamnya. Untuk informasi lebih lanjut tentang berkas OWNERS pada umumnya, lihatlah OWNERS.
Selanjutnya, berkas markdown individu dapat menyimpan daftar pengulas dan pemberi persetujuan pada bagian yang utama, baik dengan menyimpan daftar nama pengguna individu GitHub atau grup GitHub.
Kombinasi dari berkas OWNERS dan bagian yang utama dalam berkas markdown menentukan saran kepada pemilik PR yang didapat dari sistem otomatis tentang siapa yang akan meminta ulasan teknis dan ulasan editorial untuk PR mereka.
Cara menggabungkan pekerjaan
Ketika pull request digabungkan ke cabang (branch) yang digunakan untuk mempublikasikan konten, konten itu dipublikasikan di http://kubernetes.io. Untuk memastikan bahwa kualitas konten yang kita terbitkan bermutu tinggi, kita membatasi penggabungan pull request bagi para pemberi persetujuan SIG Docs. Beginilah cara kerjanya.
- Ketika pull request memiliki label
lgtm
danapprove
, tidak memiliki labelhold
, dan telah lulus semua tes, pull request akan digabungkan secara otomatis. - Anggota organisasi Kubernetes dan pemberi persetujuan SIG Docs dapat menambahkan komen
untuk mencegah penggabungan otomatis dari pull request yang diberikan (dengan menambahkan komen
/hold
atau menahan komen/lgtm
). - Setiap anggota Kubernetes dapat menambahkan label
lgtm
dengan menambahkan komenlgtm
- Hanya pemberi persetujuan SIG Docs yang bisa menggabungkan pull request
dengan menambahkan komen
/approve
. Beberapa pemberi persetujuan juga dapat melakukan tugas tambahan seperti PR Wrangler atau Ketua Umum SIG Docs.
Selanjutnya
Untuk informasi lebih lanjut tentang cara berkontribusi pada dokumentasi Kubernetes, lihatlah:
7.3 - Dokumentasi Khusus Untuk Translasi Bahasa Indonesia
Panduan khusus untuk bergabung ke komunitas SIG DOC Indonesia dan melakukan kontribusi untuk mentranslasikan dokumentasi Kubernetes ke dalam Bahasa Indonesia.
Manajemen Milestone Tim
Secara umum siklus translasi dokumentasi ke Bahasa Indonesia akan dilakukan 3 kali dalam setahun (sekitar setiap 4 bulan). Untuk menentukan dan mengevaluasi pencapaian atau milestone dalam kurun waktu tersebut jadwal rapat daring reguler tim Bahasa Indonesia dilakukan secara konsisten setiap dua minggu sekali. Dalam agenda rapat ini juga dilakukan pemilihan PR Wrangler untuk dua minggu ke depan. Tugas PR Wrangler tim Bahasa Indonesia serupa dengan PR Wrangler dari proyek upstream.
Target pencapaian atau milestone tim akan dirilis sebagai issue tracking seperti ini pada Kubernetes GitHub Website setiap 4 bulan. Dan bersama dengan informasi PR Wrangler yang dipilih setiap dua minggu, keduanya akan diumumkan di Slack channel #kubernetes-docs-id dari Komunitas Kubernetes.
Cara Memulai Translasi
Untuk menerjemahkan satu halaman Bahasa Inggris ke Bahasa Indonesia, lakukan langkah-langkah berikut ini:
- Check halaman issue di GitHub dan pastikan tidak ada orang lain yang sudah mengklaim halaman kamu dalam daftar periksa atau komentar-komentar sebelumnya.
- Klaim halaman kamu pada issue di GitHub dengan memberikan komentar di bawah dengan nama halaman yang ingin kamu terjemahkan dan ambillah hanya satu halaman dalam satu waktu.
- Fork repo ini, buat terjemahan
kamu, dan kirimkan PR (pull request) dengan label
language/id
- Setelah dikirim, pengulas akan memberikan komentar dalam beberapa hari, dan tolong untuk menjawab semua komentar. Direkomendasikan juga untuk melakukan squash commit kamu dengan pesan commit yang baik.
Informasi Acuan Untuk Translasi
Tidak ada panduan gaya khusus untuk menulis translasi ke bahasa Indonesia. Namun, secara umum kita dapat mengikuti panduan gaya bahasa Inggris dengan beberapa tambahan untuk kata-kata impor yang dicetak miring.
Harap berkomitmen dengan terjemahan kamu dan pada saat kamu mendapatkan komentar dari pengulas, silahkan atasi sebaik-baiknya. Kami berharap halaman yang diklaim akan diterjemahkan dalam waktu kurang lebih dua minggu. Jika ternyata kamu tidak dapat berkomitmen lagi, beri tahu para pengulas agar mereka dapat meberikan halaman tersebut ke orang lain.
Beberapa acuan tambahan dalam melakukan translasi silahkan lihat informasi berikut ini:
Daftara Glosarium Translasi dari tim SIG DOC Indonesia
Untuk kata-kata selengkapnya silahkan baca glosariumnya disini
KBBI
Konsultasikan dengan KBBI (Kamus Besar Bahasa Indonesia) disini dari Kemendikbud.
RSNI Glosarium dari Ivan Lanin
RSNI Glosarium dapat digunakan untuk memahami bagaimana menerjemahkan berbagai istilah teknis dan khusus Kubernetes.
Panduan Penulisan Source Code
Mengikuti kode asli dari dokumentasi bahasa Inggris
Untuk kenyamanan pemeliharaan, ikuti lebar teks asli dalam kode bahasa Inggris. Dengan kata lain, jika teks asli ditulis dalam baris yang panjang tanpa putus atu baris, maka teks tersebut ditulis panjang dalam satu baris meskipun dalam bahasa Indonesia. Jagalah agar tetap serupa.
Hapus nama reviewer di kode asli bahasa Inggris
Terkadang reviewer ditentukan di bagian atas kode di teks asli Bahasa Inggris. Secara umum, reviewer-reviewer halaman aslinya akan kesulitan untuk meninjau halaman dalam bahasa Indonesia, jadi hapus kode yang terkait dengan informasi reviewer dari metadata kode tersebut.
Panduan Penulisan Kata-kata Translasi
Panduan umum
- Gunakan "kamu" daripada "Anda" sebagai subyek agar lebih bersahabat dengan para pembaca dokumentasi.
- Tulislah miring untuk kata-kata bahasa Inggris yang diimpor jika kamu tidak
dapat menemukan kata-kata tersebut dalam bahasa Indonesia.
Benar: controller. Salah: controller,
controller
Panduan untuk kata-kata API Objek Kubernetes
Gunakan gaya "CamelCase" untuk menulis objek API Kubernetes, lihat daftar lengkapnya di sini. Sebagai contoh:
- Benar: PersistentVolume. Salah: volume persisten,
PersistentVolume
, persistentVolume - Benar: Pod. Salah: pod,
pod
, "pod"
Tips : Biasanya API objek sudah ditulis dalam huruf kapital pada halaman asli bahasa Inggris.
Panduan untuk kata-kata yang sama dengan API Objek Kubernetes
Ada beberapa kata-kata yang serupa dengan nama API objek dari Kubernetes dan dapat mengacu ke arti yang lebih umum (tidak selalu dalam konteks Kubernetes). Sebagai contoh: service, container, node , dan lain sebagainya. Kata-kata sebaiknya ditranslasikan ke Bahasa Indonesia sebagai contoh service menjadi layanan, container menjadi kontainer.
Tips : Biasanya kata-kata yang mengacu ke arti yang lebih umum sudah tidak ditulis dalam huruf kapital pada halaman asli bahasa Inggris.
Panduan untuk "Feature Gate" Kubernetes
Istilah feature gate Kubernetes tidak perlu diterjemahkan ke dalam bahasa Indonesia dan tetap dipertahankan dalam bentuk aslinya.
Contoh dari functional gate adalah sebagai berikut:
- Akselerator
- AdvancedAuditing
- AffinityInAnnotations
- AllowExtTrafficLocalEndpoints
- ...
Glosarium Indonesia
Inggris | Tipe Kata | Indonesia | Sumber | Contoh Kalimat |
---|---|---|---|---|
cluster | klaster | |||
container | kontainer | |||
node | kata benda | node | ||
file | berkas | |||
service | kata benda | layanan | ||
set | sekumpulan | |||
resource | sumber daya | |||
default | bawaan atau standar (tergantung context) | Secara bawaan, ...; Pada konfigurasi dan instalasi standar, ... | ||
deploy | menggelar | |||
image | image | |||
request | permintaan | |||
object | kata benda | objek | https://kbbi.web.id/objek | |
command | perintah | https://kbbi.web.id/perintah | ||
view | tampilan | |||
support | tersedia atau dukungan (tergantung konteks) | "This feature is supported on version X; Fitur ini tersedia pada versi X; Supported by community; Didukung oleh komunitas" | ||
release | kata benda | rilis | https://kbbi.web.id/rilis | |
tool | perangkat | |||
deployment | penggelaran | |||
client | klien | |||
reference | rujukan | |||
update | pembaruan | The latest update... ; Pembaruan terkini... | ||
state | state | |||
task | task | |||
certificate | sertifikat | |||
install | instalasi | https://kbbi.web.id/instalasi | ||
scale | skala | |||
process | kata kerja | memproses | https://kbbi.web.id/proses | |
replica | kata benda | replika | https://kbbi.web.id/replika | |
flag | tanda, parameter, argumen | |||
event | event |