2026年5月31日

2026年5月31日

KubernetesのDaemonSetの使い方|全ノードに1つずつPodを置く仕組み・YAML・更新とPodが置かれないときの調べ方

DaemonSetは、クラスターの各ノードにPodを1つずつ置くためのリソースです。ログ収集、ノードの監視、ネットワークやストレージのエージェントのように「ノードごとに1つ動いていてほしい」処理に使います。ノードが増えれば自動でPodが追加され、ノードが外れればPodも消えます。この記事では、Deploymentとの違い、node-exporterを例にしたYAMLの書き方、対象ノードの絞り方、更新の方法、一部のノードにPodが置かれないときの調べ方を説明します。

内容は、Kubernetesの現行のサポート対象の版(2026年10月現在)で共通して使える項目に絞っています。

Deploymentとの違いと向いている用途

Deploymentは「Podを何個動かすか」を replicas で決め、どのノードに置くかはスケジューラーに任せます。DaemonSetには replicas がありません。数はノードの数で決まり、各ノードに1つずつ置かれます。

DaemonSetが向いているのは、ノードそのものに結び付いた処理です。

  • ログ収集:各ノードに出力されたコンテナのログを読み、集約先に送る(Fluent Bit、Fluentdなど)。
  • ノードの監視:CPU・メモリ・ディスクなどノードの状態を集める(Prometheusのnode-exporterなど)。
  • ネットワーク・ストレージ:CNIプラグインやCSIドライバーのノード側の部品、kube-proxyなど。

WordPressのアプリ本体のように、ノードの数とは関係なく必要な処理能力で数を決めたいものには、Deploymentを使います。WordPressのPodが標準出力に出すアクセスログやエラーログを集める側が、DaemonSetの出番です。

マネージドサービスでは、DaemonSetを置けないノードの種類があります。例えばEKSのFargateで動くPodには、DaemonSetは配置されません。サイドカーなど別の方法を使うことになるので、構成を決める前に確認してください。

YAMLを書く(node-exporterの例)

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
  labels:
    app: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule
      containers:
        - name: node-exporter
          image: quay.io/prometheus/node-exporter:v1.8.2
          args:
            - --path.rootfs=/host
          ports:
            - containerPort: 9100
          resources:
            requests:
              cpu: 50m
              memory: 64Mi
            limits:
              memory: 128Mi
          securityContext:
            readOnlyRootFilesystem: true
            runAsNonRoot: true
            runAsUser: 65534
          volumeMounts:
            - name: root
              mountPath: /host
              readOnly: true
              mountPropagation: HostToContainer
      volumes:
        - name: root
          hostPath:
            path: /

各項目の意味は次のとおりです。

  • **selector と template.metadata.labels**:Deploymentと同じく一致させます。作成後に selector は変更できません。
  • **hostNetwork / hostPID**:ノードのネットワークとプロセスの情報を見るための設定です。ノードの指標を集めるnode-exporterでは一般的ですが、コンテナとノードの隔たりが小さくなります。必要な場合だけ使います。
  • **hostPath**:ノードのファイルシステムをPodに見せます。ここではノード全体を読み取り専用でマウントしています。書き込み可能なhostPathは、Podが乗っ取られたときにノードごと改ざんされる危険があるため、避けられるなら避けます。
  • **tolerations**:コントロールプレーンのノードには、通常のPodが置かれないよう「taint(汚れ)」が付いています。そこでも監視したい場合だけ、このtolerationを付けます。
  • **resources.requests**:DaemonSetは全ノードで動くため、1つあたりの要求が小さくても合計は「ノード数 × 要求量」になります。他のPodの置き場所を圧迫しない値にします。

イメージのタグは例です。使うときは公式のリリース情報で現在の版を確認し、タグを固定してください。

作成と確認

kubectl create namespace monitoring
kubectl apply -f node-exporter.yaml
kubectl rollout status daemonset/node-exporter -n monitoring
kubectl get daemonset -n monitoring
kubectl get pods -n monitoring -o wide -l app=node-exporter

kubectl get daemonset の主な列は、DESIRED(置くべきPodの数)、CURRENT(作られた数)、READY(準備完了の数)、UP-TO-DATE(最新の設定の数)、AVAILABLE(利用可能な数)です。DESIRED は「条件に合うノードの数」なので、クラスターのノード数より少なくても異常とは限りません。-o wide を付けると、各Podがどのノードで動いているかが分かります。

