LimitRange と ResourceQuota の違い

v1.37 時点(2026年10月26日 確認)

Kubernetes 基本仕様第30回 / 全45回 ・ 第6部 スケジューリングとリソース
目次

この記事では Namespace ごとに CPU とメモリの使い方を制限する LimitRange と ResourceQuota の違いを、図で説明します。LimitRange が Pod やコンテナの 1 つずつに決めることと、ResourceQuota が Namespace 全体の合計に決めることの違いがわかります。2 つがどの段階で働き、組み合わせるとどう動くのかもわかります。後半では kind のクラスタで、上限を超える Pod の作成が拒否される様子を試す手順を示します。

第29回で見た requests と limits の内容を前提にしています。まだの方は先にこちらをどうぞ。

基本仕様 ・ 第29回 requests と limits の仕組みコンテナが使う CPU とメモリの量を書く requests と limits の仕組みを図で説明します。requests で Pod を置くノードが選ばれること、limits を超えようとした CPU とメモリに起きること、QoS クラスの決まり方を押さえ、kind のクラスタで OOMKilled を観察する手順を紹介します。

以下の図は、1 つの Namespace の中で LimitRange と ResourceQuota が Pod に何を決めるかを表しています。

Pod の 1 つずつに効く LimitRange と、Namespace 全体の合計に効く ResourceQuota

LimitRange は Pod やコンテナを 1 つずつ見て、requests と limits の既定値を補ったり、範囲に収まっているかを確かめたりします。ResourceQuota は Namespace の中の Pod の requests と limits を足し合わせた合計や、オブジェクトの数に上限を設けます。図では 2 本の線をどちらも Pod の集まりに向けて描いていますが、見方が違います。LimitRange は Pod を 1 つずつ見て、ResourceQuota は Pod の値を足し合わせて見ます。

LimitRange と ResourceQuota とは

LimitRange は Namespace の中で、Pod や PersistentVolumeClaim などのオブジェクト 1 つずつに指定できる資源の割り当て(limits と requests)を制限する決まり です。PersistentVolumeClaim は、第27回で見たストレージを求めるリソースです。公式ドキュメントによると、LimitRange でできることは次の 4 つです。

  • Namespace の中の Pod やコンテナごとに、計算の資源(CPU やメモリ)の使用量の最小と最大を守らせる
  • Namespace の中の PersistentVolumeClaim ごとに、ストレージの requests の最小と最大を守らせる
  • Namespace の中で、ある資源の requests と limits の比率を守らせる
  • Namespace の中の計算の資源に既定の requests と limits を決め、コンテナに自動で入れる

参考:Limit Ranges | Kubernetes

計算の資源は第29回で見た、CPU やメモリのような資源です。第29回と同じく、この記事でも CPU やメモリを「資源」、Pod などを「リソース」と書き分けます。

ResourceQuota は、Namespace ごとに、資源の使用量の合計を制限する仕組み です。公式ドキュメントによると、ResourceQuota は Namespace の中に作れるオブジェクトの数を API の種類ごとに制限することもできます。Namespace の中のオブジェクトが使う資源の合計にも上限を設けられます。

参考:Resource Quotas | Kubernetes

Namespace は第3回で紹介した、1 つのクラスタの中でリソースをグループに分ける仕組みです。その仕組みは第37回で扱います。この回で知っておけばよいのは、LimitRange と ResourceQuota がどちらも Namespace に属するオブジェクトで、置いた Namespace の中だけに効くことです。公式ドキュメントの Namespace のページにも、Namespace はクラスタの資源を複数の利用者のあいだで分ける方法で、その手段が ResourceQuota だと書かれています。

参考:Namespaces | Kubernetes、Limit Ranges | Kubernetes、Resource Quotas | Kubernetes

2 つの違いを v1.37 時点の公式ドキュメントに沿って次の表にまとめます。どちらも apiVersion は v1 です。

項目LimitRangeResourceQuota
見るものPod、コンテナ、PersistentVolumeClaim の 1 つずつNamespace の中の合計
決められることrequests と limits の既定値、最小と最大、limits と requests の比率requests と limits の合計の上限、オブジェクトの数の上限など
守らせるアドミッションコントローラーLimitRanger(種類は変更と検証)ResourceQuota(種類は検証)
違反したときAPI へのリクエストが 403 Forbidden で拒否されるAPI へのリクエストが 403 Forbidden で拒否される

参考:Limit Ranges | Kubernetes、Resource Quotas | Kubernetes、Admission Control in Kubernetes | Kubernetes、LimitRange | Kubernetes API Reference、ResourceQuota | Kubernetes API Reference

アドミッションコントローラーと 403 Forbidden はこのあと「アドミッションで働く 2 つの仕組み」で説明します。

なぜ LimitRange と ResourceQuota が必要なのか

公式ドキュメントによると、既定では、Kubernetes のクラスタのコンテナは計算の資源を無制限に使って動きます。第29回で見たとおり、メモリの limits を書かず、Namespace に既定の limits も無いとき、コンテナはノードで使えるメモリをすべて使うことがあります。requests と limits は書くかどうかを選べる項目でした。

参考:Limit Ranges | Kubernetes、Assign Memory Resources to Containers and Pods | Kubernetes

ResourceQuota が答えるのは、クラスタを何人かで分け合うときの困りごとです。公式ドキュメントによると、決まった数のノードのクラスタを複数の利用者やチームで分け合うと、1 つのチームが公平な分より多くの資源を使ってしまうおそれがあります。ResourceQuota は、管理者がこのおそれに対処するための道具だと説明されています。

参考:Resource Quotas | Kubernetes

LimitRange が答えるのは、1 つの Namespace の中の困りごとです。公式ドキュメントによると、Namespace の中では、Pod はその Namespace の ResourceQuota が許す範囲で CPU とメモリを使えます。そのうえで、クラスタの運用者や Namespace の管理者は、1 つのオブジェクトが Namespace の中で使える資源をすべて独り占めしないようにしたいこともあります。そのために使うのが LimitRange です。

参考:Limit Ranges | Kubernetes

LimitRange と ResourceQuota の仕組み

アドミッションで働く 2 つの仕組み

第29回で触れたとおり、アドミッションは kube-apiserver がリクエストを受け付けて保存する前の段階で、第40回で詳しく扱います。公式ドキュメントによると、アドミッションコントローラーは、kube-apiserver へのリクエストを、認証と認可のあと、リソースを保存する前に受け止めるコードです。アドミッションは 2 つの段階で進みます。1 つ目の段階では内容を変えるもの(mutating)が、2 つ目の段階では内容を確かめるもの(validating)が動きます。両方の種類を兼ねるアドミッションコントローラーもあります。どちらかの段階で 1 つでもリクエストを拒否すると、リクエスト全体がすぐに拒否され、利用者にエラーが返ります。認証は相手が誰かを確かめること、認可はその相手に操作を許すかを決めることで、どちらも第40回で扱います。

参考:Admission Control in Kubernetes | Kubernetes、Admission Control in Kubernetes | Kubernetes

