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

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です。メモリの M と Mi は単位が異なるため、チームで表記を統一します。
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と現行料金ページで確認します。
調整の実務手順
- 全コンテナにrequestsを設定する
- 通常・ピーク・バッチ時のCPU、メモリ、レイテンシを観測する
- OOMKilled、CPU throttling、Pendingを確認する
- 余裕を残してrequests・limitsを小さく調整する
- HPAやレプリカ数との組み合わせを確認する
- NamespaceへLimitRangeとResourceQuotaを段階導入する
- GKE、Load Balancer、ログ、ストレージを含む請求を予算で監視する
コスト最適化は値を一度決めて終わりではありません。トラフィック、アプリバージョン、GC、依存サービスが変わるたびに見直します。