KubernetesノードのNotReadyを修正する: Node node-1 status is now: NodeNotReady

intermediate☸️ Kubernetes2026-04-21| Kubernetes 1.24以降、任意のLinuxディストリビューション(Ubuntu 20.04/22.04、CentOS 7/8、RHEL)、kubeadmまたはマネージドクラスター(EKS、GKE、AKS)

Error Message

Node node-1 status is now: NodeNotReady
#kubernetes#node#notready#kubelet#kubectl

何が起きたか

クラスターを確認したところ、ポッドが Pending 状態のまま止まっていることに気づきました。kubectl get nodes を実行すると、1つ以上のノードが NotReady ステータスになっています。コントロールプレーンのイベントログにはこう記録されています:

Node node-1 status is now: NodeNotReady

スケジューラーはすぐにそのノードへの新しいポッドの配置を停止します。そこで既に動いているポッドは、tolerations の設定によっては退避させられる場合があります — デフォルトでは通常5分後です。実際の原因を特定しましょう。

クイックトリアージ — まず確認すること

何よりも先に、影響を受けているノードにSSHでログインしてください。根本原因のほとんどは、APIサーバーではなくノード自体にあります。

1. ノードのステータスとコンディションを確認する

kubectl get nodes
kubectl describe node node-1

describe の出力にある Conditions セクションまでスクロールしてください。4つのフィールドがほぼすべてを教えてくれます:

  • ReadyTrue であるべきです。False または Unknown の場合、kubelet がコントロールプレーンと通信できていません。
  • MemoryPressure / DiskPressure / PIDPressure — いずれかが True の場合、ノード上のリソースが枯渇しています。
  • NetworkUnavailable — CNIプラグインの問題を示しています。

2. ノード上のkubeletのステータスを確認する

systemctl status kubelet
journalctl -u kubelet -n 100 --no-pager

kubelet はノードの健全性をコントロールプレーンに報告するエージェントです。クラッシュまたは停止すると、ノードは40秒以内に NotReady に切り替わります — これはデフォルトの node-monitor-grace-period です。ジャーナルのログは、最初の10行以内に何が問題だったかをほぼ必ず教えてくれます。

よくある原因と対処法

原因1:kubelet が停止またはクラッシュしている

十中八九これが原因です。kubelet プロセスが静かに終了し、何も再起動させていないのです。

# kubelet を再起動する
systemctl restart kubelet
systemctl enable kubelet

# ノードの回復を監視する
kubectl get nodes -w

それでもクラッシュする場合は、リアルタイムでログを追いましょう:

journalctl -u kubelet -f

繰り返し現れるサブ原因が3つあります:/var/lib/kubelet/config.yaml の設定ミス、TLS証明書の期限切れ、cgroupドライバーの不一致です。最後のものがよく引っかかります — ノードは cgroupfs で動いているのに、クラスターは systemd で設定されている、またはその逆のケースです。

不一致を確認するには:

# Docker ランタイム
docker info | grep -i cgroup

# containerd ランタイム
containerd config dump | grep -i cgroup

# kubelet が期待する設定
cat /var/lib/kubelet/config.yaml | grep cgroupDriver

異なっている場合は、/var/lib/kubelet/config.yaml をランタイムに合わせて更新し、kubelet を再起動してください。

原因2:ディスクプレッシャー

ディスクは、負荷の高いノードでは多くの人が予想するよりも速く埋まります。使用量が退避閾値(デフォルトは85%)を超えると、kubelet は DiskPressure=True を設定し、ノードをスケジュール不可にします。

