Kubernetesコスト最適化 実践ガイド2026:クラウド費用を最大70%削減する7つの戦略

2026年版Kubernetesコスト最適化ガイド。Karpenter、VPA、スポットインスタンス、OpenCost/Kubecostを活用し、EKS・AKS・GKEのコストを最大70%削減する7つの戦略をYAML設定例付きで解説します。

はじめに:Kubernetesのコスト問題、正直シャレにならなくなってきた

2026年現在、Kubernetesはコンテナオーケストレーション市場の92%を占めていて、Fortune 100企業の77%が本番環境で使っています。もはや「使うかどうか」ではなく「どう運用するか」のフェーズですよね。

ただ、その普及に比例してクラウドコストの問題も深刻になっています。

FinOps Foundationの「State of FinOps 2026」レポートによると、組織のクラウド予算の平均32%が無駄になっていて、その総額は世界全体で年間2,000億ドル以上。正直、この数字を初めて見たときは二度見しました。中でもKubernetesワークロードは、その動的な性質とリソース管理の複雑さから、コスト最適化が特に難しい領域です。

もっと身近な話をすると、Kubernetesワークロードの65%は、要求されたCPU・メモリの半分以下しか使っていないというデータがあります。開発者が「落ちたら怖いから多めに」と設定する、あの"念のためバッファ"の積み重ねが、クラスタ全体では莫大なコスト浪費になっているわけです。

この記事では、AWS EKS・Azure AKS・GCP GKEにおけるKubernetesコストを最大70%削減するための実践的な戦略を、具体的なYAML設定やコマンド例とともに解説していきます。実際に筆者のチームで試して効果があった方法を中心にまとめたので、ぜひ参考にしてみてください。

戦略1:ライトサイジング — これが一番効く

なぜライトサイジングが最も効果的なのか

Kubernetesのスケジューラは、Podの実際の使用量ではなく「リソース要求(requests)」に基づいてスケジューリングします。ここがポイントです。requestsが過大に設定されていると、実際には余裕があるのにノードが「満杯」と判断されて、不要なノードがどんどん追加されてしまいます。

2026年の監査データによると、80〜90%のPodがCPU・メモリのrequestsを過大に設定しているとのこと。Podごとにわずか5〜15%のrequests削減でも、ビンパッキングの改善を通じてクラスタ全体で30〜60%のコスト削減につながります。これ、逆に言えば今すぐ手をつけるだけで大きな効果が出るということです。

Vertical Pod Autoscaler(VPA)でrequestsを自動最適化する

VPAは実際のリソース使用状況を監視して、適切なrequests/limitsを自動的に推奨・適用してくれるツールです。まずはインストールから。

# VPAのインストール(Helm)
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update
helm install vpa fairwinds-stable/vpa \
  --namespace vpa \
  --create-namespace

次に、対象のDeploymentに対してVPAリソースを作成します。いきなりAutoモードにするのはちょっと怖いので、最初はOffモードで推奨値だけ確認するのがおすすめです。

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
  namespace: production
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Off"  # まずは推奨値の確認から
  resourcePolicy:
    containerPolicies:
      - containerName: my-app
        minAllowed:
          cpu: 50m
          memory: 64Mi
        maxAllowed:
          cpu: 2000m
          memory: 4Gi
        controlledResources: ["cpu", "memory"]

推奨値の確認はこのコマンドで。

kubectl describe vpa my-app-vpa -n production

出力のRecommendationセクションに、Target(推奨値)、Lower Bound(最小推奨値)、Upper Bound(最大推奨値)が表示されます。この推奨値をもとにrequestsを調整すれば、過剰プロビジョニングを解消できます。実際にやってみると「こんなに余計にリソース確保してたのか…」と驚くはずです。

注意:VPAとHPAの併用には気をつけよう

VPAとHPA(Horizontal Pod Autoscaler)を同じリソースメトリクス(CPUなど)で同時に制御すると、お互いに競合することがあります。

2026年のベストプラクティスとしては、VPAを「Off」モードにして推奨値の取得だけに使い、スケーリングはHPAに任せるのが安全です。もう一つのアプローチとして、HPAではカスタムメトリクス(リクエスト数やキュー長など)を使い、VPAにCPU/メモリの最適化を担当させる方法もあります。

