Observability ใน Microservices
ในโลกของ monolith การดีบักแทบจะเป็นเรื่องที่จับต้องได้ คำขอเข้ามา วิ่งผ่านโปรเซสเดียว แตะ log file ไฟล์เดียว แล้วก็คืนค่ากลับมาหรือไม่ก็โยน stack trace ที่คุณสามารถอ่านได้ตั้งแต่ต้นจนจบ เมื่อมีอะไรผิดพลาด คุณก็เปิด terminal, tail app.log, แนบ profiler และเฝ้าดูเรื่องราวทั้งหมดคลี่คลายในที่เดียว
จากนั้นคุณก็แยกโปรเซสนั้นออกเป็นยี่สิบบริการที่รันบน replica หลายสิบตัวอยู่หลัง load balancer คลิกเดียวของผู้ใช้ตอนนี้แตกออกเป็นต้นไม้ของการเรียกที่กระจายไปตามเครื่องที่คุณอาจไม่เคยล็อกอินเข้าไปเลย, replica ที่เกิดและดับไปทุกครั้งที่ deploy และโปรเซสที่ local log file หายวับไปในวินาทีที่ container ถูกรีไซเคิล
นิสัยเดิม ๆ ที่ว่า SSH เข้าเครื่องแล้วไล่ดู log ใช้ไม่ได้อีกแล้ว เพราะเครื่องไหนล่ะ request นั้นวิ่งผ่านไปแปดเครื่อง แล้ว replica ที่ให้บริการก็โดน autoscaler ฆ่าทิ้งไปเมื่อสองนาทีก่อน พร้อมพา log ไปด้วย ส่วน error ที่ลูกค้าแจ้งมาคือ HTTP 500 ที่ gateway คืนกลับไป ซึ่งมีเบาะแสเดียวคือ downstream timeout ที่บอกชื่อ service ไม่ได้ด้วยซ้ำ
ดังนั้นคำถามหลักของโมดูลนี้คือ เมื่อไม่มีเครื่องเดียวที่ถือความจริงทั้งหมด คุณจะเข้าใจได้อย่างไรว่าระบบของคุณกำลังทำอะไรอยู่ ดีพอที่จะดีบัก event ตอนตีสาม และดีพอที่จะสังเกตปัญหาก่อนที่ลูกค้าจะสังเกตเห็น
วิธีแก้
หัวข้อที่มีชื่อว่า “วิธีแก้”คำตอบคือ observability คือการ instrument ทุก service เพื่อให้ประกอบภาพพฤติกรรมขึ้นมาใหม่ได้จากภายนอก โดยอาศัยสัญญาณที่ service ปล่อยออกมา ไม่ต้องล็อกอินเข้าไปที่ไหนเลย สัญญาณเหล่านั้นมีสี่รูปแบบที่เสริมกัน และคุณต้องใช้ครบทั้งสี่
flowchart LR
subgraph Services
A[Order Service]
B[Payment Service]
C[Inventory Service]
end
A -->|logs| LOG[(Log Store)]
B -->|logs| LOG
C -->|logs| LOG
A -->|metrics| MET[(Metrics Store)]
B -->|metrics| MET
C -->|metrics| MET
A -->|traces| TR[(Trace Store)]
B -->|traces| TR
C -->|traces| TR
A -.->|/health| ORCH[Orchestrator]
B -.->|/health| ORCH
C -.->|/health| ORCH
LOG --> DASH[Dashboards & Alerts]
MET --> DASH
TR --> DASH แต่ละ pattern ในโมดูลนี้ครอบคลุมหนึ่งในสัญญาณเหล่านั้น
- Health Check API — ทุก service เปิด endpoint ที่รายงานว่ายังมีชีวิตและพร้อมให้บริการหรือไม่ เพื่อให้ orchestrator และ load balancer route หลบ instance ที่ป่วยได้เอง
- Log Aggregation — ส่ง structured logs จากทุก replica ไปยัง store กลางที่ค้นหาได้ ผูกเข้าด้วยกันด้วย correlation id เพื่อให้คำขอหนึ่งอ่านเป็นเรื่องราวเดียว
- Distributed Tracing — ออก trace id ให้ทุก request จากภายนอก propagate ข้ามทุก hop แล้วประกอบ call tree พร้อม timing ขึ้นมาใหม่ เพื่อให้เห็นว่า latency และ error อยู่ตรงไหนกันแน่
- Application Metrics — เปิดเผย counters, gauges และ histograms สำหรับ request rate, errors และ latency เพื่อให้ dashboards และ alerts สามารถสรุปสุขภาพของทั้ง fleet ได้ในพริบตา
- Audit Logging — บันทึกว่าใครทำอะไรเมื่อไร ในรูป record ที่คงทนและตรวจจับการดัดแปลงได้ แยกออกจาก debug log เพราะตอบคนละคำถามกัน
โมดูลนี้ครอบคลุมอะไรบ้าง
หัวข้อที่มีชื่อว่า “โมดูลนี้ครอบคลุมอะไรบ้าง”เราเริ่มจากสัญญาณที่ถูกที่สุดและใช้งานเชิงปฏิบัติการมากที่สุดอย่าง Health Check API แล้วไล่ผ่านสามเสาหลักที่อธิบายพฤติกรรมคือ log, trace และ metric จากนั้นปิดท้ายด้วย record เฉพาะทางที่ตอบโจทย์ด้านความปลอดภัยและการกำกับดูแลอย่าง Audit Logging ทุกบทเรียนใช้รูปแบบเดียวกัน ได้แก่ สถานการณ์ที่นำไปสู่ pattern แรงที่ขัดกัน สิ่งที่ pattern ทำ ไดอะแกรม code instrumentation ที่รันได้จริงหรือตัวอย่าง log และการมองอย่างตรงไปตรงมาว่าต้องจ่ายอะไรบ้าง
เนื้อหาที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “เนื้อหาที่เกี่ยวข้อง”- Health Check API — เริ่มจากตัวนี้ เป็นสัญญาณที่ง่ายที่สุดและเป็นสิ่งแรกที่ platform ของคุณพึ่งพา
- Distributed Tracing — pattern ที่เข้ามาแทนที่ “อ่าน stack trace เดียว” ในโลกแบบกระจายได้ตรงที่สุด