10日で覚えるKubernetesDay 9: スケーリングとアップデート戦略

Day 9: スケーリングとアップデート戦略

今日学ぶこと

  • Horizontal Pod Autoscaler(HPA)による自動スケーリング
  • Vertical Pod Autoscaler(VPA)の概要
  • Blue/GreenデプロイメントとCanaryデプロイメント
  • StatefulSetの基本

自動スケーリング

Day 4で手動スケーリング(kubectl scale)を学びましたが、Kubernetesは負荷に応じて自動でPod数を調整する仕組みも提供しています。

flowchart TB
    subgraph Scaling["スケーリングの種類"]
        HPA["Horizontal Pod Autoscaler\n(Pod数を増減)"]
        VPA["Vertical Pod Autoscaler\n(リソース量を増減)"]
        CA["Cluster Autoscaler\n(ノード数を増減)"]
    end
    style HPA fill:#3b82f6,color:#fff
    style VPA fill:#8b5cf6,color:#fff
    style CA fill:#22c55e,color:#fff
種類 対象 説明
HPA Pod数 CPU/メモリ使用率に応じてレプリカ数を自動調整
VPA リソース量 Podのrequests/limitsを自動調整
Cluster Autoscaler ノード数 クラスタのノード数を自動調整(クラウド環境)

Horizontal Pod Autoscaler(HPA)

HPAは、CPU使用率やカスタムメトリクスに基づいてDeploymentのレプリカ数を自動的に増減します。

前提: Metrics Server

HPAにはMetrics Serverが必要です。

# Metrics Serverの確認
kubectl top nodes
kubectl top pods

# Minikubeの場合
minikube addons enable metrics-server

# Docker Desktopの場合は通常プリインストール済み

HPAの作成

# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-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: 50
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 70
# コマンドでも作成可能
kubectl autoscale deployment web-app \
  --min=2 --max=10 --cpu-percent=50

HPAの動作

flowchart LR
    MS["Metrics Server"] -->|"メトリクス取得"| HPA["HPA"]
    HPA -->|"CPU > 50%"| UP["スケールアップ\n(Pod数を増加)"]
    HPA -->|"CPU < 50%"| DOWN["スケールダウン\n(Pod数を減少)"]
    UP --> DEP["Deployment"]
    DOWN --> DEP
    style HPA fill:#3b82f6,color:#fff
    style UP fill:#22c55e,color:#fff
    style DOWN fill:#f59e0b,color:#fff

HPAの確認と負荷テスト

# HPAの状態確認
kubectl get hpa
# NAME      REFERENCE           TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
# web-hpa   Deployment/web-app  10%/50%   2         10        2          5m

# 詳細確認
kubectl describe hpa web-hpa

# 負荷をかけてスケーリングを確認
kubectl run load-test --image=busybox:1.37 --rm -it -- \
  /bin/sh -c "while true; do wget -q -O- http://web-service; done"

# 別ターミナルでHPAの変化を監視
kubectl get hpa -w

HPAのパラメータ

パラメータ 説明
minReplicas 最小レプリカ数
maxReplicas 最大レプリカ数
averageUtilization 目標使用率(%)
scaleDown.stabilizationWindowSeconds スケールダウン前の安定化期間(デフォルト300秒)

HPAを使用するDeploymentのPodには必ずresources.requestsを設定してください。


アップデート戦略

Day 4で学んだローリングアップデート以外にも、いくつかのデプロイメント戦略があります。

1. Recreate(再作成)

全てのPodを停止してから新しいPodを起動します。ダウンタイムが発生します。

spec:
  strategy:
    type: Recreate

2. Rolling Update(ローリングアップデート)

Day 4で学んだ方式。段階的にPodを更新します(デフォルト)。

3. Blue/Green デプロイメント

Kubernetesのネイティブ機能ではありませんが、ServiceのラベルセレクターとDeploymentを使って実現できます。

flowchart TB
    SVC["Service\nselector: version=green"]
    subgraph Blue["Blue (旧バージョン)"]
        B1["Pod v1"]
        B2["Pod v1"]
    end
    subgraph Green["Green (新バージョン)"]
        G1["Pod v2"]
        G2["Pod v2"]
    end
    SVC -->|"切り替え"| Green
    style Blue fill:#3b82f6,color:#fff
    style Green fill:#22c55e,color:#fff
    style SVC fill:#8b5cf6,color:#fff
# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: blue
  template:
    metadata:
      labels:
        app: myapp
        version: blue
    spec:
      containers:
        - name: app
          image: myapp:1.0
