2026年5月31日
2026年5月31日
KubernetesのNodeのtaint・tolerationの設定|専用ノードの作り方とPendingになったときの確認
taintは「このノードには、許可を持つPod以外を載せない」という印をノードに付ける仕組みで、tolerationはPod側に持たせる許可証です。ただしtolerationは「載ってもよい」という許可にすぎず、そのノードへ引き寄せる力はありません。特定のPodだけを専用ノードに集めたいなら、taintとnodeAffinity(またはnodeSelector)を組み合わせます。この記事では、taintの付け方・外し方、tolerationの書き方、専用ノードの作り方、そしてPodがPendingになったときの確認方法を順に説明します。
内容は、Kubernetesの現行のサポート対象の版(2026年10月現在)で共通する仕様に基づいています。
taintの3つの効果(effect)
taintは キー=値:効果 の形で書きます。効果は3種類あり、違いを押さえておくことが設定ミスを防ぐ近道です。
- NoSchedule:tolerationの無いPodを新しく載せません。すでに動いているPodはそのまま残ります。
- PreferNoSchedule:できるだけ載せないようにしますが、他に空きが無ければ載せることがあります。弱い指定です。
- NoExecute:新しく載せないだけでなく、tolerationの無い動作中のPodを退去(evict)させます。
運用中のノードにいきなり NoExecute を付けると、そのノードのPodが一斉に退去します。専用ノード化の作業では、まず NoSchedule で新規の配置を止め、既存のPodを計画的に移してから必要に応じて NoExecute を検討する、という順序が安全です。
taintを付ける・確認する・外す
# 付ける:キー dedicated、値 db、効果 NoSchedule
kubectl taint nodes node-1 dedicated=db:NoSchedule
# 確認する
kubectl describe node node-1 | grep -A3 -i taints
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
# 外す:末尾にハイフンを付ける
kubectl taint nodes node-1 dedicated=db:NoSchedule-
# 同じキーと効果の値を変える
kubectl taint nodes node-1 dedicated=cache:NoSchedule --overwrite
外すときの末尾のハイフンは見落としやすい書き方です。キーだけ指定して dedicated- とすると、そのキーの全効果のtaintが外れます。
マネージドサービス(EKS、GKE、AKSなど)では、ノードを kubectl taint で直接変えても、ノードの作り直しや自動スケールで新しく作られたノードには反映されません。ノードグループ(ノードプール)の設定でtaintを指定するのが基本です。指定方法や項目名はサービスと版によって異なるため、各サービスの公式ドキュメントで確認してください。
tolerationの書き方
Podの spec.tolerations に書きます。Deploymentなら spec.template.spec.tolerations です。
tolerations:
# キーと値が一致するtaintを許容する
- key: "dedicated"
operator: "Equal"
value: "db"
effect: "NoSchedule"
# 値を問わず、キーが一致すれば許容する
- key: "gpu"
operator: "Exists"
effect: "NoSchedule"
照合のルールは次のとおりです。
operator: Equalは、キー・値・効果が一致するtaintを許容します。operatorを省略した場合は Equal として扱われます。operator: Existsは値を書かず、キー(と効果)が一致すれば許容します。effectを省略すると、そのキーの全効果に一致します。- キーを空にして
operator: Existsとすると、あらゆるtaintを許容します。障害ノードやコントロールプレーンにも載り得るため、監視エージェントのような用途以外では使わないほうが安全です。
ノードに複数のtaintがある場合、Podはその全部を許容しないと載れません(PreferNoScheduleを除く)。一つだけ許容して安心していると、残りのtaintでPendingになります。
NoExecute と tolerationSeconds
NoExecute のtaintには、退去までの猶予を tolerationSeconds で指定できます。
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 60
ノードと通信できなくなると、Kubernetesはノードに node.kubernetes.io/unreachable や node.kubernetes.io/not-ready のtaintを自動で付けます。多くのクラスタでは、Podにこの2つへの許容(猶予300秒)が既定で追加されます。障害時にもっと早く別ノードへ移したいPodでは、上のように猶予を短くします。逆に短すぎると、一時的なネットワーク断でもPodが退去して作り直しが増えるため、値は業務への影響を見て決めます。
専用ノードを作る:taintとnodeAffinityの組み合わせ
例として、DB用のノードにDB以外を載せず、DBのPodはそのノードにだけ載せる設定を作ります。
- ノードにラベルとtaintの両方を付けます。
kubectl label nodes node-1 dedicated=db
kubectl taint nodes node-1 dedicated=db:NoSchedule
- DBのPodに、tolerationとnodeAffinityの両方を書きます。
spec:
template:
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "db"
effect: "NoSchedule"
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "dedicated"
operator: In
values: ["db"]
taintが「他のPodを締め出す」役、nodeAffinityが「DBのPodをそこへ寄せる」役です。tolerationだけだと、DBのPodは空いている一般ノードにも載ります。nodeAffinityだけだと、一般のPodも専用ノードに入り込みます。両方そろえて初めて専用ノードになります。
WordPressの構成でいえば、MySQLのStatefulSetを高速なディスクを積んだノードに寄せ、WordPress本体やバッチ処理のPodがそのノードのCPUを奪わないようにする、といった使い方ができます。
自動で付くtaintと、よく見るもの
自分で付けていないtaintがノードに付いていることがあります。代表的なものは次のとおりです。
node-role.kubernetes.io/control-plane:NoSchedule:kubeadmなどで構築したクラスタのコントロールプレーンに付きます。通常のアプリを載せないためのものです。node.kubernetes.io/not-ready/unreachable:ノードの異常時に付きます。node.kubernetes.io/memory-pressure/disk-pressure/pid-pressure:ノードの資源が逼迫したときに付きます。node.kubernetes.io/unschedulable:kubectl cordonしたノードに付きます。
これらが付いているときは、taintを外すのではなく、原因(ディスクの逼迫やkubeletの停止)を解消するのが正しい対処です。taintは症状の表示なので、外しても問題は残ります。
なお、DaemonSetのPodには、こうした状態系のtaintへの許容が自動で追加されます。監視エージェントなどが異常なノードでも動き続けられるのはこのためです。ただし自分で付けた dedicated のようなtaintへの許容は追加されないため、全ノードで動かしたいDaemonSetには明示的にtolerationを書きます。
Pendingになったときの確認手順
taint絡みでPodが載らないとき、kubectl describe pod の Events に次のような行が出ます。
0/3 nodes are available: 1 node(s) had untolerated taint {dedicated: db}, 2 Insufficient memory.
この行は、ノードごとに「載せられなかった理由」を数えたものです。読み方の順序は次のとおりです。
- untolerated taint の数とキーを見る:表示されたキーと値が、Pod側のtolerationと一字一句合っているか確認します。値の大文字小文字、効果の指定違い(NoSchedule と NoExecute)がよくある原因です。
- 他の理由も同時に読む:上の例では、taintの無い2台はメモリ不足です。tolerationを直しても専用ノードの空きが無ければ、やはり載りません。
- Pod側の実際の値を確認する:
kubectl get pod <pod名> -o jsonpath='{.spec.tolerations}'で、テンプレートの変更が実際のPodに反映されているかを見ます。HelmのvaluesやKustomizeの重ね合わせで、書いたつもりのtolerationが落ちていることがあります。
本番のノードのtaintを変える前には、kubectl get nodes -o yaml で現在の状態を保存し、検証用のクラスタで同じ組み合わせを試してから反映すると安全です。
まとめ
- taintはノード側の「締め出し」、tolerationはPod側の「許可」です。tolerationだけでは専用ノードに寄りません。
- 効果は NoSchedule・PreferNoSchedule・NoExecute の3つで、NoExecute は動作中のPodも退去させます。
- 専用ノードは、ラベル+taintをノードに、toleration+nodeAffinityをPodに付けて作ります。
- マネージドサービスでは、ノードグループ側の設定でtaintを管理します。
- Pendingのときは Events の
untolerated taintの行を読み、キー・値・効果の一致と、他の理由を合わせて確認します。