はじめに
Kubernetes クラスタを IBM Instana で監視していたところ、master(control-plane)ノードも Host としてカウントされ、ライセンス使用量が想定より多くなっていることが判明しました。
本記事では、master ノードのみを監視対象から除外し、ライセンス使用量を最適化した実装方法とエビデンスを共有します。
TL;DR
- Instana Agent の DaemonSet に
nodeAffinityを追加 -
control-plane/masterラベルを持つノードを除外 - master 3台分のライセンスコストを削減
- worker ノードの監視は継続
対象読者
- Kubernetes で Instana を運用している方
- DaemonSet の配置制御を学びたい方
- ライセンスコストを最適化したい方
背景・課題
Instana のライセンス体系
Instana は Host 単位での課金モデルを採用しています。
- Kubernetes 環境では各 Node が 1 Host としてカウント
- master ノードも監視対象になるとコスト増
- 実際のアプリケーションは worker ノードで稼働
課題
今回の環境では:
- master ノード 3台が監視対象
- 実際のアプリケーションは worker ノードで稼働
- master ノードの監視は不要だがライセンスを消費
master01, master02, master03 → 3 Hosts 分のコスト
この無駄なコストを削減するため、master ノードのみを監視対象から除外することにしました。
環境情報
| 項目 | 内容 |
|---|---|
| Kubernetes | v1.24+ |
| Instana Agent | DaemonSet 形式 |
| master ノード数 | 3台 |
| worker ノード数 | 複数台 |
変更前の状態
master ノードに instana-agent が存在
$ kubectl -n instana-agent get pod -o wide | grep master
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
instana-agent-jn9v6 1/1 Running 89 (10d ago) 40d 10.1.1.113 master03 <none> <none>
instana-agent-k8sensor-7d598f5c69-vzzz7 1/1 Running 6 (3d3h ago) 33d 10.1.1.113 master03 <none> <none>
instana-agent-mldz9 1/1 Running 40 (10d ago) 40d 10.1.1.112 master02 <none> <none>
instana-agent-nlbxc 1/1 Running 4 (10d ago) 40d 10.1.1.111 master01 <none> <none>
master 3台すべてに DaemonSet が展開されていました。
注目ポイント:
-
instana-agent-jn9v6,instana-agent-mldz9,instana-agent-nlbxc→ DaemonSet -
instana-agent-k8sensor-7d598f5c69-vzzz7→ Deployment(別管理)
実施内容
nodeAffinity の追加
DaemonSet の spec.template.spec.affinity に以下を追加:
--- 10_before_ds_full.yaml 2026-02-05 00:15:53.348354217 +0900
+++ 20_after_ds_full.yaml 2026-02-05 00:21:59.040960291 +0900
@@ -43,7 +43,15 @@
app.kubernetes.io/part-of: instana
instana/agent-mode: APM
spec:
- affinity: {}
+ affinity:
+ nodeAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ nodeSelectorTerms:
+ - matchExpressions:
+ - key: node-role.kubernetes.io/control-plane
+ operator: DoesNotExist
+ - key: node-role.kubernetes.io/master
+ operator: DoesNotExist
containers:
- env:
- name: CONFIG_PATH
設定の意味
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: DoesNotExist
- key: node-role.kubernetes.io/master
operator: DoesNotExist
この設定により:
-
node-role.kubernetes.io/control-planeラベルが存在しないノード -
node-role.kubernetes.io/masterラベルが存在しないノード
の両方の条件を満たすノードにのみ Pod が配置されます。
2つのラベルを指定する理由
| Kubernetes バージョン | master ノードのラベル |
|---|---|
| 1.20 以降 | node-role.kubernetes.io/control-plane |
| 1.19 以前 | node-role.kubernetes.io/master |
両方指定することでバージョン互換性を確保しています。
適用コマンド
# DaemonSet を更新
kubectl apply -f modified_ds.yaml
# ロールアウト確認
kubectl rollout status daemonset/instana-agent -n instana-agent
結果:
daemon set "instana-agent" successfully rolled out
変更の視覚化
変更前後の Pod 配置
変更後の状態
master ノードから DaemonSet が除外された
$ kubectl -n instana-agent get pod -o wide | grep master
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
instana-agent-k8sensor-7d598f5c69-vzzz7 1/1 Running 6 (3d3h ago) 33d 10.1.1.113 master03 <none> <none>
DaemonSet 本体は消えました!
除外された Pod:
- ❌
instana-agent-jn9v6(master03) - ❌
instana-agent-mldz9(master02) - ❌
instana-agent-nlbxc(master01)
残存した Pod:
- ✅
instana-agent-k8sensor-7d598f5c69-vzzz7(Deployment)
重要ポイント
1. DaemonSet と k8sensor の違い
| コンポーネント | 種類 | 役割 | master 除外の影響 |
|---|---|---|---|
instana-agent |
DaemonSet | Node 単位の Host 監視 | ✅ 除外成功 |
instana-agent-k8sensor |
Deployment | Kubernetes API 監視 | ❌ 影響なし(別管理) |
今回除外できたのは:
instana-agent-jn9v6 ← DaemonSet
instana-agent-mldz9 ← DaemonSet
instana-agent-nlbxc ← DaemonSet
k8sensor は別管理のため、master03 に残存しています。これは正常な動作です。
2. nodeAffinity の動作原理
なぜ nodeAffinity を使うのか
Kubernetes で Pod の配置を制御する方法は主に3つ:
| 方法 | 用途 | 特徴 |
|---|---|---|
| nodeSelector | シンプルな条件 | label の完全一致のみ |
| nodeAffinity | 複雑な条件 | 複数条件、演算子使用可能 |
| toleration | taint 回避 | taint されたノードへの配置 |
今回は「control-plane ラベルが存在しないノード」という条件が必要なため、DoesNotExist 演算子が使える nodeAffinity を選択しました。
nodeAffinity の種類
# 必須条件(今回使用)
requiredDuringSchedulingIgnoredDuringExecution:
# スケジュール時に必須
# 実行中の Pod には影響しない(IgnoredDuringExecution)
# 優先条件
preferredDuringSchedulingIgnoredDuringExecution:
# スケジュール時に優先(必須ではない)
今回は確実に master 除外したいため required を使用しています。
トラブルシューティング
1. Pod が削除されない
症状:
$ kubectl rollout status daemonset/instana-agent -n instana-agent
Waiting for daemon set "instana-agent" rollout to finish...
原因:
- DaemonSet の更新戦略が
OnDeleteの場合、手動削除が必要
解決方法:
# 更新戦略を確認
kubectl get ds instana-agent -n instana-agent -o yaml | grep -A 5 updateStrategy
# OnDelete の場合は手動削除
kubectl delete pod -n instana-agent -l app.kubernetes.io/name=instana-agent
# 再度ロールアウト確認
kubectl rollout status daemonset/instana-agent -n instana-agent
2. 意図しないノードから除外された
症状:
- worker ノードからも Pod が消えた
原因:
- worker ノードに誤って
control-planeラベルが付与されている
確認方法:
# 全ノードのラベルを確認
kubectl get nodes --show-labels
# 特定ノードのラベル詳細
kubectl describe node <node-name> | grep Labels -A 10
解決方法:
# 不要なラベルを削除(末尾の - に注意)
kubectl label node <node-name> node-role.kubernetes.io/control-plane-
3. k8sensor まで消えてしまった
症状:
-
instana-agent-k8sensorも削除された
原因:
- k8sensor の Deployment にも同じ nodeAffinity を適用してしまった
確認:
kubectl get deployment instana-agent-k8sensor -n instana-agent -o yaml | grep -A 10 affinity
解決方法:
- k8sensor は Deployment なので、DaemonSet とは別管理
- k8sensor の affinity は変更しない
- 誤って変更した場合は元に戻す
4. ロールアウトが完了しない
症状:
$ kubectl rollout status daemonset/instana-agent -n instana-agent
Waiting for daemon set "instana-agent" rollout to finish: 3 out of 5 new pods have been updated...
原因:
- 一部のノードで Pod が起動できない
- リソース不足やイメージ Pull エラー
確認方法:
# Pod の状態を確認
kubectl get pods -n instana-agent -o wide
# 問題のある Pod の詳細を確認
kubectl describe pod <pod-name> -n instana-agent
# イベントを確認
kubectl get events -n instana-agent --sort-by='.lastTimestamp'
結果
コスト削減効果
| 項目 | 変更前 | 変更後 | 削減 |
|---|---|---|---|
| master 監視 | 3 Hosts | 0 Hosts | -3 Hosts |
| worker 監視 | 継続 | 継続 | 変更なし |
master 3台分の Host 消費を削減できました。
監視への影響
- ✅ worker ノードの監視は継続
- ✅ k8sensor による Kubernetes API 監視は継続
- ✅ アプリケーション監視に影響なし
- ✅ master ノード自体の OS レベル監視のみ除外
まとめ
学んだこと
-
DaemonSet は全ノード対象がデフォルト
- control-plane であっても、taint が無く toleration が存在すると監視対象になる
-
nodeAffinity で control-plane 除外が可能
-
DoesNotExist演算子で「ラベルが存在しないノード」を指定 - バージョン互換性のため
control-planeとmaster両方を指定
-
-
差分と Pod 確認を必ずエビデンスとして残す
- 変更前後の状態を記録
- トラブル時の原因究明に役立つ
-
k8sensor は別管理
- DaemonSet と Deployment は別物
- それぞれ独立して管理する必要がある
注意点
- master ノードの OS レベル監視が不要な場合のみ実施
- セキュリティ監視が必要な場合は除外しない
- 変更前に必ずバックアップを取得
- ロールバック手順を事前に確認
参考資料
- Kubernetes: Assigning Pods to Nodes
- Kubernetes: Node Affinity
- Instana Documentation: Agent Configuration
おわりに
Kubernetes の DaemonSet は便利ですが、デフォルトでは全ノードに展開されるため、ライセンスコストが想定より高くなることがあります。
本記事で紹介した nodeAffinity を使った制御方法は、コスト最適化だけでなく、セキュリティやコンプライアンスの観点からも有用です。
同様の課題を抱えている方の参考になれば幸いです。