การใช้งาน Kubernetes ที่ดี (Best Practices)

ตอนที่ ๕ การใช้งาน Kubernetes ที่ดี (Best Practices)

บทความนี้ต่อเนื่องมาจาก

 

ผมรวบรวม Best Practices ต่างๆจาก YouTube Playlist นี้ จาก articles ต่างๆที่เคยอ่านมา และจากปัญหาที่ผมเจอกับตัวเองมา หลายๆเรื่องผมอาจจะยกมาอธิบายโดยละเอียดในบทความต่อๆไป โดยเฉพาะเรื่องที่ซับซ้อนและสำคัญมากๆ


Best Practices ในการสร้าง Docker Image

  • พยายามสร้าง Image ให้เล็กที่สุดที่เป็นไปได้โดยไม่ Copy ไฟล์ที่ไม่จำเป็น ลบไฟล์ที่ใช้เฉพาะตอนสร้าง Image (เช่น rpm/dpkg ไฟล์ หรือ source code)
  • ห้าม!! ใส่ Credential ไปใน Image
  • Image ควรจะ compile จนพร้อมรันได้ทันที (เช่น yarn build)
  • Image เดียวกันควรจะสามารถรันใน Environment ไหนก็ได้ (Dev, UAT, Production) โดยไม่ต้องสร้างใหม่
  • ขณะสร้าง Dockerfile ควรจะอยู่ใน Directory ที่เก็บไฟล์ที่จะ Copy เข้าไปใน Image เท่านั้น
  • Image ควรจะ handle SIGTERM และปิดตัวเอง (Graceful)

Best Practices สำหรับการรัน Workload

  • อย่ารัน Pod ตรงๆ (Naked Pod) แต่รันผ่าน Deployments, StatefulSet หรือ Jobs
  • ใช้ Service เพื่อสร้าง Endpoint สำหรับติดต่อทั้งระหว่าง Pods ภายใน Cluster, จากภายนอกเข้ามาใน Pods, และสร้างจุดเชื่อมต่อเสมือนสำหรับจุดเชื่อมต่อที่อยู่นอก Cluster (เช่น Database)
  • สำหรับ Service ประเภท NodePort อย่ากำหนด HostPort โดยไม่จำเป็นเพื่อเลี่ยงปัญหา Port ชนกัน
  • ใช้ Labels เพิ่มความสะดวกในการจัดการ เช่น สามารถกำหนด label เพื่อเลือก Pod กับ kubectl
  • ใช้ Image Tag และเลือกใช้ imagePullPolicy ที่เหมาะสม เช่น ถ้าเป็น latest ควรจะใช้ “imagePullPolicy: Always” แต่ถ้าเป็น Tag ที่เฉพาะเจาะจง อาจจะใช้ “imagePullPolicy: IfNotPresent”
  • แยกกลุ่มของงานออกมาเป็น Namespace เฉพาะๆ
  • ใช้ Liveness เพื่อเช็คว่า Pod ยังพร้อมทำงานอยู่หรือเปล่าและ Readiness เพื่อเช็คว่า Pod พร้อมทำงานหรือยัง
  • ใช้ Sidecar หรือ Init Containers เพื่อช่วยจัดการ Container หลักแทนการรวมงานทุกๆอย่างไว้ใน Container เดียว
  • ถ้า Container ใช้เวลานานในการปิดตัวเอง สามารถเพิ่มระยะเวลารอ เพื่อจะได้ไม่ต้องปิดแบบรุนแรง (SIGKILL)

Best Practices สำหรับการจัดการ Cluster

  • รัน Cluster ข้าม Availability Zones (ทั้ง Master และทุกๆ Worker Groups)
  • สำหรับ Cluster ขนาดเล็กและมีการใช้ Persistent Volume (PV) อาจจะรัน Zone เดียว (กรณีที่โอเคกับ Zone Failure Risk) หรือไม่ควรจะหลาย Zone เกิน เพราะ PV มักจะเป็น Zonal Resource (ไม่สามารถรันข้าม Zone ได้) ถ้าไม่มีเครื่องว่างใน Zone เดียวกับ PV จะไม่สามารถ schedule Pod ได้ ดังนั้นถ้าจะเพิ่มเครื่อง ควรเพิ่มในทุกๆ Zone ถ้ามีจำนวน Zone มาก เวลาจะเพิ่มก็จะต้องเพิ่มที่ละมากๆ ซึ่งก็จะมีค่าใช้จ่ายมาก
  • สำหรับ Cluster ที่มีหลายเครื่อง อาจจะมีการใช้เครื่องหลายๆ ประเภท เช่น เครื่องที่เน้น CPU เครื่องที่เน้น Memory เครื่องที่มี GPU และเพื่อให้ง่ายในการจัดการ อาจจะทำ Node Group (บางทีก็เรียกว่า Instance Group) สำหรับเครื่องแต่ละประเภท
  • อย่าใช้เครื่องเล็กเกิน เพราะในแต่ละเครื่องจะต้องรัน Process ที่จำเป็นสำหรับต่อ Kubernetes และ DaemonSet Pods ซึ่งถ้าเครื่องเล็กเกินจะมี Overhead มากเกินพอดี
  • ตั้ง Label แต่ละเครื่องเพื่อประโยชน์ในการจัดการตอนหลัง (เช่น เป็นเครื่องที่จะรันตลอดเวลา หรือเป็นเครื่องที่จะเปิดปิดตามโหลด หรือ Zone/Region ที่เครื่องรันอยู่)
  • ถ้าจะ Rolling Update เครื่อง ควรจะเปิดเครื่องเพิ่มเผื่อไว้ก่อนและค่อยๆ ย้าย Pods ออกจากเครื่องที่จะ Rolling Update
  • การย้าย Pods ออกจากเครื่องสามารถทำได้ด้วยการ Drain เครื่อง แต่ถ้าการ Drain จะทำให้มีการสร้าง Pods ที่เครื่องอื่นเร็วเกินจนเครื่องอื่น High CPU แนะนำให้ Cordon เครื่องและค่อยๆ Kill Pod

Best Practices ที่เกี่ยวกับความปลอดภัย (Security)

  • ถ้าไม่จำเป็น ควรจะใช้ Firewall กัน API ให้เข้าได้จาก Trusted Network เท่านั้น (เช่น จาก Intranet หรือ เจาะจง IP )
  • ตั้งค่า RBAC ตามหลักการพื้นฐานด้านความปลอดภัย ควรจะให้ Access น้อยที่สุดที่จำเป็น - The Principle of Least Privilege
  • ใช้ Secrets เพื่อเก็บ Credential แทนการใช้ ConfigMap หรือฝังข้อมูลไว้ใน Image หรือ Persistent Storage
  • ใช้ Network Policy เพื่อกันการตัดต่อที่ไม่จำเป็นระหว่าง Pod หรืออาจจะตั้ง Policy ในระดับ Namespace (NS) เพิ่มปกป้อง Workload ใน NS นั้นๆ
  • ใช้ Pod Security Policy เพื่อกันไม่ให้ Pod ทำบางอย่างที่มีความเสี่ยงและไม่จำเป็นได้ - ยังเป็น Beta อยู่
  • ปิด Features ที่ไม่ได้ใช้
  • เปิด Audit Logging
Tags

What do you think?

Related articles