4 คะแนน โดย GN⁺ 2025-06-21 | 2 ความคิดเห็น | แชร์ทาง WhatsApp
  • Kubernetes เป็นผู้นำการปฏิวัติด้าน container orchestration มาตลอด 10 ปีที่ผ่านมา
  • พบข้อจำกัดและความจำเป็นต้องปรับปรุงหลายด้านในระบบปัจจุบัน เช่น การตั้งค่าด้วย YAML, การพึ่งพา etcd, การจัดการแพ็กเกจด้วย Helm
  • มีการพูดถึงองค์ประกอบการเปลี่ยนแปลงของ Kubernetes 2.0 เช่น การนำ HCL มาใช้, storage แบบปลั๊กอิน, ตัวจัดการแพ็กเกจใหม่ (KubePkg), การใช้ IPv6 เป็นค่าเริ่มต้น
  • แม้โครงสร้างแบบเปิดในปัจจุบันจะสำคัญ แต่ ค่าเริ่มต้นและทิศทางอย่างเป็นทางการส่งผลชี้ขาดต่อการสร้างนวัตกรรมใน ecosystem
  • เห็นชัดว่า Kubernetes จำเป็นต้องเหมาะกับผู้ใช้และองค์กรที่กว้างขึ้น ผ่าน การปรับปรุงแบบพลิกโฉมอย่างต่อเนื่อง

10 ปีของ Kubernetes: ความสำเร็จและข้อจำกัด

จุดเริ่มต้นและการเติบโต

  • ช่วงปี 2012~2013 ข่าวลือเกี่ยวกับ Borg ซึ่งเป็นระบบ Linux container ภายในของ Google เริ่มแพร่กระจายในชุมชน sysadmin
  • ในปี 2014 มีการเปิดตัว Kubernetes และในช่วงแรกแม้แต่ชื่อก็ยังออกเสียงยาก
  • บริษัทใหญ่อย่าง Microsoft, RedHat, IBM, Docker เข้าร่วมอย่างรวดเร็ว ทำให้ Kubernetes เริ่มตั้งหลักเป็นมาตรฐานของ ecosystem
  • ปี 2015 มีการเปิดตัว v1.0 และการก่อตั้ง CNCF จนเกิด ecosystem แบบเปิดอย่างจริงจัง

จุดสำคัญของนวัตกรรม

การจัดการ container ในระดับขนาดใหญ่

  • Kubernetes มอบความสามารถในการขยายตัวสำหรับ การพัฒนาและ deployment ซอฟต์แวร์แบบ container-based
  • ทำให้สามารถ deploy สภาพแวดล้อมเดียวกันในวงกว้าง ได้ ตั้งแต่สภาพแวดล้อมพัฒนาแบบง่ายไปจนถึงเซิร์ฟเวอร์หลายพันเครื่อง
  • องค์กรต่าง ๆ จึงมีจุดเปลี่ยนสำคัญในการย้ายจาก monolithic architecture ไปสู่ microservices แบบกระจาย

การบำรุงรักษาต้นทุนต่ำและ self-healing

  • การดูแลเซิร์ฟเวอร์เปลี่ยนอย่างรวดเร็วจากยุค "Simpsons" (แต่ละเซิร์ฟเวอร์มีชื่อเล่นและดูแลด้วยมือ) ไปสู่ยุค "UUID" (แทนที่ทั้งหมด, อัตโนมัติ, stateless)
  • แนวคิดเรื่อง อายุการใช้งานของเครื่องและระยะเวลาซัพพอร์ตของ OS แทบหายไป และเมื่อเสียหายก็จะถูกสร้างโหนดใหม่เพื่อจัดระบบอัตโนมัติ
  • ทักษะ Linux หลายอย่างที่เคยจำเป็น ตอนนี้กลายเป็นเพียงทักษะที่ "มีก็ดี"

งาน batch และการจัดการ Job

  • การประมวลผลงานแบบ batch ที่เคยพึ่งพา "cron box เฉพาะทาง" ถูกแทนที่ด้วยงานอัตโนมัติแบบอิง queue และกลไก retry
  • การรีสตาร์ตอัตโนมัติเมื่อเกิดความล้มเหลวและการจัดการที่ยืดหยุ่น ช่วยเพิ่ม ประสิทธิภาพการปฏิบัติการ และความพึงพอใจของนักพัฒนาอย่างมาก

Service discovery และ load balancing

  • มีการนำ ระบบการตั้งชื่อบริการบนพื้นฐาน DNS ภายใน มาใช้แทนการ hardcode IP address
  • ทำให้การเชื่อมต่อระหว่างบริการง่ายขึ้นผ่าน API, fixed IP, hostname และยังสามารถจัดการบริการภายนอกราวกับเป็นบริการภายในได้

Kubernetes 2.0: ข้อเสนอการปรับปรุงหลัก

จาก YAML ไปสู่ HCL: เปลี่ยนภาษาสำหรับการตั้งค่า

ข้อจำกัดของ YAML

  • แม้ YAML จะดูอ่านง่ายและดูดีกว่า JSON หรือ XML แต่ก็มีปัญหาร้ายแรง เช่น ก่อให้เกิดข้อผิดพลาด, ไม่รองรับ type, debug ยาก
  • ตัวอย่าง) ปัญหาแบบนอร์เวย์ ('NO' ถูกตีความเป็น false), ความผิดพลาดจาก indentation, ความสับสนระหว่างตัวเลขกับสตริง ฯลฯ

