Skip to content
Published on

Kubernetes VPA + In-Place Pod Resize 実践ガイド — 再起動なしのリソース自動調整

Authors
  • Name
    Twitter
VPA In-Place Resize

はじめに

Kubernetesでワークロードのリソースを自動調整するVertical Pod Autoscaler(VPA)には、長年「Podを再起動しなければならない」という致命的な欠点がありました。しかし、Kubernetes 1.35(2025年12月)でIn-Place Pod ResizeがGAに昇格したことで、ついに再起動なしでCPU/メモリをリアルタイム調整できるようになりました。

この記事では、VPAの基本概念からIn-Place Resizerとの連携、本番デプロイ戦略まで、段階的に解説します。

VPAとは?

VPA(Vertical Pod Autoscaler)は、PodのCPU/メモリのrequestsとlimitsを自動調整するKubernetesコンポーネントです。

HPA vs VPA

区分HPAVPA
スケーリング方向水平(Pod数の増減)垂直(リソースサイズの調整)
適したワークロードStatelessサービスStateful、シングルインスタンス
ダウンタイムなし従来:再起動必要 → 1.35+:なし

VPAの構成要素

VPAは3つのコンポーネントで構成されます:

# 1. Recommender: リソース使用量を分析し、推奨値を計算
# 2. Updater: 推奨値に基づいてPodの更新をトリガー
# 3. Admission Controller: 新しく作成されるPodに推奨値を適用

VPAのインストール

Helmでインストール

# VPA Helm chartの追加
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update

# VPAのインストール
helm install vpa fairwinds-stable/vpa \
  --namespace vpa-system \
  --create-namespace \
  --set recommender.enabled=true \
  --set updater.enabled=true \
  --set admissionController.enabled=true

# インストール確認
kubectl get pods -n vpa-system

手動インストール(公式リポジトリ)

git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler

# CRDとコンポーネントのインストール
./hack/vpa-up.sh

# 確認
kubectl get customresourcedefinitions | grep verticalpodautoscaler

基本的なVPA設定

VPAリソースの作成

# vpa-nginx.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: nginx-vpa
  namespace: default
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment
  updatePolicy:
    updateMode: 'Auto' # Off, Initial, Recreate, Auto
  resourcePolicy:
    containerPolicies:
      - containerName: nginx
        minAllowed:
          cpu: '50m'
          memory: '64Mi'
        maxAllowed:
          cpu: '2'
          memory: '2Gi'
        controlledResources: ['cpu', 'memory']
        controlledValues: RequestsAndLimits
kubectl apply -f vpa-nginx.yaml

# VPA推奨値の確認
kubectl get vpa nginx-vpa -o yaml

updateModeオプションの比較

# Off: 推奨値のみ提供、自動更新なし(モニタリング用)
updateMode: "Off"

# Initial: Pod作成時のみ推奨値を適用
updateMode: "Initial"

# Recreate: 推奨値が変更されるとPodを再作成
updateMode: "Recreate"

# Auto: 最適な方法を自動選択(1.35+ではIn-Placeを含む)
updateMode: "Auto"

# InPlaceOrRecreate: In-Place優先、不可能な場合は再作成(1.35+ Beta)
updateMode: "InPlaceOrRecreate"

In-Place Pod Resizeの有効化(Kubernetes 1.35+)

Feature Gateの確認

Kubernetes 1.35以降、In-Place Pod Resizeはデフォルトで有効です:

# クラスターバージョンの確認
kubectl version --short

# Feature gateの状態確認(1.35+ではデフォルトtrue)
kubectl get --raw /api/v1/nodes | jq '.items[0].status.features'

resizePolicyの設定

PodがIn-Place ResizeをサポートするにはresizePolicyを明示する必要があります:

