DevOps คืออะไร นำมาประโยชน์ได้ยังไง และตัวอย่างการทำ DevOps ที่ Credit OK

สวัสดีครับ เนื่องจากผมได้มีโอกาสได้ออกไปสอนน้องนักศึกษาบางมด KMUTT วิชา Software Engineering เรื่องการทำ DevOps จึงขอจดบันทึกเนื้อหาที่จะนำไปสอนขึ้น Blog เอาไว้เผยแพร่ให้ทุกคนได้อ่านกัน ซึ่งในตอนนี้ผมก็จะกล่าวถึงว่า DevOps คืออะไร เกี่ยวกับคนที่ทำงานทางด้านนี้ เนื้องานมีอะไรบ้าง เครื่องมือที่น่าสนใจ ไปจนถึงการใช้งานจริงที่บริษัท Credit OK ว่าเราเอา DevOps ไปใช้งานกันยังไง

ตอนนี้ก็จะยาวๆ หน่อยก็อย่าเพิ่งยอมแพ้กันไปซะก่อนนะครับ 555 เอาล่ะ ผมจะไม่พูดพร่ำเพ้อละ เรามาเริ่มกันเลยดีกว่า สำหรับ Slide ที่ใช้สอน สามารถโหลดได้จากลิงค์นี้เลยครับ http://bit.ly/spicydog-devops-cpe


DevOps คืออะไร?

DevOps เป็นคำที่ย่อมาจาก Development Operations เป็นศาสตร์ที่ช่วยเชื่อมกระบวนการพัฒนาโปรแกรม การส่งเอาขึ้นไป Deploy ให้ผู้ใช้เข้าถึงอย่างได้อย่างมีประสิทธิภาพ มีคุณภาพ ไปจนถึงการติดตามสถานะการทำงานของโปรแกรมเพื่อนำกลับมาพัฒนาปรับปรุงกระบวนการพัฒนาโปรแกรม

DevOps Engineer เปรียบได้กับ System Admin ในสมัยก่อน ที่ทำหน้าที่เอาโปรแกรมขึ้นไปรันบน Server ให้ได้ แล้วคอยดูไม่ให้มันล่มนั่นล่ะ แต่พัฒนาร่างขึ้นมาทำเรื่อง Automation ด้วย คือทำให้กระบวนการทั้งหมดที่ต้องทำมือในสมัยก่อน ทำงานโดยอัตโนมัติได้ นอกจากนั้นยังลงไปช่วยนักพัฒนาทำงานด้วย ในส่วนของการวางสภาพแวดล้อมในการพัฒนาโปรแกรมที่ดี


DevOps Process

DevOps นั้นมีรูปแบบการทำงานค่อนข้างจะตายตัวตามรูปที่อยู่ข้างล่าง ซึ่งจะพยายามทำให้ Process ต่างๆ ทำงานไปได้โดยอัตโนมัติ ไม่ต้องมีคนคอยเข้าไปกด Deploy เองอีกต่อไป ยกเว้นในส่วนของการการวางแผน การพัฒนา และดูผลลัพธ์ ในส่วนนี้ยังจำเป็นต้องอาศัยสมองคนต่อไปอยู่ ในเรื่องของรายละเอียด ผมขออธิบายลงไปในแต่ละขั้นตอน

Plan

การจะพัฒนาโปรแกรมขึ้นมา ต้องมีการวางแผนร่วมกันจากทุกฝ่ายที่เกี่ยวข้องอย่างละเอียดก่อน โปรแกรมเราจะทำอะไรบ้าง จะพัฒนาด้วยภาษาอะไร Framework อะไร จะรันบน Platform อะไร จะไปลงไว้ที่ไหน จะเก็บข้อมูลอย่างไร จะแก้ปัญหาที่เกิดขึ้น และจะพัฒนา Process การทำงานอย่างไร

Create

การสร้างหรือการพัฒนา นี่ก็คือขั้นตอนของการเขียนโปรแกรมขึ้นมา DevOps เข้ามาช่วยทำให้ Developers ทุกคนทำงานบน Environment แบบเดียวกัน ไม่ว่าเขาจะพัฒนาบน OS ใดก็ตาม

เวลา Developer ทำงานบนคอมพิวเตอร์คนละ OS กัน มักจะมีปัญหา “ทำไมโปรแกรมรันบนเครื่องเธอไม่ได้ล่ะ บนเครื่องฉันก็รันได้อยู่นะ!” ซึ่งมันไม่ควรจะเกิดขึ้นแล้วในยุคนี้ที่เรามี Docker ที่ช่วยให้ทุกคนพัฒนาโปรแกรมอยู่บนพื้นฐาน Environment เดียวกันเป๊ะ ตั้งแต่ขั้นตอนการพัฒนาไปจนถึงการส่งโปรแกรมขึ้น Production

Verify

การตรวจสอบอยู่อย่างสม่ำเสมอว่าโปรแกรมที่พัฒนาขึ้นมา ไม่ว่าจะเพิ่มฟีเจอร์อะไรเข้ามาจะไม่ไปกระทบหรือไปก่อบั๊กทำให้การใช้งานเดิมพังเสียหายนั้นเป็นเรื่องสำคัญมาก โดยเฉพาะโปรแกรมขนาดใหญ่ที่ร่วมกันทำกับทีมงานจำนวนมาก เราจะมั่นใจได้อย่างไรว่า Code ที่ Developer X ส่งขึ้นมาจะเข้ากันได้ดีกับการทำงานเดิม

วิธีการที่จะรู้ได้เร็วที่สุดคือ เราจะต้องมีการทำ Testing อย่างครอบคลุมในทุกๆ Components ของโปรแกรม แล้วทำให้มันรันโดยอัตโนมัติทุกครั้งก่อนจะปล่อยโปรแกรมออกไป เมื่อใดที่ Test Fail ก็จะรู้ได้ทันทีว่ามีปัญหาเกิดขึ้นแล้ว ให้หยุดการส่งงานที่มีปัญหาไปก่อน สามารถเข้าไปหาสาเหตุและแก้ไขปัญหาได้อย่างทันท่วงที

Package

การจะส่งโปรแกรมขึ้นไปรันบน Server เพื่อความสะดวกรวดเร็ว จะต้องมีการเอาโปรแกรมไปใส่ใน Technology ที่ออกแบบมาเพื่อนำโปรแกรมไปรันได้อย่างราบลื่น ซึ่งในปัจจุบันนี้เราใช้ Docker กัน

เวลาจะใช้ เราจะสร้าง Docker Image ที่เอาตัวโปรแกรมพร้อมสำหรับการรันใส่อยู่ในนั้น แล้วเอา Docker Image นี้ไป Deploy ที่ไหนก็ได้สามารถรัน Docker ได้ โปรแกรมก็จะรันขึ้นมาพร้อมใช้งาน

Release

เมื่อมี Docker Image พร้อมแล้ว ก็พร้อมสำหรับการนำโปรแกรมไปรันบน Deployment Platform ที่ต้องการ ตอนนี้กำลังทำของ Development หรือทำหรือ Production อยู่ จะต้องเลือกไป Deploy ให้ถูกที่

Configure

โปรแกรมที่พัฒนานั้น จำเป็นอย่างมาก ที่จะต้องตั้งค่าได้ ตัวอย่างการตั้งค่าที่ควรมีเลยก็เช่น การเลือก Database ตั้งค่า Email เป็นต้น

ยิ่งถ้ามี Service แยกอื่นๆ ที่ต้องใช้แล้ว ยิ่งสำคัญ เพราะ Development Server และ Production Server ควรอยู่แยกกันอย่างเด็ดขาด เราจะต้องหาทางสร้าง Docker Image มา 1 อัน แล้วเราจะใช้มัน Deploy ลงบน Environments ที่ต่างกันให้ได้

วิธีการที่จะทำได้ก็คือการทำให้โปรแกรมของเราตั้งค่าได้เนี่ยแหละ คือโปรแกรมที่ไปรันเป็นตัวเดียวกัน แต่เปิดด้วยการตั้งค่าที่แตกต่างกัน ทำให้ได้การทำงานที่แตกต่างกัน โดยปรกติจะใช้ไฟล์ .env และ Environment Variable ในการตั้งค่ากันเป็นมาตรฐานที่ใช้กันบนทุก Platform

Monitor

สุดท้ายที่ขาดไม่ได้เลยคือการตรวจสอบว่าโปรแกรมมันขึ้นไปแล้วทำงานได้ปรกติ มีสุขภาพแข็งแรงดี การดู Log ว่าโปรแกรมเราทำงานมีปัญหาตรงไหน มีความสำคัญอย่างมากในการแก้ไขบั๊ก ยิ่งในตอนนี้ที่มักจะออกแบบให้โปรแกรมมันสามารถทำให้ Horizontal Scale ได้ (การสร้างเครื่องขึ้นมาหลายๆ เครื่องให้มาแบ่ง Load ทำงานแยกกันได้) จำเป็นอย่างยิ่งที่จะต้องมี Centralized Logging System รวบรวม Log เอามาไว้ในที่เดียว เพราะการ Remote เข้าไปอ่าน Log ในแต่ละเครื่องเป็นไปไม่ได้อีกแล้ว

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


ทำไมพักหลังมานี้ DevOps ถึงได้เป็นที่นิยมนัก?

ความเป็นจริงการทำ DevOps ที่กำลังฮิตๆ กันอยู่นี้ เกิดขึ้นมานานมากแล้วในบริษัท Technology ขนาดใหญ่ บริษัทเหล่านั้นมี Stack ในการทำ DevOps ของเขาเองเป็น Internal Tools

แต่ความน่าสนใจมันเกิดขึ้นหลังจากการแพร่หลายของ Docker ที่ทำให้ผู้คนเข้าถึงโลก Container ได้ง่ายขึ้น การทำให้เกิดความมั่นใจว่าโปรแกรมของเราจะไปรันที่ไหนก็ได้โดยได้ผลลัพธ์เหมือนกันแน่นอนเป็นเรื่องสำคัญมาก มันกลายเป็นการยกระดับมาตรฐานการทำงานของวงการ Software Engineering ไปเลย

นอกจากเรื่องความเป็นกระแสแล้ว ก็เป็นเพราะว่ามีเครื่องมือดีๆ ในวงการ DevOps พัฒนาขึ้นมาหลายตัว ตั้งแต่ Docker, Kubernetes, CI/CD Platforms ก็เกิดขึ้นหลายตัว ช่วยให้นักพัฒนาทั่วโลกเข้าถึงเครื่องมือเจ๋งๆ เหล่านี้ได้อย่างทั่วถึง

นอกจากนั้นการทำ DevOps ยังเพิ่ม Productivity ให้กับทีม Engineers ได้อย่างมาก (เมื่อ Implement อย่างถูกวิธีในเวลาที่เหมาะสม) ตั้งแต่เรื่องการนำ Docker มาใช้ในทีมพัฒนา ช่วยให้โปรแกรมที่รันทำงานเหมือนกันทุกคนบนทุก Platform ช่วยให้ทุกคนอุ่นใจได้ว่าโปรแกรมที่รันจะไม่ได้ใช้งานได้แค่บนเครื่องของเขาคนเดียวแล้วไปพังบนเครื่องชาวบ้าน

อีกอย่างก็คือ การทำ ฃ CI/CD Pipeline ให้มัน Test และ Deploy โปรแกรมโดยอัตโนมัติ ช่วยให้ประหยัดเวลาให้กับทีมงานไปได้อย่างมาก เป็นสุดยอดเครื่องอำนวยความสะดวกในการทำงานเลยทีเดียวในมุมมองของผม คือ เราไม่จำเป็นต้องไปห่วงเรื่อง Infra มากเหมือนอย่างแต่ก่อน ไม่ต้อง Remote SSH เข้าไป Deploy เอง ทุกอย่างมันทำอัตโนมัติหมด Git Push ขึ้นไปแล้วเดี๋ยวโปรแกรมของเราที่อยู่บน Cloud ก็จะอัพเดทโดยอัตโนมัติ

อย่างไรก็ดี ใช่ว่าทีมงานตั้งขึ้นมาแล้วควรจะทำ CI/CD เลย ผมมองว่าเรื่อง DevOps นี้ค่อยทำค่อยขยับขยายกันไปได้ ในตอนต้นอาจจะวางให้ Dev กันบน Docker เลย อันนี้ทำได้แต่ต้น จากนั้นรีบพัฒนาเอาผลิตภัณฑ์ให้ออกมาใช้ได้กันก่อนเถอะ พอเราพัฒนาโปรแกรมบน Docker แล้ว เราย่อมจะเอาไปไว้ที่ไหนก็ได้ที่รองรับ Docker ตอนต้นอาจจะ Push ขึ้นไปแล้วกด Deploy เองไปก่อน ยังไงโปรแกรมก็ยังไม่พร้อมจะโชว์ให้คนภายนอกเข้ามาดูอยู่แล้ว (ความจริงช่วงหลังมานี้ก็มีบริการอย่าง Google Cloud Run ที่อำนวยความสะดวกให้เอา Docker Image ขึ้นไปรันได้เลยโดยไม่ต้องตั้ง Server เอง ถ้าผมได้เริ่มใหม่ตอนนี้คงจะ Deploy บน Cloud Run ไปเลยตั้งแต่ต้น คลิกๆ เอาอย่างเดียว) พอถึงเวลาที่ทีมเริ่มจะแข็งแรงแล้ว มีการ Commit Push กันอย่างต่อเนื่อง อยากเห็นผลลัพธ์ อยากลองเล่นกันอยู่ตลอด ถึงตอนนั้นแล้วจึงค่อยขยับขยายทำ CI/CD Pipeline ก็ยังทัน หลังจากนั้นก็นั่งเขียน Code กันชิลๆ

จากที่ได้กล่าวมาจะเห็นได้ว่า มันมีข้อดีหลายอย่างมากจริงๆ ทั้งการเพิ่ม Productivity ของทีม การการันตีคุณภาพของ Software ผ่านการ Automation Testing แล้วยังใช้คนน้อยลงอีกต่างหาก การเอาคอมพิวเตอร์มาทำในสิ่งที่มันควรจะทำได้โดยอัตโนมัติให้หมด แล้วพัฒนาคนของเราให้มาเขียนโปรแกรมให้คอมพิวเตอร์ทำงานให้แทน นั่นคือสิ่งที่ควรจะเกิดขึ้นในยุคนี้ จึงไม่ต้องแปลกใจที่หลายๆ องค์กรหันมาทำ DevOps กันมากขึ้น ทำให้มันกลายเป็นตำแหน่งงานที่ถูกตามหาค่อนข้างมาก แล้วยิ่งเป็นของใหม่ คนทำเป็นยังน้อย ก็เลยเกิดเป็นกระแสต้องการคนสาย DevOps อย่างที่เราเห็นกันอยู่