LimitRange と ResourceQuota の決まりを守らせるのは、名前の似たアドミッションコントローラーです。公式ドキュメントの説明を次の表にまとめます。

アドミッションコントローラー種類説明
LimitRanger変更と検証届いたリクエストが、Namespace の LimitRange に並んだ制約に違反していないかを確かめる。requests を書いていない Pod に既定の requests を入れるのにも使える
ResourceQuota検証届いたリクエストが、Namespace の ResourceQuota に並んだ制約に違反していないかを確かめる

参考:Admission Control in Kubernetes | Kubernetes、Admission Control in Kubernetes | Kubernetes

公式ドキュメントは LimitRange を使うなら LimitRanger のアドミッションコントローラーを必ず使わなければならない(MUST)と書いています。ResourceQuota も同じです。v1.37 の公式ドキュメントでは、LimitRanger と ResourceQuota は、どちらも既定で有効なアドミッションコントローラーの一覧に入っています。kind のクラスタも kube-apiserver の設定を変えていなければ、2 つとも有効なはずです。

参考:Admission Control in Kubernetes | Kubernetes

LimitRange について、公式ドキュメントは次の順番で働くと説明しています。

  1. 管理者が Namespace に LimitRange を作る
  2. 利用者がその Namespace に Pod や PersistentVolumeClaim などのオブジェクトを作る(作ろうとする)
  3. まず LimitRange のアドミッションコントローラーが、計算の資源の requests と limits を書いていないすべての Pod(とそのコンテナ)に、既定の requests と limits を入れる
  4. 次に、Namespace のどの LimitRange に書かれた最小、最大、比率も超えていないかを確かめる

LimitRange の制約に違反するオブジェクト(Pod か PersistentVolumeClaim)を作ったり更新したりしようとすると、API サーバーへのリクエストは HTTP の状態コード 403 Forbidden で失敗し、違反した制約を説明するメッセージが返ります。HTTP の状態コードは一般に、リクエストの結果を表す 3 桁の数で、403 Forbidden は「禁止」を表します。

参考:Limit Ranges | Kubernetes

ResourceQuota も公式ドキュメントでは次の順番で説明されています。チームごとに別の Namespace で作業し、クラスタの管理者は Namespace ごとに少なくとも 1 つの ResourceQuota を作ります。利用者が Namespace にリソースを作ると、ResourceQuota の仕組みが使用量を追いかけ、ResourceQuota に書いた上限(hard)を超えないようにします。リソースを作ったり更新したりすると上限を超える場合、コントロールプレーンはそのリクエストを 403 Forbidden で拒否します。エラーには違反することになった制約を説明するメッセージが入ります。

参考:Resource Quotas | Kubernetes

以下の図は、Pod を作るリクエストが kube-apiserver の中で LimitRange と ResourceQuota に確かめられ、保存されるか拒否されるまでの流れを表しています。

Pod を作るリクエストで LimitRange と ResourceQuota が働く段階

LimitRange の既定値は内容を変える段階で入ります。範囲と合計を確かめるのは、内容を確かめる段階です。どちらかの制約に違反すると、Pod は保存されず、作られません。図は 3 の段階の中での LimitRange と ResourceQuota の順番を表していません。この順番はこのメディアで確かめた範囲の公式ドキュメントには書かれていないからです。また、本文のとおり拒否はどちらの段階でも起こり得ますが、図はこの回で扱う検証の段階での拒否だけを描いています。

参考:Admission Control in Kubernetes | Kubernetes、Admission Control in Kubernetes | Kubernetes、Limit Ranges | Kubernetes

LimitRange:1 つずつの既定値と範囲

LimitRange の spec.limits には制限の項目(LimitRangeItem)を並べます。API リファレンスの説明を次の表にまとめます。

フィールド説明
type制限を当てるリソースの種類。公式ドキュメントの例では Container
defaultlimits を省いたときに使う、既定の limits の値(資源の名前ごと)
defaultRequestrequests を省いたときに使う、既定の requests の値(資源の名前ごと)
maxこの種類の使用量の最大(資源の名前ごと)
minこの種類の使用量の最小(資源の名前ごと)
maxLimitRequestRatio書いた場合、その資源の requests と limits はどちらも 0 でなく、limits を requests で割った値がこの値以下でなければならない。その資源のバーストの最大を表す

参考:LimitRange | Kubernetes API Reference、Limit Ranges | Kubernetes

API リファレンスは type に書ける値を並べていません。LimitRange の概念ページの冒頭は、コンテナのほかに、Pod ごとや PersistentVolumeClaim ごとにも制限できると説明しています。この回の手順では Container だけを使います。

参考:Limit Ranges | Kubernetes

バーストは第29回で見た、処理が一時的に増えることです。maxLimitRequestRatio は limits を requests の何倍まで大きくしてよいかを決める項目だと読めます。

既定値がどう入るかは、コンテナに何を書いたかで変わります。公式ドキュメントのメモリの例では、default を 512Mi、defaultRequest を 256Mi にした LimitRange のある Namespace で、次のようになっています。

コンテナの書き方requestslimits
requests も limits も書かないdefaultRequest の 256Midefault の 512Mi
limits だけ 1Gi と書くlimits と同じ 1Gi。defaultRequest の 256Mi は使われない書いた 1Gi
requests だけ 128Mi と書く書いた 128Midefault の 512Mi

参考:Configure Default Memory Requests and Limits for a Namespace | Kubernetes

defaultRequest が使われるのは、その資源の requests も limits も書いていないときです。公式ドキュメントのメモリと CPU の既定値のタスクのページでは、どちらも、その資源の requests と limits の両方を書いていないコンテナに既定値が入る、と説明しています。limits だけを書いたコンテナについては、どちらのページも、requests は limits と同じ値になり、既定の requests は使われていないことを示しています。

第29回で、limits だけを書くと requests に limits の値がコピーされると見ました(アドミッションで既定の requests が入る場合を除く)。この 2 つの例は LimitRange のある Namespace でも、limits を書いた資源には既定の requests が入らず、limits の値が requests に入ったものだと読めます。第29回の括弧書きの例外がどの仕組みを指すのかは、このメディアで確かめた範囲の公式ドキュメントには書かれていません。

参考:Configure Default Memory Requests and Limits for a Namespace | Kubernetes、Configure Default CPU Requests and Limits for a Namespace | Kubernetes、Configure Default Memory Requests and Limits for a Namespace | Kubernetes、Configure Default CPU Requests and Limits for a Namespace | Kubernetes、Resource Management for Pods and Containers | Kubernetes

LimitRange は 1 つの Namespace に 2 つ以上置くこともできますが、公式ドキュメントによると、そのときにどの既定値が入るかは決まっていません(not deterministic)。

参考:Limit Ranges | Kubernetes

既定値を書かずに、最小と最大だけを書いた LimitRange もあります。公式ドキュメントのメモリの例では、max を 1Gi、min を 500Mi にした LimitRange を作ると、書いていない既定値(default と defaultRequest)が自動で作られています。例ではどちらも max と同じ 1Gi でした。

