แผนการเรียนรู้
/

สัปดาห์ที่ 11: Kubernetes Workload Management

เจาะลึกการจัดการแอปพลิเคชัน การอัปเดตแบบไม่มีดาวน์ไทม์ การสเกลอัตโนมัติ และการจัดการคอนฟิก

Agenda วันนี้

  • ReplicaSets: กลไกการรักษาสถานะและจำนวนของ Pods
  • Deployments: การจัดการอัปเดต (Rollout) และย้อนกลับ (Rollback)
  • Horizontal Pod Autoscaler (HPA): การสเกล Pod อัตโนมัติ
  • Ingress: การจัดการ Traffic ภายนอกเข้าสู่ Cluster แบบ L7
  • ConfigMaps & Secrets: การจัดการตั้งค่าและข้อมูลความลับ
DevOps Course: Week 11

ทบทวนสัปดาห์ที่ 10 (Recap)

ในสัปดาห์ที่แล้ว เราเรียนรู้พื้นฐานของ Kubernetes ไปแล้ว

Cluster

กลุ่มของเครื่อง Server (Master & Worker Nodes) ที่ทำงานร่วมกัน

Pod

หน่วยเล็กที่สุดใน K8s ห่อหุ้ม Container (มักจะมี 1 Container ต่อ 1 Pod)

Service

การแจก IP และ Load Balance ภายในให้ Pods เพื่อให้ติดต่อกันได้

YAML

ภาษาที่ใช้ประกาศ Desired State ให้ Kubernetes ไปทำให้เป็นจริง

Kubernetes Workloads คืออะไร?

Workload คือแอปพลิเคชันที่ทำงานอยู่บน Kubernetes

แม้ว่า "Pod" จะเป็นที่อยู่ของแอปพลิเคชัน แต่ในสภาพแวดล้อมจริง (Production) เราแทบจะไม่สร้าง Pod ขึ้นมาตรงๆ ด้วยตัวเองเลย เพราะถ้า Pod ตาย มันจะตายถาวร

K8s มี Workload Resources เพื่อจัดการเรื่องเหล่านี้:

  • ReplicaSet / Deployment (สำหรับแอปฯ ที่ไม่มีสถานะ - Stateless)
  • StatefulSet (สำหรับแอปฯ ที่มีสถานะ เช่น Database)
  • DaemonSet (สำหรับรัน Agent ทุกๆ เครื่อง Node)
  • Job / CronJob (สำหรับงานที่รันแล้วจบไป)

1. ReplicaSet 🛡️

เป้าหมายหลักของ ReplicaSet (RS) คือการรักษาสถานะและจำนวนของ Pods ให้ตรงกับที่กำหนดไว้ (Desired State) อยู่ตลอดเวลา

  • รับประกันว่าจะมีจำนวน Pod ตามที่ระบุทำงานอยู่เสมอ
  • ถ้า Pod ล่มหรือถูกลบ ReplicaSet จะสร้าง Pod ใหม่ขึ้นมาทดแทนทันที (Self-Healing)
  • ถ้ามี Pod เกินมา (เช่นเกิดจาก Network Partition) ReplicaSet จะลบ Pod ที่เกินทิ้ง

ReplicaSet ทำงานอย่างไร? (Labels & Selectors)

ReplicaSet ไม่ได้ "ผูกติด" กับ Pod ตั้งแต่เกิด แต่มันใช้ Labels ในการค้นหาและควบคุม

ReplicaSet

Selector: app=frontend

Replicas: 3

🔍
Pod A (Label: app=frontend)
Pod B (Label: app=frontend)
Pod C (Label: app=frontend)

*ถ้าเปลี่ยน Label ของ Pod A เป็น app=backend, ReplicaSet จะคิดว่า Pod หายไป 1 ตัว และจะสร้าง Pod ใหม่ขึ้นมาแทนทันที!

ตัวอย่าง YAML ของ ReplicaSet

apiVersion: apps/v1