แต่คำถามที่จะต้องคิดเช่นกันก็คือ แล้วเราจำเป็นต้องมี DevOps Engineers เยอะขนาดไหนกันเพื่อให้เพียงพอต่อตลาด อันนี้ยังไงตัวเลขก็น้อยกว่า Software Developers อย่างแน่นอน


DevOps Engineers วันๆ ทำอะไรกัน?

DevOps เป็นตำแหน่งที่ทำงานอยู่ระหว่าง Developers ของ Customers แบบอยู่เบื้องหลัง คือเวลา Server ล่ม โปรแกรมพัง โหลดไม่ไหว ก็ความรับผิดชอบของ DevOps เนี่ยแหละ ดังนั้นตัวเองจะต้องเข้าใจว่า Developer ต้องการอะไรบ้างเพื่อให้โปรแกรมมันทำงานได้ มีเครื่องมืออะไรที่จะช่วยอำนวยความสะดวกให้เขาได้บ้าง ลงไปถาม ลงไปสอน ลงไปทำให้มันเกิดขึ้นมา

งานของ DevOps โดยแก่นแล้ว จึงเป็นการเขียน Script ทำ Automation และคนคอยดูแล Infrastructure ให้ยั่งยืนในสมัยก่อนเราจะเห็นตำแหน่งนี้เป็น System Admin คอยตั้งค่าเครื่อง Server แล้วเอาโปรแกรมไปลง แต่ตอนนี้ด้วยเทคโนโลยีสำหรับการ Test และ Deploy พัฒนาขึ้นมามาก เราจึงสามารถทำ CI/CD Pipeline เพื่อ Automate งานตรงนี้ได้ทั้งหมด

แต่หากจะให้กล่าวลงไปถึงรายละเอียดแล้ว ก็จะขอเล่าหน้าที่ของ DevOps ที่ผมทำอยู่ปัจจุบัน ซึ่งก็น่าจะคล้ายกันกับทีมอื่นเช่นกัน ดังนี้


พัฒนา Docker Image ให้ทีม Developer ใช้

การพูดว่า “โปรแกรมตอนรันบนเครื่องผมก็ยังใช้ได้นะ” ต้องไม่เกิดขึ้น เราต้องมั่นใจว่า Developer ทุกคนใช้ Docker Image เดียวกันทำงาน และ Docker Image อันนั้นจะต้องเป็นอันเดียวกับที่ใช้ Deploy ด้วย

หน้าที่ของ DevOps คือเขียน Dockerfile และ docker-compose.yaml ไปให้ Developers ใช้งานได้อย่างสะดวกสบาย แล้วถ้า Developer ต้องการอัพเดทตัวแปร Configuration อะไรเพิ่มเติม DevOps ก็จะต้องรู้ด้วย เพื่อจะได้เอาไปตั้งค่าตอน Automation Test และ Deployment ได้อย่างถูกต้อง


พัฒนา CI/CD Pipeline Script

เพื่อให้ทีมงานมั่นใจว่าโปรแกรมที่เขียนมาไม่มีบั๊กที่ได้เขียน Test เอาไว้แล้วโผล่ขึ้นมา ทุกครั้งที่มีการ Push Code ขึ้นไปเพิ่มเติม จึงต้องมีการรันชุดทดสอบการทำงานของโปรแกรมทั้งหมด ถ้าการทดสอบล้มเหลว Developer จะต้องมาแก้บั๊กให้เรียบร้อย ห้ามมีการส่งต่อขึ้นไปให้ผู้ใช้งาน ส่วนถ้าการทดสอบสำเร็จราบรื่น แบบนั้นจึงค่อยปล่อยให้โปรแกรมไปในขั้นตอนต่อไป ก็คือการจับโปรแกรมใส่ Docker Image แล้วเอาไป Deploy บน Platform ที่ต้องการ


สร้าง ตั้งค่า และคอยดูแล Cluster สำหรับ Deployment

DevOps ต้องรู้และเข้าใจข้อจำกัดของเทคโนโลยีที่ใช้งานเป็นอย่างดี เพื่อที่จะได้ใช้งานและแก้ปัญหาได้ ที่บริษัทตอนนี้ Deploy บนเทคโนโลยี 3 ตัว ได้แก่ Cloud Functions, Cloud Run และ Kubernetes เจ้าตัวสุดท้ายนี่ซับซ้อนพอสมควร ต้องสร้างเอง ซึ่งก็เป็นหน้าที่ของ DevOps ที่จะต้องมาทำงานตรงนี้ แล้วก็คอยดูแลให้มันทำงานได้โดยปรกติสุข จะต้องมั่นใจว่า เวลาที่บาง Node มันดับไป แล้ว Platform สามารถเคลื่อนย้าย Container ไป Deploy บนที่ Node ใหม่ได้โดนอัตโนมัติโดยโปรแกรมจะยังสามารถใช้งานได้ตามปรกติ หรือถ้าต้องมี Downtime ก็ต้องทำให้น้อยที่สุดเท่าที่จะเป็นไปได้ เวลาโหลดเข้ามาเยอะๆ ก็ต้องเอาให้ชัวร์ว่า Platform ที่ใช้อยู่รับได้ หรือไม่ก็ต้องตอบให้ได้ว่าจะรับโหลดได้เท่าไหร่ แล้วถ้ามันล้นขึ้นมาแล้วมีแผนสำรองอย่างไร


ติดตั้งและเชื่อมต่อเครื่อง Database ให้ Application ใช้งานได้

ความจริงควรเป็นงาน Database Architecture แต่ตอนนี้เรายังไม่มีคนนั้น ดังนั้นก็เลยให้ DevOps ทำไปก่อน และต้อง Deploy โปรแกรมให้ต่อใช้งานกับ Database บน Production ให้ได้ด้วย

งานนี้ก็ต้องดูว่าจะวาง Database เอาไว้ที่ไหนบ้าง ต้องกระจายโหลดอย่างไรให้สามารถรองรับผู้ใช้ได้แม้จะเข้ามามาก


คอยโวยวายเวลาเจอ Error Log บน Production

ต้องโวยวายให้ทันก่อน User จะเจอปัญหา! หน้าที่คอย Monitor ดู Log ดูความเคลื่อนไหว อันนี้ก็งาน DevOps เช่นกัน เวลาเห็นว่าโปรแกรมพ่น Error อะไรแปลกๆ ออกมา หรือบางครั้งเข้าไปใช้งานแล้วมันผิดปรกติ จะต้องรีบแจ้งให้โปรแกรมเมอร์หาทางแก้ไข เพราะหากปล่อยให้ Error Log ที่ไม่ควรจะขึ้นมาแสดงเยอะๆ จะทำให้เวลาเจอ Error ที่สำคัญขึ้นมาแล้วจะตามดูลำบาก


ทักษะพื้นฐานที่ DevOps พึงมี

Computer Infrastructure

Computer Infrastructure เป็นสิ่งที่ควรอยู่ในกระดูกสันหลังของ DevOps ทุกคน หน้าที่ของเราคือการเอา Application ไปรันบน Deployment Platform ให้ได้ ว่าต้องใช้งาน Platform แบบไหน ต้องทำยังไง มีข้อจำกัดยังไง ต่อกับ Network ยังไง DNS ต้องเซทยังไง และจะต้องรู้ไปถึงขนาดว่า ถ้าจะ Deploy โปรแกรม ทำยังไงให้ไม่มี Downtime จะต้องตั้ง Server ขนาดไหนเพื่อรับโหลด ไปจนถึง ถ้ามี Node เสีย หรือ Cloud พัง จะรับมือกันยังไง จะย้ายไปรันที่ไหนแทน ทำยังไงให้ข้อมูลไม่หาย ทำยังไงให้ User ยังใช้งานได้ต่อ

แล้วเมื่อพูดถึงเรื่อง Computer Server ทักษะที่ต้องมีและดีด้วยคือการใช้ Linux ถึงแม้คุณจะ Deploy บน Windows Platform ก็เถอะ ยังไงหนีไม่พ้น Linux หรอก นานๆ เราจะเข้าไปเขียน Command กันสักที แต่เมื่อไหร่ที่ต้องเขียน มันจะลงไปลึกมาก


Tools & Technology Embracement

ความจริงคนที่ทำงานสายคอมพิวเตอร์ไม่ว่าจะส่วนไหนก็ควรรักการศึกษาเทคโนโลยีใหม่ๆ แต่ที่มาเน้นตรงนี้เพราะช่วงนี้เทคโนโลยีทางฝั่ง DevOps มาเร็วและมาแรงมาก ตั้งแต่ Docker ได้ถือกำเนิดขึ้นมา ก็กลายเป็นยุคทองของการพัฒนาเทคโนโลยีทางด้านนี้ มาจนถึงตอนนี้ที่ปลายปี 2019 ก็ยังไม่มีท่าทาจะชะลอตัว

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

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

นอกจากนั้นก็ต้องศึกษาเทคโนโลยีทางฝั่งด้านการพัฒนา Software Development เอาไว้บ้างด้วยเช่นกัน ศึกษา Best Practices ต่างๆ จะได้คุยงานกับ Developers รู้เรื่อง จะได้ช่วยเขาทำงานได้


Computer Security

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

ไหนจะช่องโหว่ที่เกิดขึ้นมาใหม่เรื่อยๆ ต้องคอยติดตามอัพเดท Patch ทั้ง Infra ทั้ง Dependencies ต่างๆ จะต้องติดตามข่าวสารอยู่เสมอเพื่อให้โปรแกรมของเราอยู่รอดปลอดภัยบนโลกอันโหดร้าย


Communication

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

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


การ Deploy Web Application เขาทำกันอย่างไร แล้วเอาไปลงกันไว้ที่ไหน?

เรื่องต่อเป็นจะขอเล่าเป็นพื้นฐานก่อนจะโหมดเข้มข้นกันคือ เวลาจะเอาโปรแกรมไปรันบน Server เอาไปวางกันไว้ที่ไหนได้บ้าง แล้วต้องทำยังไงกันบ้าง ซึ่งความจริงผมเคยเคยเขียนเอาไว้แล้ว สำหรับท่านที่สนใจอ่านในรายละเอียดเพิ่มเติมสามารถเข้าไปอ่านกันได้ที่ Serverless Big Data Architecture on Google Cloud Platform @ Credit OK EP 1: Server & Application Deployment History

ส่วนทีที่นี้จะขอกล่างแต่เพียงคร่าวๆ ดังนี้

Bare Metal
มันคือการที่เราเอาคอมพิวเตอร์ทั้งเครื่องไปตั้งไว้ที่เน็ตแรงๆ เช่น ISP แล้วก็เอาไฟล์ไปวางบนเครื่องที่ติดตั้ง Web Server เอาไว้ ก็พร้อมใช้งาน แต่เนื่องด้วยการใช้เครื่องอย่างไม่คุ้มค่า เพราะบางทีเว็บมีคนเข้านิดเดียวจะไปตั้งเครื่องทั้งตัวก็ไม่คุ้ม นอกจากนั้นยังจัดการยากอีกต่างหาก

Virtualization
อันนี้คือการทำเครื่องจำรองบนเครื่องจริงๆ หรือทำ VM จึงเกิดเป็นบริการ VPS (Virtual Private Server) ขึ้นมา ช่วยให้ยัดผู้ใช้หลายๆ คนเข้าไปในคอมพิวเตอร์เครื่องเดียวได้ ส่วนการเข้าไปใช้งานจริงก็ไม่ได้ต่างจากการตั้งเครื่อง Bare Metal สักเท่าไหร่ แค่ต้องแบ่งกันใช้กับคนอื่น

Containerization
ต่อมาเป็นเทคโนโลยีที่กำลังได้รับความนิยมสูง โดยการเอาโปรแกรมรันไปรันด้วย Container Engine หรือที่เรารู้จักกันดีก็คือ Docker นั่นเอง ทำให้แทนที่จะต้องตั้งเครื่อง VM ลง OS ไปรันโปรแกรมแล้วเปลืองทรัพยากรสำหรับ OS หลายตัว ก็เอาโปรแกรมหลายๆ ตัวไปรันบน OS เดียวกันได้เลย เทคโนโลยีนี้เกิดขึ้นมาช่วยหลายเรื่องเหลือเกิน ดียังไงเรื่องมันยาว แต่ที่จะขอกล่าวตอนนี้เลยก็คือเรื่องการช่วยให้ Environment หรือสภาพแวดล้อมในการรันโปรแกรมเหมือนกันหมด มั่นใจได้ว่าโปรแกรมจะไม่พังไม่ว่าจะไปรันบน OS ไหน ขอเพียงรันบน Container Engine เดียวกัน และอีกอย่างก็คือเรื่องการ Scale ระบบ ซึ่ง ณ จุดนี้ทางฝั่งของ VM กลายเป็นเครื่องคอมพิวเตอร์ที่ลงเอาไว้เพียง Container Enginer สะดวกต่อการสร้างขึ้นมาหลายๆ เครื่อง แล้วเราเอา Container ไปลงไว้ในเครื่องที่ยังว่างอยู่ ย้ายไปย้ายมา จะสร้างมีหลายๆ ตัวช่วยกันทำงานก็ทำได้หมดผ่านทางสิ่งที่เรียกว่า Container Orchestration ซึ่งยี่ห้อที่ได้รับความนิยมสุดตอนนี้ก็คือ Kubernetes นั่นเอง

Serverless
สุดท้ายคือการ Deploy โปรแกรมบนสถาปัตยกรรมที่ไม่ต้องสนใจเครื่อง Server แล้ว ซึ่งวิธีการนี้ก็เติบโตอย่างมาก มันเรียกว่า Serverless ถึงแม้ชื่อมันจะบอกว่าไม่มีเครื่อง Server แต่ความจริงคือมันก็รันอยู่บนเครื่อง Server เนี่ยแหละ แต่มันเป็นเครื่อง Server จำนวนมากที่ Cloud Provider จัดหาเอาไว้ให้ มากซะจนทุกอย่างมันอัตโนมัติไปหมด ตั้งแต่การ Scale การทำ Network เราแค่เอาโปรแกรมไป Deploy ก็พอ ซึ่งก็มาให้บริการตั้งแต่แบบ CaaS (Container as a Service) ให้เราบอก Path ของ Container Image สำหรับใช้รัน แล้วมันจะเอาไป Deploy ให้เรียบร้อย FaaS (Function as a Service) คือให้เราเอา Code ไปแปะแล้วก็พร้อมใช้งานเลย แบบนี้นี่ง่ายสุดๆ ไปเลย มาถึงตอนนี้เราเลยไม่ต้องห่วงเรื่องการตั้งเครื่องขึ้นมาใช้งานอีกแล้ว นอกจากนั้นราคาก็ยังคิดเป็นเฉพาะการใช้งานจริง คือถ้าไป Deploy ไว้ไม่มีการเข้ามาใช้ก็ไม่เสียเงิน จ่ายเงินเฉพาะเท่าที่มีการเข้ามาใช้งานจริง ทุกอย่างเป็นจริงขึ้นมาได้เพราะว่าการได้รับความนิยมของ Public Cloud เลยจริงๆ


