การ Deploy คอนเทนเนอร์เพียงตัวเดียวเป็นเรื่องง่าย การ Deploy สิบตัวยังพอจัดการได้ แต่เมื่อคุณต้องรันคอนเทนเนอร์หลายร้อยตัวบนเครื่องหลายสิบเครื่อง การจัดการด้วยมือจะไม่ใช่แค่เรื่องยากอีกต่อไป แต่มันจะกลายเป็นเรื่องที่เป็นไปไม่ได้ คุณจะเริ่มตามไม่ทันว่าคอนเทนเนอร์ตัวไหนอยู่ที่ไหน เซิร์ฟเวอร์ตาย และแอปพลิเคชันของคุณก็หายวับไปจนกว่าจะมีใครสักคนตื่นขึ้นมาเพื่อรีสตาร์ทมัน ปริมาณ Traffic ที่พุ่งสูงขึ้นจะทำให้ระบบของคุณล่มก่อนที่คุณจะทันได้สร้าง Instance ใหม่ขึ้นมา และนี่คือจุดที่ Kubernetes เข้ามามีบทบาท มันไม่ใช่แค่เครื่องมือ DevOps ทั่วไป แต่มันคือเลเยอร์การจัดการ (orchestration layer) ที่มองว่าการจัดการคอนเทนเนอร์คือปัญหาด้านการควบคุม (control problem) มากกว่าจะเป็นแค่การเขียนสคริปต์
Why Scripts Eventually Break
ทีมส่วนใหญ่เริ่มต้นด้วย shell script หรือระบบอัตโนมัติพื้นฐาน พวกเขาเขียนคำสั่งเพื่อ pull image, เริ่มคอนเทนเนอร์, เฝ้าดู log และรีสตาร์ทโปรเซสที่ล้มเหลว วิธีการนั้นอาจใช้ได้ดีสำหรับการทำ Proof of Concept แต่จะพังทลายลงเมื่อต้องรับโหลดในโลกความเป็นจริง Microservices ต้องสื่อสารกันผ่านโฮสต์ที่ต่างกัน, ต้องพึ่งพา environment variables เฉพาะเจาะจง, ต้องการ persistent storage ที่คงอยู่แม้คอนเทนเนอร์จะรีสตาร์ท และต้องการระบบเครือข่ายที่สม่ำเสมอระหว่างเวอร์ชันต่างๆ สคริปต์ไม่สามารถจัดตารางงาน (reschedule) ใหม่โดยอัตโนมัติได้เมื่อ virtual machine หายไป มันไม่สามารถกระจาย network traffic ไปยัง instance ที่ยังทำงานปกติ ในขณะที่ข้าม instance ที่ติดอยู่ใน loop การ crash ได้ Kubernetes แก้ปัญหานี้โดยการทำให้ตัว cluster เองเป็นผู้รับผิดชอบในการตัดสินใจเหล่านั้น คุณเพียงแค่ระบุสิ่งที่คุณต้องการ แล้วระบบจะบังคับให้สถานะ (state) เป็นไปตามนั้นอย่างต่อเนื่อง
The Three Things It Gives You
Kubernetes มอบความสามารถหลัก 3 ประการที่จะเปลี่ยนจากการไล่แก้ปัญหาเฉพาะหน้าด้วยมือ เป็นความน่าเชื่อถือแบบอัตโนมัติ
High availability หมายถึงแอปพลิเคชันของคุณยังคงออนไลน์อยู่ได้แม้ว่าบางส่วนของโครงสร้างพื้นฐานจะล้มเหลว หากคอนเทนเนอร์ล่ม Kubernetes จะแทนที่มันภายในไม่กี่วินาที หาก worker node ทั้งหมดดับไป scheduler จะตรวจพบสัญญาณ heartbeat ที่หายไป และย้าย workload ที่ได้รับผลกระทบไปยังเครื่องที่ยังทำงานปกติในส่วนอื่นของ cluster ระบบจะเฝ้าดูสถานะที่คุณกำหนดไว้ (desired state) อย่างต่อเนื่อง และแก้ไขความเบี่ยงเบนที่เกิดขึ้นโดยไม่ต้องใช้มนุษย์เข้ามาแทรกแซง
Scalability หมายถึงแอปพลิเคชันของคุณเติบโตไปพร้อมกับจำนวนผู้ใช้งาน แทนที่จะต้องเตรียมเซิร์ฟเวอร์ไว้ถึง 20 เครื่องเพียงเพื่อรองรับช่วง traffic พุ่งสูงแค่ 2 ชั่วโมง คุณสามารถกำหนด metrics ที่สำคัญ เช่น การใช้งาน CPU หรือ request latency และปล่อยให้ cluster เพิ่มจำนวน container instance เมื่อถึงเกณฑ์ที่กำหนด เมื่อความต้องการลดลง จำนวน replica ก็จะลดลงตามไปด้วย คุณจ่ายเฉพาะสิ่งที่คุณต้องการ ในเวลาที่คุณต้องการเท่านั้น
Disaster recovery หมายถึงข้อมูลและการตั้งค่าของคุณจะกลับคืนมาหลังจากเกิดการล่ม Kubernetes เก็บสถานะทั้งหมดของ cluster ไว้ใน distributed key-value store หากเกิดความล้มเหลวร้ายแรงที่ทำให้ worker nodes หรือแม้แต่บางส่วนของ control plane หายไป สถานะที่ถูกเก็บไว้จะช่วยให้ระบบสามารถสร้าง workload ของคุณขึ้นมาใหม่ได้เหมือนกับที่เคยตั้งค่าไว้ทุกประการ ข้อมูลของคุณจะกลับมา เพราะ orchestrator จดจำได้ว่ามันควรจะมีหน้าตาเป็นอย่างไร
The Setup: Brains and Muscle
Kubernetes cluster มีบทบาทพื้นฐาน 2 อย่างที่เปรียบได้กับ "สมอง" และ "กล้ามเนื้อ" ซึ่งการเปรียบเทียบนี้ใช้ได้ดีมากในทางปฏิบัติ
Master Node คือสมอง มันไม่ได้รันแอปพลิเคชันที่ลูกค้าใช้งานโดยตรง แต่ทำหน้าที่เป็นที่อยู่ของส่วนประกอบ control plane ที่ทำหน้าที่จัดตารางงาน (schedule tasks), จัดการสถานะของ cluster และตอบสนองต่อการเปลี่ยนแปลงต่างๆ เมื่อคุณออกคำสั่งหรือส่งไฟล์การตั้งค่า Master node จะตัดสินใจว่า workload ควรจะไปอยู่ที่ไหน, มันยังทำงานปกติอยู่หรือไม่ และควรทำอย่างไรหากมันทำงานผิดปกติ
Worker Nodes คือกล้ามเนื้อ แต่ละ worker จะรัน lightweight agent ที่สื่อสารกับ master และใช้ container runtime ในการรัน pod จริงๆ โหนดเหล่านี้คือจุดที่โค้ดแอปพลิเคชันของคุณใช้ CPU และหน่วยความจำ หากเพิ่ม worker nodes มากขึ้น cluster ของคุณก็จะมีความสามารถในการรองรับงานมากขึ้น หากเพิ่ม master nodes ที่ตั้งค่าไว้เพื่อสำรองข้อมูล (redundancy) control plane ของคุณก็จะมีความทนทานต่อความล้มเหลวของฮาร์ดแวร์แต่ละชิ้นมากขึ้น
Pods, Containers, and Services
ในการทำงานกับ Kubernetes คุณจำเป็นต้องเข้าใจ 3 คำศัพท์ที่กำหนดว่าซอฟต์แวร์ถูกบรรจุและเข้าถึงได้อย่างไร
Containers คือแพ็กเกจที่รวบรวมแอปพลิเคชันของคุณเข้ากับ dependencies, libraries และการตั้งค่าต่างๆ มันช่วยแยกซอฟต์แวร์ออกจากโฮสต์ที่อยู่เบื้องหลัง เพื่อให้มันทำงานได้เหมือนกันทั้งในสภาพแวดล้อม development, staging และ production
Pods คือหน่วยที่เล็กที่สุดที่สามารถนำไปใช้งาน (deploy) ได้ใน Kubernetes Pod หนึ่งจะห่อหุ้มคอนเทนเนอร์ (container) หนึ่งตัวหรือมากกว่าที่จำเป็นต้องใช้ทรัพยากรร่วมกัน พวกมันใช้ network namespace เดียวกัน และสามารถเข้าถึง local storage volumes ชุดเดียวกันได้ สิ่งสำคัญคือ: คุณไม่ได้ deploy คอนเทนเนอร์เปล่าๆ โดยตรง แต่คุณ deploy pod ที่บรรจุคอนเทนเนอร์นั้นไว้ นอกจากนี้ Pods ยังถูกออกแบบมาให้เป็นแบบ ephemeral (ชั่วคราว) โดยตั้งใจ พวกมันจะถูกสร้าง ทำลาย และแทนที่เมื่อสภาวะต่างๆ เปลี่ยนไป อายุการใช้งานของพวกมันจึงมีความยืดหยุ่น (dynamic) โดยการออกแบบ
Services มีไว้เพราะ pods นั้นไม่คงทน (transient) ทุกครั้งที่ pod เริ่มทำงานใหม่ (restart) มีความเป็นไปได้สูงที่มันจะได้รับ IP address ภายในชุดใหม่ หากส่วนอื่นๆ ของแอปพลิเคชันพยายามเชื่อมต่อกับที่อยู่ (address) ที่เปลี่ยนแปลงตลอดเวลาเหล่านั้นโดยตรง ระบบก็จะพังอยู่เรื่อยๆ Service จะมอบ IP address และชื่อ DNS ที่คงที่ให้กับ pods ของคุณ โดยทำหน้าที่เป็นประตูหน้าบ้านที่เสถียร ทำหน้าที่ load-balancing กระจายคำขอ (requests) ที่เข้ามาไปยัง pods ที่ทำงานปกติ (healthy) ทั้งหมดที่ตรงตาม selector ของมัน สิ่งนี้ช่วยแยก (decouple) client ของคุณออกจากความวุ่นวายของวงจรชีวิตคอนเทนเนอร์แต่ละตัว
Kubernetes ในระดับสเกลใหญ่: ตัวอย่างจาก Netflix
Netflix ใช้ Kubernetes ในการจัดการเครือข่ายการส่งเนื้อหา (content delivery network) ของตน โครงสร้างพื้นฐานนี้ทำหน้าที่ส่งสตรีมวิดีโอไปยังผู้ชมหลายล้านคนพร้อมกันทั่วโลก เมื่อมีซีรีส์ยอดนิยมเปิดตัวและมีความต้องการใช้งานพุ่งสูงขึ้น คลัสเตอร์ (cluster) จะทำการ scale out โหนดแคช (cache nodes) ที่เก็บส่วนประกอบของวิดีโอ (video segments) ให้ใกล้กับผู้ใช้งานมากขึ้น หากโหนดในภูมิภาคใดภูมิภาคหนึ่งล้มเหลว ทราฟฟิกจะถูกเปลี่ยนเส้นทางโดยอัตโนมัติ ผลลัพธ์คือภาพยนตร์ยังคงเล่นต่อไปได้สำหรับผู้คนหลายล้านคน โดยไม่ต้องมีการเรียกตัววิศวกรมาแก้ไขเหตุฉุกเฉินด้วยตัวเอง ตัว orchestrator จะจัดการทั้งเรื่องสเกลและการล้มเหลว เพื่อให้การบริการดำเนินต่อไปได้อย่างไม่หยุดชะงัก
เริ่มต้นใช้งาน: YAML, JSON และ API Server
การเริ่มต้นใช้งาน Kubernetes หมายถึงการละทิ้งการสั่งการแบบ imperative (click-ops) และหันมาใช้การกำหนดค่าแบบ declarative แทน คุณเขียนสิ่งที่คุณต้องการลงในไฟล์ YAML หรือ JSON ไฟล์ manifest เหล่านี้จะอธิบายทุกอย่าง ตั้งแต่ container image ไปจนถึงจำนวน replicas, พอร์ตที่เปิดไว้ (exposed ports), ตัวแปรสภาพแวดล้อม (environment variables) และการเชื่อมต่อพื้นที่จัดเก็บข้อมูล (storage mounts) เมื่อไฟล์ของคุณพร้อมแล้ว คุณจะส่งมันไปยัง API server บน master node จากนั้น control plane จะรับคำประกาศนั้นมา จัดเก็บไว้ในฐานข้อมูลสถานะของคลัสเตอร์ (cluster state database) และเริ่มทำงานเพื่อให้ความเป็นจริงตรงกับสิ่งที่คุณระบุไว้ คุณไม่ได้บอก Kubernetes ว่าต้องทำงานอย่างไรอย่างละเอียด แต่คุณบอกว่าผลลัพธ์สุดท้ายควรเป็นอย่างไร แล้วมันจะหาวิธีดำเนินการเอง
บทสรุปที่แท้จริง
Kubernetes มีช่วงเวลาในการเรียนรู้ (learning curve) คำศัพท์ต่างๆ อาจจะดูซับซ้อนในช่วงแรก มีส่วนประกอบที่เคลื่อนไหวอยู่มากมาย และการดีบั๊ก (debugging) ระบบแบบกระจาย (distributed system) นั้นยากกว่าการดีบั๊กเซิร์ฟเวอร์เดี่ยวๆ โดยธรรมชาติ แต่ผลตอบแทนที่ได้คือความสงบในการปฏิบัติงาน (operational calm) คุณไม่ต้องคอยเฝ้าดูเครื่องแต่ละเครื่องตลอดเวลา คุณไม่ต้องภาวนาให้สคริปต์เริ่มต้นทำงานได้ในช่วงที่ระบบล่มตอนตี 3 คุณเริ่มออกแบบเพื่อรองรับความล้มเหลว (designing for failure) เป็นค่าเริ่มต้น โดยสมมติว่าโหนดต่างๆ อาจจะเสียได้ และเชื่อมั่นในตัว orchestrator ว่าจะรักษาแอปพลิเคชันของคุณให้ทำงานต่อไปได้ การเปลี่ยนแนวคิดจากการ "หวังว่าไม่มีอะไรพัง" เป็น "รู้ว่าระบบสามารถรับมือกับความเสียหายได้" คือสิ่งที่ทำให้ความพยายามนี้คุ้มค่า
แหล่งที่มา: What Is Kubernetes? Kubernetes Explained in 15 Mins
ชุมชนการเรียนรู้เพิ่มเติม: GyaanSetu AI on Telegram
