[IT-방법] 데몬셋 YAML 설정 파일 작성 가이드 – 클러스터 모든 노드에 에이전트를 자동 배포하는 핵심 기술

데몬셋 관련 쿠버네티스 구조를 설명하는 대표 이미지

왜 지금 데몬셋 YAML 설정 파일이 중요한가요?

클러스터 규모가 커질수록 테크리드들의 고민은 깊어져요. 로그 수집을 위한 Fluentd나 모니터링을 위한 Prometheus Node Exporter를 설치할 때, 노드가 10개라면 10번, 100개라면 100번을 일일이 Pod를 띄워야 할까요? 만약 새로운 노드가 추가될 때마다 수동으로 에이전트를 배포하고 있다면, 이는 운영 효율성을 심각하게 떨어뜨리는 요인이 돼요.

대부분의 플랫폼 팀은 이런 문제를 해결하기 위해 데몬셋(DaemonSet)을 활용해요. 데몬셋은 클러스터의 모든 노드, 혹은 특정 조건을 만족하는 노드에 Pod를 자동으로 하나씩 배치하는 아주 강력한 도구예요. 하지만 단순히 YAML 파일을 복사해서 쓰는 것만으로는 부족해요. 노드의 제약 사항을 무시하거나 잘못된 라벨 설정을 하면, 특정 노드에는 에이전트가 뜨지 않거나 엉뚱한 곳에 자원을 낭비하게 되거든요.

실무에서는 단순한 배포를 넘어, 마스터 노드에는 실행되지 않도록 설정하거나 특정 GPU가 있는 노드에만 모니터링 도구를 올리는 등의 정밀한 제어가 필요해요. 이 과정에서 데몬셋 YAML 설정 파일의 문법을 정확히 이해하지 못하면 운영 장애로 이어질 수 있어요.

이 글을 끝까지 읽고 나면 다음과 같은 역량을 갖출 수 있어요.

  • 데몬셋 매니페스트의 핵심 구조를 완벽히 이해해요.
  • 노드별 조건부 배포를 위한 스케줄링 전략을 세울 수 있어요.
  • 실무에서 즉시 복사해서 쓸 수 있는 고품질 YAML 예제를 확보해요.
  • 설정 오류로 인한 배포 실패를 빠르게 찾아내고 해결해요.

데몬셋 배포 전 반드시 확인해야 할 기본 개념

데몬셋을 작성하기 전에, 우리가 다루려는 리소스가 일반적인 Deployment(디플로이먼트)와 어떻게 다른지 명확히 구분해야 해요. 목적이 다르면 설정 방식도 완전히 달라지기 때문이에요. 데몬셋은 ‘모든 노드에 하나씩’이라는 목적에 최적화되어 있어요.

가장 먼저 고려해야 할 점은 어떤 워크로드를 데몬셋으로 관리할 것인가예요. 로그 수집기, 네트워크 플러그인, 보안 에이전트 같은 인프라 성격의 소프트웨어가 주 대상이 돼요. 이를 결정하기 위해 아래 비교 표를 참고해 보세요.

비교 항목 Deployment (디플로이먼트) DaemonSet (데몬셋)
주요 목적 애플리케이션 서비스 운영 노드별 백그라운드 에이전트 실행
Pod 배치 기준 사용 가능한 자원 기반 자유 배치 각 노드당 정확히 1개의 Pod 배치
노드 추가 시 동작 스케줄러가 판단하여 필요 시 배포 새 노드 등장 즉시 자동으로 Pod 생성
권장 사례 웹 서버, API 서버 등 Logging, Monitoring, CNI 등

또한, 데몬셋 YAML을 작성할 때 노드의 Taint(테인트)와 Toleration(톨러레이션) 개념을 반드시 숙지해야 해요. 쿠버네티스 마스터 노드(Control Plane)는 보통 일반 Pod가 올라오지 못하도록 테인트가 걸려 있어요. 만약 모니터링 에이전트를 마스터 노드에서도 실행하고 싶다면, 데몬셋 설정 파일에 해당 테인트를 허용하는 톨러레이션을 명시해야만 해요.

