info-workshop-k3s-lightweight-kubernetes-deploy

คู่มือปฏิบัติการภาษาไทยสำหรับ Ubuntu Server 24.04 LTS • 1 Server + 1 Agent (หรือทำแบบ Single-Node ได้)

#1. K3s คืออะไร?

K3s เป็น Kubernetes Distribution แบบ Lightweight ที่รวมองค์ประกอบสำคัญของ Kubernetes ไว้ในแพ็กเกจซึ่งติดตั้งง่าย เหมาะกับ Edge Computing, IoT, Homelab, ห้องปฏิบัติการ และ Production ที่ออกแบบและดูแลอย่างเหมาะสม

โดยทั่วไป K3s มี containerd, Flannel (CNI), CoreDNS, Traefik (Ingress Controller), ServiceLB, metrics-server และ local-path-provisioner พร้อมใช้งานตามการติดตั้งค่าเริ่มต้น ส่วนฐานข้อมูลของ Single-Server โดยทั่วไปใช้ SQLite; สำหรับ Multi-Server HA สามารถใช้ embedded etcd หรือ external datastore ได้

แนวคิด หน้าที่
Server Control plane, API Server, Scheduler, Controller และ datastore; Server สามารถรัน workload ได้
Agent Worker Node ที่รับหน้าที่รัน Pod
Deployment ประกาศจำนวน Pod และจัดการการอัปเดต
Service ให้ endpoint คงที่สำหรับเข้าถึง Pod
Ingress กำหนดเส้นทาง HTTP/HTTPS ไปยัง Service
PVC ขอพื้นที่จัดเก็บที่คงอยู่แยกจากอายุ Pod

หมายเหตุ: Agent ไม่ใช่เงื่อนไขบังคับ — K3s Server เครื่องเดียวก็ทำ Workshop ส่วน Deploy ได้เกือบทั้งหมด การมี Agent ช่วยให้เรียนรู้การทำงานแบบหลาย Node

#2. วัตถุประสงค์การเรียนรู้

เมื่อจบกิจกรรม ผู้เรียนจะสามารถ:

  1. ติดตั้งและตรวจสอบสถานะ K3s Server
  2. Join K3s Agent เข้า Cluster และตรวจสอบ Node
  3. Deploy เว็บแอปด้วย Kubernetes YAML
  4. เข้าถึงบริการผ่าน ClusterIP, NodePort และ Traefik Ingress
  5. ทำ Scaling, Rolling Update, Rollback และทดลอง PVC
  6. ตรวจสอบ Pod, Log, Event และแก้ปัญหาที่พบบ่อย
  7. ลบทรัพยากรฝึกทดลองได้อย่างถูกต้อง

#3. แผนการอบรม 4 ชั่วโมง

เวลา หัวข้อ ผลลัพธ์
00:00–00:30 พื้นฐานและเตรียม VM/Network สื่อสารระหว่าง VM ได้
00:30–01:20 ติดตั้ง Server และ Join Agent Node ขึ้น Ready
01:20–02:20 Deploy App / Service / Ingress เปิดเว็บทดลองได้
02:20–03:10 Scale / Update / Storage ปรับ replicas และเก็บข้อมูลได้
03:10–04:00 Troubleshooting / Quiz / Cleanup ตรวจและแก้ปัญหาเบื้องต้นได้

#4. สถาปัตยกรรมห้องปฏิบัติการ

flowchart TB
  U[ผู้ใช้ / Browser] -->|HTTP :80| T[Traefik Ingress]
  U -->|TCP :30080| N[NodePort Service]
  T --> S[ClusterIP Service]
  N --> D[Web Deployment / Pods]
  S --> D
  subgraph Cluster[K3s Cluster]
    subgraph Server[Server - 192.168.56.10]
      A[API Server + Control Plane]
    end
    subgraph Agent[Agent - 192.168.56.11]
      W[Worker Runtime]
    end
    D
  end
  A -.บริหาร Cluster.-> W

เครื่องที่ใช้ (เปลี่ยน IP ให้ตรงกับระบบของคุณ):

