【Kubernetes】ResourceQuotaでリソース制限
はじめに
Kubernetesのリソース制限ができるResourceQuotaについてざっくり解説しながら、実際に使っていきたいと思います。
ResourceQuotaとは
ResourceQuotaとは、Namespaceごとのリソース量を制限することができるオブジェクトです。
コンピュータリソースからPodの数などのオブジェクト数までの割り当て(クォータ)を決めることができます。
現状はNamespaceごとにResourceQuotaを作成することを強制することはできませんが、将来的に設定できるように計画しているみたいです。(公式ドキュメントより)
クォータ
設定できるクォータについてざっくり紹介します。
コンピュートリソース
リソース名 | 説明 |
---|---|
limits.cpu | PodのCPUのlimitの合計 |
limits.memory | Podの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.storage | PVCのストレージの合計 |
persistentvolumeclaims | PVCの総数 |
<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の合計 |
オブジェクト数
リソース名 | 説明 |
---|---|
configmaps | ConfigMapの総数 |
persistentvolumeclaims | PersistentVolumeClaimの総数 |
pods | Podの総数 |
replicationcontrollers | ReplicationControlerの総数 |
resourcequotas | ResourceQuotaの総数 |
services | Serviceの総数 |
services.loadbalancers | LoadBalancerのServiceの総数 |
services.nodeports | NodePortのServiceの総数 |
secrets | Secretの総数 |
使ってみる
ここからは実際にResourceQuotaを実際に使ってみたいと思います。
Namespace作成
まずはリソース制限をするNamespaceを作成します。
1kubectl create ns demo
kubens
コマンドでNamespaceを切り替えます。
1kubens demo
kubens
コマンドのインストールや使い方については下記を参考にしてください。
【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ごとのリソースの制限をできる