【Kubernetes】ResourceQuotaでリソース制限

2022.01.13
2024.03.24
Kubernetes
ResourceQuota

本ページはAmazonアフィリエイトのリンクを含みます。

はじめに

Kubernetesのリソース制限ができるResourceQuotaについてざっくり解説しながら、実際に使っていきたいと思います。

ResourceQuotaとは

ResourceQuotaとは、Namespaceごとのリソース量を制限することができるオブジェクトです。

コンピュータリソースからPodの数などのオブジェクト数までの割り当て(クォータ)を決めることができます。

現状はNamespaceごとにResourceQuotaを作成することを強制することはできませんが、将来的に設定できるように計画しているみたいです。(公式ドキュメントより)

クォータ

設定できるクォータについてざっくり紹介します。

コンピュートリソース

リソース名説明
limits.cpuPodのCPUのlimitの合計
limits.memoryPodのMemoryのlimitの合計
requests.cpu(cpu)PodのCPUのrequestの合計
requests.memory(memory)PodのMemoryのrequestの合計
hugepages-<size>Podでの指定したサイズのリクエストの数

request(要求)とlimit(制限)の違いは下記を参考にしてください。

コンテナのリソース管理

コンテナのリソース管理

Podを指定する際に、コンテナが必要とする各リソースの量をオプションで指定することができます。 指定する最も一般的なリソースはCPUとメモリ(RAM)ですが、他にもあります。 Pod内のコンテナのリソース要求を指定すると、スケジューラはこの情報を使用して、どのNodeにPodを配置するかを決定します。コンテナに制限ソースを指定すると、kubeletはその制限を適用し、実行中のコンテナが設定した制限を超えてリソースを使用することができないようにします。また、kubeletは、少なくともそのシステムリソースのうち、要求の量を、そのコンテナが使用するために特別に確保します。 要求と制限 Podが動作しているNodeに利用可能なリソースが十分にある場合、そのリソースの要求が指定するよりも多くのリソースをコンテナが使用することが許可されます ただし、コンテナはそのリソースの制限を超えて使用することはできません。 たとえば、コンテナに256MiBのメモリー要求を設定し、そのコンテナが8GiBのメモリーを持つNodeにスケジュールされたPod内に存在し、他のPodが存在しない場合、コンテナはより多くのRAMを使用しようとする可能性があります。 そのコンテナに4GiBのメモリー制限を設定すると、kubelet(およびコンテナランタイム) が制限を適用します。ランタイムは、コンテナが設定済みのリソース制限を超えて使用するのを防ぎます。例えば、コンテナ内のプロセスが、許容量を超えるメモリを消費しようとすると、システムカーネルは、メモリ不足(OOM)エラーで、割り当てを試みたプロセスを終了します。 制限は、違反が検出されるとシステムが介入するように事後的に、またはコンテナが制限を超えないようにシステムが防ぐように強制的に、実装できます。 異なるランタイムは、同じ制限を実装するために異なる方法をとることができます。 備考:コンテナが自身のメモリー制限を指定しているが、メモリー要求を指定していない場合、Kubernetesは制限に一致するメモリー要求を自動的に割り当てます。同様に、コンテナが自身のCPU制限を指定しているが、CPU要求を指定していない場合、Kubernetesは制限に一致するCPU要求を自動的に割り当てます。 リソースタイプ CPUとメモリーはいずれもリソースタイプです。リソースタイプには基本単位があります。 CPUは計算処理を表し、Kubernetes CPUsの単位で指定されます。 メモリはバイト単位で指定されます。 Kubernetes v1.14以降を使用している場合は、huge pageリソースを指定することができます。 Huge PageはLinux固有の機能であり、Nodeのカーネルはデフォルトのページサイズよりもはるかに大きいメモリブロックを割り当てます。 たとえば、デフォルトのページサイズが4KiBのシステムでは、hugepages-2Mi: 80Miという制限を指定できます。 コンテナが40を超える2MiBの巨大ページ(合計80 MiB)を割り当てようとすると、その割り当ては失敗します。 備考:hugepages-*リソースをオーバーコミットすることはできません。 これはmemoryやcpuリソースとは異なります。 CPUとメモリーは、まとめてコンピュートリソースまたは単にリソースと呼ばれます。 コンピューティングリソースは、要求され、割り当てられ、消費され得る測定可能な量です。 それらはAPI resourcesとは異なります。 PodやServicesなどのAPIリソースは、Kubernetes APIサーバーを介して読み取りおよび変更できるオブジェクトです。 Podとコンテナのリソース要求と制限 Podの各コンテナは、次の1つ以上を指定できます。 spec.containers[].resources.limits.cpu spec.containers[].resources.limits.memory spec.containers[].resources.limits.hugepages-<size> spec.containers[].resources.requests.cpu spec.containers[].resources.requests.memory spec.containers[].resources.requests.hugepages-<size> 要求と制限はそれぞれのコンテナでのみ指定できますが、このPodリソースの要求と制限の関係性について理解すると便利です。 特定のリソースタイプのPodリソース要求/制限は、Pod内の各コンテナに対するそのタイプのリソース要求/制限の合計です。 Kubernetesにおけるリソースの単位 CPUの意味 CPUリソースの制限と要求は、cpu単位で測定されます。 Kubernetesにおける1つのCPUは、クラウドプロバイダーの1 vCPU/コアおよびベアメタルのインテルプロセッサーの1 ハイパースレッドに相当します。 要求を少数で指定することもできます。 spec.containers[].resources.requests.cpuが0.5のコンテナは、1CPUを要求するコンテナの半分のCPUが保証されます。 0.1という表現は100mという表現と同等であり、100ミリCPUと読み替えることができます。 100ミリコアという表現も、同じことを意味しています。 0.1のような小数点のある要求はAPIによって100mに変換され、1mより細かい精度は許可されません。 このため、100mの形式が推奨されます。 CPUは常に相対量としてではなく、絶対量として要求されます。 0.1は、シングルコア、デュアルコア、あるいは48コアマシンのどのCPUに対してでも、同一の量を要求します。 メモリーの意味 メモリーの制限と要求はバイト単位で測定されます。 E、P、T、G、M、Kのいずれかのサフィックスを使用して、メモリーを整数または固定小数点数として表すことができます。 また、Ei、Pi、Ti、Gi、Mi、Kiのような2の累乗の値を使用することもできます。 たとえば、以下はほぼ同じ値を表しています。 128974848, 129e6, 129M, 123Mi 例を見てみましょう。 次のPodには2つのコンテナがあります。 各コンテナには、0.