戦略2:Karpenterでノードプロビジョニングを賢くする

Cluster Autoscalerの限界

従来のCluster Autoscaler(CA)はAuto Scaling Group(ASG)経由でノードを管理しますが、正直いくつかの不満がありました。

  • スケーリングに3〜4分かかる(ASGの起動時間がボトルネック)
  • ノードグループごとにインスタンスタイプが固定される
  • 大規模クラスタ(2,000ノード超)でメモリ使用量が1GiBを超える
  • プロアクティブなコスト統合(Consolidation)機能がない

特にスケーリング速度の遅さは、トラフィックスパイク時に深刻な問題になります。

Karpenter:次世代のノードオートスケーラー

Karpenter(v1.5、2025年7月リリース)は、ASGを介さずEC2 APIと直接やり取りすることで、約45〜60秒でノードをオンラインにできます。この速度の違いは体感レベルで明らかです。さらに、数百のインスタンスタイプから最適なものを自動選択し、ノードの統合も自動で行ってくれます。

機能Cluster AutoscalerKarpenter
スケーリング速度3〜4分45〜60秒
ノード管理方式ASGベースEC2 API直接
インスタンス柔軟性ノードグループごとに固定数百タイプから自動選択
コスト統合なし(手動対応)自動(emptiness-first)
スポット中断対応制限ありネイティブ対応

KarpenterのNodePool設定例(スポットインスタンス活用)

では、スポットインスタンスを活用したコスト最適化向けのNodePool設定を見てみましょう。

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: spot-workers
spec:
  template:
    metadata:
      labels:
        node-type: spot
        cost-tier: economical
    spec:
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
      expireAfter: 168h  # 7日で自動リサイクル
      taints:
        - key: spot
          value: "true"
          effect: NoSchedule
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot"]
        - key: node.kubernetes.io/instance-type
          operator: In
          values:
            - m6i.large
            - m6i.xlarge
            - m6a.large
            - m6a.xlarge
            - m5.large
            - m5.xlarge
            - c6i.large
            - c6i.xlarge
            - r6i.large
            - r5.large
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
  limits:
    cpu: 500
    memory: 1000Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized

EC2NodeClassの設定

NodePoolと合わせて、AWS固有のインフラ設定もEC2NodeClassで定義しておきます。

apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: default
spec:
  amiFamily: AL2023
  amiSelectorTerms:
    - alias: al2023@latest
  role: "KarpenterNodeRole-my-cluster"
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster
  tags:
    team: platform
    environment: production

押さえておきたいポイント

  • インスタンスの多様化が鍵:Spot-to-Spot統合を有効にするには、最低15種類のインスタンスタイプを指定するのが推奨です。少なすぎるとSpotの可用性が下がります
  • Price Capacity Optimized(PCO)戦略:Karpenterはまず中断リスクが低いSpotプールを選び、次にその中で最安のものを選択してくれます
  • 中断のネイティブ処理:Spot中断の2分前警告を検知して、自動的にcordon → drain → 新ノード起動まで一気にやってくれます。これが地味に助かる
  • emptiness-first統合:v1.5で導入された機能で、空になったノードを積極的にリサイクルしてコストを削減します

戦略3:スポットインスタンスを戦略的に使い倒す

3大クラウドのスポット割引比較

まずは各クラウドのスポット事情を整理しておきましょう。

プロバイダーサービス名最大割引率中断通知
AWSEC2 Spot Instances最大90%2分前
AzureSpot VMs最大90%30秒前
GCPSpot VMs(旧Preemptible)最大91%30秒前

Azureの30秒は正直かなりシビアですね…。

スポットに向くワークロード・向かないワークロード

スポットインスタンスは万能ではありません。使い分けが大事です。

スポットに向くワークロード:

  • ステートレスなWebサービス(水平スケーリングできるもの)
  • CI/CDパイプライン
  • バッチ処理・データ変換
  • 開発・テスト環境
  • MLトレーニングジョブ(チェックポイント機能付き)

スポットに向かないワークロード:

  • ステートフルなデータベース
  • 低レイテンシが必須のAPIゲートウェイ
  • シングルレプリカのワークロード