参考:Configure Minimum and Maximum Memory Constraints for a Namespace | Kubernetes

この Namespace で範囲を外れた Pod を作ろうとしたときの、公式ドキュメントのエラーの例は次のとおりです。1 つ目はメモリの limits が 1.5Gi(1536Mi)のコンテナ、2 つ目はメモリの requests が 100Mi のコンテナです。

Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-2.yaml":
pods "constraints-mem-demo-2" is forbidden: maximum memory usage per Container is 1Gi, but limit is 1536Mi.
Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-3.yaml":
pods "constraints-mem-demo-3" is forbidden: minimum memory usage per Container is 500Mi, but request is 100Mi.

参考:Configure Minimum and Maximum Memory Constraints for a Namespace | Kubernetes、Configure Minimum and Maximum Memory Constraints for a Namespace | Kubernetes

どちらも forbidden で、Pod は作られていません。例のメッセージでは、最大と比べられているのは limits の値(limit is 1536Mi)、最小と比べられているのは requests の値(request is 100Mi)です。

LimitRange は、入れる既定値がマニフェストに書かれたほかの値と食い違わないかを確かめません。公式ドキュメントによると、LimitRange が入れる既定の limits が、利用者がマニフェストに書いた requests より小さくなることがあります。そうなると、最終的な Pod はスケジュールできない、と説明されています。公式ドキュメントの例では、CPU の default と defaultRequest を 500m、max を 1、min を 100m にした LimitRange のある Namespace で、CPU の requests だけを 700m と書いた Pod を作ろうとしています。そのときのエラーは次のようなものだと示されています。

Pod "example-conflict-with-limitrange-cpu" is invalid: spec.containers[0].resources.requests: Invalid value: "700m": must be less than or equal to cpu limit

参考:Limit Ranges | Kubernetes

既定の limits の 500m が入った結果、requests の 700m が limits を超えた、という意味のメッセージだと読めます。第29回で見たとおり、requests は limits を超えられません。このエラーはさきほどの最小と最大の例のような LimitRange の制約の違反(forbidden)ではなく、invalid として返っています。公式ドキュメントは同じ節で「最終的な Pod はスケジュールできない」と書く一方、例のメッセージ(Pod "..." is invalid)の形からは、作成の時点でエラーになっていて、この例に従えば、この場合は Pod が作られる前に止まると読めます。公式ドキュメントは requests と limits の両方を書けば、同じ LimitRange があっても新しい Pod は問題なくスケジュールされる、と説明しています。

参考:Limit Ranges | Kubernetes、Pod | Kubernetes API Reference

ResourceQuota:Namespace 全体の合計と数

ResourceQuota の spec.hard には資源の名前ごとに上限を書きます。API リファレンスによると、status.hard は守らせている上限、status.used は Namespace の中で観測した、その資源の今の使用量の合計です。表に出てくる「終わった状態」の Pod は、公式ドキュメントによると、.status.phase が Failed か Succeeded の Pod です。フェーズは第9回で扱いました。CPU とメモリについて、v1.37 時点の公式ドキュメントで spec.hard に書ける主な名前を次の表にまとめます。

名前説明
requests.cpu終わった状態ではないすべての Pod の、CPU の requests の合計の上限
requests.memory終わった状態ではないすべての Pod の、メモリの requests の合計の上限
limits.cpu終わった状態ではないすべての Pod の、CPU の limits の合計の上限
limits.memory終わった状態ではないすべての Pod の、メモリの limits の合計の上限
cpu、memoryrequests.cpu、requests.memory と同じ

参考:Resource Quotas | Kubernetes、Resource Quotas | Kubernetes、ResourceQuota | Kubernetes API Reference

オブジェクトの数にも上限を設けられます。公式ドキュメントによると、pods は Namespace の中に存在できる、終わった状態ではない Pod の数の上限です。ほかに、count/<resource>.<group>(コアではない API グループのリソース)や count/<resource>(コアの API グループのリソース)の形で、count/deployments.apps や count/configmaps のように、いろいろな種類の数に上限を設けられます。

参考:Resource Quotas | Kubernetes

ResourceQuota には scopes もあり、上限の対象にする Pod を絞れます。公式ドキュメントによると、ResourceQuota は列挙したスコープのすべてに当てはまるリソースの使用量だけを数えます。v1.37 時点では BestEffort(第29回の QoS クラス)や NotTerminating(.spec.activeDeadlineSeconds が設定されていない Pod に当てはまる)などのスコープがあります。Pod の activeDeadlineSeconds は第16回で触れた Pod ごとの制限時間です。この回の手順ではスコープを使いません。

参考:Resource Quotas | Kubernetes、ResourceQuota | Kubernetes API Reference

ResourceQuota はクラスタの容量とは関係なく決まります。公式ドキュメントによると、ResourceQuota は絶対的な量で書くので、クラスタにノードを足しても、各 Namespace が使える資源は自動では増えません。また、ResourceQuota はクラスタ全体の資源を分けるものですが、ノードについての制限は作りません。いくつもの Namespace の Pod が、同じノードで動くことがあります。

参考:Resource Quotas | Kubernetes

公式ドキュメントのタスクのページには ResourceQuota で上限を超えたときのエラーの例があります。requests.memory を 1Gi にした ResourceQuota のある Namespace で、すでにメモリの requests を 600Mi 使っているところに、メモリの requests が 700Mi の Pod を作ろうとした例です。

Error from server (Forbidden): error when creating "examples/admin/resource/quota-mem-cpu-pod-2.yaml":
pods "quota-mem-cpu-demo-2" is forbidden: exceeded quota: mem-cpu-demo,
requested: requests.memory=700Mi,used: requests.memory=600Mi, limited: requests.memory=1Gi

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes

公式ドキュメントによると、使用中のメモリの requests と、新しい Pod のメモリの requests を足すと、上限を超えます(600 MiB + 700 MiB > 1 GiB)。そのため 2 つ目の Pod は作られません。メッセージには超えた ResourceQuota の名前(mem-cpu-demo)、求めた量(requested)、使用中の量(used)、上限(limited)が並んでいます。

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes

2 つを組み合わせたとき

ResourceQuota で CPU やメモリに上限を設けると、その資源の値を書かない Pod の扱いに注意が要ります。公式ドキュメントの ResourceQuota のページは、次のように説明しています。

  • cpu と memory の資源について、ResourceQuota は Namespace のすべての(新しい)Pod に、その資源の limits を書かせる
  • Namespace で cpu か memory の ResourceQuota を守らせるなら、新しく渡すすべての Pod に、その資源の requests か limits のどちらかを書かなければならない(must)
  • 書かないと、コントロールプレーンはその Pod のアドミッションを拒否することがある(may)

1 つ目と 2 つ目のどちらの書き方でも、CPU やメモリを何も書かない Pod が拒否され得る点は同じです。どの値が要るかは、spec.hard に並べた名前によると考えられます。なお、1 つ目は limits、2 つ目は requests か limits と、求める値の書き方が違います。