ทางเลือก: ใช้ HCL

  • HCL(HashiCorp Configuration Language) เป็นฟอร์แมตมาตรฐานของ Terraform และมีความสามารถที่ยอดเยี่ยม เช่น strong typing, validation, functions, conditional branching
  • ปัจจุบัน Kubernetes cluster จำนวนไม่น้อยก็ใช้ HCL ร่วมกับ Terraform อยู่แล้ว
  • HCL มีความสามารถที่ทรงพลังกว่า YAML เช่น ความปลอดภัยด้าน type, การลดความซ้ำซ้อน, การตั้งค่าแบบ dynamic, การทำซ้ำ, conditional logic, การรองรับคอมเมนต์ที่ดีเยี่ยม, modularity และการตรวจสอบความถูกต้อง
  • แม้ยังมีประเด็นเรื่อง license ของโอเพนซอร์ส (MPL 2.0 → ความเข้ากันได้กับ Apache 2.0) แต่ก็ยังมีคุณค่ามากพอสำหรับการยกระดับคุณภาพ
ตัวอย่าง: HCL vs YAML
  • ด้วยข้อดีของ HCL เช่น type, variables, functions, conditional statements, loops จึงช่วยป้องกันข้อผิดพลาดในการตั้งค่าได้ล่วงหน้า เพิ่มการดูแลรักษา และรักษาความสม่ำเสมอแม้ในสภาพแวดล้อมที่ซับซ้อน

รองรับตัวเลือกแทน etcd

  • etcd แม้ทรงพลัง แต่สำหรับ cluster ขนาดเล็กหรือสภาพแวดล้อมที่สเปกต่ำกลับใช้ทรัพยากรมากเกินไป
  • มีข้อเสนอให้ขยายความยืดหยุ่นของ storage พื้นฐาน ผ่านการรองรับ backend แบบปลั๊กอินอย่างเป็นทางการ เช่น Kine
  • ตัวอย่าง) k8s-dqlite: มอบ data layer ที่เบาและยืดหยุ่นด้วย distributed SQLite+Raft

ก้าวข้าม Helm: package manager แบบ native

ข้อจำกัดของ Helm

  • Helm เป็นกรณีที่โซลูชันแบบแฮ็กชั่วคราวกลายเป็นมาตรฐาน โดยมีปัญหาหลากหลาย เช่น ความซับซ้อนของ template, ความยากในการ debug, ความขัดแย้งของ dependency/เวอร์ชัน, การตรวจสอบที่ไม่เพียงพอ
  • ในการใช้งานจริงยังพบความยากอีกมาก เช่น chart ซ้ำซ้อนหลายชุด, เวอร์ชันไม่ตรงกัน, การติดตั้งข้าม namespace ที่ยุ่งยาก, การขาดการค้นหา chart/metadata, ไม่ปฏิบัติตาม semantic versioning, การจัดการ CRD ที่ไม่ปลอดภัย

ข้อเสนอระบบแพ็กเกจใหม่: KubePkg

  • จัดการได้ครอบคลุมทั้ง package/dependency/semantic version/security/lifecycle/metadata ในรูปแบบของ Kubernetes resource
  • ครบถ้วนด้วย lifecycle hook ที่ละเอียด, กลยุทธ์ด้าน state และ backup/recovery, declarative configuration, กระบวนการลงลายเซ็นที่ตรวจสอบได้, audit log และการควบคุมนโยบายระดับองค์กร
  • มุ่งสืบทอด ข้อดีของ Linux package manager เพื่อให้ได้ความน่าเชื่อถือและความสม่ำเสมอที่แข็งแกร่งต่อการจัดการ infrastructure จริง

ข้อกำหนดสำคัญ

  1. โครงสร้าง resource แบบ Kubernetes native อย่างสมบูรณ์
  2. รองรับแอปพลิเคชันแบบ stateful ในตัว
  3. เสริมกระบวนการ signing/validation/security scanning
  4. declarative configuration แบบมีโครงสร้าง + schema validation
  5. ควบคุม lifecycle ได้ครบถ้วนและรองรับ Upgrade/Hook อย่างง่าย
  6. การตีความ dependency/เวอร์ชันแบบ Linux style
  7. ประวัติการเปลี่ยนแปลงและ audit trail
  8. สามารถบังคับใช้นโยบายเฉพาะองค์กรได้
  9. มอบ UX การจัดการแพ็กเกจแบบ Linux ที่คุ้นเคย

เปลี่ยนค่าเริ่มต้นเป็น IPv6

  • ปัจจุบันรองรับทั้ง IPv6 และ dualstack แล้ว แต่ค่าเริ่มต้นยังคงเป็น IPv4
  • สิ่งนี้มีข้อดีในการแก้ปัญหา การสื่อสารระหว่าง cluster, ปัญหา NAT, การขาดแคลน IP พร้อมทั้งให้โครงสร้างเครือข่ายที่เรียบง่ายกว่าและมี IPSec ในตัว
  • ในสภาพแวดล้อมที่ต้องการ IP จำนวนมาก (เช่น ช่วง /20, มี 40 โหนด, 1 โหนดมี 30 pod) จะชนข้อจำกัดของ IPv4 อย่างรวดเร็ว
  • ยังมีประโยชน์เชิงปฏิบัติอย่างชัดเจน เช่น ความง่ายในการดำเนินงานบน public IPv6, การดึงดูดผู้ใช้ cloud และการลดภาระในการจัดการ private address space

