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:

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.

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

FEATURE STATE: 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.