参考:Resource Quotas | Kubernetes

上限の名前ごとに見ると、どの値が要るかがわかりやすくなります。公式ドキュメントのタスクのページでは、requests.cpu、requests.memory、limits.cpu、limits.memory の 4 つに上限を設けた ResourceQuota について、Namespace のすべての Pod で、各コンテナにメモリの requests と limits、CPU の requests と limits がなければならない、と説明しています。

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes

この例と上の表の名前から、requests.* に上限があれば requests が、limits.* に上限があれば limits が要ると読めます。この回の手順の ResourceQuota も、この 4 つに上限を設けます。第29回で見たとおり、limits だけを書けば requests にもその値が入るので、CPU とメモリの limits を書いたコンテナは 4 つの値がそろうと考えられます。LimitRange が無い Namespace で requests だけを書いたコンテナは、limits が無いので拒否されると考えられます。

参考:Resource Management for Pods and Containers | Kubernetes

そこで LimitRange の出番です。公式ドキュメントの ResourceQuota のページは、計算の資源を書かない Pod に既定値を強制するために LimitRange を定義できる、と案内しています。そうすれば利用者が書き忘れずに済む、という説明です。メモリの既定値のタスクのページにも、LimitRange を足すと、メモリの limits を書かないコンテナに既定の limits が入る、とあります。その結果、その Pod は、メモリの ResourceQuota がある Namespace でも動くことを許され得る、と書かれています。

参考:Resource Quotas | Kubernetes、Configure Default Memory Requests and Limits for a Namespace | Kubernetes

これはアドミッションの段階の順番から読める動きです。LimitRanger が既定値を入れるのは内容を変える段階で、ResourceQuota が確かめるのはそのあとの内容を確かめる段階です。そのため ResourceQuota が数えるのは、既定値が入ったあとの requests と limits だと考えられます。

Pod を直接作らずに Deployment(第12回)で作ったときは、拒否のされ方が違って見えます。公式ドキュメントによると、Pod はふつう直接作らず、Deployment のようなワークロードを管理するオブジェクトを作ります。使える資源より多くを使おうとする Deployment を作ると、Deployment(やほかのワークロードを管理するオブジェクト)の作成は成功します。ただし、Deployment が管理する Pod が、すべては作られないことがあります。そのときは kubectl describe などで Deployment の状態を確かめるよう案内されています。

参考:Resource Quotas | Kubernetes

第6回と第12回で見たとおり、Pod を作るよう kube-apiserver に頼むのは、ReplicaSet を受け持つ replicaset-controller です。この回のように CPU やメモリの上限だけを設けた ResourceQuota では、さきほどの表のとおり、合計を数える対象は Pod です。そのため、Deployment の中の Pod のひな形は数えられず、Deployment の作成は上限に触れないと考えられます。count/deployments.apps のような Deployment の数の上限がある場合は別で、Deployment の作成そのものが拒否され得ると考えられます。また、あとで引用する Deployment の status のメッセージは pods "..." is forbidden となっています。このことから、拒否されたのは replicaset-controller が Pod を作るリクエストだと読めます。

以下の図は、Deployment で作る Pod の数が ResourceQuota の上限を超えたときに、何が作られ、何が拒否されるかを表しています。

ResourceQuota の上限を超えた分の Pod だけが作られない Deployment

Deployment と ReplicaSet は作られ、上限に収まる分の Pod も作られます。上限を超える分の Pod の作成だけが拒否されます。図の赤い線は、上限を超える分の Pod を作るリクエストが拒否されたことを表していて、その分の Pod は作られていません。図では replicaset-controller と kube-apiserver を省き、ReplicaSet から線を引いています。

参考:Configure a Pod Quota for a Namespace | Kubernetes、Deployments | Kubernetes

公式ドキュメントの Deployment のページは、Deployment が新しい ReplicaSet を展開しきれずに止まってしまう原因の例として、ResourceQuota が足りないこと(Insufficient quota)と LimitRange(Limit ranges)を挙げています。ResourceQuota が足りない例では、kubectl describe の Deployment の表示に次の部分が出る、と示されています。

<...>
Conditions:
  Type            Status  Reason
  ----            ------  ------
  Available       True    MinimumReplicasAvailable
  Progressing     True    ReplicaSetUpdated
  ReplicaFailure  True    FailedCreate
<...>

参考:Deployments | Kubernetes

同じページの例では kubectl get deployment nginx-deployment -o yaml で表示した Deployment の status のうち、type: ReplicaFailure の項目は次のとおりです(ほかの項目は省きました)。

  - lastTransitionTime: 2016-10-04T12:25:39Z
    lastUpdateTime: 2016-10-04T12:25:39Z
    message: 'Error creating: pods "nginx-deployment-4262182780-" is forbidden: exceeded quota:
      object-counts, requested: pods=1, used: pods=3, limited: pods=2'
    reason: FailedCreate
    status: "True"
    type: ReplicaFailure

参考:Deployments | Kubernetes

ReplicaFailure の FailedCreate は Pod を作れなかったことを表すと読めます。メッセージはさきほどの Pod を直接作ったときのエラーと同じ形で、Pod の数の上限(pods)を超えたことがわかります。公式ドキュメントは、ResourceQuota が足りないときは、Deployment の Pod の数を減らすか、ほかに動かしているコントローラーの Pod の数を減らすか、Namespace の ResourceQuota を増やせば対処できると説明しています。上限を満たして展開が終わると、Deployment の状態は成功を表す状態(status: "True" と reason: NewReplicaSetAvailable)に変わります。同じページによると、これは第12回で見た Progressing の状態(Condition)で、展開が終わったときに deployment-controller が設定するものです。

参考:Deployments | Kubernetes、Deployments | Kubernetes

第11回で引用した公式ドキュメントの例では、ReplicaSet が Pod を作ると、ReplicaSet の Events: に replicaset-controller の SuccessfulCreate が記録されていました。作成が拒否されたときも、ReplicaSet のイベントに作れなかったことが記録されると考えられます。ただし、そのときのイベントの例はこのメディアで確かめた範囲の公式ドキュメントにはありません。

参考:ReplicaSet | Kubernetes

作成済みのオブジェクトには遡って効かない

LimitRange も ResourceQuota も、確かめるのはリクエストが届いたときです。公式ドキュメントは、あとから作ったり変えたりしても、すでにあるオブジェクトには影響しないと説明しています。公式ドキュメントの言い方を次の表にまとめます。

対象公式ドキュメントの説明
LimitRangeLimitRange による確認は Pod のアドミッションの段階だけで起き、動いている Pod には起きない。LimitRange を足したり変えたりしても、Namespace にすでにある Pod はそのまま
LimitRange の最小と最大Pod を作ったときか更新したときだけ守らせる。LimitRange を変えても、前に作った Pod には影響しない
ResourceQuota資源の取り合いも ResourceQuota の変更も、すでに作られたリソースには影響しない