# ノード上で実行
df -h
du -sh /var/lib/docker/*      # Docker ランタイム
du -sh /var/lib/containerd/   # containerd ランタイム

# 退避メッセージを確認する
journalctl -u kubelet | grep -i evict

コンテナイメージと古いログが通常の原因です。すぐに片付けましょう:

# Docker
docker system prune -af

# containerd
crictl rmi --prune

# 古いジャーナルログを削除する
journalctl --vacuum-time=3d

原因3:メモリプレッシャーまたはOOMキル

# 最近のOOMキルを確認する
dmesg | grep -i oom
cat /proc/meminfo | grep -i available

カーネルのOOMキラーは素早く動作します — メモリを回収するために kubelet 自体を終了させることもあります。kubelet を再起動すればノードは復帰しますが、ポッドにリソース制限がなければ、1時間後に同じことが再発します。メモリを消費しているものを特定し、該当するポッドに resources.limits.memory を追加してください。

原因4:CNIプラグインの障害(NetworkUnavailable)

NetworkUnavailable=True のコンディションは、CNIレイヤー(Flannel、Calico、Cilium、Weave、その他使用中のもの)を直接示しています。プラグインがクラッシュするか、その特定のノード上でステートを失っています。

# 壊れたノード上で動いている CNI ポッドを見つける
kubectl get pods -n kube-system -o wide | grep -E 'flannel|calico|cilium|weave'

# ログを確認する
kubectl logs -n kube-system <cni-pod-on-node-1>

# CNI バイナリと設定がノード上に存在するか確認する
ls /opt/cni/bin/
ls /etc/cni/net.d/

CNI ポッドを削除して Kubernetes に新たにスケジュールさせましょう。再初期化によって通常は問題が解消されます:

kubectl delete pod -n kube-system <cni-pod-on-node-1>

原因5:クロックスキューまたは証明書の期限切れ

クロックがずれるとTLS認証が壊れます。2分を超えるスキューは、APIサーバーが kubelet の証明書を完全に拒否する原因になります。

# ノードの時刻と期待値を比較する
date
timedatectl status

# 即座に再同期する
chronyc makestep        # chrony ユーザー向け
ntpdate -u pool.ntp.org # ntp ユーザー向け

証明書の期限切れは別の問題です — カレンダーベースで発生します。kubeadm が発行した証明書はちょうど1年で期限切れになります。コントロールプレーンから確認・更新してください:

# すべての証明書の有効期限を確認する
kubeadm certs check-expiration

# 一括で全て更新する
kubeadm certs renew all
systemctl restart kubelet

原因6:コントロールプレーンからノードに到達できない

APIサーバーはポート10250でkubeletと通信します。ファイアウォールルールの変更、誤設定されたセキュリティグループ(クラウドインフラ更新後によく発生)、またはノードがオフラインになることで、同じ NotReady の症状が現れます。

# コントロールプレーンのノードから直接テストする
curl -k https://<node-ip>:10250/healthz

# ノード上の iptables を確認する
iptables -L -n | grep 10250

# firewalld の場合
firewall-cmd --list-all

ノードが復帰したことを確認する

# ノードが Ready になっているか確認する
kubectl get nodes

# 期待される出力:
# NAME     STATUS   ROLES    AGE   VERSION
# node-1   Ready    <none>   5d    v1.28.0

# コンディションがクリアか確認する
kubectl describe node node-1 | grep -A 10 Conditions

# スケジューリングのクイックテストを実行する
kubectl run test-pod --image=nginx --restart=Never
kubectl get pod test-pod -o wide

# クリーンアップ
kubectl delete pod test-pod

インシデント中にノードがcordonされていませんでしたか?このステップを忘れずに:

kubectl uncordon node-1

メンテナンス前にcordonとdrainを行う

カーネルのアップグレードやディスクのクリーンアップを行う場合は、必ず先にノードをdrainしてください — リクエストの途中でポッドが強制終了されるより、適切に退避させる方がよいです。

# 新しいポッドがここに配置されないようにする
kubectl cordon node-1

# 既存のポッドを安全に退避させる
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data

# メンテナンス作業を行う...

# ノードをローテーションに戻す
kubectl uncordon node-1

次回に向けて改善すること

  • ディスクのアラートは85%ではなく70%に設定する。 kubelet が85%で退避をトリガーする頃には、既に悪い状況です。70%のアラートなら、本番インシデントなしに片付けるための15ポイントの余裕があります。DiskPressure は他のどの原因よりも多くの人を驚かせます。
  • 最初にAPIサーバーではなくkubeletのログを確認する。 ジャーナルはほぼ必ず最初の10行以内に正確な障害を示します。まずそこを見てください。
  • クロック同期は任意ではない。 クラウド環境ではVMがライブマイグレーション後にずれることがあります — 数分ずれることも。chronyまたはntpdを実行し、あれば嬉しい機能ではなくインフラとして扱ってください。
  • node-problem-detectorをデプロイする。 node-problem-detector DaemonSet は、カーネルパニックやランタイム障害が NotReady にエスカレートする前に、ノードコンディションとして表面化します。helm install node-problem-detector deliveryhero/node-problem-detector で2分でインストールできます。
  • 証明書の期限をopsカレンダーで管理する。 kubeadmの証明書は固定日から1年後に期限切れになります。11ヶ月時点で更新リマインダーを設定してください — サプライズとして扱うのは避けられます。

Related Error Notes