# deployment-with-resize.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web
          image: nginx:1.27
          resources:
            requests:
              cpu: '100m'
              memory: '128Mi'
            limits:
              cpu: '500m'
              memory: '512Mi'
          resizePolicy:
            - resourceName: cpu
              restartPolicy: NotRequired # CPUは再起動なしで調整
            - resourceName: memory
              restartPolicy: NotRequired # メモリも再起動なしで調整
kubectl apply -f deployment-with-resize.yaml

VPA + InPlaceOrRecreate連携

# vpa-inplace.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: web-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  updatePolicy:
    updateMode: 'InPlaceOrRecreate'
    minReplicas: 2 # 最小維持レプリカ数
  resourcePolicy:
    containerPolicies:
      - containerName: web
        minAllowed:
          cpu: '50m'
          memory: '64Mi'
        maxAllowed:
          cpu: '4'
          memory: '4Gi'
        controlledResources: ['cpu', 'memory']
kubectl apply -f vpa-inplace.yaml

# In-Place resizeの発生を確認
kubectl get pods -w
# STATUSがRunningを維持したままresourcesが変更される

リサイズ過程のモニタリング

Podリソース変更の確認

# Podの現在のリソースを確認
kubectl get pod web-app-xxx -o jsonpath='{.spec.containers[0].resources}'

# allocated resourcesの確認(実際に割り当てられたリソース)
kubectl get pod web-app-xxx -o jsonpath='{.status.containerStatuses[0].allocatedResources}'

# resizeステータスの確認
kubectl get pod web-app-xxx -o jsonpath='{.status.resize}'
# "InProgress", "Proposed", "Deferred", ""(完了)

VPA推奨値モニタリングスクリプト

#!/bin/bash
# watch-vpa.sh - VPA推奨値のリアルタイムモニタリング

VPA_NAME=${1:-web-app-vpa}
NAMESPACE=${2:-default}

while true; do
  echo "=== $(date) ==="
  kubectl get vpa $VPA_NAME -n $NAMESPACE -o jsonpath='
  Target:
    CPU: {.status.recommendation.containerRecommendations[0].target.cpu}
    Memory: {.status.recommendation.containerRecommendations[0].target.memory}
  Lower Bound:
    CPU: {.status.recommendation.containerRecommendations[0].lowerBound.cpu}
    Memory: {.status.recommendation.containerRecommendations[0].lowerBound.memory}
  Upper Bound:
    CPU: {.status.recommendation.containerRecommendations[0].upperBound.cpu}
    Memory: {.status.recommendation.containerRecommendations[0].upperBound.memory}
  '
  echo ""
  sleep 30
done

Prometheusメトリクス

# VPA関連の主要メトリクス
# kube_verticalpodautoscaler_status_recommendation_target
# vpa_recommender_recommendation_latency
# vpa_updater_evictions_total
# Pod CPU推奨値 vs 実際の使用量
rate(container_cpu_usage_seconds_total[5m])
# vs
kube_verticalpodautoscaler_status_recommendation_target{resource="cpu"}

本番環境のベストプラクティス

1. 段階的な導入戦略

# Step 1: Offモードで推奨値のみ観察(1〜2週間)
updateMode: "Off"

# Step 2: Initialモードで新しいPodにのみ適用
updateMode: "Initial"

# Step 3: InPlaceOrRecreateで自動調整
updateMode: "InPlaceOrRecreate"

2. PDB(PodDisruptionBudget)との併用

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-app-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: web-app
---
# VPAはRecreateフォールバック時にPDBを尊重
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: web-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  updatePolicy:
    updateMode: 'InPlaceOrRecreate'
    minReplicas: 2
    evictionRequirements:
      - resources: ['cpu', 'memory']
        changeRequirement: TargetHigherThanRequests

3. HPAとVPAの同時使用

# HPA: CPUベースの水平スケーリング
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
---
# VPA: メモリのみの垂直スケーリング(CPUはHPAが管理)
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: web-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  updatePolicy:
    updateMode: 'InPlaceOrRecreate'
  resourcePolicy:
    containerPolicies:
      - containerName: web
        controlledResources: ['memory']
        minAllowed:
          memory: '128Mi'
        maxAllowed:
          memory: '4Gi'