参考:Limit Ranges | Kubernetes、Configure Minimum and Maximum Memory Constraints for a Namespace | Kubernetes、Resource Quotas | Kubernetes

たとえば、ResourceQuota の上限を今の使用量より低く変えても、公式ドキュメントのとおり、すでに作られた Pod には影響しません。そのあとに作る Pod が、上限を超えるとして拒否されるはずです。

参考:Resource Quotas | Kubernetes

手元で試す

ここまでの内容を手元の kind のクラスタで試す手順を示します。公式ドキュメントのタスクのページの例をもとに、Namespace に ResourceQuota を置き、上限を超える Pod の作成が拒否されることを確かめます。続けて LimitRange を足し、既定値で Pod が受け付けられること、LimitRange の最大を超える Pod が拒否されること、Deployment で作ると上限を超えた分の Pod だけが作られないことを確かめます。

コマンドは macOS や Linux のシェル(bash や zsh)で実行する前提で書いています。Windows では WSL(Windows の中で Linux を動かす仕組み)などを使ってください。試す環境は次のとおりです。

項目内容
kindv0.33.0
Kubernetesv1.37.0(kind v0.33.0 の既定のノードイメージ)
ノード構成シングルノード(クラスタ名 kind):コントロールプレーン 1
必要なものDocker、kubectl(v1.36〜v1.38)、テキストエディタ、端末(ターミナル)2 つ

参考:Release v0.33.0 · kubernetes-sigs/kind、Version Skew Policy | Kubernetes

この回では第29回と同じく、シングルノードのクラスタを使います。LimitRange と ResourceQuota が確かめるのは kube-apiserver に届いたリクエストで、ノードが 1 つでも確かめられるからです。kind でクラスタを作る手順は、以下の記事で解説しています。

基本仕様 ・ 第2回 kind で検証用のクラスタを作るDocker のコンテナをノードにして、手元のマシンに Kubernetes のクラスタを作るツール kind の仕組みを図で説明します。kind create cluster で何が起きるかを押さえ、シングルノードとマルチノードのクラスタを作って、ノードの正体が Docker のコンテナであることを確かめる手順を紹介します。

シングルノードのクラスタを用意する

まず、前の回のクラスタが残っていないかを確かめます。

console
$ kind get clusters

kind が表示されたら、作り直さずにそのまま使えるので、クラスタを作る次のコマンドは飛ばします。表示されなければ、クラスタを作ってから、もう一度一覧します。前の回までの multi-node が表示されても、この回では使いません。手元のマシンの資源(メモリなど)に余裕がなければ、kind delete cluster --name multi-node で消してから進めてください。

console
$ kind create cluster
$ kind get clusters

kind get clusters に kind が表示されれば、クラスタができています。第3回で決めたとおり、ここからのコマンドには --context kind-kind を付けて、操作するクラスタをはっきりさせます。

参考:Quick Start | kind

続けて、ノードを一覧します。

console
$ kubectl get nodes --context kind-kind

ノードが 1 つ表示され、STATUS 列が Ready になっていれば準備ができています。Ready になっていなければ、少し待ってからもう一度実行します。

参考:kubectl get | Kubernetes、Node Status | Kubernetes

試すための Namespace を作る

この回では公式ドキュメントのタスクのページと同じく、試すための Namespace を作ります。公式ドキュメントは作ったリソースをクラスタのほかの部分から切り離すために Namespace を作る、と説明しています。ResourceQuota と LimitRange は置いた Namespace だけに効くので、default の Namespace を使わずに済みます。Namespace の名前は quota-demo にします。公式ドキュメントによると、Namespace の名前は DNS ラベル(第8回で見た、63 文字以内で小文字の英数字と - だけを使うなどの名前の決まり)の形でなければなりません。

console
$ kubectl create namespace quota-demo --context kind-kind

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes、Share a Cluster with Namespaces | Kubernetes

namespace/quota-demo が作られたことを知らせる 1 行が出るはずです。続けて、この Namespace に LimitRange と ResourceQuota がまだ無いことを確かめます。kubectl get では種類をカンマで区切って並べると、まとめて一覧できます。-n は第4回で使った、Namespace を指定するオプションです。

console
$ kubectl get limitrange,resourcequota -n quota-demo --context kind-kind

参考:kubectl get | Kubernetes

作ったばかりの Namespace なので、見つからないことを知らせる 1 行が出るはずです。

Pod を監視する

ここからは端末を 2 つ使います。第29回と同じく、1 つ目の端末で変化を追い続け、2 つ目の端末でマニフェストを渡したり、状態を確かめたりします。この回で 1 つ目の端末が追うのは、quota-demo の Namespace の Pod です。2 つ目の端末を開いたら、cd でマニフェストを保存するディレクトリに移動しておきます。

1 つ目の端末で、Pod を監視します。この監視は片付けの前まで止めずに続けます。

console
$ kubectl get pods -n quota-demo --watch --context kind-kind

参考:kubectl get | Kubernetes

Pod がまだ無いので、見つからないことを知らせる 1 行が出たあと、止まったように見えると考えられます。この回では、作成が拒否された Pod はこの端末に現れないことも確かめます。

ResourceQuota を作る

以下は Namespace の Pod の CPU の requests の合計を 1 CPU、メモリの requests の合計を 1GiB、CPU の limits の合計を 2 CPU、メモリの limits の合計を 2GiB までにする ResourceQuota のマニフェストです。公式ドキュメントのタスクのページの例と同じものです。quota-mem-cpu.yaml という名前で保存します。

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-demo
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes

2 つ目の端末で、マニフェストを渡します。マニフェストに metadata.namespace を書いていないので、-n quota-demo で Namespace を指定します。

console
$ kubectl apply -f quota-mem-cpu.yaml -n quota-demo --context kind-kind

resourcequota/mem-cpu-demo が作られたことを知らせる 1 行が出るはずです。公式ドキュメントによると、この ResourceQuota を置いた Namespace には次の制約がかかります。

  • 各 Pod の各コンテナに、メモリの requests と limits、CPU の requests と limits がなければならない
  • すべての Pod のメモリの requests の合計は 1GiB、limits の合計は 2GiB を超えてはならない
  • すべての Pod の CPU の requests の合計は 1 CPU、limits の合計は 2 CPU を超えてはならない

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes

上限に収まる Pod を作る

以下は CPU の requests を 400m、limits を 800m、メモリの requests を 600Mi、limits を 800Mi にしたコンテナの Pod のマニフェストです。公式ドキュメントのタスクのページの例と同じものです。quota-mem-cpu-pod.yaml という名前で保存します。

yaml
apiVersion: v1
kind: Pod
metadata:
  name: quota-mem-cpu-demo
spec:
  containers:
  - name: quota-mem-cpu-demo-ctr
    image: nginx
    resources:
      limits:
        memory: "800Mi"
        cpu: "800m"
      requests:
        memory: "600Mi"
        cpu: "400m"

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes

2 つ目の端末で、マニフェストを渡します。

