This is the multi-page printable view of this section. Click here to print.
Mengatur Pod dan Kontainer
- 1: Menetapkan Sumber Daya Memori untuk Container dan Pod
- 2: Konfigurasi Quality of Service untuk Pod
- 3: Mengatur Pod untuk Menggunakan Volume sebagai Tempat Penyimpanan
- 4: Mengatur Pod untuk Penyimpanan dengan PersistentVolume
- 5: Mengonfigurasi Konteks Keamanan untuk Pod atau Container
- 6: Mengatur ServiceAccount untuk Pod
- 7: Menarik Image dari Register Pribadi
- 8: Mengatur Probe Liveness, Readiness dan Startup
- 9: Menempatkan Pod pada Node Menggunakan Afinitas Pod
- 10: Mengatur Pod untuk Menggunakan ConfigMap
- 11: Pembagian Namespace Proses antar Container pada sebuah Pod
- 12: Membuat Pod Statis
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
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
Catatan:
Jika sebuah Container hanya menspesifikasikan batasan memori tanpa menentukan permintaan memori, maka Kubernetes akan secara otomatis menetapkan permintaan memori yang sesuai dengan batasan memori yang dicantumkan. Sama halnya jika sebuah Container menspesifikasikan batasan CPU tanpa menentukan permintaan CPU, maka Kubernetes akan secara otomatis menetapkan permintaan CPU yang sesuai dengan batasan CPU yang dicantumkan.Hapuslah Pod:
kubectl delete pod qos-demo --namespace=qos-example
Membuat sebuah Pod yang mendapatkan penempatan kelas Qos Burstable
Sebuah Pod akan mendapatkan kelas QoS Burstable apabila:
- Pod tidak memenuhi kriteria untuk kelas QoS Guaranteed.
- Setidaknya ada satu Container di dalam Pod dengan permintaan memori atau CPU.
Berikut adalah berkas konfigurasi untuk Pod dengan satu Container. Container yang dimaksud memiliki batasan memori sebesar 200MiB dan permintaan memori sebesar 100MiB.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
- name: qos-demo-2-ctr
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
Buatlah Pod:
kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-2.yaml --namespace=qos-example
Tampilkan informasi detail Pod yang telah dibuat:
kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml
Keluaran dari perintah di atas menunjukkan Kubernetes memberikan kelas QoS Burstable pada Pod.
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: qos-demo-2-ctr
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
status:
qosClass: Burstable
Hapuslah Pod:
kubectl delete pod qos-demo-2 --namespace=qos-example
Membuat sebuah Pod yang mendapatkan penempatan kelas QoS BestEffort
Agar Pod mendapatkan kelas QoS BestEffort, Container dalam pod tidak boleh memiliki batasan atau permintaan memori atau CPU.
Berikut adalah berkas konfigurasi untuk Pod dengan satu Container. Container yang dimaksud tidak memiliki batasan atau permintaan memori atau CPU apapun.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- name: qos-demo-3-ctr
image: nginx
Buatlah Pod:
kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-3.yaml --namespace=qos-example
Tampilkan informasi detail Pod yang telah dibuat:
kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml
Keluaran dari perintah di atas menunjukkan Kubernetes memberikan kelas QoS BestEffort pada Pod.
spec:
containers:
...
resources: {}
...
status:
qosClass: BestEffort
Hapuslah Pod:
kubectl delete pod qos-demo-3 --namespace=qos-example
Membuat sebuah Pod yang memiliki dua Container
Berikut adalah konfigurasi berkas untuk Pod yang memiliki dua Container. Satu Container menentukan permintaan memori sebesar 200MiB. Container yang lain tidak menentukan permintaan atau batasan apapun.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-4
namespace: qos-example
spec:
containers:
- name: qos-demo-4-ctr-1
image: nginx
resources:
requests:
memory: "200Mi"
- name: qos-demo-4-ctr-2
image: redis
Perhatikan bahwa Pod ini memenuhi kriteria untuk kelas QoS Burstable. Maksudnya, Container tersebut tidak memenuhi kriteria untuk kelas QoS Guaranteed, dan satu dari Container tersebut memiliki permintaan memori.
Buatlah Pod:
kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-4.yaml --namespace=qos-example
Tampilkan informasi detail Pod yang telah dibuat:
kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml
Keluaran dari perintah di atas menunjukkan Kubernetes memberikan kelas QoS Burstable pada Pod.
spec:
containers:
...
name: qos-demo-4-ctr-1
resources:
requests:
memory: 200Mi
...
name: qos-demo-4-ctr-2
resources: {}
...
status:
qosClass: Burstable
Hapuslah Pod:
kubectl delete pod qos-demo-4 --namespace=qos-example
Membersihkan
Hapuslah Namespace:
kubectl delete namespace qos-example
Selanjutnya
Untuk pengembang aplikasi
Untuk administrator klaster
3 - 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 - 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"
Catatan:
Jika Node kamu menggunakan alat untuk mengakses superuser selain dengansudo
, 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.
Catatan:
Ketika sebuah Pod mengkonsumsi PersistentVolume, GID yang terkait dengan PersistentVolume tidak ada di dalam sumberdaya Pod itu sendiri.Selanjutnya
- Belajar lebih lanjut tentang PersistentVolume.
- Baca dokumen perancangan Penyimpanan Persistent.
Referensi
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.
Catatan:
Bagian ini tidak berpengaruh pada tipe volume yang bersifat sementara (ephemeral) sepertisecret
,
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.
Catatan:
Konstanta kapabilitas Linux memiliki formatCAP_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"
Catatan:
Untuk menetapkan label SELinux, modul keamanan SELinux harus dimuat terlebih dahulu pada sistem operasi dari hosnya.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.
Peringatan:
Setelah kamu menentukan label MCS untuk Pod, maka semua Pod dengan label yang sama dapat mengakses Volume tersebut. Jika kamu membutuhkan perlindungan antar Pod, kamu harus menetapkan label MCS yang unik untuk setiap Pod.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
6 - Mengatur ServiceAccount untuk Pod
ServiceAccount menyediakan identitas untuk proses yang sedang berjalan dalam sebuah Pod.
Catatan:
Dokumen ini digunakan sebagai pengenalan untuk pengguna terhadap ServiceAccount dan menjelaskan bagaimana perilaku ServiceAccount dalam konfigurasi klaster seperti yang direkomendasikan Kubernetes. Pengubahan perilaku yang bisa saja dilakukan administrator klaster terhadap klaster tidak menjadi bagian pembahasan dokumentasi ini.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: ...
Catatan:
Isi daritoken
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=<registry name> \ --docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD \ --docker-email=DUMMY_DOCKER_EMAIL
-
Memastikan bahwa Secret telah terbuat.
kubectl get secrets myregistrykey
Keluarannya akan serupa dengan:
NAME TYPE DATA AGE myregistrykey kubernetes.io/.dockerconfigjson 1 1d
Menambahkan imagePullSecret ke ServiceAccount
Selanjutnya, modifikasi ServiceAccount standar dari Namespace untuk menggunakan Secret ini sebagai imagePullSecret.
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
Sebagai gantinya kamu dapat menggunakan kubectl edit
, atau melakukan pengubahan secara manual manifes YAML seperti di bawah ini:
kubectl get serviceaccounts default -o yaml > ./sa.yaml
Keluaran dari berkas sa.yaml
akan serupa dengan:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-08-07T22:02:39Z
name: default
namespace: default
resourceVersion: "243024"
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
Menggunakan editor pilihanmu (misalnya vi
), buka berkas sa.yaml
, hapus baris dengan key resourceVersion
, tambahkan baris dengan imagePullSecrets:
dan simpan.
Keluaran dari berkas sa.yaml
akan serupa dengan:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-08-07T22:02:39Z
name: default
namespace: default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
imagePullSecrets:
- name: myregistrykey
Terakhir ganti serviceaccount dengan berkas sa.yaml
yang telah diperbarui.
kubectl replace serviceaccount default -f ./sa.yaml
Memverifikasi imagePullSecrets sudah ditambahkan ke spesifikasi Pod
Ketika Pod baru dibuat dalam Namespace yang sedang aktif dan menggunakan ServiceAccount, Pod baru akan memiliki field spec.imagePullSecrets
yang ditentukan secara otomatis:
kubectl run nginx --image=<registry name>/nginx --restart=Never
kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'
Keluarannya adalah:
myregistrykey
ServiceAccountTokenVolumeProjection
Kubernetes v1.12 [beta]
Catatan:
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.
Catatan:
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.
Catatan:
Respons yang disediakan pada/.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:
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"
}
}
}
Catatan:
Jika kamu menggunakan tempat penyimpanan kredensial (credential) untuk Docker, maka kamu tidak akan melihat entriauth
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
.
Catatan:
Mengetik Secret pada baris perintah dapat menyimpannya dalam riwayat (history) dari shell kamu tanpa perlindungan, dan Secret tersebut mungkin juga terlihat oleh pengguna lain dalam PC kamu selama perintahkubectl
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":"jdoe@example.com","auth":"c3R...zE2"}}}
Untuk memahami apa yang ada dalam bidang auth
, ubahlah data Secret menjadi format yang bisa terbaca:
echo "c3R...zE2" | base64 --decode
Keluarannya, nama pengguna dan kata sandi yang digabungkan dengan tanda :
, seperti dibawah ini:
janedoe:xxxxxxxxxxx
Perhatikan bahwa data Secret berisi token otorisasi yang serupa dengan berkas ~/.docker/config.json
lokal kamu.
Kamu telah berhasil menetapkan kredensial Docker kamu sebagai sebuah Secret yang dipanggil dengan regcred
pada klaster.
Membuat Pod yang menggunakan Secret kamu
Berikut ini adalah berkas konfigurasi untuk Pod yang memerlukan akses ke kredensial Docker kamu pada regcred
:
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg-container
image: <image-pribadi-kamu>
imagePullSecrets:
- name: regcred
Unduh berkas diatas:
wget -O my-private-reg-pod.yaml https://k8s.io/examples/pods/private-reg-pod.yaml
Dalam berkas my-private-reg-pod.yaml
, ubah <your-private-image>
dengan tautan ke image dalam register pribadi seperti ini:
your.private.registry.example.com/janedoe/jdoe-private:v1
Untuk menarik image dari register pribadi, Kubernetes memerlukan kredensial.
Bidang imagePullSecrets
dalam berkas konfigurasi menentukan bahwa Kubernetes harus mendapatkan kredensial dari Secret yang bernama regcred
.
Buatlah Pod yang menggunakan Secret kamu, dan verifikasi bahwa Pod tersebut berjalan:
kubectl apply -f my-private-reg-pod.yaml
kubectl get pod private-reg
Selanjutnya
- 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.
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
registry.k8s.io/busybox
. Berikut ini adalah berkas konfigurasi untuk Pod tersebut:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: registry.k8s.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
Pada berkas konfigurasi di atas, kamu dapat melihat bahwa Pod memiliki satu Container
.
Field periodSeconds
menentukan bahwa kubelet harus melakukan probe liveness setiap 5 detik.
Field initialDelaySeconds
memberitahu kubelet untuk menunggu 5 detik sebelum mengerjakan
probe yang pertama. Untuk mengerjakan probe, kubelet menjalankan perintah cat /tmp/healthy
pada Container tujuan. Jika perintah berhasil, kode 0 akan dikembalikan, dan kubelet menganggap
Container sedang dalam kondisi hidup (alive) dan sehat (healthy). Jika perintah mengembalikan
kode selain 0, maka kubelet akan mematikan Container dan mengulangnya kembali.
Saat dimulai, Container akan menjalankan perintah berikut:
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600"
Container memiliki berkas /tmp/healthy
pada saat 30 detik pertama setelah dijalankan.
Kemudian, perintah cat /tmp/healthy
mengembalikan kode sukses. Namun setelah 30 detik,
cat /tmp/healthy
mengembalikan kode gagal.
Buatlah sebuah Pod:
kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml
Dalam 30 detik pertama, lihatlah event dari Pod:
kubectl describe pod liveness-exec
Keluaran dari perintah tersebut memperlihatkan bahwa belum ada probe liveness yang gagal:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
24s 24s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "registry.k8s.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "registry.k8s.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
Setelah 35 detik, lihatlah lagi event Pod tersebut:
kubectl describe pod liveness-exec
Baris terakhir dari keluaran tersebut memperlihatkan pesan bahwa probe liveness mengalami kegagalan, dan Container telah dimatikan dan dibuat ulang.
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
37s 37s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "registry.k8s.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "registry.k8s.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
2s 2s 1 {kubelet worker0} spec.containers{liveness} Warning Unhealthy Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Tunggu 30 detik lagi, dan verifikasi bahwa Container telah diulang kembali:
kubectl get pod liveness-exec
Keluaran perintah tersebut memperlihatkan bahwa jumlah RESTARTS
telah meningkat:
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
Mendefinisikan probe liveness dengan permintaan HTTP
Jenis kedua dari probe liveness menggunakan sebuah permintaan GET HTTP. Berikut ini
berkas konfigurasi untuk Pod yang menjalankan Container dari image registry.k8s.io/e2e-test-images/agnhost
.
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: registry.k8s.io/e2e-test-images/agnhost:2.40
args:
- liveness
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
Pada berkas konfigurasi tersebut, kamu dapat melihat Pod memiliki sebuah Container.
Field periodSeconds
menentukan bahwa kubelet harus mengerjakan probe liveness setiap 3 detik.
Field initialDelaySeconds
memberitahu kubelet untuk menunggu 3 detik sebelum mengerjakan
probe yang pertama. Untuk mengerjakan probe tersebut, kubelet mengirimkan sebuah permintaan
GET HTTP ke server yang sedang berjalan di dalam Container dan mendengarkan (listen) pada porta 8080.
Jika handler path /healthz
yang dimiliki server mengembalikan kode sukses, kubelet menganggap
Container sedang dalam kondisi hidup dan sehat. Jika handler mengembalikan kode gagal,
kubelet mematikan Container dan mengulangnya kembali.
Kode yang lebih besar atau sama dengan 200 dan kurang dari 400 mengindikasikan kesuksesan. Kode selain ini mengindikasikan kegagalan.
Kamu dapat melihat kode program untuk server ini pada server.go.
Untuk 10 detik pertama setelah Container hidup (alive), handler /healthz
mengembalikan
status 200. Setelah itu, handler mengembalikan status 500.
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
Pemeriksaan kesehatan (health check) dilakukan kubelet 3 detik setelah Container dimulai, sehingga beberapa pemeriksaaan pertama akan berhasil. Namun setelah 10 detik, pemeriksaan akan gagal, dan kubelet akan mematikan dan mengulang Container kembali.
Untuk mencoba pemeriksaan liveness HTTP, marilah membuat sebuah Pod:
kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml
Setelah 10 detik, lihatlah event Pod untuk memverifikasi bahwa probe liveness telah gagal dan Container telah diulang kembali:
kubectl describe pod liveness-http
Untuk rilis sebelum v1.13 (termasuk v1.13), jika variabel lingkungan
http_proxy
(atau HTTP_PROXY
) telah diatur pada Node dimana Pod
berjalan, probe liveness HTTP akan menggunakan proksi tersebut.
Untuk rilis setelah v1.13, pengaturan variabel lingkungan pada proksi HTTP lokal
tidak mempengaruhi probe liveness HTTP.
Mendefinisikan probe liveness TCP
Jenis ketiga dari probe liveness menggunakaan sebuah soket TCP. Dengan konfigurasi ini, kubelet akan mencoba untuk membuka soket pada Container kamu dengan porta tertentu. Jika koneksi dapat terbentuk dengan sukses, maka Container dianggap dalam kondisi sehat. Namun jika tidak berhasil terbentuk, maka Container dianggap gagal.
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: registry.k8s.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
Seperti yang terlihat, konfigurasi untuk pemeriksaan TCP cukup mirip dengan
pemeriksaan HTTP. Contoh ini menggunakan probe readiness dan liveness.
Probe readiness yang pertama akan dikirimkan oleh kubelet, 5 detik setelah
Container mulai dijalankan. Container akan coba dihubungkan oleh kubelet dengan
goproxy
pada porta 8080. Jika probe berhasil, maka Pod akan ditandai menjadi
ready. Pemeriksaan ini akan dilanjutkan oleh kubelet setiap 10 detik.
Selain probe readiness, probe liveness juga termasuk di dalam konfigurasi.
Probe liveness yang pertama akan dijalankan oleh kubelet, 15 detik setelah Container
mulai dijalankan. Sama seperti probe readiness, kubelet akan mencoba untuk
terhubung dengan Container goproxy
pada porta 8080. Jika probe liveness gagal,
maka Container akan diulang kembali.
Untuk mencoba pemeriksaan liveness TCP, marilah membuat sebuah Pod:
kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml
Setelah 15 detik, lihatlah event Pod untuk memverifikasi probe liveness tersebut:
kubectl describe pod goproxy
Menggunakan sebuah porta dengan nama
Kamu dapat menggunakan ContainerPort dengan nama untuk melakukan pemeriksaan liveness HTTP atau TCP:
ports:
- name: liveness-port
containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
Melindungi Container yang lambat untuk dimulai dengan probe startup
Terkadang kamu harus berurusan dengan aplikasi peninggalan (legacy) yang
memerlukan waktu tambahan untuk mulai berjalan pada saat pertama kali diinisialisasi.
Pada kasus ini, cukup rumit untuk mengatur parameter probe liveness tanpa
mengkompromikan respons yang cepat terhadap deadlock yang memotivasi digunakannya
probe_ tersebut. Triknya adalah mengatur probe startup dengan perintah yang sama,
baik pemeriksaan HTTP ataupun TCP, dengan failureThreshold * periodSeconds
yang
mencukupi untuk kemungkinan waktu memulai yang terburuk.
Sehingga, contoh sebelumnya menjadi:
ports:
- name: liveness-port
containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 10
startupProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 30
periodSeconds: 10
Berkat probe startup, aplikasi akan memiliki paling lambat 5 menit (30 * 10 = 300 detik)
untuk selesai memulai.
Ketika probe startup telah berhasil satu kali, maka probe liveness akan
mengambil alih untuk menyediakan respons cepat terhadap deadlock Container.
Jika probe startup tidak pernah berhasil, maka Container akan dimatikan setelah
300 detik dan perilakunya akan bergantung pada restartPolicy
yang dimiliki Pod.
Mendefinisikan probe readiness
Terkadang aplikasi tidak dapat melayani lalu lintas jaringan sementara. Contohnya, aplikasi mungkin perlu untuk memuat data besar atau berkas konfigurasi saat dimulai, atau aplikasi bergantung pada layanan eksternal setelah dimulai. Pada kasus-kasus ini, kamu tidak ingin mematikan aplikasi, tetapi kamu tidak ingin juga mengirimkan permintaan ke aplikasi tersebut. Kubernetes menyediakan probe readiness sebagai solusinya. Sebuah Pod dengan Container yang melaporkan dirinya tidak siap, tidak akan menerima lalu lintas jaringan dari Kubernetes Service.
Catatan:
Probe readiness dijalankan di dalam Container selama siklus hidupnya.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:
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.
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"
Perhatian:
Ketika memasukkan--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: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
# Tentukan variabel environment
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
# ConfigMap berisi nilai yang ingin kamu berikan pada SPECIAL_LEVEL_KEY
name: special-config
# Tentukan kunci yang diasosiasikan dengan nilainya
key: special.how
restartPolicy: Never
Buat Pod:
kubectl create -f https://kubernetes.io/id/examples/pods/pod-single-configmap-env-variable.yaml
Sekarang, keluaran dari Pod meliputi variabel environment SPECIAL_LEVEL_KEY=very
.
Menentukan variabel environment kontainer dengan data dari beberapa ConfigMap
-
Seperti pada contoh sebelumnya, buat ConfigMap terlebih dahulu.
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: special.how: very --- apiVersion: v1 kind: ConfigMap metadata: name: env-config namespace: default data: log_level: INFO
Buat ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmaps.yaml
-
Tentukan variabel environment pada spesifikasi Pod.
apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: registry.k8s.io/busybox command: [ "/bin/sh", "-c", "env" ] env: - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how - name: LOG_LEVEL valueFrom: configMapKeyRef: name: env-config key: log_level restartPolicy: Never
Buat Pod:
kubectl create -f https://kubernetes.io/id/examples/pods/pod-multiple-configmap-env-variable.yaml
Sekarang, keluaran Pod meliputi variabel environment SPECIAL_LEVEL_KEY=very
dan LOG_LEVEL=INFO
.
Mengatur semua pasangan kunci-nilai pada ConfigMap sebagai variabel environment kontainer
Catatan:
Fungsi ini tersedia pada Kubernetes v1.6 dan selanjutnya.-
Buat ConfigMap yang berisi beberapa pasangan kunci-nilai.
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: SPECIAL_LEVEL: very SPECIAL_TYPE: charm
Buat ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
- Gunakan
envFrom
untuk menentukan seluruh data pada ConfigMap sebagai variabel environment kontainer. Kunci dari ConfigMap akan menjadi nama variabel environment di dalam Pod.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: special-config
restartPolicy: Never
Buat Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-envFrom.yaml
Sekarang, Pod keluaran pod meliputi variabel environment SPECIAL_LEVEL=very
dan SPECIAL_TYPE=charm
.
Menggunakan variabel environment yang ditentukan ConfigMap pada perintah Pod
Kamu dapat menggunakan variabel environment yang ditentukan ConfigMap pada bagian command
dari spesifikasi Pod menggunakan sintaks substitusi Kubernetes $(VAR_NAME)
.
Sebagai contoh, spesifikasi Pod berikut
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never
dibuat dengan menjalankan
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-env-var-valueFrom.yaml
menghasilkan keluaran pada kontainer test-container
seperti berikut:
kubectl logs dapi-test-pod
very charm
Menambahkan data ConfigMap pada Volume
Seperti yang sudah dijelaskan pada Membuat ConfigMap dari berkas, ketika kamu membuat ConfigMap menggunakan --from-file
, nama dari berkas tersebut akan menjadi kunci yang disimpan pada bagian data
dari ConfigMap. Isi berkas tersebut akan menjadi nilai dari kunci tersebut.
Contoh pada bagian ini merujuk pada ConfigMap bernama special-config
, Seperti berikut.
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
Buat ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
Mengisi Volume dengan data yang disimpan Pada ConfigMap
Tambahkan nama ConfigMap di bawah bagian volumes
pada spesifikasi Pod.
Hal ini akan menambahkan data ConfigMap pada direktori yang ditentukan oleh volumeMounts.mountPath
(pada kasus ini, /etc/config
).
Bagian command
berisi daftar berkas pada direktori dengan nama-nama yang sesuai dengan kunci-kunci pada ConfigMap.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
# Berikan nama dari ConfigMap yang berisi berkas-berkas yang ingin kamu
# tambahkan ke kontainer
name: special-config
restartPolicy: Never
Buat Pod:
kubectl create -f https://kubernetes.io/i/examples/pods/pod-configmap-volume.yaml
Ketika Pod berjalan, perintah ls /etc/config/
akan menghasilkan keluaran di bawah:
SPECIAL_LEVEL
SPECIAL_TYPE
Perhatian:
Jika ada beberapa berkas pada direktori/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: registry.k8s.io/busybox
command: [ "/bin/sh","-c","cat /etc/config/keys" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: SPECIAL_LEVEL
path: keys
restartPolicy: Never
Buat Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume-specific-key.yaml
Ketika Pod berjalan, perintah cat /etc/config/keys
akan menghasilkan keluaran di bawah:
very
Perhatian:
Seperti sebelumnya, semua berkas yang sebelumnya berada pada direktori/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.
Catatan:
Kontainer yang menggunakan ConfigMap sebagai volume subPath tidak akan menerima pembaruan ConfigMap.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.
Catatan:
ConfigMap harus mereferensikan berkas-berkas properti, bukan menggantikannya. Anggaplah ConfigMap sebagai sesuatu yang merepresentasikan direktori/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.
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 exec -it nginx -c shell -- /bin/sh
Jika kamu tidak melihat prompt perintah, kamu dapat menekan tombol enter:
/ # ps ax PID USER TIME COMMAND 1 root 0:00 /pause 8 root 0:00 nginx: master process nginx -g daemon off; 14 101 0:00 nginx: worker process 15 root 0:00 sh 21 root 0:00 ps ax
Kamu dapat memberikan sinyal pada kontainer lain. Misalnya saja, mengirim sinyal SIGHUP
pada
nginx untuk menjalankan ulang proses worker. Hal ini membutuhkan kapabilitas SYS_PTRACE
.
/ # kill -HUP 8
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
15 root 0:00 sh
22 101 0:00 nginx: worker process
23 root 0:00 ps ax
Hal ini juga merupakan alasan mengapa kita dapat mengakses kontainer lain menggunakan
tautan (link) /proc/$pid/root
.
/ # head /proc/8/root/etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
Memahami Pembagian Namespace Process
Pod berbagi banyak sumber daya yang ada sehingga memungkinkan adanya pembagian namespace proses. Beberapa image kontainer bisa jadi terisolasi dari kontainer lainnya, meskipun begitu, memahami beberapa perbedaan berikut juga merupakan hal yang penting untuk diketahui:
-
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.
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.
Catatan:
Jika kamu menjalankan klaster Kubernetes dan menggunakan Pod statis untuk menjalankan Pod pada setiap Node, kamu kemungkinan harus menggunakan 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:
Untuk melihat versi, tekankubectl version
.
Laman ini mengasumsikan kamu menggunakan CRI-O untuk menjalankan Pod, dan Node kamu berjalan menggunakan sistem operasi Fedora. Instruksi untuk distribusi lain atau instalasi Kubernetes mungkin berbeda.
Membuat sebuah Pod statis
Kamu dapat mengatur Pod statis dengan menggunakan sebuah berkas konfigurasi pada file system atau sebuah berkas konfigurasi ditempatkan pada web.
Manifes Pod statis pada berkas sistem (file system)
Manifes adalah standar definisi Pod dalam format JSON atau YAML pada suatu direktori.
Gunakan field staticPodPath: <direktori>
pada
berkas konfigurasi kubelet,
yang akan membaca direktori
secara berkala dan membuat atau menghapus Pod statis sesuai dengan berkas YAML/JSON
yang bertambah atau berkurang disana.
Catatan bahwa kubelet akan mengabaikan berkas yang diawali dengan titik (dot) ketika memindai suatu direktori.
Sebagai contoh, ini cara untuk memulai server web sederhana sebagai Pod statis:
-
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
crictl ps
Keluarannya kira-kira seperti berikut:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6d05272b57e nginx:latest "nginx" 8 minutes ago Up 8 minutes k8s_web.6f802af4_static-web-fk-node1_default_67e24ed9466ba55986d120c867395f3c_378e5f3c
Kamu dapat melihat Pod mirror tersebut pada API server:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web 1/1 Running 0 2m
Catatan:
Pastikan kubelet memiliki izin untuk membuat Pod mirror pada server API. Jika tidak, pembuatannya akan ditolak oleh API server. Lihat PodSecurityPolicy.Label dari Pod statis akan dibuat juga pada Pod mirror. Kamu dapat menggunakan label tersebut seperti biasa menggunakan selector, atau yang lainnya.
Kamu dapat mencoba untuk menggunakan kubelet untuk menghapus Pod mirror tersebut pada API server, namun kubelet tidak akan menghapus Pod statis:
kubectl delete pod static-web
pod "static-web" deleted
Kamu akan melihat bahwa Pod tersebut tetap berjalan:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web 1/1 Running 0 4s
Kembali ke Node tempat kubelet berjalan, kamu dapat mencoba menghentikan Container Docker secara manual. Kamu akan melihat, setelah beberapa saat, kubelet akan mengetahui dan akan menjalankan ulang Pod secara otomatis:
# Jalankan perintah ini pada Node tempat kubelet berjalan
crictl stop 129fd7d382018 # ganti dengan ID pada Container-mu
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
89db4553e1eeb docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
Penambahan dan pengurangan secara dinamis pada Pod statis
Direktori konfigurasi (/etc/kubelet.d
pada contoh kita) akan dipindai secara berkala oleh kubelet
untuk melakukan perubahan dan penambahan/pengurangan
Pod sesuai dengan penambahan/pengurangan berkas pada direktori tersebut.
# Ini mengasumsikan kamu menggunakan konfigurasi Pod statis pada _filesystem_
# Jalankan perintah ini pada Node tempat kubelet berjalan
#
mv /etc/kubernetes/manifests/static-web.yaml /tmp
sleep 20
crictl ps
# Kamu mendapatkan bahwa tidak ada Container nginx yang berjalan
mv /tmp/static-web.yaml /etc/kubernetes/manifests/
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
f427638871c35 docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106