Deploy VM-Based Application ง่ายๆ แถม Rollback ด้วย Jenkins บน Google Cloud Platform

Chainarong Tangsurakit
rootuser.cc
Published in
3 min readJun 30, 2017

This article also available in english version. Please click here!

ต้องบอกก่อนว่า Infrastructure หลักๆ ของบริษัท HotelQuickly ตอนนี้ รันอยู่บน Google Container Engine (Kubernetes Cluster) เกือบหมดแล้ว แอพพลิเคชั่นส่วนใหญ่เราสร้างละจัดวางบน Concept ของ Micro-Services ซึ่งจะมีขนาดเล็ก, เบา, รู้น้อย… ขอเรียกแอพพลิเคชั่นที่วางอยู่บนระบบนี้ว่า Modern-System ครับ

หน้าตา Console สำหรับดูแลแอพพลิเคชั่น และ Node ต่างๆ บน Kubernetes

แต่ก็เหมือนบริษัทอื่นๆ นั่นแหละ… เรามีแอพพลิเคชั่นอีกกลุ่มนึง ที่มันใหญ่โตมโหฬาร (Monolithic application) แอพพลิเคชั่นอเนกประสงค์ ที่ผ่านการปู้ยี้ปู้ยำมาร่วมสิบถึงยี่สิบ มือด้วยกัน… ซึ่งแอพเหล่านี้ใช้ Nette PHP Framework ในการพัฒนา และรันอยู่บน Google Compute Engine ที่ตั้ง Autoscale Group ไว้ หลัง Load Balance ขอเรียก แอพเหล่านี้ว่า Legacy-System

แอพบางตัว ยังไม่ได้จัดการยัดลง Container เนื่องด้วยหลายๆ ปัจจัย (CPU-Intensive)

ในบทความนี้ ผมจะพุ่งเป้าไปที่เรื่องของขั้นตอนการ Develop และ Deploy ลง Production ของเจ้า Legacy-System ที่กล่าวถึงไปนะครับ

Development Phase ก่อนหน้าการเปลี่ยนแปลง

ก่อนหน้านี้ หลังจากที่เราเสร็จสิ้นส่วนการ Coding แล้ว สิ่งที่เราทำต่อไปเป็นประจำก็คือ Commit และ Push ขึ้น Git Remote Repository ซึ่งของที่ HotelQuickly เราจะใช้ GitHub ครับ ซึ่งตัว Commit ที่ Developer Push เข้ามานี้เอง จะเป็นตัวจุดชนวนเริ่มต้นเส้นทาง CI (Continuous Integration)​ ซึ่งในทีมผมใช้ Jenkins เป็นตัวจัดการ CI Jobs ต่างๆ ครับ

วิธีการกำหนดขั้นตอนต่างๆ ว่า จะให้ Jenkins ทำอะไรบ้าง เราใช้ Jenkins Pipeline (Jenkinsfile) ในการควบคุมครับ ซึ่งหน้าที่หลักๆ ของขั้นตอนก่อนการเปลี่ยนแปลง จะเน้นเรื่องของการ Run Test อย่างเดียว หลังจากนั้น Jenkins ก็จะส่ง Response ตอบกลับไปให้ GitHub ว่า Test ผ่าน หรือไม่ผ่าน เป็นอันจบขั้นตอนที่ผมเรียกว่า Development Phase

DEVELOPMENT PHASE ก่อนการเปลี่ยนแปลง

Deployment Phase ก่อนการเปลี่ยนแปลง

เอาล่ะ! เมื่อทุกอย่างไปได้สวย, Run Test ก็ผ่านฉลุย… เราก็พร้อมเข้าสู่ขั้นตอนการ Deploy… ซึ่งก่อนหน้าการเปลี่ยนแปลง, Developer จะต้องเข้าห้อง Slack #deployment ซึ่งจะมีเจ้า hubot นามว่า @wall-e คอยเฝ้าห้องนี้อยู่ เมื่อ Developer พร้อม Deploy ก็เพียงพิมพ์ข้อความสั่ง @wall-e หลังจากนั้น มันก็จะไปรัน Script ansible-playbook เพื่อ Update working directory บนเครื่อง Production ทุกเครื่องหลัง Load Balance ให้ตรงกับ Commit ล่าสุดบน GitHub Repository เป็นอันจบส่วนของ Deployment Phase

DEPLOYMENT PHASE ก่อนการเปลี่ยนแปลง

แล้วปัญหาคืออะไรหละ ?

แน่นอนครับ ก่อนที่เราจะเริ่มต้นสร้างอะไร เราควรตอบคำถามให้ได้ก่อนว่า มันเข้ามาช่วยแก้ไขปัญหาอะไร… ซึ่งผมลิสต์รายการปัญหาของระบบเดิมไว้ดังนี้

  • ไร้มาตรฐาน… เพราะที่ HQ เราค่อนข้างซีเรียสเรื่องความเป็นมาตรฐานมากครับ
  • Developer สามารถ Deploy Test-failed ไปยัง Production ได้ (โอ้วว…)
  • Rollback ทำได้ไม่ง่ายนัก
  • มี Downtime ระหว่างที่ Node ใหม่ Spin-up ขึ้นมา (เพราะต้องติดตั้งส่วนต่างๆ จาก Based-image เดิม)

เมื่อเรารับทราบปัญหาเหล่านี้แล้ว ก็ถึงเวลาที่ต้องจัดการมัน! ซึ่งสิ่งที่ผมทำก็คือ ควบรวมส่วนของ Develop และ Deploy เข้าด้วยกัน โดยใช้ Jenkins CI จะได้รูปตามด้านล่างครับ