kind: ReplicaSet

metadata:

  name: frontend-rs

spec:

  replicas: 3 # ระบุจำนวน Pod ที่ต้องการ (Desired State)

  selector:

    matchLabels:

      app: frontend # เงื่อนไขการค้นหา Pod

  template: # แม่พิมพ์สำหรับสร้าง Pod ใหม่

    metadata:

      labels:

        app: frontend

    spec:

      containers:

      - name: web

        image: nginx:1.14

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

ปัญหาเวลาอัปเดตแอปพลิเคชัน

หากคุณต้องการเปลี่ยนเวอร์ชันของ Image (เช่น จาก nginx:1.14 เป็น nginx:1.15) ใน ReplicaSet คุณต้องเข้าไปแก้ไฟล์ YAML

แต่ ReplicaSet จะไม่ทำการลบ Pod เก่าและสร้างใหม่ให้! คุณต้องไปลบ Pod เก่าด้วยมือเอง เพื่อให้มันสร้าง Pod ใหม่ด้วย Image ล่าสุด

Downtime & Manual Work

2. Deployments 🚀

Deployment คือ Workload Resource ระดับสูงที่สร้างมาครอบทับ ReplicaSet อีกที เพื่อแก้ปัญหาการอัปเดตแอปพลิเคชัน

  • รองรับการทำ Rolling Updates (เปลี่ยนเวอร์ชันแบบไม่มีดาวน์ไทม์)
  • สามารถทำ Rollback ย้อนกลับไปใช้เวอร์ชันก่อนหน้าได้ทันทีหากเกิดข้อผิดพลาด
  • สามารถ Pause และ Resume ระหว่างการอัปเดตได้
  • นี่คือ Resource ที่ถูกใช้งานมากที่สุดในการรันแอปพลิเคชันแบบ Stateless

ความสัมพันธ์ (The Hierarchy)

Deployment ไม่ได้ควบคุม Pod โดยตรง แต่มันไปควบคุม ReplicaSet แทน

Deployment

ควบคุมเวอร์ชันและการอัปเดต

⬇️

ReplicaSet

ควบคุมจำนวน Pod ให้ครบ

⬇️

Pod

Pod

Pod

Deployment Strategies (กลยุทธ์การอัปเดต)

1. Recreate

ทำลาย Pod เวอร์ชั่นเก่าทั้งหมดทิ้งก่อน แล้วค่อยสร้าง Pod เวอร์ชั่นใหม่ขึ้นมา

  • ข้อดี: แน่ใจว่าไม่มี 2 เวอร์ชั่นรันพร้อมกัน (เหมาะกับระบบที่ใช้ Database ห้ามชนกัน)
  • ข้อเสีย: เกิด Downtime 100% ระหว่างรอ Pod ใหม่พร้อมทำงาน

2. RollingUpdate (Default)

ทยอยสร้าง Pod ใหม่ทีละตัว และทยอยลบ Pod เก่าทีละตัว สลับกันไปจนครบ

  • ข้อดี: Zero Downtime ระบบทำงานต่อเนื่อง
  • ข้อเสีย: จะมีบางช่วงเวลาที่แอป 2 เวอร์ชั่นให้บริการพร้อมกัน (Code ต้องรองรับ Backward Compatibility)

กลไกการทำงานของ Rolling Update

V1 ReplicaSet (เก่า)

V1 V1 V1
เริ่มต้น

V2 ReplicaSet (ใหม่)

V1 V1
กำลังอัปเดต...
V2 V2
เสร็จสมบูรณ์
V2 V2 V2

การจัดการ Rollout

Kubectl มีคำสั่งสำหรับตรวจสอบและจัดการสถานะการอัปเดต (Rollout) ของ Deployment

ดูสถานะการอัปเดตว่าเสร็จหรือยัง

$ kubectl rollout status deployment/myapp

ดูประวัติการอัปเดต (Revision History)

$ kubectl rollout history deployment/myapp

