ЁЯПл The SchoolтА║тШ╕я╕П KubernetesтА║ЁЯзп рдзрдбрд╛ 21 тАФ DaemonSets: рдкреНрд░рддреНрдпреЗрдХ рдордЬрд▓реНрдпрд╛рд╡рд░ рдПрдХ
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯзп рдзрдбрд╛ 21 тАФ DaemonSets: рдкреНрд░рддреНрдпреЗрдХ рдордЬрд▓реНрдпрд╛рд╡рд░ рдПрдХ

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: рдзрдбрд╛ 21 / 26 ┬╖ рдорд╛рдЧреАрд▓: lesson-20-taints-affinity ┬╖ рдкреБрдвреАрд▓: lesson-22-statefulsets


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдЖрдзреАрдЪреЗ рд╕рдЧрд│реЗ, рдЖрдгрд┐ workload рдЪрд╛ рддрд┐рд╕рд░рд╛ рдЖрдХрд╛рд░: DaemonSets тАФ рдкреНрд░рддреНрдпреЗрдХ node рд╡рд░ рдиреЗрдордХрд╛ рдПрдХ pod.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рдЖрдЧ-рд╕реБрд░рдХреНрд╖реЗрдЪреЗ рдирд┐рдпрдо ЁЯзп: "рдкреНрд░рддреНрдпреЗрдХ рдордЬрд▓реНрдпрд╛рд╡рд░ рдПрдХ рдЕрдЧреНрдирд┐рд╢рд╛рдордХ." "рдЗрдорд╛рд░рддреАрдд рдХреБрдареЗрддрд░реА рджреЛрди рдЕрдЧреНрдирд┐рд╢рд╛рдордХ" рдирд╛рд╣реА тАФ рдкреНрд░рддреНрдпреЗрдХ рдордЬрд▓реНрдпрд╛рд╡рд░, рдиреЗрдордХрд╛ рдПрдХ, рдЕрдкрд╡рд╛рдж рдирд╛рд╣реА. рдирд╡рд╛ рдордЬрд▓рд╛ рдмрд╛рдВрдзрд▓рд╛? рддреНрдпрд╛рд╕реЛрдмрдд рдЕрдЧреНрдирд┐рд╢рд╛рдордХ рдпреЗрддреЛ. рдордЬрд▓рд╛ рдкрд╛рдбрд▓рд╛? рддреНрдпрд╛рдЪрд╛ рдЕрдЧреНрдирд┐рд╢рд╛рдордХрд╣реА рдЬрд╛рддреЛ.

рд╣рд╛рдЪ DaemonSet тАФ рдЖрддрд╛ рддреБрдореНрд╣рд╛рд▓рд╛ рдорд╛рд╣реАрдд рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рддреАрди рдЖрдХрд╛рд░рд╛рдВрдЪреА рддреБрд▓рдирд╛ рдХрд░рд╛:

рдкреНрд░рддреНрдпреЗрдХ рдордЬрд▓реНрдпрд╛рд╡рд░ рдХреЛрдг рд╣рд╡реЗ? рдЗрдорд╛рд░рддреАрдЪрд╛ рд╕реНрд╡рддрдГрдЪрд╛ рдХрд░реНрдордЪрд╛рд░реА рд╡рд░реНрдЧ: рдХреЙрд░рд┐рдбреЙрд░рдордзрд▓реНрдпрд╛ рдлреЛрдирдЪреА wiring (kube-proxy тАФ рдзрдбрд╛ 04 рдЪреНрдпрд╛ Services рдкреНрд░рддреНрдпрдХреНрд╖ route рдХрд╕реЗ рдХрд░рддрд╛рдд!), intercom рдмрд╕рд╡рдгрд╛рд░рд╛ (CNI plugin), log collectors (рддреНрдпрд╛ рдмрд╛рдХрд╛рд╡рд░рдЪреНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ pod рдЪреА рджреИрдирдВрджрд┐рдиреА рд╡рд╛рдЪреВрди рдмрд╛рд╣реЗрд░ рдкрд╛рдард╡рддрд╛рдд тАФ рдзрдбрд╛ 26 рд╣реЗ рд╡рд╛рдкрд░рддреЛ), monitoring agents (node-exporter), рдЖрдгрд┐ security sensors. рддреБрдореНрд╣реА рдзрдбрд╛ 01 рдкрд╛рд╕реВрди рдирдХрд│рдд DaemonSets рдЪрд╛рд▓рд╡рдд рдЖрд╣рд╛рдд. ЁЯдп