console
$ kubectl apply -f quota-mem-cpu-pod.yaml -n quota-demo --context kind-kind

pod/quota-mem-cpu-demo が作られたことを知らせる 1 行が出るはずです。1 つ目の端末には quota-mem-cpu-demo の行が書き足されていき、STATUS 列は Pending、ContainerCreating を経て Running になるはずです。

続けて、ResourceQuota の使用量を確かめます。

console
$ kubectl get resourcequota mem-cpu-demo -n quota-demo -o yaml --context kind-kind

公式ドキュメントの例では、表示のうち status の部分は次のとおりです。

status:
  hard:
    limits.cpu: "2"
    limits.memory: 2Gi
    requests.cpu: "1"
    requests.memory: 1Gi
  used:
    limits.cpu: 800m
    limits.memory: 800Mi
    requests.cpu: 400m
    requests.memory: 600Mi

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes

hard は上限、used は今の使用量の合計です。公式ドキュメントは、Pod のメモリと CPU の requests と limits が上限を超えていないことがわかる、と説明しています。手元の表示はこの部分のほかに metadata などの行も並びます。名前と値が例と同じなので、status の部分は例と同じになるはずです。

合計の上限を超える Pod を作る

以下はメモリの requests を 700Mi にしたコンテナの Pod のマニフェストです。公式ドキュメントのタスクのページの例と同じものです。quota-mem-cpu-pod-2.yaml という名前で保存します。

yaml
apiVersion: v1
kind: Pod
metadata:
  name: quota-mem-cpu-demo-2
spec:
  containers:
  - name: quota-mem-cpu-demo-2-ctr
    image: redis
    resources:
      limits:
        memory: "1Gi"
        cpu: "800m"
      requests:
        memory: "700Mi"
        cpu: "400m"

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes

使用中のメモリの requests の 600Mi と、この Pod の 700Mi を足すと、上限の 1Gi を超えます。2 つ目の端末で、マニフェストを渡します。

console
$ kubectl apply -f quota-mem-cpu-pod-2.yaml -n quota-demo --context kind-kind

作成は拒否されるはずです。公式ドキュメントの例では、次のエラーが出ています(「仕組み」の節で引用したものと同じです)。

Error from server (Forbidden): error when creating "examples/admin/resource/quota-mem-cpu-pod-2.yaml":
pods "quota-mem-cpu-demo-2" is forbidden: exceeded quota: mem-cpu-demo,
requested: requests.memory=700Mi,used: requests.memory=600Mi, limited: requests.memory=1Gi

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes

メッセージに forbidden: exceeded quota: mem-cpu-demo と requests.memory が含まれていれば、ResourceQuota のメモリの requests の上限で拒否されています。公式ドキュメントは kubectl apply -f https://k8s.io/examples/admin/resource/quota-mem-cpu-pod-2.yaml --namespace=quota-mem-cpu-example のように、マニフェストを URL で渡していて、例の error when creating のあとは examples/admin/resource/quota-mem-cpu-pod-2.yaml になっています。手元ではファイル名の quota-mem-cpu-pod-2.yaml になると考えられます。Pod と ResourceQuota の名前、値は例と同じなので、メッセージのほかの部分は例と同じになると考えられます。例では 1 つのメッセージが 3 行に分かれていますが、手元では折り返し方が違うことがあります。1 つ目の端末には quota-mem-cpu-demo-2 の行は現れないはずです。Pod が作られていないからです。

requests と limits を書かない Pod を作る

以下は requests も limits も書かないコンテナの Pod のマニフェストです。公式ドキュメントのメモリの既定値のタスクのページの例をもとに、名前だけを変えました。no-resources-demo.yaml という名前で保存します。

yaml
apiVersion: v1
kind: Pod
metadata:
  name: no-resources-demo
spec:
  containers:
  - name: no-resources-demo-ctr
    image: nginx

参考:Configure Default Memory Requests and Limits for a Namespace | Kubernetes

2 つ目の端末で、マニフェストを渡します。

console
$ kubectl apply -f no-resources-demo.yaml -n quota-demo --context kind-kind

作成は拒否されるはずです。この Namespace の ResourceQuota について、タスクのページは各コンテナに 4 つの値がなければならないとしています。このコンテナには 1 つもありません。拒否されると、Error from server (Forbidden) で始まり、forbidden と、違反することになった制約の説明を含むメッセージが出るはずです。このときのメッセージの例はこのメディアで確かめた範囲の公式ドキュメントにはありません。1 つ目の端末に、この Pod の行が現れないことも確かめます。

参考:Resource Quotas | Kubernetes、Configure Memory and CPU Quotas for a Namespace | Kubernetes

LimitRange を作る

以下はコンテナに既定の requests と limits を入れ、メモリの limits の最大を 512Mi にする LimitRange のマニフェストです。既定の requests は CPU 100m とメモリ 128Mi、既定の limits は CPU 200m とメモリ 256Mi です。値はこの回で決めたもので、公式ドキュメントの例ではありません。default-limits.yaml という名前で保存します。

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
spec:
  limits:
  - type: Container
    default:
      cpu: 200m
      memory: 256Mi
    defaultRequest:
      cpu: 100m
      memory: 128Mi
    max:
      memory: 512Mi

参考:LimitRange | Kubernetes API Reference、Limit Ranges | Kubernetes

既定の limits のメモリ(256Mi)は最大(512Mi)より小さくしてあります。2 つ目の端末で、マニフェストを渡します。

console
$ kubectl apply -f default-limits.yaml -n quota-demo --context kind-kind

limitrange/default-limits が作られたことを知らせる 1 行が出るはずです。

ここで、すでに動いている quota-mem-cpu-demo を確かめます。この Pod のメモリの limits は 800Mi で、いま作った LimitRange の最大(512Mi)を超えています。

console
$ kubectl get pod quota-mem-cpu-demo -n quota-demo --context kind-kind

STATUS 列は Running のままのはずです。1 つ目の端末でも、quota-mem-cpu-demo の行に変化は無いはずです。公式ドキュメントのとおり、LimitRange を足しても、Namespace にすでにある Pod はそのままだからです。

参考:Limit Ranges | Kubernetes

既定値で補われた Pod を作る

さきほど拒否された no-resources-demo.yaml を、2 つ目の端末でもう一度渡します。マニフェストは変えません。

console
$ kubectl apply -f no-resources-demo.yaml -n quota-demo --context kind-kind

今度は pod/no-resources-demo が作られたことを知らせる 1 行が出るはずです。1 つ目の端末には no-resources-demo の行が書き足されていき、Running になるはずです。LimitRange の既定値が入ったので、ResourceQuota が求める 4 つの値がそろうからです。

参考:Configure Default Memory Requests and Limits for a Namespace | Kubernetes

入った値を確かめます。spec.containers の最初の項目(この Pod の唯一のコンテナ)の resources を取り出します。

console
$ kubectl get pod no-resources-demo -n quota-demo -o jsonpath='{.spec.containers[0].resources}{"\n"}' --context kind-kind

参考:JSONPath Support | Kubernetes