0.5CPUは1CPUの半分になります。

ストレージリソース

リソース名説明
requests.storagePVCのストレージの合計
persistentvolumeclaimsPVCの総数
<storage-class-name>.storageclass.storage.k8s.io/requests.storage特定のストレージクラスのPVCのストレージの合計
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims特定のストレージクラスのPVCの総数
requests.ephemeral-storage(ephemeral-storage)エフェメラルストレージのrequestの合計
limits.ephemeral-storageエフェメラルストレージのlimitの合計

オブジェクト数

リソース名説明
configmapsConfigMapの総数
persistentvolumeclaimsPersistentVolumeClaimの総数
podsPodの総数
replicationcontrollersReplicationControlerの総数
resourcequotasResourceQuotaの総数
servicesServiceの総数
services.loadbalancersLoadBalancerのServiceの総数
services.nodeportsNodePortのServiceの総数
secretsSecretの総数

使ってみる

ここからは実際にResourceQuotaを実際に使ってみたいと思います。

Namespace作成

まずはリソース制限をするNamespaceを作成します。

1kubectl create ns demo

kubensコマンドでNamespaceを切り替えます。

1kubens demo

kubensコマンドのインストールや使い方については下記を参考にしてください。

【Kubernetes】kubectxとkubensでContextとNamespaceを簡単に切り替える

【Kubernetes】kubectxとkubensでContextとNamespaceを簡単に切り替える

:::affiliate-message 本ページはAmazonアフィリエイトのリンクを含みます。