REVISION CHANGE-CAUSE

1 Initial commit

2 Update image to v2

Rollback (การย้อนกลับ) ⏪

หากอัปเดตไปแล้วแอปพลิเคชันมีปัญหา (เช่น ติด CrashLoopBackOff หรือ Error 500) เราสามารถสั่งถอยหลังกลับไปยังเวอร์ชันก่อนหน้าได้อย่างรวดเร็ว

# ย้อนกลับไปยังเวอร์ชันก่อนหน้าทันที (Revision ล่าสุด)

$ kubectl rollout undo deployment/myapp


# หรือย้อนกลับไปยัง Revision ที่ระบุเจาะจง

$ kubectl rollout undo deployment/myapp --to-revision=1

*Deployment เก็บ ReplicaSet เวอร์ชั่นเก่าไว้ (ปกติ 10 อัน) โดยตั้ง Replicas=0 ทำให้สามารถสลับกลับไปได้ทันที

ตัวอย่าง YAML ของ Deployment

apiVersion: apps/v1

kind: Deployment

metadata:

  name: myapp-deployment

spec:

  replicas: 3

  strategy: # กำหนดกลยุทธ์การ Rollout

    type: RollingUpdate

    rollingUpdate:

      maxSurge: 1 # ยอมให้มี Pod เกินตอนอัปเดตได้ 1 ตัว

      maxUnavailable: 0 # ห้ามมี Pod ขาดเลย (ต้องรับทราฟฟิกได้เต็ม 100%)

  selector:

    matchLabels:

      app: web

  ... (template ของ Pod) ...

3. Horizontal Pod Autoscaler (HPA) 📈

เมื่อมีผู้ใช้งานเพิ่มขึ้นอย่างมหาศาล จำนวน Pod (Replicas) ที่กำหนดไว้คงที่อาจจะไม่พอรับโหลด K8s จึงมี HPA มาช่วย

  • ทำหน้าที่สเกล (เพิ่ม/ลด) จำนวน Pod อัตโนมัติ (Scale Out / Scale In)
  • ทำงานร่วมกับ Deployment หรือ ReplicaSet
  • วัดผลจาก Metrics พื้นฐาน เช่น CPU utilization หรือ Memory usage
  • สามารถประยุกต์ใช้กับ Custom Metrics (เช่น จำนวนคิวใน Kafka หรือ Request per second)

HPA ทำงานอย่างไร?

🌍

High Traffic

➡️

CPU 85%

Pod 1
⬆️

Metrics Server

(เก็บค่า CPU/Mem)

➡️

HPA

Target CPU: 50%

  1. Metrics Server ตรวจจับได้ว่า CPU ของ Pod 1 พุ่งไป 85%
  2. HPA ซึ่งตั้งเป้าไว้ว่า CPU เฉลี่ยควรอยู่ที่ 50% เห็นว่าโหลดเกิน
  3. HPA สั่งเพิ่มจำนวน Replicas ใน Deployment จาก 1 ตัวเป็น 2 ตัว เพื่อหารเฉลี่ยโหลด

*คำเตือน: HPA จะทำงานได้ Pod ต้องมีการกำหนด resources.requests.cpu ไว้ใน YAML ด้วย

การเปิดใช้งาน HPA

# สร้างผ่าน Command Line (Imperative)

$ kubectl autoscale deployment myapp \

  --cpu-percent=50 \

  --min=1 --max=10


# ตรวจสอบสถานะ

$ kubectl get hpa

NAME TARGETS MINPODS MAXPODS REPLICAS

myapp 85%/50% 1 10 1

# สร้างผ่าน YAML (Declarative)

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

  name: myapp-hpa

spec:

  scaleTargetRef:

    apiVersion: apps/v1

    kind: Deployment

    name: myapp

  minReplicas: 1

  maxReplicas: 10

  metrics:

  - type: Resource

    resource:

      name: cpu

      target:

        type: Utilization

        averageUtilization: 50