Deployment Platforms ที่ผมอยากแนะนำให้ทำความรู้จัก

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

Google Cloud Run

ตัวนี้มีความใกล้เคียงกับ Kubernetes สูงมาก เพราะมันต่อยอดขึ้นมาจาก Platform ที่ชื่อว่า KNative ซึ่งมีเป้าหมายเพื่อทำให้การ Deployment เป็นแบบ Serverless บน Kubernetes​ กันไปเลย

กล่าวคือ ตอนที่เราใช้ Kubernetes เนี่ย เรายังต้องตั้ง Node ตั้งทรัพยากรวุ่นวาย Pod ต้องเปิดพร้อมรับ User อยู่ตลอดเวลา ตอนไม่มีคนใช้ทำไมจะต้องเสียทรัพยากรตรงนี้ไปด้วยล่ะ

Cloud Run มาตอบโจทย์ตรงนี้เลย เอา Container ไปรันให้เราแบบตอนตั้งค่า Kubernetes นอกจากนั้นยังจัดการเรื่อง Network ส่งออก Domain name แถม HTTPS ให้ด้วย โดยไม่ต้องเซท Routing เองให้วุ่นวาย นอกจากนั้นยังคิดเงินเฉพาะตอนโปรแกรมรันใช้งานจริงๆ เรียกว่าเหมาะสมมากสำหรับโปรเจกต์ที่มีการใช้งานไม่มาก

ผมเคยเขียน Blog เรื่องนี้เอาไว้แล้วเช่นกัน ใครสนใจศึกษาต่อไปดูกันได้ที่นี่ ทำความรู้จักกับ Cloud Run โฮสเว็บด้วย Container แบบไม่ต้องแตะ Infrastructure กันไปเลย

Heroku

Heroku นี่อยู่กันมานานมาก อยู่มาตั้งแต่ก่อน Docker จะดังซะด้วยซ้ำ เป็น PaaS ให้เราส่ง Source Code ทั้งโปรแกรมขึ้นไปรันให้เลย (คล้ายๆ กับ App Engine ของ Google) แต่ง่ายกว่าด้วยการที่เขากำหนด Platform เอาไว้แล้วว่าจะต้องทำอย่างไรถึงจะเอา Code ขึ้นไปรันได้ ทีนี้เวลา Push Code ขึ้นไปบน Git ของ Heroku มันก็จะ Trigger Pipeline โดยอัตโนมัติ เบื้องหลังมันจะไปสร้าง Container จะไปทำอะไรก็เรื่องของมันละ สุดท้ายรอไม่นานโปรแกรมของเราก็จะขึ้นไปรันได้เรียบร้อย

ตัวนี้น่าสนใจมากสำหรับการเริ่มต้นโครงการ หรือทำโปรเจกต์ใช้งานคนเดียวเป็นครั้งเป็นคราว เข้าไปเปิดใช้งานได้กันฟรีๆ เลย ใช้ง่ายไม่ต้องปวดหัวเรื่อง Server

Firebase

Firebase เป็นบริการที่แรกเริ่มเกิดขึ้นมาเพราะโลก Mobile Developer ขี้เกียจทำ Database หลังบ้านเอง Firebase จึงทำ Database ให้ มีระบบ SSO Authentication พร้อมสรรพ เรียกว่า Mobile Application Developers มีชีวิตที่ดีกันไปเลย ต่อมาภายหลังโดย Google มาซื้อไป เลยเกิดการรวมพลังกับ Google Cloud Platform ขึ้น (ซึ่งมันแชร์ Project ข้ามกันและทำให้ผมสับสนมาก)

ตอนนี้ Firebase มีฟีเจอร์ต่างๆ เพิ่มขึ้นมามาก ที่น่าสนใจก็คือมันมีแบบ Google Cloud Functions มาให้ด้วย แต่ล้ำกว่านั้นตรงที่สามารถทำ Routing ได้ เชื่อม Domain ได้ นี่เรียกว่าแทบจะเหมือน Heroku เลย แต่อยู่บนร่างของ Google Cloud Functions นอกจากนั้นก็ยังมี Database ของเดิมของเขาให้ใช้งาน มีระบบ Authentication และอื่นๆ เยอะแยะไปหมด คือดีมาก ใช้ฟรีด้วยนะ (ถ้าไม่ได้ใช้เยอะมาก) แนะนำให้ลองศึกษากันดูครับ ค่อนข้างพร้อมสำหรับการพัฒนา Web Application ระดับย่อมๆ เลยล่ะ

Google Cloud Functions

มาถึงตัวนี้ยิ่งง่ายหนักเข้าไปอีกขั้น แทนที่เราจะต้องไปสร้าง Container ให้วุ่นวาย เราแยก Code ของเราให้เป็น Module เล็กๆ จับขึ้นไปโฮสบน Google Cloud Functions ได้เลย

หน้าตามันก็จะเป็นประมาณว่า เป็นช่องให้ใส่ Code ลงไปว่าจะให้ทำอะไร จากนั้นเลือกว่าจะให้ Trigger ด้วยอะไร เปิดผ่าน HTTP จะใช้ Google Cloud Stoage หรือจะผ่าน Pub/Sub ก็ทำได้ เมื่อมี Trigger มา Code ก็จะรัน เวลามีโหลดมาเยอะๆ ก็จับต่อคิวให้ด้วย สะดวกมากๆ ไม่ต้องห่วงเรื่อง Scale และโหลดเลย

ตัวนี้ที่บริษัทใช้เยอะมาก ผมเขียนกล่าวถึงใน Blog ก่อนๆ ด้วย เข้าไปอ่านกันได้ที่ Serverless Big Data Architecture on Google Cloud Platform @ Credit OK | EP 1

Cloudflare Workers

เล็กลงมาอีกระดับ มาเจอกับ Cloudflare Workers ความจริงแล้ว Cloudflare คือผู้บริการ CDN มี Nodes ให้บริการตั้งอยู่ทั่วโลก มี Interface สำหรับการจัดการ DNS ที่ดีมาก ใช้ฟรีอีกต่างหาก (อีตานี่ใช้แต่ของฟรี) เนื่องจากไหนๆ ฉันมี Nodes ตั้งอยู่ทั่วโลกแล้ว ก็เอามันมีเปิดบริการ Compute ซะเลยซิ จึงเกิดเป็นบริการนี้ขึ้นมา ซึ่งจะให้ดูๆ ไปก็คล้ายๆ กับ Google Cloud Functions นั่นเอง

อย่างไรก็ดี Cloudflare Workers จะทำงานในระดับที่เล็กกว่า เน้นความเร็วจัด เน้นงานที่ประมวลผลน้อยๆ ตัวของมันเองก็ไม่ได้มี Service อื่นๆ มีแต่ Key Value Database ให้ใช้ ก็เลยเหมาะกับการคำนวณอะไรสั้นๆ แต่เน้นความ Reliable แล้วก็เข้าถึงได้อย่างรวดเร็วใน Scale ขนาดใหญ่

ส่วนตัวคือรู้สึกว่าถ้าเอาโปรแกรมไปรันบน Cloudflare Workers เนี่ย แทบจะไม่มีล่มเลย เพราะโปรแกรมของเราจะถูก Deploy บน Server ทีอยู่ทั่วโลก ไม่เหมือนบริการของเจ้าอื่นๆ ที่จะต้องเลือก Region (อาจจะมีล่มก็ต้องตอน Cloduflare มันล่มเนี่ยล่ะ ซึ่งนานมากๆ จะเจอครั้ง เป็น Service ที่ล่มน้อยที่สุดแล้ว)

เรื่องนี้ก็เคยเขียน Blog เอาไว้แล้วเช่นกัน ตามไปอ่านกันได้ที่ ทำ Reverse Proxy เข้า Raspberry Pi เน็ตบ้าน ด้วย Cloudflare Workers และ Heroku

GitLab Pages

สุดท้ายที่อยากให้ลองเล่นกันดูคือ GitLab Pages เจ้านี่ไม่ได้ประมวลผลอะไรละ แค่เอา Static Files ไปแปะไว้ให้เรา แล้วก็เปิดได้ผ่านทางอินเทอร์เน็ตเลย ความเด็ดคือใช้งานได้ฟรีสุดๆ ไปแล้วจ้า แล้วคนที่ใช้ GitLab อยู่แล้วก็แสนสะดวก ยังไงก็ต้องเก็บ Source Code อยู่แล้ว ก็ให้มันเอาไป Deploy ไว้ให้ด้วยเลย

นอกจากนั้นยังสามารถเชื่อม Domain Name ทำ HTTPS ให้ด้วยเรียบร้อย จึงเกิดเป็น Flow ของการทำเว็บไซต์ด้วย Static Web Generator ขึ้นมา คือเว็บที่ไม่ค่อยมีการอัพเดทบ่อยๆ เอาไปโฮสบนนี้เลย ไม่ต้องเสียค่าโฮส จ่ายแต่ค่า Domain แล้วก็ยังสามารถจัดการ Content บนเว็บได้อย่างดี ลองไปอ่านรายละเอียดกันได้ที่ ทำเว็บไซต์ด้วย Hugo แล้วโฮสกันฟรีๆ บน GitLab Pages และ Cloudflare


เทคโนโลยีในวงการ DevOps ที่ต้องรู้จัก

หลังจากพิจารณามาสักพักหนึ่งแล้ว ผมพบว่าสาย DevOps นี้เป็นสายที่เน้นเรื่องเครื่องมือเอามากๆ เรียกว่าถ้าไม่ชอบลองอะไรใหม่ๆ ใช้เครื่องมือไม่เป็น ไม่น่าจะอยู่ได้ เพราะมันเป็นเรื่องของการทำ Automation เอาเครื่องมือมาต่อกันแทบจะทั้งหมด และการทำ Automation ก็จะต้องอาศัยการออกแบบให้คนทำงานกับคอมพิวเตอ์ได้อย่างเป็นระบบ คนกล่าวถึงนี้ก็คือเหล่า Developer นั่นเอง ทำยังไงให้เขาทำงานได้อย่างสะดวกสบายเขียนโปรแกรมและส่ง Code กันขึ้นมาได้อย่างเป็นระบบ แล้วเราจึงนำ Source Code เหล่านั้นไปต่อกับเครื่องมืออื่นอย่างเป็นระบบ เพื่อให้เกิดกระบวนการทำ DevOps ที่สมบูรณ์ (อารมณ์คล้ายกับการต่อ Lego ที่เอาชิ้นส่วนมาต่อกัน) มาถึงจุดนี้เดี๋ยวผมจะมาเล่าถึงเครื่องมือที่นิยมใช้งานในการทำ DevOps


Git (Version Control Software)

แรกเริ่มเลยสำหรับกระบวนการพัฒนาคือการต้องมีโปรแกรมสำหรับจัดการ Source Code ใช้งาน ซึ่งทุกวันนี้ทุกคนก็ควรจะใช้ Git กันอยู่แล้วเนอะ ถ้ายังใช้ไม่เป็น ผมแนะนำให้คุณหยุดอ่าน Blog นี้ ไปเรียน Git ให้เรียบร้อย แล้วค่อยกลับมาคุยกันต่อนะ เพราะว่า Git กลายเป็นเครื่องมือพื้นฐานที่สุดในการทำงานด้านการพัฒนาโปรแกรมไปเสียแล้ว ผมอยากให้น้องๆ โปรแกรเมอร์มือใหม่ใช้ Git ให้เป็นก่อนจะเขียนโปรแกรมได้ซะด้วยซ้ำ

คำถามก็คือ Git มันมาเกี่ยวอะไรกับ DevOps ประการแรกเลยก็คือ มันช่วยให้ Developer สามารถทำงานร่วมกัน พร้อมกันได้ ช่วยเพิ่ม Productivity อย่างทวีคูณ ทีนี้ล่ะ ปัญหาก็มาอยู่ที่ว่า แล้วจะมั่นใจได้ไงว่า Code ที่โปรแกรมเมอร์แต่ละคนจะไม่ทำให้โปรแกรมเจ๊ง เราจึงต้องเขียน Unit Test, Integration Test และอื่นๆ ที่สามารถรันทั่วทั้งโปรแกรมและตรวจสอบได้ว่าทุกอย่างยังทำงานปรกติดี เพื่อความมั่นใจ การ Test ตรงนี้จะต้องทำได้เป็นอัตโนมัติโดยการรันโปรแกรม และทุกครั้งที่มีการ Push Code จาก Git ขึ้นไปรวมกันตรงกลาง จะต้องมีการรันเพื่อตรวจสอบความเรียบร้อย และนี่เป็นที่มาของหัวข้อต่อไปคือ CI/CD

https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow

CI/CD Pipeline

Code จาก Developer ทุก Push ที่ส่งขึ้นไปที่ Repo จะต้องมีการตรวจสอบความถูกต้องอยู่ตลอด เพื่อให้มั่นใจว่า เราไม่ได้ส่งโปรแกรมที่มีปัญหาไปให้ User วิธีการก็คือ การสร้างระบบที่จะถูก Trigger ให้รันโดยอัตโนมัติจากการ Push Code ขึ้นมานั่นเอง ระบบที่ว่านี้เรียกว่า Continuous Integration and Continuous Delivery (CI/CD) และเพิ่มคำว่า Pipeline เข้าไป เพื่อบอกว่ามันเป็นการทำงานที่ต่อเนื่องการโดยอัตโนมัติ โดยขั้นตอนเหล่านี้จะรันบนเครื่อง Server ที่สร้างขึ้นมาเพื่อรันงานพวกนี้โดยเฉพาะ (Pipeline Runner) โปรแกรมที่ผมใช้อยู่เป็นหลักเลยก็คือ GitLab CI/CD เจ้าเดียวกับที่ใช้กับ Git เนี่ยล่ะ มันอยู่ด้วยกัน

https://about.gitlab.com/product/continuous-integration/