JSON の形で requests と limits が表示されるはずです。マニフェストには書いていないのに、requests には cpu の 100m と memory の 128Mi、limits には cpu の 200m と memory の 256Mi が入っているはずです。公式ドキュメントの例と同じく、requests も limits も書かないコンテナには、defaultRequest と default の値が入るからです。

参考:Configure Default Memory Requests and Limits for a Namespace | Kubernetes

LimitRange の最大を超える Pod を作る

以下はメモリの requests を 128Mi、limits を 600Mi にしたコンテナの Pod のマニフェストです。limits の 600Mi は LimitRange の最大(512Mi)を超えます。CPU は書いていないので、LimitRange の既定値が入るはずです。over-max-demo.yaml という名前で保存します。

yaml
apiVersion: v1
kind: Pod
metadata:
  name: over-max-demo
spec:
  containers:
  - name: over-max-demo-ctr
    image: nginx
    resources:
      limits:
        memory: "600Mi"
      requests:
        memory: "128Mi"

この Pod は ResourceQuota の上限には収まるようにしてあります。この Pod が加わった場合の合計を足し算すると、次の表のとおりです。拒否された quota-mem-cpu-demo-2 は作られていないので、数えません。

Podrequests(CPU/メモリ)limits(CPU/メモリ)
quota-mem-cpu-demo400m/600Mi800m/800Mi
quota-mem-cpu-demo-2(拒否済み)数えない数えない
no-resources-demo(既定値)100m/128Mi200m/256Mi
over-max-demo(CPU は既定値)100m/128Mi200m/600Mi
合計600m/856Mi1200m/1656Mi
上限1(1000m)/1Gi(1024Mi)2(2000m)/2Gi(2048Mi)

どの合計も上限より小さいので、拒否されるとすれば LimitRange の最大によるものだと考えられます。

参考:Resource Quotas | Kubernetes

2 つ目の端末で、マニフェストを渡します。

console
$ kubectl apply -f over-max-demo.yaml -n quota-demo --context kind-kind

作成は拒否されるはずです。公式ドキュメントの例(最大を 1Gi にした LimitRange で、メモリの limits が 1.5Gi の Pod を作ろうとしたもの)では、次のエラーが出ています。

Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-2.yaml":
pods "constraints-mem-demo-2" is forbidden: maximum memory usage per Container is 1Gi, but limit is 1536Mi.

参考:Configure Minimum and Maximum Memory Constraints for a Namespace | Kubernetes

手元のメッセージは、例と次の点が違うと考えられます。

違い手元の表示
ファイル名error when creating のあとは over-max-demo.yaml
Pod の名前constraints-mem-demo-2 ではなく over-max-demo
最大と limits の値1Gi と 1536Mi ではなく、この回の LimitRange の 512Mi と、この Pod の 600Mi

1 つ目の端末には、over-max-demo の行は現れないはずです。

Deployment で上限を超える数の Pod を作る

以下は requests と limits を書かないコンテナの Pod を 3 つ保つ Deployment のマニフェストです。公式ドキュメントの Pod の数の上限のタスクのページの Deployment をもとに、名前とラベルをこの回のものにしました。quota-deploy-demo.yaml という名前で保存します。

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: quota-deploy-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: quota-deploy-demo
  template:
    metadata:
      labels:
        app: quota-deploy-demo
    spec:
      containers:
      - name: nginx
        image: nginx

参考:Configure a Pod Quota for a Namespace | Kubernetes、Deployments | Kubernetes

Pod の requests と limits には、LimitRange の既定値が入るはずです。足し算すると、合計は次の表のとおりです。拒否された quota-mem-cpu-demo-2 と over-max-demo は作られていないので、数えません。

Podrequests(CPU/メモリ)limits(CPU/メモリ)
quota-mem-cpu-demo400m/600Mi800m/800Mi
no-resources-demo(既定値)100m/128Mi200m/256Mi
Deployment の 1 つ目の Pod(既定値)100m/128Mi200m/256Mi
Deployment の 2 つ目の Pod(既定値)100m/128Mi200m/256Mi
2 つ目までの合計700m/984Mi1400m/1568Mi
3 つ目を足した場合の合計800m/1112Mi1600m/1824Mi
上限1(1000m)/1Gi(1024Mi)2(2000m)/2Gi(2048Mi)

3 つ目を足すと、メモリの requests の合計(1112Mi)だけが上限の 1Gi(1024Mi)を超えます。そのため、作られる Pod は 2 つで、3 つ目の作成がメモリの requests の上限で拒否されると考えられます。

参考:Resource Quotas | Kubernetes

2 つ目の端末で、マニフェストを渡します。

console
$ kubectl apply -f quota-deploy-demo.yaml -n quota-demo --context kind-kind

deployment.apps/quota-deploy-demo が作られたことを知らせる 1 行が出るはずです。公式ドキュメントのとおり、使える資源より多くを使おうとする Deployment でも、作成そのものは成功するからです。1 つ目の端末には、quota-deploy-demo- で始まる名前の Pod の行が書き足されていきます。上の計算どおりなら、現れる Pod は 2 つのはずです。

参考:Resource Quotas | Kubernetes

続けて、Deployment を一覧します。

console
$ kubectl get deployment quota-deploy-demo -n quota-demo --context kind-kind

第6回で見たとおり、Deployment の READY 列は「使える数/望ましい数」の形です。上の計算どおりなら、2/3 のまま 3/3 にならないはずです。公式ドキュメントのタスクのページでも、Pod の数の上限を 2 にした Namespace で、replicas: 3 の Deployment を作ると、Pod は 2 つしか作られない例が示されています。

参考:Deployments | Kubernetes、Configure a Pod Quota for a Namespace | Kubernetes

Deployment を詳しく表示して、状態(Conditions)を確かめます。

console
$ kubectl describe deployment quota-deploy-demo -n quota-demo --context kind-kind

Conditions: の欄に、「仕組み」の節で引用した公式ドキュメントの例と同じく、ReplicaFailure が True、理由が FailedCreate の行があるはずです。Available と Progressing の行の値は例と違うことがあると考えられます。

参考:Deployments | Kubernetes、kubectl describe | Kubernetes

拒否の理由は Deployment の status に書かれた ReplicaFailure のメッセージで読めます。

console
$ kubectl get deployment quota-deploy-demo -n quota-demo -o yaml --context kind-kind

status.conditions の type: ReplicaFailure の項目の message に、is forbidden: exceeded quota: を含むメッセージがあるはずです。そこに mem-cpu-demo の名前と requests.memory の値が並んでいれば、上の表のとおり、メモリの requests の上限で拒否されたと読めます。公式ドキュメントの例はどちらも Pod の数の上限(pods)を超えたものでした。メッセージの書き出しは、Deployment のページでは Error creating:、Pod の数の上限のタスクのページでは unable to create pods: です。手元でどちらになるかは、公式ドキュメントからはわかりません。

参考:Deployments | Kubernetes、Configure a Pod Quota for a Namespace | Kubernetes