---
# green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: green
  template:
    metadata:
      labels:
        app: myapp
        version: green
    spec:
      containers:
        - name: app
          image: myapp:2.0
---
# service.yaml(Blue/Green切り替え)
apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  selector:
    app: myapp
    version: blue  # green に変更して切り替え
  ports:
    - port: 80
# Blue → Greenに切り替え
kubectl patch service app-service -p '{"spec":{"selector":{"version":"green"}}}'

# 問題があればBlueに戻す
kubectl patch service app-service -p '{"spec":{"selector":{"version":"blue"}}}'

4. Canary デプロイメント

新バージョンを少数のPodで試験的に公開し、問題がなければ徐々に拡大する戦略です。

flowchart TB
    SVC["Service\nselector: app=myapp"]
    subgraph Stable["Stable (90%)"]
        S1["Pod v1"]
        S2["Pod v1"]
        S3["Pod v1"]
        S4["Pod v1"]
        S5["Pod v1"]
        S6["Pod v1"]
        S7["Pod v1"]
        S8["Pod v1"]
        S9["Pod v1"]
    end
    subgraph Canary["Canary (10%)"]
        C1["Pod v2"]
    end
    SVC --> Stable
    SVC --> Canary
    style Stable fill:#3b82f6,color:#fff
    style Canary fill:#f59e0b,color:#fff
# stable-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-stable
spec:
  replicas: 9
  selector:
    matchLabels:
      app: myapp
      track: stable
  template:
    metadata:
      labels:
        app: myapp
        track: stable
    spec:
      containers:
        - name: app
          image: myapp:1.0
---
# canary-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      track: canary
  template:
    metadata:
      labels:
        app: myapp
        track: canary
    spec:
      containers:
        - name: app
          image: myapp:2.0
---
# service.yaml(両方のDeploymentに送る)
apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  selector:
    app: myapp  # trackは指定しない → 両方にルーティング
  ports:
    - port: 80

デプロイメント戦略の比較

戦略 ダウンタイム ロールバック リソース 複雑さ
Recreate あり 遅い
Rolling Update なし 自動
Blue/Green なし 瞬時
Canary なし 瞬時 少し多い

StatefulSet

これまでのDeploymentはステートレスなアプリケーション向けでした。データベースやメッセージキューなどのステートフルなアプリケーションにはStatefulSetを使います。

DeploymentとStatefulSetの違い

特性 Deployment StatefulSet
Pod名 ランダム(app-7f8b-abc) 連番(app-0, app-1, app-2)
起動順序 並行 順番(0 → 1 → 2)
ストレージ 共有PVC Pod固有のPVC
ネットワーク ランダムIP 安定したDNS名

StatefulSetの例

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres-headless
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:17
          ports:
            - containerPort: 5432
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi
---
# Headless Service(StatefulSetに必要)
apiVersion: v1
kind: Service
metadata:
  name: postgres-headless
spec:
  clusterIP: None
  selector:
    app: postgres
  ports:
    - port: 5432

StatefulSetのPodは安定したDNS名を持ちます:

  • postgres-0.postgres-headless.default.svc.cluster.local
  • postgres-1.postgres-headless.default.svc.cluster.local
  • postgres-2.postgres-headless.default.svc.cluster.local

まとめ

概念 説明
HPA CPU/メモリに基づくPod数の自動スケーリング
VPA Podのリソース量の自動調整
Blue/Green 2つの環境を切り替えるデプロイメント戦略
Canary 少数のPodで新バージョンを試験的に公開
StatefulSet ステートフルアプリケーション用のコントローラー

重要ポイント

  1. HPAを使えば負荷に応じてPod数が自動調整される。resources.requestsの設定が必須
  2. Blue/Greenは瞬時の切り替え、Canaryは段階的なリリースに適している
  3. データベースなどステートフルなアプリケーションにはStatefulSetを使う

練習問題

問題1: HPA

WebアプリのDeploymentにHPAを設定してください。CPU使用率50%で2〜8Podの範囲でスケーリングするようにしましょう。

問題2: Blue/Green

2つのバージョンのアプリ(nginx:1.26とnginx:1.27)でBlue/Greenデプロイメントを実装し、Serviceの切り替えを試してください。

チャレンジ問題

StatefulSetでRedisの3ノードクラスタを構成してください。各Podが固有のPVCを持ち、安定したDNS名でアクセスできることを確認しましょう。


参考リンク


次回予告: Day 10では「本番環境への準備とベストプラクティス」について学びます。Namespace、RBAC、リソース管理、モニタリング、そして本番運用のための総合的なベストプラクティスを習得しましょう。