問題:PodがPending状態から進まないKubernetesクラスターに新しいアプリケーションをデプロイした際、YAMLファイルに間違いがないように見えても、Podのステータスを確認するとPendingのまま動かないことがあります。kubectl describe podを実行すると、eventsセクションに以下の警告が表示されます。
0/1 nodes are available: 1 node(s) had taint {key: value}, that the pod didn't tolerate.
このエラーは、ノードの**Taint(汚れ)とPodのToleration(許容)**の不一致を示しています。Kubernetesにおいて、Taintはノードに貼られた「立入禁止」の標識のようなものです。Podがその標識に一致する特定の「通行証(Toleration)」を持っていない限り、スケジューラーはそのノードにPodを配置することを拒否します。
ステップ1:ノードのTaintを確認するこれを修正するには、まずどのTaintがPodをブロックしているのかを特定する必要があります。以下のコマンドを使用して、すべてのノードと現在のTaintを一覧表示できます。
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
特定のノードを確認したい場合は、describeコマンドで詳細を表示できます。
kubectl describe node <node-name> | grep Taints
key=production:NoScheduleやnode-role.kubernetes.io/control-plane:NoScheduleのような出力が表示されます。これにより、Taintのキー(Key)、値(Value)、および**効果(Effect)**がわかります。
ステップ2:Podの要件を確認するPodまたはDeploymentのマニフェストを確認してください。tolerationsセクションを明示的に定義していない場合、PodはTaintが設定されたノードに配置されることはありません。定義していても、キーや値にわずかなタイポ(打ち間違い)があるだけで、スケジューラーはPodを拒否します。
よく見られる効果(Effect)は以下の通りです:
- NoSchedule: Taintを許容しない限り、新しいPodはスケジューリングされません。- PreferNoSchedule: システムは可能な限りそのノードへの配置を避けますが、強制ではありません。- NoExecute: Taintを許容しない既存のPodは、ノードから排出(エビクト)されます。### ステップ3:解決策を選択する目的や状況に応じて、主に2つの解決方法があります。
方法A:PodにTolerationを追加する(推奨)ノードにTaintが設定されている正当な理由(例:専用のGPUハードウェアを搭載している、本番環境ワークロード専用に予約されているなど)がある場合は、PodまたはDeploymentのマニフェストを更新して、対応するTolerationを含める必要があります。
deployment.yamlのspec.template.specの下にtolerationsフィールドを追加します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
template:
spec:
containers:
- name: my-container
image: nginx:latest
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
Taintにキーのみがあり値がない場合は、Exists演算子を使用します。
tolerations:
- key: "dedicated"
operator: "Exists"
effect: "NoSchedule"
方法B:ノードからTaintを削除する誤ってノードにTaintを設定してしまった場合や、制限を解除したい場合は、kubectl taintコマンドを使用してTaintを削除できます。コマンドの最後にあるマイナス記号(-)が削除を意味することに注意してください。
kubectl taint nodes <node-name> key=value:NoSchedule-
ステップ4:修正を確認する変更を適用した後(Deploymentの更新またはTaintの削除)、Podのステータスを再度確認します。
kubectl get pods -w
PodはPendingからContainerCreating、そして最終的にRunningに移行するはずです。どのノードに配置されたかも確認できます。
kubectl get pod <pod-name> -o wide