💡 알아두기
데몬셋은 기본적으로 모든 노드에 Pod를 실행하려고 노력하지만, nodeSelector이나 Affinity 설정을 통해 특정 조건을 만족하는 노드 그룹에만 한정하여 배포할 수도 있어요.

마지막으로 체크리스트를 준비했어요. 작성 전 이 질문들에 스스로 답해 보세요.

  • 이 서비스가 모든 노드에서 실행되어야 하는가?
  • 특정 노드(예: GPU 노드)에만 실행되어야 하는가?
  • 마스터 노드나 특정 워크로드 노드를 제외해야 하는가?
  • 노드의 파일 시스템(hostPath)에 접근해야 하는가?

데몬셋 YAML 작성 실무 6단계

이제 본격적으로 데몬셋 매니페스트를 작성해 볼게요. 단순히 형식을 맞추는 것을 넘어, 실무에서 발생하는 복잡한 요구사항을 어떻게 코드로 녹여낼지에 집중해서 설명할게요.

STEP 1. 매니페스트의 기본 골격 구성하기

모든 쿠버네티스 객체는 동일한 시작점을 가져요. apiVersionapps/v1을 사용하고, kindDaemonSet으로 지정해요. metadata 섹션에는 이름과 네임스페이스를 명시하며, 여기서 정의한 이름은 나중에 관리 및 로그 추적 시 매우 중요해요.

기본적인 구조는 다음과 같아요.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: my-agent
  namespace: kube-system
spec:
  # 여기에 상세 설정이 들어갑니다

이 초기 설정이 틀리면 쿠버네티스 API 서버가 요청을 거절해요. 특히 네임스페이스를 명시하지 않으면 기본값인 default 네임스페이스에 생성되는데, 인프라 에이전트는 보통 kube-system에 격리하여 관리하는 것이 보안상 안전해요.

STEP 2. Selector와 Template의 완벽한 일치시키기

데몬셋에서 가장 실수가 많은 구간이 바로 selectortemplate.metadata.labels 사이의 관계예요. 데몬셋 컨트롤러는 selector에 정의된 라벨을 보고 어떤 Pod를 관리할지 결정해요. 만약 이 두 값이 서로 다르면 데몬셋은 생성되지만, Pod를 제대로 관리하지 못해 무한 루프에 빠지거나 에러를 내뱉어요.

반드시 아래와 같이 라벨을 일치시켜 주세요.

spec:
  selector:
    matchLabels:
      app: my-agent
  template:
    metadata:
      labels:
        app: my-agent

라벨은 단순한 이름표가 아니에요. 나중에 서비스(Service)를 통해 이 Pod들에 접근하거나, 다른 리소스가 이 Pod들을 식별할 때 기준이 되는 중요한 데이터예요. 너무 포괄적인 이름보다는 app.kubernetes.io/name: my-agent와 같은 표준 형식을 권장해요.

STEP 3. Pod Spec 상세 설정: 리소스와 볼륨

에이전트 성격의 Pod는 노드의 자원을 직접 사용하거나 노드 파일에 접근하는 경우가 많아요. 따라서 container 설정 시 resources.limitsresources.requests를 반드시 설정해야 해요. 에이전트가 자원을 무한정 사용하면 노드 전체가 다운될 수 있기 때문이죠.

또한, 노드의 로그를 읽어야 한다면 hostPath 볼륨을 사용해야 해요. 아래 예시처럼 노드의 특정 경로를 Pod 내부로 연결해 주세요.

containers:
- name: agent
  image: agent-image:v1
  volumeMounts:
  - name: host-logs
    mountPath: /var/log
volumes:
- name: host-logs
  hostPath:
    path: /var/log

이때 주의할 점은 경로의 보안이에요. 너무 광범위한 노드 경로를 마운트하면 Pod가 탈취되었을 때 노드 전체가 위험해질 수 있으니 필요한 최소한의 경로만 노출하세요.

