12
AUTOMATE AND ENABLE LOW-RISK RELEASES (ทำให้การปล่อยซอฟต์แวร์มีความเสี่ยงต่ำและเป็นอัตโนมัติ)
C huck Rossi เป็น director of release engineering ของ Facebook มาถึงสิบปี หนึ่งในความรับผิดชอบของเขาคือการดูแลการ push โค้ดในแต่ละวัน ในปี 2012 Rossi ได้อธิบายกระบวนการของพวกเขาไว้ดังนี้:
เริ่มตั้งแต่ประมาณบ่ายโมง PM ผมจะสลับไปที่ "โหมดปฏิบัติการ" และทำงานร่วมกับทีมเพื่อเตรียมพร้อมที่จะปล่อยการเปลี่ยนแปลงที่จะส่งไปยัง Facebook.com ในวันนั้น นี่คือส่วนที่เครียดที่สุดของงานและต้องพึ่งพาการตัดสินใจและประสบการณ์ของทีมอย่างมาก เราทำงานเพื่อให้แน่ใจว่าทุกคนที่มีการเปลี่ยนแปลงที่จะปล่อยออกไปได้รับการติดตาม และกำลังทดสอบและสนับสนุนการเปลี่ยนแปลงของตนอย่างแข็งขัน 1
ก่อนการ push ขึ้น production นักพัฒนาทุกคนที่มีการเปลี่ยนแปลงต้องมาอยู่พร้อมหน้าและเช็กอินในช่อง IRC chat—นักพัฒนาที่ไม่อยู่จะถูกนำการเปลี่ยนแปลงออกจาก deployment package โดยอัตโนมัติ 2 Rossi กล่าวต่อ "ถ้าทุกอย่างดูดีและ test dashboards รวมถึง canary tests * เป็นสีเขียว เราก็กดปุ่มใหญ่สีแดง และ Facebook.com ทั้งเซิร์ฟเวอร์ฟลีตก็จะได้รับโค้ดใหม่ส่งไป ภายในยี่สิบนาที เครื่องนับพัน ๆ เครื่องก็จะรันบนโค้ดใหม่โดยไม่มีผลกระทบที่เห็นได้ชัดต่อผู้ใช้ที่กำลังใช้งานเว็บไซต์" 3 †
ต่อมาในปีเดียวกัน Rossi ก็เพิ่มความถี่ในการปล่อยซอฟต์แวร์เป็นสองเท่าต่อวัน 4 เขาอธิบายว่าการ push โค้ดรอบที่สองช่วยให้วิศวกรที่ไม่ได้อยู่ฝั่ง West Coast ของสหรัฐฯ สามารถ "เคลื่อนไหวและปล่อยงานได้เร็วเท่ากับวิศวกรคนอื่น ๆ ในบริษัท" และยังเปิดโอกาสให้ทุกคนมีโอกาสครั้งที่สองในแต่ละวันในการ ship โค้ดและเปิดตัวฟีเจอร์ต่าง ๆ 5
Figure 12.1: จำนวนนักพัฒนาที่ Deploy ต่อสัปดาห์ที่ Facebook
Source: Chuck Rossi, "Ship early and ship twice as often."
Kent Beck ผู้สร้าง methodology แบบ Extreme Programming (XP) หนึ่งในผู้สนับสนุนหลักของ Test-Driven Development และ technical coach ที่ Facebook ได้ให้ความเห็นเพิ่มเติมเกี่ยวกับกลยุทธ์การปล่อยโค้ดของพวกเขาในบทความที่โพสต์บนหน้า Facebook ของเขา:
Chuck Rossi สังเกตว่าดูเหมือนจะมีจำนวนการเปลี่ยนแปลงคงที่ที่ Facebook สามารถจัดการได้ใน deployment ครั้งเดียว ถ้าเราต้องการให้มีการเปลี่ยนแปลงมากขึ้น เราก็ต้องมี deployment มากขึ้น สิ่งนี้นำไปสู่การเพิ่มความเร็วในการ deployment อย่างต่อเนื่องในช่วงห้าปีที่ผ่านมา จากรายสัปดาห์เป็นรายวันเป็นสามครั้งต่อวันสำหรับการ deploy โค้ด PHP และจากรอบหกสัปดาห์เป็นสี่สัปดาห์เป็นสองสัปดาห์สำหรับการ deploy แอปมือถือ การปรับปรุงนี้ขับเคลื่อนโดยทีม release engineering เป็นหลัก 6
การใช้ continuous integration และทำให้การ deploy โค้ดเป็นกระบวนการที่มีความเสี่ยงต่ำ ทำให้ Facebook สามารถทำให้การ deploy โค้ดเป็นส่วนหนึ่งของงานประจำวันของทุกคนและรักษา productivity ของนักพัฒนาไว้ได้ สิ่งนี้ต้องการให้การ deploy โค้ดเป็นไปโดยอัตโนมัติ ทำซ้ำได้ และคาดเดาได้ ในแนวทางปฏิบัติที่อธิบายไว้ในหนังสือจนถึงตอนนี้ แม้ว่าโค้ดและ environment ของเราจะถูกทดสอบร่วมกันแล้ว แต่ส่วนใหญ่แล้วเรายังไม่ได้ deploy ขึ้น production บ่อยนัก เพราะการ deploy เป็นงานที่ทำด้วยมือ ใช้เวลานาน เจ็บปวด น่าเบื่อ และมีโอกาสผิดพลาดสูง และมักเกี่ยวข้องกับการส่งต่องานที่ยุ่งยากและไม่น่าเชื่อถือระหว่าง Development และ Operations
และเพราะว่ามันเจ็บปวด เราจึงมักจะทำมันน้อยลงเรื่อย ๆ ส่งผลให้เกิดวงจรขาลงที่เสริมกันเองอีกครั้ง การเลื่อน deployment ขึ้น production ออกไปทำให้เราสะสมความแตกต่างระหว่างโค้ดที่จะ deploy กับสิ่งที่รันอยู่ใน production มากขึ้นเรื่อย ๆ ทำให้ deployment batch size เพิ่มขึ้น เมื่อ deployment batch size โตขึ้น ความเสี่ยงของผลลัพธ์ที่ไม่คาดคิดจากการเปลี่ยนแปลงก็เพิ่มขึ้นตามไปด้วย รวมถึงความยากในการแก้ไขก็เพิ่มขึ้นเช่นกัน
ในบทนี้ เราจะลด friction ที่เกี่ยวข้องกับการ deployment ขึ้น production เพื่อให้แน่ใจว่าสามารถทำได้บ่อยและง่าย ไม่ว่าจะโดย Operations หรือ Development โดยการขยาย deployment pipeline ของเรา
แทนที่จะทำแค่การ integrate โค้ดของเราอย่างต่อเนื่องใน environment ที่คล้าย production เราจะทำให้สามารถ promote build ใดก็ตามที่ผ่านกระบวนการ automated test และ validation ของเรา ขึ้นไปยัง production ได้ ไม่ว่าจะเป็นแบบ on demand (เช่น กดปุ่ม) หรือโดยอัตโนมัติ (เช่น build ที่ผ่านการทดสอบทั้งหมดจะถูก deploy โดยอัตโนมัติ)
เนื่องจากมีแนวทางปฏิบัติจำนวนมากที่นำเสนอ จึงมีเชิงอรรถมากมายพร้อมตัวอย่างและข้อมูลเพิ่มเติมโดยไม่รบกวนการนำเสนอแนวคิดในบทนี้
Automate Our Deployment Process (ทำให้กระบวนการ Deployment ของเราเป็นอัตโนมัติ)
การจะได้ผลลัพธ์แบบที่ Facebook ทำได้นั้น เราจำเป็นต้องมีกลไกอัตโนมัติที่ deploy โค้ดของเราขึ้น production โดยเฉพาะอย่างยิ่งถ้าเรามีกระบวนการ deployment ที่มีมาหลายปีแล้ว เราต้องบันทึกขั้นตอนต่าง ๆ ในกระบวนการ deployment อย่างละเอียด เช่น ในแบบฝึกหัด value stream mapping ซึ่งเราสามารถรวบรวมใน workshop หรือบันทึกแบบ incremental ก็ได้ (เช่น ใน wiki)
เมื่อเรามีกระบวนการที่บันทึกไว้แล้ว เป้าหมายของเราคือการทำให้ขั้นตอนที่ทำด้วยมือนั้นง่ายขึ้นและเป็นอัตโนมัติให้มากที่สุด เช่น:
• การแพ็กเกจจิ้งโค้ดในรูปแบบที่เหมาะสมสำหรับการ deploy
• การสร้าง preconfigured virtual machine images หรือ containers
• การทำให้การ deploy และ configuration ของ middleware เป็นอัตโนมัติ
• การคัดลอก packages หรือไฟล์ไปยัง production servers
• การ restart servers, applications หรือ services
• การสร้าง configuration files จาก templates
• การรัน automated smoke tests เพื่อให้แน่ใจว่าระบบทำงานได้และได้รับการ configure อย่างถูกต้อง
• การรัน testing procedures
• การเขียนสคริปต์และทำให้ database migrations เป็นอัตโนมัติ
เมื่อเป็นไปได้ เราจะ re-architect เพื่อตัดขั้นตอนที่ไม่จำเป็นออก โดยเฉพาะขั้นตอนที่ใช้เวลานาน เรายังต้องการลดไม่เพียงแต่ lead time แต่ยังรวมถึงจำนวนการส่งต่องานให้มากที่สุด เพื่อลดข้อผิดพลาดและการสูญเสียความรู้
การให้ developers โฟกัสที่การทำให้กระบวนการ deployment เป็นอัตโนมัติและปรับให้เหมาะสม สามารถนำไปสู่การปรับปรุงที่สำคัญใน deployment flow เช่น การทำให้การเปลี่ยนแปลง application configuration เล็ก ๆ ไม่ต้องมี deployment หรือ environment ใหม่ ๆ อย่างไรก็ตาม สิ่งนี้ต้องการให้ Development ทำงานใกล้ชิดกับ Operations เพื่อให้แน่ใจว่าเครื่องมือและกระบวนการที่เราสร้างร่วมกันนั้นสามารถใช้งานต่อ downstream ได้ แทนที่จะทำให้ Operations รู้สึกถูกกันออกไปหรือเป็นการ reinventing the wheel
เครื่องมือมากมายที่ให้ความสามารถด้าน continuous integration และ testing ก็รองรับการขยาย deployment pipeline เช่นกัน เพื่อให้ build ที่ผ่านการ validate แล้วสามารถถูก promote ขึ้น production ได้ โดยทั่วไปหลังจากผ่าน production acceptance tests (เช่น CircleCI, Jenkins Build Pipeline plugin, Go.cd, Microsoft Visual Studio Team Services และ Pivotal Concourse)
ข้อกำหนดสำหรับ deployment pipeline ของเราได้แก่:
• Deploying the same way to every environment (การ deploy ด้วยวิธีเดียวกันในทุก environment): การใช้กลไก deployment เดียวกันกับทุก environment (เช่น development, test และ production) จะทำให้การ deploy ขึ้น production มีโอกาสสำเร็จสูงขึ้นมาก เพราะเรารู้ว่ามันถูกดำเนินการสำเร็จหลายครั้งแล้วใน pipeline ก่อนหน้านี้
• Smoke testing our deployments (การทำ smoke testing สำหรับ deployment ของเรา): ในระหว่างกระบวนการ deployment เราควรทดสอบว่าเราสามารถเชื่อมต่อกับระบบสนับสนุนต่าง ๆ (เช่น databases, message buses, external services) และรัน single test transaction ผ่านระบบเพื่อให้แน่ใจว่าระบบของเราทำงานตามที่ออกแบบไว้ ถ้าการทดสอบใดล้มเหลว เราควรทำให้ deployment ล้มเหลว
• Ensure we maintain consistent environments (การรักษาความสอดคล้องของ environment): ในขั้นตอนก่อนหน้านี้ เราสร้าง single-step environment build process เพื่อให้ environment development, test และ production มี build mechanism ร่วมกัน เราต้องมั่นใจอยู่เสมอว่า environment เหล่านี้ยังคง sync กันอยู่
แน่นอนว่าเมื่อเกิดปัญหาใด ๆ ระหว่าง deployment เราจะดึง Andon cord และรวมตัวกันแก้ไขปัญหาจนกว่าจะเรียบร้อย เช่นเดียวกับที่เราทำเมื่อ deployment pipeline ของเราล้มเหลวในขั้นตอนก่อนหน้านี้
CASE STUDY (กรณีศึกษา)
Daily Deployments at CSG International (2013) (การ Deploy รายวันที่ CSG International)
CSG International คือผู้ให้บริการ SaaS-based customer care และ billing รายใหญ่ที่สุดในอเมริกาเหนือ โดยมีสมาชิกกว่า 65 ล้านราย และ tech stack ที่ครอบคลุมตั้งแต่ Java ไปจนถึง mainframe 7 Scott Prugh, Chief Architect และ VP of Development นำความพยายามในการปรับปรุงความสามารถในการคาดเดาและความน่าเชื่อถือของการปล่อยซอฟต์แวร์ เพื่อให้บรรลุเป้าหมายนี้ พวกเขาเพิ่มความถี่ในการปล่อยจากปีละสองครั้งเป็นปีละสี่ครั้ง (ลด deployment interval จาก 28 สัปดาห์เหลือ 14 สัปดาห์) 8
แม้ว่าทีม Development จะใช้ continuous integration เพื่อ deploy โค้ดขึ้น test environments ทุกวัน แต่การปล่อยขึ้น production ยังคงดำเนินการโดยทีม Operations Prugh สังเกตว่า
มันเหมือนกับว่าเรามี "ทีมซ้อม" ที่ซ้อมทุกวัน (หรือบ่อยกว่านั้น) ใน test environments ที่มีความเสี่ยงต่ำ ทำให้กระบวนการและเครื่องมือของพวกเขาสมบูรณ์แบบ แต่ทีม "เกมจริง" ของเราใน production ได้โอกาสในการซ้อมน้อยมาก แค่ปีละสองครั้ง แถมยังต้องซ้อมใน production environments ที่มีความเสี่ยงสูง ซึ่งมักจะแตกต่างจาก pre-production environments อย่างมากและมีข้อจำกัดที่แตกต่างกัน—development environments ขาดทรัพยากร production หลายอย่าง เช่น security, firewalls, load balancers และ SAN [storage area network] 9
เพื่อแก้ปัญหานี้ พวกเขาจึงสร้าง Shared Operations Team (SOT) ที่รับผิดชอบในการจัดการทุก environment (development, test, production) โดยทำการ deploy ทุกวันใน environment development และ test รวมถึงทำ production deployments และ releases ทุก 14 สัปดาห์ เนื่องจาก SOT ทำการ deploy ทุกวัน ปัญหาใดที่พวกเขาพบและไม่ได้รับการแก้ไขก็จะเกิดขึ้นอีกในวันถัดไป สิ่งนี้สร้างแรงจูงใจมหาศาลในการ automate ขั้นตอน manual ที่น่าเบื่อหรือมีโอกาสผิดพลาด และแก้ไขปัญหาที่อาจเกิดขึ้นซ้ำได้ เนื่องจากการ deploy ถูกดำเนินการเกือบ 100 ครั้งก่อนการปล่อยขึ้น production ปัญหาส่วนใหญ่จึงถูกพบและแก้ไขก่อนหน้านั้นนานแล้ว 10
การทำเช่นนี้เผยให้เห็นปัญหาที่ก่อนหน้านี้มีแต่ทีม Ops เท่านั้นที่ประสบ ซึ่งกลายเป็นปัญหาที่ value stream ทั้งหมดต้องร่วมกันแก้ไข การ deploy รายวันทำให้มี feedback รายวันว่าแนวทางปฏิบัติใดใช้ได้ผลและไม่ได้ผล 11
พวกเขายังโฟกัสที่การทำให้ทุก environment ดูคล้ายคลึงกันมากที่สุด รวมถึงสิทธิ์การเข้าถึงด้านความปลอดภัยและ load balancers Prugh เขียนว่า "เราทำให้ non-production environments มีความคล้ายคลึงกับ production มากที่สุด และเราพยายามเลียนแบบข้อจำกัดของ production ในหลาย ๆ ด้านเท่าที่จะทำได้ การได้สัมผัสกับ production-class environments ตั้งแต่เนิ่น ๆ ช่วยปรับเปลี่ยนการออกแบบสถาปัตยกรรมให้เป็นมิตรมากขึ้นในสภาพแวดล้อมที่มีข้อจำกัดหรือแตกต่างเหล่านี้ ทุกคนฉลาดขึ้นจากแนวทางนี้" 12
Prugh ยังสังเกตว่า:
เราพบหลายกรณีที่การเปลี่ยนแปลง database schemas นั้น 1) ถูกส่งต่อไปให้ทีม DBA เพื่อให้พวกเขา "ไปคิดเอาเอง" หรือ 2) automated tests ที่รันบนชุดข้อมูลขนาดเล็กเกินจริง (เช่น "ระดับ 100 MB เทียบกับ 100 GB") ซึ่งนำไปสู่ความล้มเหลวใน production ในวิธีการทำงานแบบเก่าของเรา สิ่งนี้จะกลายเป็นเกมโทษกันดึกดื่นระหว่างทีมเพื่อพยายามแก้ไขความยุ่งเหยิง
เราสร้างกระบวนการ development และ deployment ที่ขจัดความจำเป็นในการส่งต่องานให้ DBAs โดยการ cross-training developers, automating schema changes และดำเนินการทุกวัน เราสร้าง realistic load testing กับ sanitized customer data โดยพยายามรัน migrations ทุกวัน ด้วยการทำเช่นนี้ เรารัน service ของเราหลายร้อยครั้งด้วยสถานการณ์ที่สมจริงก่อนที่จะเจอ production traffic จริง 13 ‡
ผลลัพธ์ของพวกเขาน่าทึ่งมาก การทำ daily deployments และเพิ่มความถี่ในการปล่อย production เป็นสองเท่า ทำให้จำนวน production incidents ลดลง 91%, MTTR ลดลง 80% และ deployment lead time ที่จำเป็นสำหรับ service ในการรันใน production ใน "สถานะที่ไม่ต้องใช้มือแตะเลย" ลดลงจาก 14 วันเหลือ 1 วัน 15
Prugh รายงานว่า deployment กลายเป็นเรื่องปกติจนทีม Ops เล่น video games ภายในสิ้นวันแรก นอกจากนี้ การ deploy ราบรื่นขึ้นทั้งสำหรับ Dev และ Ops และ 50% ของเวลาที่ลูกค้าได้รับคุณค่าเร็วขึ้นครึ่งหนึ่ง 16
Figure 12.2: Daily Deployments at CSG International (การ Deploy รายวันที่ CSG International)
การ deploy รายวันและการเพิ่มความถี่ในการปล่อยส่งผลให้จำนวน production incidents และ MTTR ลดลง
Source: "DOES15 - Scott Prugh & Erica Morrison—Conway & Taylor Meet the Strangler (v2.0)," YouTube video, 29:39, posted by DevOps Enterprise Summit, November 5, 2015, https://www.youtube.com/watch?v=tKdIHCL0DUg .
กรณีศึกษานี้ชี้ให้เห็นว่าการ deploy ที่บ่อยขึ้นนั้นดีต่อ Development, QA, Operations และลูกค้า การ deploy ที่บ่อยขึ้นช่วยให้ปัญหาถูกระบุได้เร็วขึ้น สร้างแรงจูงใจให้ทีมแก้ไขข้อผิดพลาดเร็วขึ้น และนำไปสู่การส่งมอบโค้ดที่สะอาดและเร็วกว่า
Enable Automated Self-Service Deployments (เปิดใช้งานการ Deploy แบบ Self-Service อัตโนมัติ)
ลองพิจารณาคำพูดของ Tim Tischler, Director of Operations Automation ที่ Nike, Inc. ซึ่งบรรยายประสบการณ์ทั่วไปของ developer รุ่นหนึ่งว่า "ในฐานะ developer ไม่มีช่วงเวลาไหนในอาชีพที่ทำให้ผมพอใจมากกว่าตอนที่ผมเขียนโค้ด ตอนที่ผมกดปุ่ม deploy มัน ตอนที่ผมเห็น production metrics ยืนยันว่ามันทำงานได้จริงใน production และตอนที่ผมสามารถแก้ไขมันเองได้ถ้ามันไม่ทำงาน" 17
ความสามารถของ developers ที่จะ self-deploy โค้ดขึ้น production เพื่อดูลูกค้ามีความสุขเมื่อฟีเจอร์ของพวกเขาทำงานได้ และเพื่อแก้ไขปัญหาได้อย่างรวดเร็วโดยไม่ต้องเปิด ticket ไปหา Operations ลดน้อยลงในช่วงทศวรรษที่ผ่านมา ส่วนหนึ่งเป็นผลมาจากความจำเป็นในการควบคุมและกำกับดูแล ซึ่งอาจขับเคลื่อนโดยข้อกำหนดด้านความปลอดภัยและการปฏิบัติตามข้อกำหนด
แนวทางปฏิบัติทั่วไปที่เกิดขึ้นคือการให้ Operations เป็นผู้ดำเนินการ deploy โค้ด เนื่องจากนี่คือการ implement หลักการ separation of duties ซึ่งเป็นแนวทางที่ยอมรับอย่างกว้างขวางในการลดความเสี่ยงของ production outages และการทุจริต โดยกำหนดว่าไม่มีบุคคลใดมี control แบบ end-to-end เหนือกระบวนการ เช่น การส่งมอบซอฟต์แวร์ อย่างไรก็ตาม งานวิจัยของ DORA แสดงให้เห็นว่าเราสามารถปรับปรุงประสิทธิภาพการส่งมอบซอฟต์แวร์ได้อย่างมีนัยสำคัญผ่านการ implement separation of duties ด้วยการ code review ในการ implement นี้ เรากำหนดให้ developer คนอื่นต้องตรวจสอบและอนุมัติทุกการเปลี่ยนแปลงโค้ด 18
การ implement นี้มีประสิทธิภาพมากขึ้นอย่างมากเมื่อเสริมด้วย automated test suite ที่ต้องผ่านก่อนที่จะส่งการเปลี่ยนแปลงได้ จากนั้น deployment ทั้งหมดจะถูกดำเนินการแบบ self-service ผ่านระบบอัตโนมัติที่ตรงตามข้อกำหนดที่อธิบายในหัวข้อถัดไป
เมื่อมีเป้าหมายร่วมกันที่ครอบคลุมทั้ง Development และ Operations และมีความโปร่งใส ความรับผิดชอบ และการรับผิดชอบต่อผลลัพธ์ของการ deploy ไม่สำคัญว่าใครจะเป็นคน deploy จริง ๆ แล้ว เราอาจให้บทบาทอื่น ๆ เช่น tester หรือ project manager สามารถ deploy ขึ้นบาง environment ได้เพื่อให้พวกเขาทำงานของตัวเองได้เร็วขึ้น เช่น การตั้งค่าโชว์ฟีเจอร์เฉพาะใน test หรือ UAT environments
เพื่อให้เกิด fast flow ได้ดีขึ้น เราต้องการกระบวนการ promote โค้ดที่สามารถทำได้โดยทั้ง Development หรือ Operations โดย ideally ไม่มีขั้นตอน manual หรือการส่งต่องาน ซึ่งส่งผลต่อขั้นตอนต่อไปนี้:
• Build (การสร้าง): Deployment pipeline ของเราต้องสร้าง packages จาก version control ที่สามารถ deploy ไปยัง environment ใดก็ได้ รวมถึง production
• Test (การทดสอบ): ใครก็ควรจะสามารถรัน automated test suite ทั้งหมดหรือบางส่วนได้บน workstation ของตนเองหรือบน test systems
• Deploy (การ deploy): ใครก็ควรจะสามารถ deploy packages เหล่านี้ไปยัง environment ใดก็ได้ที่พวกเขามีสิทธิ์ โดยการรัน scripts ที่ถูก check-in ไว้ใน version control เช่นกัน
Integrate Code Deployment into the Deployment Pipeline (ผสานการ Deploy โค้ดเข้ากับ Deployment Pipeline)
เมื่อกระบวนการ deploy โค้ดเป็นอัตโนมัติแล้ว เราสามารถทำให้มันเป็นส่วนหนึ่งของ deployment pipeline ดังนั้นระบบ deployment automation ของเราต้องมีความสามารถดังต่อไปนี้:
• ทำให้แน่ใจว่า packages ที่สร้างระหว่าง continuous integration process นั้นเหมาะสมสำหรับการ deploy ขึ้น production
• แสดงความพร้อมของ production environments ได้อย่างรวดเร็ว
• มีวิธีการแบบ push-button, self-service สำหรับ version ใดก็ตามของ packaged code ที่เหมาะสม เพื่อ deploy ขึ้น production
• บันทึกโดยอัตโนมัติเพื่อวัตถุประสงค์ในการ audit และ compliance ว่าคำสั่งใดถูกเรียกใช้บนเครื่องใด เมื่อใด ใครเป็นผู้อนุมัติ และ output คืออะไร รวมถึงบันทึก hash ของ binaries ทั้งหมดที่ deploy และ version ของ source control ที่ใช้สำหรับข้อมูล configuration และ scripts ทั้งหมด
• รัน smoke test เพื่อให้แน่ใจว่าระบบทำงานได้อย่างถูกต้อง และการตั้งค่า configuration (รวมถึงสิ่งต่าง ๆ เช่น database connection strings) ถูกต้อง
• ให้ feedback ที่รวดเร็วแก่ผู้ deploy เพื่อให้พวกเขาสามารถระบุได้อย่างรวดเร็วว่า deployment สำเร็จหรือไม่ (เช่น deployment สำเร็จหรือไม่, application ทำงานตามที่คาดหวังใน production หรือไม่)
เป้าหมายของเราคือทำให้ deployment รวดเร็ว—เราไม่ต้องการรอเป็นชั่วโมงเพื่อรู้ว่า deployment โค้ดสำเร็จหรือล้มเหลว แล้วต้องใช้เวลาอีกหลายชั่วโมงในการ deploy การแก้ไขโค้ดที่จำเป็น ตอนนี้เรามีเทคโนโลยีเช่น containers แล้ว ทำให้สามารถทำ deployment ที่ซับซ้อนที่สุดให้เสร็จภายในไม่กี่วินาทีหรือไม่กี่นาที
ใน DORA's 2019 State of DevOps Report ข้อมูลแสดงให้เห็นว่าผู้ที่มีผลงานระดับ elite สามารถ deploy ได้ตามต้องการ โดยมี deployment lead time วัดเป็นนาทีหรือชั่วโมง ในขณะที่ผู้ที่มีผลงานต่ำที่สุดมี deployment lead time วัดเป็นเดือน ในช่วงหลายปีที่ผ่านมา สถิติการ deployment หลายอย่างดีขึ้น โดยรายงาน Puppet Labs' 2014 State of DevOps Report แสดงให้เห็นว่าผู้ที่มีผลงานสูงโดยทั่วไป deploy โค้ดภายใน 1 ชั่วโมงถึง 1 วัน และผู้ที่มีผลงานต่ำที่สุดมี lead time 6 เดือนขึ้นไป ดังที่นำเสนอในหนังสือรุ่นแรก 19
ด้วยการสร้างความสามารถนี้ ตอนนี้เรามีปุ่ม "deploy code" ที่ช่วยให้เราสามารถ promote การเปลี่ยนแปลงโค้ดและ environment ของเราขึ้น production ได้อย่างปลอดภัยและรวดเร็วผ่าน deployment pipeline
Figure 12.3: Elite and High Performers Achieve Faster Deployment Lead Times and MTTR (2019) (ผู้ที่มีผลงานระดับ Elite และสูงมี Deployment Lead Time และ MTTR ที่เร็วกว่า) §
Source: Forsgren, et. al., Accelerate: State of DevOps Report , 2019.
CASE STUDY (กรณีศึกษา)
Etsy—Self-Service Developer Deployment: An Example of Continuous Deployment (2014) (Etsy—การ Deploy แบบ Self-Service ของนักพัฒนา: ตัวอย่างของ Continuous Deployment)
ไม่เหมือนที่ Facebook ที่ deployment ถูกจัดการโดย release engineers ที่ Etsy การ deploy ดำเนินการโดยใครก็ได้ที่ต้องการ deploy เช่น Development, Operations หรือ Infosec กระบวนการ deploy ที่ Etsy กลายเป็นเรื่องที่ปลอดภัยและเป็นกิจวัตรจนวิศวกรใหม่สามารถทำ production deployment ในวันแรกที่ทำงานได้ กรรมการของ Etsy และแม้แต่สุนัขก็เคย deploy ขึ้น production มาแล้ว! 20
ตามที่ Noah Sussman, test architect ที่ Etsy เขียนไว้ว่า "พอถึงเวลา 8 โมงเช้าในวันทำงานปกติ คน 15 คนและสุนัขก็เริ่มเข้าแถวรอ โดยทุกคนคาดหวังว่าจะได้ deploy รวมกันมากถึง 25 changesets ก่อนวันจะจบ" 21
วิศวกรที่ต้องการ deploy โค้ดของตนไปที่ chat room ก่อน ซึ่งวิศวกรจะเพิ่มตัวเองเข้าไปใน deploy queue ดูกิจกรรม deployment ที่กำลังดำเนินการ ดูว่าใครอยู่ในคิวบ้าง ประกาศกิจกรรมของตน และขอความช่วยเหลือจากวิศวกรคนอื่นเมื่อต้องการ เมื่อถึงคิวของวิศวกร พวกเขาจะได้รับการแจ้งเตือนใน chat room 22
เป้าหมายที่ Etsy คือการทำให้การ deploy ขึ้น production เป็นเรื่องง่ายและปลอดภัย ด้วยจำนวนขั้นตอนน้อยที่สุดและพิธีการน้อยที่สุด ก่อนที่ developer จะ check-in โค้ดด้วยซ้ำ พวกเขามักจะรัน unit tests ทั้งหมด 4,500 ข้อบน workstation ซึ่งใช้เวลาไม่ถึงหนึ่งนาที การเรียกไปยังระบบภายนอกทั้งหมด เช่น databases ถูก stub ไว้ 23
หลังจากที่พวกเขา check-in การเปลี่ยนแปลงลง trunk ใน version control แล้ว automated trunk tests กว่า 7,000 ข้อจะถูกรันทันทีบน CI servers Sussman เขียนว่า "จากการลองผิดลองถูก เราพบว่าประมาณ 11 นาทีคือเวลาที่ยาวนานที่สุดที่ automated tests จะใช้ได้ระหว่างการ push โดยเหลือเวลาให้รัน tests อีกครั้งระหว่าง deployment [ถ้ามีคนทำอะไรพังและต้องแก้ไข] โดยไม่เกินขีดจำกัด 20 นาที" 24
ถ้า tests ทั้งหมดถูกรันแบบ sequential Sussman กล่าวว่า "การ tests trunk 7,000 ข้อจะใช้เวลาประมาณครึ่งชั่วโมงในการดำเนินการ ดังนั้นเราจึงแบ่ง tests เหล่านี้ออกเป็น subsets และกระจายไปยัง 10 เครื่องใน Jenkins [CI] cluster ของเรา... การแบ่ง test suite และรันหลาย tests แบบ parallel ทำให้เราได้ runtime 11 นาทีตามที่ต้องการ" 25
การทดสอบถัดไปคือ smoke tests ซึ่งเป็นการทดสอบระดับระบบที่ใช้ cURL เพื่อรัน PHPUnit test cases หลังจากการทดสอบเหล่านี้ ก็จะมีการรัน functional tests ซึ่งเป็นการทดสอบแบบ end-to-end GUI-driven บน live server—server นี้คือ QA environment หรือ staging environment (มีชื่อเล่นว่า "Princess") ซึ่งจริง ๆ แล้วคือ production server ที่ถูกดึงออกจากรอบการให้บริการ เพื่อให้แน่ใจว่ามันตรงกับ production environment ทุกประการ
เมื่อถึงคิวของวิศวกรที่จะ deploy Erik Kastner เขียนว่า "คุณไปที่ Deployinator [เครื่องมือที่พัฒนาภายใน ดู Figure 12.4 ] และกดปุ่มเพื่อส่งขึ้น QA จากนั้นมันจะไปที่ Princess... เมื่อมันพร้อมที่จะขึ้นจริง คุณกดปุ่ม 'Prod' และเร็ว ๆ นี้โค้ดของคุณก็จะขึ้น live และทุกคนใน IRC [chat channel] จะรู้ว่าใคร push โค้ดอะไร พร้อมลิงก์ไปยัง diff สำหรับคนที่ไม่ได้อยู่ใน IRC ก็จะมีอีเมลที่ทุกคนได้รับพร้อมข้อมูลเดียวกัน" 26
Figure 12.4: The Deployinator Console at Etsy (คอนโซล Deployinator ที่ Etsy)
Source: Erik Kastner, "Quantum of Deployment," CodeasCraft.com , May 20, 2010, https://codeascraft.com/2010/05/20/quantum-of-deployment/ .
ในปี 2009 กระบวนการ deploy ที่ Etsy เป็นสาเหตุของความเครียดและความกลัว ภายในปี 2011 มันกลายเป็นการดำเนินการที่เป็นกิจวัตร เกิดขึ้น 25 ถึง 50 ครั้งต่อวัน ช่วยให้วิศวกรนำโค้ดของตนขึ้น production ได้อย่างรวดเร็ว ส่งมอบคุณค่าให้ลูกค้า
การทำให้กระบวนการ deploy ส่วนใหญ่เป็นอัตโนมัติและการรวม automated testing อย่างครอบคลุม ทำให้เกิด self-service deployment pipeline ที่ง่ายและมีประสิทธิภาพ และทีมงานมีความเครียดน้อยลงและมีความมั่นใจมากขึ้น
Decouple Deployments from Releases (แยกการ Deploy ออกจากการ Release)
ในการเปิดตัวโปรเจกต์ซอฟต์แวร์แบบดั้งเดิม การ release จะถูกขับเคลื่อนโดยวันที่เปิดตัวทางการตลาด ในคืนก่อนหน้า เราจะ deploy ซอฟต์แวร์ที่เสร็จสมบูรณ์ (หรือใกล้เคียงที่สุดเท่าที่จะทำได้) ขึ้น production เช้าวันถัดมา เราจะประกาศความสามารถใหม่สู่โลก เริ่มรับออเดอร์ ส่งมอบฟังก์ชันใหม่ให้ลูกค้า ฯลฯ
อย่างไรก็ตาม บ่อยครั้งที่ทุกอย่างไม่ได้เป็นไปตามแผน เราอาจเจอ production loads ที่เราไม่เคยทดสอบหรือออกแบบไว้ ทำให้ service ของเราล้มเหลวอย่างรุนแรง ทั้งต่อลูกค้าและองค์กรของเรา แย่กว่านั้น การกู้คืน service อาจต้องใช้กระบวนการ rollback ที่เจ็บปวดหรือการดำเนินการ fix forward ที่มีความเสี่ยงพอ ๆ กัน ซึ่งเราต้องเปลี่ยนแปลงโค้ดโดยตรงใน production ทั้งหมดนี้เป็นประสบการณ์ที่แย่มากสำหรับพนักงาน เมื่อทุกอย่างกลับมาทำงานได้ ทุกคนก็ถอนหายใจโล่งอก ดีใจที่ production deployments และ releases ไม่ได้เกิดขึ้นบ่อยกว่านี้
แน่นอนว่าเรารู้ว่าเราต้อง deploy ให้บ่อยขึ้นเพื่อให้ได้ผลลัพธ์ที่ต้องการคือ flow ที่ราบรื่นและรวดเร็ว ไม่ใช่น้อยลง เพื่อให้สิ่งนี้เป็นไปได้ เราต้องแยก production deployments ออกจาก feature releases ในทางปฏิบัติ คำว่า deployment และ release มักถูกใช้แทนกัน แต่มันคือสองการกระทำที่แตกต่างกันซึ่งมีวัตถุประสงค์ที่แตกต่างกันสองอย่าง:
• Deployment คือการติดตั้งซอฟต์แวร์เวอร์ชันที่ระบุลงใน environment ที่กำหนด (เช่น การ deploy โค้ดขึ้น integration test environment หรือการ deploy โค้ดขึ้น production) โดยเฉพาะ deployment อาจจะเกี่ยวข้องหรือไม่เกี่ยวข้องกับการ release ฟีเจอร์ให้ลูกค้าก็ได้
• Release คือการทำให้ฟีเจอร์ (หรือชุดของฟีเจอร์) พร้อมใช้งานสำหรับลูกค้าทุกคนหรือลูกค้าบางส่วน (เช่น เราเปิดให้ฟีเจอร์ถูกใช้งานโดย 5% ของฐานลูกค้า) โค้ดและ environment ของเราควรถูกออกแบบในลักษณะที่การ release ฟังก์ชันการทำงานไม่จำเป็นต้องเปลี่ยนแปลง application code ¶
กล่าวอีกนัยหนึ่ง เมื่อเรารวม deployment และ release เข้าด้วยกัน มันทำให้ยากที่จะสร้าง accountability สำหรับผลลัพธ์ที่สำเร็จ—การแยกสองกิจกรรมนี้ออกจากกันช่วยให้เรามอบอำนาจให้ Development และ Operations รับผิดชอบต่อความสำเร็จของการ deploy ที่รวดเร็วและบ่อยครั้ง ในขณะที่ทำให้ product owners รับผิดชอบต่อผลลัพธ์ทางธุรกิจที่สำเร็จของการ release (เช่น "การสร้างและเปิดตัวฟีเจอร์นี้คุ้มค่ากับเวลาของเราไหม")
แนวทางปฏิบัติที่อธิบายมาจนถึงตอนนี้ในหนังสือเล่มนี้ช่วยให้แน่ใจว่าเราทำการ deploy ขึ้น production ที่รวดเร็วและบ่อยครั้งตลอดการพัฒนา features โดยมีเป้าหมายเพื่อลดความเสี่ยงและผลกระทบของข้อผิดพลาดในการ deploy ความเสี่ยงที่เหลืออยู่คือ release risk ซึ่งก็คือว่าฟีเจอร์ที่เรานำขึ้น production บรรลุผลลัพธ์ที่ต้องการสำหรับลูกค้าและธุรกิจหรือไม่
ถ้าเรามี deployment lead time ที่ยาวมาก สิ่งนี้จะกำหนดว่าเราสามารถปล่อยฟีเจอร์ใหม่ออกสู่ตลาดได้บ่อยแค่ไหน อย่างไรก็ตาม เมื่อเราสามารถ deploy ตามต้องการแล้ว การจะเปิดฟังก์ชันใหม่ให้ลูกค้าได้เร็วแค่ไหนก็กลายเป็นการตัดสินใจทางธุรกิจและการตลาด ไม่ใช่การตัดสินใจทางเทคนิค มีรูปแบบการ release หลักสองประเภทที่เราสามารถใช้ได้ (และสามารถรวมกันได้):
• Environment-based release patterns (รูปแบบการ release แบบใช้ Environment): เป็นรูปแบบที่เรามีสอง environment ขึ้นไปที่เรา deploy เข้าไป แต่มีเพียง environment เดียวที่รับ traffic จากลูกค้าจริง (เช่น โดยการกำหนดค่า load balancers ของเรา) โค้ดใหม่จะถูก deploy เข้าไปใน environment ที่ไม่ live และการ release จะดำเนินการโดยการย้าย traffic ไปยัง environment นี้ รูปแบบเหล่านี้มีประสิทธิภาพอย่างมากเพราะโดยทั่วไปแล้วแทบไม่ต้องเปลี่ยนแปลง application ของเรา รูปแบบเหล่านี้ได้แก่ blue-green deployments , canary releases และ cluster immune systems ซึ่งทั้งหมดจะถูกกล่าวถึงเร็ว ๆ นี้
• Application-based release patterns (รูปแบบการ release แบบใช้ Application): เป็นรูปแบบที่เราแก้ไข application ของเราเพื่อให้สามารถเลือกปล่อยและเปิดเผยฟังก์ชันเฉพาะของ application ได้โดยการเปลี่ยนแปลง configuration เล็กน้อย ตัวอย่างเช่น เราสามารถ implement feature flags ที่ค่อย ๆ เปิดเผยฟังก์ชันใหม่ใน production ให้กับทีมพัฒนา พนักงานภายในทั้งหมด ลูกค้า 1% หรือเมื่อเรามั่นใจว่า release จะทำงานตามที่ออกแบบไว้ ก็เปิดให้ฐานลูกค้าทั้งหมด ตามที่กล่าวไว้ก่อนหน้านี้ สิ่งนี้ทำให้เกิดเทคนิคที่เรียกว่า dark launching ซึ่งเราจะจัดเตรียมฟังก์ชันทั้งหมดที่จะเปิดตัวใน production และทดสอบกับ production traffic ก่อนการ release ตัวอย่างเช่น เราอาจทดสอบฟังก์ชันใหม่อย่างเงียบ ๆ กับ production traffic เป็นเวลาหลายสัปดาห์ก่อนการเปิดตัว เพื่อค้นหาปัญหาและแก้ไขก่อนการเปิดตัวจริง
Environment-Based Release Patterns (รูปแบบการ Release แบบใช้ Environment)
การแยก deployments ออกจาก releases เปลี่ยนแปลงวิธีการทำงานของเราอย่างมาก เราไม่ต้องทำ deployment ในตอนกลางดึกหรือวันหยุดสุดสัปดาห์อีกต่อไปเพื่อลดความเสี่ยงที่จะส่งผลกระทบต่อลูกค้า แต่เราสามารถทำ deployment ในช่วงเวลาทำการปกติ ทำให้ Ops มีเวลาทำงานปกติเหมือนกับคนอื่น ๆ ในที่สุด
หัวข้อนี้โฟกัสที่ environment-based release patterns ซึ่งไม่ต้องการการเปลี่ยนแปลง application code เราทำสิ่งนี้โดยการมีหลาย environment ให้ deploy เข้าไป แต่มีเพียง environment เดียวที่รับ traffic ของลูกค้าจริง การทำเช่นนี้ช่วยลดความเสี่ยงที่เกี่ยวข้องกับ production releases และลด deployment lead time ได้อย่างมาก
The Blue-Green Deployment Pattern (รูปแบบการ Deploy แบบ Blue-Green)
รูปแบบที่ง่ายที่สุดในสามรูปแบบคือ blue-green deployment ในรูปแบบนี้ เรามี production environments สองชุด: blue และ green ในเวลาใดก็ตาม มีเพียงชุดเดียวเท่านั้นที่ให้บริการ traffic ของลูกค้า (ดู Figure 12.5 )
Figure 12.5: Blue-Green Deployment Patterns (รูปแบบการ Deploy แบบ Blue-Green)
Source: Humble and North, Continuous Delivery , 261.
ในการปล่อย service เวอร์ชันใหม่ เราจะ deploy ไปยัง environment ที่ไม่ได้ทำงานอยู่ ซึ่งเราสามารถทดสอบได้โดยไม่รบกวนประสบการณ์ของผู้ใช้ เมื่อเรามั่นใจว่าทุกอย่างทำงานตามที่ออกแบบไว้ เราก็ทำการ release โดยการเปลี่ยนเส้นทาง traffic ไปยัง blue environment ดังนั้น blue จะกลายเป็น live และ green จะกลายเป็น staging การ rollback ทำได้โดยการส่ง traffic กลับไปยัง green environment **
รูปแบบ blue-green deployment เป็นเรื่องง่าย และง่ายอย่างมากในการปรับใช้กับระบบที่มีอยู่ มันยังมีประโยชน์ที่เหลือเชื่อ เช่น ช่วยให้ทีมสามารถทำ deployment ในช่วงเวลาทำการปกติและทำการเปลี่ยนได้ง่าย (เช่น การเปลี่ยนการตั้งค่า router, การเปลี่ยน symlink) ในช่วงนอกเวลา การทำเพียงเท่านี้ก็สามารถปรับปรุงสภาพการทำงานของทีมที่ทำ deployment ได้อย่างมาก
Dealing with Database Changes (การจัดการกับการเปลี่ยนแปลง Database)
การมี application สองเวอร์ชันใน production สร้างปัญหาเมื่อทั้งคู่ต้องพึ่งพา database ร่วมกัน—เมื่อ deployment ต้องการการเปลี่ยนแปลง database schema หรือการเพิ่ม แก้ไข หรือลบตารางหรือคอลัมน์ database จะไม่สามารถรองรับ application ทั้งสองเวอร์ชันได้ มีสองแนวทางทั่วไปในการแก้ปัญหานี้:
• Create two databases (i.e., a blue and green database) (สร้างสอง databases คือ blue และ green database): แต่ละเวอร์ชัน—blue (เก่า) และ green (ใหม่)—ของ application มี database ของตัวเอง ระหว่างการ release เราจะทำให้ blue database อยู่ในโหมดอ่านอย่างเดียว สำรองข้อมูล กู้คืนไปยัง green database และสุดท้ายสลับ traffic ไปยัง green environment ปัญหาของรูปแบบนี้คือถ้าเราต้องการ rollback กลับไปยัง blue version เราอาจสูญเสีย transactions ถ้าเราไม่ได้ migrate transactions จาก green version ก่อน
• Decouple database changes from application changes (แยกการเปลี่ยนแปลง database ออกจากการเปลี่ยนแปลง application): แทนที่จะรองรับสอง databases เราจะแยกการ release การเปลี่ยนแปลง database ออกจากการ release การเปลี่ยนแปลง application โดยทำสองสิ่ง: หนึ่ง เราทำการเปลี่ยนแปลงแบบ additive เท่านั้นกับ database ของเรา—เราจะไม่ mutate objects ที่มีอยู่แล้วใน database สอง เราไม่ตั้งสมมติฐานใน application ของเราเกี่ยวกับว่า database เวอร์ชันใดจะทำงานใน production วิธีการนี้แตกต่างอย่างมากจากวิธีที่เราถูกสอนให้คิดเกี่ยวกับ databases แบบดั้งเดิม ซึ่งเราหลีกเลี่ยงการทำข้อมูลซ้ำซ้อน กระบวนการแยกการเปลี่ยนแปลง database ออกจากการเปลี่ยนแปลง application นี้ถูกใช้โดย IMVU (และอื่น ๆ) ในช่วงปี 2009 ทำให้พวกเขาสามารถทำ deployment ได้ 50 ครั้งต่อวัน ซึ่งบางครั้งต้องมีการเปลี่ยนแปลง database 27 ††
CASE STUDY (กรณีศึกษา)
Dixons Retail—Blue-Green Deployment for Point-Of-Sale System (2008) (Dixons Retail—การ Deploy แบบ Blue-Green สำหรับระบบ ณ จุดขาย)
Dan Terhorst-North, ที่ปรึกษาด้านเทคโนโลยีและการเปลี่ยนแปลงองค์กร และ Dave Farley, ผู้ร่วมเขียน Continuous Delivery ทำงานในโปรเจกต์ให้กับ Dixons Retail ร้านค้าปลีกขนาดใหญ่ของอังกฤษ ที่เกี่ยวข้องกับระบบ point-of-sale (POS) หลายพันระบบที่อยู่ในร้านค้าปลีกหลายร้อยแห่งและดำเนินการภายใต้แบรนด์ลูกค้าที่แตกต่างกันหลายแบรนด์ แม้ว่า blue-green deployments จะเกี่ยวข้องกับ web services เป็นส่วนใหญ่ North และ Farley ก็ใช้รูปแบบนี้เพื่อลดความเสี่ยงและเวลาในการเปลี่ยนสำหรับการอัปเกรด POS อย่างมาก 29
โดยทั่วไปแล้ว การอัปเกรดระบบ POS เป็นโปรเจกต์แบบ big-bang, waterfall: POS clients และ centralized server จะถูกอัปเกรดพร้อมกัน ซึ่งต้องใช้ downtime จำนวนมาก (บ่อยครั้งทั้งสุดสัปดาห์) รวมถึง bandwidth ของเครือข่ายจำนวนมากในการ push ซอฟต์แวร์ client ใหม่ไปยังร้านค้าปลีกทั้งหมด เมื่อทุกอย่างไม่เป็นไปตามแผนที่วางไว้ อาจส่งผลกระทบอย่างรุนแรงต่อการดำเนินงานของร้านค้า
สำหรับการอัปเกรดนี้ ไม่มี bandwidth ของเครือข่ายเพียงพอที่จะอัปเกรดทุกระบบ POS พร้อมกัน ซึ่งทำให้กลยุทธ์แบบดั้งเดิมเป็นไปไม่ได้ เพื่อแก้ปัญหานี้ พวกเขาใช้กลยุทธ์ blue-green และสร้าง centralized server software สองเวอร์ชันใน production ทำให้สามารถรองรับ POS clients ทั้งเวอร์ชันเก่าและใหม่พร้อมกัน
หลังจากทำเช่นนี้ ไม่กี่สัปดาห์ก่อนการอัปเกรด POS ตามแผน พวกเขาเริ่มส่งตัวติดตั้งซอฟต์แวร์ POS client เวอร์ชันใหม่ไปยังร้านค้าปลีกผ่านลิงก์เครือข่ายที่ช้า โดย deploy ซอฟต์แวร์ใหม่บนระบบ POS ในสถานะที่ไม่ได้ทำงาน ในขณะที่เวอร์ชันเก่ายังคงทำงานตามปกติ
เมื่อ POS clients ทั้งหมดมีทุกอย่างพร้อมสำหรับการอัปเกรด (client และ server ที่อัปเกรดแล้วได้ทดสอบร่วมกันสำเร็จ และซอฟต์แวร์ client ใหม่ได้ถูก deploy ไปยัง clients ทั้งหมดแล้ว) ผู้จัดการร้านค้าก็มีอำนาจในการตัดสินใจว่าจะ release เวอร์ชันใหม่เมื่อใด
ขึ้นอยู่กับความต้องการทางธุรกิจ ผู้จัดการบางคนต้องการใช้ฟีเจอร์ใหม่ทันทีและ release ทันที ในขณะที่บางคนต้องการรอ ไม่ว่าจะ release ทันทีหรือรอ มันดีกว่าสำหรับผู้จัดการมากกว่าการให้ฝ่าย IT ส่วนกลางเลือกเวลา release ให้พวกเขา
กรณีศึกษานี้แสดงให้เห็นว่ารูปแบบ DevOps สามารถนำไปใช้กับเทคโนโลยีที่แตกต่างกันได้อย่างเป็นสากล บ่อยครั้งในวิธีที่น่าประหลาดใจ แต่ให้ผลลัพธ์ที่ยอดเยี่ยมเหมือนกัน
The Canary and Cluster Immune System Release Patterns (รูปแบบการ Release แบบ Canary และ Cluster Immune System)
รูปแบบ blue-green release ใช้งานง่ายและสามารถเพิ่มความปลอดภัยของการปล่อยซอฟต์แวร์ได้อย่างมาก มีรูปแบบต่าง ๆ ที่สามารถปรับปรุงความปลอดภัยและ deployment lead times ได้มากขึ้นด้วยการใช้ automation แต่ก็อาจมีความซับซ้อนเพิ่มขึ้นเป็นการแลกเปลี่ยน
รูปแบบ canary release ทำให้กระบวนการ release เป็นอัตโนมัติโดยการ promote ไปยัง environment ที่ใหญ่ขึ้นและสำคัญมากขึ้นเรื่อย ๆ เมื่อเรายืนยันว่าโค้ดทำงานตามที่ออกแบบไว้ คำว่า canary release มาจากประเพณีของคนงานเหมืองถ่านหินที่นำนกขมิ้นในกรงลงไปในเหมืองเพื่อตรวจหา ระดับคาร์บอนมอนอกไซด์ที่เป็นพิษตั้งแต่เนิ่น ๆ ถ้ามีก๊าซมากเกินไปในถ้ำ มันจะฆ่านกขมิ้นก่อนที่จะฆ่าคนงานเหมือง เตือนให้พวกเขาอพยพ
ในรูปแบบนี้ เมื่อเราทำการ release เราจะติดตามว่าซอฟต์แวร์ในแต่ละ environment ทำงานเป็นอย่างไร เมื่อมีอะไรผิดปกติ เราจะ roll back ถ้าไม่เช่นนั้น เราจะ deploy ไปยัง environment ถัดไป ‡‡ Figure 12.6 แสดงกลุ่มของ environment ที่ Facebook สร้างขึ้นเพื่อรองรับรูปแบบการ release นี้:
Figure 12.6: The Canary Release Pattern (รูปแบบ Canary Release)
Source: Humble and Farley, Continuous Delivery , 263.
• A1 group: production servers ที่ให้บริการเฉพาะพนักงานภายในเท่านั้น
• A2 group: production servers ที่ให้บริการเฉพาะลูกค้าเปอร์เซ็นต์เล็กน้อย และจะถูก deploy เมื่อผ่านเกณฑ์การยอมรับที่กำหนด (ไม่ว่าจะ automated หรือ manual)
• A3 group: production servers ที่เหลือ ซึ่งจะถูก deploy หลังจากซอฟต์แวร์ที่รันใน A2 cluster ผ่านเกณฑ์การยอมรับที่กำหนด
cluster immune system ขยายรูปแบบ canary release โดยการเชื่อมต่อระบบ monitoring การผลิตของเรากับกระบวนการ release และทำให้การ rollback โค้ดเป็นอัตโนมัติเมื่อประสิทธิภาพที่ผู้ใช้เห็นของระบบผลิตเบี่ยงเบนออกไปนอกช่วงที่คาดการณ์ไว้ เช่น เมื่อ conversion rates สำหรับผู้ใช้ใหม่ลดลงต่ำกว่าค่ามาตรฐานในอดีตที่ 15–20%
มีประโยชน์สำคัญสองประการของระบบป้องกันแบบนี้ หนึ่ง เราป้องกันข้อบกพร่องที่ยากต่อการค้นหาผ่าน automated tests เช่น การเปลี่ยนแปลงหน้าเว็บที่ทำให้องค์ประกอบหน้าสำคัญบางอย่างมองไม่เห็น (เช่น การเปลี่ยน CSS) สอง เราลดเวลาที่ต้องใช้ในการตรวจจับและตอบสนองต่อประสิทธิภาพที่ลดลงจากการเปลี่ยนแปลงของเรา §§
Application-Based Patterns to Enable Safer Releases (รูปแบบที่ใช้ Application เพื่อให้การ Release ปลอดภัยยิ่งขึ้น)
ในหัวข้อที่แล้ว เราสร้าง environment-based patterns ที่ช่วยให้เราแยก deployments ออกจาก releases โดยใช้หลาย environment และสลับว่า environment ไหน live ซึ่งสามารถ implement ได้ทั้งหมดที่ระดับ infrastructure
ในหัวข้อนี้ เราจะอธิบาย application-based release patterns ที่เราสามารถ implement ในโค้ดของเรา ทำให้มีความยืดหยุ่นมากยิ่งขึ้นในการปล่อยฟีเจอร์ใหม่ให้ลูกค้าอย่างปลอดภัย โดยมักจะเป็นแบบ per-feature เนื่องจาก application-based release patterns ถูก implement ใน application จึงต้องอาศัยการมีส่วนร่วมจาก Development
Implement Feature Toggles (การ Implement Feature Toggles)
วิธีหลักในการทำให้ application-based release patterns เกิดขึ้นได้คือการ implement feature toggles (หรือที่เรียกว่า feature flags) ซึ่งให้กลไกในการเลือกเปิดและปิดฟีเจอร์โดยไม่ต้อง deploy โค้ดขึ้น production Feature toggles ยังสามารถควบคุมว่าฟีเจอร์ใดที่มองเห็นและพร้อมใช้งานสำหรับกลุ่มผู้ใช้เฉพาะ (เช่น พนักงานภายใน, กลุ่มลูกค้าบางส่วน)
Feature toggles มักถูก implement โดยการห่อหุ้ม application logic หรือ UI elements ด้วย conditional statement โดยฟีเจอร์จะถูกเปิดหรือปิดตามการตั้งค่า configuration ที่เก็บไว้ที่ไหนสักแห่ง อาจจะง่าย ๆ แค่ application configuration file (เช่น configuration files ในรูปแบบ JSON, XML) หรืออาจผ่าน directory service หรือแม้แต่ web service ที่ออกแบบมาเพื่อจัดการ feature toggling โดยเฉพาะ ¶¶
Feature toggles ยังช่วยให้เราทำสิ่งต่อไปนี้ได้:
• Roll back easily (roll back ได้ง่าย): ฟีเจอร์ที่สร้างปัญหาหรือการหยุดชะงักใน production สามารถถูกปิดได้อย่างรวดเร็วและปลอดภัยเพียงแค่เปลี่ยนการตั้งค่า feature toggle สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อ deployment ไม่บ่อย—การปิดฟีเจอร์ของผู้มีส่วนได้ส่วนเสียเพียงรายเดียวมักจะง่ายกว่าการ roll back ทั้ง release
• Gracefully degrade performance (ลดประสิทธิภาพอย่างนุ่มนวล): เมื่อ service ของเรามีโหลดสูงมาก ซึ่งปกติจะต้องเพิ่ม capacity หรือแย่กว่านั้นคือเสี่ยงให้ service ล้มเหลวใน production เราสามารถใช้ feature toggles เพื่อลดระดับของคุณภาพบริการ กล่าวอีกนัยหนึ่ง เราสามารถเพิ่มจำนวนผู้ใช้ที่เราให้บริการโดยลดระดับฟังก์ชันที่ส่งมอบ (เช่น ลดจำนวนลูกค้าที่สามารถเข้าถึงฟีเจอร์บางอย่าง, ปิดฟีเจอร์ที่ใช้ CPU มาก เช่น recommendations ฯลฯ)
• Increase our resilience through a service-oriented architecture (เพิ่มความยืดหยุ่นด้วย service-oriented architecture): ถ้าเรามีฟีเจอร์ที่ต้องพึ่งพา service อื่นที่ยังไม่เสร็จ เรายังสามารถ deploy ฟีเจอร์ของเราขึ้น production ได้ แต่ซ่อนไว้หลัง feature toggle เมื่อ service นั้นพร้อมใช้งานในที่สุด เราก็ toggle ฟีเจอร์ให้เปิด ในทำนองเดียวกัน เมื่อ service ที่เราพึ่งพาล้มเหลว เราสามารถปิดฟีเจอร์เพื่อป้องกันการเรียกไปยัง downstream service ในขณะที่ให้ application ที่เหลือทำงานต่อไป
• Perform A/B testing (ทำ A/B testing): ระบบ feature toggle สมัยใหม่ เช่น LaunchDarkly, Split และ Optimizely ยังช่วยให้ทีม product สามารถรันการทดลองเพื่อทดสอบฟีเจอร์ใหม่และดูผลกระทบต่อ business metrics ด้วยวิธีนี้ เราสามารถแสดงความสัมพันธ์เชิงสาเหตุระหว่างฟีเจอร์ใหม่และผลลัพธ์ที่เราสนใจ นี่คือเครื่องมือที่ทรงพลังอย่างเหลือเชื่อที่ช่วยให้แนวทางเชิงวิทยาศาสตร์และสมมติฐาน-driven ในการพัฒนาผลิตภัณฑ์ (เทคนิคที่อธิบายในภายหลังในหนังสือเล่มนี้)
เพื่อให้แน่ใจว่าเราจะพบข้อผิดพลาดในฟีเจอร์ที่ถูกห่อหุ้มด้วย feature toggles automated acceptance tests ของเราควรทำงานโดยเปิด feature toggles ทั้งหมด (และเราควรทดสอบว่าฟังก์ชันการ toggle ทำงานถูกต้องด้วย!)
Perform Dark Launches (การทำ Dark Launch)
Feature toggles ทำให้เราสามารถ deploy ฟีเจอร์ขึ้น production โดยไม่ทำให้ผู้ใช้เข้าถึงได้ ทำให้เกิดเทคนิคที่เรียกว่า dark launching ซึ่งเราจะ deploy ฟังก์ชันทั้งหมดขึ้น production แล้วทำการทดสอบฟังก์ชันใหม่ในขณะที่มันยังมองไม่เห็นสำหรับลูกค้า สำหรับการเปลี่ยนแปลงที่ใหญ่หรือมีความเสี่ยงสูง เรามักทำแบบนี้เป็นเวลาหลายสัปดาห์ก่อนการเปิดตัว production เพื่อให้สามารถทดสอบกับโหลดที่ใกล้เคียง production ได้อย่างปลอดภัย
ตัวอย่างเช่น สมมติว่าเรา dark launch ฟีเจอร์ใหม่ที่มีความเสี่ยงในการ release สูง เช่น ฟีเจอร์การค้นหาใหม่ กระบวนการสร้างบัญชี หรือ database queries ใหม่ หลังจากโค้ดทั้งหมดอยู่ใน production โดยให้ฟีเจอร์ใหม่ถูกปิดไว้ เราอาจแก้ไข user session code เพื่อเรียกใช้ฟังก์ชันใหม่—แทนที่จะแสดงผลลัพธ์ให้ผู้ใช้ เราแค่ log หรือ discard ผลลัพธ์ทิ้ง
ตัวอย่างเช่น เราอาจให้ผู้ใช้ออนไลน์ 1% ทำการเรียกใช้ฟีเจอร์ใหม่อย่างไม่เห็นได้ชัด เพื่อดูว่าฟีเจอร์ใหม่ของเราทำงานอย่างไรภายใต้โหลด หลังจากที่เราพบและแก้ไขปัญหาใด ๆ แล้ว เราก็ค่อย ๆ เพิ่ม simulated load โดยเพิ่มความถี่และจำนวนผู้ใช้ที่ใช้งานฟังก์ชันใหม่ ด้วยการทำเช่นนี้ เราสามารถจำลองโหลดที่ใกล้เคียง production ได้อย่างปลอดภัย ทำให้เรามั่นใจว่า service ของเราจะทำงานตามที่ต้องการ
ยิ่งไปกว่านั้น เมื่อเราเปิดตัวฟีเจอร์ เราสามารถค่อย ๆ เปิดตัวให้กับกลุ่มลูกค้าเล็ก ๆ ก่อน โดยหยุดการ release หากพบปัญหาใด ๆ ด้วยวิธีนี้ เราจะลดจำนวนลูกค้าที่ได้รับฟีเจอร์เพียงเพื่อจะถูกเอาคืนเพราะเราพบข้อบกพร่องหรือไม่สามารถรักษาประสิทธิภาพที่ต้องการได้
ในปี 2009 เมื่อ John Allspaw เป็น VP of Operations ที่ Flickr เขาเขียนถึงทีมผู้บริหารของ Yahoo! เกี่ยวกับกระบวนการ dark launch ของพวกเขา โดยกล่าวว่า:
มันเพิ่ม ความมั่นใจของทุกคน เกือบจะถึงจุดที่ไม่แยแส ในแง่ของความกลัวเกี่ยวกับปัญหาที่เกี่ยวกับโหลด ผมไม่รู้ว่ามีการ deploy โค้ดขึ้น production กี่ครั้งในวันใดวันหนึ่งในช่วง 5 ปีที่ผ่านมา... เพราะส่วนใหญ่แล้วผมไม่สนใจ เพราะการเปลี่ยนแปลงที่ทำใน production มีโอกาสต่ำมากที่จะก่อให้เกิดปัญหา เมื่อมันเคยก่อให้เกิดปัญหา พนักงาน Flickr ทุกคนสามารถหาได้ในหน้าเว็บว่า เมื่อไหร่ ที่มีการเปลี่ยนแปลง ใคร เป็นคนเปลี่ยนแปลง และ (ทีละบรรทัด) อะไร ที่เปลี่ยนแปลงไป 32 ***
ต่อมา เมื่อเราสร้าง production telemetry ที่เพียงพอใน application และ environment ของเราแล้ว เรายังสามารถเปิดใช้งานวงจร feedback ที่เร็วขึ้นเพื่อตรวจสอบสมมติฐานและผลลัพธ์ทางธุรกิจของเราได้ทันทีหลังจากที่เรา deploy ฟีเจอร์ขึ้น production
การทำเช่นนี้ เราไม่ต้องรอจนถึงการ release แบบ big-bang เพื่อทดสอบว่าลูกค้าต้องการใช้งานฟังก์ชันที่เราสร้างขึ้นหรือไม่ แต่เมื่อถึงเวลาที่เราประกาศและปล่อยฟีเจอร์ใหญ่ของเรา เราได้ทดสอบสมมติฐานทางธุรกิจของเราและรันการทดลองนับไม่ถ้วนเพื่อปรับแต่งผลิตภัณฑ์ของเรากับลูกค้าจริงอย่างต่อเนื่อง ซึ่งช่วยให้เรายืนยันว่าฟีเจอร์ต่าง ๆ จะบรรลุผลลัพธ์ที่ต้องการของลูกค้า
CASE STUDY (กรณีศึกษา)
Dark Launch of Facebook Chat (2008) (การ Dark Launch ของ Facebook Chat)
เกือบทศวรรษที่ผ่านมา Facebook เป็นหนึ่งในเว็บไซต์ที่มีผู้เยี่ยมชมมากที่สุด ตามการวัดจากจำนวนหน้าที่ถูกดูและจำนวนผู้ใช้ที่ไม่ซ้ำ ในปี 2008 มันมีผู้ใช้ที่ใช้งานทุกวันกว่า 70 ล้านคน ซึ่งสร้างความท้าทายให้กับทีมที่กำลังพัฒนาฟังก์ชัน Facebook Chat ใหม่ 34 †††
Eugene Letuchy วิศวกรในทีม Chat เขียนเกี่ยวกับว่าจำนวนผู้ใช้พร้อมกันนั้นเป็นความท้าทายทางวิศวกรรมซอฟต์แวร์ครั้งใหญ่ "การดำเนินการที่ใช้ทรัพยากรมากที่สุดในระบบ chat ไม่ใช่การส่งข้อความ แต่เป็นการทำให้ผู้ใช้ออนไลน์แต่ละคนรับรู้ถึงสถานะ online-idle-offline ของเพื่อนของพวกเขา เพื่อให้การสนทนาเริ่มต้นได้" 36
การ implement ฟีเจอร์ที่ต้องใช้การคำนวณสูงนี้เป็นหนึ่งในงานด้านเทคนิคที่ใหญ่ที่สุดเท่าที่ Facebook เคยทำมา และใช้เวลาเกือบปีจึงจะเสร็จ ‡‡‡ ส่วนหนึ่งของความซับซ้อนของโปรเจกต์นี้เกิดจากเทคโนโลยีที่หลากหลายที่จำเป็นเพื่อให้ได้ประสิทธิภาพตามต้องการ รวมถึง C++, JavaScript และ PHP รวมถึงการใช้ Erlang ครั้งแรกในโครงสร้างพื้นฐาน back-end ของพวกเขา 37
ตลอดระยะเวลาเกือบปีของการดำเนินการ ทีม Chat check-in โค้ดของพวกเขาลง version control ซึ่งจะถูก deploy ขึ้น production อย่างน้อยวันละครั้ง ในตอนแรก ฟังก์ชัน Chat มองเห็นได้เฉพาะทีม Chat เท่านั้น ต่อมา มันถูกทำให้มองเห็นได้สำหรับพนักงานภายในทั้งหมด แต่ถูกซ่อนจากผู้ใช้ Facebook ภายนอกโดยสมบูรณ์ผ่าน Gatekeeper ซึ่งเป็น service การ toggle ฟีเจอร์ของ Facebook
เป็นส่วนหนึ่งของกระบวนการ dark launch ทุก session ของผู้ใช้ Facebook ซึ่งรัน JavaScript ในเบราว์เซอร์ของผู้ใช้ จะมี test harness โหลดเข้าไป—UI elements ของ chat ถูกซ่อนไว้ แต่ browser client จะส่งข้อความ chat ทดสอบที่ไม่เห็นได้ชัดไปยัง back-end chat service ที่อยู่ใน production แล้ว ทำให้พวกเขาสามารถจำลองโหลดที่ใกล้เคียง production ได้ตลอดทั้งโปรเจกต์ ทำให้สามารถค้นหาและแก้ไขปัญหาด้านประสิทธิภาพก่อนการปล่อยให้ลูกค้าใช้งานได้นาน
การ release และเปิดตัว Chat ต้องการเพียงสองขั้นตอน: การแก้ไขการตั้งค่า Gatekeeper configuration เพื่อทำให้ฟีเจอร์ Chat มองเห็นได้สำหรับผู้ใช้ภายนอกบางส่วน และการให้ผู้ใช้ Facebook โหลด JavaScript code ใหม่ที่แสดง UI ของ Chat และปิดการใช้งาน invisible test harness ถ้ามีอะไรผิดพลาด สองขั้นตอนนี้จะถูกย้อนกลับ
เมื่อวันเปิดตัว Facebook Chat มาถึง มันประสบความสำเร็จอย่างน่าประหลาดใจและราบรื่น ดูเหมือนว่าจะ scale จากศูนย์ไปสู่ผู้ใช้ 70 ล้านคนได้อย่างง่ายดายในชั่วข้ามคืน ระหว่างการ release พวกเขาเปิดฟังก์ชัน Chat ให้กับกลุ่มประชากรลูกค้าที่ใหญ่ขึ้นเรื่อย ๆ—แรกเริ่มให้พนักงาน Facebook ภายในทั้งหมด จากนั้นให้ 1% ของประชากรลูกค้า จากนั้น 5% และต่อไปเรื่อย ๆ ตามที่ Letuchy เขียน "เคล็ดลับในการไปจากศูนย์ถึง 70 ล้านผู้ใช้ในชั่วข้ามคืนคือการหลีกเลี่ยงการทำทั้งหมดในครั้งเดียว" 38
ในกรณีศึกษานี้ ผู้ใช้ Facebook ทุกคนเป็นส่วนหนึ่งของโปรแกรมการทดสอบโหลดขนาดใหญ่ ซึ่งทำให้ทีมมั่นใจว่าระบบของพวกเขาสามารถจัดการกับโหลดที่เหมือนจริงใน production
Survey of Continuous Delivery and Continuous Deployment in Practice (ภาพรวมของ Continuous Delivery และ Continuous Deployment ในทางปฏิบัติ)
ในหนังสือ Continuous Delivery Jez Humble และ David Farley กำหนดคำว่า continuous delivery ส่วนคำว่า continuous deployment ถูกกล่าวถึงครั้งแรกโดย Tim Fitz ในโพสต์บล็อกของเขา "Continuous Deployment at IMVU: Doing the impossible fifty times a day" อย่างไรก็ตาม ในปี 2015 ระหว่างการพัฒนาหนังสือ The DevOps Handbook ฉบับแรก Jez Humble ได้ให้ความเห็นว่า
ในช่วงห้าปีที่ผ่านมา มีความสับสนเกี่ยวกับคำว่า continuous delivery เทียบกับ continuous deployment—และอันที่จริง ความคิดและคำจำกัดความของผมเองก็เปลี่ยนไปตั้งแต่เราเขียนหนังสือ ทุกองค์กรควรสร้างรูปแบบของตัวเองตามสิ่งที่พวกเขาต้องการ สิ่งสำคัญที่เราควรใส่ใจไม่ใช่รูปแบบ แต่เป็นผลลัพธ์: deployments ควรเป็นเหตุการณ์ที่มีความเสี่ยงต่ำ กดปุ่มได้ และเราสามารถทำได้ตามต้องการ 39
คำจำกัดความที่อัปเดตของเขาเกี่ยวกับ continuous delivery และ continuous deployment มีดังนี้:
เมื่อ developers ทั้งหมดทำงานใน small batches บน trunk หรือทุกคนทำงานบน trunk ใน short-lived feature branches ที่ merge ไปยัง trunk เป็นประจำ และเมื่อ trunk อยู่ในสถานะที่สามารถ release ได้ตลอดเวลา และเมื่อเราสามารถ release ได้ตามต้องการด้วยการกดปุ่มในช่วงเวลาทำการปกติ เรากำลังทำ continuous delivery อยู่ Developers จะได้รับ feedback ที่รวดเร็วเมื่อพวกเขานำ regression errors ใด ๆ เข้ามา ซึ่งรวมถึง defects, performance issues, security issues, usability issues ฯลฯ เมื่อพบปัญหาเหล่านี้ พวกเขาจะถูกแก้ไขทันทีเพื่อให้ trunk สามารถ deploy ได้ตลอดเวลา
นอกเหนือจากข้างต้น เมื่อเรากำลัง deploy good builds ขึ้น production เป็นประจำผ่าน self-service (ถูก deploy โดย Dev หรือ Ops)—ซึ่งโดยทั่วไปหมายความว่าเรากำลัง deploy ขึ้น production อย่างน้อยวันละครั้งต่อ developer หรือแม้กระทั่ง deploy โดยอัตโนมัติทุกครั้งที่ developer commit การเปลี่ยนแปลง—นี่คือตอนที่เรากำลังทำ continuous deployment 40
หากนิยามแบบนี้ continuous delivery คือ prerequisite สำหรับ continuous deployment เช่นเดียวกับ continuous integration คือ prerequisite สำหรับ continuous delivery Continuous deployment นั้นน่าจะใช้ได้ในบริบทของ web services ที่ส่งมอบผ่านออนไลน์ อย่างไรก็ตาม continuous delivery ใช้ได้ในเกือบทุกบริบทที่เราต้องการ deployments และ releases ที่มีคุณภาพสูง, lead time ที่รวดเร็ว และผลลัพธ์ที่มีความเสี่ยงต่ำและคาดเดาได้ รวมถึงสำหรับ embedded systems, COTS products และ mobile apps
ที่ Amazon และ Google ทีมส่วนใหญ่ปฏิบัติตาม continuous delivery แม้ว่าบางทีมจะทำ continuous deployment—ดังนั้นจึงมีความแปรผันอย่างมากระหว่างทีมในเรื่องความถี่ในการ deploy โค้ดและวิธีการ deploy ทีมต่าง ๆ มีอำนาจในการเลือกวิธีการ deploy ตามความเสี่ยงที่พวกเขาจัดการ
ในทำนองเดียวกัน กรณีศึกษาส่วนใหญ่ในหนังสือเล่มนี้ก็เป็น continuous delivery เช่นกัน เช่น ซอฟต์แวร์ embedded ที่รันบนเครื่องพิมพ์ HP LaserJet, การดำเนินการพิมพ์บิลของ CSG ที่รันบนเทคโนโลยี 20 แพลตฟอร์มรวมถึงแอปพลิเคชัน COBOL mainframe, Facebook และ Etsy รูปแบบเดียวกันนี้สามารถใช้ได้กับซอฟต์แวร์ที่รันบนโทรศัพท์มือถือ, สถานีควบคุมภาคพื้นดินที่ควบคุมดาวเทียม และอื่น ๆ
Continuous Learning (การเรียนรู้อย่างต่อเนื่อง)
DORA's 2018 และ 2019 State of DevOps Report s แสดงให้เห็นว่า continuous delivery เป็นตัวทำนายสำคัญของประสิทธิภาพระดับ elite งานวิจัยพบว่าสิ่งนี้รวมถึงองค์ประกอบทั้งทางเทคนิคและวัฒนธรรม: 41
• ทีมสามารถ deploy ตามต้องการไปยัง production หรือ end users ตลอดทั้ง software delivery life cycle
• Feedback ที่รวดเร็วเกี่ยวกับคุณภาพและความสามารถในการ deploy ของระบบนั้นพร้อมใช้งานสำหรับทุกคนในทีม
• สมาชิกในทีมให้ความสำคัญกับการรักษาระบบให้อยู่ในสถานะที่สามารถ deploy ได้
CASE STUDY: NEW TO SECOND EDITION (กรณีศึกษา: ใหม่ในฉบับที่สอง)
Creating a Win-Win for Dev & Ops at CSG (2016) (การสร้าง Win-Win สำหรับ Dev และ Ops ที่ CSG)
หลังจากที่ปรับปรุงการ release ได้สำเร็จระหว่างปี 2012 ถึง 2015 CSG ก็พัฒนาโครงสร้างองค์กรของพวกเขาต่อไปเพื่อปรับปรุงท่าทีการดำเนินงานในแต่ละวัน ในการประชุม DevOps Enterprise Summit ปี 2016 Scott Prugh, Chief Architect และ VP Software Engineering ในขณะนั้น พูดถึงการเปลี่ยนแปลงองค์กรครั้งใหญ่ที่รวมทีม development และ operations ที่แยกจากกันเป็นทีม build/run แบบ cross-functional
Prugh อธิบายจุดเริ่มต้นของการเดินทางนี้:
เราได้ปรับปรุงกระบวนการ release และคุณภาพของการ release อย่างมาก แต่ยังคงมีการ escalation และความขัดแย้งกับสมาชิกทีม operations ของเรา ทีม development รู้สึกมั่นใจเกี่ยวกับคุณภาพโค้ดของพวกเขาและยังคง push releases เร็วขึ้นและบ่อยขึ้น
ในทางกลับกัน ทีม ops ของเราบ่นเกี่ยวกับ production outages และการเปลี่ยนแปลงที่รวดเร็วที่ทำให้สภาพแวดล้อมเสียหาย เพื่อต่อสู้กับแรงที่ต่อต้านเหล่านี้ ทีม change และ program management ของเราเพิ่มกระบวนการของพวกเขาขึ้นเพื่อปรับปรุงการประสานงานและพยายามควบคุมความโกลาหล น่าเศร้า สิ่งนี้ไม่ได้ปรับปรุงคุณภาพของการผลิต ประสบการณ์ของทีมปฏิบัติการของเรา หรือความสัมพันธ์ระหว่างทีม development และ operations 42
Figure 12.7: How Structure Influences Behavior and Quality (โครงสร้างมีอิทธิพลต่อพฤติกรรมและคุณภาพอย่างไร)
Image courtesy of Scott Prugh.
เพื่อทำความเข้าใจมากขึ้นว่าเกิดอะไรขึ้น ทีมงานได้เจาะลึกข้อมูล incident ซึ่งเผยให้เห็นแนวโน้มที่น่าประหลาดใจและน่าตกใจ: 43
• ผลกระทบและ incidents จากการ release ดีขึ้นเกือบ 90% (จาก 201 เหลือ 24 incidents)
• Release incidents คิดเป็น 2% ของ incidents ที่เกิดขึ้น (98% อยู่ใน production)
• และ 92% ของ production incidents เหล่านี้เป็นการกู้คืนอย่างรวดเร็วที่แก้ไขโดย operations
Prugh สังเกตเพิ่มเติมว่า " โดยพื้นฐานแล้วเราได้ปรับปรุงท่าทีการพัฒนาของเราอย่างมีนัยสำคัญ แต่ทำเพียงเล็กน้อยเพื่อปรับปรุงสภาพแวดล้อมการดำเนินงานใน production เราได้ผลลัพธ์ที่เราปรับให้เหมาะสมพอดี: คุณภาพโค้ดที่ยอดเยี่ยมและคุณภาพการดำเนินงานที่แย่ " 44
เพื่อหาทางแก้ไข Prugh ถามคำถามต่อไปนี้:
• เป้าหมายขององค์กรที่แตกต่างกันกำลังขัดแย้งกับเป้าหมายของระบบหรือไม่?
• การที่ development ขาดความเข้าใจใน operations ส่งผลให้ซอฟต์แวร์ที่ยากต่อการใช้งานหรือไม่?
• การขาดพันธกิจร่วมกันสร้างการขาดความเห็นอกเห็นใจระหว่างทีมหรือไม่?
• การส่งต่องานของเรามีส่วนทำให้ lead time ยาวขึ้นหรือไม่?
• การขาดทักษะด้านวิศวกรรมใน operations ขัดขวางการปรับปรุงและส่งเสริมวิศวกรรมแบบ duct-tape หรือไม่?
Figure 12.8: From Siloed Approach to Cross-Functional Teams (จากแนวทางแบบแยกส่วนสู่ทีม Cross-Functional)
Image courtesy of Scott Prugh.
ในขณะเดียวกันที่ Prugh กำลังค้นพบสิ่งเหล่านี้ การ escalation ของปัญหาจากลูกค้าเกี่ยวกับ production issues ก็ถูกหยิบยกขึ้นไปยังผู้นำบริหารซ้ำแล้วซ้ำเล่า ลูกค้าของ CSG โกรธเคือง และผู้บริหารถามว่าสามารถทำอะไรได้บ้างเพื่อปรับปรุงท่าทีการดำเนินงานของ CSG
หลังจากพยายามหลายครั้ง Prugh เสนอให้สร้าง "Service Delivery Teams" ที่ build และ run ซอฟต์แวร์ โดยพื้นฐานแล้ว เขาเสนอให้รวม Dev และ Ops ไว้ในทีมเดียวกัน 45
ในตอนแรก ข้อเสนอนี้ถูกมองว่าทำให้เกิดความแตกแยก แต่หลังจากนำเสนอความสำเร็จก่อนหน้านี้กับ shared operations teams Prugh โต้แย้งเพิ่มเติมว่าการนำ Dev และ Ops มารวมกันจะสร้าง win-win สำหรับทั้งสองทีมโดย:
• ปรับปรุงความเข้าใจเพื่อให้ทีมสามารถปรับปรุงห่วงโซ่การส่งมอบทั้งหมด (development ถึง operations)
• ปรับปรุง flow และประสิทธิภาพของความรู้ และสร้าง accountability แบบรวมศูนย์สำหรับ design, build, test และ operations
• ทำให้ operations เป็นปัญหาทางวิศวกรรม §§§
• นำประโยชน์อื่น ๆ เช่น การปรับปรุงการสื่อสาร ลดการประชุม สร้างการวางแผนร่วมกัน ปรับปรุงการทำงานร่วมกัน สร้างความโปร่งใสในการทำงานร่วมกัน และวิสัยทัศน์ร่วมกันของผู้นำ
Figure 12.9: Conventional vs. Cross-Functional Structure (โครงสร้างแบบดั้งเดิมเทียบกับ Cross-Functional)
Image courtesy of Scott Prugh.
ขั้นตอนถัดไปเกี่ยวข้องกับการสร้างโครงสร้างทีมใหม่ที่รวมทีม development และ operations และผู้นำเข้าด้วยกัน ผู้จัดการและผู้นำของทีมใหม่ถูกคัดเลือกจากกลุ่มปัจจุบัน และสมาชิกทีมถูกคัดเลือกใหม่เข้าสู่ทีม cross-functional ใหม่ หลังจากการเปลี่ยนแปลง ผู้จัดการและผู้นำฝ่าย development ได้รับประสบการณ์จริงในการรันซอฟต์แวร์ที่พวกเขาสร้างขึ้น 46
มันเป็นประสบการณ์ที่ช็อก ผู้นำตระหนักว่าการสร้างทีม build/run เป็นเพียงขั้นตอนแรกในการเดินทางที่ยาวนานมาก Erica Morrison, VP Software Engineering เล่าถึง:
เมื่อผมมีส่วนร่วมมากขึ้นกับทีม Network Load Balancer ผมเริ่มรู้สึกเหมือนอยู่ใน The Phoenix Project แม้ว่าผมจะเห็นความคล้ายคลึงหลายอย่างกับหนังสือในประสบการณ์การทำงานก่อนหน้านี้ แต่มันไม่เคยเป็นแบบนี้มาก่อน มันมีงานที่มองไม่เห็น/งานในหลายระบบ: ระบบหนึ่งสำหรับ stories, อีกระบบสำหรับ incidents, อีกระบบสำหรับ CRQs, อีกระบบสำหรับคำขอใหม่ และอีเมลจำนวนมหาศาล และบางอย่างไม่ได้อยู่ในระบบใดเลย สมองของผมระเบิด พยายามติดตามทั้งหมด
ภาระทางปัญญาจากการจัดการงานทั้งหมดนั้นมหาศาล มันยังเป็นไปไม่ได้ที่จะติดตามกับทีมและผู้มีส่วนได้ส่วนเสีย โดยพื้นฐานแล้วใครก็ตามที่ตะโกนดังที่สุดจะอยู่บนสุดของคิว เกือบทุกรายการเป็น priority #1 เนื่องจากการขาดระบบที่ประสานงานในการติดตามและจัดลำดับความสำคัญของงาน
เรายังตระหนักว่ามีหนี้ทางเทคนิคจำนวนมากที่สะสม ซึ่งขัดขวางการอัปเกรด vendor ที่สำคัญหลายอย่าง ทำให้เราต้องอยู่กับ hardware, software และ OS ที่ล้าสมัย นอกจากนี้ยังขาดมาตรฐาน เมื่อเรามีมาตรฐาน พวกมันก็ไม่ได้ถูกนำไปใช้หรือ roll out สู่ production อย่างทั่วถึง
คอขวดด้านบุคลากรที่สำคัญก็มีมากมายเช่นกัน สร้างสภาพแวดล้อมการทำงานที่ไม่ยั่งยืน
สุดท้าย การเปลี่ยนแปลงทั้งหมดต้องผ่านกระบวนการ CAB [change advisory board] แบบดั้งเดิม ซึ่งสร้างคอขวดมหาศาลในการอนุมัติสิ่งต่าง ๆ นอกจากนี้ มี automation เพียงเล็กน้อยที่สนับสนุนกระบวนการเปลี่ยนแปลง ทำให้ทุกการเปลี่ยนแปลงเป็น manual, ไม่สามารถติดตามได้ และมีความเสี่ยงสูงมาก" 47
เพื่อแก้ไขปัญหาเหล่านี้ ทีม CSG ใช้แนวทางหลายด้าน หนึ่ง พวกเขาสร้าง bias for action และการเปลี่ยนแปลงวัฒนธรรมโดยนำบทเรียนจาก John Shook's Model of Change มาใช้: "เปลี่ยนพฤติกรรมเพื่อเปลี่ยนวัฒนธรรม" ทีมผู้นำเข้าใจว่าเพื่อเปลี่ยนวัฒนธรรม พวกเขาต้องเปลี่ยนพฤติกรรม ซึ่งจะส่งผลต่อค่านิยมและทัศนคติ และนำไปสู่การเปลี่ยนแปลงวัฒนธรรมในที่สุด
ถัดไป ทีมงานนำ developers เข้ามาเสริมวิศวกรปฏิบัติการและแสดงให้เห็นถึงสิ่งที่เป็นไปได้ด้วย automation ที่ยอดเยี่ยมและวิศวกรรมที่ประยุกต์ใช้กับปัญหาการปฏิบัติการที่สำคัญ Automation ถูกเพิ่มเข้าไปในการรายงาน traffic และการรายงานอุปกรณ์ Jenkins ถูกใช้เพื่อ orchestrate และ automate งานพื้นฐานที่เคยทำด้วยมือ Telemetry และ monitoring ถูกเพิ่มเข้าไปในแพลตฟอร์มทั่วไปของ CSG (StatHub) และสุดท้าย deployments ถูกทำเป็นอัตโนมัติเพื่อลดข้อผิดพลาดและรองรับ rollback
ทีมงานลงทุนในการนำ config ทั้งหมดใส่ในโค้ดและ version control ซึ่งรวมถึง CI practices รวมถึง lower environments ที่สามารถทดสอบและฝึกซ้อมการ deploy ไปยังอุปกรณ์โดยไม่กระทบ production กระบวนการและเครื่องมือใหม่ช่วยให้การ peer review เป็นเรื่องง่ายเพราะโค้ดทั้งหมดผ่าน pipeline ระหว่างทางไป production
สุดท้าย ทีมงานลงทุนในการนำงานทั้งหมดมารวมไว้ใน backlog เดียว รวมถึง automation เพื่อดึง tickets จากหลายระบบเข้าสู่ระบบกลางที่ทีมสามารถทำงานร่วมกันและจัดลำดับความสำคัญของงานได้
Erica Morrison เล่าถึงบทเรียนสุดท้าย:
เราทำงานหนักมากในการเดินทางครั้งนี้เพื่อนำแนวปฏิบัติที่ดีที่สุดที่เรารู้จาก Development มาสู่โลกของ Ops มีหลายสิ่งในการเดินทางครั้งนี้ที่ไปได้ดี แต่ก็มีพลาดมากมายและเซอร์ไพรส์มากมาย เซอร์ไพรส์ที่ใหญ่ที่สุดน่าจะเป็นว่า Ops นั้นยากแค่ไหน การอ่านเกี่ยวกับมันเป็นเรื่องหนึ่ง แต่การได้สัมผัสมันด้วยตัวเองเป็นอีกเรื่อง
นอกจากนี้ การจัดการการเปลี่ยนแปลงก็น่ากลัวและไม่สามารถมองเห็นได้สำหรับ developers ในฐานะทีม development เราไม่มีรายละเอียดเกี่ยวกับกระบวนการเปลี่ยนแปลงและการเปลี่ยนแปลงที่กำลังเกิดขึ้น ตอนนี้เราจัดการกับการเปลี่ยนแปลงในแต่ละวัน การเปลี่ยนแปลงสามารถท่วมท้นและกินเวลาส่วนใหญ่ของสิ่งที่ทีมทำในแต่ละวัน
เรายังยืนยันอีกว่าการเปลี่ยนแปลงเป็นหนึ่งในจุดตัดสำคัญของเป้าหมายที่ขัดแย้งกันระหว่าง Dev และ Ops Developers ต้องการให้การเปลี่ยนแปลงของพวกเขาไปถึง production โดยเร็วที่สุด แต่เมื่อ Ops รับผิดชอบในการนำการเปลี่ยนแปลงนั้นไปใช้และจัดการกับผลกระทบ มันสร้างปฏิกิริยาธรรมชาติที่จะอยากให้ช้าลง ตอนนี้เราเข้าใจแล้วว่าการให้ Dev และ Ops ทำงานร่วมกันเพื่อออกแบบและ implement การเปลี่ยนแปลงสร้าง win-win ที่ปรับปรุงทั้งความเร็วและความเสถียร 48
กรณีศึกษาที่อัปเดตจาก CSG นี้แสดงให้เห็นถึงความสำคัญของการที่ทีม development และ operations ทำงานร่วมกันเพื่อออกแบบและ implement การเปลี่ยนแปลง สร้าง releases ที่มีความเสี่ยงต่ำและไร้ความวุ่นวาย
Conclusion (บทสรุป)
ดังที่ตัวอย่างจาก Facebook, Etsy และ CSG ได้แสดงให้เห็น การ releases และ deployments ไม่จำเป็นต้องเป็นเรื่องที่มีความเสี่ยงสูงและวุ่นวายที่ต้องใช้วิศวกรหลายสิบหรือหลายร้อยคนทำงานตลอด 24 ชั่วโมงเพื่อให้เสร็จ ในทางตรงกันข้าม พวกมันสามารถกลายเป็นเรื่องปกติและเป็นส่วนหนึ่งของงานประจำวันของทุกคน การทำเช่นนี้ เราสามารถลด deployment lead times จากเดือนเป็นนาที ทำให้องค์กรของเราสามารถส่งมอบคุณค่าให้ลูกค้าได้อย่างรวดเร็วโดยไม่ก่อให้เกิดความโกลาหลและการหยุดชะงัก ยิ่งไปกว่านั้น ด้วยการให้ Dev และ Ops ทำงานร่วมกัน ในที่สุดเราก็สามารถทำให้งาน Operations เป็นมนุษย์มากขึ้น