DevOps จะต้องเขียน Script ว่า หลังจากมี Code ส่งขึ้นมาแล้ว จะต้องให้มันรันคำสั่งอะไรยังไงบ้าง โดยกระบวนการทำ CI/CD ก็มักจะมีขั้นตอนที่คล้ายๆ กัน ประมาณนี้

  1. Build ขั้นตอนนี้คือการเตรียมโปรแกรมให้พร้อมสำหรับการใช้งาน ขั้นตอนนี้จะโหลด Dependency ต่างๆ แล้วรัน Code สำหรับ Build โปรแกรมให้พร้อมสำหรับการ Test
  2. Test นำโปรแกรมที่ได้จากขั้นตอนก่อนหน้ามารัน Script เพื่อทดสอบการทำงาน การ Test นี้มันก็คือ Code ทั่วไปนี่ล่ะ เพียงแต่ทำหน้าที่ในการตรวจสอบการทำงานของโปรแกรมของเรา รันให้ครบทุกอัน ให้มั่นใจว่าโปรแกรมยังทำงานได้ปรกติดีอยู่แม้จะมีการเปลี่ยนแปลง Source Code ไป ถ้ามี Test ที่ไม่ผ่านขึ้นมา ไม่ต้องเสียใจ ควรยินดี เพราะนั่นคือสัญญาณว่า Test ที่เราเขียนขึ้นมามันมีประโยชน์แล้วเว้ย! นอกจากนั้นเรายังจับบั๊กได้ก่อนจะไปถึงมือ User ด้วย ควรจุดพรุได้เลย แต่ในสถาการณ์ปรกติจะต้อง Test ให้ผ่านทั้งหมด ซึ่งเมื่อผ่านแล้วก็จะไปที่ขั้นตอนต่อไป
  3. Package ขั้นตอนนี้คือการเอาโปรแกรมมาจับใส่กล่องเตรียมพร้อมสำหรับการนำออกไปใช้งาน กล่องที่ว่าก็คือ Docker Image นั่นเอง ถ้าไม่เห็นภาพก็จินตนาการซะว่ามันคือการ Build ให้ได้ไฟล์ .exe ขึ้นมาที่จะเอาไปรันที่ไหนก็ได้นั่นเอง ทีนี้เราก็พร้อมสำหรับการนำโปรแกรมนี้ไปรันที่ไหนก็ได้ที่มี Docker ทีนี้ก็ส่ง Docker Image ที่ได้ไปไว้บนฃฃบน Host ที่เรียกว่า Docker Registry ซึ่งเราจะได้ URL มาหนึ่งอันสำหรับนำไปใช้งาน
  4. Deploy สุดท้ายคือการเอาโปรแกรมไปรันบน Server จริง โดยเราติดต่อเข้าไปหา Server ที่เราใช้งาน อาจจะเป็น Kubernetes หรืออื่นๆ ก็แล้วแต่ เมื่อต่อเข้าไปแล้ว ก็บอกว่าให้เอา Docker Image URL ที่ได้มาจากขั้นตอนก่อนหน้า เอามาใช้ใน Deployment ที่ต้องการ ทีนี้ระบบ Container Orchestration ก็จะทำการ Download Docker Image ลงมา สร้าง Container และทำการรัน เมื่อทุกอย่างเรียบร้อยดีแล้ว มันก็จะลบ Container เวอร์ชั่นเก่าโดยอัตโนมัติ เป็นอันสิ้นสุดกระบวนการ CI/CD

ตัวอย่างหน้าตาของไฟล์ GitLab CI ของ Laravel + VueJS

https://gitlab.com/spicydog/laravel-vuejs-gitlab-kubernetes-demo

Container Technology

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

Docker คืออะไร?

Docker เป็น Container Runtime หรือโปรแกรมที่เอาไว้รัน Container ขึ้นมาใช้งาน แล้ว Container คืออะไร? Container คือรูปแบบหนึ่งของการเอาโปรแกรมไปรัน โดยกำหนดสภาพแวดล้อมที่จำกัดและเฉพาะเจาะจงเอาไว้ได้

เพื่อให้เห็นภาพชัดๆ ผมอยากให้มอง Container เป็นเหมือน VM เนี่ยแหละ แต่แทนที่เราจะต้องรัน OS แยกกันหลายๆ ตัวบนเครื่องคอมพิวเตอร์ ถ้าใช้ Docker ไม่ใช่แบบนั้น มันจะใช้ทรัพยากรจาก Host OS โดยตรง มี OS ตัวเดียวพอ แต่ยังสามารถรักษาคุณสมบัติของการแยกกันอยู่ (Isolation) ของแต่ละ Instance เอาไว้ได้ ซึ่งคุณสมบัตินี้ช่วยให้เราสามารถรันโปรแกรมที่ใช้การตั้งค่า env ที่แตกต่างกันได้บน Host OS ตัวเดียวกันได้

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

https://www.docker.com/resources/what-container

นอกจาก Docker ช่วยให้เราสามารถรันโปรแกรมได้ง่ายขึ้นบนเครื่อง Server แล้ว สิ่งที่ผมเห็นว่าสำคัญยิ่งกว่าอีกก็คือ มันช่วยให้เกิดความสม่ำเสมอในการรันโปรแกรม (Runtime Consistency) ความสม่ำเสมอนี้คือความสม่ำเสมอของ Environment ที่ใช้ในการรันโปรแกรม

การที่พัฒนาโปรแกรมบนเครื่องของเราแล้วโปรแกรมนั้นถูกรันบน Production ด้วยการตั้งค่าเครื่องในแบบเดียวกันนั้น ช่วยให้เราไม่ต้องมาพูดว่า “อ้าว มีบั๊กบน Production หรอ ตอน Dev ในเครื่องผมยังรันได้ไม่มีปัญหาเลย” ยิ่งไปกว่านั้นก็คือ ถ้าเจอบั๊กบน Production บั๊กนั้นก็ย่อมทำให้เกิดได้บนเครื่องของ Local ด้วยเช่นกัน ไหนจะเครื่องเพื่อนร่วมงานก็ช่วยให้ Config เป็นแบบเดียวกันได้อีกไม่ว่าจะใช้ OS อะไร มันจึงช่วยลดปัญหาน่าปวดหัวของ Developer ไปได้อย่างมากกกกกกก และนี่ล่ะที่ผมว่าเป็นสิ่งที่ทำให้ Software Developer ทุกวันนี้หันมาใช้งาน Docker ทำงานกัน คือยอมพัฒนาโปรแกรมบนเครื่องที่ช้าลงหน่อย แต่ว่ามั่นใจว่าโปรแกรมของเราใช้งานได้ไม่ว่าจะเอาไปรัน


Docker Concept

ผู้ที่เพิ่งใช้ Docker ครั้งแรกและคุ้นชินกับการสร้างอะไรแล้วได้ไฟล์อะไรบางอย่างออกมาอาจจะมีความสับสนนิดหน่อยในตอนต้น เพราะสิ่งที่ Build ที่ Download ต่างๆ จะถูกเก็บไว้ใน Docker ทั้งหมด เราจะต้องใช้ Command Line ในการ Query สิ่งที่ถูกบันทึกเอาไว้ออกมา ที่เป็นเช่นนั้นก็เพราะว่า Docker มันมีความซับซ้อนในการทำงานของมันอยู่

ต่อมาผมขอกล่าวถึง Concept การใช้งาน Docker คร่าวๆ โดยภาพรวมแล้วเราเพียงแค่ทำความเข้าใจของ 3 อย่าง ขอให้ดูภาพข้างล่างประกอบก่อน

https://cultivatehq.com/posts/docker/

หลักงานง่ายๆ ประมาณนี้ เริ่มจาก Dockerfile ที่เป็น Script ที่เราเขียนขึ้นมา โดยมันจะทำงานตามขั้นตอนคำสั่งที่เราเขียน เช่น เลือก OS ลงโปรแกรมจนจบ แล้วก็ได้ผลลัพธ์ออกมาเป็น Docker Image ซึ่งเปรียบได้กับการทำแผ่น CD พร้อมสำหรับทำสำเนาเพื่อเอาไปใช้งาน

เราสามารถอัพ Docker Image ขึ้นไปเก็บบน Hosting ได้ด้วย มันมีชื่อเรียกว่า Docker Registry เพื่อให้พร้อมสำหรับการถูกดึงเอาไปใช้ได้จากทุกที่บนโลกอินเทอร์เน็ต

ทีนี้เวลาเราจะใช้งาน Docker Image เราก็สั่ง docker run <docker image> มันจะทำการสร้าง Docker Container ขึ้นมา หน้าตาไส้ในเหมือน Docker Image ที่สร้างเอาไว้เป๊ะ

เราสามารถรัน Container พร้อมกันหลายๆ อันได้ แต่ละอันที่รันมีความเป็นเอกเทศของตัวเอง จินตนาการเหมือนเราเอาแผ่น CD ไปลงบนคอมพิวเตอร์คนละเครื่องกัน ทีนี้เราเปิดเข้าไปใช้งานในแต่ละเครื่องมันก็จะไม่มีการเชื่อมโยงกันอีกต่อไป

เราสามารถสั่งให้เชื่อมไฟล์จากเครื่อง Local ไปวางบน Container ได้ตรงๆ ทำให้โปรแกรมที่รันผ่าน Docker Container ใช้ Source Code เดียวกับที่เราพัฒนาอยู่ เมื่อเป็นเช่นนี้แล้วเราจึงพัฒนาโปรแกรมบน Docker Container ได้เลยโดยไม่จำเป็นต้องลงโปรแกรม Runtime บนเครื่อง

เอาล่ะ ต่อมาเรามาลงถึงรายละเอียดของแต่ละชิ้นส่วนเพื่อความเข้าใจที่มากขึ้นกัน


Dockerfile

Dockerfile เป็น Script ที่เอาไว้เก็บ Command ที่จะสั่งให้สร้าง Docker Image ขึ้นมาว่าจะให้มีคำสั่งอะไรบ้าง โดยพื้นฐานที่ต้องทำความเข้าใจเลยก็คือ เราจะสร้าง Docker Image ของเราโดยใช้ Image ของคนอื่นเป็นฐาน ซึ่ง Image ของคนอื่นที่ว่านี้ เรียกมันว่า Base Image โดยมี Docker Hub เป็นศูนย์กลางในการเก็บ Image เหล่านี้เอาไว้ให้ใช้กันฟรีๆ โดยแทบทั้งหมดล้วนเป็น Open Source

ถามว่าข้างใน Docker เป็นยังไง ขอให้มาดูตัวอย่างกันจะได้เห็นภาพมากขึ้น

นี่คือตัวอย่างของ Docker Image สำหรับ Apache Web Server ที่ใช้ PHP 7.3 เป็นพื้นฐาน โดยจุดประสงค์เพื่อที่จะเอามาใช้งานกับ Laravel จึงต้องมีการปรับค่านิดหน่อย มาลองเริ่มกันทีละบรรทัดเลยดีกว่า

เลือก Base Image จาก php:7.3-apache โดยที่ยอมรับ minor update ทุกครั้งที่ Build เราจะได้ PHP 7.3.x สดใหม่อยู่เสมอ

ต่อมารันคำสั่งเซทตัวแปร Environment ให้ใช้ Document Root Directory ไปที่ /var/www/html/public เพราะว่าเราจะเอาไฟล์วางไว้ที่ /var/www/html/ แต่สำหรับ Laravel ไฟล์ index.php อยู่ใน ./public ดังนั้นจึงต้องมีการปรับนิดหน่อย แต่อันนี้เป็นเพียงการเขียนตัวแปรเพื่อให้ง่ายในการอ่าน

ต่อมาก็ใช้คำสั่ง sed (คำสั่งสำหรับ replace string ใน file บน unix) ให้เปลี่ยนค่าในไฟล์ config ของ apache ให้ชี้ Document Root ไปหาตัวแปร APACHE_DOCUMENT_ROOT ที่เราได้เขียนเอาไว้ก่อนหน้านั้นเอง

ต่อมาทำการลง Extension ต่างๆ ที่จะต้องมีใช้งาน สังเกตว่าจะเขียนคำสั่งต่อกันเป็นพวงเลย นี่เป็น Best Practice ที่จะทำกันบน Docker เพื่อใช้ประโยชน์ในเรื่องของ Docker Image Layer ซึ่งเดี๋ยวจะอธิบายให้ฟังในภายหลัง สัญลักษณ์ที่ต้องรู้จักคือ \ บอกว่า ขอขึ้นบรรทัดใหม่นะ อย่าเพิ่งให้จบ Command แล้วก็ && บอกว่า รันคำสั่งก่อนหน้าสำเร็วแล้ว ให้รันคำสั่งต่อไปด้วย

ต่อมาเป็นการเปิด mod_rewrite เป็นฟีเจอร์ของ Apache ให้สามารถทำ URL สวยๆ ด้วย ไม่ต้องพ่วง .php ตลอด

คำสั่งสุดท้ายคือ CMD ซึ่งจะเป็นคำสั่งสำหรับรัน Container ตอนเอาไปใช้งาน และรันนี่ก็เพื่อการเปิด Server แล้ว แต่ก่อนจะรัน เราทำการปรับ Config อีกนิดหน่อย คือเปลี่ยน Port Apache ให้เป็นอย่างที่เราต้องการ คือโดย Default แล้ว Apache จะเปิดที่ Port 80 แต่เกิดเราอยากจะเปลี่ยนตอน Container มันถูก Spawn ขึ้นมาล่ะ เราก็ใช้ตัวแปร Environment อีกแล้ว ในทีนี้ชื่อว่า PORT นั่นเอง ดังนั้นถ้าจะเปลี่ยนก็แค่ใส่ตัวแปร PORT ลงไปตอนรัน มันก็จะทำการ Replace Config ตรงนี้ ก่อนจะรันคำสั่งให้เปิด Apache Web Server ขึ้นมาใช้งาน

ความจริงแล้วตัวอย่างที่โชว์นี้ยังไม่ค่อยดีเท่าไหร่เพราะยังขาด Best Practice ไปอีกหลายเรื่อง แต่ตอนนี้ขอให้เห็นภาพคร่าวๆ ก่อนหน้า Dockerfile หน้าตาเป็นยังไง

ซึ่งเวลามันทำงาน มันก็จะรันคำสั่งที่เราเขียนๆ ไว้ที่ล่ะเหมือนเดิมทุกครั้งเลย แบบนี้ล่ะที่เขาเรียกว่า Infrastructure as Code (IaC) ในเบื้องต้น


Layers of Docker Image

