ทำความเข้าใจ Pod, Deployment, Service และ Ingress ใน Kubernetes

บทนำ: Kubernetes Workloads Overview

Kubernetes เป็นระบบจัดการคอนเทนเนอร์ที่ทรงพลัง และการเข้าใจ Workload Resources พื้นฐาน เป็นขั้นตอนสำคัญในการเรียนรู้ Kubernetes ทั้งหมด บทความนี้จะอธิบายส่วนประกอบหลักสี่ส่วน คือ Pod, Deployment, Service และ Ingress ซึ่งเป็นรากฐานของการทำงานบน Kubernetes

เมื่อคุณเข้าใจแนวคิดเหล่านี้แล้ว คุณจะสามารถ Deploy แอปพลิเคชันไปยัง Cloud VPS ของ ผู้ให้บริการโฮสติ้ง ได้อย่างมีประสิทธิภาพ

Pod คืออะไร

ลักษณะและคุณสมบัติของ Pod

Pod เป็นหน่วยที่เล็กที่สุด (smallest deployable unit) ใน Kubernetes โดยปกติ Pod จะมีคอนเทนเนอร์หนึ่งตัว แต่สามารถมีหลายตัวได้หากจำเป็น Pod จะสร้างหรือลบขึ้นมาใหม่อย่างรวดเร็ว และจะไม่ถูกสร้างโดยตรง แต่จะสร้างผ่าน Deployment หรือ StatefulSet

ลักษณะเฉพาะของ Pod:

  • ระบบเครือข่ายแบบแชร์ (Shared networking) – คอนเทนเนอร์ทั้งหมดในอพอด แชร์ IP address เดียวกัน
  • Storage ร่วมกัน (Shared storage) – สามารถแชร์ Volume ระหว่างคอนเทนเนอร์ได้
  • Ephemeral (ชั่วแล้วชั่นคน) – Pod จะหายไปเมื่อถูกลบออกจาก Cluster
  • Smallest unit – ไม่สามารถจัดการคอนเทนเนอร์แต่ละตัวได้ ต้องจัดการในระดับ Pod

YAML ตัวอย่าง Pod แบบง่าย

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: default
spec:
  containers:
  - name: nginx
    image: nginx:1.21
    ports:
    - containerPort: 80
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

คำสั่ง kubectl พื้นฐานสำหรับ Pod

# สร้าง Pod
kubectl apply -f pod.yaml

# ดูรายชื่อ Pod
kubectl get pods

# ดูรายละเอียดของ Pod
kubectl describe pod nginx-pod

# ดูลอก (logs) ของ Pod
kubectl logs nginx-pod

# ลบ Pod
kubectl delete pod nginx-pod

Deployment คืออะไร

ReplicaSet และ Desired State

Deployment เป็น Workload Resource ที่ใช้สำหรับการจัดการ Pod หลายตัวพร้อมๆ กัน และการอัปเดต Pod เวอร์ชั่นใหม่ Deployment ใช้ ReplicaSet เพื่อควบคุมจำนวน Pod ที่ต้องการให้ทำงาน (Desired State)

Deployment มีข้อดีดังนี้:

  • Replication – จัดการให้มี Pod จำนวนที่ต้องการเสมอ
  • Rolling Update – อัปเดตเวอร์ชั่นใหม่โดยไม่ขัดจังหวะ
  • Rollback – สามารถย้อนกลับไปเวอร์ชั่นก่อนหน้าได้
  • Automatic Recovery – สร้าง Pod ใหม่เมื่อ Pod เดิมหยุดทำงาน

YAML ตัวอย่าง Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.21
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5

Rolling Update และการจัดการเวอร์ชั่น

Rolling Update เป็นการอัปเดตที่ปลอดภัย ซึ่ง Kubernetes จะ:

  1. สร้าง Pod ใหม่เวอร์ชั่นล่าสุด (maxSurge: 1 หมายถึงสร้างเพิ่ม 1 Pod)
  2. ลบ Pod เก่า (maxUnavailable: 1 หมายถึงลบได้ 1 Pod)
  3. ทำซ้ำจนกว่า Pod ทั้งหมดจะเป็นเวอร์ชั่นใหม่
# อัปเดต image ของ Deployment
kubectl set image deployment/web-app web=nginx:1.22

# ตรวจสอบสถานะ rollout
kubectl rollout status deployment/web-app

# ดูประวัติ rollout
kubectl rollout history deployment/web-app

# ย้อนกลับไปเวอร์ชั่นก่อนหน้า
kubectl rollout undo deployment/web-app

# Scale จำนวน Pod
kubectl scale deployment web-app --replicas=5

Service คืออะไร

เหตุใดจึงต้องการ Service

Pod มีลักษณะ Ephemeral (ชั่วแล้วชั่นคน) เมื่อ Pod ถูกลบออก IP address ของ Pod จะหายไป ดังนั้นเราต้อง Service เพื่อให้การเข้าถึง Pod มีความเสถียร Service จะให้ DNS name และ IP address ที่ไม่เปลี่ยนแปลง (stable) แม้ว่า Pod ข้างในจะเปลี่ยนไปเรื่อยๆ

ประเภท Service หลัก 3 ประเภท

1. ClusterIP (ค่าเริ่มต้น) – Expose Service ภายใน Cluster เท่านั้น ใช้สำหรับการติดต่อระหว่าง Pod ภายใน Cluster

apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: web

2. NodePort – Expose Service จากภายนอก Cluster ผ่านพอร์ตเฉพาะบน Node

apiVersion: v1
kind: Service
metadata:
  name: web-nodeport
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: web

3. LoadBalancer – ใช้เมื่อ Kubernetes ทำงานบน Cloud Provider (เช่น AWS, GCP) เพื่อสร้าง Load Balancer ภายนอก

apiVersion: v1
kind: Service
metadata:
  name: web-lb
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: web

คำสั่ง Service ที่สำคัญ

# สร้าง Service
kubectl apply -f service.yaml

# ดูรายชื่อ Service
kubectl get svc

# ดูรายละเอียดของ Service
kubectl describe svc web-service

# ดู Endpoints (IP ของ Pod ที่เชื่อมต่ออยู่)
kubectl get endpoints web-service

Ingress คืออะไร

Ingress vs Service

Service ทำให้การเข้าถึง Pod เสถียร แต่ Ingress มีคุณสมบัติมากกว่า Ingress ช่วยในการ:

  • HTTP/HTTPS routing – กำหนดเส้นทาง URL ไปยัง Service ต่างๆ
  • TLS/SSL termination – จัดการ Certificate สำหรับ HTTPS
  • Name-based virtual hosting – ใช้ชื่อโดเมนต่างกันสำหรับ Service ต่างกัน
  • Path-based routing – กำหนดเส้นทาง URL Path ไปยัง Service ต่างๆ

YAML ตัวอย่าง Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

Ingress พร้อม HTTPS

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    secretName: example-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

ความสัมพันธ์ระหว่าง Pod, Deployment, Service, และ Ingress

มาดูความสัมพันธ์ระหว่าง 4 คอมโพเนนต์นี้:

┌─────────────────────────────────────────────┐
│          Internet / User Browser            │
└─────────────────────────────────────────────┘
                      ↓
        ┌─────────────────────────┐
        │  Ingress (HTTP Router)  │
        │ example.com → Service   │
        └─────────────────────────┘
                      ↓
        ┌─────────────────────────┐
        │ Service (Network Layer) │
        │ Stable IP & DNS name    │
        └─────────────────────────┘
                      ↓
        ┌─────────────────────────┐
        │  Deployment             │
        │  (Manages Pods)         │
        │  Replicas: 3            │
        └─────────────────────────┘
                      ↓
  ┌─────────────┬─────────────┬─────────────┐
  │   Pod 1     │   Pod 2     │   Pod 3     │
  │ nginx:1.21  │ nginx:1.21  │ nginx:1.21  │
  └─────────────┴─────────────┴─────────────┘

ลำดับการทำงาน:

  1. ผู้ใช้เข้าถึง example.com
  2. Ingress routing traffic ไปยัง web-service
  3. Service ไปหา Pod ที่มี label app: web
  4. Traffic ถูกส่งไปยัง Pod ใดๆ ของทั้ง 3 Pod (round-robin)

Workshop: Deploy Web Application จาก A ถึง Z

ขั้นตอนที่ 1: สร้าง Deployment

cat << 'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
  labels:
    app: demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: app
        image: nginx:latest
        ports:
        - containerPort: 80
EOF

ขั้นตอนที่ 2: สร้าง Service

cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: demo-service
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: demo
EOF

ขั้นตอนที่ 3: สร้าง Ingress

cat << 'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-service
            port:
              number: 80
EOF

ขั้นตอนที่ 4: ตรวจสอบการปรับใช้

# ตรวจสอบ Deployment
kubectl get deployment demo-app
kubectl describe deployment demo-app

# ตรวจสอบ Pod
kubectl get pods -l app=demo

# ตรวจสอบ Service
kubectl get svc demo-service
kubectl get endpoints demo-service

# ตรวจสอบ Ingress
kubectl get ingress demo-ingress
kubectl describe ingress demo-ingress

เมื่อทำการ Deploy บน Cloud VPS ของ ผู้ให้บริการโฮสติ้ง ที่รองรับ Kubernetes ระบบจะอนุญาตให้คุณเข้าถึงแอปพลิเคชันผ่าน URL myapp.example.com ได้อย่างมั่นคง

สรุป

ในบทความนี้ เราได้เรียนรู้เกี่ยวกับ 4 คอมโพเนนต์หลักใน Kubernetes:

  • Pod - หน่วยที่เล็กที่สุดใน Kubernetes สำหรับรันคอนเทนเนอร์
  • Deployment - จัดการ Pod หลายตัวพร้อมๆ กัน และสนับสนุน Rolling Update
  • Service - ให้ IP address และ DNS name ที่เสถียรสำหรับการเข้าถึง Pod
  • Ingress - HTTP/HTTPS routing และ TLS termination สำหรับการเข้าถึงจากภายนอก

การเข้าใจคอมโพเนนต์เหล่านี้จะช่วยให้คุณสามารถ Deploy แอปพลิเคชันบน Kubernetes ได้อย่างมีประสิทธิภาพ ทั้งสำหรับการทดสอบและการใช้งานจริง ลองใช้บริการ Cloud VPS ของ ผู้ให้บริการโฮสติ้ง ที่รองรับ Kubernetes เพื่อเริ่มต้นการทำงานกับแพลตฟอร์มนี้อย่างมีประสิทธิภาพ