cd-at-instagram
วันนี้เห็นมีการ share บทความเรื่อง Continuous Deployment at Instagram
เป็นบทความที่อธิบายขั้นตอนการ deploy ระบบงานของ Instagram ว่าเป็นอย่างไร
ดังนั้นจึงทำการแปล และ สรุปส่วนที่น่าสนใจไว้นิดหน่อย
ซึ่งถือว่าเป็นแนวทางหนึ่งของการพัฒนา software ที่ดี
เริ่มกันเลยดีกว่า

ระบบ Instagram นั้น ทำการ deploy code ส่วน backend ประมาณวันละ 30-40 ครั้งต่อวัน

หรือว่าทำทุก ๆ ครั้งเมื่อมีการเปลี่ยนแปลง code ที่ branch master
โดยส่วนใหญ่แล้วจะไม่มีคนเข้าไปมีส่วนร่วมเลย !!
นั่นคือทำงานแบบอัตโนมัตินั่นเอง

เป็นไงล่ะ แค่เริ่มต้นก็ต้องร้อง ว้าววววว กันแล้ว
และทาง Instagram บอกว่า
ด้วยขนาดและการ scale ของระบบนั้น
ต้องการการทำงานในรูปแบบนี้ ซึ่งมันแจ่ม และ เหมาะมาก ๆ

ดังนั้นมาเรียนรู้กันว่า Instagram ทำกันอย่างไร ?

เริ่มด้วยคำถามอีกแล้ว ทำไปทำไม ?

ข้อดีของ Continuous Deployment มีดังนี้

ทำให้ทีมพัฒนาทำงานได้รวดเร็วขึ้น
เนื่องจากสามารถทำการ deploy code ได้บ่อยเท่าที่ต้องการ
ไม่ต้องมารอช่วงเวลา และ จำนวนครั้งที่จำกัดในการ deploy ต่อวัน
ผลที่ตามมาก็คือ ไม่ต้องสูญเสียเวลาไปโดยเปล่าประโยชน์
รวมทั้งค่อย ๆ ทำการเปลี่ยนแปลงระบบไปทีละเล็กละน้อย

ทำให้รู้ว่าแต่ละการเปลี่ยนแปลงมันผิดหรือถูกได้รวดเร็วขึ้น
เนื่องจากทำการ deploy ทุก ๆ การเปลี่ยนแปลง
ทำให้ไม่ต้องมานั่งหาข้อผิดพลาดจากการเปลี่ยนแปลงมากมาย

ดังนั้น ถ้าการเปลี่ยนแปลงไหนผิด ก็จะรู้ได้ทันที
ทำให้สามารถระบุปัญหาได้ทันที และ แก้ไขได้รวดเร็วขึ้น
แนวคิดนี้คือ Fail fast, Break things จริง ๆ

มันคุ้น ๆ ไหม ถ้าการ deploy แต่ละครั้งมีการเปลี่ยนแปลงเยอะ ๆ
การหาข้อผิดพลาดแต่ละเรื่องก็ยากใช่ไหม ?

ทำการสร้างระบบอย่างไร ?

การพัฒนาระบบ Continuous Deployment จะประสบความสำเร็จได้นั้น
มันมาจากหลายปัจจัย
จะสร้างครั้งเดียวให้เสร็จนั้น เป็นไปไม่ได้เลย !!

ดังนั้นวิธีการที่ทำคือ ค่อย ๆ สร้างอย่างยั่งยืน (Iterative approch)
ค่อย ๆ สร้างที่ละส่วนขึ้นมา
จากนั้นดูผลลัพธ์และทำการปรับปรุงให้ดียิ่งขึ้นอย่างสม่ำเสมอ
จนทำให้ได้ระบบ Continuous Deployment ในปัจจุบันขึ้นมาได้

ก่อนที่จะมีระบบ Continuous Deployment นั้น ทำการ deploy อย่างไร ?

นักพัฒนาทุกคนจะทำการ deploy การเปลี่ยนแปลงต่าง ๆ เอง
โดยงานเหล่านี้คืองาน ad-doc หรืองานที่ไม่ได้เตรียมการไว้ล่วงหน้า
ซึ่งจะทำการ run script การ rollout เอง
หรือบางครั้งก็ต้องรอคนอื่น ๆ ที่จะ deploy ด้วย