การ Deploy รูปแบบใหม่

จากไดอะแกรมด้านบนนี้ ผมจะใช้ Jenkins ในการ Deploy แทนที่จะให้ Developer เป็นคนจุดฉนวน (แต่ยังต้องอาศัยการโต้ตอบ ในช่วงก่อน Deploy จริงอยู่ดี)

ในรูปแบบใหม่นี้ ตัว Jenkins จะเป็นคนตรวจสอบก่อนว่า Test Case ผ่านหรือใหม่ ซึ่งเจ้า Jenkins ก็จะอนุญาตให้เฉพาะ Test Case ที่ผ่านเท่านั้น ได้เดินทางต่อไปยังขั้นตอนถัดๆ ไป นั่นคือ การทำงานของ Packer ที่จะ Build VM-Image โดยอาศัย ansible-playbook ครับ

เมื่อเจ้า Packer Build Image สำเร็จแล้ว มันก็จะรีบวิ่งมาบอก Developer ผ่าน Slack Channel ว่า “พร้อม Deploy ละนะจ้า” … หาก Developer พร้อมรับชะตากรรมแล้ว ก็กดปุ่ม Proceed บน Jenkins เพื่อเริ่มทำการ Rolling-update ของเหล่า Servers ใน Instance Groups โดยอาศัยคำสั่งของ gcloud SDK command-line. (อันนี้เป็น Alpha Feature อยู่ครับ สนใจเพิ่มเติมคลิกที่นี่เลย)

เอาตั้งแต่ต้นจนจบมาต่อกัน ก็จะได้ไดอะแกรมตามรูปนี้ครับ

จบปัญหา!

รูปแบบการ Deploy ใหม่นี้ ช่วยผมแก้ปัญหาต่างๆ ที่ได้กล่าวไปข้างต้น… เราใช้ Jenkins CI เพื่อให้เป็นมาตรฐานเดียวกันกับบริษัทอื่นๆ Developer ก็ไม่สามารถ Push Test Failed Code ได้อีกต่อไป เวลา Rollback ก็ทำได้ง่ายๆ เพราะเรามี Image Version ก่อนล่าสุดเก็บไว้ แถมเวลาจะ Spin-up เครื่องก็ทำได้รวดเร็ว เพราะไม่ต้องเสียเวลา Install นู่น นั่น นี่ จาก Based-image (ไม่ต้องเสียเวลา Provisioning) แค่ Pull image แล้วก็พร้อมรับ Traffic เลยจ้า

ลาก่อนเจ้า wall-e เพื่อนยาก… ขอต้อนรับ BB-8 เข้าสู่ทีม BB-8 จะคอยเตือน Developer เวลาพร้อม Deploy สู่ Production

บทส่งท้าย

หลังจากที่ผมเขียนบทความเสร็จ ก็แชร์ไปตามที่ต่างๆ แล้วก็มีคนแนะนำว่า ให้ลองพิจารณา Spinnaker.io ด้วย เพราะเป็น Google Product เองเลย แถมยัง Opensource อีกต่างหาก… เท่าที่ผมดูคร่าวๆ คือ จะเป็นที่โฟกัสในช่วงของ CD (Continuous Deployment) และมีฟีเจอร์เด็ดๆ อย่าง Blue/Green Deployment หรือ Rollback มาพร้อมการติดตั้งเลย… ลองฟัง Podcast ของผู้พัฒนาแบบเต็มๆ กันได้ที่นี่เลย

ส่วนตัวผมยังไม่ได้ลองเล่น แต่คิดว่าเด็ด ใครได้ลองสัมผัสแล้ว ก็มาแชร์กันได้นะครับ… และในส่วนของ CI อาจจะลองหยิบ Container Registry มาเล่นดูได้ครับ เท่าที่ฟังๆ บางบริษัท ใช้ Tools ตัวนี้แทน Jenkins ไปเลยทีเดียว…

ถ้าถูกใจบทความ ฝากกดไลค์ Facebook Page เตาะแตะต๊อกแต๊ก ทีนะคร๊าบบ https://www.facebook.com/rootusercc/ เป็นกำลังใจให้ผู้เขียนสุดพลัง :-)

เกี่ยวกับ Developer Team ที่ HotelQuickly

ทีมของพวกเรามีขนาดไม่ใหญ่มาก… ทำให้เรามีความ Agile สูงสุดเต็มพิกัด… รับฟังความคิดเห็นของทุกคน พยายามเปลี่ยนโน่น ทำนี่ ตลอดเวลา เพื่อพัฒนาทีมให้เลเวลอัพตลอดเวลา ทีมของพวกเราไม่เคยกลัวความผิดพลาด เพราะเรามีมุมมองว่า นั่นเป็นสิ่งที่ทำให้เราเติบโตขึ้น… ถ้าคุณกำลังมองหาบริษัทที่เป็นเหมือนสนามเด็กเล่น ให้คุณได้ทดลอง ค้นคว้าเทคโนโลยี และเครื่องมือใหม่ๆ สำหรับพัฒนาโครงสร้างต่างๆ ของระบบแล้วละก็ HotelQuickly คือคำตอบที่คุณตามหาอยู่… มาร่วมพัฒนาทีม และโปรดักส์ไปด้วยกัน… ดูตำแหน่งงานว่างได้ที่นี่เลยครับ!

This article also available in english version. Please click here!

--

--