Kubernetesのリソース管理周りの調査方法

Uncategorized

Kubernetesのリソース管理の調査方法

  • 消えてほしくないPodがevictedで強制終了させられている
  • 特定のpodを安定してノード上で稼働させたい
  • k8sにpodが動的にアサインされる予定だが、どのように管理されるか分からない

皆さんこんなご経験はないでしょうか

私はKEDAを用いたイベントドリブンなk8sクラスター運用を行った際に上記のような現象や不安に遭いました。
その際に行った対応を備忘録を兼ねて残します。

k8sのリソース管理について

最初にk8sのリソース管理の仕組みについて説明します。

resouces

k8sではコンテナ単位で使用するメモリ、CPUに制限を設けることができます。
メモリが超過した場合、OOM(Out of Memory)エラーが発生し、コンテナが強制終了されます。
CPUが超過した場合スロットリング(制限)され、処理が遅くなります。

nginxのレプリカセットを作成するymlを例に挙げますが、manifestにおけるリソース指定は以下のようにresoucesで行います。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        resources:
          requests:
            cpu: "250m"      # 最低250m(0.25CPU)を保証
            memory: "256Mi"  # 最低256MiBのメモリを保証
          limits:
            cpu: "500m"      # 最大500m(0.5CPU)まで使用可能
            memory: "512Mi"  # 最大512MiBのメモリまで使用可能
        ports:
        - containerPort: 80

この例の場合、最低0.25CPU256MiBのメモリを割り当てられ、アクセス負荷によっては0.5CPU512MiBまで利用できる、ということになります。

PriorityClass

ポッドを割り当てるリソースがノードにない場合、k8sはどのようになるでしょう?
この時k8sはPriorityClassQoSClassという2つのクラスによる辞書式順序を用いてPodを削除することでリソースを管理します。
PriorityClassを確認し劣後するPodを削除、もし全てのPriorityClassが等しい場合はQoSClassを確認して劣後するPodを削除、といった具合です。

PriorityClassは以下のようにリソースとして定義します。

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 100000  # 優先度のスコア(高いほど優先)
preemptionPolicy: PreemptLowerPriority  # 低優先度ポッドを退避させる
globalDefault: false
description: "High priority class for critical workloads"

premptionPolicyは低優先Podをどのように扱うかを定義するエリアで、低優先Podを削除するPreemptLowerPriority、削除しないNeverがあります。

作成したクラスにPodをアサインすることで、優先順位をつけることができます。

apiVersion: v1
kind: Pod
metadata:
  name: high-priority-pod
spec:
  priorityClassName: high-priority  # 先ほど作成したPriorityClassを指定
  containers:
  - name: nginx
    image: nginx
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"

QoS

参考:https://kubernetes.io/docs/concepts/workloads/pods/pod-qos/

k8sはQuality of Service (QoS)という概念を持っており、これによって全てのポッドはBestEffort, Burstable, Guranteedの3種類に分類されています。
PriorityClassが等しいとき、k8sはQoSに従って削除するPodを決定します。

BestEffort

最も優先度の低いクラスがBestEffortです。(名前の通りですね)
ノードがリソース不足でPodを整理する必要がある場合、真っ先に削除されます。
ポッドがBestEffortになる基準は以下です。

  • どのコンテナもresourceの定義を持たない

基本的にBestEffortにするのはログのクリーンナップなど、いつでもいいから空いているときに行ってほしい作業に限ります。

Guaranteed

BestEffortと反対に最も優先度の高いクラスがGuranteedになります。

このクラスは他の2つのクラスよりも優先的にノードに配置され、リソースが不足した場合は他のクラスを追い出します。

PodがGuranteedに分類されるためにはCPU・メモリそれぞれについて以下を満たす必要があります。

  • ポッド内のすべてのコンテナに、requestslimitが定義されている
  • ポッド内のすべてのコンテナそれぞれについて、requestslimitが等しい

CPUもメモリもあらかじめ決められた量で利用するということですね。

Burstable

残った中間層がBurstableになります。Podとしてのスケール能力を残しつつ最低限の動作保証を行いたい場合はこのクラスにアサインされるようにします。

Burstableに分類される条件はBestEffortでもGuranteedでもないことですが、書き下すと以下になります。

  • Guranteedの基準を満たさない
  • 少なくとも1つのコンテナにメモリかCPUのrequestlimitが定義されている。

逆引き辞典

k8sのポッドの消費リソースを確認したい

kubectl topコマンドでリソースの確認が行えます。

kubectl top pod
# >>>
# NAME                      CPU(cores)   MEMORY(bytes)   
# nginx-deployment-abc123   50m         20Mi           
# nginx-deployment-def456   70m         30Mi           
# backend-app-xyz789        200m        150Mi      

これは実際の消費量に基づくため、resourceで1000m割り当てたからと言って1000mと表示されはしません。
Podと同様にNodeのリソース使用量は以下で確認できます。

kubectl top node

デプロイされているPodがどのQoSに属しているかを確認したい

kubectl describeで詳細情報を取得することで確認できます。

kubectl describe pod <ポッド名> | grep QoS

ちなみにVSCode拡張機能のKubernetesからリソースを右クリック->describeでも簡単に確認できます。メトリック計測などは難しいですが、k8sの簡易GUIとして重宝します。

file

特定のポッドを優先的にノードに配置したい

確実なのはPriorityの高いクラスに配置することです。業務最優先のPodはまず高PriorityClassに所属されることを考えます。

apiVersion: v1
kind: Pod
metadata:
  name: high-priority-pod
spec:
  priorityClassName: high-priority  # 先ほど作成したPriorityClassを指定
  containers:
  - name: nginx
    image: nginx
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"

参考

k8s公式ドキュメント

コメント

タイトルとURLをコピーしました