最後に、Deployment が作った ReplicaSet を詳しく表示します。この Namespace にある ReplicaSet はこの 1 つだけなので、名前を指定しません。

console
$ kubectl describe replicaset -n quota-demo --context kind-kind

Events: の欄には作れた Pod について replicaset-controller の SuccessfulCreate の行が並ぶと考えられます(第11回)。作成が拒否された Pod については、Type 列が Warning で、exceeded quota を含むメッセージの行が並ぶと考えられます。API リファレンスによると、イベントの種類(type)は Normal か Warning です(今後、種類が増えることもあります)。Warning は名前のとおり、問題を知らせるほうの種類だと考えられます。ただし、拒否されたときの表示の例は、このメディアで確かめた範囲の公式ドキュメントにはありません。

参考:ReplicaSet | Kubernetes、Event | Kubernetes API Reference

片付け

1 つ目の端末で Ctrl+C を押して、Pod の監視を止めます。

2 つ目の端末で、Namespace ごと削除します。公式ドキュメントのタスクのページも、片付けでは Namespace を削除しています。公式ドキュメントによると、Namespace を削除すると、その Namespace の中のものがすべて削除されます。この回で作った Pod、Deployment、ReplicaSet、LimitRange、ResourceQuota はすべて quota-demo の中にあります。

console
$ kubectl delete namespace quota-demo --context kind-kind

参考:Configure Memory and CPU Quotas for a Namespace | Kubernetes、Share a Cluster with Namespaces | Kubernetes

公式ドキュメントによると、この削除は非同期で進むので、しばらくのあいだ Namespace は Terminating の状態で見えます。少し待ってから、残っていないかを確かめます。

console
$ kubectl get namespace quota-demo --context kind-kind

STATUS 列が Terminating で表示されていたら、少し待ってからもう一度実行します。見つからないことを知らせる 1 行が出れば、削除できています。

参考:Share a Cluster with Namespaces | Kubernetes

最後に、クラスタを削除し、消えたことを確かめます。

console
$ kind delete cluster
$ kind get clusters

kind delete cluster は存在しないクラスタを指定してもエラーを返しません。kind get clusters に kind が表示されなくなったことを確かめます。kubeconfig に kind-kind のコンテキストが残っていたら、第3回の片付けと同じく kubectl config delete-context kind-kind で消します。

参考:Quick Start | kind、kubectl config | Kubernetes

注意点

LimitRange と ResourceQuota でつまずきやすい点と、バージョンで変わる点を、次の表にまとめます。

項目内容
作成済みのオブジェクトには効かないLimitRange も ResourceQuota も、足したり変えたりしても、すでにある Pod などには影響しない
ResourceQuota で CPU やメモリに上限を設けると、書かない Pod は拒否され得るどの値が要るかは spec.hard に並べた名前によると読める(タスクのページの 4 つの名前の例では 4 つとも要る)。LimitRange の既定値で補える
Pod の資源(CPU やメモリ)の上限を超える Deployment でも、作成は成功する作られない Pod があるかは、Deployment の状態(ReplicaFailure)で確かめる
LimitRange は、入れる既定値がマニフェストに書かれたほかの値と食い違わないかを確かめない既定の limits が、書いた requests より小さくなることがある
Namespace に LimitRange が 2 つ以上あると、既定値が決まらないどの既定値が使われるかは決まっていない(not deterministic)
ResourceQuota はノードを足しても増えない絶対的な量で書くので、クラスタの容量とは関係がない
ResourceQuota の削除や更新の権限公式ドキュメントは、守らせ続けるために、クラスタの管理者がこの権限も制限するべき(should)としている
動かしたままの変更(第29回)にも、LimitRange の最小と最大も、ResourceQuota の上限も効く公式のタスクのページによると、違反する変更は拒否される。そのとき資源は前の値のまま
2 つのアドミッションコントローラーは v1.37 では既定で有効既定で有効な一覧に入っている。ResourceQuota のページは、多くのディストリビューションで既定で有効で、--enable-admission-plugins に ResourceQuota が含まれていると有効になる、と説明している

参考:Limit Ranges | Kubernetes、Resource Quotas | Kubernetes、Resource Quotas | Kubernetes、Configure Minimum and Maximum Memory Constraints for a Namespace | Kubernetes、Configure Minimum and Maximum CPU Constraints for a Namespace | Kubernetes、Configure Memory and CPU Quotas for a Namespace | Kubernetes、Admission Control in Kubernetes | Kubernetes、Resource Quotas | Kubernetes

この回の kind のクラスタでは、v1.37 で既定で有効な一覧に入っていることから、2 つのアドミッションコントローラーを有効にするために何かをする必要はないと考えられます。

ResourceQuota の削除や更新の権限について、公式ドキュメントは例として ValidatingAdmissionPolicy を定義する方法を挙げています。ValidatingAdmissionPolicy は v1.37 で既定で有効なアドミッションコントローラーの一覧にも名前があります。公式ドキュメントのアドミッションのページでは、独自の処理を動かすための拡張の仕組みの 1 つとして挙がっています。アドミッションの仕組みは第40回で扱います。第29回の補足でも、Namespace への書き込みの権限をすべて与えると、その人は ResourceQuota も消せる、という注意を引用しました。権限の仕組み(RBAC)は第38回で扱います。

参考:Resource Quotas | Kubernetes、Admission Control in Kubernetes | Kubernetes、Resource Management for Pods and Containers | Kubernetes

関連記事

この回で使った Namespace について、分けられるリソースと分けられないリソースは、以下の記事で解説しています。

基本仕様 ・ 第37回 Namespace で分けられるもの、分けられないもの1 つのクラスタの中でリソースをグループに分ける Namespace の仕組みを図で説明します。名前の範囲になること、Namespace に属さないクラスタ全体のリソース、既定では Namespace をまたいで届く通信、Namespace を消すと中身も消える流れを押さえ、kind のクラスタで確かめる手順を紹介します。

LimitRange と ResourceQuota が働くアドミッションを含め、kube-apiserver がリクエストを処理する流れについては、以下の記事で解説しています。

基本仕様 ・ 第40回 kube-apiserver がリクエストを処理する流れkube-apiserver が API のリクエストを受け取ってから etcd に保存するまでの、認証・認可・アドミッションの流れを図で説明します。各段階で誰が何を判断し、どの段階でどう断られるかを押さえ、リクエストが段階ごとに拒否される様子を kind のクラスタで確かめる手順を紹介します。

次の回では Pod を置くノードを選ぶ nodeSelector と Node Affinity を扱います。

基本仕様 ・ 第31回 nodeSelector と Node Affinity の違いPod を置くノードをノードのラベルで選ぶ nodeSelector と Node Affinity の違いを図で説明します。required と preferred、演算子、IgnoredDuringExecution の意味、nodeName との違いを押さえ、kind のマルチノードのクラスタでワーカーにラベルを付けて Pod を寄せる・避ける手順を紹介します。

Kubernetes 基本仕様の目次へ