рддреНрдпрд╛рдВрдЪреНрдпрд╛рдХрдбреЗ рд╕рд╣рд╕рд╛ рдореВрдарднрд░ tolerations рдЕрд╕рддрд╛рдд (рдзрдбрд╛ 20!) тАФ рдЕрдЧреНрдирд┐рд╢рд╛рдордХ tainted рдордЬрд▓реНрдпрд╛рдВрд╡рд░рд╣реА рдЬрд╛рддреЛ, рдЕрдЧрджреА рд╢рд┐рдХреНрд╖рд┐рдХрд╛рдВрдЪреНрдпрд╛ рд╡рд┐рд╢реНрд░рд╛рдВрддреА-рдЦреЛрд▓реАрддрд╕реБрджреНрдзрд╛.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart TB
    ds["ЁЯзп DaemonSet: log-collector<br/>'one per desk, always'"]
    subgraph n1["ЁЯЦея╕П desk 1"]
        a1["ЁЯкС app podsтАж"]
        d1["ЁЯзп collector"]
    end
    subgraph n2["ЁЯЦея╕П desk 2"]
        a2["ЁЯкС app podsтАж"]
        d2["ЁЯзп collector"]
    end
    subgraph n3["ЁЯЦея╕П NEW desk 3<br/>added by autoscaler"]
        d3["ЁЯзп collector<br/>appears automatically"]
    end
    ds --> d1
    ds --> d2
    ds -.->|"new desk тЖТ new copy,<br/>no human involved"| d3

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдкреНрд░рддреНрдпреЗрдХ node рдЪреНрдпрд╛ рдЧрд░рдЬрд╛ Deployments рд╡рд░ рдЯрд╛рдХрддрд╛ рдпреЗрдд рдирд╛рд╣реАрдд тАФ "рдХреБрдареЗрд╣реА N copies" рдореБрд│реЗ рдЬреНрдпрд╛ node рдЪреЗ logs рддреБрдореНрд╣рд╛рд▓рд╛ рд╣рд╡реЗ рд╣реЛрддреЗ рддреНрдпрд╛рдЪ node рд╡рд░ рд╢реВрдиреНрдп collectors рдпреЗрдК рд╢рдХрддрд╛рдд. DaemonSets node-рдкрд╛рддрд│реАрд╡рд░рдЪреА infrastructure declarative рдЖрдгрд┐ рд╕реНрд╡рддрдГ рд╕рд╛рдВрднрд╛рд│рдгрд╛рд░реА рдмрдирд╡рддрд╛рдд: platform team рдЪреЗ tools fleet рд╡рд╛рдврддрд╛рдирд╛, рдХрдореА рд╣реЛрддрд╛рдирд╛ рдЖрдгрд┐ рдмрд░рд╛ рд╣реЛрддрд╛рдирд╛ рдЖрдкреЛрдЖрдк рддрд┐рдЪреНрдпрд╛рдорд╛рдЧреЗ рдЬрд╛рддрд╛рдд.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

# you already run DaemonSets тАФ meet them:
kubectl -n kube-system get daemonsets
# kube-proxy (lesson 04's routing!) + your CNI тАФ DESIRED == number of nodes

# a toy extinguisher on every floor:
kubectl -n school apply -f - <<'EOF'
apiVersion: apps/v1
kind: DaemonSet
metadata: { name: floor-watch }
spec:
  selector: { matchLabels: { app: floor-watch } }
  template:
    metadata: { labels: { app: floor-watch } }
    spec:
      containers:
        - name: watch
          image: busybox
          command: ["sh","-c","echo watching floor $(hostname); sleep infinity"]
          resources: { requests: { cpu: 10m, memory: 16Mi } }
EOF
kubectl -n school get ds,pods -o wide | grep floor
# multi-node cluster? one pod PER node. minikube: one node, one pod тАФ
#   `minikube node add` and watch a second appear by itself ЁЯОЙ
kubectl -n school delete ds floor-watch

ЁЯФз рдпрд╛ рдзрдбреНрдпрд╛рд╕рд╛рдареА kubectl

kubectl get ds -A ┬╖ kubectl rollout status ds/тАж

ЁЯФЧ рдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд: ЁЯкк AWS L18 (рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рдХрд╛рд╡рд░рдЪрд╛ CloudWatch agent)

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд▓реЗ рдкрд╛рд╣рд┐рдЬреЗ

kubectl get ds рдордзреНрдпреЗ DESIRED = nodes рдЪреА рд╕рдВрдЦреНрдпрд╛ рджрд┐рд╕рддреЗ; рдПрдХ node рдЬреЛрдбрд╛ тЖТ рдирд╡рд╛ pod рдЖрдкреЛрдЖрдк рджрд┐рд╕рддреЛ.

ЁЯз╣ рд╕рд╛рдлрд╕рдлрд╛рдИ

local cluster: kubectl delete -f k8s/ (рдХрд┐рдВрд╡рд╛ рддреБрдореНрд╣реА apply рдХреЗрд▓реЗрд▓реА file) тАФ EKS рд╡рд░ рдЪрд╛рд▓реВ рд░рд╛рд╣рд┐рд▓реЗрд▓реНрдпрд╛ рдХрд╢рд╛рдЪреЗрд╣реА рддрд╛рд╕рд╛рдкреНрд░рдорд╛рдгреЗ рдмрд┐рд▓ рдпреЗрддреЗ

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