基本的な考え方として、「突然落ちても数十秒以内に別のインスタンスで復旧できるか?」がスポット採用の判断基準になります。

EKSでのスポット活用:4層コスト構造

いきなり全部スポットにするのはリスクが高いので、以下のような4層構造がおすすめです。

  1. ベースライン(全体の60〜70%):Savings Plans / Reserved Instancesでカバー
  2. バッファ(15〜20%):オンデマンドインスタンス
  3. バースト対応(15〜20%):スポットインスタンス
  4. 開発・テスト環境:100%スポット(ここはケチって大丈夫)

Pod Disruption Budget(PDB)でスポット中断に備える

スポットを使うなら、PDBの設定は必須です。中断時にPodの可用性を維持するためのセーフティネットですね。

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
  namespace: production
spec:
  minAvailable: 2  # 常に最低2つのPodを維持
  selector:
    matchLabels:
      app: my-app

さらに、Pod Topology Spread Constraintsを使ってPodを複数のAZ・ノードに分散させておくと、単一のスポット中断による影響を最小限に抑えられます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 6
  template:
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: my-app
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: my-app
      tolerations:
        - key: spot
          value: "true"
          effect: NoSchedule
      containers:
        - name: my-app
          image: my-app:latest
          resources:
            requests:
              cpu: 250m
              memory: 512Mi
            limits:
              cpu: 500m
              memory: 1Gi

戦略4:コスト可視化 — OpenCostとKubecostで「見える化」する

なぜコスト可視化が必要なのか

「見えないものは最適化できない」——FinOpsの基本中の基本です。

Kubernetesのコストが厄介なのは、ノード料金がNamespace・Deployment・Pod単位に自動で分割されないこと。結果、どのチームやアプリがいくら使っているのかがブラックボックスになりがちです。「うちのチームはそんなに使ってないはず」と全員が思っている状況、経験ありませんか?

OpenCost:無料で始められるオープンソースソリューション

OpenCostはCNCFのIncubatingプロジェクトで、Kubernetesコストのリアルタイム配分を提供してくれます。コンテナレベルの粒度でコストを可視化でき、AWS・Azure・GCPの課金APIとも連携可能です。

# OpenCostのインストール
helm repo add opencost https://opencost.github.io/opencost-helm-chart
helm repo update
helm install opencost opencost/opencost \
  --namespace opencost \
  --create-namespace

インストールしたら、APIを通じてNamespace単位のコストを確認してみましょう。

# Namespace別コストの取得(過去24時間)
kubectl port-forward -n opencost svc/opencost 9090:9090 &

curl -s "http://localhost:9090/allocation/compute?window=24h&aggregate=namespace" \
  | jq '.data | to_entries | .[] | {
    namespace: .key,
    totalCost: .value.totalCost
  }'

初めて実行すると、予想外のNamespaceが上位に来て驚くことが多いです。

Kubecost:エンタープライズ向けの高度な可視化

KubecostはOpenCostを基盤としつつ、割引(RI/Savings Plans/Spot)の反映やマルチクラスタ対応、コスト予測、異常検知といった高度な機能を備えています。

# Kubecostのインストール(無料版)
helm repo add kubecost https://kubecost.github.io/cost-analyzer/
helm repo update
helm install kubecost kubecost/cost-analyzer \
  --namespace kubecost \
  --create-namespace

両者の機能比較はこんな感じです。

機能OpenCostKubecost FreeKubecost Enterprise
コスト配分(Pod/Namespace)
割引・Spot価格の反映×
マルチクラスタ××
コスト予測・異常検知×
最適化推奨×
ライセンスApache 2.0無料有料

個人的には、まずOpenCostで始めて、マルチクラスタ管理が必要になったタイミングでKubecostに移行するのがスムーズだと思います。

戦略5:Resource QuotaとLimitRangeでガバナンスを効かせる

Namespace単位のリソース制限

開発チームが無制限にリソースを要求できる環境では、コスト管理なんて不可能です。(これは断言できます。)Resource QuotaとLimitRangeを使って、組織的なガバナンスを導入しましょう。

apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-a-quota
  namespace: team-a
