Node Allocatableの概要
Kubernetesクラスターにおいて、各ノードは物理的なハードウェアリソース(CPU、メモリ、ストレージ)を持っています。これらのリソースはPodだけでなく、Kubernetes自体やOSのシステムプロセスにも使用されます。しかし、デフォルトではすべてのリソースがPodに割り当て可能となっており、システムプロセスがリソース不足に陥るとノードの不安定化を引き起こす可能性があります。
リソース予約が必要な理由
- ノード上で動作するkubelet、container runtime、node-problem-detectorなどのコアコンポーネントは安定稼働のために最低限のリソースを必要とする。
- 特定のPodがCPUやメモリを過剰に消費し、kubeletの処理が遅延すると、APIサーバーとのハートビートがタイムアウトし、ノード状態が
NotReadyになるリスクがある。 - 一度
NotReadyとなったノード上のPodが他のノードへ移行され、同様の高負荷を発生させれば、連鎖的にクラスター全体がダウンする「リソース雪崩」が発生する。 - このような事態を防ぐため、Node Allocatableという仕組みを用いて、システムプロセス専用のリソースを事前に確保することが重要です。
Allocatableリソースの計算方式
ノード上で実際にPodに割り当て可能なリソース量(= Allocatable)は、以下の式で算出されます:
Allocatable = Capacity - kube-reserved - system-reserved - eviction-threshold
この値に基づき、KubernetesのスケジューラはPodの配置を判断します。つまり、すべてのPodのresources.requests合計がAllocatableを超えないように制御されます。
関連項目の説明
- Capacity: ノードの物理リソース総量(例: cpu=8, memory=15595848Ki)
- Allocatable: 実際にPodに割り当て可能なリソース量
- kube-reserved: kubeletやCRIなどKubernetesコンポーネント専用のリザーブ
- system-reserved: sshd、udev、監視エージェントなどOSレベルのデーモン向けリザーブ
- eviction-hard: リソース枯渇時にPodを強制終了するしきい値
実際のリソース予約設定
以下は、kubeletの構成ファイル(/var/lib/kubelet/config.yaml)を通じてリソース予約を適用する方法です。
Kubernetesコンポーネント向けのリザーブ
kube-reservedを使用して、kubeletやコンテナランタイムに必要なリソースを確保します。
kubeReserved:
cpu: "200m"
memory: "256Mi"
ephemeral-storage: "5Gi"
また、対象プロセスが属するcgroupを明示的に指定することで、リソース制限が正しく適用されるようにします。
kubeReservedCgroup: /kube-reserved
OSシステムプロセス向けのリザーブ
システム全体の安定性を保つために、OS関連のバックグラウンドプロセスにもリソースを確保します。
systemReserved:
cpu: "100m"
memory: "512Mi"
ephemeral-storage: "3Gi"
systemReservedCgroup: /system-reserved
リソース枯渇時のポリシー設定
ノードがリソース不足に陥った場合の挙動を定義します。これはノードの自己防衛機構として機能します。
evictionHard:
memory.available: "300Mi"
nodefs.available: "10%"
imagefs.available: "15%"
さらに、Eviction発生後に回復を促進するために、最低限のリソース回収量を指定できます。
evictionMinimumReclaim:
memory.available: "200Mi"
nodefs.available: "500Mi"
imagefs.available: "1Gi"
最終的な設定例
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
enforceNodeAllocatable:
- pods
- kube-reserved
- system-reserved
kubeReserved:
cpu: "200m"
memory: "256Mi"
ephemeral-storage: "5Gi"
kubeReservedCgroup: /kube-reserved
systemReserved:
cpu: "100m"
memory: "512Mi"
ephemeral-storage: "3Gi"
systemReservedCgroup: /system-reserved
evictionHard:
memory.available: "300Mi"
nodefs.available: "10%"
imagefs.available: "15%"
evictionMinimumReclaim:
memory.available: "200Mi"
nodefs.available: "500Mi"
imagefs.available: "1Gi"
設定の反映手順
設定変更後はkubeletサービスを再起動して反映します。
sudo systemctl daemon-reload
sudo systemctl restart kubelet
sudo systemctl status kubelet
設定の確認方法
変更が正しく反映されたかは、以下のコマンドで確認できます。
kubectl describe node <node-name>
出力結果のAllocatableセクションに、新しいリソース量が表示されていることを確認してください。
補足:効果の検証
たとえば、次のような環境を想定します:
- ノード容量: CPU=16, Memory=32Gi, Ephemeral-Storage=100Gi
- kube-reserved: cpu=1, memory=2Gi, storage=1Gi
- system-reserved: cpu=0.5, memory=1Gi, storage=1Gi
- eviction-hard: memory.available<500Mi
この場合、Podに割り当て可能なリソース(Allocatable)は以下のようになります:
- CPU: 14.5
- Memory: 28.5Gi
- Ephemeral-Storage: 88Gi
スケジューラはこの値を基準にPodの配置を決定し、システムの安定稼働を担保します。