โดยขั้นตอนแรกทำการ deploy ไปยังเครื่อง production server เพียง 1 ตัว
เพื่อทดสอบว่า การทำงานมันถูกต้องตามที่คาดหวังหรือไม่ ?
ด้วยการ run ระบบ และเข้าไปดู logg ที่ server
ถ้าผลจาก logg ไม่มีข้อผิดพลาดอะไร
ก็จะทำการ deploy ไปยังเครื่องทั้งหมด

โดยระบบ logging ของการ rollout/deploy จะเรียกว่า Sauron
ชื่อคุ้น ๆ ไหม จากเรื่อง The Lord of the Rings นั่นเอง

ปล.
การทดสอบนั้นใช้ traffic จริง ๆ กันเลยนะ

ต่อมาเริ่มมีการเตรียมเครื่อง server สำหรับการทดสอบโดยเฉพาะเรียกว่า Canary server

ทำให้ควบคุมการ deploy และทดสอบได้ง่ายกว่า
แต่การทดสอบเพียงตรวจสอบการ log การทำงานอย่างเดียวมันไม่เพียงพอ
จึงได้เพิ่มให้ทำการ run ชุดการทดสอบ
ซึ่งแต่ก่อนชุดการทดสอบมีอยู่แล้ว
เพียงแต่ถูกทดสอบเฉพาะเครื่องของนักพัฒนาแต่ละคนเท่านั้น

ดังนั้นจึงทำการติดตั้ง และ configuration Jenkins server ขึ้นมา
เพื่อทำการทดสอบในทุก ๆ การเปลี่ยนแปลงที่ branch master
และส่งผลการทดสอบไปยังเครื่อง Sauron

ดังนั้นในตอนนี้เครื่อง Sauron จะรู้ว่า
ในแต่ละการเปลี่ยนแปลงผ่านการทดสอบหรือไม่ ?
ถ้าไม่ผ่านการทดสอบ
การเปลี่ยนแปลงเหล่านั้นก็ไม่ถูกสนใจ หรือนำไป deploy
ส่งผลทำให้การ deploy มีประสิทธิภาพยิ่งขึ้น
คือ ไม่ deploy สิ่งผิด ๆ ขึ้นไป

โดยที่ Facebook นั้น
ใช้ Fabricator สำหรับการทำ code review
ใช้ Sandcastle สำหรับสร้างระบบ Continuous Integration ซึ่งสามารถทำงานร่วมกับ Fabricator ได้
ซึ่ง Sandcastle จะทำการทดสอบทุก ๆ ครั้งที่มีการเปลี่ยนแปลง
และส่งผลการทดสอบของการเปลี่ยนแปลงนั้นออกมา

จากนั้นเริ่มสร้างระบบการทำงานแบบอัตโนมัติขึ้นมา

เมื่อระบบการทำงานรู้แล้วว่า
ในแต่ละการเปลี่ยนแปลงมีสถานะเป็นอย่างไร
ต้องใช้คนมาตัดสินใจว่า จะต้องทำอย่างไรต่อไป
เช่นตัดสินใจว่า ต้องทำการ rollout/deploy การเปลี่ยนแปลงใด

เมื่อผ่านไปสักระยะ จะเริ่มเห็นรูปแบบการทำงาน
และทำการสร้าง algorithm สำหรับตัดสินใจว่า rollout/deploy อะไรบ้างขึ้นมา
โดยรูปแบบที่ได้คือ

  • ต้องผ่านการทดสอบทั้งหมด
  • จำนวนการเปลี่ยนแปลงต้องน้อย ๆ

แต่ถ้ามีจำนวนการเปลี่ยนแปลงที่ผ่านการทดสอบมาก ๆ
จะเลือกมาเพียง 3 การเปลี่ยนแปลงเท่านั้น

จากนั้นจำเป็นต้องมี algorithm สำหรับการตรวจสอบผลการ rollout/deploy ด้วย
ว่าการทำงานมันสำเร็จ หรือ ล้มเหลว
นั่นคือ ถ้ามีเครื่องที่ทำการ deploy ผิดพลาดเกิน 1%
แสดงว่าการ deploy ครั้งนั้นล้มเหลว

