0. Contents

1. Overview

Daemon Service 패턴의 위치Deployment원하는 수의 Pod 복제본을 클러스터 어딘가에 배치Node 1PodPodNode 2Node 3PodDaemonSet모든(또는 특정) 노드에 Pod를 하나씩 배치이번 챕터!Node 1PodNode 2PodNode 3Pod
Daemon Service 패턴의 위치: Deployment 와 DaemonSet 의 배치 방식

비유: 쿠버네티스는 아파트 단지

  • 노드(Node) = 각 아파트 동
  • 일반 Pod = 빈방이 있는 동에 자유롭게 들어가는 주민
  • DaemonSet = 관리소가 “각 동마다 꼭 한 명씩 배치하는 경비원"을 두는 규칙

DaemonSet의 핵심 두 가지

“조건에 맞는 모든 노드에, 빠짐없이, Pod를 하나씩”


2. Daemon 이란

2.1 OS 수준의 데몬

데몬: 백그라운드 일꾼 프로그램

  • 데몬은 백그라운드에서 죽지 않고 계속 돌아가는 프로그램이다
    • 화면에 창이 뜨지 않는다
    • 컴퓨터가 켜지는 순간 알아서 시작된다
    • 문제가 생겨도 자동으로 다시 켜진다

이름 끝의 d

  • Unix/Linux에서는 이름 끝에 d를 붙이는 관례가 있다
이름역할
httpd웹 서버
sshd원격 접속
named도메인 주소 변환(DNS)

다른 OS에서의 이름

  • Windows: 서비스(Service)
  • 메인프레임: Started Task / Ghost Job

2.2 애플리케이션 수준의 데몬 (JVM)

JVM 데몬 스레드

  • OS에만 있는 개념이 아니다
  • JVM의 데몬 스레드도 같은 원리다
    • 낮은 우선순위로 백그라운드에서 실행
    • 가비지 컬렉션(GC), 파이널라이제이션 같은 보조 작업 전담
    • 메인 프로그램(사용자 스레드)이 종료되면 자신의 작업 완료 여부와 무관하게 함께 종료

사용자 스레드 vs 데몬 스레드

사용자 스레드 (User Thread)데몬 스레드 (Daemon Thread)
우선순위높은 우선순위낮은 우선순위
수명앱 수명 제어수명 제어 불가
맡는 일비즈니스 로직 처리GC, 파이널라이제이션 등 보조 작업
JVM 종료JVM이 종료를 기다림JVM 종료 시 무시됨

공통점: 24시간 백그라운드 일꾼

  • “눈에 보이지 않는 곳에서 시스템이 잘 돌아가도록 묵묵히 돕는 24시간 백그라운드 일꾼”
  • 이 개념이 이제 쿠버네티스로 확장된다

3. Problem

클러스터 수준의 인프라 작업

용도예시
클러스터 스토리지Ceph, GlusterFS 에이전트
로그 수집Fluentd, Filebeat
메트릭 수집Prometheus Node Exporter
핵심 컴포넌트kube-proxy, CNI 플러그인

공통점: 모든 노드에 똑같이 설치

  • 이런 프로그램들은 모든 서버(노드)에 똑같이 설치되어야 한다
  • 서버가 추가되면 → 자동으로 그 서버에도 설치되어야 한다
  • 서버가 제거되면 → 함께 삭제되어야 한다

Deployment의 한계

  • 일반 Deployment로는 이를 표현할 수 없다
  • “원하는 개수"를 지정하는 방식이다
    • “모든 노드에 하나씩"이라는 보장이 없다

4. Solution: DaemonSet

DaemonSet의 정의

  • DaemonSet은 클러스터의 모든(또는 특정) 노드에 Pod를 하나씩 자동으로 배치하고 유지하는 리소스다
DaemonSet노드마다 Pod를 하나씩 배치하고 유지클러스터Node 1PodDaemonSet 관리Node 2PodDaemonSet 관리Node 3PodDaemonSet 관리Node 4신규 추가Pod 자동 생성 ✅DaemonSet 관리
DaemonSet 배치 구조: 노드마다 Pod 하나, 새 노드에도 자동 생성

노드 증감에 따른 자동 처리

  • 노드가 추가되면 → 자동으로 Pod가 생성된다
  • 노드가 제거되면 → 해당 Pod도 함께 정리된다
  • 관리자가 별도로 지시하지 않아도 된다

