Troubleshooting Scenarios — ฝึก Debug สด
หน้านี้คือเวอร์ชัน "live coding" ของหมวด OpenShift — เน้นสถานการณ์ที่เกิดเฉพาะบน OpenShift (ไม่ใช่ debug K8s ทั่วไปซ้ำ ดู K8s → Troubleshooting Scenarios สำหรับ debug flow มาตรฐานก่อน)
Scenario 1: Pod ไม่ขึ้น เจอ "unable to validate against any security context constraint"
อาการ: oc get pods แสดง Pod ค้างไม่สร้างเลย ไม่มีแม้แต่สถานะ Pending
ลำดับการสืบสวน:
oc get events --sort-by=.lastTimestamp | grep -i "security context"
oc get pod my-app -o yaml | grep -A10 "securityContext:"
oc get scc restricted -o yaml | grep -A5 "runAsUser:"
สาเหตุที่พบบ่อย: Dockerfile มี USER root หรือ USER 0 แบบ hardcode, หรือ image
พยายาม bind port ต่ำกว่า 1024 (ต้องใช้สิทธิ์ root) — แก้ด้วยการปรับ Dockerfile ให้รองรับ
arbitrary UID (ดู Security Model) ไม่ใช่ขอ SCC สูงขึ้นเป็นอันดับแรก
error นี้มีจุดสังเกตที่ชี้สาเหตุได้ชัดเจนถ้าอ่านดีๆ: ข้อความจะบอกด้วยว่า SCC ไหนที่ "เกือบผ่าน แต่ไม่ผ่านตรงไหน" (เช่น "capabilities.add: Invalid value: NET_ADMIN: capability may not be added") ไม่ใช่แค่บอกว่า "ไม่ผ่านทุก SCC" เฉยๆ — การอ่าน field ที่ error message ชี้มาตรงๆ (ไม่ใช่ เดาทั้งหมด) ช่วยลดเวลา debug ได้มาก เพราะบอกตรงๆ ว่า field ไหนใน Pod spec ที่ต้องแก้ ไม่ต้อง ไล่เทียบทุก field เอง
Scenario 2: Build fail ตอน oc start-build ด้วย error "no space left on device"
อาการ: Build pod ขึ้น error เกี่ยวกับ disk space ทั้งที่ Node ดูมี storage เหลือเยอะ
ลำดับการสืบสวน:
oc get build my-app-3 -o yaml | grep -A5 "message:"
oc adm top nodes --show-capacity # เช็ค storage บน node ที่ build pod รันอยู่
oc describe node <build-node> | grep -A5 "Allocated resources"
Error นี้มักไม่ได้มาจาก Node disk เต็มจริงๆ แต่มาจาก emptyDir ที่ build pod ใช้เป็น working
directory มีขนาดจำกัด (ผูกกับ ephemeral-storage quota/limit ที่ตั้งไว้ใน project หรือ
default ของ build pod เอง) — source code ที่ clone มา + dependency ที่ install ระหว่าง
assemble step (เช่น node_modules ขนาดใหญ่, หรือ build cache ของ compiler) อาจเกิน
ephemeral-storage limit ที่ build pod ได้รับ แม้ Node จะมี disk เหลือเยอะจริงๆ ก็ตาม — วิธี
แก้คือเพิ่ม resources.limits.ephemeral-storage ใน BuildConfig's resources field หรือ
optimize build process ให้ไม่สะสม cache ที่ไม่จำเป็น (เช่น npm ci --no-cache)
Scenario 3: Route สร้างแล้วแต่ curl ไม่ตอบ (timeout)
อาการ: oc get route my-app แสดง host ถูกต้อง แต่ curl ไปที่ host นั้น timeout
ลำดับการสืบสวน:
oc get route my-app -o yaml | grep -A5 "status:" # เช็คว่า Route ถูก admit โดย router หรือยัง
oc get endpoints my-app # เช็คว่า Service มี Pod backend จริงไหม
oc get pods -l deployment=my-app -o wide # เช็คว่า Pod พร้อม Ready จริงไหม
field ที่คนมักข้ามไปไม่เช็คคือ status.ingress[].conditions ของ Route object เอง — Route
ที่สร้างสำเร็จไม่ได้แปลว่า router "ยอมรับ" (admit) มันแล้วเสมอไป ถ้ามี Route อื่นประกาศ
hostname เดียวกันไปแล้วก่อนหน้า (host collision ข้าม project — ซึ่งเป็นไปได้เพราะ hostname
เป็น global namespace ไม่ได้แบ่งตาม project) Route ใหม่ที่สร้างทีหลังจะถูก reject เงียบๆ
(ไม่มี error ตอน oc create แต่จะไม่ถูก router หยิบไปใช้งานจริง) ต้องดูที่
status.ingress[].conditions[].status ว่าเป็น Admitted: True จริงไหมถึงจะมั่นใจได้ว่า
Route ทำงานอยู่จริง — เป็นจุดที่ debug Route ไม่ทำงานที่คนส่วนใหญ่มองข้ามเพราะ oc get route
แบบปกติไม่โชว์ field นี้ให้เห็นชัดถ้าไม่ -o yaml ดูเจาะลึก
For "unable to validate against any security context constraint," read the specific field the
error message points to (e.g. a rejected capability) rather than guessing broadly — it usually
traces back to a hardcoded root user in the Dockerfile. Build failures reporting "no space left
on device" often come from the build pod's ephemeral-storage limit being exceeded by
dependency/cache bloat, not actual Node disk exhaustion — raise the BuildConfig's
ephemeral-storage limit or trim build caching instead. A Route that times out despite looking
correctly created may have been silently rejected due to a hostname collision with another
Route elsewhere in the cluster (hostnames are a global, not per-project, namespace) — check
status.ingress[].conditions for Admitted: True to confirm the router actually picked it up.