spec:
  hard:
    requests.cpu: "20"
    requests.memory: 40Gi
    limits.cpu: "40"
    limits.memory: 80Gi
    pods: "100"
    persistentvolumeclaims: "20"

LimitRangeでデフォルト値を設定する

開発者がrequests/limitsを指定し忘れた場合に備えて、デフォルト値を設定しておくのも重要です。「requests未指定で巨大なノードが割り当てられてしまった」なんて事故、意外とよくあるんですよね。

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: team-a
spec:
  limits:
    - type: Container
      default:
        cpu: 250m
        memory: 256Mi
      defaultRequest:
        cpu: 100m
        memory: 128Mi
      max:
        cpu: 4000m
        memory: 8Gi
      min:
        cpu: 50m
        memory: 64Mi

戦略6:アイドルリソースのクリーンアップと自動スケジュール

開発・テスト環境の自動停止

開発環境やステージング環境を24時間動かし続ける必要、本当にありますか?

業務時間外にクラスタをスケールダウンするだけで、かなりのコスト削減になります。以下はCronJobとkubectlを使ったシンプルな自動スケジュールの例です。

apiVersion: batch/v1
kind: CronJob
metadata:
  name: scale-down-dev
  namespace: dev
spec:
  schedule: "0 20 * * 1-5"  # 平日20時にスケールダウン
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: scaler
          containers:
            - name: kubectl
              image: bitnami/kubectl:latest
              command:
                - /bin/sh
                - -c
                - |
                  kubectl scale deployment --all --replicas=0 -n dev
          restartPolicy: OnFailure
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: scale-up-dev
  namespace: dev
spec:
  schedule: "0 8 * * 1-5"  # 平日8時にスケールアップ
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: scaler
          containers:
            - name: kubectl
              image: bitnami/kubectl:latest
              command:
                - /bin/sh
                - -c
                - |
                  kubectl scale deployment --all --replicas=2 -n dev
          restartPolicy: OnFailure

これだけで、開発環境のコストを最大50%以上カットできます。導入のハードルも低いので、まだやっていないなら今日にでも設定してほしいくらいです。

孤立リソースの検出と削除

時間が経つにつれて、こういった「孤立リソース」が静かにコストを食い続けます。

  • Pod削除後も残っているPersistentVolumeClaim(PVC)
  • 使われなくなったLoadBalancerタイプのService
  • 古いConfigMapやSecret
  • 放置されたNamespace

定期的にチェックする習慣をつけましょう。以下のコマンドが便利です。

# PVCの使用状況を一覧表示(作成日順)
kubectl get pvc --all-namespaces --sort-by=.metadata.creationTimestamp

# LoadBalancerタイプのServiceを一覧表示
kubectl get svc --all-namespaces -o wide | grep LoadBalancer

# 長期間更新されていないNamespaceの確認
kubectl get namespaces --sort-by=.metadata.creationTimestamp

戦略7:ネットワークコストの最適化

見落としがちなネットワーク転送コスト

クラウドのネットワーク転送(Egress)コスト、意外と見落としていませんか? 特にAZ間・リージョン間の通信が多いマイクロサービスアーキテクチャでは、無視できない金額になります。

Topology Aware Routingの活用

Kubernetes v1.27以降で安定版となったTopology Aware Routingは、同じAZ内のPodへ優先的にトラフィックをルーティングしてくれます。設定もシンプルで、Serviceにアノテーションを追加するだけです。

apiVersion: v1
kind: Service
metadata:
  name: my-service
  annotations:
    service.kubernetes.io/topology-mode: Auto
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080

たったこれだけでAZ間転送コストを削減できます。やらない理由がないですよね。

VPCエンドポイントでEgressコストを削減

AWSの場合、S3・ECR・DynamoDBなどのサービスへのアクセスにVPCエンドポイントを設定すると、トラフィックがAWSネットワーク内に留まってEgressコストを回避できます。

# Terraform例:S3用VPCエンドポイント
resource "aws_vpc_endpoint" "s3" {
  vpc_id       = var.vpc_id
  service_name = "com.amazonaws.ap-northeast-1.s3"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = var.route_table_ids

  tags = {
    Name = "s3-vpc-endpoint"
    team = "platform"
  }
}