บทสรุป: ความจำเป็นของการเปลี่ยนแปลงและพลังของค่าเริ่มต้น

  • แม้อาจมีความเห็นว่า "เพราะเป็น open platform ชุมชนก็จัดการกันเองได้" แต่ ค่าเริ่มต้น คือสิ่งที่กำหนดพฤติกรรมของทั้งอุตสาหกรรม
  • สำหรับ Kubernetes 2.0 ตอนนี้ถึงเวลาที่ต้องมี ความเชื่ออย่างเป็นทางการ, การออกแบบที่ยอดเยี่ยม, และค่าเริ่มต้นที่ทรงพลัง
  • ในฐานะมาตรฐานของอุตสาหกรรมและกระแสหลักของการดำเนินงาน data center ทั่วโลก นี่คือช่วงเวลาสำคัญของ การก้าวกระโดดครั้งใหม่
  • ในหลายวงการเทคโนโลยี ทั้งมือถือ เว็บ และด้านอื่น ๆ การเปลี่ยนแปลงแบบกล้าหาญ ได้จุดประกายนวัตกรรมของ ecosystem ทั้งหมดซ้ำแล้วซ้ำเล่า
  • ถึงเวลาแล้วที่ Kubernetes จะใช้ 2.0 อันเป็นหมุดหมายสำคัญเพื่อคิดถึงก้าวถัดไป

2 ความคิดเห็น

 
kaydash 2025-06-23

