สวัสดีค่าา EP.7 กันแล้ว!

EP นี้เราจะมาเรียนเรื่องที่หลายคนกลัวที่สุดในวงการ DevOps นั่นคือ Kubernetes หรือที่นิยมเรียกสั้นๆว่า K8s (K + 8 ตัวอักษร + s ฉลาดมากเลยนะคนตั้งชื่อ 5555)

ขอบอกก่อนเลยว่า K8s ซับซ้อนจริง ไม่ได้ง่ายอย่าง Docker เลย แต่ถ้าเข้าใจ concept แล้ว ทุกอย่างจะ click เองค่ะ


ทำไมต้องมี Kubernetes

จาก EP.5 เราเรียนรู้ว่า Docker ช่วยให้รัน container ได้ง่ายมาก แต่สมมติว่าแอปเราโตขึ้น มี traffic เยอะขึ้น และต้องรัน container หลายสิบหรือหลายร้อยตัวพร้อมกัน คำถามคือ

  • จะรู้ได้ยังไงว่า container ไหนพัง และต้อง restart ตัวไหน?
  • ถ้า traffic เพิ่มขึ้น 10 เท่ากะทันหัน จะ scale ยังไง?
  • ถ้า server เครื่องนึงล่ม container บน server นั้นจะย้ายไปอีกเครื่องได้ไหม?
  • จะ distribute container ไปยัง server หลายเครื่องยังไงให้ใช้ resource ได้คุ้มค่า?

ทำมือไม่ไหวแน่นอน นั่นแหละเหตุผลที่ Kubernetes มีอยู่ค่ะ

Kubernetes เหมือนโค้ชยิมที่ดูแล athlete หลายร้อยคนพร้อมกัน รู้ว่าใครต้องพักฟื้น ใครต้องเพิ่ม load ใครพังแล้วต้อง replace และจัดสรร equipment ให้ทุกคนได้ใช้อย่างเหมาะสม ทำทั้งหมดนี้โดยอัตโนมัติตลอด 24 ชั่วโมง


Architecture ของ K8s

Kubernetes Cluster Control Plane (สมองของ cluster) ├── API Server ← ทุก request ผ่านที่นี่ ├── Scheduler ← ตัดสินใจว่า Pod จะไปอยู่ Node ไหน ├── etcd ← เก็บ state ทั้งหมดของ cluster └── Controller ← ดูแลให้ทุกอย่าง match กับที่กำหนด Worker Nodes (ที่ container รันอยู่จริง) ├── Node 1 │ ├── Pod A (container 1, container 2) │ └── Pod B (container 3) ├── Node 2 │ ├── Pod C │ └── Pod D └── Node 3 └── Pod E

Building Blocks หลักของ K8s

Pod

Pod คือหน่วยที่เล็กที่สุดใน K8s หนึ่ง Pod มีหนึ่ง container หรือมากกว่าที่ต้องทำงานด้วยกัน Pod มี IP address ของตัวเองและแชร์ storage กันภายใน

Deployment

Deployment คือการบอก K8s ว่าต้องการรัน Pod กี่ตัว ด้วย image อะไร ถ้า Pod ตายไป Deployment จะสร้าง Pod ใหม่ขึ้นมาแทนอัตโนมัติ

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3          # รัน 3 copies พร้อมกัน
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: chawadesu/my-app:1.0
        ports:
        - containerPort: 8000
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"

Service

Pod เกิดและตายตลอด IP เปลี่ยนทุกครั้งที่ Pod ใหม่ขึ้นมา Service คือ stable endpoint ที่ไม่เปลี่ยน ชี้ไปหา Pod ที่ match label ที่กำหนดให้อัตโนมัติ

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app       # ชี้ไปหา Pod ที่มี label app=my-app
  ports:
  - port: 80
    targetPort: 8000
  type: LoadBalancer   # expose ออก internet

Namespace