4. GoldilocksでVPA推奨値を可視化

# Goldilocksのインストール(VPA推奨値ダッシュボード)
helm install goldilocks fairwinds-stable/goldilocks \
  --namespace goldilocks \
  --create-namespace

# ネームスペースでGoldilocksを有効化
kubectl label namespace default goldilocks.fairwinds.com/enabled=true

# ダッシュボードにアクセス
kubectl port-forward -n goldilocks svc/goldilocks-dashboard 8080:80

トラブルシューティング

In-Place Resizeが動作しない場合

# 1. Kubernetesバージョンの確認
kubectl version --short
# 1.35+が必要

# 2. ノードのContainer Runtimeの確認
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.containerRuntimeVersion}'
# containerd 1.7+またはCRI-O 1.29+が必要

# 3. PodのresizePolicyの確認
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[0].resizePolicy}'

# 4. resizeステータスの確認
kubectl get pod <pod-name> -o jsonpath='{.status.resize}'
# "Deferred" -> ノードにリソース不足
# "Infeasible" -> ノードがresizeをサポートしていない

# 5. イベントの確認
kubectl describe pod <pod-name> | grep -A5 "Events"

VPAが推奨値を生成しない場合

# VPA Recommenderのログ確認
kubectl logs -n vpa-system -l app=vpa-recommender --tail=50

# metrics-serverの動作確認
kubectl top pods

# VPAステータスの確認
kubectl describe vpa <vpa-name>

実践例:JavaアプリへのVPA適用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-boot-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: spring-boot
  template:
    metadata:
      labels:
        app: spring-boot
    spec:
      containers:
        - name: app
          image: myregistry/spring-boot-app:latest
          resources:
            requests:
              cpu: '500m'
              memory: '512Mi'
            limits:
              cpu: '2'
              memory: '2Gi'
          resizePolicy:
            - resourceName: cpu
              restartPolicy: NotRequired
            - resourceName: memory
              restartPolicy: RestartContainer # JVMはヒープの再設定が必要
          env:
            - name: JAVA_OPTS
              value: '-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0'
---
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: spring-boot-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: spring-boot-app
  updatePolicy:
    updateMode: 'InPlaceOrRecreate'
  resourcePolicy:
    containerPolicies:
      - containerName: app
        minAllowed:
          cpu: '200m'
          memory: '256Mi'
        maxAllowed:
          cpu: '4'
          memory: '4Gi'

まとめ

Kubernetes 1.35のIn-Place Pod Resize GAとVPAのInPlaceOrRecreateモードは、本番環境でのリソース最適化を次のレベルに引き上げます。重要なポイント:

  1. In-Place ResizeでPod再起動なしにCPU/メモリを調整可能
  2. VPA + InPlaceOrRecreateで自動化された垂直スケーリング
  3. HPAとVPAの併用時は管理リソースを分離(HPA=CPU、VPA=Memory)
  4. 段階的な導入:Off → Initial → InPlaceOrRecreate

クイズ(5問)

Q1. VPAの3つの構成要素は? Recommender、Updater、Admission Controller

Q2. In-Place Pod ResizeがGAになったKubernetesバージョンは? Kubernetes 1.35(2025年12月)

Q3. VPAのupdateModeのうち、推奨値のみ提供し自動更新しないモードは? Off

Q4. HPAとVPAを同時に使用する際に推奨されるリソースの分離方法は? HPAがCPUベースの水平スケーリング、VPAがメモリのみの垂直スケーリング

Q5. JVMベースのアプリでメモリのIn-Place Resize時にrestartPolicyをRestartContainerに設定する理由は? JVMがヒープメモリを動的に再設定する必要があるため、コンテナの再起動が必要