4.1 ReplicaSet vs DaemonSet

비유: 주민 기준 vs 동 기준

ReplicaSet (주민 기준): 입주민이 많이 몰릴 것을 대비해, 동 개수와 상관없이 “무조건 총 3가구만 입주시켜!”

DaemonSet (동 기준): 모든 동을 청소하고 관리하기 위해, “동마다 무조건 경비원 1명씩 다 배치해!”

코드로 보는 차이

# ReplicaSet: 개수 기준
spec:
  replicas: 3   # 서버가 몇 대든 상관없이 총 3개

# DaemonSet: 노드 기준
# replicas 필드 없음 → 노드당 자동으로 1개

항목별 비교

항목ReplicaSetDaemonSet
Pod 개수 기준관리자가 숫자로 지정노드 수에 따라 자동 결정
트래픽 증가 시replicas 늘려서 대응변화 없음 (노드당 1개 유지)
노드 추가 시변화 없음Pod 자동 추가
주요 용도웹서버, API 서버 등 앱로그 수집기, 모니터링 에이전트 등 인프라

4.2 Example 9-1. DaemonSet Resource

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: random-refresher
spec:
  selector:
    matchLabels:
      app: random-refresher       # 이 DaemonSet이 관리할 Pod 라벨
  template:
    metadata:
      labels:
        app: random-refresher
    spec:
      nodeSelector:
        feature: hw-rng           # hw-rng 라벨이 있는 노드에만 배포
      containers:
      - image: k8spatterns/random-generator:1.0
        name: random-generator
        command: [ "java", "RandomRunner", "/numbers.txt", "10000", "30" ]
        volumeMounts:
        - mountPath: /host_dev
          name: devices
      volumes:
      - name: devices
        hostPath:
          path: /dev              # 호스트의 /dev 디렉토리를 직접 마운트

필드별 설명

  • kind: DaemonSet — “이건 일반 앱이 아니라, 서버마다 하나씩 까는 데몬셋이야”
  • nodeSelector: feature: hw-rng — 하드웨어 난수 생성기(hw-rng)가 장착된 노드들만 골라서 배포
  • hostPath: /dev — 호스트의 /dev(하드웨어 장치 경로)를 컨테이너의 /host_dev에 연결
    • 컨테이너가 실제 하드웨어 장치에 접근하기 위해 필요하다

구조 한눈에 보기

DaemonSetselector어떤 Pod를 관리할지templatePodnodeSelector: feature=hw-rng어느 노드에서 실행할지container (random-generator)뭘 실행할지volume (hostPath: /dev)호스트 장치 직접 접근
Example 9-1 의 구조: 각 필드가 정하는 것

4.3 nodeSelector — 모든 노드 vs 특정 노드

특정 노드 선택: 모순이 아닌 이유

  • “모든 노드에 하나씩"이라고 했는데 왜 특정 노드만 고르냐는 의문이 생길 수 있다
  • 모순이 아니다

“조건을 만족하는 노드들을 모아놓고, 그 안에서 모든 노드에 하나씩”

아파트 비유로 다시 보기

  • 기본 DaemonSet (조건 없음)
    • 1동, 2동, 3동, 4동, 5동 → 전부 경비원 1명씩
  • nodeSelector 적용 (hw-rng 조건)
    • 지하주차장 있는 동: 1동, 3동, 5동
    • → 1동, 3동, 5동에만 경비원 1명씩
    • → 나중에 지하주차장 있는 7동 신축 → 자동으로 7동에도 배치 ✅
nodeSelector: feature=hw-rng전체 클러스터 노드Node 1feature:hw-rngPod✅ Pod 배포Node 2(라벨 없음)❌ 배포 안됨Node 3feature:hw-rngPod✅ Pod 배포Node 4(라벨 없음)❌ 배포 안됨Node 5feature:hw-rngPod✅ Pod 배포
nodeSelector: 라벨이 맞는 노드에만 Pod 배포

일반 Pod(ReplicaSet)와의 차이

  • 여기서 일반 Pod(ReplicaSet)와의 차이도 드러난다
