k8sのリソース管理まとめ

2022/10/31に公開約3,100字

業務でコンテナのリソース管理を整理する機会があったので、将来の自分のための備忘録

TL;DR

  • コンテナ単位での制御 → spec.containers[].resources
    • requestsの値と実使用量は違うので、limitsは明示的に指定しよう
  • オーバーコミットしている時は、実使用量を取得・考慮して、追加のリソースをデプロイしよう
    • メモリはOOMによるプロセス停止が発生する可能性あるので特に注意
  • namespace単位での制御 → LimitRange, ResourceQuota

リソース制限

制限をかけられるリソース

  • CPU : 1 = 1000m = 1vCPU
  • メモリ : 100M, 1G
  • エフェメラルストレージ
  • GPU (デバイスプラグイン必要)

https://kubernetes.io/ja/docs/concepts/configuration/manage-resources-containers/

requests,limits

  • requests
    • コンテナを起動するために必要な空きリソース(割り当て可能なリソース)
    • コンテナは、この値を超えてリソースを使用することができる
    • スケジューラーは、この値を見てNodeに空きがない場合は、コンテナを起動しない。
      [重要!!!]実際のNodeのリソース使用量を見てるわけではない
  • limits
    • コンテナが使用できるリソース量を制限できる
    • limitsを超えた時
      • メモリ : OOMでコンテナが強制終了, SIGTERMが送られずkill
      • CPU : コンテナは終了しない

マニフェストと挙動

以下の場合

  • コンテナは cpu 250m・ memory 64Mの空きがNodeにないと起動されない
  • コンテナは cpu 500m・ memory 128Mまでリソースを使用できる
yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-pod
spec:
  containers:
  - name: nginx-container
    image: nginx
    resources:
      requests:
        memory: "64M"
        cpu: "250m"
      limits:
        memory: "128M"
        cpu: "500m"
  • requestsのみ指定した場合
    • limitは未指定のまま
apiVersion: v1
kind: Pod
...
    resources:
      requests:
        memory: "64M"
        cpu: "250m"
k get po sample-pod -o json | jq .spec.containers[0].resources
{
  "requests": {
    "cpu": "250m",
    "memory": "64M"
  }
}
  • limitsのみ指定した場合
    • requestはlimitsの値が指定される
apiVersion: v1
kind: Pod
...
    resources:
      limits:
        memory: "64M"
        cpu: "250m"
k get po sample-pod -o json | jq .spec.containers[0].resources
{
  "limits": {
    "cpu": "250m",
    "memory": "64M"
  },
  "requests": {
    "cpu": "250m",
    "memory": "64M"
  }
}

QoS Class

k8s は requests,limits に応じて Pod に QoS(Quality of Service)Class を割り当てる。
3種類あり、k8s がコンテナの oom score を設定する際に使用。

Class 条件 OOM Killの順序
Guaranteed requests,limits 共に設定されている && 同値 3
Burstable requests,limits 共に設定されている && 同値ではない 2
BestEffort requests,limits 共に設定されていない 1

オーバーコミット

コンテナのlimitsの合計がNodeのリソースより大きくても許容する方式のこと
例えば以下の例だとNodeの4GBに対して、limits 2GBのPodを4つ立てることができる

podが常時多くのリソースを使用する場合ではない時であれば、可能な構成
とはいえ、同時にpodの負荷が高まるなどでNodeの上限を超えると、PodがEvict (終了される)ので不安定な状態となる
podのリソース集約とのトレードオフを検討して利用するか判断

またk8sは上述の通り、マニフェストとNodeのrequest値のみを見てデプロイ可否を判断するため、Nodeの残がギリギリでもpodを配置する。
kubectl desribe node <node名>やDataDogなどを用いて、Nodeの実使用量から残物理量を算出しておく必要がある

LimitRange

Namespace単位でPodなどに対して、リソース制限を設けることができる
https://kubernetes.io/ja/docs/concepts/policy/limit-range/

ResourceQuota

Namespace単位で、kubernetesリソースの使用量やデプロイする個数を制限できる
https://kubernetes.io/ja/docs/concepts/policy/limit-range/

ex)
count/pod : pod数
requests.cpu : 全podのrequests.cpuの合計

まとめ

きちんとリソース制限は設けましょう
HPA・VPAや、Evictされた時の挙動や設定などもまとめて整理しておきたい

参照

https://kubernetes.io/ja/docs/concepts/configuration/manage-resources-containers/
https://kubernetes.io/ja/docs/concepts/policy/limit-range/
https://kubernetes.io/ja/docs/concepts/policy/limit-range/

Discussion

ログインするとコメントできます