เรื่องต่อมาที่จะต้องทำความเข้าใจกันก่อนจะออกไปสนามจริงกันคือเรื่อง Layer ที่มีขึ้นเพื่อประสิทธิภาพในการทำงานของ Docker ระบบที่ดีควรมี Caching และ Docker ทำการ Cache Image ออกมาในทุกๆ คำสั่ง คำสั่งใน Dockerfile แต่ละบรรทัดที่เขียนลงไปนั่น มันคือการกระทำ 1 ขั้นตอนที่จะเกิด Layer ขึ้นมา 1 ชั้น โดย 1 Layer นี่ก็คือ Docker Image 1 อัน และสามารถใช้ข้ามกันได้ด้วย ทีนี้ Image ดังกล่าวมันจะถูกเก็บไว้บนเครื่องของเราก่อน ซึ่งตัว Docker Daemon จะจัดการบริหารให้ทั้งหมด สำหรับเรื่อง Layer ขอให้ดูรูปด้านล่างเพื่อให้เห็นภาพว่ามันหน้าตาประมาณไหน

https://subscription.packtpub.com/book/application_development/9781788992329/1/ch01lvl1sec14/understanding-docker-images-and-layers

ทีนี้มันสำคัญอย่างไร ทำไมถึงต้องมาแยกเล่าเป็นเรื่องเป็นราว ขอให้อ่านกันต่อไป

ประการแรกคือเรื่องประสิทธิภาพ ลองจินตนาการว่าเราแก้ Dockerfile ในบรรทัดหลังๆ แล้ว แต่ปรากฎว่าทุกครั้งที่ Build จะต้องมาโหลดมารันทุกอย่างตั้งแต่ต้น แบบนี้ลำบาก รอนานแน่นอน แต่พอ Docker ทำการเซฟ Image ออกมาเป็น Layer แบบนี้แล้ว มันทำให้เพียงดึงชั้นก่อนหน้าที่เคยทำเอาไว้แล้วไม่ได้มีการแก้ไขมาต่อยอด แล้วก็รันคำสั่งต่อไปบนนั้นเลย เราก็จะได้ Image ใหม่ออกมาอย่างรวดเร็ว

แต่เมื่อมี Caching แล้ว ย่อมเกิดปัญหา Cache Invalidate คู่กันเสมอ และนี่เป็นเรื่องที่ต้องระวังให้มาก เพราะมันทำให้เกิดความ Inconsistent ในการสร้าง Docker Image มาลองคิดตามกันดู

จากตัวอย่างที่ผมใช้ PHP 7.3 เป็น Base Image สมมุติวันแรกที่ Build เวอร์ชั่นของ Official Image จริงๆ คือ PHP 7.3.1 ดังนั้นเมื่อเรียกใช้งาน PHP 7.3 ก็จะได้ 7.3.1 ที่เป็นเวอร์ชั่นใหม่สุด ณ ตอนนั้น หนึ่งสัปดาห์ผ่านมา ปรากฎว่า PHP 7.3.1 ดันโชคร้ายมีช่องโหว่ ทาง Official Channel ก็ออก PHP 7.3.2 มาให้ใช้กัน ส่วนตัวเราก็ยังคงใช้ PHP 7.3 ที่ติด Cache อยู่ในเครื่องอยู่ ทำให้การ Build ครั้งต่อไปก็ยังคงเป็น PHP 7.3.1 ต่อไป จึงไม่เกิดการแก้ช่องโหว่ขึ้นทั้งๆ ที่ก็ตั้งเอาไว้แล้วว่าให้มันอัพเดทได้ ถ้าไม่เข้าไปตรวจสอบก็คงไม่เจอ ดังนั้นการ Build Docker Image จึงควรทำบนระบบ CI/CD ที่ออกแบบมาจัดการงานเรื่องนี้โดยเฉพาะ เพราะการ Build ควรจะต้องทำโดยไม่ติด Cache

ยัง ยังมีอีก ปัญหาต่อมากลับกันกับปัญหาเมื่อสักครู่ แต่ทีนี้เล่น Scale ใหญ่ขึ้นมาหน่อย สมมุติมือใหม่ลองของบอกว่า ผมใช้ Docker ของ PHP 7 ไปเลยก็ละกัน จะได้ใช้ความสามารถของ PHP ได้อย่างเต็มที่ตลอด ก็สร้าง Image ออกมาใช้งานสบายใจ Test กันได้อยู่เรื่อยมา จนกระทั้ง.. PHP 7.4 ออกมา มีการ Obsolete บางฟังก์ชั่นที่เคยมีใน PHP 7.3 แต่ตอนนี้ไม่มีแล้ว แล้วทีมงานก็ยังคงสบายใจอยู่โดยไม่เห็นภัยร้ายที่กำลังคืบคลานเข้าทำ มิหนำซ้ำทีมนี้ดันไม่ทำ Unit Testing ไม่ทำ CI/CD อีกต่างหาก วันหนึ่ง Deploy โปรแกรมผ่านทาง Docker Image ตัวใหม่ที่เป็น 7.4 มันก็ Build ผ่านปรกติ ไอ้ตอนส่งขึ้นไปก็ยังไม่มีใครรู้สึกว่ามีปัญหาอะไร เพราะยังไม่มีใครไปถูกเจ้าฟังก์ชั่นที่ Obsolete จนกระทั้งวันที่หัวหน้าเข้ามาลองเล่นโปรแกรม นั่นล่ะครับถึงจะมีคนมาเจอปัญหา เจอแบบนี้หนาวสะท้านกันทั้งทีมแน่นอน ก็ผมก็ใช้ Docker แล้ว เขาบอกว่ามัน Consistent บลาๆๆ ว่ากันไป แต่สิ่งที่นายเขียนไปใน Dockerfile มันไม่ควรจะเป็นอย่างนั้นไงล่ะ

นี่คือเรื่องที่ต้องระวังให้มากนะครับ Best Practice คือเราจะต้องเข้าใจข้อจำกัดของโปรแกรมที่พัฒนาขึ้นมา ใช้ได้กับเวอร์ชั่นไหนบ้าง Update Major ได้ไหม หรือได้แค่ Minor หรือไม่ได้เลยก็ต้อง Lock เลข Version ให้ดี แต่ที่สำคัญที่สุดเลยคือการเขียน Testing นะครับ อย่าละเลยเด็ดขาด พยายามเขียนให้เยอะที่สุดเท่าที่จะเป็นไปได้ ทำ CI/CD ให้เรียบร้อย ทุกครั้งที่ Push Code ขึ้นไปให้มันรันไปเลย เวลาเสียจะได้รู้ตัวได้ไว อย่าให้ให้เกิดเหตุไประเบิดบน Production บั๊กเล็กน้อยก็แล้วไป แต่ถ้ามันกระทบเรื่อง Security ของโปรแกรมล่ะก็ ตัวใครตัวมันละงานนี้

เล่าซะน่ากลัว แล้วทำไมเขาไม่ปิดฟีเจอร์นี้ไปเลยล่ะ ไม่ต้อง Cache มันแล้ว คือมันไม่ใช่เรื่องของ Cache หรือไม่ Cache หรอก เพราะต่อให้ไม่ Cache มันก็พลาดได้อยู่ดีในท่าเดียวกับเคสสุดท้ายที่ผมเล่า ก็ Official เขาจะอัพเดท คุณไปห้ามอะไรเขาไม่ได้ คนที่ต้องรู้คือคนที่เอาไปใช้งาน ต้องกำหนด Version ที่เหมาะสมกับโปรแกรมของตัวเอง นอกจากนั้น Caching ก็ช่วยให้ประสิทธิภาพการทำงานของ Docker อย่างมหาศาล แทนที่จะต้องไปโหลด Image มาใหม่ทั้งหมดทุกครั้ง โหลดแค่ส่วนต่างนิดๆ หน่อยๆ มาใช้ อะไรๆ ก็เร็วขึ้นไปหมด รวมไปถึงการ Deploy โปรแกรมก็เร็วขึ้นด้วยเช่นกัน ดังนั้นจะมาใช้ Docker ต้องเข้าใจตรงนี้อย่างกระจ่างแจ้ง ผมขอย้ำเรื่องนี้เป็นครั้งสุดท้าย


Docker Build

เอาล่ะ หลังจากที่ได้ Dockerfile แล้ว เราจะสร้าง Docker Image กัน ซึ่งไม่ยากเลย ก็แค่รันคำสั่ง Docker Build . (. คือให้ใช้ Dockerfile ใน directory ปัจจุบัน) มันก็จะทำการรัน Script ที่เราได้เขียนเอาไว้ รอมันทำจนเสร็จ ก็จะเห็นตัวเลขฐาน 16 (hex) ออกมาท้ายสุดหนึ่งชุด นั่นคือ ID ของ Docker Image ที่เราได้ออกมา นั่นล่ะครับคือ Docker Image ที่เราจะเอามาใช้กันต่อ

ส่วนเวลาใช้งานจริง เราจะจับ Source Code หรือโปรแกรมที่ถูก Compile แล้วลงไปใน Docker Image เลย เวลาเอาไปรันก็จะได้โปรแกรมขึ้นมาพร้อมใช้งานได้ทันที

เราสามารถส่ง Docker Image ขึ้น Docker Registry เพื่อใช้งานผ่านอินเทอร์เน็ต ได้ด้วยคำสั่ง docker push


Docker Run

หลังจากได้ Docker Image มาแล้ว ต่อมาเราจะเอามาใช้งานแล้ว การใช้งานเราจะต้องใช้งานผ่าน Docker Container เท่านั้น คิดซะว่ามันคือการสร้างเครื่อง VM ขึ้นมาใช้นั่นล่ะ วิธีการจะรันนั้นก็แสนง่าย เพียงสั่ง docker run <image> โดย <image> ก็คือ ID หรือ URL ของ Docker Image นั่นเอง ถ้ามันไม่มีในเครื่องมันก็จะไปโหลดลงมาให้โดยอัตโนมัติ สั่งเสร็จแล้วก็จะได้ Container ขึ้นมาใช้งานแล้วล่ะ

แต่ทีนี้จะใช้งานจริง มันก็ต้องมา Source Code ของโปรแกรมที่เราจะเอามารัน โดยมากจะใช้งานเชื่อม Directory ในเครื่อง เข้ากับ Directory ของ Container เพื่อให้มันอ่านไฟล์ตรงกัน สิ่งนี้เราเรียกกันว่า Mount Volume พอไฟล์ที่เราเขียนขึ้นไปอยู่กับ Container ที่พร้อมรัน เมื่อนั้นประโยชน์จึงเกิดขึ้น โปรแกรมของเราถูกรันขึ้นแล้ว ซึ่งเดี๋ยวจะขออธิบายให้เห็นภาพมากขึ้นในส่วนของ docker-compose ต่อไป

ขอแถมคำสั่งเอาไว้ Remote เข้าไปใน Container ซะหน่อย นั่นก็คือ docker exec -it <CONTAINER_ID> /bin/sh โดยหา CONTAINER_ID ได้จากคำสั่ง docker ps


Docker Compose

สุดท้ายที่อยากจะเล่าเกี่ยวกับ Docker คือ Docker Compose เป็นโปรแกรมที่ช่วยให้โลกของ Developer เปลี่ยนไปเลยทีเดียว

Docker Compose เป็นโปรแกรมที่เอาไว้ช่วยรัน Container ขึ้นมา โดยอิงจากไฟล์ตั้งค่า docker-compose.yml ซึ่งมีประโยชน์มาก เพราะว่าเวลาพัฒนาโปรแกรมจริง เราจะต้องมี Application มี Database และอื่นๆ อีกในบางครั้ง การใช้งาน Docker Compose เป็นการสร้าง Environment สำหรับการพัฒนาโปรแกรมขึ้นมาเพียงคำสั่งเดียว นอกจากนั้นไฟล์ Config นี้เราก็ใส่ลงไปใน Git ด้วย ทีนี้ทีมงานก็เลยใช้ Runtime Environment เดียวกันได้ ช่วยให้การพัฒนาง่ายขึ้นอย่างมาก ง่ายไปถึงขนาดที่ว่า นักพัฒนาไม่จำเป็นจะต้องติดตั้ง Dependency ที่ใช้รันโปรแกรมบนเครื่องเลยซะด้วยซ้ำแต่ก็สามารถทำงานได้ทันที


Deployment & Container Orchestration

เมื่อเรามี Docker Image สำหรับโปรแกรมของเราเรียบร้อยแล้ว พร้อมสำหรับการเอาไปรัน คำถามคือจะเอาไปรันได้ยังไง อย่างง่ายที่สุดเลยคือการใช้ Docker Compose เนี่ยแหละรัน ตั้งค่าให้เรียบร้อยแล้วก็ docker-compose run บนเครื่อง VM แล้วก็ใช้งานได้เลย แต่เส้นทางนี้นี่แทบจะไม่ต่างอะไรจากการ Git Pull ลงมาเลย ต้องเข้าไปเปิดปิดเองบน Server

โชคดี (หรือโชคร้ายก็ไม่รู้ต้องมาเรียนเพิ่มอีกแล้ว) ที่มีเครื่องมือช่วยจัดการการ Deploy Container ลงระบบ Cluster ขนาดใหญ่ให้โดยอัตโนมัติ เพียงแค่เราเขียน Code ว่าแต่ละ Container จะต้อง Deploy อย่างไร ตั้งค่าอะไรบ้าง Network ต้องเชื่อมต่ออย่างไร เพียงเท่านี้มันก็จะจับ Container ของเราไปรันและสามารถเข้าถึงได้โดยอัตโนมัติ นอกจากนั้นเวลามีโหลดมากๆ ก็ยังทำ Auto Scale ให้อีกด้วย

ตอนนี้ Platform สำหรับการเอา Container ไป Deploy ที่ได้รับความนิยมสูงสุดตอนนี้ก็คือ Kubernetes ซึ่งเป็น Open Source จากระบบ K8S ที่ใช้กันภายใน Google มาอย่างยาวนาน พี่ใหญ่ใจดีแจกให้ทุกคนใช้ และของเขาดีจริง ดีซะจน Cloud Providers แทบทุกเจ้ารองรับกันหมดแล้ว เพียงคลิกๆ ไม่กี่ทีก็ได้ Kubernetes Cluster ขึ้นมาใช้กันง่ายๆ เลย


Kubernetes Overview

เรื่องแรกที่ผมอยากจะพูดก่อนเริ่ม Kubernetes คือคำว่า Infrastruture as Code (IaC) มันคือการที่เราสร้าง Infrastrure สำหรับโปรแกรมขึ้นมาจาก Code

