Skip to main content

VPAをInPlaceOrRecreateにしたのに、Podはまだ再起動していた。K3sでInPlacePodVerticalScalingの"無停止"を検証する

"無停止リサイズ"という触れ込みで試したら、Podが再作成されていた

VPA(Vertical Pod Autoscaler)のupdateModeをInPlaceOrRecreateに変更した。これでPodを再起動せずにCPU・メモリを調整できるはずだった。ところが数日後にイベントログを見返すと、何度かPodがEvictedされて再作成されていた。

結論から言うと、これは不具合ではない。In-Place Pod Resize(In-Place Pod Vertical Scaling)は「条件を満たした場合にだけ」コンテナを再起動せずにリソース変更できる機能であり、条件を外れると静かにPodの再作成にフォールバックする設計になっている。

この記事では、VPAのInPlaceOrRecreateモードとIn-Place Pod Resizeの挙動を、K3s環境を前提に実際の設定・コマンド・ステータスの読み方まで含めて検証する(先に結論だけ言うと、Kuboのようにcgroupまわりの前提条件が構成済みのマネージドK3sであれば、この検証の大半を意識せずに済む)。

section01

In-Place Pod Resizeの基礎 — alphaからGAまでの6年間

In-Place Pod Resize(Kubernetesの/resizeサブリソースを使った機能)は2023年にv1.27でalphaとして登場し、2025年5月のv1.33でbetaに昇格、そして2025年12月のv1.35でStable(GA)に到達した。v1.33のベータ化を伝える公式ブログによれば、この間に再起動なしでのリソース調整がデフォルト有効になっている。

コンテナ単位で指定するresizePolicyには2つの値がある。

  • NotRequired: リソース変更時にコンテナを再起動しない(デフォルト)
  • RestartContainer: リソース変更時にコンテナを再起動する

Kubernetes公式ドキュメントには、kubectl patch pod <name> --subresource=resizeでリソースをパッチする方法と、結果をstatus.conditionsのPodResizePending(理由: DeferredまたはInfeasible)やPodResizeInProgressで確認する方法が示されている。Deferredはノードの空きリソース不足による保留、Infeasibleはノードの最大容量を超えていて実行不可能、という意味だ。2026年4月にはv1.36でPodレベルのリソースに対するin-placeリサイズもベータに昇格しており、対象範囲は広がり続けている。

なぜ"InPlaceOrRecreate"なのに再作成されるのか

最初に疑うべきはQoSクラスだ。Kubernetes公式ドキュメントが明記している通り、PodのQoSクラス(Guaranteed / Burstable / BestEffort)は作成時に固定され、リサイズによって変更することはできない。Burstableなコンテナのrequestsとlimitsを両方とも同じ値にしてGuaranteed相当にしてしまうような変更は、in-placeでは実行できない。

さらに見落としやすいのが初期値の有無だ。実践的な設定ガイドによれば、コンテナ側でrequests/limitsを何も設定していないと、そのPodはBestEffortとして扱われ、VPAがリソースを設定しようとした瞬間にQoSクラスが変わってしまうため再作成が必要になる。InPlaceOrRecreateを使うなら、最初から最低限のrequests/limitsを入れておくことが前提条件になる。

VPA側の挙動も重要だ。InPlaceOrRecreateモードの解説記事によると、VPAは/resizeサブリソースでのパッチを試み、次の条件でevict(再作成)にフォールバックする。

  • kubeletがリサイズをinfeasible、またはエラーと報告した場合
  • Deferred状態が5分を超えて解消しない場合
  • PodResizeInProgressが1時間を超えて解消しない場合
  • 提案されたリソース変更がQoSクラスを変えてしまう場合

同記事はもう一点、見落としがちな仕様にも触れている。/resizeが成功した場合はEviction APIを呼び出さないため、PodDisruptionBudgetが消費されない。PDBで保護しているつもりでも、in-place成功時はそもそもPDBの判定を経由しないということだ。

section02

K3s/エッジ環境特有の罠 — cgroupドライバが絡むと話がややこしくなる

K3sで運用している場合、もう一段ややこしい要因がある。cgroupのバージョンとドライバだ。In-Place Pod ResizeやPod Level Resourcesの検証では、ノードがcgroup2で動作していることが前提になっている(devopscube.comの検証ガイドでも最初に確認すべき項目として挙げられている)。