ResourceQuota作成

ResouceQuotaを作成します。

マニフェストresourcequota.yamlは下記の通りです。

1apiVersion: v1
2kind: ResourceQuota
3metadata:
4  name: resource-quota
5spec:
6  hard:
7   limits.cpu: "0.7"
8   limits.memory: 1Gi
9   requests.cpu: "0.3"
10   requests.memory: 500Mi
11   pods: "2"

CPUとMemoryのlimitsとrequests、Pod数の制限をしています。

マニフェストからResourceQuotaを作成します。

1kubectl apply -f resourcequota.yaml

作成したResouceQuotaを確認してみます。 このNamespaceでは何も作成していないので、Usedが全て0になっています。

1❯ kubectl describe quota
2Name:            resource-quota
3Namespace:       demo
4Resource         Used  Hard
5--------         ----  ----
6limits.cpu       0     700m
7limits.memory    0     1Gi
8pods             0     2
9requests.cpu     0     300m
10requests.memory  0     500Mi

Deployment作成

Deploymentを作成していきます。

Deploymentが作成するPodには2つのコンテナを含めています。 マニフェストdeployment.yamlは下記の通りです。

1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: test-deployment
5spec:
6  replicas: 2
7  selector:
8    matchLabels:
9      app: app1
10  template:
11    metadata:
12      labels:
13        app: app1
14    spec:
15      containers:
16        - name: nginx
17          image: nginx:latest
18          resources:
19            requests:
20              memory: 100Mi
21              cpu: 100m
22            limits:
23              memory: 200Mi
24              cpu: 200m
25        - name: redis
26          image: redis:latest
27          resources:
28            requests:
29              memory: 200Mi
30              cpu: 200m
31            limits:
32              memory: 500Mi
33              cpu: 500m

PodのCPUとMemoryのlimitsとrequestsの合計はそれぞれ下記になります。

  • requests CPU: 300m
  • limits CPU: 700m
  • requests Memory: 300Mi
  • limits Memory: 700Mi

さらにレプリカ数が2であるので、上記の倍のリソースが必要になります。 つまり、最終的に必要なリソースは下記になります。

  • requests CPU: 600m
  • limits CPU: 1400m
  • requests Memory: 600Mi
  • limits Memory: 1.4Gi

Deploymentを作成します。

1kubectl apply -f deployment.yaml

作成結果確認

DeploymentからPodを作成できたのか確認してみます。

1❯ kubectl get deployment
2NAME              READY   UP-TO-DATE   AVAILABLE   AGE
3test-deployment   1/2     1            1           14s
4
5❯ kubectl get rs
6NAME                         DESIRED   CURRENT   READY   AGE
7test-deployment-8676fcf7bc   2         1         1       19s
8
9❯ kubectl get pod
10NAME                               READY   STATUS    RESTARTS   AGE
11test-deployment-8676fcf7bc-pzg86   2/2     Running   0          23s

Podは1つしか作成されていないのが確認できます。

また、ReplicaSetの詳細を確認してみるとPodの作成でエラーになっていることがわかります。

