Principles of Microservice Deployment (หลักการของการ Deploy Microservice)
ด้วยตัวเลือกมากมายในการ deploy microservices ของคุณ ผมคิดว่ามันสำคัญที่ผมจะต้องกำหนดหลักการหลักบางอย่างในเรื่องนี้ ความเข้าใจที่มั่นคงในหลักการเหล่านี้จะช่วยคุณได้ไม่ว่าคุณจะตัดสินใจเลือกอะไรในท้ายที่สุด เราจะดูแต่ละหลักการอย่างละเอียดในไม่ช้า แต่เพื่อเริ่มต้น นี่คือแนวคิดหลักที่เราจะครอบคลุม:
Isolated execution
รัน microservice instance ในลักษณะที่แยกจากกัน (isolated) เพื่อให้แต่ละตัวมี computing resource เป็นของตัวเอง และการทำงานของมันไม่สามารถกระทบ microservice instance อื่นที่รันอยู่ใกล้เคียงได้
Focus on automation
เมื่อจำนวน microservice เพิ่มขึ้น automation ก็ยิ่งสำคัญมากขึ้นเรื่อย ๆ มุ่งเน้นเลือกเทคโนโลยีที่รองรับ automation ในระดับสูง และรับเอา automation มาเป็นส่วนหลักของวัฒนธรรมของคุณ
Infrastructure as code
แสดง configuration ของ infrastructure ของคุณเพื่อให้ automation ง่ายขึ้นและส่งเสริมการแบ่งปันข้อมูล เก็บโค้ดนี้ไว้ใน source control เพื่อให้สามารถสร้าง environment ขึ้นใหม่ได้
Zero-downtime deployment
ขยายแนวคิด independent deployability ไปอีกขั้น และให้แน่ใจว่าการ deploy microservice เวอร์ชันใหม่สามารถทำได้โดยไม่มี downtime ต่อผู้ใช้ service ของคุณ (ไม่ว่าจะเป็นมนุษย์หรือ microservice อื่น)
Desired state management
ใช้แพลตฟอร์มที่รักษา microservice ของคุณไว้ในสถานะที่กำหนดไว้ โดยเปิด instance ใหม่หากจำเป็นเมื่อเกิด outage หรือ traffic เพิ่มขึ้น
Isolated Execution (การทำงานแบบแยกส่วน)
คุณอาจถูกล่อใจ โดยเฉพาะในช่วงต้นของการเดินทางสู่ microservices ที่จะใส่ microservice instance ทั้งหมดของคุณลงบนเครื่องเดียว (ซึ่งอาจเป็นเครื่อง physical เดียวหรือ VM เดียว) ดังที่แสดงใน Figure 8-10 ในแง่ของการจัดการ host เพียงอย่างเดียว โมเดลนี้ง่ายกว่า ในโลกที่ทีมหนึ่งจัดการ infrastructure และอีกทีมจัดการซอฟต์แวร์ ภาระงานของทีม infrastructure มักเป็นฟังก์ชันของจำนวน host ที่ต้องจัดการ ถ้ามี service มากขึ้นถูกอัดลงบน host เดียว ภาระงานการจัดการ host จะไม่เพิ่มขึ้นตามจำนวน service ที่เพิ่มขึ้น
Figure 8-10. Microservice หลายตัวต่อหนึ่ง host
อย่างไรก็ตาม โมเดลนี้ก็มีความท้าทายอยู่บ้าง ประการแรก มันทำให้การ monitor ยากขึ้น ตัวอย่างเช่น เมื่อ track CPU ผมต้อง track CPU ของแต่ละ service แยกจากกันหรือไม่? หรือผมสนใจ CPU ของ host โดยรวม? side effect ก็หลีกเลี่ยงได้ยากเช่นกัน ถ้า service หนึ่งอยู่ภายใต้โหลดที่สูงมาก มันอาจลด resource ที่มีให้ส่วนอื่น ๆ ของระบบ นี่เป็นปัญหาที่ Gilt ผู้ค้าปลีกแฟชั่นออนไลน์ เคยพบเจอ เริ่มต้นด้วย Ruby on Rails monolith Gilt ตัดสินใจย้ายไปสู่ microservices เพื่อให้ scale แอปพลิเคชันได้ง่ายขึ้น และรองรับจำนวนนักพัฒนาที่เพิ่มขึ้นได้ดีขึ้นด้วย ในตอนแรก Gilt ให้ microservices หลายตัวอยู่ร่วมกันบนกล่องเดียว แต่โหลดที่ไม่สม่ำเสมอของ microservice ตัวหนึ่งส่งผลเสียต่อทุกอย่างที่รันอยู่บน host เดียวกัน สิ่งนี้ทำให้การวิเคราะห์ผลกระทบจาก host failure ซับซ้อนขึ้นด้วย—การนำ host เพียงตัวเดียวออกจากการใช้งานสามารถส่งผลกระทบเป็นวงกว้างได้
การ deploy service ก็อาจซับซ้อนมากขึ้นเช่นกัน เพราะการทำให้แน่ใจว่า deployment หนึ่งไม่กระทบอีก deployment หนึ่งนำมาซึ่งความยุ่งยากเพิ่มเติม ตัวอย่างเช่น ถ้าแต่ละ microservice มี dependency ที่แตกต่างกัน (และอาจขัดแย้งกัน) ที่ต้องติดตั้งบน shared host ผมจะทำให้มันทำงานได้อย่างไร?
โมเดลนี้ยังสามารถขัดขวางความเป็นอิสระของทีมได้อีกด้วย ถ้า service ของทีมที่ต่างกันถูกติดตั้งบน host เดียวกัน ใครจะเป็นผู้กำหนดค่า host สำหรับ service ของตัวเอง? แน่นอนว่าสิ่งนี้มักจะจบลงด้วยการที่ทีมกลางเป็นผู้จัดการ ซึ่งหมายความว่าต้องมีการประสานงานมากขึ้นเพื่อให้ service ถูก deploy ได้
โดยพื้นฐานแล้ว การรัน microservice instance จำนวนมากบนเครื่องเดียวกัน (ไม่ว่าจะเป็น virtual หรือ physical) ท้ายที่สุดจะบั่นทอนหนึ่งในหลักการสำคัญของ microservices โดยรวม—นั่นคือ independent deployability ดังนั้นจึงสรุปได้ว่าเราต้องการรัน microservice instance แบบแยกส่วนจริง ๆ ดังที่เราเห็นใน Figure 8-11
Figure 8-11. Microservice เดียวต่อหนึ่ง host
Microservice instance แต่ละตัวได้รับ execution environment ที่แยกส่วนเป็นของตัวเอง มันสามารถติดตั้ง dependency ของตัวเอง และมี resource ที่ถูกกันไว้เป็นของตัวเอง
ตามที่ Neal Ford เพื่อนร่วมงานเก่าของผมกล่าวไว้ แนวทางการทำงานหลายอย่างของเราเกี่ยวกับการ deploy และการจัดการ host เป็นความพยายามที่จะ optimize สำหรับความขาดแคลนของ resource ในอดีต ถ้าเราต้องการเครื่องอีกเครื่องเพื่อให้ได้ isolation ทางเลือกเดียวของเราคือการซื้อหรือเช่าเครื่อง physical อีกเครื่อง ซึ่งมักใช้เวลานานและส่งผลให้เกิดพันธะทางการเงินระยะยาว จากประสบการณ์ของผม ไม่ใช่เรื่องแปลกที่ลูกค้าจะจัดหา server ใหม่เพียงทุกสองถึงสามปี และการพยายามหาเครื่องเพิ่มเติมนอกเหนือจากกรอบเวลานี้ก็ทำได้ยาก แต่ platform คอมพิวเตอร์แบบ on-demand ได้ลดต้นทุนของ computing resource ลงอย่างมาก และการพัฒนาของเทคโนโลยี virtualization หมายถึงความยืดหยุ่นที่มากขึ้น แม้แต่สำหรับ infrastructure ที่ host ในองค์กรเอง
เมื่อ containerization เข้ามาร่วมวง เรามีตัวเลือกมากกว่าที่เคยมีมาสำหรับการจัดหา execution environment แบบแยกส่วน ดังที่ Figure 8-12 แสดงให้เห็น พูดกว้าง ๆ เราจะเห็นสเปกตรัมตั้งแต่การมีเครื่อง physical เฉพาะสำหรับ service ของเรา ซึ่งให้ isolation ที่ดีที่สุดแต่อาจมีต้นทุนสูงที่สุด ไปจนถึง container ที่อีกด้านหนึ่ง ซึ่งให้ isolation ที่อ่อนกว่าแต่มักคุ้มค่ากว่าและ provision ได้เร็วกว่ามาก เราจะกลับมาพูดถึงรายละเอียดเฉพาะเกี่ยวกับเทคโนโลยีอย่าง containerization ในบทนี้อีกครั้ง
Figure 8-12. Trade-off ที่แตกต่างกันเกี่ยวกับโมเดล isolation
ถ้าคุณ deploy microservices ของคุณไปยัง platform ที่ abstract มากขึ้น เช่น AWS Lambda หรือ Heroku isolation นี้จะถูกจัดหาให้คุณ ขึ้นอยู่กับลักษณะของ platform เอง คุณอาจคาดหวังได้ว่า microservice instance ของคุณจะจบลงด้วยการรันอยู่ภายใน container หรือ dedicated VM เบื้องหลัง
โดยทั่วไปแล้ว isolation รอบ ๆ container ได้พัฒนาไปมากพอที่จะทำให้มันเป็นตัวเลือกที่เป็นธรรมชาติมากขึ้นสำหรับ microservice workload ความแตกต่างของ isolation ระหว่าง container และ VM ลดลงจนถึงจุดที่สำหรับ workload ส่วนใหญ่ container นั้น "ดีพอ" ซึ่งเป็นเหตุผลส่วนใหญ่ที่ทำให้มันเป็นตัวเลือกยอดนิยม และเป็นเหตุผลที่มันมักจะเป็นตัวเลือกเริ่มต้นของผมในสถานการณ์ส่วนใหญ่
Focus on Automation (มุ่งเน้นที่ Automation)
เมื่อคุณเพิ่ม microservice มากขึ้น คุณจะมีชิ้นส่วนที่ต้องจัดการมากขึ้น—process มากขึ้น สิ่งที่ต้อง configure มากขึ้น instance ที่ต้อง monitor มากขึ้น การย้ายไปสู่ microservices ผลักดันความซับซ้อนจำนวนมากเข้าไปในพื้นที่ operational และถ้าคุณจัดการ operational process ของคุณด้วยวิธีแบบ manual เป็นส่วนใหญ่ นี่หมายความว่า service ที่มากขึ้นจะต้องการคนมากขึ้นเรื่อย ๆ ในการทำสิ่งต่าง ๆ
แทนที่จะเป็นแบบนั้น คุณต้องมุ่งเน้นอย่างไม่ลดละที่ automation เลือกเครื่องมือและเทคโนโลยีที่รองรับให้สิ่งต่าง ๆ ถูกทำโดยอัตโนมัติ โดยควรมองไปที่การทำงานร่วมกับ infrastructure as code (ซึ่งเราจะครอบคลุมในไม่ช้า)
เมื่อจำนวน microservice เพิ่มขึ้น automation ก็ยิ่งสำคัญมากขึ้นเรื่อย ๆ ให้พิจารณาอย่างจริงจังถึงเทคโนโลยีที่รองรับ automation ในระดับสูง และรับเอา automation มาเป็นส่วนหลักของวัฒนธรรมของคุณ
Automation ยังเป็นวิธีที่คุณสามารถทำให้แน่ใจว่านักพัฒนาของคุณยังคงมี productivity อยู่ การให้ความสามารถแก่นักพัฒนาในการ self-service provision service แต่ละตัวหรือกลุ่มของ service คือกุญแจสำคัญที่จะทำให้ชีวิตของพวกเขาง่ายขึ้น
การเลือกเทคโนโลยีที่รองรับ automation เริ่มต้นจากเครื่องมือที่ใช้จัดการ host คุณสามารถเขียนโค้ดหนึ่งบรรทัดเพื่อเปิด virtual machine หรือปิดมันได้หรือไม่? คุณสามารถ deploy ซอฟต์แวร์ที่คุณเขียนโดยอัตโนมัติได้หรือไม่? คุณสามารถ deploy การเปลี่ยนแปลง database โดยไม่ต้องมีการแทรกแซงด้วยมือได้หรือไม่? การรับเอาวัฒนธรรม automation มาใช้เป็นกุญแจสำคัญถ้าคุณต้องการควบคุมความซับซ้อนของสถาปัตยกรรม microservice ให้อยู่หมัด
Two case studies on the power of automation (สองกรณีศึกษาเกี่ยวกับพลังของ Automation)
คงจะเป็นประโยชน์ที่จะยกตัวอย่างที่เป็นรูปธรรมสักสองสามตัวอย่างที่อธิบายพลังของ automation ที่ดี บริษัท realestate.com.au (REA) ของออสเตรเลียให้บริการประกาศอสังหาริมทรัพย์สำหรับลูกค้ารายย่อยและองค์กรในออสเตรเลียและที่อื่น ๆ ในภูมิภาคเอเชียแปซิฟิก ตลอดหลายปีที่ผ่านมา บริษัทได้ย้าย platform ของตนไปสู่การออกแบบแบบ distributed microservices มากขึ้น เมื่อเริ่มต้นการเดินทางนี้ พวกเขาต้องใช้เวลาจำนวนมากในการทำให้เครื่องมือรอบ ๆ service ถูกต้อง—ทำให้นักพัฒนาสามารถ provision เครื่อง, deploy โค้ด และ monitor service ของพวกเขาได้ง่าย สิ่งนี้ทำให้เกิดการทุ่มงานล่วงหน้าเพื่อเริ่มต้นสิ่งต่าง ๆ
ในสามเดือนแรกของความพยายามนี้ REA สามารถย้าย microservice ใหม่เพียงสองตัวเข้าสู่ production ได้ โดยทีมพัฒนารับผิดชอบทั้งหมดของการ build, deploy และ support service ในสามเดือนถัดมา มี service ระหว่าง 10 ถึง 15 ตัวขึ้น live ในลักษณะเดียวกัน เมื่อสิ้นสุดช่วงเวลา 18 เดือน REA มี service มากกว่า 70 ตัวใน production
รูปแบบนี้ยังสอดคล้องกับประสบการณ์ของ Gilt ที่เรากล่าวถึงก่อนหน้านี้ อีกครั้งหนึ่ง automation โดยเฉพาะเครื่องมือที่ช่วยนักพัฒนา เป็นตัวขับเคลื่อนการเติบโตอย่างก้าวกระโดดในการใช้ microservices ของ Gilt หนึ่งปีหลังจากเริ่มการย้ายไปสู่ microservices Gilt มี microservice ประมาณ 10 ตัวที่ live อยู่ ภายในปี 2012 มีมากกว่า 100 ตัว และในปี 2014 มี microservice มากกว่า 450 ตัวที่ live อยู่—หรือประมาณสาม microservice ต่อนักพัฒนาหนึ่งคนใน Gilt อัตราส่วนของ microservice ต่อนักพัฒนาแบบนี้ไม่ใช่เรื่องแปลกในองค์กรที่มีความเชี่ยวชาญในการใช้ microservices โดย Financial Times ก็เป็นบริษัทที่มีอัตราส่วนใกล้เคียงกัน
Infrastructure as Code (IAC)
เมื่อขยายแนวคิดของ automation ต่อไป infrastructure as code (IAC) เป็นแนวคิดที่ infrastructure ของคุณถูก configure โดยใช้โค้ดที่เครื่องอ่านได้ คุณอาจกำหนด configuration ของ service ของคุณใน chef หรือ puppet file หรืออาจเขียน bash script บางอย่างเพื่อตั้งค่าสิ่งต่าง ๆ—แต่ไม่ว่าคุณจะใช้เครื่องมือใดในท้ายที่สุด ระบบของคุณสามารถถูกนำไปสู่สถานะที่รู้จักได้ผ่านการใช้ source code แน่นอนว่าแนวคิดของ IAC อาจถือได้ว่าเป็นวิธีหนึ่งในการ implement automation ผมคิดว่ามันคุ้มค่าที่จะเรียกมันออกมาเป็นสิ่งของมันเอง เพราะมันพูดถึง วิธีการ ที่ automation ควรถูกทำ Infrastructure as code ได้นำแนวคิดจากการพัฒนาซอฟต์แวร์เข้าสู่พื้นที่ operations การกำหนด infrastructure ของเราผ่านโค้ดทำให้ configuration นี้สามารถถูก version control, ทดสอบ และทำซ้ำได้ตามต้องการ สำหรับข้อมูลเพิ่มเติมในหัวข้อนี้ ผมแนะนำหนังสือ Infrastructure as Code ฉบับพิมพ์ครั้งที่ 2 โดย Kief Morris 1
ในทางทฤษฎี คุณสามารถใช้ภาษาโปรแกรมใดก็ได้เพื่อนำแนวคิดของ infrastructure as code ไปใช้ แต่ก็มีเครื่องมือเฉพาะทางในพื้นที่นี้ เช่น Puppet, Chef, Ansible และอื่น ๆ ซึ่งทั้งหมดได้แนวทางมาจาก CFEngine รุ่นก่อนหน้า เครื่องมือเหล่านี้เป็นแบบ declarative—มันช่วยให้คุณกำหนดในรูปแบบข้อความว่าคุณคาดหวังให้เครื่อง (หรือชุด resource อื่น ๆ) มีลักษณะอย่างไร และเมื่อ script เหล่านี้ถูกนำไปใช้ infrastructure จะถูกนำไปสู่สถานะนั้น เครื่องมือที่ใหม่กว่าได้ก้าวไปไกลกว่าการ configure เครื่องเดียว และมองไปที่การ configure ชุด cloud resource ทั้งหมด—Terraform ประสบความสำเร็จอย่างมากในพื้นที่นี้ และผมตื่นเต้นที่จะเห็นศักยภาพของ Pulumi ซึ่งมุ่งหวังจะทำสิ่งที่คล้ายกัน แม้จะโดยการให้คนใช้ภาษาโปรแกรมปกติแทนที่จะเป็น domain-specific language ที่มักถูกใช้โดยเครื่องมือเหล่านี้ AWS CloudFormation และ AWS Cloud Development Kit (CDK) เป็นตัวอย่างของเครื่องมือเฉพาะ platform ในกรณีนี้รองรับเฉพาะ AWS—แม้ว่าจะควรสังเกตว่าถึงแม้ผมจะทำงานกับ AWS เท่านั้น ผมก็ยังชอบความยืดหยุ่นของเครื่องมือแบบ cross-platform อย่าง Terraform มากกว่า
การ version control infrastructure code ของคุณช่วยให้คุณมีความโปร่งใสเกี่ยวกับว่าใครเป็นผู้เปลี่ยนแปลง ซึ่งเป็นสิ่งที่ auditor ชื่นชอบ มันยังทำให้การสร้าง environment ขึ้นใหม่ ณ จุดเวลาใดจุดเวลาหนึ่งง่ายขึ้นด้วย นี่เป็นสิ่งที่มีประโยชน์อย่างยิ่งเมื่อพยายามตามหา defect ในตัวอย่างที่น่าจดจำตัวอย่างหนึ่ง ลูกค้ารายหนึ่งของผม ในฐานะส่วนหนึ่งของคดีความในศาล ต้องสร้างระบบที่กำลังรันอยู่ทั้งหมดขึ้นใหม่ ณ เวลาที่กำหนดเมื่อหลายปีก่อน จนถึงระดับ patch ของ operating system และเนื้อหาของ message broker ถ้า environment configuration ถูกเก็บไว้ใน version control งานของพวกเขาคงจะง่ายขึ้นมาก—แต่เมื่อเป็นจริง พวกเขาต้องใช้เวลากว่าสามเดือนอย่างทุกข์ทรมานในการพยายามสร้าง production environment เก่าขึ้นใหม่ให้เหมือนเดิม โดยต้องไล่ดูอีเมลและ release note เพื่อพยายามหาว่าใครทำอะไรไปบ้าง คดีความนี้ ซึ่งดำเนินมานานแล้ว ก็ยังไม่ได้รับการแก้ไขในเวลาที่ผมสิ้นสุดงานกับลูกค้ารายนี้
Zero-Downtime Deployment (การ Deploy แบบไม่มี Downtime)
ดังที่คุณคงเบื่อหน่ายกับการได้ยินผมพูดซ้ำ ๆ independent deployability นั้นสำคัญมากจริง ๆ อย่างไรก็ตาม มันก็ไม่ใช่คุณสมบัติที่แน่นอนตายตัวเช่นกัน ความอิสระมากแค่ไหนจึงจะเรียกว่าอิสระจริง ๆ? ก่อนบทนี้ เราได้พิจารณา independent deployability ในแง่ของการหลีกเลี่ยง implementation coupling เป็นหลัก ก่อนหน้าในบทนี้ เราพูดถึงความสำคัญของการให้ microservice instance มี execution environment ที่แยกส่วน เพื่อให้แน่ใจว่ามันมีความเป็นอิสระในระดับหนึ่งที่ระดับ physical deployment แต่เราสามารถไปได้ไกลกว่านั้น
การ implement ความสามารถในการ zero-downtime deployment สามารถเป็นก้าวกระโดดครั้งใหญ่ในการช่วยให้ microservices ถูกพัฒนาและ deploy ได้ ถ้าไม่มี zero-downtime deployment ผมอาจต้องประสานงานกับ upstream consumer เมื่อผม release ซอฟต์แวร์เพื่อแจ้งเตือนพวกเขาถึง outage ที่อาจเกิดขึ้น
Sarah Wells จาก Financial Times อ้างถึงความสามารถในการ implement zero-downtime deployment ว่าเป็นประโยชน์เดี่ยวที่ใหญ่ที่สุดในแง่ของการเพิ่มความเร็วในการส่งมอบ ด้วยความมั่นใจว่า release จะไม่รบกวนผู้ใช้ของพวกเขา Financial Times สามารถเพิ่มความถี่ในการ release ได้อย่างมาก นอกจากนี้ zero-downtime release ยังสามารถทำได้ง่ายขึ้นมากในช่วงเวลาทำงานปกติ นอกเหนือจากข้อเท็จจริงที่ว่าการทำเช่นนี้ช่วยปรับปรุงคุณภาพชีวิตของคนที่เกี่ยวข้องกับ release (เมื่อเทียบกับการทำงานตอนเย็นหรือวันหยุดสุดสัปดาห์) ทีมที่พักผ่อนเพียงพอและทำงานในช่วงกลางวันมีแนวโน้มที่จะทำผิดพลาดน้อยลง และจะได้รับการสนับสนุนจากเพื่อนร่วมงานหลายคนเมื่อพวกเขาต้องแก้ไขปัญหา
เป้าหมายตรงนี้คือ upstream consumer ไม่ควรสังเกตเห็นอะไรเลยเมื่อคุณทำการ release สิ่งนี้จะเป็นไปได้มากน้อยแค่ไหนขึ้นอยู่กับลักษณะของ microservice ของคุณอย่างมาก ถ้าคุณใช้การสื่อสารแบบ asynchronous ที่รองรับด้วย middleware ระหว่าง microservice ของคุณกับ consumer อยู่แล้ว สิ่งนี้อาจ implement ได้ง่ายมาก—message ที่ถูกส่งมาหาคุณจะถูกส่งมอบเมื่อคุณกลับมาออนไลน์ แต่ถ้าคุณใช้การสื่อสารแบบ synchronous เรื่องนี้อาจมีปัญหามากกว่า
แนวคิดอย่าง rolling upgrade สามารถมีประโยชน์ตรงนี้ และนี่เป็นพื้นที่หนึ่งที่การใช้ platform อย่าง Kubernetes ทำให้ชีวิตคุณง่ายขึ้นมาก ด้วย rolling upgrade microservice ของคุณจะไม่ถูกปิดทั้งหมดก่อนที่เวอร์ชันใหม่จะถูก deploy แต่ instance ของ microservice ของคุณจะค่อย ๆ ลดจำนวนลงในขณะที่ instance ใหม่ที่รันซอฟต์แวร์เวอร์ชันใหม่ค่อย ๆ เพิ่มขึ้น ควรสังเกตว่าถ้าสิ่งเดียวที่คุณต้องการคือความช่วยเหลือเรื่อง zero-downtime deployment การ implement Kubernetes อาจเกินความจำเป็นไปมาก บางสิ่งที่ง่ายกว่าอย่างกลไก blue-green deployment (ซึ่งเราจะสำรวจเพิ่มเติมใน "Separating Deployment from Release" ) ก็สามารถทำงานได้อย่างมีประสิทธิภาพเช่นกัน
อาจมีความท้าทายเพิ่มเติมในแง่ของการจัดการปัญหาอย่าง long-lived connection และอื่น ๆ มันเป็นความจริงอย่างแน่นอนว่าถ้าคุณสร้าง microservice โดยคำนึงถึง zero-downtime deployment ตั้งแต่แรก คุณมักจะทำได้ง่ายกว่ามากเมื่อเทียบกับการนำสถาปัตยกรรมระบบที่มีอยู่แล้วมาพยายาม retrofit แนวคิดนี้ในภายหลัง ไม่ว่าคุณจะสามารถ implement zero-downtime deployment สำหรับ service ของคุณได้ตั้งแต่แรกหรือไม่ ถ้าคุณไปถึงจุดนั้นได้ คุณจะต้องชื่นชมระดับความเป็นอิสระที่เพิ่มขึ้นนั้นอย่างแน่นอน
Desired State Management (การจัดการ Desired State)
Desired state management คือความสามารถในการกำหนดข้อกำหนด infrastructure ที่คุณมีสำหรับแอปพลิเคชันของคุณ และให้ข้อกำหนดเหล่านั้นถูกรักษาไว้โดยไม่ต้องมีการแทรกแซงด้วยมือ ถ้าระบบที่กำลังรันอยู่เปลี่ยนแปลงไปในลักษณะที่ desired state ของคุณไม่ถูกรักษาไว้อีกต่อไป platform ที่อยู่เบื้องล่างจะดำเนินการตามขั้นตอนที่จำเป็นเพื่อนำระบบกลับสู่ desired state
ในฐานะตัวอย่างง่าย ๆ ของวิธีที่ desired state management อาจทำงาน คุณสามารถกำหนดจำนวน instance ที่ microservice ของคุณต้องการ อาจรวมถึงการกำหนดว่าต้องการ memory และ CPU เท่าไรสำหรับ instance เหล่านั้นด้วย platform เบื้องล่างบางตัวจะนำ configuration นี้ไปใช้ นำระบบไปสู่ desired state มันเป็นหน้าที่ของ platform ที่จะระบุว่าเครื่องไหนมี resource ว่างที่สามารถจัดสรรให้กับจำนวน instance ที่ร้องขอได้ ดังที่ Figure 8-13 แสดงให้เห็น ถ้า instance หนึ่งตายลง platform จะรับรู้ว่าสถานะปัจจุบันไม่ตรงกับ desired state และดำเนินการที่เหมาะสมโดยการเปิด instance ทดแทนขึ้นมา
Figure 8-13. Platform ที่จัดการ desired state management เปิด instance ใหม่ขึ้นมาเมื่อตัวหนึ่งตาย
ความงดงามของ desired state management คือ platform เองเป็นผู้จัดการว่า desired state จะถูกรักษาไว้อย่างไร มันปลดปล่อยทั้งฝ่าย development และ operations จากการต้องกังวลว่าสิ่งต่าง ๆ ถูกทำอย่างไรอย่างแน่ชัด—พวกเขาแค่ต้องมุ่งเน้นไปที่การกำหนด desired state definition ให้ถูกต้องตั้งแต่แรก มันยังหมายความว่าเมื่อเกิดปัญหา เช่น instance ตาย hardware เบื้องล่างล้มเหลว หรือ data center ปิดตัวลง platform สามารถจัดการปัญหาให้คุณได้โดยไม่ต้องมีการแทรกแซงจากมนุษย์
แม้จะเป็นไปได้ที่จะสร้าง toolchain ของตัวเองเพื่อใช้ desired state management แต่โดยทั่วไปแล้วคุณจะใช้ platform ที่รองรับมันอยู่แล้ว Kubernetes เป็นหนึ่งในเครื่องมือที่รับเอาแนวคิดนี้มาใช้ และคุณยังสามารถบรรลุสิ่งที่คล้ายกันได้โดยใช้แนวคิดอย่าง autoscaling group บน public cloud provider อย่าง Azure หรือ AWS อีก platform หนึ่งที่สามารถให้ความสามารถนี้ได้คือ Nomad ต่างจาก Kubernetes ที่มุ่งเน้นการ deploy และจัดการ container-based workload Nomad มีโมเดลที่ยืดหยุ่นมากในการรัน application workload ประเภทอื่น ๆ ด้วยเช่นกัน เช่น Java application, VM, Hadoop job และอื่น ๆ มันอาจคุ้มค่าที่จะพิจารณาถ้าคุณต้องการ platform สำหรับจัดการ workload แบบผสมที่ยังคงใช้แนวคิดอย่าง desired state management
Platform เหล่านี้รับรู้ถึง resource ที่มีอยู่เบื้องล่างและสามารถจับคู่ request สำหรับ desired state กับ resource ที่มีอยู่ได้ (หรือไม่ก็บอกคุณว่ามันเป็นไปไม่ได้) ในฐานะ operator คุณจะถูกแยกออกจาก low-level configuration—คุณสามารถพูดสิ่งที่ง่าย ๆ เช่น "ผมต้องการ 4 instance กระจายไปทั้งสอง data center" และพึ่งพา platform ของคุณให้แน่ใจว่ามันถูกทำให้คุณ Platform ที่แตกต่างกันให้ระดับการควบคุมที่แตกต่างกัน—คุณสามารถทำ desired state definition ที่ซับซ้อนมากขึ้นได้ถ้าต้องการ
การใช้ desired state management บางครั้งอาจสร้างปัญหาให้คุณได้ถ้าคุณลืมว่ากำลังใช้มันอยู่ ผมจำได้ว่ามีสถานการณ์หนึ่งที่ผมกำลังปิด development cluster บน AWS ก่อนกลับบ้าน ผมกำลังปิด managed virtual machine instance (ที่จัดหาโดยผลิตภัณฑ์ EC2 ของ AWS) เพื่อประหยัดเงิน—มันจะไม่ถูกใช้ตลอดทั้งคืน อย่างไรก็ตาม ผมพบว่าทันทีที่ผมฆ่า instance หนึ่งตัว อีก instance หนึ่งก็ผุดขึ้นมาแทน ผมใช้เวลาสักพักกว่าจะรู้ว่าผมได้ configure autoscaling group ไว้เพื่อให้แน่ใจว่ามีจำนวนเครื่องขั้นต่ำ AWS เห็น instance ตายและเปิด instance ทดแทนขึ้นมา ผมใช้เวลา 15 นาทีเล่นเกม whack-a-mole แบบนี้ก่อนจะรู้ว่าเกิดอะไรขึ้น ปัญหาคือเราถูกคิดเงินสำหรับ EC2 เป็นรายชั่วโมง แม้ instance จะรันเพียงหนึ่งนาที เราก็ถูกคิดเงินเต็มชั่วโมง ดังนั้นการดิ้นรนของผมในตอนท้ายวันจึงมีค่าใช้จ่ายที่ค่อนข้างสูง ในแง่หนึ่ง นี่เป็นสัญญาณของความสำเร็จ (อย่างน้อยก็เป็นสิ่งที่ผมบอกตัวเอง)—เราตั้งค่า autoscaling group ไว้ก่อนหน้านี้ และมันก็ทำงานได้ดีจนถึงจุดที่เราลืมไปว่ามันมีอยู่ มันเป็นเพียงเรื่องของการเขียน script เพื่อปิด autoscaling group เป็นส่วนหนึ่งของการปิด cluster เพื่อแก้ปัญหาในอนาคต
Prerequisites (ข้อกำหนดเบื้องต้น)
เพื่อใช้ประโยชน์จาก desired state management platform ต้องมีวิธีบางอย่างในการเปิด instance ของ microservice ของคุณโดยอัตโนมัติ ดังนั้นการมี deployment ที่อัตโนมัติเต็มรูปแบบสำหรับ microservice instance จึงเป็นข้อกำหนดเบื้องต้นที่ชัดเจนสำหรับ desired state management คุณอาจต้องพิจารณาอย่างรอบคอบด้วยว่า instance ของคุณใช้เวลานานแค่ไหนในการเปิดตัว ถ้าคุณใช้ desired state management เพื่อให้แน่ใจว่ามี computing resource เพียงพอในการรับโหลดผู้ใช้ ถ้า instance ตาย คุณจะต้องการ instance ทดแทนโดยเร็วที่สุดเพื่อเติมเต็มช่องว่างนั้น ถ้าการ provision instance ใหม่ใช้เวลานาน คุณอาจต้องมี capacity ส่วนเกินไว้เพื่อรับมือกับโหลดในกรณีที่ instance ตาย เพื่อให้ตัวเองมีพื้นที่หายใจเพียงพอในการนำสำเนาใหม่ขึ้นมา
แม้คุณจะสามารถแฮก solution สำหรับ desired state management ขึ้นมาเองได้ ผมไม่แน่ใจว่ามันเป็นการใช้เวลาของคุณอย่างคุ้มค่า ถ้าคุณต้องการรับเอาแนวคิดนี้มาใช้ ผมคิดว่าคุณควรใช้ platform ที่รับเอาแนวคิดนี้เป็น first-class concept ดีกว่า เนื่องจากนี่หมายถึงการทำความเข้าใจกับสิ่งที่อาจเป็น deployment platform ใหม่และแนวคิดและเครื่องมือที่เกี่ยวข้องทั้งหมด คุณอาจต้องการชะลอการรับเอา desired state management มาใช้จนกว่าคุณจะมี microservices จำนวนหนึ่งที่รันอยู่แล้ว สิ่งนี้จะช่วยให้คุณคุ้นเคยกับพื้นฐานของ microservices ก่อนที่จะรับภาระเทคโนโลยีใหม่มากเกินไป Platform อย่าง Kubernetes ช่วยได้มากจริง ๆ เมื่อคุณมีสิ่งของมากมายที่ต้องจัดการ—ถ้าคุณมีเพียงไม่กี่ process ที่ต้องกังวล คุณสามารถรอไว้รับเอาเครื่องมือเหล่านี้มาใช้ทีหลังได้
GitOps
GitOps เป็นแนวคิดที่ค่อนข้างใหม่ที่ริเริ่มโดย Weaveworks นำแนวคิดของ desired state management และ infrastructure as code มารวมกัน GitOps ถูกคิดค้นขึ้นในบริบทของการทำงานกับ Kubernetes ในตอนแรก และนี่คือที่ที่เครื่องมือที่เกี่ยวข้องมุ่งเน้น แม้จะกล่าวได้ว่ามันอธิบาย workflow ที่คนอื่นเคยใช้มาก่อนแล้วก็ตาม
ด้วย GitOps desired state สำหรับ infrastructure ของคุณถูกกำหนดในโค้ดและเก็บไว้ใน source control เมื่อมีการเปลี่ยนแปลง desired state นี้ เครื่องมือบางอย่างจะทำให้แน่ใจว่า desired state ที่อัปเดตแล้วนี้ถูกนำไปใช้กับระบบที่กำลังรันอยู่ แนวคิดคือการมอบ workflow ที่เรียบง่ายขึ้นให้นักพัฒนาสำหรับการทำงานกับแอปพลิเคชันของพวกเขา
ถ้าคุณเคยใช้เครื่องมือ configuration infrastructure อย่าง Chef หรือ Puppet โมเดลนี้จะดูคุ้นเคยสำหรับการจัดการ infrastructure เมื่อใช้ Chef Server หรือ Puppet Master คุณจะมีระบบส่วนกลางที่สามารถ push การเปลี่ยนแปลงออกไปแบบไดนามิกเมื่อมันถูกทำขึ้น การเปลี่ยนแปลงที่เกิดขึ้นกับ GitOps คือเครื่องมือนี้ใช้ความสามารถภายใน Kubernetes เพื่อช่วยจัดการแอปพลิเคชัน ไม่ใช่แค่ infrastructure เท่านั้น
เครื่องมืออย่าง Flux ทำให้การรับเอาแนวคิดเหล่านี้มาใช้ง่ายขึ้นมาก ควรสังเกตด้วยว่า แม้เครื่องมือจะทำให้คุณเปลี่ยนวิธีการทำงานได้ง่ายขึ้น แต่มันไม่สามารถบังคับให้คุณรับเอาแนวทางการทำงานใหม่มาใช้ได้ พูดอีกแบบหนึ่งคือ เพียงเพราะคุณมี Flux (หรือเครื่องมือ GitOps อื่น) ไม่ได้หมายความว่าคุณกำลังรับเอาแนวคิดของ desired state management หรือ infrastructure as code มาใช้
ถ้าคุณอยู่ในโลกของ Kubernetes การรับเอาเครื่องมืออย่าง Flux และ workflow ที่มันส่งเสริมมาใช้อาจช่วยเร่งการนำแนวคิดอย่าง desired state management และ infrastructure as code เข้ามาใช้ เพียงแค่อย่าลืมเป้าหมายของแนวคิดพื้นฐานเหล่านี้ และอย่าตาบอดไปกับเทคโนโลยีใหม่ ๆ ทั้งหมดในพื้นที่นี้!