ดังนั้นเมื่อระบบบอกว่า การเปลี่ยนแปลง A ต้องทำการ deploy แล้วนะ
ระบบการ deploy จะทำงานแบบอัตโนมัติ ดังนี้

  1. ทำการ deploy การเปลี่ยนแปลง A ไปยัง Canary server
  2. ทำการทดสอบอีกรอบ
  3. ทำการ deploy ไปยังทุก ๆ เครื่อง

โดยในช่วงแรก ๆ นั้นจะมีคนที่มาดูแลการ deploy
แต่เมื่อผ่านไปสักระยะ ก็ไม่จำเป็นต้องมีคนมาดูแลอีกต่อไปแล้ว

แต่เส้นทางนี้ ใช่ว่าจะโรยด้วยกลีบกุหลาบ ปัญหาก็เพียบเช่นกัน !!

โดยมีข้อผิดพลาด และ บกพร่องไปมากมาย อาทิเช่น

การทดสอบที่ผิดพลาดและล่าช้า
นั่นคือ การทดสอบมันผิดพลาดได้ง่าย หรือ ไม่เสถียรนั่นเอง
บางครั้งทดสอบผ่าน บางครั้งทดสอบผิดพลาด
รวมทั้งการทดสอบมันช้า !!
แทนที่ระบบการทำงานจะดี กลับสร้างปัญหาให้อีก
มันขัดแย้งกับข้อดีของ Continuous Deployment เลยนะ

ดังนั้นจึงต้องลงทั้งแรงกายและแรงใจ
เพื่อปรับปรุงให้การทดสอบจากเดิมที่ใช้เวลา 12-15 นาที ให้เหลือเพียง 5 นาที
รวมทั้งแก้ไขระบบ infrastructure เพื่อทำให้ระบบการทดสอบมีความน่าเชื่อถือ และ เสถียรขึ้น

ส่วนเรื่อง backlog ยังอ่านไม่เข้าใจ ขอข้ามไปก่อน !!

มาดูเรื่อง Key Principle หรือแนวคิดของการสร้างกันหน่อยว่ามีอะไรบ้าง ?

1. Tests หรือชุดการทดสอบแบบอัตโนมัติ
ต้องทำงานอย่างรวดเร็ว
มีจำนวน test coverage ที่เหมาะสม ไม่จำเป็นต้อง 100%
เนื่องจากการทดสอบต้องทดสอบอยู่บ่อย ๆ
ทั้งก่อนส่งการเปลี่ยนแปลง
ทั้งระหว่างการทำ code review
ทั้งหลังจากการ deploy

2. Canary
ต้องมี canary server เพื่อป้องกันการ deploy การเปลี่ยนแปลงที่แย่ ๆ ขึ้นไป
แน่นอนว่า ไม่ได้ต้องการการทำงานที่สมบูรณ์แบบ
แต่ต้องการเพียงข้อมูลเชิงสถิติแบบง่าย ๆ
เพื่อช่วยวิเคราะห์ว่า แต่ละการเปลี่ยนแปลงส่งผลกระทบอย่างไร

3. Automate the normal case
เราไม่สามารถให้ทำงานแบบอัตโนมัติได้ทุก ๆ กรณี
ดังนั้น ให้สร้างระบบทำงานแบบอัตโนมัติ
เฉพาะส่วนที่เรารู้ และเป็นกรณีแบบปกติทั่วไป

แต่ถ้ามีเหตุการณ์หรือกรณีอะไรที่ดูแปลก ๆ หรือผิดปกติ
ให้ระบบหยุดการทำงานทันที และให้คนเข้ามาจัดการต่อไป

4. Make people comfortable
ปัญหาเรื่องคน มันคือกำแพงที่ยิ่งใหญ่และใหญ่ยิ่ง
ของการสร้างระบบการทำงานแบบอัตโนมัติ
เนื่องจากคนที่ทำงานอยู่ตรงนั้นก่อนหน้านี้ จะรู้สึกว่า
ตัวเองไม่มีความสำคัญ และ ไม่สามารถควบคุมอะไรเองได้เลย

ดังนั้นสิ่งที่ต้องทำก็คือ
การทำงานของระบบต้องแสดงออกมาให้ทุกคนเห็นอย่างชัดเจน
ว่ามีงานอะไรที่ทำเสร็จไปแล้วบ้าง
ว่ามีงานอะไรที่กำลังทำอยู่บ้าง
ว่าสิ่งที่ทำคืออะไร
เพื่อทำให้เห็นว่า สิ่งต่าง ๆ เหล่านี้มันเข้ามาช่วยนะ

