CTS-KB

requests・limits・LimitRange・ResourceQuota:GKEの安定性とコストを管理する

⏱ 約 4 分で読めます
#Kubernetes#GKE#requests#limits#コスト最適化

KubernetesのCPU・メモリ設定は、安定性だけでなくPod配置とGKE料金に直結します。「LimitRate」という標準リソースはなく、正しくは requests・limits・LimitRange・ResourceQuota を組み合わせます。

Kubernetesのリソース管理とコストの関係

requestsとlimits

設定役割超過・不足時の主な影響
requests必要量の基準。schedulerが配置に利用大きすぎると配置効率と費用が悪化。小さすぎると競合しやすい
limits使用できる上限CPUは主に抑制、メモリはOOM終了の可能性
resources:
  requests:
    cpu: 250m
    memory: 256Mi
  limits:
    cpu: "1"
    memory: 512Mi

250m CPUは0.25 vCPU、256Mi は256 MiBです。メモリの MMi は単位が異なるため、チームで表記を統一します。

schedulerはrequestsを見る

実際のCPU使用率が低くても、requestsの合計を収容できないNodeにはPodを配置できません。たとえば500mを要求するPodを10個置くには、システム予約分を除いて概ね5 vCPU以上の割り当て余地が必要です。

Pending状態のPodで次のようなイベントが出たら、Node台数だけでなくrequestsと配置制約を確認します。

kubectl describe pod YOUR_POD_NAME -n YOUR_NAMESPACE
kubectl top pods -n YOUR_NAMESPACE
kubectl top nodes

kubectl top にはMetrics ServerまたはGKE側のメトリクス経路が必要です。瞬間値だけで決めず、通常時とピーク時を一定期間観測します。

CPU limitとmemory limitの違い

CPUは圧縮可能な資源です。上限に達すると処理時間を抑制され、レイテンシが上がることがあります。メモリは圧縮できず、上限超過ではコンテナが OOMKilled になる可能性があります。

kubectl get pod YOUR_POD_NAME -n YOUR_NAMESPACE \
  -o jsonpath='{.status.containerStatuses[*].lastState.terminated.reason}{"\n"}'
kubectl logs YOUR_POD_NAME -n YOUR_NAMESPACE --previous

OOMを見て即座にlimitだけを大幅増加させる前に、メモリリーク、同時処理数、キャッシュ、requestsとの差、実データ量を調べます。

LimitRangeでNamespaceの既定と範囲を決める

apiVersion: v1
kind: LimitRange
metadata:
  name: container-defaults
  namespace: YOUR_NAMESPACE
spec:
  limits:
    - type: Container
      defaultRequest:
        cpu: 100m
        memory: 128Mi
      default:
        cpu: 500m
        memory: 512Mi
      min:
        cpu: 50m
        memory: 64Mi
      max:
        cpu: "2"
        memory: 2Gi

LimitRangeは未指定コンテナへ既定値を補い、極端な値を拒否します。ただし既定値が突然入ると、既存Podの配置やAutopilot課金へ影響します。適用前に kubectl get deployments -o yaml とメトリクスを棚卸しします。

ResourceQuotaでNamespace全体を制限する

apiVersion: v1
kind: ResourceQuota
metadata:
  name: namespace-budget
  namespace: YOUR_NAMESPACE
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "30"
    services.loadbalancers: "2"

CPU・メモリだけでなく、Pod数やLoadBalancer Service数も制限できます。暴走防止には有効ですが、Quota到達時は新しいPodが作れず、ローリングアップデートが停止することがあります。maxSurge 分の余裕も含めます。

kubectl describe limitrange container-defaults -n YOUR_NAMESPACE
kubectl describe resourcequota namespace-budget -n YOUR_NAMESPACE

GKE Standardのコストとの関係

Standardでは、基本的にNodeとして確保したCompute Engine資源が課金対象です。

  • requestsが過大 → Pod密度が下がり、より多くのNodeが必要
  • requestsが過小 → 高密度になるが競合し、性能劣化やOOMが増える
  • limitsだけ大きい → schedulerはその最大値を予約しないため、Node上で競合し得る
  • 不要なNode Poolや最小Node数 → ワークロードが少なくても費用が残る

Cluster Autoscalerを使っても、スケールダウン制約、DaemonSet、ローカルストレージ、PodDisruptionBudgetなどでNodeが残る場合があります。

GKE Autopilotのコストとの関係

一般的なAutopilotワークロードのPodベース課金では、実行Podのrequestsが費用計算の重要な基準です。ただし特定ハードウェアやComputeClassではNodeベース課金になる場合があります。またAutopilotが未指定値を既定化・調整する場合もあります。

「Autopilotならrequestsは不要」ではなく、必要量を現実的に宣言することが費用と性能の両方に重要です。正確な課金方式は利用するComputeClassと現行料金ページで確認します。

調整の実務手順

  1. 全コンテナにrequestsを設定する
  2. 通常・ピーク・バッチ時のCPU、メモリ、レイテンシを観測する
  3. OOMKilled、CPU throttling、Pendingを確認する
  4. 余裕を残してrequests・limitsを小さく調整する
  5. HPAやレプリカ数との組み合わせを確認する
  6. NamespaceへLimitRangeとResourceQuotaを段階導入する
  7. GKE、Load Balancer、ログ、ストレージを含む請求を予算で監視する

コスト最適化は値を一度決めて終わりではありません。トラフィック、アプリバージョン、GC、依存サービスが変わるたびに見直します。

参考資料