DaemonSet

Agen yang berjalan satu per Node melalui DaemonSet: pola logging, pemantauan, dan penjadwalannya.

Daftar isi

DaemonSet adalah objek workload yang menjamin satu Pod berjalan di setiap Node yang cocok dengan seleksinya. Berbeda dari Deployment yang mengatur jumlah replika secara manual, jumlah Pod pada DaemonSet mengikuti jumlah Node di kluster. Topik ini membahas pola agen per Node, yaitu pengumpul logging ke arsip cadangan berkas dan agen pemantauan, pengaruh taint terhadap penempatan, serta perbandingan Deployment, DaemonSet, dan Job dalam satu tabel. Simulasi di bagian akhir menghitung penempatan Pod agen dari berkas manifest nyata.

Satu Pod per Node#

DaemonSet membuat satu Pod pada setiap Node yang labelnya cocok dengan nodeSelector atau Node affinity pada bagian spec.template, tanpa perantara ReplicaSet dan tanpa bidang replicas. Controller memantau daftar Node, sehingga setiap Node baru yang bergabung langsung menerima Pod agen, sedangkan Pod pada Node yang keluar ikut terhapus. Jumlah Pod yang diinginkan tidak ditulis di manifest, karena nilainya selalu sama dengan jumlah Node yang lolos seleksi.

Kedudukan Pod yang menempel pada Node tersebut penting bagi agen. Pod agen membaca sumber daya yang dimiliki Node secara langsung, misalnya berkas log pada /var/log atau statistik perangkat keras, sehingga pekerjaan itu tidak dapat dilakukan oleh Pod yang dijadwalkan bebas. Apabila satu Node bertambah, kapasitas agen bertambah satu Pod, dan apabila Node berkurang, Pod-nya hilang bersama Node itu.

Pembaruan image agen mengikuti bidang updateStrategy. Strategi bawaan RollingUpdate mengganti Pod per Node dengan batas maxUnavailable, sedangkan strategi OnDelete hanya mengganti agen apabila Pod di Node tersebut dihapus secara manual. Keduanya beroperasi per Node, bukan per replika seperti pada Deployment.

Pola agen per Node#

Dua pola mencakup sebagian besar penggunaan DaemonSet. Pola pertama adalah pengumpul logging, yaitu agen yang membaca log dari setiap Node dan menulis arsip cadangan berkas ke direktori Node masing-masing. Pola kedua adalah agen pemantauan yang melaporkan metrik perangkat keras dan container dari setiap Node. Keduanya harus hadir di semua Node, sehingga Deployment yang boleh menumpuk Pod di satu Node tidak memenuhi kebutuhan tersebut.

Akses langsung ke berkas Node memerlukan volume hostPath, yaitu volume yang memetakan direktori Node ke dalam Pod. Berkas log container dibaca dari /var/log dalam keadaan hanya-baca, sedangkan arsip ditulis ke direktori Node yang dibuat bila belum ada melalui type: DirectoryOrCreate. Karena setiap Pod menulis ke arsip Node-nya sendiri, tidak ada perselisihan penulisan antara agen.

Berkas daemonset.yaml berikut mendefinisikan DaemonSet bernama pengumpul-log yang mengemas arsip log setiap Node pekerja setiap satu jam:

yaml daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pengumpul-log
  labels:
    app: pengumpul-log
spec:
  selector:
    matchLabels:
      app: pengumpul-log
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: pengumpul-log
    spec:
      nodeSelector:
        peran: pekerja
      tolerations:
        - key: node.kubernetes.io/disk-pressure
          operator: Exists
          effect: NoSchedule
      containers:
        - name: pengumpul
          image: busybox:1.36
          command:
            - sh
            - -c
            - >-
              while true; do
                tar -czf /arsip/log-$(date +%s).tar.gz /log-node;
                sleep 3600;
              done
          volumeMounts:
            - name: log
              mountPath: /log-node
              readOnly: true
            - name: arsip
              mountPath: /arsip
      volumes:
        - name: log
          hostPath:
            path: /var/log
            type: Directory
        - name: arsip
          hostPath:
            path: /var/arsip-log
            type: DirectoryOrCreate

Perintah berikut menerapkan manifest tersebut lalu menampilkan jumlah Pod agen per keadaan. Kolom DESIRED sama dengan jumlah Node yang lolos seleksi, dan tidak ada nilai yang diatur manual:

bash
# tidak-dijalankan
# terapkan manifest DaemonSet ke kluster
kubectl apply -f daemonset.yaml
# tampilkan DaemonSet beserta jumlah pod per keadaannya
kubectl get daemonset pengumpul-log
text Contoh keluaran
NAME           DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
pengumpul-log  4         4         4       4            4           peran=pekerja   40s

DaemonSet dan taint#

Taint adalah penanda pada Node yang menolak Pod tanpa toleration yang cocok, dan DaemonSet tidak dikecualikan dari aturan itu. Node control-plane membawa taint node-role.kubernetes.io/control-plane:NoSchedule, sehingga agen tidak berjalan di sana kecuali toleration yang cocok ditambahkan ke template. Taint kondisional seperti node.kubernetes.io/disk-pressure menahan Pod agen selama kondisi bermasalah, dan Pod baru dibuat kembali setelah kondisinya pulih.

Pemilihan Node dilakukan dengan dua lapis seleksi. nodeSelector menyaring Node berdasarkan label, sedangkan tolerations menentukan taint mana yang dapat ditembus. Dua lapis tersebut bekerja bersama, yaitu Node harus lolos seleksi label dan seluruh taint-nya harus ditoleransi, sehingga pengurangan cakupan agen dapat dilakukan dari salah satu lapis saja.

Agen pada Node control-plane sering memang diperlukan, misalnya untuk mengumpulkan log komponen control-plane. Apabila agen harus hadir di seluruh Node, toleration yang cocok ditambahkan ke template, sedangkan apabila Node control-plane sengaja dikeluarkan, seleksi yang ada sudah cukup. Keputusan ini menentukan cakupan agen sejak manifest ditulis.

Simulasi penempatan per Node#

Skrip berikut membaca daemonset.yaml, lalu menghitung penempatan Pod agen pada lima Node dengan aturan yang sama seperti scheduler, yaitu seleksi label terlebih dahulu, kemudian pemeriksaan taint terhadap tolerations. Kelima Node mewakili susunan kluster belajar yang umum, yaitu tiga Node pekerja sehat, satu Node pekerja bermasalah, dan satu Node control-plane. Scheduler asli juga menimbang sumber daya yang tersedia, sedangkan simulasi ini membatasi diri pada dua aturan seleksi agar hasilnya dapat dihitung ulang persis. Perhitungan kedua dijalankan dengan tolerations dihapus untuk memperlihatkan dampaknya secara langsung.

python simulasi-daemonset.py
"""Perhitungan penempatan pod DaemonSet per node dengan nodeSelector dan taint."""
import yaml

with open("daemonset.yaml", encoding="utf-8") as berkas:
    ds = yaml.safe_load(berkas)
pod_spec = ds["spec"]["template"]["spec"]
node_selector = pod_spec.get("nodeSelector", {})
tolerations = pod_spec.get("tolerations", [])

# daftar node beserta label dan taint yang terpasang
NODE = [
    ("node-1", {"peran": "pekerja"}, []),
    ("node-2", {"peran": "pekerja"}, []),
    ("node-3", {"peran": "pekerja"}, []),
    ("node-4", {"peran": "pekerja"}, [("node.kubernetes.io/disk-pressure", "NoSchedule")]),
    ("node-0", {}, [("node-role.kubernetes.io/control-plane", "NoSchedule")]),
]


def cocok_tolerasi(taint, daftar_tolerasi):
    """Benar bila seluruh taint ditoleransi oleh daftar tolerations."""
    return all(
        any(
            (kunci_t == t["key"] or t["key"] == "")
            and t["operator"] == "Exists"
            and (t["effect"] == "" or t["effect"] == efek_t)
            for t in daftar_tolerasi
        )
        for kunci_t, efek_t in taint
    )


def status_node(label, taint, daftar_tolerasi):
    cocok_label = all(label.get(k) == v for k, v in node_selector.items())
    if not cocok_label:
        return "dilewati (label tidak cocok)"
    if taint and not cocok_tolerasi(taint, daftar_tolerasi):
        return "dilewati (taint tidak ditoleransi)"
    return "pod dibuat"


