DaemonSet
DaemonSet memastikan semua atau sebagian Node memiliki salinan sebuah Pod. Ketika Node baru ditambahkan ke klaster, Pod ditambahkan ke Node tersebut. Ketika Node dihapus dari klaster, Pod akan dibersihkan oleh garbage collector. Menghapus DaemonSet akan menghapus semua Pod yang ia buat.
Beberapa penggunaan umum DaemonSet, yaitu:
- menjalankan daemon penyimpanan di klaster, seperti
glusterd
,ceph
, di setiap Node. - menjalankan daemon pengumpulan log di semua Node, seperti
fluentd
ataulogstash
. - menjalankan daemon pemantauan Node di setiap Node, seperti Prometheus Node Exporter, Flowmill, Sysdig Agent,
collectd
, Dynatrace OneAgent, AppDynamics Agent, Datadog agent, New Relic agent, Gangliagmond
atau Instana Agent.
Dalam kasus sederhana, satu DaemonSet, mencakup semua Node, akan digunakan untuk setiap jenis daemon. Pengaturan yang lebih rumit bisa saja menggunakan lebih dari satu DaemonSet untuk satu jenis daemon, tapi dengan flag dan/atau permintaan cpu/memori yang berbeda untuk jenis hardware yang berbeda.
Menulis Spek DaemonSet
Buat DaemonSet
Kamu bisa definisikan DaemonSet dalam berkas YAML. Contohnya, berkas
daemonset.yaml
di bawah mendefinisikan DaemonSet yang menjalankan image Docker
fluentd-elasticsearch:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- Buat DaemonSet berdasarkan berkas YAML:
kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml
Field Wajib
Seperti semua konfigurasi Kubernetes lainnya, DaemonSet membutuhkan field
apiVersion
, kind
, dan metadata
. Untuk informasi umum tentang berkas konfigurasi, lihat dokumen men-deploy aplikasi,
pengaturan kontainer, dan pengelolaan objek dengan kubectl.
DaemonSet juga membutuhkan bagian .spec
.
Templat Pod
.spec.template
adalah salah satu field wajib di dalam .spec
.
.spec.template
adalah sebuah templat Pod. Skemanya benar-benar sama dengan Pod, kecuali bagian bahwa ia bersarang/nested dan tidak memiliki apiVersion
atau kind
.
Selain field wajib untuk Pod, templat Pod di DaemonSet harus menspesifikasikan label yang sesuai (lihat selektor Pod).
Templat Pod di DaemonSet harus memiliki RestartPolicy
yang bernilai Always
, atau tidak dispesifikasikan, sehingga default menjadi Always
.
DaemonSet dengan nilai Always
membuat Pod akan selalu di-restart saat kontainer
keluar/berhenti atau terjadi crash.
Selektor Pod
Field .spec.selector
adalah selektor Pod. Cara kerjanya sama dengan .spec.selector
pada Job.
Pada Kubernetes 1.8, kamu harus menspesifikasikan selektor Pod yang cocok dengan label pada .spec.template
.
Selektor Pod tidak akan lagi diberi nilai default ketika dibiarkan kosong. Nilai default selektor tidak
cocok dengan kubectl apply
. Juga, sesudah DaemonSet dibuat, .spec.selector
tidak dapat diubah.
Mengubah selektor Pod dapat menyebabkan Pod orphan yang tidak disengaja, dan membingungkan pengguna.
Objek .spec.selector
memiliki dua field:
matchLabels
- bekerja seperti.spec.selector
pada ReplicationController.matchExpressions
- bisa digunakan untuk membuat selektor yang lebih canggih dengan mendefinisikan key, daftar value dan operator yang menyatakan hubungan antara key dan value.
Ketika keduanya dispesifikasikan hasilnya diperoleh dari operasi AND.
Jika .spec.selector
dispesifikasikan, nilainya harus cocok dengan .spec.template.metadata.labels
. Konfigurasi yang tidak cocok akan ditolak oleh API.
Selain itu kamu tidak seharusnya membuat Pod apapun yang labelnya cocok dengan selektor tersebut, entah secara langsung, via DaemonSet lain, atau via workload resource lain seperti ReplicaSet. Jika kamu coba buat, Pengontrol DaemonSet akan berpikir bahwa Pod tersebut dibuat olehnya. Kubernetes tidak akan menghentikan kamu melakukannya. Contoh kasus di mana kamu mungkin melakukan ini dengan membuat Pod dengan nilai yang berbeda di sebuah Node untuk testing.
Menjalankan Pod di Sebagian Node
Jika kamu menspesifikasikan .spec.template.spec.nodeSelector
, maka controller DaemonSet akan
membuat Pod pada Node yang cocok dengan selektor
Node. Demikian juga, jika kamu menspesifikasikan .spec.template.spec.affinity
,
maka controller DaemonSet akan membuat Pod pada Node yang cocok dengan Node affinity.
Jika kamu tidak menspesifikasikan sama sekali, maka controller DaemonSet akan
membuat Pod pada semua Node.
Bagaimana Pod Daemon Dijadwalkan
Dijadwalkan oleh default scheduler
Kubernetes v1.23 [stable]
DaemonSet memastikan bahwa semua Node yang memenuhi syarat menjalankan salinan Pod. Normalnya, Node yang menjalankan Pod dipilih oleh scheduler Kubernetes. Namun, Pod DaemonSet dibuat dan dijadwalkan oleh controller DaemonSet. Hal ini mendatangkan masalah-masalah berikut:
- Inkonsistensi perilaku Pod: Pod normal yang menunggu dijadwalkan akan dibuat
dalam keadaan
Pending
, tapi Pod DaemonSet tidak seperti itu. Ini membingungkan untuk pengguna. - Pod preemption ditangani oleh default scheduler. Ketika preemption dinyalakan, controller DaemonSet akan membuat keputusan penjadwalan tanpa memperhitungkan prioritas Pod dan preemption.
ScheduleDaemonSetPods
mengizinkan kamu untuk menjadwalkan DaemonSet
menggunakan default scheduler daripada controller DaemonSet, dengan
menambahkan syarat NodeAffinity
pada Pod DaemonSet daripada syarat
.spec.nodeName
. Kemudian, default scheduler digunakan untuk mengikat Pod ke
host target. Jika afinitas Node dari Pod DaemonSet sudah ada, maka ini
akan diganti. Controller DaemonSet hanya akan melakukan operasi-operasi ini
ketika membuat atau mengubah Pod DaemonSet, dan tidak ada perubahan yang terjadi
pada spec.template
DaemonSet.
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-name
Sebagai tambahan, toleration node.kubernetes.io/unschedulable:NoSchedule
ditambahkan secara otomatis pada Pod DaemonSet. Default scheduler akan
mengabaikan Node unschedulable
ketika menjadwalkan Pod DaemonSet.
Taint dan Toleration
Meskipun Pod Daemon menghormati taint dan toleration, toleration berikut ini akan otomatis ditambahkan ke Pod DaemonSet sesuai dengan fitur yang bersangkutan.
Toleration Key | Effect | Versi | Deskripsi |
---|---|---|---|
node.kubernetes.io/not-ready |
NoExecute | 1.13+ | Pod DaemonSet tidak akan menjadi evicted ketika ada masalah Node seperti partisi jaringan. |
node.kubernetes.io/unreachable |
NoExecute | 1.13+ | Pod DaemonSet tidak akan menjadi evicted ketika ada masalah Node seperti partisi jaringan. |
node.kubernetes.io/disk-pressure |
NoSchedule | 1.8+ | |
node.kubernetes.io/memory-pressure |
NoSchedule | 1.8+ | |
node.kubernetes.io/unschedulable |
NoSchedule | 1.12+ | Pod DaemonSet mentoleransi atribut unschedulable default scheduler. |
node.kubernetes.io/network-unavailable |
NoSchedule | 1.12+ | Pod DaemonSet yang menggunakan jaringan host mentoleransi atribut network-unavailable default scheduler. |
Berkomunikasi dengan Pod Daemon
Beberapa pola yang mungkin digunakan untuk berkomunikasi dengan Pod dalam DaemonSet, yaitu:
- Push: Pod dalam DaemonSet diatur untuk mengirim pembaruan status ke servis lain, contohnya stats database. Pod ini tidak memiliki klien.
- IP Node dan Konvensi Port: Pod dalam DaemonSet dapat menggunakan
hostPort
, sehingga Pod dapat diakses menggunakan IP Node. Klien tahu daftar IP Node dengan suatu cara, dan tahu port berdasarkan konvensi. - DNS: Buat headless service dengan Pod selektor yang sama,
dan temukan DaemonSet menggunakan resource
endpoints
atau mengambil beberapa A record dari DNS. - Service: Buat Servis dengan Pod selektor yang sama, dan gunakan Servis untuk mengakses daemon pada Node random. (Tidak ada cara mengakses spesifik Node)
Melakukan Pembaruan DaemonSet
Jika label Node berubah, DaemonSet akan menambahkan Pod ke Node cocok yang baru dan menghapus Pod dari Node tidak cocok yang baru.
Kamu bisa mengubah Pod yang dibuat DaemonSet. Namun, Pod tidak membolehkan perubahan semua field. Perlu diingat, controller DaemonSet akan menggunakan templat yang asli di waktu selanjutnya Node baru (bahkan dengan nama yang sama) dibuat.
Kamu bisa menghapus DaemonSet. Jika kamu spesifikasikan --cascade=false
dengan kubectl
, maka
Pod akan dibiarkan pada Node. Jika kamu pada waktu kemudian membuat DaemonSet baru dengan selektor
yang sama, DaemonSet yang baru akan mengadopsi Pod yang sudah ada. Jika ada Pod yang perlu diganti,
DaemonSet akan mengganti sesuai dengan updateStrategy
.
Kamu bisa melakukan rolling update pada DaemonSet.
Alternatif DaemonSet
Init Scripts
Kamu mungkin menjalankan proses daemon dengan cara menjalankan mereka langsung pada Node (e.g.
menggunakan init
, upstartd
, atau systemd
). Tidak ada salahnya seperti itu. Namun, ada beberapa
keuntungan menjalankan proses daemon via DaemonSet.
- Kemampuan memantau dan mengatur log daemon dengan cara yang sama dengan aplikasi.
- Bahasa dan alat Konfigurasi yang sama (e.g. Templat Pod,
kubectl
) untuk daemon dan aplikasi. - Menjalankan daemon dalam kontainer dengan batasan resource meningkatkan isolasi antar daemon dari kontainer aplikasi. Namun, hal ini juga bisa didapat dengan menjalankan daemon dalam kontainer tapi tanpa Pod (e.g. dijalankan langsung via Docker).
Pod Polosan
Dimungkinkan untuk membuat Pod langsung dengan menspesifikasikan Node mana untuk dijalankan. Namun, DaemonSet akan menggantikan Pod yang untuk suatu alasan dihapus atau dihentikan, seperti pada saat kerusakan Node atau pemeliharaan Node yang mengganggu seperti pembaruan kernel. Oleh karena itu, kamu perlu menggunakan DaemonSet daripada membuat Pod satu per satu.
Pod Statis
Dimungkinkan untuk membuat Pod dengan menulis sebuah berkas ke direktori tertentu yang di-watch oleh Kubelet. Pod ini disebut dengan istilah Pod statis. Berbeda dengan DaemonSet, Pod statis tidak dapat dikelola menggunakan kubectl atau klien API Kubernetes yang lain. Pod statis tidak bergantung kepada apiserver, membuat Pod statis berguna pada kasus-kasus bootstrapping klaster.
Deployment
DaemonSet mirip dengan Deployment sebab mereka sama-sama membuat Pod, dan Pod yang mereka buat punya proses yang seharusnya tidak berhenti (e.g. peladen web, peladen penyimpanan)
Gunakan Deployment untuk layanan stateless, seperti frontend, di mana proses scaling naik dan turun jumlah replika dan rolling update lebih penting daripada mengatur secara tepat di host mana Pod berjalan. Gunakan DaemonSet ketika penting untuk satu salinan Pod selalu berjalan di semua atau sebagian host, dan ketika Pod perlu berjalan sebelum Pod lainnya.