置くノードを絞る

一部のノードだけで動かしたいときは、Podのテンプレートに条件を書きます。

spec:
  template:
    spec:
      nodeSelector:
        node-role/logging: "true"

この例では、node-role/logging=true のラベルが付いたノードだけにPodが置かれます。ラベルは kubectl label node <ノード名> node-role/logging=true で付けます。ラベル名は例なので、自分の環境の命名規則に合わせてください。より細かい条件は affinity.nodeAffinity で書けます。

逆に、taintの付いたノードにも置きたいときは、そのtaintに合う tolerations を足します。DaemonSetのPodには、ノードの準備未完了やメモリ・ディスクの逼迫などのtaintに対するtolerationが自動で付くため、状態の悪いノードからもすぐには追い出されません。監視やログ収集が、問題の起きているノードで止まらないようにするための仕組みです。

更新する

updateStrategy には2種類あります。

  • RollingUpdate(既定):テンプレートを変えると、古いPodを止めて新しいPodを作る、をノードごとに順に進めます。maxUnavailable(既定は1)で、同時に止めてよい数を決めます。maxSurge を指定すると、古いPodを止める前に新しいPodを起動する動きにもできますが、hostPort を使っているとポートが重なって起動できないため、組み合わせに注意します。
  • OnDelete:テンプレートを変えても自動では入れ替わらず、Podを手で削除したときに新しい設定で作り直されます。ネットワークのエージェントなど、1ノードずつ様子を見ながら入れ替えたいときに使います。
kubectl apply -f node-exporter.yaml
kubectl rollout status daemonset/node-exporter -n monitoring
kubectl rollout history daemonset/node-exporter -n monitoring
kubectl rollout undo daemonset/node-exporter -n monitoring

ノードが多いクラスターでは、maxUnavailable: 1 だと更新に時間がかかります。ログ収集のように一時的に止まっても困らないものは、割合(例: 10%)にして速めることもできます。一方、CNIのようにノードの通信を担うものは、慎重に1つずつ進めます。

一部のノードにPodが置かれないときの調べ方

DESIRED がノード数より少ない、または特定のノードだけPodがない、Pending のまま、という場合は、起きやすい順に次を確かめます。

kubectl describe daemonset node-exporter -n monitoring
kubectl get nodes --show-labels
kubectl describe node <ノード名>
kubectl describe pod <Pod名> -n monitoring
  1. taintにtolerationが合っていない:describe node の Taints 欄を見ます。GPUノードや専用ノードに独自のtaintが付いていると、DaemonSetのPodも置かれず、DESIRED に数えられません。必要ならtolerationを足します。
  2. nodeSelectorやaffinityの条件に合わない:--show-labels でラベルを確かめます。ラベルの値のつづりや、"true" を文字列にしていない、といった誤りが多いです。
  3. リソースが足りない:Podが Pending で、Events に「Insufficient cpu」「Insufficient memory」と出ます。そのノードがすでに他のPodで埋まっています。requests を減らすか、DaemonSetに priorityClassName で高い優先度を与え、他のPodより先に置かれるようにします。クラスターの動作に欠かせない部品には、組み込みの system-node-critical が使われます。
  4. hostPortの衝突:同じノードで同じ hostPort を使う別のPodがあると起動できません。

Podは置かれているのに READY にならない場合は、通常のPodと同じく kubectl logs と describe pod で原因を見ます。hostPathのパスがノードの種類によって違う、セキュリティの設定で読み取りが拒否されている、といったノード依存の原因が出やすいのがDaemonSetの特徴です。

まとめ

  • DaemonSetは各ノードに1つずつPodを置く。数はノードの数と条件で決まり、replicas はない。
  • ログ収集・ノード監視・ネットワークやストレージのエージェントに使い、アプリ本体はDeploymentで動かす。
  • hostNetwork・hostPID・hostPath は必要な場合だけ使い、hostPathは読み取り専用にする。
  • 対象ノードは nodeSelector やaffinityで絞り、taintのあるノードにはtolerationを足す。
  • 置かれないときはtaint、ラベル、リソース、hostPortの順に確かめる。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