午前2時のデプロイ失敗
AWS EKSクラスターに重要なアップデートをプッシュした直後、CI/CDパイプラインは正常終了(緑のチェックマーク)を示していますが、5分後、アプリケーションがオフラインになっています。kubectl get podsを実行すると、Pendingステータスが並んでいます。数分経過しても、コンテナは起動しません。
ポッドのイベントを確認すると、次のようなボトルネックが発生しています:
0/3 nodes are available: 3 Insufficient cpu. preemption: 0/3 nodes are available: 3 No preemption victims found for incoming pod.
このエラーは、Kubernetesのスケジューラがすべてのノードを確認した結果、利用可能なCPU容量がゼロであることを示しています。さらに悪いことに、新しいデプロイのためのスペースを確保するために終了(プリエンプション)できる低優先度のポッドも見つかりませんでした。クラスターが実質的に満杯の状態です。
ステップ1:「ゴースト」リソース使用量のデバッグ
よくある混乱の原因は、ノードの実際のCPU使用率は低いのに、新しいポッドの配置が拒否されることです。Kubernetesはリアルタイムの消費量ではなく、**Requests(要求量)**に基づいてスケジューリングを行います。例えば、ノードに2 vCPUがあり、それぞれ450mのCPUを要求する4つのポッドがある場合、それらのポッドが現在1%の使用率でアイドル状態であっても、スケジューラから見ればそのノードは90%埋まっていることになります。
ポッドのリソース要求(Requests)の分析
保留中(Pending)のポッドが具体的にどれだけのCPUを要求しているかを確認します。出力内のRequestsセクションを探してください:
kubectl describe pod <pod-name> | grep -A 5 "Requests:"
ノード容量の監査
次に、ノード全体でどれだけのCPUがすでに「予約」されているかを確認します。このコマンドにより、物理的に存在するリソースと論理的に割り当てられたリソースの差を特定できます:
kubectl describe nodes | grep -A 10 "Allocated resources:"
「CPU Requests」列が90%以上を示している場合、スケジューラは残りのわずかな空き容量に収まらないポッドをすべて拒否します。
ステップ2:即時の修正対応
オプションA:ポッドの要求リソースを適切に設定する
開発者は推測でCPUリクエストを設定しがちです。マイクロサービスが実際には50m(0.05コア)しか使用していないのに、マニフェストで1000m(1フルコア)を要求している場合、支払っているリソースの95%を無駄にしていることになります。実態に合わせてdeployment.yamlを調整してください:
spec:
containers:
- name: api-server
resources:
requests:
cpu: "250m" # 1000mから削減
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1Gi"
アップデートを適用します:kubectl apply -f deployment.yaml。新しい要求量が利用可能なオーバーヘッドに収まれば、Kubernetesは即座にポッドをスケジュールします。
オプションB:手動スケーリング
リソース要求がすでに正確である場合は、単純にハードウェアを増やす必要があります。AWS CLIを介してノードグループのサイズを手動で増やすことができます。例えば、クラスターを3ノードから5ノードに増やすには次のようにします:
aws autoscaling update-auto-scaling-group \
--auto-scaling-group-name <your-eks-asg-name> \
--desired-capacity 5
新しいEC2インスタンスがクラスターに参加するには、通常2〜3分かかります。ステータスがReadyになれば、スケジューラは自動的にポッドをPendingからRunningに移行させます。
ステップ3:長期的な予防策
Karpenterを導入してジャストインタイムのスケーリングを実現する
手動スケーリングはダウンタイムの原因となります。モダンなEKS構成ではKarpenterを使用します。従来のCluster Autoscalerとは異なり、Karpenterは保留中のポッドを確認し、計算負荷の高いタスクにはc5.large、メモリを大量に消費するタスクにはr5.largeといった具合に、必要な正確なEC2インスタンスタイプをプロビジョニングし、1分以内に起動させることができます。
Vertical Pod Autoscaler (VPA) の活用
CPU要求量をどの程度にすべきか不明な場合は、VPAをRecommendation(推奨)モードで実行してください。過去の使用データを追跡し、推奨値を提供します。これにより、「念のため」の過剰なプロビジョニングによる「Insufficient CPU」エラーを防ぐことができます。
確認
ポッドのライフサイクルを監視して修正を確認します:
kubectl get pods -w
ステータスがPendingからContainerCreating、そして最終的にRunningに遷移するはずです。ポッドが具体的にどのノードに配置されたかを確認するには、-o wideフラグを使用します:
kubectl get pod <pod-name> -o wide
重要なまとめ
- スケジューラは計算エンジン:
requests(要求量)のみを考慮します。アプリが現在実際にどれだけのCPUを使用しているかは見ていません。 - EKSのオーバーヘッドを考慮する:
t3.mediumインスタンスには2 vCPUありますが、EKSはシステム用に約190mのCPUを予約します。ポッドで使用できるのは実質約1.81 vCPUのみです。 - 自動化か、さもなくば失敗か: KarpenterやCluster Autoscalerなしで本番ワークロードを運用することは、手動介入と停止を招きます。
- アラート通知:
kube_pod_status_phase{phase="Pending"}に対してPrometheusアラートを設定しましょう。これにより、ユーザーが気づく前に容量の問題を把握できます。