K3sはあるバージョンからsystemd検出時にデフォルトのcgroupドライバをcgroupfsからsystemdへ変更している。この変更自体はcgroup v2環境との親和性を高めるためのものだが、Docker上でK3sを動かす構成や、古いOSイメージのノードでは、systemdドライバへの切り替えが原因でkubepodsコンテナが見つからないといった起動エラーが報告されている。さらにエッジデバイス側では、K3sエージェントがcgroup v1のままでは起動に失敗する事例も確認できる。

工場や店舗に置かれたエッジのK3sノードは、OSイメージの更新が後回しになりがちで、cgroup v1のまま運用され続けていることが珍しくない。そうしたノードでIn-Place Pod ResizeやVPAのInPlaceOrRecreateを有効にしても、Pod Level Resourcesを使った機能は前提から外れてしまう。「クラウドのクラスタでは動いたのに、エッジのクラスタでは同じYAMLがうまく機能しない」という事態は、まずcgroupのバージョンとドライバを疑うとよい。

Kubo On-PremiseのようにK3sディストリビューション側でcgroup v2・systemdドライバの組み合わせを前提として構成しておけば、エッジ側のノードを個別に手直しする手間自体をなくせる。自前でOSイメージを管理している場合は、この前提条件のズレが最も起きやすいポイントだと意識しておきたい。

section03

実践 — resizePolicyの設定とkubectlでの検証手順

まずコンテナ側にresizePolicyを明示しておく。

yaml
resources:
  requests:
    cpu: "250m"
    memory: "256Mi"
  limits:
    cpu: "500m"
    memory: "512Mi"
resizePolicy:
  - resourceName: cpu
    restartPolicy: NotRequired
  - resourceName: memory
    restartPolicy: RestartContainer

CPUはNotRequiredで再起動なしの調整を許可しつつ、メモリはRestartContainerにしておくと、JVMなどヒープサイズの再計算が必要なアプリケーションでも安全に動く。devopscube.comのガイドもメモリ変更時のRestartContainer活用を推奨している。

検証はkubectlだけで完結する。

bash
kubectl patch pod <pod-name> --subresource=resize -p \
  '{"spec":{"containers":[{"name":"app","resources":{"requests":{"cpu":"400m"}}}]}}'

kubectl get pod <pod-name> -o jsonpath='{.status.conditions}'

PodResizeInProgressが表示されていればリサイズ実行中、PodResizePendingにDeferredがあればノードのリソース不足、Infeasibleがあれば現在のノードでは実行不可能という意味になる。メモリを減らす方向のリサイズでは、使用量が新しいlimitを超えているとPodResizeInProgressがErrorのまま止まることがあるため、ダウンサイジング系の変更はRestartContainerを基本にしておくのが無難だ。

section04

まとめ — "再起動しない"を前提に設計しない

In-Place Pod Resizeは確かにv1.35でGAに到達し、VPAのInPlaceOrRecreateモードも実運用で使えるレベルになってきた。ただしそれは「条件を満たせば再起動が省略される」機能であって、「絶対に再起動しない」保証ではない。QoSクラスの固定、初期requests/limitsの有無、cgroupのバージョンとドライバ——この3点を事前に揃えておかないと、期待していたタイミングでPodが再作成される。

K3sをベースにしたマネージド環境であれば、cgroup v2とsystemdドライバの組み合わせやノード側の前提条件はあらかじめ揃っている。KuboはK3sベースのマネージドKubernetesとして、こうした低レイヤーの前提条件を意識せずにVPAやIn-Place Pod Resizeを試せる環境を提供している。

VPAの運用設計そのものを見直したい場合は、Kubo CloudのAI-Driven Deploymentであれば、リソース設定やcgroup周りの前提条件をYAMLで細かく気にする前に、まず動く構成から始められる。EKSやAKSで同様の検証をする場合と比べて、月額48,000円〜という価格でフルスペックのKubernetesを試せる点も実務上の検討材料になるはずだ。

新機能を本番投入する前に、構成済みの環境で挙動を確かめたい場合は、お問い合わせから相談してみてほしい。

Related articles

← Back to all posts