print(f"DaemonSet    : {ds['metadata']['name']}")
print(f"nodeSelector : {node_selector}")
print()
print("Penempatan dengan tolerations pada manifest:")
for nama, label, taint in NODE:
    print(f"  {nama:<8} {status_node(label, taint, tolerations)}")
jumlah = sum(1 for _, label, taint in NODE if status_node(label, taint, tolerations) == "pod dibuat")
print(f"Total: {jumlah} dari {len(NODE)} node")
print()
print("Penempatan tanpa tolerations (tolerations dihapus):")
for nama, label, taint in NODE:
    print(f"  {nama:<8} {status_node(label, taint, [])}")
jumlah_tanpa = sum(1 for _, label, taint in NODE if status_node(label, taint, []) == "pod dibuat")
print(f"Total: {jumlah_tanpa} dari {len(NODE)} node")
text Keluaran
DaemonSet    : pengumpul-log
nodeSelector : {'peran': 'pekerja'}

Penempatan dengan tolerations pada manifest:
  node-1   pod dibuat
  node-2   pod dibuat
  node-3   pod dibuat
  node-4   pod dibuat
  node-0   dilewati (label tidak cocok)
Total: 4 dari 5 node

Penempatan tanpa tolerations (tolerations dihapus):
  node-1   pod dibuat
  node-2   pod dibuat
  node-3   pod dibuat
  node-4   dilewati (taint tidak ditoleransi)
  node-0   dilewati (label tidak cocok)
Total: 3 dari 5 node

Keluaran menunjukkan empat Node memperoleh agen dengan tolerations pada manifest, sedangkan Node control-plane tertahan karena tidak membawa label peran: pekerja. Tanpa tolerations, Node keempat ikut tertahan karena taint disk-pressure tidak lagi ditoleransi, sehingga jumlah agen turun menjadi tiga. Angka yang sama akan muncul pada kolom DESIRED apabila DaemonSet yang sama diterapkan pada kluster dengan lima Node tersebut. Seluruh keputusan bersifat per Node, dan tidak ada alokasi jumlah Pod yang diatur manual di mana pun.

Deployment, DaemonSet, dan Job dalam satu tabel#

Tiga objek tersebut berbagi mekanisme template Pod, tetapi menjawab pertanyaan penempatan yang berbeda. Deployment membagi replika ke Node mana pun yang memiliki sumber daya, DaemonSet menautkan satu Pod pada setiap Node yang lolos seleksi, sedangkan Job mengisi jumlah slot pekerjaan tanpa mengikat Pod ke Node tertentu. Ketiganya memuat spec.template yang sama, sehingga pemindahan definisi Pod antara objek hanya mengubah penempatan dan masa hidupnya.

AspekDeploymentDaemonSetJob
Jumlah PodDitetapkan melalui replicasSatu per Node yang lolos seleksiDitetapkan melalui completions
PenempatanBebas mengikuti sumber daya NodeMenempel pada Node tertentuBebas mengikuti sumber daya Node
Masa hidup PodTerus berjalanTerus berjalan selama Node adaBerhenti setelah sukses
Contoh kegunaanLayanan web aplikasi catatanPengumpul log dan agen pemantauanPemrosesan statistik nilai ujian

Tabel tersebut menegaskan batas masing-masing objek. Agen yang dijalankan sebagai Deployment dapat menumpuk di satu Node dan menyisakan Node lain tanpa agen, sedangkan agen yang dijalankan sebagai Job hanya berjalan sekali dan berhenti sebelum Node berikutnya bergabung. DaemonSet memenuhi syarat kehadiran yang berkelanjutan pada setiap Node, dan itulah satu-satunya alasan objek ini dipilih.

Ringkasan#

  • DaemonSet membuat satu Pod pada setiap Node yang lolos seleksi, dan jumlah Pod mengikuti jumlah Node tanpa bidang replicas.
  • Pola utamanya adalah agen per Node, seperti pengumpul log ke arsip cadangan berkas dan agen pemantauan, yang mengakses berkas Node melalui volume hostPath.
  • Taint menahan Pod agen pada Node yang bermasalah, sedangkan nodeSelector dan tolerations menentukan cakupan agen.
  • Pembaruan template berjalan per Node melalui RollingUpdate dengan maxUnavailable atau menunggu penghapusan manual pada strategi OnDelete.

Referensi#