マルチクラウド環境でのコスト最適化比較

AWS・Azure・GCPのKubernetesマネージドサービスには、それぞれ異なるコスト最適化の特色があります。

機能AWS EKSAzure AKSGCP GKE
コントロールプレーン料金$0.10/時間無料(Standardティア)無料(Standardモード)
ノードオートスケーラーKarpenter / CAKarpenter(プレビュー)/ CAGKE Autopilot / CA
スポット割引最大90%最大90%最大91%
コミットメント割引Savings Plans(最大72%)Reservations(最大65%)CUD(最大70%)
自動ライトサイジング手動 / サードパーティ手動 / サードパーティGKE Autopilotが自動
コスト監視ネイティブCost ExplorerCost ManagementBilling Reports

特にGKE Autopilotは注目に値します。ノード管理をGoogleに完全に任せることで、ライトサイジングとビンパッキングの最適化を自動でやってくれるため、運用負荷とコスト両方の削減が期待できます。Kubernetesの運用に専任チームを割けない組織には特におすすめです。

コスト最適化チェックリスト

さて、ここまで読んでいただいた方に、すぐに実行できるアクションアイテムをまとめておきます。

  1. VPAを「Off」モードでデプロイし、全Deploymentの推奨値を確認する(まずはここから)
  2. requestsが実使用量の2倍以上のPodを特定し、ライトサイジングする
  3. EKSならKarpenterを導入し、スポットインスタンスとConsolidationを有効化する
  4. OpenCostまたはKubecostを導入し、Namespace・チーム別のコスト配分を可視化する
  5. Resource QuotaとLimitRangeを全Namespaceに設定する
  6. 開発・テスト環境に自動スケジュールを設定し、業務時間外はスケールダウンする
  7. 孤立PVC・未使用LoadBalancerを定期的に監査・削除する
  8. Topology Aware RoutingとVPCエンドポイントでネットワークコストを削減する

全部を一度にやる必要はありません。まずは戦略1のライトサイジングから始めて、効果を実感してから次のステップに進むのが現実的です。

よくある質問(FAQ)

Q1: Kubernetesのコスト最適化で最も効果が大きい施策は何ですか?

ライトサイジング(requests/limitsの適正化)です。Kubernetesワークロードの65%以上が要求リソースの半分以下しか使用しておらず、requestsを適正化するだけでクラスタ全体で30〜60%のコスト削減が見込めます。VPAを「Off」モードで導入して、まずは推奨値を確認するところから始めてみてください。

Q2: KarpenterとCluster Autoscalerのどちらを使うべきですか?

AWS EKSを使っているなら、2026年時点ではKarpenterが推奨です。ノードのプロビジョニングが約45〜60秒と高速で、数百のインスタンスタイプから最適なものを自動選択し、Consolidation機能でコストも自動最適化してくれます。ただし、オンプレミスとのハイブリッド環境や厳格なコンプライアンス要件がある場合は、Cluster Autoscalerの方が適していることもあります。

Q3: スポットインスタンスを本番環境で使っても大丈夫ですか?

条件付きですが、安全に使えます。ステートレスでレプリカ数が十分なワークロードであれば、Pod Disruption BudgetとTopology Spread Constraintsを適切に設定することで、スポット中断時もサービスの可用性を維持できます。ただし、シングルレプリカのワークロードやステートフルなサービスには使わないでください。

Q4: Kubernetes環境のコスト可視化はどのツールから始めるべきですか?

無料のOpenCostから始めるのがおすすめです。Helmで簡単にインストールできて、Namespace・Pod単位でのコスト配分を可視化できます。マルチクラスタ環境や割引の正確な反映が必要になった段階で、Kubecostへの移行を検討すればOKです。

Q5: GKE Autopilotは本当にコスト削減に効果がありますか?

特にKubernetesの運用経験が少ないチームには効果的です。ノード管理をGoogleに任せることで、ライトサイジングとビンパッキングが自動最適化されます。ただしPod単位の課金モデルなので、常に高い使用率を維持している環境ではStandardモードの方がお得な場合もあります。ワークロードの特性に応じて比較してみてください。

著者について Editorial Team

Our team of expert writers and editors.