LimitRangeとResourceQuotaでCPUとメモリを制御する

# はじめに

KubernetesのLimitRangeとResourceQuotaがよくわからなかったので、実際に動作させて確認してみました。

# LimitRangeとは

KubernetesにおけるLimitRangeとは、Namespace内で作成されるリソースに対して、デフォルト値・最大・最小値の制限を課す仕組みです。

例えばコンテナに対してCPU/メモリのデフォルト値、最大値 (limit)、最小値 (Request)を設定することができます。

指定できる対象のリソースは以下です。
- コンテナ
- Pod
- PersistentVolume

# ResourceQuotaとは

ResourceQuotaは、Namespace単位で使えるリソースの総量を制限する仕組みです。

制御できるものは以下です。 (代表的なもの)
- コンピューティングリソース
  - CPUのRequests/Limits
  - メモリのRequests/Limits
- オブジェクト数
  - Pod数
  - Service数
  - ConfigMap数
- ストレージ
  - PersistentVolumeの使用容量

# 環境情報

|Component|Version|
|---|---|
| PC | M1 MacBook Pro |
| OS | macOS 15.5 |
| Docker Desktop | 4.41.2 |
| kind | v0.29.0 |
| Kubernetes | v1.33.1 |

# LimitRangeの動作確認

limitsというNamespace内のContainerのrequests/limitsのデフォルト値をCPU: 1000m、メモリ: 1Giに設定します。

## LimitRangeを設定し、Podを作成

limitsというNamespaceを作成し、LimitRangeを設定し、limits NamespaceにPodを作成します。

```yaml:example.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: limits
---
apiVersion: v1
kind: LimitRange
metadata:
  name: limits
  namespace: limits
spec:
  limits:
  - type: Container
    default:
      cpu: 1000m
      memory: 1Gi
    defaultRequest:
      cpu: 1000m
      memory: 1Gi

---
apiVersion: v1
kind: Pod
metadata:
  name: example
  namespace: limits
spec:
  containers:
  - name: example
    image: nginx

```

## 実行結果

```zsh
❯ k apply -f example.yaml
❯ k -n limits get po example -o jsonpath='{range .spec.containers[*]}{.name}{"\n"}  Requests:{"\n"}    CPU: {.resources.requests.cpu}{"\n"}    Memory: {.resources.requests.memory}{"\n"}  Limits:{"\n"}    CPU: {.resources.limits.cpu}{"\n"}    Memory: {.resources.limits.memory}{"\n"}{"\n"}{end}' 
example
  Requests:
    CPU: 1
    Memory: 1Gi
  Limits:
    CPU: 1
    Memory: 1Gi
```

# ResourceQuotaの動作確認

quotaというNamespaceを作成して、CPUのLimitを1000m、メモリのLimitを1Giに設定します。

## ResourceQuotaの設定

quotaというNamespaceを作成して、ResourceQuotaを設定します。

```yaml:example.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: quota
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota
  namespace: quota
spec:
  hard:
    requests.cpu: 1000m
    requests.memory: 1Gi
    limits.cpu: 1000m
    limits.memory: 1Gi
```

## ResourceQuotaの作成

ResourceQoutaが設定されています。
```zsh
❯ k apply -f example.yaml
❯ k -n quota get quota 
NAME    REQUEST                                     LIMIT                                   AGE
quota   requests.cpu: 0/1, requests.memory: 0/1Gi   limits.cpu: 0/1, limits.memory: 0/1Gi   50s
```

## 1つ目のPodを作成

cpu: 500m、memory: 500MiのPodを作成します。

```yaml:pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
  namespace: quota
spec:
  containers:
  - name: pod1
    image: nginx
    resources:
      requests:
        cpu: "500m"
        memory: "500Mi"
      limits:
        cpu: "500m"
        memory: "500Mi"
```

Podが作成でき、ResourceQuotaにもリソースが反映されています。

```zsh
❯ k apply -f pod1.yaml
❯ k -n quota get quota
NAME    REQUEST                                            LIMIT                                          AGE
quota   requests.cpu: 500m/1, requests.memory: 500Mi/1Gi   limits.cpu: 500m/1, limits.memory: 500Mi/1Gi   4m52s
```

## 2つ目のPodを作成

2つ目のPodはcpu: 1000m、memory: 1GiのPodです。

```yaml:pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod2
  namespace: quota
spec:
  containers:
  - name: pod2
    image: nginx
    resources:
      requests:
        cpu: "1000m"
        memory: "1Gi"
      limits:
        cpu: "1000m"
        memory: "1Gi"
```


1つ目のPodと合わせるとリソースがResourceQuotaを超えるため、2つ目のPodの作成は失敗しました。
```zsh
❯ k apply -f pod2.yaml 
Error from server (Forbidden): error when creating "pod2.yaml": pods "pod2" is forbidden: exceeded quota: quota, requested: limits.cpu=1,limits.memory=1Gi,requests.cpu=1,requests.memory=1Gi, used: limits.cpu=500m,limits.memory=500Mi,requests.cpu=500m,requests.memory=500Mi, limited: limits.cpu=1,limits.memory=1Gi,requests.cpu=1,requests.memory=1Gi
```

# 最後に

LimitRangeとResourceQuotaがどういうものか、そしてその挙動について動作確認することができました

# 参考情報

- https://kubernetes.io/ja/docs/concepts/policy/limit-range/
- https://kubernetes.io/ja/docs/concepts/policy/resource-quotas/