1❯ kubectl describe rs test-deployment-8676fcf7bc
2Name:           test-deployment-8676fcf7bc
3Namespace:      demo
4
5          :
6          :
7
8Conditions:
9  Type             Status  Reason
10  ----             ------  ------
11  ReplicaFailure   True    FailedCreate
12Events:
13  Type     Reason            Age                 From                   Message
14  ----     ------            ----                ----                   -------
15  Normal   SuccessfulCreate  112s                replicaset-controller  Created pod: test-deployment-8676fcf7bc-pzg86
16  Warning  FailedCreate      112s                replicaset-controller  Error creating: pods "test-deployment-8676fcf7bc-cpkjn" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi
17  Warning  FailedCreate      112s                replicaset-controller  Error creating: pods "test-deployment-8676fcf7bc-qvtb8" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi
18  Warning  FailedCreate      112s                replicaset-controller  Error creating: pods "test-deployment-8676fcf7bc-ckk7b" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi
19  Warning  FailedCreate      112s                replicaset-controller  Error creating: pods "test-deployment-8676fcf7bc-2ck57" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi
20  Warning  FailedCreate      112s                replicaset-controller  Error creating: pods "test-deployment-8676fcf7bc-sktfv" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi
21  Warning  FailedCreate      112s                replicaset-controller  Error creating: pods "test-deployment-8676fcf7bc-gkwxb" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi
22  Warning  FailedCreate      111s                replicaset-controller  Error creating: pods "test-deployment-8676fcf7bc-m2nzz" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi
23  Warning  FailedCreate      111s                replicaset-controller  Error creating: pods "test-deployment-8676fcf7bc-9hhpv" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi
24  Warning  FailedCreate      111s                replicaset-controller  Error creating: pods "test-deployment-8676fcf7bc-f9fbc" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi
25  Warning  FailedCreate      61s (x6 over 109s)  replicaset-controller  (combined from similar events): Error creating: pods "test-deployment-8676fcf7bc-bgzk6" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, used: limits.cpu=700m,limits.memory=700Mi,requests.cpu=300m,requests.memory=300Mi, limited: limits.cpu=700m,limits.memory=1Gi,requests.cpu=300m,requests.memory=500Mi

ResourceQuotaの詳細を確認してみると、リソースが足りていないことがわかります。

1❯ kubectl describe quota
2Name:            resource-quota
3Namespace:       demo
4Resource         Used   Hard
5--------         ----   ----
6limits.cpu       700m   700m
7limits.memory    700Mi  1Gi
8pods             1      2
9requests.cpu     300m   300m
10requests.memory  300Mi  500Mi

ResourceQuota変更

ResouceQuotaが足りていないことがわかったので、ResouceQuotaのクォータを増やしてみます。

1apiVersion: v1
2kind: ResourceQuota
3metadata:
4  name: resource-quota
5spec:
6  hard:
7   limits.cpu: "1.5"
8   limits.memory: 2Gi
9   requests.cpu: "0.6"
10   requests.memory: 800Mi
11   pods: "2"

ResouceQuotaを更新します。

1kubectl apply -f resourcequota.yaml

クォータが増えているのを確認します。

1❯ kubectl describe quota
2Name:            resource-quota
3Namespace:       demo
4Resource         Used   Hard
5--------         ----   ----
6limits.cpu       700m   1500m
7limits.memory    700Mi  2Gi
8pods             1      2
9requests.cpu     300m   600m
10requests.memory  300Mi  800Mi

Pod再作成

クォータが足りるようになったので、Deploymentのマニフェストを反映してPodを再作成します。

1kubectl apply -f deployment.yaml

作成結果確認

再作成の結果を確認してみると、正常にPodが作成されているのが確認できます。

1❯ kubectl get deployment
2NAME              READY   UP-TO-DATE   AVAILABLE   AGE
3test-deployment   2/2     2            2           5m53s
4
5❯ kubectl get rs
6NAME                         DESIRED   CURRENT   READY   AGE
7test-deployment-8676fcf7bc   2         2         2       5m57s
8
9❯ kubectl get pod
10NAME                               READY   STATUS    RESTARTS   AGE
11test-deployment-8676fcf7bc-mlbv8   2/2     Running   0          64s
12test-deployment-8676fcf7bc-pzg86   2/2     Running   0          6m1s

最後にクォータを確認するとぎりぎりで作成できたのがわかります。

1❯ kubectl describe quota
2Name:            resource-quota
3Namespace:       demo
4Resource         Used    Hard
5--------         ----    ----
6limits.cpu       1400m   1500m
7limits.memory    1400Mi  2Gi
8pods             2       2
9requests.cpu     600m    600m
10requests.memory  600Mi   800Mi

まとめ

  • ResouceQuotaはNamespaceごとのリソースの制限をできる

参考

Support

\ この記事が役に立ったと思ったら、サポートお願いします! /

buy me a coffee
Share

Profile

author

Masa

都内のIT企業で働くエンジニア
自分が学んだことをブログでわかりやすく発信していきながらスキルアップを目指していきます!

buy me a coffee