STEP 4. NodeSelector를 통한 타겟팅 전략

모든 노드가 아닌, 특정 하드웨어나 환경을 가진 노드에만 데몬셋을 띄우고 싶다면 nodeSelector을 활용하세요. 예를 들어, GPU가 장착된 노드에만 모니터링 에이전트를 올리고 싶다면 노드에 hardware=gpu라는 라벨을 붙이고 아래와 같이 작성해요.

spec:
  template:
    spec:
      nodeSelector:
        hardware: gpu

이 방식은 매우 직관적이고 빠르지만, 조건이 복잡해지면 한계가 있어요. 예를 들어 ‘A 라벨이 있거나 B 라벨이 있는 노드’ 같은 논리 연산이 필요할 때는 nodeAffinity를 사용해야 해요. affinity는 좀 더 정교한 스케줄링을 가능하게 해 줘요.

STEP 5. Taints와 Tolerations로 제약 조건 극복하기

클러스터의 마스터 노드는 보안을 위해 node-role.kubernetes.io/control-plane:NoSchedule 같은 테인트가 걸려 있어요. 데몬셋이 이 노드에서도 실행되어야 한다면, 반드시 tolerations 설정을 추가해야 해요. 이 설정이 없으면 데몬셋 Pod는 마스터 노드를 건너뛰고 일반 워커 노드에만 배치돼요.

spec:
  template:
    spec:
      tolerations:
      - key: "node-role.kubernetes.io/control-plane"
        operator: "Exists"
        effect: "NoSchedule"

여기서 operator: “Exists”는 해당 키가 존재하기만 하면 테인트를 무시하겠다는 뜻이에요. 매우 유용한 패턴이니 꼭 기억해 두세요.

STEP 6. 실무형 종합 예제 매니페스트

지금까지 배운 내용을 모두 통합한 실무용 데몬셋 예제를 보여드릴게요. 이 예제는 노드의 시스템 로그를 수집하는 에이전트를 가정하며, 마스터 노드에서도 실행되고 특정 라벨이 있는 노드에 우선 배치되도록 설계되었어요.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: system-log-agent
  namespace: kube-system
  labels:
    app: log-collector
spec:
  selector:
    matchLabels:
      app: log-collector
  template:
    metadata:
      labels:
        app: log-collector
    spec:
      # 마스터 노드에서도 실행될 수 있도록 설정
      tolerations:
      - key: "node-role.kubernetes.io/control-plane"
        operator: "Exists"
        effect: "NoSchedule"
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"
      # 특정 조건의 노드 선호 (Affinity 활용)
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            preference:
              matchExpressions:
              - key: zone
                operator: In
                values:
                - kr-central-1
      containers:
      - name: collector
        image: fluentd:v1.14
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
      volumes:
      - name: varlog
        hostPath:
          path: /var/log

이 YAML은 단순히 배포만 하는 것이 아니라, 자원 관리, 보안, 스케줄링 정밀도를 모두 고려한 완성형 모델이에요. 실제 환경에 맞게 값을 조금씩 수정해서 바로 테스트해 보세요.

자주 하는 실수와 해결법

데몬셋을 운영하다 보면 예상치 못한 상황이 자주 발생해요. 현장에서 가장 많이 마주치는 5가지 사례를 정리했어요.

  • 실수: Selector와 Pod Label 불일치
    왜 발생하는가: 매니페스트 수정 중 template의 라벨만 바꾸고 selector는 그대로 두는 경우예요.
    해결법: 반드시 spec.selector.matchLabelsspec.template.metadata.labels가 완전히 동일한지 확인하세요.
  • 실수: 마스터 노드에 Pod가 생성되지 않음
    왜 발생하는가: 마스터 노드에 설정된 Taint를 무시할 수 있는 Toleration이 누락되었기 때문이에요.
    해결법: 마스터 노드의 Taint 정보를 확인하고, 그에 맞는 tolerations 블록을 추가하세요.
  • 실수: 노드의 파일 시스템 접근 실패
    왜 발생하는가: hostPath 경로를 잘못 지정했거나, 보안 정책(PSP/Kyverno 등)에 의해 차단된 경우예요.
    해결법: 노드에서 실제 해당 경로가 존재하는지 확인하고, 클러스터의 보안 정책을 검토하세요.
  • 실수: 특정 노드에서 Pod가 Pending 상태로 유지됨
    왜 발생하는가: nodeSelector로 지정한 라벨을 가진 노드가 클러스터에 하나도 없기 때문이에요.
    해결법: 노드 라벨을 확인하거나, nodeSelector 조건을 완화하세요.
  • 실수: 과도한 자원 점유로 인한 노드 불안정
    왜 발생하는가: 데몬셋 Pod에 resources.limits를 설정하지 않아 에이전트가 폭주하는 경우예요.
    해결법: 모든 데몬셋에는 반드시 CPU와 Memory의 limit를 명시해야 해요.