같은 조건(hw-rng 노드 3대)에서ReplicaSet + nodeSelector"그 노드들 중에서 아무 데나 총 3개만 켜줘"Node 1hw-rngPodPodPodNode 3hw-rngNode 5hw-rng→ Node 1에 3개가 몰릴 수도 있음DaemonSet + nodeSelector"그 노드들 각각에 무조건 1개씩 켜줘"Node 1hw-rngPodNode 3hw-rngPodNode 5hw-rngPod→ Node 1, 3, 5에 각 1개씩, 총 3개 (보장)
같은 hw-rng 노드 3대에서: ReplicaSet 과 DaemonSet 의 차이

5. DaemonSet의 주요 특징

ReplicaSet과 다른 특이점

  • DaemonSet은 일반 ReplicaSet과 동작 방식이 다른 몇 가지 특이점이 있다

스케줄러 없이도 실행 가능 (구버전 기준)

  • DaemonSet이 생성한 Pod는 nodeName이 직접 지정되어 있다
    • 쿠버네티스 스케줄러 없이도 실행된다
  • 덕분에 스케줄러가 시작되기 전에도 Pod를 띄울 수 있다
    • 즉 클러스터 부팅 초기에 어떤 Pod보다도 먼저 실행될 수 있다

unschedulable 노드도 무시

  • 노드가 drain이나 cordon 상태(unschedulable)여도 DaemonSet은 영향을 받지 않는다
  • 이유: 인프라 관리 작업은 노드 격리 상태와 무관하게 실행되어야 한다

RestartPolicy는 Always만

  • 데몬은 항상 살아있어야 한다
  • liveness probe 실패 시 컨테이너가 종료되어도 반드시 재시작이 보장되어야 한다
restartPolicy: Always     # ✅ 허용
restartPolicy: OnFailure  # ❌ 불가
restartPolicy: Never      # ❌ 불가

높은 우선순위: 컨트롤러의 특별 대우

  • DaemonSet Pod는 특정 노드에서만 실행되어야 한다
  • 그래서 여러 컨트롤러가 특별 대우를 한다
컨트롤러DaemonSet Pod 처리
Descheduler축출(eviction) 회피
Cluster Autoscaler별도로 분리해 관리

6. Scheduling Evolution

버전별 스케줄링 방식 변화

  • DaemonSet의 스케줄링 방식은 Kubernetes 버전을 거치며 크게 바뀌었다

6.1 구버전: nodeName 방식

# DaemonSet 컨트롤러가 직접 nodeName 지정
spec:
  nodeName: worker-node-1   # 스케줄러 완전 우회

nodeName 방식: 스케줄러 우회

  • 스케줄러를 거치지 않고 Pod에 직접 노드를 지정했다
  • 스케줄러 없이도 동작하고, 스케줄러보다 먼저 실행될 수 있었다
  • 하지만 문제가 있었다

노드 리소스 부족 시나리오

  1. DaemonSet 컨트롤러: “이 노드에 Pod를 배포해야 하는데…”
  2. 리소스가 없음!
  3. ❌ 아무것도 못함 (선점/Preemption 불가)

nodeName 방식의 문제

  • 스케줄러가 가진 선점(Preemption) 기능을 사용할 수 없었다
  • 스케줄링 로직이 스케줄러와 DaemonSet 컨트롤러 두 곳에 중복되어 유지보수 부담도 생겼다
  • nodeSelector, node affinity, Taint/Toleration은 컨트롤러가 직접 따져서 반영했다
    • 다만 스케줄러와 같은 판단을 컨트롤러가 따로 하다 보니 일반 Pod와 동작이 어긋났다
  • 일반 Pod는 Pending 상태로 먼저 만들어진 뒤 스케줄되지만, DaemonSet Pod는 노드가 정해진 채로 만들어져 Pending을 거치지 않았다
    • 같은 Pod인데 생성 흐름이 달라 헷갈리기 쉬웠다

6.2 신버전: nodeAffinity 방식 (v1.17+)

# nodeAffinity를 통해 기본 스케줄러에 위임
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchFields:
          - key: metadata.name
            operator: In
            values:
            - worker-node-1

기본 스케줄러에 위임

  • nodeName 직접 지정 대신 nodeAffinity를 설정한다
  • 기본 스케줄러에 위임하는 방식으로 전환했다
