Namespace และ Resource Quota
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”Namespace แบ่ง object และชื่อของ cluster เดียวให้หลาย user, ทีม หรือโปรเจกต์ใช้ร่วมกัน แต่ไม่ได้แบ่ง network ให้ด้วย ต้องใช้ NetworkPolicy ถึงจะทำได้
Namespace scope อะไรจริง ๆ
หัวข้อที่มีชื่อว่า “Namespace scope อะไรจริง ๆ”Namespace scope ชื่อ ของ object Deployment web ใน namespace team-a กับ Deployment web ใน namespace team-b เป็นคนละ object กันโดยสิ้นเชิง แค่บังเอิญชื่อเหมือนกัน Namespace ยังเป็นหน่วยที่ RBAC (จะพูดถึงใน module ถัดไป) มักถูก scope ไว้ ทำให้สิทธิ์ของแต่ละทีมจำกัดอยู่แค่ namespace ที่ทีมนั้นดูแล ไม่ใช่ทั้ง cluster
สิ่งที่ Namespace ไม่ได้ ให้คือ network isolation โดย default Pod ใน team-a ยังส่ง traffic ไปหา Pod ใน team-b ได้อยู่ดี Namespace เป็นขอบเขตเรื่องชื่อและการจัดระเบียบ ไม่ใช่ขอบเขตเรื่อง network ถ้าอยากบล็อก traffic นั้นต้องใช้ NetworkPolicy ซึ่งอยู่ใน module Networking
apiVersion: v1kind: Namespacemetadata: name: team-akubectl create namespace team-akubectl config set-context --current --namespace=team-aไม่ใช่ทุก object จะอยู่ใน namespace
หัวข้อที่มีชื่อว่า “ไม่ใช่ทุก object จะอยู่ใน namespace”บาง object เป็น cluster-scoped คืออยู่นอก namespace ไหนเลย เพราะอธิบายแนวคิดระดับ cluster ไม่ใช่สิ่งที่ทีมใดทีมหนึ่งเป็นเจ้าของ Node, PersistentVolume และ ClusterRole ล้วนเป็น cluster-scoped ส่วน object ที่ใช้กันบ่อย ๆ อย่าง Pod, Deployment, Service, ConfigMap, PersistentVolumeClaim เป็น namespaced
# List objects that live outside any namespacekubectl api-resources --namespaced=falseResourceQuota: จำกัดการใช้รวมของทั้ง namespace
หัวข้อที่มีชื่อว่า “ResourceQuota: จำกัดการใช้รวมของทั้ง namespace”ResourceQuota จำกัดการใช้ resource รวมทั้งหมดของ namespace หนึ่งตัว คือ CPU กับ memory requests/limits รวมของทุก Pod ใน namespace นั้น และ/หรือจำนวน object รวม เช่น จำนวน Pod, Service หรือ PersistentVolumeClaim สูงสุด
apiVersion: v1kind: ResourceQuotametadata: name: team-a-quota namespace: team-aspec: hard: requests.cpu: "10" requests.memory: 20Gi limits.cpu: "20" limits.memory: 40Gi pods: "50" persistentvolumeclaims: "10"LimitRange: กำหนดขอบเขตของ Pod และ container แต่ละตัว
หัวข้อที่มีชื่อว่า “LimitRange: กำหนดขอบเขตของ Pod และ container แต่ละตัว”ResourceQuota จำกัดทั้ง namespace รวมกัน แต่ไม่ได้พูดถึง Pod ตัวใดตัวหนึ่งเลย ถ้าไม่มีขอบเขตระดับ object เดียว Pod ที่ไม่ถูกจำกัดตัวเดียวสามารถขอ CPU กับ memory มากพอจะกิน ResourceQuota ทั้ง namespace ไปคนเดียว ทำให้ Pod อื่นในทีมเดียวกันขาดแคลนไปด้วย LimitRange ปิดช่องว่างนี้ด้วยการตั้งค่า default, ขั้นต่ำ และขั้นสูงของ requests/limits สำหรับ Pod และ container แต่ละตัวที่ถูกสร้างใน namespace นั้น
apiVersion: v1kind: LimitRangemetadata: name: team-a-limits namespace: team-aspec: limits: - type: Container default: cpu: 500m memory: 512Mi defaultRequest: cpu: 250m memory: 256Mi max: cpu: "2" memory: 2Gi min: cpu: 100m memory: 128Miหมายเหตุ environment: kind cluster ของโมดูลนี้เองผ่านช่วงที่ CPU ขาดแคลนอย่างหนักจากเครื่องที่ใช้ร่วมกันซึ่งรัน kind cluster ของหลาย agent พร้อมกัน (uptime แสดง load average ค้างที่ 20–30 และตรวจตรงด้วย docker exec ... cat /proc/loadavg พบว่า load average ระดับ kernel ของเครื่องจริงวัดได้เกิน 1490 ในจุดหนึ่ง ยืนยันแล้วว่าเป็นปัญหาระดับเครื่องทั้งเครื่องเพราะ cluster verify-k8s ที่ใช้ร่วมกันแยกต่างหาก ก็ fail เหมือนกันในช่วงเวลาเดียวกัน) การพิสูจน์ทั้งหมดด้านล่างถูกจับไว้หลัง cluster กลับมาใช้ได้ปกติ — output ของ kubectl ด้านล่างทุกอันมาจาก run จริง
ResourceQuota: rejection จริง พร้อมข้อความ exceeded quota: เป๊ะ ๆ
หัวข้อที่มีชื่อว่า “ResourceQuota: rejection จริง พร้อมข้อความ exceeded quota: เป๊ะ ๆ”apiVersion: v1kind: Namespacemetadata: name: quota-demo---apiVersion: v1kind: ResourceQuotametadata: name: team-quota namespace: quota-demospec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi pods: "3"---apiVersion: v1kind: LimitRangemetadata: name: team-limits namespace: quota-demospec: limits: - type: Container max: cpu: "1" min: cpu: 100m# k8s/namespaces-and-resource-quotas/quota-exceed-pod.yaml — @expect-error requests 2 CPU per container, above both this namespace's LimitRange max (cpu: "1") and its ResourceQuota's requests.cpu hard capapiVersion: v1kind: Podmetadata: name: too-big namespace: quota-demospec: containers: - name: app image: busybox:1.38 command: ['sh', '-c', 'sleep 3600'] resources: requests: cpu: '2' memory: 4Gi limits: cpu: '2' memory: 4Gi$ kubectl apply -f quota-exceed-pod.yamlError from server (Forbidden): error when creating "quota-exceed-pod.yaml": pods "too-big" is forbidden: maximum cpu usage per Container is 1, but limit is 2rejection จริงมาจาก LimitRange ของ namespace ก่อนเลย ไม่ใช่ ResourceQuota — LimitRange ตรวจ request/limit ของแต่ละ container เทียบกับ max/min ของตัวเองแยกต่างหาก และ 2 CPU ชน max: cpu: "1" ก่อนที่การคำนวณรวมของ ResourceQuota จะเกี่ยวข้องด้วยซ้ำ พอจะเห็น rejection ของ ResourceQuota เองจริง ๆ request ต้องผ่าน LimitRange ได้ (cpu อยู่ในขอบเขต 1) แต่ยังเกิน hard cap ของ ResourceQuota ใน resource อื่น:
$ kubectl apply -f - <<'EOF'apiVersion: v1kind: Podmetadata: name: too-much-mem namespace: quota-demospec: containers: - name: app image: busybox:1.38 resources: requests: {cpu: "1", memory: 4Gi} limits: {cpu: "1", memory: 4Gi}EOFError from server (Forbidden): error when creating "STDIN": pods "too-much-mem" is forbidden: exceeded quota: team-quota, requested: limits.memory=4Gi,requests.memory=4Gi, used: limits.memory=0,requests.memory=0, limited: limits.memory=2Gi,requests.memory=1Giนั่นคือข้อความ exceeded quota: จริง ๆ — Forbidden เต็ม ๆ ตอน admission ไม่ใช่ throttle หรือเข้าคิว พร้อมตัวเลข requested/used/limited จริงของ resource ที่ชนพอดี สอง rejection จริงที่ต่างกันจาก namespace เดียวกัน: LimitRange จับ container เดี่ยวที่เกินขอบเขตก่อน ResourceQuota จับการรวมที่ Pod ที่ผ่าน LimitRange แล้วยังดันเกิน hard cap ของ namespace อยู่ดี
Quota บนจำนวน object
หัวข้อที่มีชื่อว่า “Quota บนจำนวน object”ResourceQuota ตัวเดียวกันด้านบนยังจำกัด pods: "3" ด้วย — เป็น count-based limit ที่แยกจากการคำนวณ CPU/memory เลย:
$ kubectl apply -f pod-count-1.yaml -f pod-count-2.yaml -f pod-count-3.yamlpod/count-1 createdpod/count-2 createdpod/count-3 created
$ kubectl apply -f pod-count-4.yamlError from server (Forbidden): error when creating "pod-count-4.yaml": pods "count-4" is forbidden: exceeded quota: team-quota, requested: pods=1, used: pods=3, limited: pods=3Pod ตัวที่ 4 แต่ละตัวขอแค่ 100m/64Mi เท่านั้น อยู่ในขอบเขตอื่นทุกอย่างสบาย ๆ ถูก reject ล้วน ๆ ด้วยจำนวน — quota แบบนับจำนวน object บล็อกการ scale-up ที่ถูกต้องได้แรงพอ ๆ กับ quota แบบจำนวน resource เลย แค่ด้วยเหตุผลคนละอย่าง
LimitRange interplay: Pod ที่ไม่มี requests ใต้ quota ที่บังคับต้องมี
หัวข้อที่มีชื่อว่า “LimitRange interplay: Pod ที่ไม่มี requests ใต้ quota ที่บังคับต้องมี”# k8s/namespaces-and-resource-quotas/quota-norequest-pod.yaml — @expect-error no resources.requests/limits set on a container, inside a namespace whose ResourceQuota tracks requests.cpu/requests.memory/limits.cpu/limits.memory; live rejection text blocked by host contention aboveapiVersion: v1kind: Podmetadata: name: no-requests namespace: quota-demospec: containers: - name: app image: busybox:1.38 command: ['sh', '-c', 'sleep 3600']$ kubectl apply -f quota-norequest-pod.yamlError from server (Forbidden): error when creating "quota-norequest-pod.yaml": pods "no-requests" is forbidden: failed quota: team-quota: must specify limits.memory for: app; requests.memory for: appนี่คือผลจริงที่แม่นยำและน่าแปลกใจนิดหน่อย: error ระบุแค่ memory เท่านั้น ไม่มี cpu เลย เหตุผลคือการ default ของ LimitRange พิสูจน์ตรง ๆ ด้วยการ apply Pod แบบไม่มี resources ตัวเดียวกันเป๊ะ ใน namespace แยกที่มี LimitRange เดียวกันแต่ไม่มี ResourceQuota แล้วตรวจดูว่าอะไรถูกใส่เข้าไปจริง:
$ kubectl get pod no-res -o jsonpath='{.spec.containers[0].resources}'{"limits":{"cpu":"1"},"requests":{"cpu":"1"}}ตาม กฎการเติม default ของ LimitRange ของ Kubernetes พอ LimitRange ตั้ง max ไว้แต่ไม่ได้ตั้ง default ชัดเจน API server จะใช้ max เองเป็น default ของ limit (และเมื่อไม่มี defaultRequest 1 ก็กลายเป็น default ของ request ด้วย) — ดังนั้น LimitRange ของ namespace นี้ (max: cpu: "1", min: cpu: 100m ไม่มีขอบเขต memory เลย) เลยเติม cpu ให้ Pod ด้านบนแบบเงียบ ๆ เหลือแค่ memory ที่ไม่ได้ตั้งค่าจริง ๆ ResourceQuota เองไม่เคยเติม default ให้เลย มันแค่ reject เท่านั้น — ตรงนี้มัน reject พอดีตัวเดียวที่ LimitRange ไม่ได้มีความเห็นอะไรด้วยเลย
Namespace ค้าง Terminating เพราะ finalizer
หัวข้อที่มีชื่อว่า “Namespace ค้าง Terminating เพราะ finalizer”apiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata: name: slowresources.example.comspec: group: example.com names: kind: SlowResource plural: slowresources singular: slowresource scope: Namespaced versions: - name: v1 served: true storage: true schema: openAPIV3Schema: type: object properties: spec: type: object x-kubernetes-preserve-unknown-fields: true# k8s/namespaces-and-resource-quotas/stuck-ns.yaml — @expect-error dry-run=server never actually registers the CRD above with the API server, so a CR instance of that same never-installed CRD fails validation in this harness with a real, separate error (`no matches for kind "SlowResource"`) — proven for real below on a cluster where the CRD was actually (non-dry-run) applied firstapiVersion: v1kind: Namespacemetadata: name: stuck-demo---apiVersion: example.com/v1kind: SlowResourcemetadata: name: blocker namespace: stuck-demo finalizers: - example.com/never-removedspec: {}$ kubectl apply -f stuck-crd.yamlcustomresourcedefinition.apiextensions.k8s.io/slowresources.example.com created
$ kubectl apply -f stuck-ns.yamlnamespace/stuck-demo createdslowresource.example.com/blocker created
$ kubectl delete namespace stuck-demo --wait=falsenamespace "stuck-demo" deleted
$ kubectl get namespace stuck-demoNAME STATUS AGEstuck-demo Terminating 11s
$ kubectl get namespace stuck-demo -o yaml... - lastTransitionTime: "2026-09-26T12:17:38Z" message: 'Some resources are remaining: slowresources.example.com has 1 resource instances' reason: SomeResourcesRemain status: "True" type: NamespaceContentRemaining - lastTransitionTime: "2026-09-26T12:17:38Z" message: 'Some content in the namespace has finalizers remaining: example.com/never-removed in 1 resource instances' reason: SomeFinalizersRemain status: "True" type: NamespaceFinalizersRemaining phase: Terminatingจริงและตรงตามกลไกที่คาดไว้เป๊ะ: namespace controller รอทุก object ข้างในถูกลบออกจริง ๆ ก่อน และ object ที่มี finalizer ค้างอยู่จะได้แค่ deletionTimestamp ไม่เคยถูกลบจริงจนกว่า finalizer ทุกตัวจะถูกเคลียร์ namespace เลยค้างอยู่ที่ Terminating ตลอดไป status.conditions ระบุปัญหาตรง ๆ (SomeFinalizersRemain ระบุชื่อ example.com/never-removed) วิธีที่ถูกต้องในการ ตรวจสอบ เรื่องนี้ — ไม่ใช่วิธี ตอบสนอง แรกสุด — คือการ sweep ตาม namespace ไม่ใช่การไปแก้ metadata.finalizers ทันทีเป็นทางแรก
เรื่องข้างเคียงจริงที่ควรรู้เวลาใช้ harness ของคอร์สนี้เอง (หรือ workflow แบบ --dry-run=server ไหนก็ตาม) พิสูจน์คู่ CRD-กับ-instance แบบนี้: kubectl apply --dry-run=server บน CRD ไม่เคยลงทะเบียนมันกับ API server จริง (dry-run แปลว่าไม่มีอะไรถูกเก็บจริง) การ dry-run แยกต่างหาก ของ instance SlowResource กับ cluster ที่ไม่เคย apply CRD จริง ๆ เลยจะ fail ด้วย error จริงที่ต่างออกไป — no matches for kind "SlowResource" in version "example.com/v1": ensure CRDs are installed first นั่นไม่ใช่ข้อผิดพลาดใน instance manifest แต่เป็นข้อจำกัดจริงของการพิสูจน์ CRD ใหม่เอี่ยมกับ instance ของมันในรอบ dry-run เดียวกัน และนี่คือเหตุผลที่ fence ที่สองด้านบนถูก mark @expect-error สำหรับ harness ของคอร์สนี้ ทั้งที่ (ตามที่พิสูจน์ไปแล้ว) มันทำงานได้สมบูรณ์แบบบน cluster ที่ CRD ถูก apply จริงแบบ non-dry-run มาก่อน:
kubectl api-resources --verbs=list --namespaced -o name | while read -r r; do cnt=$(kubectl get "$r" -n stuck-demo --no-headers 2>/dev/null | wc -l | tr -d ' ') if [ "$cnt" != "0" ]; then echo "$r: $cnt"; fidoneslowresources.example.com: 1sweep เจอ resource kind เดียวที่มี object เหลืออยู่ในจริง ๆ ตรงกับ status.conditions เป๊ะ — จากตรงนั้น ทางแก้ที่ถูกต้องคือเอา finalizer entry เฉพาะที่ object เอง มีออก (หรือทำให้ controller ที่ควรจะเอาออกกลับมารันอีกครั้ง) ไม่ใช่ไปแก้ metadata.finalizers ที่ตัว namespace เอง
kubectl get all -A ไม่ใช่ทั้งหมด
หัวข้อที่มีชื่อว่า “kubectl get all -A ไม่ใช่ทั้งหมด”kubectl api-resources --namespaced=true --no-headers | wc -lkubectl api-resources --namespaced=true -o name$ kubectl api-resources --namespaced=true --no-headers | wc -l45$ kubectl api-resources --namespaced=true -o nameconfigmapscontrollerrevisions.appscronjobs.batchcsistoragecapacities.storage.k8s.iodaemonsets.appsdeployments.appsendpointsendpointslices.discovery.k8s.ioeventshorizontalpodautoscalers.autoscalingingresses.networking.k8s.iojobs.batchleases.coordination.k8s.iolimitrangesnetworkpolicies.crd.projectcalico.orgnetworkpolicies.networking.k8s.iopersistentvolumeclaimspoddisruptionbudgets.policypodspodtemplatesreplicasets.appsreplicationcontrollersresourcequotasrolebindings.rbac.authorization.k8s.ioroles.rbac.authorization.k8s.iosecretsserviceaccountsservicesslowresources.example.comstatefulsets.apps... (รวม 45 บน cluster นี้)45 namespaced kind จริงบน cluster นี้ — kubectl get all -A ครอบคลุมแค่ kind ที่พบบ่อยตามรายการ hardcode คงที่ (Pod, Deployment, ReplicaSet, Service และอีกไม่กี่ตัว) — ไม่รวม ResourceQuota, LimitRange, ConfigMap, Secret, Role/RoleBinding, NetworkPolicy, หรือ PodDisruptionBudget เลย ทั้งที่ทุกตัวอยู่ใน list จริงด้านบนในฐานะ namespaced object ธรรมดา kubectl api-resources --namespaced=true คือ inventory ที่ครบจริงว่า “namespaced” หมายถึงอะไรบน cluster หนึ่ง ๆ — จำนวนและเนื้อหาที่แน่นอนขึ้นอยู่กับว่า CRD ไหนติดตั้งอยู่บ้าง (Calico ที่ติดตั้งบน cluster นี้ กับ CRD SlowResource ของคอร์สเองก็เพิ่มแถวที่ cluster เปล่าจะไม่มี) script หรือความเคยชินที่ grep output ของ get all -A แล้วคิดว่าเห็น namespaced object ทุกตัวใน cluster แล้ว พลาดไปเกือบทั้งหมดแบบเงียบ ๆ
flowchart LR
subgraph cluster["Cluster"]
subgraph nsa["Namespace: team-a"]
qa["ResourceQuota"] --- la["LimitRange"]
pa1["Pod"] --- pa2["Pod"]
end
subgraph nsb["Namespace: team-b"]
qb["ResourceQuota"] --- lb["LimitRange"]
pb1["Pod"] --- pb2["Pod"]
end
end อ่านโค้ดที่ AI เขียน
หัวข้อที่มีชื่อว่า “อ่านโค้ดที่ AI เขียน”ตอนรีวิว manifest ของ namespace/quota ที่ AI สร้าง ให้เช็ค
- manifest ที่คิดว่า
ResourceQuotaเติม request/limit ที่หายไปแบบเดียวกับdefault/defaultRequestของLimitRange— พิสูจน์/อ้างอิงด้านบนแล้วว่าResourceQuotaแค่ reject เท่านั้น ไม่เคยเติม default เองเลย - script cleanup หรือ deletion ที่ไม่มีการจัดการ namespace ที่ค้าง
Terminating— อ้างอิงด้านบนแล้วว่านี่คือสถานะจริงที่พบบ่อย ไม่ใช่ edge case สมมติ - script audit หรือ cleanup ที่ grep
kubectl get all -Aแล้วคิดว่าเห็น namespaced object ทุกตัวแล้ว — อ้างอิงด้านบนแล้วว่าget allคือ list คงที่เล็ก ๆ ที่ไม่รวม ResourceQuota, LimitRange, ConfigMap, Secret, RBAC object, NetworkPolicy, และ PodDisruptionBudget เป็นต้น - โค้ดหรือเอกสารที่ปฏิบัติต่อขอบเขต namespace ราวกับเทียบเท่า NetworkPolicy default-deny — namespace จำกัดแค่ ชื่อ กับ การนับ resource ไม่เคยจำกัด การเข้าถึงทาง network เลย ตามที่หัวข้อเปิดบทนี้พูดไว้แล้ว
🐛 หา bug ในโค้ดนี้
apiVersion: v1kind: Namespacemetadata:name: team-b---apiVersion: v1kind: ResourceQuotametadata:name: team-b-quotanamespace: team-bspec:hard: requests.cpu: "4" requests.memory: 8Gi limits.cpu: "8" limits.memory: 16Gi---apiVersion: v1kind: Podmetadata:name: workernamespace: team-bspec:containers: - name: app image: myregistry/worker:1.0เฉลย
ResourceQuota ของ team-b track requests.cpu/requests.memory/limits.cpu/limits.memory แต่ manifest Pod ไม่ได้ตั้ง block resources บน container เลย และไม่มี LimitRange ใด ๆ ใน namespace นี้ที่จะเติม default ให้ พิสูจน์ด้านบนแล้วว่านี่ไม่ใช่กรณีที่ Pod จะได้ default request มาเงียบ ๆ — API server จะ reject Pod นี้ตรง ๆ ด้วย error must specify ที่ระบุทุก resource ที่ track ไว้ที่ container ไม่ได้ตั้ง (must specify limits.cpu,limits.memory,requests.cpu,requests.memory for: app) และไม่มีอะไรใน manifest นี้ที่จะป้องกัน rejection นั้นได้เลย ทางแก้: เพิ่ม resources.requests/resources.limits ให้ container ตรง ๆ หรือไม่ก็เพิ่ม LimitRange ให้ namespace พร้อมตั้ง default/defaultRequest ไว้ เพื่อให้ container ที่ไม่ได้ตั้งค่าได้ default ที่สมเหตุสมผลแทนที่จะถูก reject ตรง ๆ
Mental Model
หัวข้อที่มีชื่อว่า “Mental Model”namespace คือขอบเขตเรื่อง ชื่อและการนับ resource ไม่ใช่ขอบเขตเรื่อง ความสามารถ ด้วยตัวเอง ResourceQuota นับการใช้รวมของทั้ง namespace LimitRange เติมและจำกัดว่า Pod/container แต่ละตัวขอได้แค่ไหน และทั้งคู่ (รวมถึงตัว namespace เอง) ไม่แตะเรื่องการเข้าถึงทาง network เลย ซึ่งเป็นการควบคุมคนละชั้นไปเลย (NetworkPolicy อยู่ใน module Networking)
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ทางเลือก | ข้อดี | ต้นทุน |
|---|---|---|
ResourceQuota track requests.*/limits.* | จำกัดการใช้รวมของ namespace ได้จริง อ้างอิงด้านบนพร้อม rejection รูปแบบจริง | ทุก Pod ใน namespace ต้องตั้ง request/limit เอง (หรือมี default จาก LimitRange) ไม่งั้นถูก reject ตรง ๆ |
LimitRange พร้อม default/defaultRequest | ตัดภาระ “ต้องตั้งเอง” ออกจากทุกคนที่เขียน manifest อ้างอิงด้านบน | default ที่ apply แบบเงียบ ๆ อาจผิดสำหรับ workload บางตัวถ้าไม่มีใครสังเกต |
Quota แบบนับจำนวน object (pods: "3") | ป้องกันการสร้าง object เกินควบคุมไม่ว่าขนาดจะเท่าไหร่ อ้างอิงด้านบน | บล็อกการ scale-up ที่ถูกต้องได้ด้วย error เรื่อง “จำนวน” ถ้าไม่มีใครเช็ค quota ก่อน |
| ตรวจ namespace ที่ค้าง Terminating ด้วยการ sweep ตาม namespace | เจอ resource ที่บล็อกจริง แบบไม่ทำลายอะไร | ช้ากว่าการ force-clear finalizer — แต่ force-clear ซ่อนปัญหาจริงไว้แทนที่จะแก้ |
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”- “ResourceQuota เติม default request/limit ให้ Pod ที่ไม่ได้ตั้งเอง” อ้างอิงด้านบนแล้ว — แค่ reject เท่านั้น
LimitRangeต่างหากที่เติม default ให้ และเติมก็ต่อเมื่อตั้งค่าไว้เท่านั้น - “kubectl get all -A แสดง object ทุกตัวใน cluster” อ้างอิงด้านบนแล้ว — เป็น list คงที่ที่ไม่ครบ
kubectl api-resources --namespaced=trueต่างหากคือ inventory ที่ครบจริง - “namespace ที่ค้าง Terminating แก้ได้แค่ทางเดียวคือไปแก้ finalizer ออก” อ้างอิงด้านบนแล้ว — ตรวจดูว่า resource ตัวไหนที่ยังมี finalizer ค้างอยู่ (ผ่านการ sweep ตาม namespace) คือขั้นแรกที่ถูกต้องและไม่ทำลายอะไร