ถามว่าทำไมต้องสร้าง Infra ขึ้นมาจาก Code ลองจินตนาการว่า เรากำลังพัฒนาโปรแกรมที่จะมีผู้ใช้เข้ามาใช้งานพร้อมกันเป็นแสนคน จะต้องมี Server ระดับไหนจึงจะเอาอยู่ มันต้องขยายออกแนวนอนอยู่แล้ว เราต้องเพิ่ม Server เข้าไปหลายๆ เครื่อง ช่วยกันแบ่งงานกันทำ แล้วใครล่ะจะบอกว่า จะเอาเครื่องมาใส่เพิ่มนะเมื่อมีโหลด 80% จะต้องตั้ง Spec เท่านี้ จะต้องเชื่อมต่อ Network เข้ากันด้วยท่านั้น ทุกอย่างมันอัตโนมัติไปหมด และมันทำได้ด้วยการ Config เอาไว้ก่อนล่วงหน้า แล้วการเขียน Script ที่เอาไว้ตั้งค่าสร้างเครื่องออกมานั่นล่ะครับเขาเรียกว่าการทำ IaC

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

ต่อมา แล้วจะควบคุมเครื่องจำนวนมากๆ นี่ได้ยังไง สมัยก่อนจะใช้ Container กัน เราใช้ Disk Image เอา Source Code ไปใส่ 1 โปรแกรมตั้งบน VM 1 ตัว แล้วก็ Scale เจ้าเครื่องตรงนี้ออกไป ทีนี้ก็ต้องสร้าง Image ของโปรแกรมแต่ละ Version ให้แยกกันออกไป ลองกลับมุมมอง ทำไมเราไม่ทำให้เครื่องมันเหมือนๆ กัน จะได้จัดการง่ายๆ ใช้ Disk Image เดียว แต่ไปเล่นเอาตรง Container แทน เอาไปรันตรงพื้นที่ๆ มันว่างอยู่ล่ะ นั่นล่ะครับจึงเกิด Kubernetes ขึ้นมา

ลองจินตนาการแบบนี้ เรามี Server Farm ขนาดใหญ่โตมาก มีเครื่องพร้อม Scale ทันทีที่ต้องการเพราะไปรันบน Cloud ที่พร้อมมากๆ แล้วเราอยากจะเอาอะไรก็ได้ไปรันบนนั้นโดยมีคนคอยจัดการให้ว่า จะต้องเอาโปรแกรมไปรันที่เครื่องไหน เรียกใช้งานได้อย่างไร Kubernetes เข้ามาช่วยจัดการตรงนี้

เขาให้มองว่า Server Farm ที่มี Server จำนวนมากเป็นเหมือนคอมพิวเตอร์เครื่องใหญ่เครื่องเดียว ไม่ต้องสนใจแล้วว่าข้างล่างมันจะทำงานยังไง เราเพียงสร้าง Deployment Script บอกว่าให้เอา Docker Image ไหนขึ้นไปรัน กำหนดทรัพยากรที่ใช้งานได้ แล้วก็บอกว่าจะรันพร้อมกันได้กี่ตัว (Replica) พร้อมกัน จากนั้นสั่ง Apply Deployment มันก็จะทำการโหลด Container มารันให้บนเครื่อง (Node) ที่ยังมีทรัพยากรเหลือเพียงพออยู่ จัดการทำ Network Routing ทำ Load Balancing ให้เราเสร็จสรรพตามที่ Config เอาไว้ใน Service มี Traffic เข้ามาใหม่ก็จะกระจายโหลดให้เราโดยอัตโนมัติเลย

ในบทความนี้ผมคงไม่เจาะลึกไปถึงการใช้งานของ Kubernetes นะครับ เพราะถ้าจะเขียนจริงคงยาวกว่า Docker ที่เขียนไปข้างบนเสียอีก แต่จะขออธิบาย Concept คร่าวๆ ให้ได้รู้กันไว้ เวลาจะต้องไปใช้งานจริงจะได้ไปกันได้อย่างเร็ว


Pod

ถ้าจะมองให้เข้าใจง่าย Pod ก็คือเครื่อง VM 1 เครื่องก็ละกัน จินตนาการว่าเรามี Farm อย่างใหญ่ จะ Depoy VM ลงไป ข้างใน VM 1 เครื่องจะต้องมีอะไรบ้าง ก็ต้องมีโปรแกรมที่เกี่ยวข้องกับมัน ซึ่งหนึ่ง Application ของเราอาจต้องการหลายโปรแกรมทำงานเชื่อมกัน Pod ก็สามารถเอา Container หลายอันไปใส่ได้เช่นกัน

ตัวอย่างเช่น ตัว Application ของเราต้องมีตัว Web Server และ Database Proxy อยู่ด้วยกัน อันนี้นับเป็น 2 Containers เวลา Deploy ก็ Deploy ไปพร้อมกัน ต่อเข้าหากันได้ในระดับ Local แชร์ไฟล์ถึงกันได้ เราเรียก Web Server ว่า Container หลัก และ Database Proxy ว่า Sidecar Container จากนั้นเราเลือกให้ Web Server รับ Traffic ที่ HTTP ที่เหลืออยู่เบื้องหลังเข้าถึงจากภายนอกไม่ได้ ทีนี้ก็จะได้เรื่อง Security ถ้าจะใช้งานต่อเข้ามา Port นี้ ต้องใช้ผ่านทาง HTTP ที่กำหนดเอาไว้เท่านั้น

Pod แบบเดียวกัน สามารถ Deploy ไปหลายๆ อันได้ ช่วยกันทำงาน สิ่งนี้เราเรียกว่า Replica เวลาโหลดน้อยอาจมี 1-2 replica แต่เวลาโหลดเข้ามาเยอะๆ ก็ Spawn ออกมาช่วยกันทำงานหลายๆ ตัวได้ โดยมี Service เป็น Load Balancer ช่วยจัดการกระจายงานให้


Deployment

Pod 1 ชุด จะใช้ไปหา Container ไหน จะใช้ทรัพยากรได้เท่าไหร่ จะมี Replica Scale แบบไหน นี่คือสิ่งที่ Deployment เป็นคนกำหนด และนี่คือ Script พื้นฐานที่เราจะเขียนเพื่อ Deploy โปรแกรมของเรา เราตั้งค่าที่นี่ และสั่งเข้าไปใน Cluster แล้วที่เหลือ Kubernetes มันจะจัดการตามคำสั่งที่เราเขียนเอาไว้ ง่ายๆ แบบนี้เลย (งงปะ มันคือการเขียน Script บอกให้ต้องรันโปรแกรมยังไงนั่นล่ะ)

เวลาต้องเปลี่ยน Container เราก็อ้างถึง Deployment ที่ต้องการ แล้วทำการ patch เอา Docker Image ใหม่มาเสียบแทน เป็นอันจบ การอัพเดท Kubernetes เขาจะให้ค่อยๆ สร้างแล้วลบ Pod สลับๆ กันไปได้ไม่เปลืองเครื่อง (Rolling Update) หรือจะสร้าง Version ใหม่ขึ้นมาให้พร้อมแล้วจับย้ายทีเดียว (Blue/Green Deployment) ก็ Config จาก Deployment ได้ทั้งสิ้น


Service

อย่างสุดท้ายที่ไม่รู้ไม่ได้เลยคือ Service ซึ่งเป็นการ Routing ข้างใน Cluster ให้จินตนาการเหมือนเราสร้าง Domain Name ขึ้นมาใช้เองข้างใน Cluster ของเรา แล้วให้มันชี้ไปหาที่ Pod ไหน Port อะไร Service ก็มีหน้าที่ประมาณนี้ แต่เหนือกว่านั้นคือมันทำ Load Balancing ให้ด้วยในตัว มี Traffic เข้ามา ต้อง Route ไปที่ Node ไหน ที่ Pod ไหน เขาจัดการตรงนี้ให้ด้วยครับ

Service จะมาเริ่มซับซ้อนตอนที่เราต้องการ Expose โปรแกรมของเราออกมาจากอินเทอร์เน็ต ซึ่งมันมีหลายอยู่ท่าขึ้นอยู่กับเครื่องมือที่เอามาใช้ เริ่มต้นอย่าเพิ่งตกใจ ทำความเข้าใจแต่ละประเภทก่อน แล้วค่อยทดลองค่อยทำไปแล้วเดี๋ยวก็จะเข้าใจเอง ผมเคยเขียนสรุปเรื่องนี้เอาไว้แล้วเช่นกัน ตามไปอ่านกันได้ที่ สรุปเรื่อง Kubernetes Services บน GKE หลังศึกษาและทดลองอย่างเอาจริงเอาจัง


ในส่วนของ Kubernetes ก็ขอจบเอาไว้แบบภาพรวมหน่อย เพราะว่ารายละเอียดค่อยข้างเยอะ ที่มาเล่าก็เพื่ออยากให้ได้ผ่านตาบ้าง เวลาจะต้องไปเรียนจริงจะได้มีพื้นฐานติดไปบ้าง นอกจากนั้นสำหรับโปรเจกต์เล็กๆ อาจจะไม่เหมาะเท่าไหร่ด้วย เพราะการตั้ง Kubernetes กว่าจะ Config ขึ้นมากันได้ ผมบอกเลยว่ายากนะครับ ถ้ายังไม่มีเคสพิเศษจริงๆ แนะนำให้ใช้ Platform อื่นๆ ในการ Deploy ดีกว่าครับ


Logging & Monitoring

เมื่อโปรแกรมของเราถูกเอาไป Deploy และรันอัตโนมัติบน Platform ที่มีการเพิ่มและลด Application Serverโดยอัตโนมัติตามปริมาณโหลด มันเป็นไปไม่ได้เลยที่จะ Remote เข้าไปดู Log ต่างๆ ในเครื่องพวกนั้น เพราะเราจะไม่รู้ได้ไงว่าต้องเข้าไปที่เครื่องไหน ดังนั้นจึงต้องใช้ระบบ Centralized Logging ในการ Monitor Application ของเรา

นั่นหมายความว่า เวลามีการเขียน Log จาก Application แทนที่จะเขียนลงไฟล์ใน Container โปรแกรมจะส่ง Request และ Payload ออกมาที่ระบบนี้ ทำให้เราดู Log ได้จากที่เดียวสามารถเห็นความเคลื่อนไหวของ Application ทุกตัว โดยเฉพาะเวลาที่มี Error เกิดขึ้น ก็จะได้รู้อย่างทันท่วงที

นอกจากเอาไว้ดู Error Log ต่างๆ แล้ว การที่เรามี Log รวมกันก็ช่วยให้เราตาม Monitor สถาการณ์ต่างๆ ของระบบได้ด้วย ช่วงไหนคนเข้ามากเข้าน้อย ฟีเจอร์ไหนถูกเรียกใช้งานมากน้อยอย่างไร สามารถเอา Log เหล่านี้แหละมาวิเคราะห์และ Plot ออกมาเป็นกราฟให้เห็นภาพรวมของระบบได้อย่างชัดเจน

สำหรับระบบ Logging & Monitoring นี้มีเกิดขึ้นมาหลายเจ้า ที่บริษัทใช้ Stackdriver ซึ่งเป็นบริการที่มีติดมาให้แล้วกับ Google Cloud Platform เวลาเกิดอะไรขึ้นมันจะเขียนลงที่นี่ทั้งสิ้น สามารถเลือก Filter ได้ เวลามี Error ก็จะแจ้งขึ้น Dashboard ให้เห็นชัดเจน เอา Log ไปสร้าง Dashboard ดูกราฟได้ นอกจากนั้นยัง Export ไปใส่ Big Query ได้อีกต่างหาก ซึ่งพอมาถึง Big Query ได้ ได้แล้วทุกอย่างล้วนเป็นไปได้ จะหมุน จะวิเคราะห์การใช้งานของผู้คนอย่างละเอียด จะไปสร้าง Dashboard ต่อด้วย Data Studio ก็ทำได้หมด


DevOps @ Credit OK

ก่อนจะเข้าเรื่อง DevOps ในบริษัท ผมขอเล่าเรื่องเกี่ยวกับธุรกิจของบริษัทก่อน จะได้เห็นภาพมากขึ้นว่าทำไมเราถึงวาง Infrastructure ออกมาเป็นอย่างที่เป็นอยู่

รู้จักกับ Credit OK

Credit OK เราก่อตั้งขึ้นมาเพื่อแก้ปัญหาการเข้าถึงสินเชื่อของผู้คน โดยเฉพาะสินเชื่อเพื่อการทำมาหากินหรือ Working Capital เพราะการได้รับสินเชื่อเพื่อนำเงินไปต่อยอด เป็นเหมือนน้ำมันที่ช่วยหล่อลื่นให้ธุรกิจเกิดการขยายตัว เพิ่มศักยภาพในการแข่งขัน และเป็นสิ่งที่ดีต่อทุกคนในระบบตั้งแต่ลูกค้า ผู้กู้ ผู้ให้กู้ ไปจนถึงระบบเศรษฐกิจของประเทศ

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


ความจริงแล้วโลกนี้ดีขึ้นทุกวัน โชคดีที่ความก้าวล้ำทางเทคโนโลยีสามารถเข้ามาแก้ปัญหาตรงนี้ได้บ้างแล้ว เพราะการประเมินสินเชื่อสามารถทำจากข้อมูลอื่นๆ ได้ด้วย ข้อมูลการซื้อขาย ข้อมูลการทำธุรกิจ และข้อมูลอื่นๆ อีกมากมายที่หามาได้จากแหล่งต่างๆ เชื่อมโยงเข้ากับการทำ Big Data และ Machine Learning เกิดขึ้นมาเป็น Credit Scoring แบบใหม่ที่ทำงานได้โดยอัตโนมัติและแม่นยำ

การทำเรื่องเช่นนี้ได้ เราจำเป็นต้องอาศัย Infrastructure สำหรับเก็บข้อมูลที่มีประสิทธิภาพและเชื่อถือได้ นอกจากนั้นยังมีส่วนของโปรแกรมที่จะนำมารัน ทั้งการทำ Credit Scoring ไปจนถึง API และ Web Application ที่ให้ผู้ใช้บริการของเราเข้ามาใช้งาน จะต้องทำงานประสานกันได้อย่างยอดเยี่ยม

แต่ในทางตรงกันข้ามด้วยความที่เรายังเป็น Startup เกิดใหม่ แล้วต้องไปเจอกับสภาพการขาดตลาดของแรงงานบุคลากรทางด้านไอทีที่มีคุณภาพของประเทศไทย เราจึงเลือกเส้นทางการใช้คนให้น้อยที่สุด ทำ Automation ให้มากที่สุด อะไรต้องทำซ้ำๆ ทำบ่อยๆ ถ้าใช้คอมพิวเตอร์ทำได้ เราจะไม่รีรอรีบทำให้มันอัตโนมัติทันที แล้วโยกคนออกไปทำงานอื่นที่คอมทำไม่ได้