รายการ Hostname IP ตัวอย่าง ทรัพยากรแนะนำสำหรับ Lab
Server k3s-server 192.168.56.10 2 vCPU, RAM 4 GB, Disk 20 GB
Agent k3s-agent1 192.168.56.11 2 vCPU, RAM 2 GB, Disk 15 GB

Minimum ของ K3s ที่เอกสารระบุคือ Server 2 CPU / 2 GB และ Agent 1 CPU / 512 MB ไม่รวมภาระงานของแอป; Workshop แนะนำเผื่อทรัพยากรเพิ่ม

ข้อกำหนดเครือข่าย: ทั้งสองเครื่องต้องติดต่อกันโดย Private IP ได้ และ hostname ต้องไม่ซ้ำกัน โดยปกติต้องเปิด TCP 6443 จาก Agent ไป Server, UDP 8472 ระหว่าง Node สำหรับ Flannel VXLAN, TCP 10250 ระหว่าง Node สำหรับ kubelet/metrics และ TCP 80 (หรือ 30080) จากเครื่องผู้เรียนตามวิธีทดสอบ ห้ามเปิด UDP 8472 ให้เข้าถึงจาก Internet สาธารณะ

ตัวอย่าง IP 192.168.56.x มักใช้กับ Host-Only Adapter หากใช้ Cloud VM ให้ใช้ Private VPC IP และ Security Group/Firewall ที่จำกัดต้นทางอย่างเคร่งครัด

#5. Lab 1 – เตรียม Ubuntu ทั้งสองเครื่อง

ดำเนินการ บนทั้ง Server และ Agent โดย login ด้วยบัญชีที่ใช้ sudo ได้:

sudo apt update
sudo apt install -y curl ca-certificates iproute2
hostnamectl
ip -4 address show
free -h

ตั้งชื่อแยกกัน:

บน Server

sudo hostnamectl set-hostname k3s-server

บน Agent

sudo hostnamectl set-hostname k3s-agent1

ตรวจสอบจากแต่ละเครื่อง:

ping -c 3 192.168.56.10
ping -c 3 192.168.56.11

หาก Firewall เปิดอยู่ต้องอนุญาตพอร์ตภายในเครือข่ายตามหัวข้อก่อนหน้า ทั้งนี้ UFW อาจขัดขวางเครือข่าย Pod; เอกสาร K3s แนะนำให้ปิด UFW หรือกำหนดกฎที่รองรับ Pod CIDR (10.42.0.0/16) และ Service CIDR (10.43.0.0/16) อย่างครบถ้วน ไม่ควรปิด Firewall ของ Production โดยไม่มีมาตรการทดแทน

บนเครื่อง Cloud อย่ารันคำสั่งเปลี่ยน Firewall ผ่าน SSH โดยไม่ตรวจสอบการอนุญาต TCP/22 และช่องทางกู้คืนก่อน

#6. Lab 2 – ติดตั้ง K3s Server

บน Server ให้ตรวจสอบสคริปต์ติดตั้งก่อนใช้งานถ้าต้องการควบคุม Supply Chain:

curl -fsSL https://get.k3s.io -o /tmp/install-k3s.sh
less /tmp/install-k3s.sh
sudo sh /tmp/install-k3s.sh

หรือใช้คำสั่ง Quick Start จากเว็บไซต์โครงการ:

curl -sfL https://get.k3s.io | sh -

เลือกเพียง วิธีใดวิธีหนึ่ง ไม่จำเป็นต้องติดตั้งซ้ำ สำหรับ Production ควรตรึงเวอร์ชัน ตรวจสอบ checksum/signature ตามนโยบายองค์กร และสำรองข้อมูลก่อนอัปเกรด

ตรวจสอบ:

sudo systemctl status k3s --no-pager
sudo k3s kubectl get nodes -o wide
sudo k3s kubectl get pods -A
sudo k3s --version

ผลที่คาดหวัง: Node k3s-server มีสถานะ Ready; System Pod เช่น coredns, traefik, metrics-server, local-path-provisioner จะค่อย ๆ พร้อมใช้งาน