ผมคิดว่าวิศวกรที่สามารถประกอบและดูแล vanilla k8s ซึ่งสร้างขึ้นจากการนำโอเพนซอร์สมาผูกเข้าด้วยกันได้ จะยังคงมีอยู่เพียงส่วนน้อยต่อไป
ก็เหมือนกับที่ในอดีตมีวิศวกรเพียงส่วนน้อยมากที่สามารถดูแล vanilla Hadoop ecosystem ได้ โดยไม่ซื้อ Hadoop cluster ที่ถูกรวมมาเป็นแพลตฟอร์มของ Cloudera

 
GN⁺ 2025-06-21
ความเห็นใน Hacker News
  • ปัญหาใหญ่ที่สุดของ Kubernetes สำหรับผมคือมันไม่ใช่ระบบที่ "แค่ใช้แล้วมันก็ทำงาน" ได้เลย ในความเป็นจริงมีวิศวกรเพียงไม่กี่คนที่สามารถรันบริการในโปรดักชันได้อย่างราบรื่น และการสร้างกับดูแล Kubernetes cluster บน VM เองยิ่งยากเข้าไปอีก นั่นจึงเป็นเหตุผลที่สตาร์ตอัปสาย serverless ที่กำลังมาแรงช่วงนี้เกิดขึ้น เพราะมีมุมมองแพร่หลายว่า (1) มันกินเวลามาก (2) มีข้อผิดพลาดเยอะมาก และ (3) มีโอกาสล้มเหลวสูงในสภาพแวดล้อมโปรดักชัน ผมคิดว่า Kubernetes 2.0 ควรไปในทิศทางที่ใครก็สามารถ self-host แพลตฟอร์มสำหรับ deploy ได้ง่ายและใช้งานได้อย่างมั่นใจ พร้อมคงแกน orchestrator ขนาดเล็กแต่ทรงพลังไว้ ตอนนี้ผมกำลังพัฒนา orchestrator และ deployment platform ชื่อ Rivet โดยชูว่าเป็น แพลตฟอร์ม serverless แบบโอเพนซอร์สของ Rivet แต่ก็ยังถามตัวเองบ่อย ๆ ว่า “Kubernetes 2.0 จะหน้าตาเป็นยังไง?” และตอนนี้ก็มีกรณีที่ผู้คนนำ Rivet ไปใช้กับสถานการณ์ที่เกินความคาดหมายมากขึ้นเรื่อย ๆ จุดแข็งที่สุดของ Rivet คือทำฟีเจอร์ระดับ Kubernetes controller ได้ง่ายมาก ทำให้เอาไปใช้ได้กับหลายสถานการณ์ เช่น เกมเซิร์ฟเวอร์ การ deploy แยกตาม tenant การ orchestrate workload ขั้นสูง multi-tenancy การคิดค่าบริการแยกตาม tenant และการออกแบบ operator ที่ทรงพลัง

    • มุมมองแบบนี้ทำให้ผมหงุดหงิดพอสมควร อาจเพราะอายุมากขึ้นและค่อนข้างมองโลกแบบถากถางนิด ๆ เลยเห็นแพตเทิร์นนี้บ่อยมาก เทคโนโลยี X หนักเกินไปจนมีคนบอกว่า "ฉันแค่อยากรันแบบง่าย ๆ บนโน้ตบุ๊กโดยไม่ต้องใช้มัน" แล้วคนนั้นก็สร้างเทคโนโลยี Y ขึ้นมา จากนั้น Y ก็ได้รับความนิยม และเมื่อเริ่มถูกใช้ในที่ที่ไม่ใช่โน้ตบุ๊ก มันก็ต้องเพิ่มความสามารถในการขยายระบบจนหนักขึ้น สุดท้ายก็มีคนอีกกลุ่มพูดว่า "ตอนนี้ Y ก็หนักเกินไปแล้ว" แล้ววนซ้ำประโยคเดิมอีกครั้ง มันเหมือน 'กงล้อแห่งกาลเวลา' ที่ไม่มีจุดเริ่มหรือจุดจบ เป็นเรื่องเล่าซ้ำไปซ้ำมาไม่รู้จบ

    • ความจริงคือ k3s (k8s แบบเบา) ดูแลง่ายมาก ถ้ามี auto-update ของ k3s และมีกฎ eviction ที่เหมาะสม แทบไม่ต้องแตะอะไรเลย และถ้า storage อย่าง Ceph ยากเกินไป ก็เลือกทางเลือกแบบ “แทบไม่ต้องดูแล” อย่าง Lemon หรือ Longhorn ได้ มี Helm chart หลายพันรายการ ทำให้แม้แต่ฐานข้อมูลที่ซับซ้อนก็ deploy ได้ใน 1 นาที การ deploy บริการเองก็ง่ายมากถ้าใช้ Helm template ที่นิยมกัน Helm ไม่ได้สมบูรณ์แบบ แต่ถ้าตั้งค่าให้ดี คุณก็ยังได้ประโยชน์อย่าง value completion เป็นต้น จุดเริ่มต้นอาจสูงกว่า serverless นิดหน่อย แต่การเรียนสักหนึ่งสัปดาห์แล้วประหยัดค่าโปรดักชันจริงได้เป็นหลักหลายแสนวอนก็คุ้มมาก

    • ปัญหาที่ Kubernetes แก้คือ "จะ deploy สิ่งนี้อย่างไร?" แต่พอดู Docs ของ Rivet กลับมีแค่ single container, Docker Compose และ manual deploy (คำสั่ง Docker) เท่านั้น ทำให้สงสัยว่าโครงสร้างพื้นฐานแบบ serverless จะ deploy ในสเกลจริงด้วยวิธีนี้ได้จริงหรือไม่ คำถามแรกของผมคือ "มาถึงจุดนี้แล้ว ทำไมไม่รัน Rivet บน Kubernetes เลยล่ะ (container, kube-virt ฯลฯ)?" ผมไม่เห็นว่า Docker Compose จะ robust หรือขยายระบบได้ดีกว่า Kubernetes อย่างไร ถ้าไม่ใช่แบบนั้นและคุณกำลังขายบริการคลาวด์ มันก็ไม่สอดคล้องกับคอนเซปต์ Kubernetes 2.0 ด้วย ถ้าต้อง self-host Rivet เอง ผมคงเปลี่ยนเอกสารให้มันรันบน Kubernetes ได้

    • ถ้าใช้ “k8s แบบบริการ” ที่เอาการดูแลคลัสเตอร์ไป outsource ให้คลาวด์เวนเดอร์ ผมอยากรู้ว่ามีส่วนไหนที่รู้สึกซับซ้อนมากนัก ถึงขอบเขตการตั้งค่าจะกว้าง แต่สำหรับการประกอบบริการเพื่อส่งขึ้นโปรดักชันจริง ๆ รู้แค่ไม่กี่ค่าก็พอ การตั้งค่าที่ซับซ้อนกว่า Docker Compose เล็กน้อยก็ deploy ลง k8s ได้สบาย แต่สำหรับแอปส่วนใหญ่ แม้แต่ความ “เพิ่มขึ้นเล็กน้อย” นี้ก็อาจไม่จำเป็น ความต้องการแบบแมสมาก ๆ จริง ๆ แล้วคือสิ่งที่ Docker Compose เคยพยายามตอบโจทย์ เพียงแต่น่าเสียดายที่มันไม่ได้รับความสนใจต่อเนื่อง

    • จากประสบการณ์ของผม ในงานอินฟราฯ ไม่มีทางมีอะไรที่ “แค่ใช้แล้วมันก็ทำงาน” ได้จริง แม้แต่ Heroku ก็ยังมีปัญหาเรื่องการสเกล ถ้าอยากได้ deployment platform ที่ทุกคนรับไปใช้ได้ง่าย การมอง Kubernetes ว่าเป็น primitive พื้นฐานของ PaaS แบบใดแบบหนึ่งน่าจะสมจริงกว่า Rivet มีเอกลักษณ์ดีและยังเห็นแนวคิดบางอย่างจากระบบนิเวศ BEAM ด้วยเลยน่าสนใจ สำหรับผมเองสนใจเรื่องความแข็งแกร่งและ local-first มากกว่าการ deploy ขนาดใหญ่

  • “Low maintenance” เหรอ... ผมใช้ EKS (managed k8s) เยอะมาก และแทบไม่ต้องสนใจสถานะของคลัสเตอร์เองเลย (แน่นอนว่าไม่รวมวิธีพิสดารที่ผมอาจทำ node พังเอง) Kubernetes ชอบทำตัวเหมือน “แทบไม่ต้องดูแล” แต่ความจริงคือมันคือก้อนมหึมาของงานดูแลรักษาล้วน ๆ การโยน yaml เข้าไปแล้ว deploy ซอฟต์แวร์ออกสู่โลกได้ทันทีนั้นยอดเยี่ยมมาก แต่ราคาที่ต้องจ่ายคือความซับซ้อนในการดูแล การตั้งค่าคลัสเตอร์ การ bootstrap ArgoCD การลงทะเบียนคลัสเตอร์อื่นในโมเดล hub-spoke ทั้งหมดนี้ก็เหมือนโชว์ละครสัตว์ฉากหนึ่ง ยังไม่รวมการติดตั้ง operator ที่พอใช้ได้จาก tooling ใน CNCF Landscape และเครื่องมือเสริมอีกมากมาย (แม้ทางกายภาพจะไม่ใช่ลำดับแรกแต่ก็ขาดไม่ได้) จนสุดท้ายมีอย่างน้อยราว 30 ตัวกำลังทำงานอยู่ การตั้งค่า values.yaml ก็ไม่ใช่เรื่องชั่วโมงสองชั่วโมง ส่วนใหญ่หมดเวลาไปกับ ArgoCD และงาน template อย่าง Secrets Manager -> External Secrets -> ArgoCD ApplicationSet -> values.yaml อีกไฟล์หนึ่ง แค่ส่งค่า boolean ตัวเดียวก็เสียเวลาไม่น้อย รอบการอัปเดตคลัสเตอร์/โอเปอเรเตอร์ก็เร็ว ทำให้มีปัญหางานดูแลเกิดอยู่เสมอ เวลาใช้ Karpenter ทำ autoscale ก็มีการเปลี่ยน node และการทำให้ไร้ downtime ซึ่งเป็นอีกเวทีผาดโผนหนึ่ง (แอปแบบ stateful บน k8s ยิ่งสนุกเป็นสองเท่า) สรุป: คำว่า “Low maintenance” เป็นคำประชดมากกว่า

    • “Low maintenance” สุดท้ายก็เป็นแนวคิดสัมพัทธ์เมื่อเทียบกับทางเลือกอื่น จากประสบการณ์ของผม เมื่อใช้ k8s ภาระการดูแลเพื่อให้ได้บริการคุณภาพระดับเดียวกันนั้นต่ำกว่ามาก ทั้งด้านการสเกล การ failover การ rollback การกู้คืนจากภัยพิบัติ DevOps และการ spin up คลัสเตอร์แยกอิสระ แน่นอนว่าอาจต่างกันตามสถานการณ์ แต่นี่คือประสบการณ์ของผม

    • ผมใช้ k3s บน hetzner มา 2 ปีแล้วและได้ uptime 100% ภาระการดูแลต่ำมากจนครั้งหนึ่งผมทำ SSH key ของ master node หาย แต่การ provision คลัสเตอร์ใหม่ทั้งหมดรวมถึงอัปเดตเอกสารใช้เวลาแค่ 90 นาที ถ้าด่วนจริง 15 นาทีก็น่าจะพอ ตอนนี้ผมรันคลัสเตอร์ k8s ที่มี ARM 3 nodes 1 master, storage เล็กน้อย และ DNS อัตโนมัติผูกกับ Cloudflare ในงบเดือนละ 20 ยูโร

    • แต่สิ่งที่คุณกำลังดูแลจริง ๆ ไม่ใช่ Kubernetes เอง แต่เป็นระบบเสริมอย่าง CI/CD, ระบบจัดการ secrets และระบบอัตโนมัติสำหรับปฏิบัติการฐานข้อมูลต่างหาก เมื่อก่อนสิ่งเหล่านี้ก็คงทำด้วย cronjob, ansible, systemd, bash script แทน yaml

    • ฟังดูเหมือนคุณสร้างโรงละครสัตว์ขึ้นมาด้วยมือตัวเอง ไม่ควรติดตั้งของมากขนาดนั้น ทุกครั้งที่เพิ่มอะไรเข้าไปก็เท่ากับเพิ่มหนี้ทางเทคนิคและต้นทุนการดูแล ต่อให้เป็นเครื่องมือฟรีก็เหมือนกัน ถ้า autoscale ทำให้หนี้/ค่าดูแลมากกว่าที่ประหยัดได้ ก็ปิดมันไปเถอะ

    • ถ้าคุณต้องประกอบและรันชุดบริการคล้ายกันแบบแยกเป็นรายตัว ภาระดูแลจะหนักกว่านี้มาก แต่ Kubernetes นั้นดูแลง่ายพอที่จะปล่อยไว้หลังจากจุดไฟติดแล้วได้เลย ตราบใดที่คุณรู้ว่าตัวเองกำลังทำอะไรอยู่ คุณก็จะไม่ตกหลุมพรางการติดตั้ง “เครื่องมือที่ดูเท่”

  • K8S ไม่ได้บังคับให้ใช้ yaml ด้วยซ้ำ มันอาจเป็นแนวทางที่ idiomatic แต่ไม่ใช่ข้อบังคับ kubectl apply รองรับ json มาตั้งแต่แรก และ endpoint ก็เป็น json กับ grpc คุณยังสร้าง config จากภาษาต่าง ๆ อย่าง jsonnet ได้ด้วย ประเด็นที่สองคือผมสงสัยว่าทำไม dependency และ dependency ordering ใน Helm chart ถึงกลายเป็นปัญหา idiom หลักของ Kubernetes อยู่ที่ loop: ถ้ายังไม่มี dependency ก็ถือว่าเป็น recoverable error แล้ว retry ไปเรื่อย ๆ จนกว่าจะพร้อม หรือไม่ก็ crash แล้วให้ ReplicaSet controller รีสตาร์ตให้อัตโนมัติ ถ้า chart ไม่มี dependency ก็ไม่มี dependency conflict ถ้าเป็นแอปที่ต้องพึ่งกันจริง ก็ควรใส่แอป/บริการที่พึ่งพานั้นรวมไปใน Helm chart เดียวกัน

    • (อ้างความเห็นหลัก) > การที่ ReplicaSet controller รีสตาร์ตแอปให้ตอน crash นั้นไม่เพียงพอ ตัวอย่างเช่นถ้า keycloak ใช้เวลา 1 นาทีในการเริ่มทำงาน บริการที่พึ่งมันจะ crash ทันทีเพราะยังไม่มี keycloak แล้วพอ retry ไปสักพักก็โดน throttle ทำให้หลังจาก keycloak พร้อมแล้วก็ยังต้องรออย่างเสียเปล่าอีก 5-10 นาที ถ้าความสัมพันธ์ของ dependency ชัดเจน แบบนี้ใช้ init container ตรวจสอบบริการที่พึ่งพาก่อนค่อยรัน main container น่าจะเหมาะกว่า ผมคิดว่าน่าจะมีความสามารถในการประกาศ start dependency แบบชัดเจนใน Kubernetes เพราะการปล่อยให้ crash แล้ว retry ไม่กี่ครั้งก่อนโดน throttle ไม่ใช่คำตอบ dependency เป็นความจริงที่มีอยู่แล้ว

    • ผมคิดว่าความล้มเหลวของ dependency ควร recoverable ได้เสมอ ผมเคยมีประสบการณ์ระบบล่มเพราะ dependency ที่จริง ๆ แล้วแทบไม่ได้ใช้งานแต่ถูกทำให้ fail-closed ความสัมพันธ์ระหว่างเซิร์ฟเวอร์แทบทั้งหมดเป็น soft dependency ถ้า downstream dependency ใช้ไม่ได้ก็แค่ส่ง 500 แล้วให้ load balancer เลี่ยงเซิร์ฟเวอร์ที่ unhealthy ก็พอ

    • เขาพูดว่า “supposed to” แต่สิ่งนั้นใช้ได้ดีกับกรณีสร้างซอฟต์แวร์สแตกภายในองค์กรเท่านั้น ซอฟต์แวร์เก่า ๆ ที่สร้างเสร็จแล้วจำนวนมากเดิมรองรับแค่ docker แล้วค่อยถูกทำให้รันบน kubernetes ได้ทีหลัง เมื่อนักพัฒนาสร้างเครื่องมือตามปรัชญาของตัวเอง คนใช้ก็ยังหาทางใช้ในแบบที่ตัวเองต้องการอยู่ดี จนบางครั้งผลลัพธ์ก็เละเทะ สุดท้ายคุณต้องให้ฟีเจอร์และทางเลือกหลากหลายแก่ผู้คน และตลาดก็จะนำไปใช้ตามที่ตัวเองต้องการ

    • ผมเห็นด้วยมากกับคำพูดที่ว่า “ลักษณะสถาปัตยกรรมหลักของ Kubernetes คือ reconciliation loop” สังเกตสถานะปัจจุบัน เปรียบเทียบกับสถานะที่ต้องการ แล้วก็ apply เท่าที่ต่างกัน ทำซ้ำไม่รู้จบ มันไม่ใช่เรื่องสำเร็จ/ล้มเหลว แต่เป็นการแก้ความต่างระหว่างสถานะปัจจุบันกับสถานะเป้าหมายแบบ iterative อย่างเดียว ผมมองว่าแพตเทิร์นนี้คล้ายกับ 'good enough technology' ของระบบควบคุมเชิงกลอย่าง PID control ด้วย

    • การวิจารณ์ประเด็นนี้ด้วยข้อเท็จจริงว่า “ไม่ใช้ yaml ก็ใช้ json ได้” มันไม่ตรงจุด เพราะนั่นไม่ใช่สิ่งที่คนส่วนใหญ่สนใจจริง ๆ รู้สึกว่าเป็นการจับผิดจุกจิกมากกว่า

  • ผมคัดค้านอย่างหนักกับความเห็นที่ว่าให้เปลี่ยนจาก yaml ไปใช้ HCL แทน HCL ดูยากและอ่านยากสำหรับนักพัฒนา ผมมีข้อไม่พอใจมากเรื่อง usability เช่น รองรับ import แค่ไหน ดีบักยากหรือไม่ ฯลฯ ผมไม่เข้าใจเลยว่าทำไมไม่เอาภาษาอธิบาย interface อย่าง protobuf มาเป็นแกนกลาง แล้วปล่อยให้ผู้ใช้แปลงรูปแบบไปตามความชอบ

    • HCL แย่มาก yaml ของ k8s ก็ไม่เคยไม่พอสำหรับผม ถ้าคอนฟิกซับซ้อนเกินไป ปัญหาน่าจะอยู่ที่การออกแบบแอปมากกว่า config map

    • จริง ๆ จะเป็น HCL, JSON หรือ YAML ก็แค่ serialize/deserialize กันที่ฝั่งไคลเอนต์ได้ทั้งนั้น นั่นหมายความว่านี่ไม่ใช่ประเด็นของ Kubernetes เอง แต่เป็นเพียงชั้นแปลงภายนอกเท่านั้น

    • นิยาม interface ของ Kubernetes ก็อิง protobuf อยู่แล้ว (ยกเว้น crd)

    • ข้อร้องเรียนหลักของผมกับ HCL คือ syntax ของ for loop มันแย่มากจริง ๆ

    • เรื่องที่ว่า “HCL ยากสำหรับนักพัฒนาและ lint/debug ยาก” ฟังดูคล้ายคนที่ไม่อยากเรียนของใหม่มากกว่า ดูเหมือนจะสับสนระหว่างการเรียน HCL กับความซับซ้อนของโดเมนเสียมากกว่า

  • ผมกำลังพัฒนา โปรเจกต์ nebulous ในสไตล์ “Kubernetes 2.0” (ยังอยู่ระดับ pre-alpha) เป้าหมายคือกระจายศูนย์/น้ำหนักเบาในระดับทั่วโลก รันเป็น single binary บนโน้ตบุ๊กได้ และสเกลขึ้นไปถึงหลายพันโหนดบนคลาวด์ได้ พร้อมฟีเจอร์อย่างเครือข่าย Tailnet, storage แบบ BitTorrent, multi-tenancy, live migration ฯลฯ ข้อกำหนดส่วนใหญ่เกิดจากการปฏิบัติการ ML (โดยเฉพาะปัญหาขาดแคลน GPU) และถ้าโลกอนาคต ML กลายเป็นเรื่องธรรมดา สิ่งเหล่านี้อาจกลายเป็นมาตรฐานพื้นฐานก็ได้

    • live migration น่าสนใจมาก ตอนนี้เราใช้กลยุทธ์ด้านราคาที่อิง autoscaling ข้ามหลายคลัสเตอร์และหลายคลาวด์อยู่แล้ว แต่ live migration นี่เป็นความท้าทายอีกระดับหนึ่ง

    • นี่ไม่ใช่ Kubernetes แต่เป็นระบบแยกที่ออกแบบมาสำหรับการปฏิบัติการ GPU โดยเฉพาะ

    • “กระจายศูนย์ระดับโลก” อาจเป็น non-requirement เสียด้วยซ้ำ ถ้าใช้ Tailnet เป็นเครือข่ายพื้นฐาน นี่อาจเป็นฟีเจอร์ที่ผมอยากตัดออกก่อนเลย สมมติฐาน single NIC ของ Kubernetes เป็นมรดกน่าอึดอัดที่เหมาะกับคลาวด์มากเกินไป (เลยยิ่งดีใจที่มีหลาย CNI และโปรเจกต์อย่าง Multus ในช่วงหลัง ดู บล็อกของ redhat) ส่วนการออกแบบ multi-tenant นั้นผมอยากรู้ว่ามันต่างจาก k8s ในทางปฏิบัติอย่างไร และถ้าทำ storage ด้วย BitTorrent ถ้าแชร์แม้แต่ public container image ด้วย ค่า egress traffic จะมหาศาลมาก

    • พอดูใน GitHub ก็เห็น Chart.yaml แถม template อย่าง provider_aws.yaml ก็เป็นแพตเทิร์นโค้ดที่ผมไม่อยากเห็นจริง ๆ

  • ผมยังรู้สึกว่า Kubernetes ซับซ้อนมากอยู่ดี เพียงแต่ความแพร่หลายทำให้มันรู้สึกน้อยลง ใน Kubernetes 2.0 ผมอยากให้ประสบการณ์ผู้ใช้ โดยเฉพาะงานที่ทำบ่อยอย่าง deploy แอป เปิดบริการ เปลี่ยน service account/อิมเมจ ฯลฯ ง่ายขึ้นกว่านี้ แต่ตอนนี้กระแสหลักคือ LLM เลยดูเหมือนการพัฒนาต่อจะยาก

    • Kubernetes มีชั้น abstraction เยอะเกินไป pods เป็นแนวคิดแกนกลางที่เท่มาก แต่พอมี deployment, rep set, namespace ฯลฯ เพิ่มเข้ามา ก็อดคิดไม่ได้ว่าถ้ามันเรียบง่ายแบบ Docker Swarm ก็คงดี Terraform ก็มีชั้นเดียวและเรียนรู้ง่ายกว่า ตอนนี้ผมกำลังตระหนักอย่างแท้จริงว่าเส้นโค้งการเรียนรู้ของ K8s ชันมาก

    • นี่เป็นประเด็นที่ทำให้ผมนึกถึงความคิดว่า “การแบ่งประเภทของคอมพิวเตอร์โปรแกรมคือผลลัพธ์จากการรับรู้ของมนุษย์” operator/controller นั้น abstract มากเกินไปเหมือน COM/CORBA ในอดีต (ซึ่งเป็นทั้งข้อดีและข้อเสีย) สำหรับการใช้งานเรียบง่าย บางที k8s-lite ที่จำกัดกว่าน่าจะเหมาะกว่า ตรงกันข้าม ในสภาพแวดล้อมที่ซับซ้อน abstraction เดิมของ k8s ก็ยังไม่พออยู่ดี ผมสงสัยว่าระบบเดียวระบบหนึ่ง (จะเป็น Kubernetes 2.0 หรืออะไรก็ตาม) จะครอบคลุมปัญหาโลกจริงทั้งหมดได้ในสภาพที่นักพัฒนา/ผู้ออกแบบมนุษย์ยังรับมือไหวหรือไม่

  • ผมต้องการระบบที่มี “sane default” คือแม้ไม่เลือกอะไรเป็นพิเศษ ค่าเริ่มต้นก็เพียงพอเหมาะสมอยู่แล้ว (เครือข่าย/storage/load balancer ฯลฯ) ผมไม่ชอบทั้ง yaml และ HCL เราต้องการวิธี config ที่ดีกว่านี้ และแค่เปลี่ยนภาษาอย่างเดียวก็ไม่แก้ปัญหา ผมคิดว่า IPv6 เป็นสิ่งจำเป็น Docker, container และ Kubernetes ควรเป็น IPv6-only ภายในมาตั้งแต่แรก ส่วน IPv4 ควรเป็นข้อยกเว้นที่จัดการใน ingress controller

    • มีความขัดแย้งโดยเนื้อแท้ระหว่าง “Sane defaults” กับ “การเปลี่ยนลูกค้าไปใช้ managed service” ยิ่งผมดู k8s มานานเท่าไร ก็ยิ่งเห็นปรัชญาแบบ “batteries not included” ชัดขึ้นเรื่อย ๆ ในเรื่องอย่าง storage/เครือข่าย และจากนั้น AWS/GCP ฯลฯ ก็นำไปขายเป็นบริการเชื่อมต่อราคาแพง ในความเป็นจริง k8s วันนี้บางครั้งดูไม่ใช่โอเพนซอร์สด้วยซ้ำ แต่เป็นเครื่องมือกระตุ้นการขายสำหรับอุดช่องว่างของคลาวด์

    • (ประสบการณ์ส่วนตัว) สิ่งที่ Terraform/HCL ดีกว่า YAML คือมันไม่พึ่งพาอักขระที่มองไม่เห็น จึงอ่านง่ายกว่า

    • เพราะ “sane defaults” นี่แหละ ผมถึงชอบ k3s มากกว่าเยอะ

  • สำหรับวิสัยทัศน์แบบ 2.0 ผมคิดว่านี่เป็น wish list ที่ค่อนข้างถ่อมตัว คนรอบตัวผมทุกคนบ่นเรื่องความซับซ้อนของ k8s ในโปรดักชันกันมาก ประเด็นสำคัญจริง ๆ คือจะทำ backward compatibility กับความเรียบง่ายให้ไปด้วยกันได้อย่างไร เพราะโดยปกติ backward compatibility นี่แหละทำให้ความซับซ้อนพุ่งทะยาน (ระบบใหม่ต้องแบกรับทั้งฟีเจอร์เก่าและใหม่พร้อมกัน)

    • สุดท้ายประเด็นก็อยู่ที่ว่า “จะลดความซับซ้อนได้มากแค่ไหนและตรงไหน” abstraction ของ k8s ที่ผมเห็นมาจนถึงตอนนี้มักครอบคลุมได้เพียงส่วนน้อยมาก (wrapper แบบ heroku) หรือไม่ก็สร้าง DSL ของตัวเองขึ้นมา ทำให้เส้นโค้งการเรียนรู้สูงขึ้นไปอีก (สุดท้ายต้องเรียนทั้ง k8s ที่ซับซ้อนและ DSL ประหลาดอีกหนึ่งภาษา)
  • ผมรู้สึกว่าตัวเองกำลังอยู่ใน “โลกแบบ Kubernetes 2.0” อยู่แล้ว เพราะผมจัดการทั้งคลัสเตอร์และแอปด้วย Terraform

    • ใช้ HCL/type/resource dependency/data manipulation ได้โดยตรง
    • tf apply ครั้งเดียวก็ตั้งค่าคลัสเตอร์ โหนด การเชื่อมต่อคลาวด์ (เช่น S3) และบริการในคลัสเตอร์ได้ครบ
    • ใช้ terraform module เพื่อ reuse โค้ด และรวมอินฟราที่ไม่ใช่ K8s เข้าไว้ด้วยกัน เช่นใช้โมดูล Cloudflare ZeroTrust เพื่อสร้าง public SSO endpoint ได้ในโค้ดแค่ 5 บรรทัด (deploy cloudflared ในคลัสเตอร์ + config tunnel ผ่าน Cloudflare API)
    • ผู้ให้บริการอินฟรารายใหญ่มี Terraform module ของตัวเองที่ทำมาดีอยู่แล้ว และการจัดการ dependency ของโมดูล/โปรไวเดอร์ผ่าน provider lockfile ก็สะดวก
    • จัดการ Helm chart ได้อิสระด้วย Helm terraform provider โดยเฉพาะ chart ที่ทำแค่ “สร้าง namespace + deploy operator + สร้าง custom resource” ผมจะติดตั้งเฉพาะ operator และจัดการ CRD โดยตรงใน terraform
    • ข้อเสียคือ orchestration ของกระบวนการ apply ค่อนข้างจุกจิกนิดหน่อย (YAML ฯลฯ ก็คล้ายกัน) ซึ่งเราแก้ปัญหานี้ด้วย Spacelift
    • จริง ๆ แล้วการจัดการสถานะของระบบซ้ำสองทั้ง k8s state และ Terraform state นั้นไม่มีประสิทธิภาพ ถ้า resource ถูกเปลี่ยนโดย mutating webhook ฯลฯ ก็ต้องตั้งค่า “computed fields” เพิ่มด้วย เพราะงั้นผมจึงหลีกเลี่ยงการจัดการระดับแอปพลิเคชันด้วย Terraform แต่สำหรับตัวคลัสเตอร์เอง ผมคิดว่าจัดการด้วย Terraform ก็โอเค
  • ในฐานะคนสายฟรอนต์เอนด์ ผมกลับรู้สึกว่า Kubernetes เข้าใจง่ายมาก เดิมทีผมเคยเขียนโค้ดเพื่อรับข้อมูลเข้าแล้วสร้าง UI แบบ reactive ตอนนี้ก็เหมือนกำลังเขียนโค้ดเพื่อปรับ resource และ config ให้ตรงกับ control plane