자주 묻는 질문

Q. 데몬셋의 이미지를 업데이트하려면 어떻게 해야 하나요?

A. YAML 파일에서 image 필드의 태그를 새 버전으로 수정한 뒤, kubectl apply -f <파일명>.yaml 명령어를 실행하면 돼요. 쿠버네티스가 자동으로 각 노드의 Pod를 순차적으로 교체해 줍니다.

Q. 특정 노드 하나에서만 데몬셋을 제외하고 싶어요. 가능한가요?
A. 네, 가능해요. 제외하고 싶은 노드에 특정 라벨을 붙인 뒤, 데몬셋의 nodeSelector를 설정하거나, 반대로 nodeAffinityDoesNotExist 연산자를 사용하여 해당 라벨이 없는 노드에만 배포되도록 설정하면 돼요.

Q. 데몬셋이 중복 실행되지는 않나요?
A. 데몬셋의 핵심 원칙은 ‘노드당 하나’예요. 만약 중복 실행된다면, Selector 설정이 잘못되어 기존 Pod를 제어하지 못하고 새 Pod를 계속 만들고 있는 상황일 가능성이 높아요.

Q. 마스터 노드에 Pod를 띄우는 게 보안상 위험하지 않나요?
A. 맞아요. 그래서 꼭 필요한 경우(모니터링, 로그 수집 등)에만 톨러레이션을 사용하여 제한적으로 허용하는 것이 베스트 프랙티스예요. 무분별한 배포는 피해야 해요.

성공적인 데몬셋 운영을 위한 요약

데몬셋은 클러스터 관리의 자동화를 완성하는 핵심 요소예요. 오늘 살펴본 내용을 바탕으로 안정적인 인프라 에이전트를 운영해 보세요.

✅ 핵심 요약

  • Selector와 Template 라벨은 무조건 일치시켜야 해요.
  • 노드 파일 접근 시 hostPath 사용 시 보안을 주의하세요.
  • 마스터 노드 배포 시에는 반드시 Toleration을 설정하세요.
  • 자원 폭주를 막기 위해 Resource Limit은 필수예요.
  • NodeSelector와 Affinity로 배포 대상을 정교하게 제어하세요.
  • 설정 변경 후에는 apply와 diff로 검증하는 습관을 가지세요.

데몬셋 설정이 완료되었다면, 이제 실제 환경에 적용해 볼 차례예요. 명령어를 바로 실행하기보다는 kubectl diff -f <파일명>.yaml을 통해 어떤 변화가 일어날지 먼저 확인하는 과정을 거치길 강력히 권장해요.

오늘 배운 내용이 클러스터 운영 효율을 높이는 데 도움이 되었기를 바라요. 실습 중에 설정값이 적용되지 않거나 예상치 못한 에러가 발생한다면, 주저하지 말고 댓글로 상황을 공유해 주세요. 함께 고민해 드릴게요!

관련하여 더 깊이 있는 학습을 원하신다면 아래 글들도 참고해 보세요.

  • 쿠버네티스 데몬셋 기본 개념 글
  • 클러스터 구축 및 운영 입문 글

댓글 남기기