#ตั้งค่า kubectl ให้ User ปัจจุบัน

บน Server เท่านั้น:

mkdir -p "$HOME/.kube"
sudo cp /etc/rancher/k3s/k3s.yaml "$HOME/.kube/config"
sudo chown "$(id -u):$(id -g)" "$HOME/.kube/config"
chmod 600 "$HOME/.kube/config"
kubectl get nodes

~/.kube/config นี้มีสิทธิ์ผู้ดูแล Cluster ระดับสูงมาก ควรเก็บไว้เป็นความลับ ไม่ส่งขึ้น Git หรือแจกให้ผู้เรียนคนอื่น การคัดลอกไฟล์อาจต้องทำใหม่เมื่อใบรับรองหรือค่าการเชื่อมต่อเปลี่ยน

#7. Lab 3 – เพิ่ม K3s Agent / Worker Node

บน Server ค้นหา Join Token:

sudo cat /var/lib/rancher/k3s/server/node-token

ห้ามโพสต์ Token ลงแชต, สไลด์, Git, Screen Recording หรือ Logs สาธารณะ ผู้เรียนควรรับ Token ผ่านช่องทางที่ปลอดภัย

บน Agent ให้พิมพ์ Token แบบไม่แสดงบนหน้าจอ:

read -rsp 'K3s join token: ' K3S_TOKEN; echo
curl -sfL https://get.k3s.io | K3S_URL='https://192.168.56.10:6443' K3S_TOKEN="$K3S_TOKEN" sh -
unset K3S_TOKEN
sudo systemctl status k3s-agent --no-pager

ตรวจสอบจาก Server:

kubectl get nodes -o wide
kubectl describe node k3s-agent1

ผลคาดหวัง: มี k3s-server และ k3s-agent1 โดยสถานะ Ready ทั้งคู่

หาก Agent Join ไม่สำเร็จ:

# บน Agent
sudo journalctl -u k3s-agent -n 100 --no-pager
curl -k --connect-timeout 5 https://192.168.56.10:6443/

การตอบ HTTP 401/403/404 จาก endpoint เป็นไปได้และยังบ่งชี้ว่า TCP/TLS ไปถึง Server; ให้ตรวจสอบ Log สำหรับรายละเอียดการรับรองตัวตน (การใช้ -k ที่นี่เพื่อวิเคราะห์การเชื่อมต่อเท่านั้น ไม่ใช่แนวทางใช้งานทั่วไป)

#8. Lab 4 – Deploy เว็บด้วย Deployment + Service

โครงสร้างไฟล์ที่แนบมากับชุด Workshop:

k3s-workshop/
├── K3s-Workshop-Thai.md
├── manifests/
│   ├── 00-namespace.yaml
│   ├── 01-configmap.yaml
│   ├── 02-deployment.yaml
│   ├── 03-service.yaml
│   ├── 04-ingress.yaml
│   └── 05-storage-demo.yaml
└── scripts/
    └── verify.sh

ไฟล์ 01-configmap.yaml เก็บหน้า index.html ภาษาไทย; 02-deployment.yaml สร้าง nginx 2 replicas พร้อม readiness/liveness probes และ resource requests/limits; 03-service.yaml สร้าง ClusterIP และ NodePort

บน Server คัดลอกโฟลเดอร์ Workshop และเข้า Directory:

cd k3s-workshop
kubectl apply -f manifests/00-namespace.yaml
kubectl apply -f manifests/01-configmap.yaml
kubectl apply -f manifests/02-deployment.yaml
kubectl apply -f manifests/03-service.yaml

kubectl -n k3s-workshop get deployments,pods,services -o wide
kubectl -n k3s-workshop rollout status deployment/web

ผลคาดหวัง: deployment/web มี READY 2/2, Pod 2 รายการพร้อมใช้งาน, web-service เป็น ClusterIP และ web-nodeport มี Port 80:30080/TCP

#ทดสอบผ่าน port-forward