тПня╕П рдкреБрдвреЗ

рдирд╛рд╡реЗ рдЖрдгрд┐ рд╕реНрд╡рддрдГрдЪреЗ drawers рдЕрд╕рд▓реЗрд▓реЗ pods тАФ cluster рдЪреНрдпрд╛ рдЖрдд database, рдиреАрдЯрдкрдгреЗ рдЪрд╛рд▓рд╡рдгреЗ: StatefulSets.

git checkout lesson-22-statefulsets

ЁЯзп Lesson 21 тАФ DaemonSets: one on every floor

ЁЯУН You are here: Lesson 21 of 26 ┬╖ Previous: lesson-20-taints-affinity ┬╖ Next: lesson-22-statefulsets


ЁЯУж What's in this branch

Everything before, plus the third workload shape: DaemonSets тАФ exactly one pod on EVERY node.

ЁЯзТ Explain like I'm 5

Fire safety rules ЁЯзп: "one fire extinguisher on EVERY floor." Not "two extinguishers somewhere in the building" тАФ every floor, exactly one, no exceptions. New floor built? Extinguisher appears with it. Floor demolished? Its extinguisher goes too.

That's a DaemonSet тАФ compare the three shapes you now know:

Who needs to be on every floor? The building's own staff: the hall-phone wiring (kube-proxy тАФ how lesson 04's Services actually route!), the intercom installer (the CNI plugin), log collectors (read every pod's diary on that desk and ship it out тАФ lesson 26 uses this), monitoring agents (node-exporter), and security sensors. You've been running DaemonSets since lesson 01 without knowing it. ЁЯдп

They usually carry a fistful of tolerations (lesson 20!) тАФ the fire extinguisher goes on tainted floors too, even the teacher's lounge.

ЁЯЧ║я╕П Diagram

flowchart TB
    ds["ЁЯзп DaemonSet: log-collector<br/>'one per desk, always'"]
    subgraph n1["ЁЯЦея╕П desk 1"]
        a1["ЁЯкС app podsтАж"]
        d1["ЁЯзп collector"]
    end
    subgraph n2["ЁЯЦея╕П desk 2"]
        a2["ЁЯкС app podsтАж"]
        d2["ЁЯзп collector"]
    end
    subgraph n3["ЁЯЦея╕П NEW desk 3<br/>added by autoscaler"]
        d3["ЁЯзп collector<br/>appears automatically"]
    end
    ds --> d1
    ds --> d2
    ds -.->|"new desk тЖТ new copy,<br/>no human involved"| d3

тЭУ What

ЁЯдФ Why

Per-node concerns can't ride on Deployments тАФ "N copies anywhere" might put zero collectors on the one node whose logs you needed. DaemonSets make node-level infrastructure declarative and self-maintaining: the platform team's tools follow the fleet automatically as it grows, shrinks and heals.

ЁЯзк Try it

# you already run DaemonSets тАФ meet them:
kubectl -n kube-system get daemonsets
# kube-proxy (lesson 04's routing!) + your CNI тАФ DESIRED == number of nodes

# a toy extinguisher on every floor:
kubectl -n school apply -f - <<'EOF'
apiVersion: apps/v1
kind: DaemonSet
metadata: { name: floor-watch }
spec:
  selector: { matchLabels: { app: floor-watch } }
  template:
    metadata: { labels: { app: floor-watch } }
    spec:
      containers:
        - name: watch
          image: busybox
          command: ["sh","-c","echo watching floor $(hostname); sleep infinity"]
          resources: { requests: { cpu: 10m, memory: 16Mi } }
EOF
kubectl -n school get ds,pods -o wide | grep floor
# multi-node cluster? one pod PER node. minikube: one node, one pod тАФ
#   `minikube node add` and watch a second appear by itself ЁЯОЙ
kubectl -n school delete ds floor-watch

ЁЯФз kubectl for this lesson

kubectl get ds -A ┬╖ kubectl rollout status ds/тАж

ЁЯФЧ Builds on: ЁЯкк AWS L18 (the CloudWatch agent on every desk)

тЬЕ Verify тАФ what you should see

kubectl get ds shows DESIRED = number of nodes; add a node тЖТ a new pod appears by itself.

ЁЯз╣ Clean up

local cluster: kubectl delete -f k8s/ (or the file you applied) тАФ on EKS, anything left running bills by the hour

тЪая╕П Common mistakes

тПня╕П Next

Pods with NAMES and their own drawers тАФ running a database inside the cluster, properly: StatefulSets.

git checkout lesson-22-statefulsets
тЖР Previoustaints affinityNext тЖТstatefulsets

This page is the lesson's README from the lesson-21-daemonsets branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.