5. Expect bad deploys
ต้องทำการระบุว่าการเปลี่ยนแปลงใดที่มันแย่ ๆ ให้เร็วที่สุด
เพื่อทำให้เราสามารถ rollback ได้รวดเร็ว
นั่นคือลดผลกระทบจากความผิดพลาดนั่นเอง

สิ่งต่าง ๆ เหล่านี้ทุกบริษัทสามารถนำไปสร้างเองได้เลย
โดยที่ระบบ Continuous Deployment ไม่จำเป็นต้องมีความซับซ้อน
ให้เริ่มจากวิธีการที่ง่าย ๆ เน้นทำตามแนวคิดทั้ง 5 ข้อ
เพื่อทำการแก้ไข และ ปรับปรุงกันต่อไป

สุดท้ายแล้วระบบ Continuous Deployment ของ Instagram ยังคงพัฒนาต่อไป

แน่นอนว่าในตอนนี้ ระบบมันยังทำงานได้ดี และ เหมาะสมสำหรับสถานะปัจจุบันของระบบ
แต่ก็ยังมีสิ่งต่าง ๆ มากมายที่ต้องทำการปรับปรุง ดังนี้

Keeping it fast
เนื่องจากระบบของ Instgram มันโตขึ้นสูงมาก ๆ
ทำให้จำนวนการเปลี่ยนแปลงสูงมากเช่นเดียวกัน
ดังนั้นต้องการให้ระบบ rollout/deploy ให้เร็วที่สุดเท่าที่จะทำได้

วิธีการหนึ่งที่น่าจะเอาเข้ามาทำคือ
การแบ่งการ rollout/deploy ออกเป็นหลาย ๆ สถานะ
และสร้าง pipeline ของการทำงานขึ้นมา

Adding canary
เนื่องจากนำนวนการเปลี่ยนแปลงสูงขึ้น
เครื่อง canary ก็ได้กลายเป็นปัญหาคอขวด
ดังนั้นการเพิ่มเครื่อง canary จึงมีความสำคัญมาก

More data
สิ่งที่ต้องการคือ ข้อมูล
เพื่อทำให้ระบบรู้ว่า การเปลี่ยนแปลงใด ๆ มันแย่ได้ดีขึ้น
เพื่อขจัดสิ่งที่แย่ ๆ ออกไปจากสายการ rollout/deploy
เช่น logging การทำงานของแต่ละ feature กันไปเลย

Improving detection
ทำการปรับปรุงการตรวจสอบหลังจากทำการ rollout/deploy ออกไปแล้ว
แทนที่จะทำเพียงการทดสอบ และ deploy ไปทุก ๆ เครื่อง
ก็น่าจะทำการแบ่งการ deploy ออกเป็น region หรือ cluster
จากนั้นทำการตรวจสอบและตัดสินใจว่า จะทำการ deploy ต่อไปหรือไม่

เป็นอย่างไรบ้างสำหรับระบบ Continuous Deployment ของ Instagram

น่าจะพอทำให้เห็นว่า
การ rollout/deploy ทุก ๆ การเปลี่ยนแปลง
มันเป็นเรื่องที่เป็นไปได้
และช่วยลดความเสี่ยงจากข้อผิดพลาดต่าง ๆ ด้วยสิ
อะไรที่มันเจ็บก็ให้ทำบ่อย ๆ กันนะครับ
ต้องสร้างระบบขึ้นมา โดยมีพื้นฐานอยู่บนสิ่งที่เรียกว่า คุณภาพ
และความไว้เนื้อเชื่อใจกันนั่นเอง
รวมทั้งต้องค่อย ๆ สร้างขึ้นมาและเรียนรู้ไปกับมัน

แต่คำถามที่น่าจะอยู่ในใจของใครหลาย ๆ คนคือ
แล้วแต่ละการเปลี่ยนแปลงมันเป็นอย่างไร ?
เป็น feature ?
เป็น bug ?
เป็น ….

ผมก็ไม่รู้เหมือนกัน แต่เชื่อว่าแต่ละการเปลี่ยนแปลงต้องมีคุณค่าสิ !!