Terminal ที่ 1:

kubectl -n k3s-workshop port-forward svc/web-service 18080:80

Terminal ที่ 2 บนเครื่องเดียวกัน:

curl -i http://127.0.0.1:18080/

เปิดเว็บได้ที่ http://127.0.0.1:18080 จากเครื่องที่รัน port-forward หากทำผ่าน SSH บน Server ให้ใช้ SSH local port forwarding หรือทดสอบ curl บน Server โดยตรง

#ทดสอบ NodePort

จากเครื่องที่เชื่อมถึง Node ใน Private Network และได้รับอนุญาตพอร์ต 30080:

curl -i http://192.168.56.10:30080/

การทดสอบล้มเหลวอาจเกิดจาก NodePort Firewall, การเชื่อมต่อ Private IP, Pod ไม่พร้อมหรือ Service selector ผิด

#9. Lab 5 – เปิดเว็บด้วย Traefik Ingress

K3s ติดตั้ง Traefik และ ServiceLB โดยค่าเริ่มต้น บริการ Traefik ใช้พอร์ต 80/443 ของ Node ที่ ServiceLB เลือก (ค่าเริ่มต้นมักครอบคลุมทุก Node) ดังนั้นตรวจสอบก่อนว่าพอร์ตไม่ได้ถูกใช้โดยเว็บเซิร์ฟเวอร์ตัวอื่น

kubectl -n kube-system get svc traefik
kubectl -n kube-system get pods | grep -E 'traefik|svclb'
kubectl apply -f manifests/04-ingress.yaml
kubectl -n k3s-workshop get ingress

ทดสอบโดยไม่ต้องตั้งค่า DNS จริง:

curl -i -H 'Host: app.k3s.test' http://192.168.56.10/

หรือกำหนดใน /etc/hosts ของเครื่องผู้เรียน:

192.168.56.10  app.k3s.test

แล้วเปิด http://app.k3s.test (ชื่อโดเมนนี้ใช้เพื่อ Lab เท่านั้น) ถ้าได้ 404 จาก Traefik ให้ตรวจ Host header, ingressClassName, เส้นทาง backend และ readiness ของ Pod

ใช้ HTTP เฉพาะในเครือข่ายทดลอง สำหรับ Production ต้องตั้งค่า DNS/TLS, ออก Certificate และจำกัดการเข้าถึงตามนโยบายองค์กร

#10. Lab 6 – Scaling และ Rolling Update

เพิ่มจำนวน Pod จาก 2 เป็น 3:

kubectl -n k3s-workshop scale deployment/web --replicas=3
kubectl -n k3s-workshop get pods -o wide
kubectl -n k3s-workshop rollout status deployment/web

ทดลอง Rolling Update โดยปรับแท็ก image:

kubectl -n k3s-workshop set image deployment/web nginx=nginx:1.29-alpine
kubectl -n k3s-workshop rollout status deployment/web
kubectl -n k3s-workshop rollout history deployment/web

ทดลอง Rollback:

kubectl -n k3s-workshop rollout undo deployment/web
kubectl -n k3s-workshop rollout status deployment/web

ตัวอย่างนี้สมมติว่าสามารถ Pull image จาก Registry ได้ ถ้าแท็ก Image ใน Registry เปลี่ยนแปลงหรือ Pull ไม่ได้ ให้ใช้แท็กที่เผยแพร่จริงและตรวจ kubectl describe pod การ scale ด้วย CLI เป็นการเปลี่ยนสถานะปัจจุบัน; ถ้า kubectl apply ไฟล์เดิมซึ่งระบุ replicas: 2 อีกครั้ง จำนวน Pod อาจกลับเป็น 2

#แก้เนื้อหา ConfigMap

แก้ข้อความใน manifests/01-configmap.yaml จากนั้น:

kubectl apply -f manifests/01-configmap.yaml
kubectl -n k3s-workshop rollout restart deployment/web
kubectl -n k3s-workshop rollout status deployment/web