Technology Stack @ Credit OK

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

Slack | Line | Gmail | Google Drive

ขอเริ่มจากเครื่องมือสำหรับการสื่อสารภายในทีม ทีม Developer เราใช้ Slack ในการสื่อสารกันเป็นหลัก รวมถึงแสดง Notification ต่างๆ ที่ทีมงานควรรู้ เช่น Pipeline รันสำเสร็จหรือเปล่า

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

สุดท้ายคือ Gmail และ Google Drive ซึ่งใช้งานภายใต้ GSuite โดยรวมแล้วก็มีความสุขดี

Cloudflare

ขยับขึ้นมาอีกนิดเป็น Cloudflare นี่เครื่องมือตัวโปรดของผมเลยสำหรับทำ DNS Server ซึ่ง Cloudflare จัดการได้ดีมาก อีกส่วนก็คือเอาไว้ทำ CDN คู่กับ GitLab Pages สำหรับ Static Files ที่เราต้องการ Serve ผู้ใช้ให้ได้อย่างรวดเร็ว

GitLab

ในส่วนของ GitLab นี่ใช้หลายส่วนมาก ตั้งแต่ใช้ทำ Source Code Repository, CI/CD Pipeline, Knowledge Management, Project Management เกือบจะครบลูปของการทำ Software Development

นอกจากนั้นยังเอามาทำเป็น Data Pipeline และบางอย่างที่รันเป็น Schedule อีกต่างหาก โดยอาศัยความสามารถของ CI/CD Pipeline เนี่ยแหละ

ชีวิตประมาณ 20% ของ DevOps อยู่ที่นี่ พัฒนา GitLab CI/CD Pipeline ในตอนต้นมันจะยากๆ หน่อย แต่พอทำสำเร็จทีนึงแล้ว เราก็ Copy Code เก่าๆ มาปรับๆ นิดหน่อยแล้วไปใช้ข้าม Project ได้เลย

Google Cloud Platform

ท้ายที่สุดก็คือ Google Cloud Platform ทุกอย่างที่เหลืออยู่บนนี้ ผมจะขอแยกเครื่องมือออกมาเป็นประเภทดังนี้

Storage, Databases, and Data Analytics

  • Cloud Storage (GCS)
    – ใช้เก็บ Files จาก Application ที่ User Upload ขึ้นมา
    – ใช้ทำ Data Pipeline ที่รับมาจากฝั่งลูกค้า มาวางไว้ที่นี่แล้วจึงส่งต่อไปให้ Google Cloud Functions และ Big Query ต่อไป
    – ใช้เก็บ Static Files บางอย่างที่ก็แค่เก็บไว้เฉยๆ
  • Container Registry (GCR)
    อาจไม่ได้เกี่ยวกับการเก็บ Data โดยตรง แต่ Container Registry เอาไว้เก็บ Docker Image ที่เราเอาไว้ Deploy Program ของเรานั่นเอง
  • Datastore (GDS)
    Datastore เป็น Columna Database เป็นเหมือน BigTable ที่มี Interface ให้ใช้ง่ายๆ ไม่ต้องมี Server จ่ายเงินตามการใช้งานจริง จึงใช้สำหรับบางงานที่ต้องการเก็บข้อมูลแบบ NoSQL ที่ต้องการการเข้าถึงแบบ Real Time
  • SQL
    ชัดเจนเลย นี่ก็คือ MySQL/pgSQL นั่นเอง เพียงแต่แทนที่เราจะต้องมาจัดการเรื่อง Server เอง ใช้ Cloud SQL Google จัดการให้ ที่ต้องให้ Google ทำให้ก็เพราะเราไม่อยากต้องมาเฝ้าดูแลเอง
  • Dataprep
    สุดยอดเครื่องมือในการทำ Data Exploration ข้อมูลเน่าๆ เข้ามาก็โหลดเข้ามาทำความสะอาดเบื้องต้นที่นี่เนี่ยล่ะ นอกจากนั้นยังทำ Data Pipeline ได้ด้วย
  • BigQuery (GBQ)
    สุดท้ายคือพระเอกแห่งวงการ Serverless Big Data ของเรา Big Query เป็น Data Analytics Tool ที่เอาไว้จัดการกับข้อมูลขนาดใหญ่ และใช้ภาษา SQL ในการ Query ได้ เอามาทำ Data Pipeline ก็ได้ ข้อมูล Big Data ก็เอาเก็บไว้ที่นี่นั่นเอง เวลาจะใช้งานถึงจะโหลดออกไปไว้ที่อื่น

Computing

  • Compute Engine (GCE)
    The primitive VM บางงานก็ยังต้องการ Server อยู่ ก็ตั้งเครื่องแล้วก็ใช้งานที่นี่ล่ะ แต่มีอีกงานที่เราใช้งานแล้วรู้สึกคุ้มค่ามากก็คือเอาเครื่อง Preemptible มาใช้ทำ GitLab Runner
  • Cloud Functions (GCF)
    ต่อมาก็เป็นงานเล็กๆ น้อยๆ และงาน Data Pipeline ที่ต้องเขียนแยกเฉพาะเจาะจง เราใช้ Google Cloud Functions ในการจัดการ ไฟล์จากลูกค้าที่ส่งมาพร้อมกันจากทั่วประเทศ โหลดมาแตก Zip ทำความสะอาด ส่งเข้า Big Query จัดการได้สบายๆ ไม่ต้องห่วง Server ล่ม
  • Cloud Run
    ของเล่นใหม่ที่เพิ่งมา ถูกใช้เป็นเรื่องเป็นราวแล้วตอนนี้ สำหรับ Web Application ที่ถูกจับใส่ Container ได้ และไม่ซับซ้อนมาก โดนจับมารันบนนี้หมด ไม่ต้องห่วงเรื่องเครื่องอีกต่อไป นอกจากนั้นก็ทำ CI/CD ได้ง่ายๆ
  • Kubernetes Engine (GKE)
    พี่ใหญ่ตอนนี้ก็คือ Kubernetes Engine นั่นเอง สำหรับโปรแกรมที่รันยาก มีความซับซ้อนขึ้นมา ก็จะถูกเอามาใช้รันบนนี้ ซึ่งตอนนี้ประมาณ 70% ที่ให้บริการอยู่รันอยู่บนนี้นี่แหละ Refactor กันอยู่นานกว่าจะเข้าที่เข้าทาง ถ้าไม่มีเหตุต้องใช้ ไปใช้อย่างอื่นดีกว่าครับ 555

Task Management

  • Cloud Scheduler
    แน่นอนทำ Data ก็ต้องมีงานที่ต้องให้มันรันเป็นประจำอยู่เรื่อยๆ จะ Trigger ให้มันรัน ก็ต้องมี Scheduler ใช้งาน ตอนแรกๆ ที่มาใช้ GCP ไม่มีให้ใช้ทรมานมาก ตอนนี้มี Job รันอยู่เพียบ ส่วนใหญ่จะใช้ Trigger Google Cloud Functions ผ่านทาง Pub/Sub
  • Pub/Sub
    เจ้านี่คือการใช้ Broadcast Messages ทำตัวคล้ายๆ เป็นตัวกลางคอยพูดคุยกับโปรแกรมอื่นๆ โดยจะตั้งชื่อ Topic เอาไว้ แล้วก็บอกว่าถ้ามี Message เข้ามา ใครจะคอยรับสารจาก Topic นั้นก็รับไปทำงานต่อ ซึ่งโดยปรกติแล้วก็เอาไว้ Trigger Google Cloud Functions เนี่ยล่ะ
    บางทีต้องการให้รันโหลดอะไรบางอย่างแบบจำกัด Concurrency หน่อยก็สั่งให้ GCF มันจำกัดจำนวน Instance แล้วข้อมูลต่างๆ ก็จะค่อยๆ ถูกทยอยส่งออกไป รู้สึกสุขภาพดีมากเลย แทบไม่จำเป็นจะต้องไปใช้ Task Queue เลย ยกเว้นต้องการจะตั้ง Delay ซึ่ง Pub/Sub ทำไม่ได้

Logging & Monitoring

  • Stackdriver
    เล่าไปแล้ว Stackdriver เป็น Default Logging ของ Google ใช้ทำ Metric ใช้ทำ Dashboard แล้วก็ Export Log ไปไว้ที่อื่นเพื่อเอาไว้ประมวลผลอย่างอื่นได้อีกด้วย
  • Data Studio
    ถามว่า Log ข้างบน Export แล้วไปไหน มันจะเข้าไปที่ Big Query แล้วถูก Digest มาแสดงผลบน Dashboard ที่นี่ล่ะครับ ผู้คนเข้าออกมีพฤติกรรมอย่างไร เอา Big Query ออกมาแล้วมา Vistualize ด้วย Data Store ได้สบายๆ

Technology Integration @ Credit OK

เอาล่ะ หลังจากได้พอทราบแล้วว่าที่ Credit OK ตอนนี้เราใช้เครื่องมืออะไรบ้าง เพื่อให้เห็นภาพมากขึ้น ผมได้วาดภาพแผนผังการเชื่อมต่อกันของเครื่องมือให้ดูข้างล่าง เชิญชมกันได้เลยครับ

หน้าที่การวางโครงสร้างนี้ไม่ใช่ของ DevOps แต่เป็นของ Cloud Architect ส่วน DevOps Engineer มีหน้าที่เป็นผู้ใช้หลัก เอาของมาแปะวางไว้ให้มันใช้งานได้ ซึ่งส่วนงานของที่ DevOps ต้องใช้งานจะอยู่ส่วนของซ้ายบนตั้งแต่ GitLab เป็นตันมา ไปจนถึงการเอาโปรแกรมมา Deploy แล้วก็ในส่วน Monitor ของ Stackdriver

ที่นี่เราดูแลความสงบเรียบร้อยของ Cloud กันแบบ Part-time 3 คน (3 คนนี้จริงๆ ทำงานอื่นไปด้วย) ความจริงก็พอเซทให้มันดีตั้งแต่ต้น พอทุกอย่างทำงานต่อกันได้โดยอัตโนมัติแล้ว ก็ไม่ค่อยต้องมีอะไรกังวลเท่าไหร่ นานๆ จะมีบั๊กต้องมาดูเวลามี Error ใหม่เตือนขึ้นมาในอีเมล์จาก Stackdriver


How Credit OK utilizes Docker

ชิ้นส่วนต่างๆ ของการใช้ Docker ที่ควรรู้ก็ได้เล่าให้ฟังกันไปหมดแล้ว ต่อมาผมจะขอเล่าให้เห็นภาพมากขึ้นถึงการเอา Docker ไปใช้งานจริงในการพัฒนาโปรแกรม ซึ่งผมขอยกตัวอย่างของ Flow การใช้ Docker กับ Kubernetes ให้เห็นภาพกัน


Develop Application with Docker Compose

พัฒนาโปรแกรมด้วย Docker Compose

จุดเริ่มต้นเริ่มจากการพัฒนาโปรแกรมบนเครื่อง Local โดยที่ DevOps ทำหน้าที่ในการเลือกหรือสร้าง Base Docker Image และ Docker Compose File ให้กับ Developer

จากนั้น Developer ก็ Mount Source Code และรัน docker-compose up ซึ่งนอกจาก Web Server แล้ว ก็อาจจะมี Database อย่าง MySQL ด้วยก็ใส่ลงไปให้รันพร้อมกันเลย แล้วก็จะได้ Web Server ขึ้นมาพร้อมใช้งาน เป็น Source Code เดียวกับที่เรา Map เข้าไปจากเครื่อง Local โดยตรง

Docker Compose จะทำการ Expose Port ของ Web Server ออกมา ทำให้ Developer สามารถเปิดเข้าไปใช้งานได้ผ่านทาง Web Browser จากฝั่ง Local ได้ทันที


Run CI with GitLab Runner

รัน CI ด้วย Docker Image บน GitLab CI

Source Code ทั้งหมดเก็บบน Git เมื่อเขียนเสร็จเรียบร้อยแล้วก็ส่งขึ้นไปบน Origin Server อย่างในภาพเราใช้ GitLab CI ในการทำ CI/CD Pipeline นี่ก็คือหน้าที่ของ DevOps ที่จะต้องมาเขียนเช่นกัน

เมื่อ Source Code ถูก Push ขึ้นมา GitLab CI จะถูกรันโดยอัตโนมัติ มันจะสร้าง Container ขึ้นมาใหม่ โดยใช้ Base Image อันเดียวกันกับที่ใช้พัฒนาเลย

สิ่งที่มันทำในขั้นตอนนี้ก็คือการ Test โปรแกรม โดยจะรัน Test Script ว่าทุกอย่างยังทำงานปรกติดี และ ผลลัพธ์ของการ Test ก็จะแสดงออกมาให้ดูบนเว็บ GitLab เลย


Pack Source Code to Docker Image

สร้าง Application Docker Image ด้วย GitLab CI

หลังจาก Test ผ่านไปด้วยดี เราก็จะทำการ Release โปรแกรมแล้ว โดยการล้างทุกอย่างทิ้ง แล้ว Copy เอา Source Code ไปใส่ไว้ใน Base Docker Image จากนั้นก็ทำการ Build Docker Image ใหม่ ได้ออกมาเป็น Application Docker Image ที่พร้อมสำหรับการเอาไปรัน จากนั้นโหลดขึ้นไปเก็บเอาไว้บน Container Registry


Deploy Application Docker Image

ส่ง Application Docker Image ไป Deploy

ขั้นตอนสุดท้ายคือการเอาไป Application Docker Image ไป Deploy บน Platform ที่ต้องการ ซึ่งในภาพเป็น Kubernetes นั่นเอง โดยวิธีการนั้นก็แสนง่าย เพียง Remote เข้าไปที่ Cluster แล้วก็สั่ง Update Docker Image ของ Application Deployment ที่ต้องการ เปลี่ยน Container ให้ชี้ไปหา Image Registry URL ที่เพิ่งสร้างขึ้นมาใหม่ใส่เข้าไป ตัว Kubernetes ก็จะทำการจัดการทุกอย่างที่เหลือให้โดยอัตโนมัติ


การพัฒนาโปรแกรมให้เข้าได้กับ DevOps Technology สมัยใหม่

