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