เนื่องจากใช้ ConfigMap ผ่าน subPath การแก้ค่าไม่อัปเดตไฟล์ใน Pod ปัจจุบันโดยตรง จึงต้อง Restart/Deploy ใหม่

#11. Lab 7 – Persistent Storage (PVC)

K3s ติดตั้ง StorageClass ชื่อ local-path โดยค่าเริ่มต้น ซึ่งเก็บข้อมูลในไฟล์ระบบของ Node: เป็น Node-local storage ไม่ใช่ shared/distributed storage

kubectl get storageclass
kubectl apply -f manifests/05-storage-demo.yaml
kubectl -n k3s-workshop get pvc,pods -o wide
kubectl -n k3s-workshop rollout status deploy/storage-demo
kubectl -n k3s-workshop exec deploy/storage-demo -- cat /data/workshop.log

Restart เพื่อพิสูจน์ว่าไฟล์ยังอยู่:

kubectl -n k3s-workshop rollout restart deploy/storage-demo
kubectl -n k3s-workshop rollout status deploy/storage-demo
kubectl -n k3s-workshop exec deploy/storage-demo -- cat /data/workshop.log

คาดว่าจะเห็นข้อความหลายบรรทัดจากการเริ่ม Pod คนละครั้ง ข้อมูลอยู่ต่อเนื่องภายใน PVC; อย่างไรก็ตาม หาก Node เจ้าของ Local PV สูญหาย จะไม่สามารถย้ายข้อมูลไปอีก Node ได้อัตโนมัติ ถ้าต้องการ High Availability ของ Storage ต้องออกแบบระบบ Storage อีกชั้น เช่น Longhorn/CSI ที่เหมาะกับสภาพแวดล้อม

#12. Lab 8 – Observability และ Troubleshooting

#ชุดคำสั่งตรวจระบบ

kubectl get nodes -o wide
kubectl get pods -A -o wide
kubectl -n k3s-workshop describe deployment web
kubectl -n k3s-workshop get events --sort-by=.lastTimestamp
kubectl -n k3s-workshop logs deployment/web --tail=50
kubectl -n k3s-workshop get endpointslices -l kubernetes.io/service-name=web-service
kubectl -n k3s-workshop describe ingress web-ingress
kubectl top nodes
kubectl top pods -n k3s-workshop

kubectl top ต้องมี metrics-server ทำงานและ Metrics อาจใช้เวลาสักระยะก่อนพร้อมใช้งาน

อาการ จุดตรวจ การแก้ไขเบื้องต้น
Node NotReady systemctl status k3s / k3s-agent, journalctl เช็กการเชื่อมต่อและ CNI
Pod Pending kubectl describe pod เช็ก RAM/CPU, scheduling, PVC
ImagePullBackOff Pod Events เช็กชื่อ Tag, Internet, Registry Auth
Service ใช้ไม่ได้ selector, ports, EndpointSlice ตรวจ Pod labels และ readiness
Ingress 404 Host header, IngressClass ตรวจชื่อ host/path/class และ ingress controller
PVC ไม่ Bound StorageClass, PVC Events ตรวจ provisioner และ Node ที่ใช้ Storage
Join Agent ไม่สำเร็จ Token, server URL, TCP 6443 ตรวจ Firewall, hostname ไม่ซ้ำ และ Log

#ตรวจสอบแบบอัตโนมัติ

ในโฟลเดอร์ Workshop:

bash scripts/verify.sh

สคริปต์จะเช็ก Node, Pods, Deployment, Ingress/PVC และทำ HTTP smoke test ผ่าน kubectl port-forward ที่พอร์ต 18080 บนเครื่องปัจจุบัน

#13. Cleanup – ลบ Lab โดยไม่ถอน K3s

บน Server:

kubectl delete namespace k3s-workshop
kubectl get namespaces

การลบ Namespace จะลบ Deployment, Service, Ingress และ PVC ที่อยู่ภายใน รวมถึงอาจทำให้ข้อมูลบน PV ที่ถูกจัดการด้วย StorageClass local-path ถูกลบตาม Reclaim Policy; สำรองข้อมูลที่ต้องเก็บก่อนเสมอ