จากที่ได้เล่าถึง DevOps Technology ไปทั้งหมด ฟังดูเหมือนจะเข้าท่าและดูดี แม้จะต้องเรียนรู้อะไรเพิ่มขึ้นมา และสิ่งที่ได้เรียนก็แลดูน่าตื่นเต้นน่าสนุก ดูจะไม่มีพิษมีภัยอะไร หารู้หรือไม่ว่า ความเป็นจริงแล้วการจะได้มาซึ่งการวางโครงสร้างที่ดีนั้นต้องเปลี่ยนพฤติกรรมการพัฒนาโปรแกรมไปมากเลยทีเดียว มาดูกันว่าต้องเปลี่ยนอะไรกันบ้าง


โปรเจกต์เพิ่งเริ่ม อย่าเพิ่งทำ DevOps ครบ Flow

การทำ DevOps เนี่ยดีในระยะยาว แต่ในร่วมเริ่มต้น ผมอยากให้ไปโฟกัสเรื่องอื่นมากกว่า ตัวอย่างเช่น รีบๆ ทำโปรแกรม Prototype ออกมาใช้งานให้ได้ แล้วก็ Deploy เองไปก่อนบน Platform ที่ใช้งานง่ายๆ

แต่จะมี Flow บางอย่างที่ควรเริ่มทำแต่ต้นเลย คือการสร้าง Environment ในการพัฒนาร่วมกันที่ดี ซึ่งจะกินไปถึงการวางโครงสร้างโปรแกรม การพัฒนาโปรแกรมบน Docker Compose และการเขียน Unit Test ในส่วนสำคัญๆ ของโปรแกรมที่จะต้องมั่นใจว่ามันทำงานได้ถูกต้อง สิ่งเหล่านี้ควรทำก่อนเลยตั้งแต่ต้น เพราะสุดท้ายก็จะได้ใช้งานในท้ายที่สุดอยู่ดี และมันก็ช่วยให้ทีมทำงานร่วมกันง่ายขึ้นด้วย

แต่สิ่งที่ยังไม่ควรทำในช่วงช่นก็เช่น การเอาโปรแกรมไป Deploy บน Kubernetes แบบนี้ นั่งเซทกันวุ่นวาย เสียเวลาเป็นวันๆ ต้องมาสร้าง CI/CD Pipeline ให้ครบ Flow ถ้าต้องมาสร้างกันใหม่ ผมแนะนำให้ข้ามไปก่อนดีกว่าครับ รอให้โปรแกรมเราใกล้จะคลอดแล้ว ค่อยแบ่งเวลาบางส่วนมาทำเรื่องพวกนี้


ใช้ Environment Variable เพื่อให้ Config โปรแกรมตอน Deploy ได้

หลายครั้งโปรแกรมที่เราเขียนขึ้นมาถูกนำไป Deploy ในหลายที่ หลายลูกค้า แต่มีการแก้ไขค่า แก้ไขหน้าตา นิดๆ หน่อยๆ เช่นการเปลี่ยนสี เปลี่ยน Title Website มันจะดีไม่น้อยถ้าเราสามารถใช้ Container เดียวกันได้ แล้วเปลี่ยนแค่ค่าตัวแปรตอน Deploy

Environment Variable คือตัวแปรที่สามารถถูกเซทตาม Env ที่เอาไปรันได้ เช่น รันบนเครื่อง Dev รันบน Test รันบน UAT และ Production สามารถเซทให้ต่างกันได้ แต่ใช้ Container Image อันเดียวกัน

Environment Variable จะมาในรูปแบบของไฟล์ .env เป็นพื้นฐาน แต่ที่จะเหนือไปกว่านั้นก็คือมาในรูปแบบของตัวแปรในระบบ OS ที่เราสามารถตั้งค่าได้จาก Docker หรือ Kubernetes หรือ Deployment Platform อื่นๆ โดยโปรแกรมมันจะไปดึงค่าตัวแปรนี้ออกมาใช้งาน แทนที่จะเป็นการใช้งานจากการ Hard code ลงไปในโปรแกรม

ตัวอย่างที่ชัดเจนที่สุดเลยก็เช่น การเลือก Database ที่จะต้องใช้เชื่อมต่อ ประการที่หนึ่งที่ขอให้ระลึกไว้เสมอเลยคือ ห้ามเก็บ Credential ลง Git เด็ดขาด เพราะ Source Code ที่อยู่ในนั้นจะอยู่ตลอดไป แล้ว Username Password ไม่ควรถูกบันทึกลงหน้าประวัติศาสตร์ เราจึงเก็บ Credential ลงไปใน .env ซึ่งเป็นไฟล์ที่จะไม่ถูกเขียนลงใน Git ต่อมาเวลาจะไป Deploy ไฟล์ .env จะถูก gitignore จะไม่ติดไปด้วย ดังนั้นเราจะต้องเขียน Deployment file ให้มีตัวแปรที่ต้องใช้ (พวก Credential จะเขียนเชื่อมออกไปใน Secret อีกทีแล้วค่อยเอามาใส่ใน Deployment เพราะไฟล์ Deployment ก็ก็เอาขึ้น Git เช่นกัน) ถ้าเราอยากจะแยกโปรแกรมให้อ่าน Database คนละตัวกัน ก็แค่เปลี่ยนค่า แล้วก็ส่งขึ้นไป Deploy เลย

แต่การจะได้มาซึ่งการใช้งาน .env นี้ไม่ใช่จะทำได้ปุ๊บปั๊บ มันก็จะมี Overhead ในการ Dev ขึ้นมานิดหน่อย ก็คือเราจะ Hard code ไม่ได้แล้ว จะต้องรู้ว่า ค่าตรงไหนให้ไปอ่านจาก .env มาใช้ แล้วก็ต้องจดเอาไว้ด้วย เวลาจะไป Deploy ก็ต้องมาตั้งค่าเหล่านี้ด้วยโปรแกรมถึงจะใช้งานได้ตามที่ต้องการ

ถึงแม้จะทำให้การพัฒนายากลำบากขึ้น แต่ก็ช่วยให้โปรแกรมเราเอาไปใช้งานสะดวกขึ้นในระยะยาว ดังนั้นนักพัฒนาควรจะพิจารณาใช้งาน .env อย่างจริงจัง


อย่าเขียนไฟล์ที่จะต้องเอากลับมาใช้ลงไปใน Container

Container เป็นเหมือน VM เวอร์ชั่นที่เล็กกว่า โปรแกรมที่รันขึ้นมาแล้วอยู่คนละ Container ไม่มีความเชื่อมโยงต่อกัน นอกจากนั้นยังพร้อมสำหรับการถูกทำลายตลอดเวลา ดังนั้นไฟล์ที่ต้องการจะเซฟไว้ใช้งานห้ามเอามาเก็บเอาไว้บนนี้ เพราะมันจะถูกลบ

นอกจากนั้นแต่ละ Container ที่รัน ถึงแม้จะมาจาก Image เดียวกัน แต่มันไม่ได้เชื่อม File System กัน ดังนั้นเอามาเก็บ Cache ที่จะต้อง Invalidate (มีการอัพเดท) จะไม่สามารถทำได้ ไม่งั้นเครื่องนึงเก็บ Cache อีกครึ่งนึงบอกให้ลบ มันไปไม่ถึงกัน แล้วโปรแกรมของเราจะทำงานผิดพลาดแบบ Debug ไม่ได้ด้วย หายนะชัดๆ

ดังนั้นเราต้องไปใช้ Service อื่น แรกเริ่มเลยคือเรื่อง Database เราต้องตั้งตรงกลางมาใช้งานอยู่แล้ว เราอาจจะมาเก็บ Session/Cache ไว้ที่นี่ก็ได้ถ้าไม่มีการใช้งานที่หนักเกินไป แต่ถ้ามีการใช้งานที่เยอะและถี่มากๆ ควรใช้ In-memory database อย่างเช่น Redis หรือ Memcache เจ้าพวกนี้พร้อมให้บริการด้วยความเร็วสูงสุด

ต่อมาเรื่องของไฟล์ที่ User อัพโหลดขึ้นมา พวกนี้จะต้องไปใช้ Object Storage อย่างเช่น Google Cloud Storage หรือ AWS S3 หรืออื่นๆ ตามแต่ค่ายที่ให้บริการจะมีให้เลือกใช้ ซึ่งมันก็จะทำให้เกิดความยากลำบากในการพัฒนาโปรแกรมขึ้นมากกว่าเดิม แต่นี่ก็เป็นสิ่งที่ต้องทำ

อย่างไรก็ดีมีไฟล์บางประเภทที่พอจะเขียนไปเก็บไว้บน Container ได้บ้าง เช่น Cache ที่ไม่จำเป็นต้อง Invalidate หรือจะไม่เคยมีการเปลี่ยนแปลงเลยจนกว่าจะหมดอายุ (ข้อมูลประเภทที่เราใช้เก็บกันไว้บน CDN พวก View และ Static Files ต่างๆ) ข้อมูล Cache ในกลุ่มนี้ถ้ามันหาไม่เจอใน Cache ก็จะไปดึงข้อมูลมาเมื่อไหร่ก็ได้ แล้วมาเซฟเก็บไว้ แล้วดึงกลับออกมาใช้งานได้ นอกจากนั้นแต่ละเครื่องก็มีของตัวเองแยกกันได้ เพราะข้อมูลไม่ได้มีการเปลี่ยนแปลง การทำแบบนี้จะช่วยให้ Cache Database โหลดน้อยลงได้ แต่ต้องมั่นใจจริงๆ นะว่ามันจะไม่มีการเปลี่ยนแปลง

ฟังดูแล้วมีเคสน้อยมากเลยที่จะ Cache ได้ ดังนั้นเป็นไปได้ใช้อย่าเขียนไฟล์ลงไปใน Container จะง่ายสุด


เชื่อฟัง Docker Best Practice เหนื่อยหน่อยแต่ไม่เจ็บตัว

สุดท้ายคือ ใช้ Docker ขอให้เชื่อฟัง Best Practice กันหน่อย เพราะกับดักในการใช้ Docker มันเยอะพอสมควรเลยครับ โดยเฉพาะกับดักที่เกิดจากการมี Layer นั้น มันส่งผลโดยตรงกับเรื่อง Security และบางครั้งจะทำให้โปรแกรมของเราอยู่ๆ ก็รันไม่ได้ขึ้นมาซะงั้น เพราะใช้ tag เจาะจงไม่มากพอ

ผมคงจะไม่เล่าทั้งหมด แต่ขอเน้นในบางประเด็นที่คนพลาดกันมากที่สุดก็คือการใช้ tag latest เนี่ย มันสร้างขึ้นมาเพื่อความสะดวกก็จริง แต่ Image พวกนี้มันถูก Update ถูก Build อยู่ตลอด วันไหนมันอัพเวอร์ชั่นขึ้นมาแล้วโชคร้ายไม่ compat กับโปรแกรม เกิดโปรแกรมรันไม่ได้ขึ้นมา แบบนี้ยุ่งเลยนะครับ ดังนั้นเวลาเลือก tag เลือกให้ถูก version จะได้ไม่เจ็บตัวแบบงงๆ (เห็นหลายคนเคยเจ็บมาแล้วรวมถึงผมด้วยถึงได้มาเตือน)

นอกจากนั้นยังมีกระบวนท่าที่แนะนำในการสร้าง Dockerfile อีกมาก ขอแนะนำให้เข้าไปอ่านหลังจากเริ่มใช้ Docker แบบพอไปไร่ไปนาได้แล้ว มีคนแปรไทยเอาไว้ให้เรียบร้อยแล้ว Docker แนะนำ 11 เทคนิคการเขียน Dockerfile


สรุปปิดท้าย

ที่เล่ามาทั้งหมดก็น่าจะพอหอมปากหอมคอนะครับสำหรับการแนะนำเรื่อง DevOps ในเบื้องต้น ตั้งแต่ว่ามันคืออะไร คนทำงานนี้เขาทำอะไรกันบ้าง ไปจนถึงเครื่องมือที่น่าสนใจและการเอาไปใช้งานจริงจาก Use Case ของ Credit OK ซึ่งโดยสรุปแล้ว DevOps มันก็คือกระบวนการการทำ Automation ที่ช่วยส่งเสริมการพัฒนา Software ให้สะดวกสบายขึ้น แล้วยังช่วยการันตีคุณภาพของ Software ที่พัฒนา เพื่อความมั่นใจว่าเราจะไม่ Ship ของเสียส่งไปถึงลูกค้า

ผมคิดว่าที่สำคัญหลังจากนี้ก็คงจะเป็นการได้ลองเอาไปต่อยอด ฝึกฝน และใช้งานจริงแล้วล่ะ ถ้าใครรู้สึกสนใจพัฒนาทักษะทางด้านนี้ แต่ไม่แน่ใจว่าจะเริ่มต้นอย่างไรดี ผมขอแนะนำให้ลองตั้ง Website ส่วนตัวง่ายๆ ขึ้นมาก่อนก็ได้ครับ อย่างผมเองก็เริ่มทำเว็บไซต์มาตั้งแต่สมัย ม.1 พัฒนามาเรื่อยๆ จนมาถึงเว็บไซต์ปัจจุบันที่คุณกำลังอ่านกันอยู่ ได้ผ่านร้อนผ่านหนาว เรียนรู้สิ่งต่างๆ มากมายจากการทำสิ่งเล็กสิ่งนี้ ลองทำของตัวเองขึ้นมาบ้างซิครับ ผมรับรองคุณจะต้องทึ่งกับความรู้ที่ได้รับจากการทำงานเป็นชิ้นขึ้นมาอย่างแน่อน

เดี๋ยวนี้ Public Cloud แทบทุกเจ้ามี Credit ให้ใช้ฟรีกันทั้งนั้นในช่วงต้น อย่าง GCP ก็ให้ใช้งานกันฟรีๆ $300 เป็นเวลา 1 ปี หลังจากนั้นก็ยังมี Resource ฟรีให้ใช้ต่อไปอีกต่างหาก จึงอยากจะเชิญชวนให้ เพื่อนๆ พี่ๆ น้องๆ เข้าไปใช้กันนะครับ เข้าไปฝึกฝนฝึกฝีมือกัน เราจะได้เก่งๆ ขึ้นไปด้วยกันครับ

สุดท้ายนี้ถ้าใครมีคำถาม ใครอยากปรึกษาเรื่องอะไรก็ติดต่อเข้ามากันได้นะครับ จะ Message มาทาง Fan Page หรือจะ Comment ไว้ข้างล่างโพสก็ได้ ส่วนในตอนนี้ผมก็ขอจบเอาไว้เพียงเท่านี้ครับ ขอบคุณครับที่ตามอ่านกันจนจบนะครับ Happy Deployment สวัสดีครับ 🙂

Tags: , , , ,