구버전 흐름DaemonSet 컨트롤러nodeName 직접 설정스케줄러 우회신버전 흐름 (v1.17+)DaemonSet 컨트롤러nodeAffinity 설정기본 스케줄러가 처리일반 Pod와 같은 스케줄링, 우선순위·선점 반영
DaemonSet 스케줄링: 구버전은 스케줄러 우회, 신버전은 기본 스케줄러에 위임

트레이드오프 비교

구버전신버전 (v1.17+)
스케줄러 의존성없음필수
선점(Preemption)❌✅
Node affinity / Taints 판단DaemonSet 컨트롤러가 직접기본 스케줄러
스케줄링 로직 중복있음없음
스케줄러 없이 실행가능불가

결과: 독립성 대신 안정성

  • 스케줄러 독립성을 포기했다
  • 대신 리소스 경쟁 상황에서의 안정성과 최신 스케줄러 기능을 얻었다

7. Static Pods

노드 실행의 또 다른 방법: Static Pod

  • DaemonSet과 유사하게 노드에서 컨테이너를 실행하는 또 다른 방법 — Static Pod다
  • Kubelet은 API 서버와 통신하는 것 외에, 로컬 디렉토리를 직접 감시해서 Pod를 실행할 수 있다
일반 Pod 실행 흐름사용자API Server스케줄러KubeletPod 실행Static Pod 실행 흐름/etc/kubernetes/manifests/로컬 디렉토리Kubelet직접 감시Pod 실행API Server, 스케줄러 불필요
일반 Pod 와 Static Pod 의 실행 흐름

Kubelet의 직접 관리

  • Kubelet은 해당 디렉토리를 주기적으로 스캔해 변경을 감지한다
    • Pod를 추가/제거한다
  • Pod가 크래시하면 직접 재시작한다

Static Pod vs DaemonSet

항목Static PodDaemonSet
관리 주체Kubelet만DaemonSet 컨트롤러
API Server 필요❌✅
스케줄러 필요❌✅ (v1.17+)
실행 노드1개 노드만모든(또는 지정) 노드
헬스체크(probe)✅ (Kubelet이 직접 실행)✅
kubectl로 관리❌✅
플랫폼 통합성낮음높음

주된 사용처: 쿠버네티스 시스템 컴포넌트

  • etcd, kube-apiserver, kube-controller-manager, kube-scheduler
  • 이유: API 서버 자체가 없는 상황에서도 실행되어야 한다

일반 용도: DaemonSet 권장

  • 일반적인 용도에는 DaemonSet이 권장된다
  • 플랫폼 통합성이 높고 Kubernetes 도구를 그대로 활용할 수 있다

8. Discussion

방법별 한계점

  • 노드에서 데몬 프로세스를 실행하는 방법은 여러 가지가 있지만 각각 한계가 있다
방법한계점
Static PodAPI로 관리 불가, 단일 노드에만 존재
Bare Pod삭제/노드 장애 시 복구 불가
Init 스크립트 (systemd 등)별도 툴체인 필요, Kubernetes 도구 활용 불가, 앱과 데몬을 완전히 다른 방식으로 관리해야 함

DaemonSet이 해결하는 것

  • DaemonSet은 이 모든 한계를 해결한다
    • ✅ Kubernetes API로 완전히 관리 (kubectl 그대로 사용)
    • ✅ 노드 장애 시 자동 복구
    • ✅ Affinity, Taint 등 플랫폼 기능 활용
    • ✅ 노드 추가 시 자동 배포
    • ✅ 앱과 동일한 방식으로 모니터링/운영

단일 노드 개념의 분산 프리미티브 승격

  • DaemonSet과 CronJob은 단일 노드 개념을 분산 시스템 프리미티브로 승격시킨 좋은 예시다
전통적 단일 노드 개념Kubernetes 분산 개념
crontabCronJob (클러스터 전체에서 스케줄 관리)
daemon 스크립트 (systemd, upstart)DaemonSet (모든 노드에서 일관되게 실행)

개발자에게도 필요한 개념

  • DaemonSet은 플랫폼 관리자에 가까운 도구다
  • 하지만 클러스터 인프라가 어떻게 동작하는지 이해하려는 개발자에게도 반드시 필요한 개념이다

DaemonSet이 해결해주는 문제들이 원래 복잡했던 것이지, DaemonSet 자체가 복잡한 게 아니다. 그 복잡한 걸 “각 동마다 경비원 한 명씩” 수준으로 단순하게 만들어준 것이 핵심이다.