จากการอ่านบทความเรื่อง How we run migrations across 2,800 microservices ของทาง monzo
ซึ่งเป็น online banking ที่ UK
ทำการเขียนบทความเรื่องการ upgrade library
จากเดิมที่ใช้งาน OpenTracing และ Jaeger ที่ deprecated ไปแล้ว
มาใช้งาน OpenTelemetry
บน service จำนนวน 2,800 service !!
มาดูกันว่าทำอย่างไรบ้าง ?
แนวทางในการ upgrade มีอยู่ 3 ทางเลือกคือ
- Update library มายัง version ล่าสุด
- ทุก ๆ serviceต้องใช้ library version เดียวกันเสมอ
- ใช้ effort ในการ upgrade ให้น้อยที่สุด เปลี่ยนแปลง code ให้น้อยที่สุด
โดยในการ upgrade หรือ migrate ครั้งนี้
ต้องการลดปัญหาที่อาจจะเกิดขึ้น เช่น
การทำงานร่วมกับหลาย ๆ ทีม ซึ่งอาจจะเกิด overhead ในการพูดคุยหรือติดต่อกัน ทำให้ช้าลงไปอีก
รวมทั้ง version ของ library ที่ใช้งานอาจจะไม่ตรงกัน
ดังนั้นแก้ไขด้วยการสร้างทีม migration ขึ้นมาเลย เพื่อจัดการเรื่องนี้โดยตรง
ซึ่ง code ของ service ต่าง ๆ จะเป็นแบบ monorepo
และมีการใช้ automation tool ในขั้นตอนต่าง ๆ ทั้งการ deploy และ rollback เป็นต้น
มี Migration Principles ดังนี้
- Centrally driven migrations that are transparent to service owners ลด overhead ในการทำงานร่วมกัน และลดความเสี่ยงต่าง ๆ ด้วยการสร้างทีมจัดการโดยตรงมาเลย และยังต้องสร้างความชัดเจนไปยังเข้าของ service ต่าง ๆ ด้วย ว่าผลการ migrate/upgrade เป็นอย่างไร กระทบต่อ service หรือไม่
- No downtime ชัดเจนมาก ๆ มิเช่นนั้นจะกระทบต่อ business แน่ ๆ
- Gradual roll forward, quick roll back จะค่อย ๆ ทำการ rollout ออกไป แต่ถ้ามีปัญหาก็สามารถ rollback ได้อย่างรวดเร็ว เพื่อลดผลกระทบที่จะเกิดขึ้น
- 80/20 rule when it comes to automation ในการ migrate/upgrade จำนวนมาก ๆ บบนี้ มีการเปลี่ยนแปลงที่เยอะมาก ๆ ดังนั้นจะทำการสร้าง template ของการเปลี่ยนแปลงขึ้นมา เพื่อให้ง่ายต่อการ automated ซึ่งช่วยลดความเสี่ยงต่าง ๆ ลงไปได้เยอะ
ขั้นตอนการ migrate/upgrade library เป็นดังนี้
ขั้นตอนแรก ในการใช้งาน 3-party library ความมี abstraction layer คั่นก่อนเสมอ
เพื่อลดการผูกมัดกับ library และ ระบบงานลงไป
จะเรียกส่วนนี้ว่า adapter
ขั้นตอนที่สอง ทำการเพิ่มเติม library version ใหม่ในส่วนของ adapter นั่นเอง
พร้อมให้มีการ configuration ให้ใช้ของเก่า หรือ ใหม่ แบบ dynamic ได้
ทำให้มี library ทั้งสอง version อยู่ด้วยกัน
ไม่ต้องทำการ refactor ใด ๆ
ทำให้ง่ายต่อการเปลี่ยน หรือ rollback นั่นเอง โดยไม่ต้อง deploy ใหม่
หัวใจหลัก ๆ ของแนวทางนี้ คือ
ลดการผูกมัดระหว่าง external code กับ application code ให้น้องลง (Loose coupling)
ขั้นตอนต่อมา คือ การจัดการกับ service จำนวนมาก ๆ
สิ่งที่ขาดไม่ได้คือ automation tool นั่นเอง
เมื่อทำการ push code version ใหม่เข้ามา
จะทำการ deploy ไปยังแต่ละ service แบบอัตโนมัติ
ทำการเป็น asynchronous batch job
แต่เมื่อการ deploy มีปัญหา ก็ต้องทำการ rollback ซึ่งใช้งาน
แน่นอนว่า เรื่องของ Monitoring ก็สำคัญมาก ๆ
เพื่อช่วยตรวจสอบว่า หลังจากการ deploy ไปแล้วมีปัญหาหรือไม่
ด้วยการใช้งาน Grafana และ Prometheus
เมื่อเกิดปัญหา หรือ ตาม pattern ที่กำหนดไว้ ก็ทำการ rollback ทันที
ขั้นตอนสุดท้าย เมื่อทำการ migrate/update ตรงเรียบร้อยแล้ว
ทำการลบ code ของ version เก่าทิ้งไปซะ
ลองอ่านในรายละเอียดเพิ่มเติมได้
น่าจะเป็นอีก use case ที่น่าสนใจ
ว่าการ migrate/update library ที่ใช้ก็สำคัญมาก ๆ
Later === Never !!