CPUは空いて見えるのに、なぜ入れないのか
目標
リソースの要求によるスケジューリングの失敗と、クォータによるAPIの作成拒否を、実際のk3sで区別します。
なぜ重要なのか
現在の使用率が低くても、宣言した要求はノードに合わないことがあります。受け入れ(admission)が許可されても、実際の起動は別の段階です。 ポリシーを削除したり、他人のPodを回収したりして通すのではなく、デフォルト値・合計・身元・実際のレスポンスを比較します。 実験は個人用VM上の小さな待機アプリで、CPUの飽和・throttling・OOMの負荷実験ではありません。本番のkubeconfigや実際のシークレットを持ち込まないでください。 50分のラボです。必要なら期限が切れる前に延長し、セッションの終了時にVMとファイルが回収される点を覚えておいてください。
用意されている環境とヘルパー
kcna-capacityは実験用の空間、kcna-capacity-control/controlは正常な比較群です。どちらの空間も、restricted/v1.36のポリシーです。 アプリは、digest固定・Always pull・non-root・cap drop ALL・RuntimeDefault・読み取り専用ルート・ServiceAccountトークンの非マウントです。 ノードと比較群を変更しないでください。受講生のすべてのファイルは、/root/kcna-resourcesの下に置きます。 入力ファイルは受講生が作成し、観測ファイルは実際のAPI・Podの状態を読んだcaptureが作ります。成功・UID・イベントを、自分で作り上げて書かないでください。 ヘルパーは、python3 /opt/fixtures/kcna_resources_lab.pyのあとに、act・capture・grade・prepareとステップ番号を付けたものです。 observeは、現在の状態を読むだけです。gradeも、受講生のファイルやKubernetesのオブジェクトを変更しません。 actのAPIレスポンスは、/opt/fixtures/kcna-resource-action-N.jsonに保存されます。同じリクエストを繰り返して、過去の403・201を再現しないでください。
ステップ
- capture 1で/root/kcna-resources/baseline.jsonを保存してください。Nodeの実際のallocatable CPU・UID、空のkcna-capacityネームスペースと、kcna-capacity-control/controlのUID・コンテナID・Ready・再起動回数を調べます。
- oversized-resources.jsonに、requestsとlimitsのオブジェクトを作成してください。2つのcpuの値は、実際のノードのallocatableよりCPU 1大きい値をm単位の文字列で書き、memoryはそれぞれ32Mi・64Miです。act 2・capture 2でunschedulable.jsonを保存します。oversized Podは存在するものの、未配置のPendingであり、該当UIDのUnschedulable条件・Insufficient cpuイベントがある必要があります。
- fit-resources.jsonに、requests={cpu:50m,memory:32Mi}、limits={cpu:200m,memory:64Mi}をJSONで作成してください。act 3は、調査したoversized UIDだけを回収し、小さなfit Podを作成します。capture 3でfitted.jsonを保存し、別のPod UID・正常な起動を確認してください。
- defaults-policy.jsonに、type=Container、defaultRequest={cpu:100m,memory:32Mi}、default={cpu:200m,memory:64Mi}を作成してください。act 4・capture 4でdefaults.jsonを保存します。リソースを省略したdefaultedの実際の要求100mと、既存のfitの50mの保存を比較します。
- quota.jsonに、requests.cpu=200m、requests.memory=128Mi、limits.cpu=1、limits.memory=256Mi、pods=4を、すべて文字列で作成してください。act 5は、team-budgetを作成したあと、リソースを省略したextraの作成を要求します。capture 5でquota_denied.jsonを保存します。使用量150mの状態で追加の100mが、実際のクォータのHTTP 403で拒否され、extraが存在しない必要があります。
- increase.jsonにrequests.cpu=300mを作成してください。act 6・capture 6でquota_admitted.jsonを保存します。同じextraの作成リクエストの実際のHTTP 201と、新しいPod UID・Ready、使用量250mを確認します。ほかのクォータの軸と既存のPodは変更しません。
- lower.jsonにrequests.cpu=100mを作成してください。act 7・capture 7でquota_lowered.jsonを保存します。使用量250mの既存のPodは、同じUID・コンテナで維持され、新しい10mのsmallの要求は、実際のHTTP 403で拒否される必要があります。ポリシーの縮小を、既存のPodの自動終了と解釈しないでください。
- recover.jsonに、remove=extra、requests.cpu=200m、replacement={requests:{cpu:50m,memory:32Mi},limits:{cpu:200m,memory:64Mi}}を作成してください。act 8は、調査したextraだけを回収し、使用量の減少後にバジェットを調整してsmallを作成します。capture 8でbudget_restored.jsonを保存します。実際のHTTP 201・Ready・最終的な要求の合計200mと、比較群の保存を立証してください。
参考
本文のcpu:50mのような表記は、フィールドと値を説明したものです。保存するファイルは、例のようにキーと文字列を引用符で囲んだ、正しいJSONである必要があります。 CPU 1は1000mです。ステップ2は、このVMの実際のallocatableを先に読んで計算し、特定のVMの値を暗記しません。 完了した入力と観測は保存します。進行中の入力を誤って書いたなら、エラーの原因を読んで直しますが、保存した過去の観測は書き直しません。 準備は、ない前のステップだけを埋めます。現在の課題の入力・観測を作ることはなく、誤って作成した既存の入力も上書きしません。 採点は60秒、ステップの準備は90秒の制限です。バジェット・使用量は収束を確認し、固定のsleepだけで成功と仮定しません。 中断の直後にオブジェクトが作成されたのに、身元の記録がない場合は、任意のオブジェクトを引き継がず、失敗します。自動初期化で学習の記録を消すことはありません。 記録のハッシュは、ミス防止のためのものであり、rootの悪意のある変更を防ぐリモート証明の装置ではありません。 公式の根拠: リソース管理・デフォルト値のポリシー・クォータ
配置バジェットと正常な比較群の調査
capture 1で/root/kcna-resources/baseline.jsonを保存してください。Nodeの実際のallocatable CPU・UID、空のkcna-capacityネームスペースと、kcna-capacity-control/controlのUID・コンテナID・Ready・再起動回数を調べます。
使用量のグラフとallocatableは、別の質問に答えます。
暇そうに見えても入れない要求
oversized-resources.jsonに、requestsとlimitsのオブジェクトを作成してください。2つのcpuの値は、実際のノードのallocatableよりCPU 1大きい値をm単位の文字列で書き、memoryはそれぞれ32Mi・64Miです。act 2・capture 2でunschedulable.jsonを保存します。oversized Podは存在するものの、未配置のPendingであり、該当UIDのUnschedulable条件・Insufficient cpuイベントがある必要があります。
Pendingだけを見ず、nodeName・PodScheduled条件・同一UIDのイベントをあわせて見てください。
合った大きさの要求で起動する
fit-resources.jsonに、requests={cpu:50m,memory:32Mi}、limits={cpu:200m,memory:64Mi}をJSONで作成してください。act 3は、調査したoversized UIDだけを回収し、小さなfit Podを作成します。capture 3でfitted.jsonを保存し、別のPod UID・正常な起動を確認してください。
ノードのリソースを変更したり、比較群を削除したりしないでください。
省略したリソースにデフォルト値を適用する
defaults-policy.jsonに、type=Container、defaultRequest={cpu:100m,memory:32Mi}、default={cpu:200m,memory:64Mi}を作成してください。act 4・capture 4でdefaults.jsonを保存します。リソースを省略したdefaultedの実際の要求100mと、既存のfitの50mの保存を比較します。
入力になかった値が保存されたオブジェクトに入ったかを見て、既存のオブジェクトも比較してください。
Podの作成そのものが拒否されるクォータ
quota.jsonに、requests.cpu=200m、requests.memory=128Mi、limits.cpu=1、limits.memory=256Mi、pods=4を、すべて文字列で作成してください。act 5は、team-budgetを作成したあと、リソースを省略したextraの作成を要求します。capture 5でquota_denied.jsonを保存します。使用量150mの状態で追加の100mが、実際のクォータのHTTP 403で拒否され、extraが存在しない必要があります。
Forbiddenの原因がRBACなのかteam-budgetなのかを、レスポンス本文で区別してください。
受け入れの許可と実際の実行を区別する
increase.jsonにrequests.cpu=300mを作成してください。act 6・capture 6でquota_admitted.jsonを保存します。同じextraの作成リクエストの実際のHTTP 201と、新しいPod UID・Ready、使用量250mを確認します。ほかのクォータの軸と既存のPodは変更しません。
201は作成の受け入れです。同じUIDが実際に実行されているかまで確認してください。
上限を下げても既存のPodは残る
lower.jsonにrequests.cpu=100mを作成してください。act 7・capture 7でquota_lowered.jsonを保存します。使用量250mの既存のPodは、同じUID・コンテナで維持され、新しい10mのsmallの要求は、実際のHTTP 403で拒否される必要があります。ポリシーの縮小を、既存のPodの自動終了と解釈しないでください。
quotaのusedがhardより大きくても、既存のオブジェクトは維持されることがあります。
調査した要求だけを回収してバジェットを復旧する
recover.jsonに、remove=extra、requests.cpu=200m、replacement={requests:{cpu:50m,memory:32Mi},limits:{cpu:200m,memory:64Mi}}を作成してください。act 8は、調査したextraだけを回収し、使用量の減少後にバジェットを調整してsmallを作成します。capture 8でbudget_restored.jsonを保存します。実際のHTTP 201・Ready・最終的な要求の合計200mと、比較群の保存を立証してください。
削除した名前だけでなく、UIDと使用量の帳簿の収束を確認してください。