Namespace คือการแบ่ง cluster ออกเป็นส่วนๆ เหมือนมีห้องแยกกันใน cluster เดียว นิยมใช้แยก environment dev, staging, prod บน cluster เดียวกัน

kubectl get pods -n production    # ดู pods ใน namespace production
kubectl get pods -n staging

kubectl คำสั่งที่ใช้บ่อยที่สุด

# apply config ไฟล์ (สร้างหรืออัปเดต resource)
kubectl apply -f deployment.yaml
kubectl apply -f ./k8s/    # apply ทุกไฟล์ใน folder

# ดู resources
kubectl get pods
kubectl get deployments
kubectl get services
kubectl get all    # ดูทุกอย่าง

# ดู detail
kubectl describe pod my-app-xxx

# ดู logs
kubectl logs my-app-xxx
kubectl logs -f my-app-xxx    # follow

# เข้าไปใน pod
kubectl exec -it my-app-xxx -- bash

# ลบ resource
kubectl delete -f deployment.yaml

Auto-scaling

K8s scale ได้สองแบบ

Horizontal Pod Autoscaler (HPA)

เพิ่ม/ลดจำนวน Pod ตาม CPU หรือ memory usage

# scale อัตโนมัติ 2-10 pods ตาม CPU usage
kubectl autoscale deployment my-app \
  --min=2 --max=10 --cpu-percent=70

เปรียบเหมือนยิมที่เปิด lane เพิ่มช่วง peak hour แล้วลดช่วงเงียบๆ แทนที่จะมี lane ว่างๆตลอด 24 ชั่วโมงให้เปลืองค่าเช่า

Vertical Pod Autoscaler (VPA)

เพิ่ม/ลด resource (CPU/memory) ของแต่ละ Pod แทนที่จะเพิ่มจำนวน Pod


Self-healing

หนึ่งใน feature ที่ powerful ที่สุดของ K8s คือ self-healing ถ้า Pod crash K8s restart ให้เลย ถ้า Node ล่ม K8s ย้าย Pod ไป Node อื่น ถ้า health check ไม่ผ่าน K8s หยุดส่ง traffic ไปหา Pod นั้น

# กำหนด health check ใน deployment
livenessProbe:       # ถ้า fail K8s restart pod
  httpGet:
    path: /health
    port: 8000
  initialDelaySeconds: 30
  periodSeconds: 10

readinessProbe:      # ถ้า fail K8s หยุดส่ง traffic มา
  httpGet:
    path: /ready
    port: 8000
  initialDelaySeconds: 5
  periodSeconds: 5

Managed K8s ไม่ต้องดูแล Control Plane เอง

การ setup K8s เองมันซับซ้อนมาก Cloud providers เลยมี managed K8s service ที่ดูแล control plane ให้ เราดูแลแค่ workload

  • Amazon EKS (Elastic Kubernetes Service) บน AWS
  • Google GKE (Google Kubernetes Engine) บน GCP
  • Azure AKS (Azure Kubernetes Service)

💡 สำหรับมือใหม่ แนะนำให้ลอง minikube หรือ kind ก่อนค่ะ เป็น K8s แบบรัน local บนเครื่องตัวเอง ลองเล่นได้ฟรีโดยไม่ต้องเสียค่า cloud


สรุป EP.7

  • K8s คือ orchestration tool จัดการ container จำนวนมากอัตโนมัติ
  • Building blocks หลัก: Pod, Deployment, Service, Namespace
  • Auto-scaling เพิ่ม/ลด Pod ตาม load อัตโนมัติ
  • Self-healing restart หรือย้าย Pod เมื่อมีปัญหาอัตโนมัติ
  • ใช้ managed K8s (EKS, GKE, AKS) บน cloud แทนการ setup เองจะง่ายกว่ามาก

K8s เป็น topic ที่ลึกมาก EP นี้แค่ขีดเส้นใต้ concept สำคัญไว้ก่อน ในการทำงานจริงจะได้เรียนรู้ลึกขึ้นเรื่อยๆตามความต้องการของงานค่ะ