หากต้องการถอน K3s จาก VM ที่ใช้สำหรับ Workshop เท่านั้น:

Agent

sudo /usr/local/bin/k3s-agent-uninstall.sh

Server

sudo /usr/local/bin/k3s-uninstall.sh

คำเตือน: การถอน K3s อาจลบข้อมูล Cluster, Local Datastore, Storage, Config และ Tooling บน Node นั้น ห้ามใช้คำสั่ง uninstall บนระบบที่มีงานจริงหรือข้อมูลสำคัญโดยไม่มี Backup/แผนย้ายระบบ

#14. Best Practices ก่อนนำไป Production

  • ใช้ private network และจำกัดพอร์ตด้วย Firewall/Security Groups; ห้ามเปิด Flannel UDP 8472 สู่ Internet
  • ระบุเวอร์ชันของ K3s และ Image ที่ผ่านการทดสอบ รวมถึงใช้ Image Digest หากต้องการ Reproducibility สูง
  • จำกัดสิทธิ์ Kubernetes ด้วย RBAC และไม่แชร์ Admin Kubeconfig/Join Token
  • ใช้ TLS สำหรับ Ingress และจัดการ Certificate/DNS ให้ครบ
  • ตั้ง Resource Requests/Limits, Health Probes, NetworkPolicy และ Pod Security ตามความเหมาะสม
  • สำรองข้อมูล Datastore และ Server Token; ถ้าใช้ SQLite Single-Server ให้สำรอง directory ฐานข้อมูลตามคู่มือทางการ
  • ใช้ HA Control Plane เมื่อบริการต้องทนต่อการล่มของ Server และประเมิน Storage HA แยกจาก Control Plane HA
  • ติดตั้ง Observability/Logging/Monitoring และทดสอบ Restore อย่างสม่ำเสมอ

#15. แบบฝึกหัดท้าย Workshop

  1. เปลี่ยน replicas เป็น 4 และแสดงผลลัพธ์ kubectl get pods -o wide
  2. เปลี่ยนชื่อ Host Ingress เป็น demo.k3s.test และทดสอบด้วย curl -H 'Host: ...'
  3. ทดลองใส่ชื่อ Container Image ผิด แล้ววิเคราะห์สาเหตุจาก describe และ Events ก่อนแก้คืน
  4. Restart Deployment storage-demo แล้วพิสูจน์ว่าข้อมูลใน PVC ยังอยู่
  5. อธิบายข้อจำกัดของ local-path เมื่อ Node สูญหาย และเสนอแนวทาง Storage HA

เกณฑ์ประเมิน: Deploy แอปและเข้าถึง HTTP ได้ (30%), Join/ตรวจ Nodes ได้ (20%), Update/Scaling (20%), Storage (15%), Troubleshooting (15%)

#16. เอกสารอ้างอิง

  1. K3s Quick Start — https://docs.k3s.io/quick-start
  2. K3s Requirements — https://docs.k3s.io/installation/requirements
  3. K3s Networking Services — https://docs.k3s.io/networking/networking-services
  4. K3s Cluster Access — https://docs.k3s.io/cluster-access
  5. K3s Volumes and Storage — https://docs.k3s.io/add-ons/storage
  6. K3s Cluster Datastore — https://docs.k3s.io/datastore
  7. K3s Backup and Restore — https://docs.k3s.io/datastore/backup-restore
  8. K3s Uninstalling — https://docs.k3s.io/installation/uninstall
  9. Kubernetes Documentation — https://kubernetes.io/docs/

สรุป: Workshop นี้นำผู้เรียนจาก K3s Cluster เริ่มต้นไปสู่การ Deploy แอปจริงโดยใช้ Kubernetes Resource พื้นฐาน รู้จักการเปิด Service และ Ingress, การ Scale/Update และข้อจำกัดของ Node-local Storage พร้อมแนวปฏิบัติตรวจสอบระบบและป้องกันความเสี่ยงก่อนใช้ Production