ปัญหาการรับ Traffic เข้า Cluster

ในสัปดาห์ก่อน เราใช้ Service ชนิด NodePort หรือ LoadBalancer ในการเปิดให้ภายนอกเข้าถึงแอปได้ แต่มีข้อจำกัด:

  • NodePort: ใช้พอร์ตแปลกๆ (30000-32767) ไม่เหมาะกับ Production
  • LoadBalancer: ผูกกับ Cloud Provider 1 Service = 1 Cloud LoadBalancer ซึ่งแพงมาก! ถ้าเรามี 10 Microservices เราต้องเสียเงินซื้อ Load Balancer 10 ตัว
  • มันทำงานที่ Layer 4 (TCP/UDP) ทำให้ไม่สามารถแยกแยะ Domain Name หรือ URL Path (เช่น /api, /web) ได้

4. Ingress 🌐

Ingress คือการจัดการ Traffic ภายนอกเข้าสู่ Cluster ในระดับ Layer 7 (HTTP/HTTPS)

  • เราใช้ Cloud Load Balancer หรือ IP สาธารณะเพียง 1 ตัว ชี้เข้ามาที่ Ingress
  • จากนั้น Ingress จะเป็นด่านหน้า (Smart Router) คอยแจกจ่ายทราฟฟิกไปหา Service ย่อยๆ ภายใน
  • สามารถทำ Name-based virtual hosting (แยกตาม Domain Name เช่น app.com, api.com)
  • สามารถทำ Path-based routing (แยกตาม URL เช่น /frontend, /backend)
  • จัดการ SSL/TLS Termination ให้อัตโนมัติ (เช่น รวมกับ Let's Encrypt / Cert-manager)

Controller vs Resource

Ingress แบ่งออกเป็น 2 ส่วนที่ต้องทำงานร่วมกันเสมอ

1. Ingress Controller

เป็นโปรแกรมจริงๆ (มักจะรันเป็น Pod) ที่ทำหน้าที่เป็น Reverse Proxy

  • Kubernetes ไม่ได้มี Ingress Controller ติดตั้งมาให้โดย Default
  • คุณต้องเลือกติดตั้งเอง ตัวยอดนิยมเช่น: NGINX Ingress Controller, Traefik, HAProxy, Caddy หรือ AWS ALB

2. Ingress Resource (YAML)

เป็นไฟล์ Configuration ที่เราเขียนเพื่อบอก Controller ว่าจะสร้างกฎการ Routing อย่างไร

  • เมื่อเรา Apply ไฟล์นี้ Ingress Controller จะอ่านและอัปเดตไฟล์คอนฟิกของมันเอง (เช่น nginx.conf) ทันที

ตัวอย่าง YAML ของ Ingress (Path-based)

ingress.yaml

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

  name: minimal-ingress

spec:

  ingressClassName: nginx # ระบุว่าใช้ Controller ตัวไหน

  rules:

  - host: myapp.example.com # Domain-based

    http:

      paths:

      - path: /api # Path-based

        pathType: Prefix

        backend:

          service:

            name: backend-service # ส่งไปที่ Service ของ Backend

            port: { number: 8080 }

หลักการแยกคอนฟิกออกจากโค้ด

Anti-Pattern (สิ่งที่ห้ามทำ):

การใส่รหัสผ่าน Database, URL ของ API ปลายทาง, หรือค่าคอนฟิกฝังไว้ใน Source Code (Hardcode) หรือการแพ็กใส่ไว้ใน Docker Image ตรงๆ

เพราะหากต้องการเปลี่ยนค่าสำหรับ Environment อื่น (Dev -> Prod) คุณต้องทำการ Rebuild Docker Image ใหม่ทั้งหมด!

Best Practice (สิ่งที่ควรทำ):

Docker Image ตัวเดียว ควรสามารถนำไปรันได้ในทุก Environment โดยรับค่าตั้งค่าตัวแปรจากภายนอก ใน Kubernetes เราใช้ ConfigMap และ Secret ในการเก็บค่าเหล่านี้

5. ConfigMaps 📄

ConfigMap คือ Object ที่ใช้เก็บข้อมูลการตั้งค่าที่ไม่ใช่ความลับ (Non-confidential data) ในรูปแบบ Key-Value

Pod สามารถนำ ConfigMap ไปใช้งานได้ 2 รูปแบบหลักๆ:

  • Environment Variables: ฉีดค่าเข้าไปเป็นตัวแปรสภาพแวดล้อม (ENV) ให้กับ Container (ตัวอย่างเช่น APP_ENV=production)
  • Volume Mounts: นำข้อมูลไปสร้างเป็นไฟล์และ Mount เข้าไปใน Path ของ Container (เช่น นำไฟล์ nginx.conf หรือ settings.json ไปวาง)

ตัวอย่างการสร้างและใช้งาน ConfigMap

# 1. ไฟล์ cm.yaml

apiVersion: v1

kind: ConfigMap

metadata:

  name: app-config

data:

  LOG_LEVEL: "info"

  DB_HOST: "mysql-service.default.svc"

# 2. การเรียกใช้ใน Deployment YAML

...

containers:

- name: myapp

  env:

  - name: DATABASE_HOST # ชื่อ ENV ใน Container

    valueFrom:

      configMapKeyRef:

        name: app-config

        key: DB_HOST

6. Secrets 🤫

Secret ทำงานคล้ายกับ ConfigMap แต่ถูกออกแบบมาเพื่อเก็บข้อมูลที่มีความอ่อนไหว (Sensitive data) เช่น รหัสผ่าน, OAuth Tokens หรือ SSH Keys

  • ข้อมูลใน Secret จะถูกจัดเก็บด้วยการเข้ารหัสแบบ Base64 (ไม่ใช่ Encryption ที่แข็งแกร่ง เป็นแค่ Encoding ต้องระวังเวลาเอาขึ้น Git!)
  • หลีกเลี่ยงการเก็บรหัสผ่านไว้ใน Image หรือ Pod YAML ป้องกันไม่ให้คนอื่นมาเห็นง่ายๆ
  • ใน Production สามารถเชื่อมต่อ K8s Secret กับระบบจัดการความลับภายนอกได้ (เช่น HashiCorp Vault หรือ AWS Secrets Manager)

ตัวอย่างการสร้างและใช้งาน Secret

# การสร้าง Base64 ใน Linux/Mac

$ echo -n 'myPassword123' | base64

bXlQYXNzd29yZDEyMw==


# 1. ไฟล์ secret.yaml

apiVersion: v1

kind: Secret

metadata:

  name: db-credentials

type: Opaque

data:

  password: bXlQYXNzd29yZDEyMw==

# 2. การเรียกใช้ใน Deployment YAML

...

containers:

- name: myapp

  env:

  - name: DB_PASS

    valueFrom:

      secretKeyRef:

        name: db-credentials

        key: password

สรุปบทเรียน (Recap)

ReplicaSet: คอยเฝ้าดูและรักษาสถานะจำนวน Pod ให้เท่ากับค่าที่ต้องการเสมอ
Deployment: ตัวช่วยที่ดีที่สุดในการจัดการแอปพลิเคชัน รองรับการทำ Rolling Update และ Rollback อัตโนมัติ
HPA: ตรวจสอบ Metrics (CPU/Memory) และเพิ่มหรือลดจำนวน Pod ให้อัตโนมัติตามโหลดที่เข้ามา
Ingress: ด่านหน้าระดับ Layer 7 ที่ใช้รับ Traffic ภายนอกและกระจายเข้า Service ด้วยโดเมนและพาร์ท (Path)
ConfigMap & Secret: เครื่องมือแยก Configuration และรหัสผ่านออกจาก Source Code เพื่อทำ Immutable Image

เตรียมตัวทำ Lab! 🛠️

Next: Kubernetes Workloads in Action

ในส่วนของปฏิบัติการ เราจะนำทฤษฎีทั้งหมดมาประยุกต์ใช้งานจริง โดยการนำ Web Application ขึ้นบน Cluster ของคุณ

  • ✅ สร้าง Deployment แทนที่การรัน Pod แบบตรงๆ และทดลองสั่ง Rolling Update / Rollback
  • ✅ สร้าง ConfigMap และ Secret เพื่อเก็บค่าคอนฟิกและจำลองการเก็บรหัสผ่าน นำไปใส่เป็น ENV ให้แอป
  • ✅ เปิดใช้งาน NGINX Ingress Controller บน Minikube/K3s
  • ✅ สร้าง Ingress Resource เพื่อเข้าถึง Web Application จากภายนอกผ่านการตั้งชื่อ Domain เสมือน
ทบทวนคำสั่ง kubectl apply และการเขียน YAML ให้พร้อม แล้วเจอกันในชั่วโมง Lab ครับ!

Lab: Advanced K8s Workloads 🚀

จัดการแอปพลิเคชันอย่างมืออาชีพด้วย Deployments, ConfigMaps และเผยแพร่สู่ภายนอกด้วย Ingress

🎯 เป้าหมายของ Lab

  • ✅ ใช้ ConfigMaps เพื่อจัดการ Environment Variables
  • ✅ สร้าง Deployment สำหรับ Web application (Nginx หรือ Image ของคุณ)
  • ✅ ทดลอง Scale Deployment เพื่อเพิ่ม/ลดจำนวน Pods
  • ✅ เปิดใช้งาน Ingress Controller บน Minikube
  • ✅ สร้าง Ingress เพื่อเชื่อมต่อ Domain เสมือนเข้าสู่ Web App

Step 1: สร้าง ConfigMap สำหรับ Env Vars

แทนที่จะ Hardcode ค่าต่างๆ ลงในโค้ด เราจะเก็บการตั้งค่าไว้ใน ConfigMap

# สร้างไฟล์ชื่อ web-configmap.yaml

$ nano web-configmap.yaml


apiVersion: v1

kind: ConfigMap

metadata:

  name: webapp-config

data:

  APP_ENV: "production"

  APP_VERSION: "1.0.0"

  GREETING_MSG: "Hello from Kubernetes ConfigMap!"

Step 2: เขียนไฟล์ Deployment YAML

เราจะสร้าง Deployment ที่ควบคุม 2 Pods และดึงค่าจาก ConfigMap มาใช้เป็น Environment Variables

# สร้างไฟล์ชื่อ web-deployment.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: my-webapp

spec:

  replicas: 2 # ต้องการ 2 Pods เสมอ

  selector:

    matchLabels:

      app: web

  template:

    metadata:

      labels:

        app: web

    spec:

      containers:

      - name: web-container

        image: nginx:latest # หรือใส่ Docker Image ที่คุณสร้างไว้

        ports:

        - containerPort: 80

        envFrom: # ดึงข้อมูลทั้งหมดจาก ConfigMap มาเป็น ENV

        - configMapRef:

            name: webapp-config

Step 3: Apply และตรวจสอบผลลัพธ์

ใช้ kubectl นำไฟล์ YAML ทั้งสองไปรันใน Cluster

$ kubectl apply -f web-configmap.yaml

configmap/webapp-config created


$ kubectl apply -f web-deployment.yaml

deployment.apps/my-webapp created


# ตรวจสอบ Deployment และ Pods

$ kubectl get deployments

NAME READY UP-TO-DATE AVAILABLE AGE

my-webapp 2/2 2 2 15s


$ kubectl get pods

NAME READY STATUS RESTARTS AGE

my-webapp-65c8f9b9c4-abc12 1/1 Running 0 18s

my-webapp-65c8f9b9c4-xyz89 1/1 Running 0 18s

Step 4: พิสูจน์การทำงานของ ConfigMap

เราจะมุดเข้าไปใน Pod ที่กำลังรันอยู่ เพื่อดูว่า Environment Variables ถูกส่งเข้าไปจริงหรือไม่

# ใช้คำสั่ง exec เข้าไปรันคำสั่ง 'env' ใน pod (เลือกชื่อ Pod ของคุณมา 1 อัน)

$ kubectl exec -it my-webapp-65c8f9b9c4-abc12 -- env | grep APP


# ผลลัพธ์ที่ควรจะเห็น:

APP_ENV=production

APP_VERSION=1.0.0


$ kubectl exec -it my-webapp-65c8f9b9c4-abc12 -- env | grep GREETING

GREETING_MSG=Hello from Kubernetes ConfigMap!

💡 ความเจ๋งคือ: ถ้าคุณแก้ ConfigMap และสั่ง Restart Pod ค่าตัวแปรเหล่านี้จะเปลี่ยนไปโดยที่คุณไม่ต้อง Rebuild Docker Image ใหม่เลย!

Step 5: ทดลอง Scale Deployment (Scaling)

หากมีผู้ใช้งานเว็บเพิ่มขึ้น เราสามารถเพิ่มจำนวน Pod ได้ง่ายๆ ภายในเสี้ยววินาที

# สั่งเพิ่ม Replica จาก 2 เป็น 5

$ kubectl scale deployment my-webapp --replicas=5

deployment.apps/my-webapp scaled


# รีบพิมพ์คำสั่งนี้เพื่อดู K8s ทำงานแบบ Real-time

$ kubectl get pods -w

NAME READY STATUS AGE

my-webapp-65c8f9b9c4-abc12 1/1 Running 5m

my-webapp-65c8f9b9c4-xyz89 1/1 Running 5m

my-webapp-65c8f9b9c4-kpl22 0/1 ContainerCreating 2s

my-webapp-65c8f9b9c4-mnq33 0/1 ContainerCreating 2s

my-webapp-65c8f9b9c4-rst44 0/1 ContainerCreating 2s

กด Ctrl+C เพื่อออกจากโหมด Watch (-w) เมื่อทุก Pod ขึ้นสถานะ Running

Step 6: สร้าง Service สำหรับรับ Traffic

ก่อนจะใช้ Ingress ได้ เราต้องมี Service ชนิด ClusterIP (IP ภายใน) เพื่อมัดรวม Pod ทั้ง 5 ตัวเข้าด้วยกันเป็นเป้าหมายเดียว

# ใช้คำสั่ง expose เพื่อสร้าง Service อย่างรวดเร็ว

$ kubectl expose deployment my-webapp --port=80 --target-port=80 --type=ClusterIP

service/my-webapp exposed


# ตรวจสอบ Service

$ kubectl get svc

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 443/TCP 5d my-webapp ClusterIP 10.101.55.200 80/TCP 10s

Step 7: เปิดใช้งาน Ingress Controller

ใน K8s ปกติ Ingress เป็นแค่กฎ (Rules) เราต้องมีตัว Ingress Controller (เช่น Nginx) คอยรันอยู่เพื่อทำหน้าที่เป็น Reverse Proxy จริงๆ

# สั่งให้ Minikube เปิดใช้งาน Nginx Ingress Controller

$ minikube addons enable ingress


💡 ingress is an addon maintained by Kubernetes.

... (กระบวนการดาวน์โหลดและติดตั้ง Image ของ Ingress Controller)

🌟 The 'ingress' addon is enabled


# ตรวจสอบว่า Ingress Controller รันขึ้นมาหรือยัง (จะอยู่ใน namespace: ingress-nginx)

$ kubectl get pods -n ingress-nginx

Step 8: เขียนไฟล์ Ingress YAML

เราจะสร้างกฎ Routing ว่าถ้ามีคนเข้าเว็บด้วยโดเมน myapp.local ให้ชี้ไปที่ Service my-webapp

# สร้างไฟล์ชื่อ web-ingress.yaml

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

  name: webapp-ingress

spec:

  rules:

  - host: myapp.local # โดเมนที่เราต้องการใช้งาน

    http:

      paths:

      - path: / # ทุกๆ path ให้เข้าแอปนี้

        pathType: Prefix

        backend:

          service:

            name: my-webapp # ชื่อ Service ที่เราสร้างใน Step 6

            port:

              number: 80 # Port ของ Service

Step 9: Apply Ingress และตั้งค่า Local DNS

เนื่องจาก myapp.local เป็นโดเมนสมมติ เราต้องหลอกคอมพิวเตอร์ของเราให้ชี้โดเมนนี้ไปที่ IP ของ Minikube

# 1. Apply ไฟล์ Ingress

$ kubectl apply -f web-ingress.yaml

ingress.networking.k8s.io/webapp-ingress created


# 2. ดู IP ของ Ingress (รอจนกว่า ADDRESS จะมีค่า)

$ kubectl get ingress

NAME HOSTS ADDRESS PORTS

webapp-ingress myapp.local 192.168.49.2 80

# 3. แก้ไขไฟล์ hosts ในคอมพิวเตอร์ของคุณ


สำหรับ Windows (เปิด Notepad แบบ Admin):

C:\Windows\System32\drivers\etc\hosts


สำหรับ Mac/Linux (ใช้ sudo nano):

/etc/hosts


# เพิ่มบรรทัดนี้ลงไปท้ายไฟล์ (ใช้ IP จากข้อ 2):

192.168.49.2 myapp.local

Step 10: ทดสอบการเข้าถึงผ่าน Ingress

ความพยายามอยู่ที่ไหน ความสำเร็จอยู่ที่นั่น! ทดสอบเปิดเบราว์เซอร์ของคุณ

http://myapp.local

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working.

(Traffic ถูกส่งผ่าน Ingress -> Service -> Pod 1 ใน 5 ตัวแบบ Load Balanced)

🛠️ Troubleshooting: เข้าเว็บไม่ได้ทำอย่างไร?

ปัญหา: Mac / Windows ใช้ Docker Driver

หากคุณรัน Minikube ด้วย Docker driver บน Mac หรือ Windows IP ของ Minikube จะไม่สามารถเข้าถึงได้โดยตรงจากเบราว์เซอร์โฮสต์

วิธีแก้: เปิด Terminal ใหม่แล้วรันคำสั่งนี้ทิ้งไว้

$ minikube tunnel

มันจะขอรหัสผ่าน Admin เครื่องเพื่อเจาะอุโมงค์ให้ Traffic วิ่งเข้า Ingress ได้ (ต้องเปิดค้างไว้ตลอดตอนทดสอบ)

ปัญหา: ไม่มีสิทธิ์แก้ไขไฟล์ /etc/hosts

คุณอาจจะ Save ไฟล์ไม่ได้เพราะติด Permission Denied

วิธีแก้:

  • Windows: ต้องเปิดโปรแกรม Notepad โดยคลิกขวาแล้วเลือก "Run as Administrator" ก่อนเสมอ
  • Mac/Linux: ต้องใช้คำสั่ง sudo nano /etc/hosts
🏆

Lab Complete! การส่งงาน

รายละเอียดสิ่งที่ต้องส่ง (Submission):

  • ไฟล์ YAML ทั้งหมด (.zip):
    • web-configmap.yaml
    • web-deployment.yaml
    • web-ingress.yaml
  • Screenshots (รวมเป็น PDF):
    • ภาพ Terminal ที่แสดงการใช้คำสั่ง kubectl scale และผลลัพธ์ kubectl get pods (แสดง 5 pods)
    • ภาพ Terminal ที่แสดง kubectl exec เข้าไปดู Environment Variables
    • ภาพหน้า Web Browser ที่เข้าใช้งานผ่าน http://myapp.local ได้สำเร็จ