- 1. K3s คืออะไร?
- 2. วัตถุประสงค์การเรียนรู้
- 3. แผนการอบรม 4 ชั่วโมง
- 4. สถาปัตยกรรมห้องปฏิบัติการ
- 5. Lab 1 – เตรียม Ubuntu ทั้งสองเครื่อง
- 6. Lab 2 – ติดตั้ง K3s Server
- 7. Lab 3 – เพิ่ม K3s Agent / Worker Node
- 8. Lab 4 – Deploy เว็บด้วย Deployment + Service
- 9. Lab 5 – เปิดเว็บด้วย Traefik Ingress
- 10. Lab 6 – Scaling และ Rolling Update
- 11. Lab 7 – Persistent Storage (PVC)
- 12. Lab 8 – Observability และ Troubleshooting
- 13. Cleanup – ลบ Lab โดยไม่ถอน K3s
- 14. Best Practices ก่อนนำไป Production
- 15. แบบฝึกหัดท้าย Workshop
- 16. เอกสารอ้างอิง

คู่มือปฏิบัติการภาษาไทยสำหรับ 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. วัตถุประสงค์การเรียนรู้
เมื่อจบกิจกรรม ผู้เรียนจะสามารถ:
- ติดตั้งและตรวจสอบสถานะ K3s Server
- Join K3s Agent เข้า Cluster และตรวจสอบ Node
- Deploy เว็บแอปด้วย Kubernetes YAML
- เข้าถึงบริการผ่าน ClusterIP, NodePort และ Traefik Ingress
- ทำ Scaling, Rolling Update, Rollback และทดลอง PVC
- ตรวจสอบ Pod, Log, Event และแก้ปัญหาที่พบบ่อย
- ลบทรัพยากรฝึกทดลองได้อย่างถูกต้อง
#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
- เปลี่ยน replicas เป็น 4 และแสดงผลลัพธ์
kubectl get pods -o wide - เปลี่ยนชื่อ Host Ingress เป็น
demo.k3s.testและทดสอบด้วยcurl -H 'Host: ...' - ทดลองใส่ชื่อ Container Image ผิด แล้ววิเคราะห์สาเหตุจาก
describeและ Events ก่อนแก้คืน - Restart Deployment
storage-demoแล้วพิสูจน์ว่าข้อมูลใน PVC ยังอยู่ - อธิบายข้อจำกัดของ
local-pathเมื่อ Node สูญหาย และเสนอแนวทาง Storage HA
เกณฑ์ประเมิน: Deploy แอปและเข้าถึง HTTP ได้ (30%), Join/ตรวจ Nodes ได้ (20%), Update/Scaling (20%), Storage (15%), Troubleshooting (15%)
#16. เอกสารอ้างอิง
- K3s Quick Start — https://docs.k3s.io/quick-start
- K3s Requirements — https://docs.k3s.io/installation/requirements
- K3s Networking Services — https://docs.k3s.io/networking/networking-services
- K3s Cluster Access — https://docs.k3s.io/cluster-access
- K3s Volumes and Storage — https://docs.k3s.io/add-ons/storage
- K3s Cluster Datastore — https://docs.k3s.io/datastore
- K3s Backup and Restore — https://docs.k3s.io/datastore/backup-restore
- K3s Uninstalling — https://docs.k3s.io/installation/uninstall
- Kubernetes Documentation — https://kubernetes.io/docs/
สรุป: Workshop นี้นำผู้เรียนจาก K3s Cluster เริ่มต้นไปสู่การ Deploy แอปจริงโดยใช้ Kubernetes Resource พื้นฐาน รู้จักการเปิด Service และ Ingress, การ Scale/Update และข้อจำกัดของ Node-local Storage พร้อมแนวปฏิบัติตรวจสอบระบบและป้องกันความเสี่ยงก่อนใช้ Production