Extract microservices ด้วยวิธี reuse บน kubernetes เพื่อ resource efficiency
เพราะทรัพยากรเรามีอยู่จำกัด ทำให้เราต้องกังวลถึงขนาดของ container นั่นเอง และจะยิ่งกังวลมากขึ้นหากเราใช้ cloud service เพราะการใช้ทรัพยากรณ์มากขึ้นย่อมหมายถึงใช้เงินที่มากขึ้นเช่นกัน
Example system
สมมติระบบ karaoke เรามี service อยู่ 2 ตัวอย่างง่าย คือ music service (backend) และ jukebox service (frontend) โดยทุกอย่างที่ jukebox จะเอามาแสดงผล ใช้ข้อมูลมาจาก music service
Music service
และ music service นั้น expose REST API อย่างง่าย อยู่ 3 อย่างคือ
/musics, /music/{id} และ /search
Memory usage per request
ทุกๆ request ที่เกิดขึ้น service ของเราจะมีการใช้ memory อยู่บ้างซึ่งไม่ใช่เรื่องแปลกอะไร
ทว่าด้วยเหตุผลบางประการ /search ของเราดันใช้ memory สูงกว่าคนอื่นอยู่มาก
ทำให้เราต้องขยายขนาดของ container ขึ้นเพื่อให้รองรับ /search
note:
สาเหตุที่ไม่ใช้วิธี set upper bound > lower bound (burstable) ของ memory นั้นเพราะมองว่าหากเกิด out-of-memory event ที่ระดับ node จะทำให้ chain of failure หรือ domino effect มากกว่า ถึงแม้ QoS ของ pod จะเป็น burstable อยู่ดีก็ตาม (ในรูป cpu burst ได้ ทำให้ class เป็น burstable)see more: Quality Of Service
see more: Node OOM Behaviour
Wasted memory scaling
เมื่อ pod/container มีขนาดใหญ่ การขยายตัวออกก็ทำให้ใช้ทรัพยากรณ์เยอะตามไปด้วย
จะกังวลขนาดของ container ไปทำไม? คำตอบก็ง่ายแสนง่าย เพราะทรัพยากรณ์เรามีอยู่จำกัดนั่นเอง
note:
ถ้าโชคดีที่ทุกๆ api มีอัตราการถูกเรียกใช้งานเท่าๆกัน การ scale out แบบนี้ถือว่าโอเค แต่ถ้าในความเป็นจริงมีคนเรียกใช้ /search แค่ 10% ละ? (หรืออีกนัยหนึ่งก็คือแค่ pod/container เดียวก็เพียงพอจะทำงานได้)
Extracting by Reusing
ด้วยความสามารถของ Kubernetes ทำให้เราสามารถที่จะสร้าง virtual service ขึ้นมาอีกตัวได้อย่างง่ายดาย เราจึงทำการ extract /search ออกมาเป็น search service โดยการ reuse image ของ music service ได้อย่างง่าย
จากรูปจะเห็นว่าเราใช้วิธี resuse image music:1.0.0 ตรงๆ แต่ทำให้เราได้ search service ขึ้นมา (ถึงแม้ข้างในจะเป็น music service เหมือนเดิมนั่นแหละ)
แล้วเราได้ประโยชน์อะไรจากการทำแบบนี้? คำตอบก็คือช่วยให้ประหยัด resource ในตอน scale out นั่นเอง
/musics กับ /music/{id} ใน music service จะยังคงมี 3 pods/containers เท่าเดิมเพราะต้องรองรับ load 90% ในขณะที่ /search ใน search service มี load แค่ 10% แค่ pod/container เดียวก็เพียงพอแล้ว
จะเห็นว่าประหยัดพื้นที่ได้อีกเกือบ 60% เลยทีเดียว หลังจากนั้นก็ปรับแก้ไข code นิดหน่อยให้ไปเรียกใช้งาน search service ที่สร้างขึ้นมาใหม่
Adaptive
วิธีนี้ยังสามารถนำไปประยุกต์กับการ extract microservices from monolith ได้อีกด้วย เริ่มจาก wrap monolith ให้เป็น containerized application
สร้าง service และแก้ไข code ให้ใช้ service ที่สร้างขึ้นมาใหม่ ด้วยวิธีการ reuse image แล้วค่อยๆ implement microservices จริงๆมา replace ทีละ service
Backward compatible
หากเข้าใจ concept จะพบว่าเราสามารถใช้วิธีได้ตั้งแต่ที่ระดับของ docker หรือ container orchestration ตัวอื่นๆได้อีกด้วย ไม่จำเป็นต้องใช้ kubernetes เพียงอย่างเดียว