เมื่อพูดถึง Kubernetes Workloads คนส่วนใหญ่คิดถึง Deployment เท่านั้น แต่ Kubernetes มี Workload Controllers อีกหลายตัวที่ออกแบบมาสำหรับ Use Cases ที่ต่างกัน โดยเฉพาะ DaemonSet และ StatefulSet ที่เป็น Workloads สำคัญที่ทุก K8s Admin ต้องรู้
K8s Workload Types ทั้งหมด
| Workload Type | Use Case | ตัวอย่าง |
|---|---|---|
| Deployment | Stateless apps ที่ Scale ได้ | Web Server, API Server, Microservices |
| DaemonSet | รัน 1 Pod ต่อ 1 Node | Log Collector, Monitoring Agent, Network Plugin |
| StatefulSet | Stateful apps ที่ต้องการ Persistent Identity | Database, Kafka, ZooKeeper, Redis Cluster |
| Job | รันงานครั้งเดียวแล้วจบ | Batch Processing, Migration, Backup |
| CronJob | รันงานตาม Schedule | Daily Report, Cleanup, Scheduled Backup |
| ReplicaSet | (ใช้ผ่าน Deployment) | ไม่ค่อยสร้างตรงๆ |
DaemonSet — 1 Pod ต่อ 1 Node
DaemonSet คืออะไร?
DaemonSet คือ Workload Controller ที่รับประกันว่าจะมี Pod รันอยู่บน ทุก Node (หรือ Subset ของ Node) เมื่อมี Node ใหม่เข้ามาใน Cluster จะถูกสร้าง Pod ให้อัตโนมัติ เมื่อ Node ถูกลบออก Pod จะถูกลบด้วย
DaemonSet Use Cases
| Use Case | ตัวอย่าง Software | ทำไมต้อง DaemonSet |
|---|---|---|
| Log Collection | Fluentd, Fluent Bit, Filebeat | ต้องจับ Log จากทุก Node |
| Monitoring | Node Exporter, Datadog Agent | ต้องเก็บ Metrics จากทุก Node |
| Networking | Cilium, Calico, kube-proxy | Network Plugin ต้องรันบนทุก Node |
| Storage | CSI Node Driver | Storage Driver ต้องรันบนทุก Node |
| Security | Falco, Aqua, Twistlock | Security Agent ต้อง Monitor ทุก Node |
DaemonSet YAML ตัวอย่าง: Fluentd
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: logging
labels:
app: fluentd
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
app: fluentd
spec:
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.16
resources:
limits:
memory: 200Mi
cpu: 100m
requests:
memory: 100Mi
cpu: 50m
volumeMounts:
- name: varlog
mountPath: /var/log
- name: containers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: containers
hostPath:
path: /var/lib/docker/containers
DaemonSet Update Strategy
| Strategy | พฤติกรรม | เมื่อไรใช้ |
|---|---|---|
| RollingUpdate (Default) | ลบ Pod เก่าแล้วสร้างใหม่ทีละ Node | ทั่วไป ปลอดภัย |
| OnDelete | อัพเดทเมื่อ Pod ถูกลบด้วยตนเอง | ต้องการควบคุม Rollout เอง |
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # อัพเดททีละ 1 Node
Tolerations — รัน DaemonSet บน Control Plane
ปกติ K8s จะไม่ Schedule Pod บน Control Plane Node (Master) ถ้าต้องการให้ DaemonSet รันบน Master ด้วย ต้องเพิ่ม Tolerations:
spec:
template:
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
StatefulSet — Ordered, Persistent Identity
StatefulSet คืออะไร?
StatefulSet คือ Workload Controller สำหรับ Applications ที่ต้องการ:
- Stable Network Identity: แต่ละ Pod มีชื่อที่คงที่ (pod-0, pod-1, pod-2) ไม่ใช่ Random Hash เหมือน Deployment
- Persistent Storage: แต่ละ Pod มี PersistentVolume ของตัวเอง ไม่ใช้ร่วมกัน
- Ordered Deployment: สร้าง/ลบ Pod ตามลำดับ (0 → 1 → 2 ตอนสร้าง, 2 → 1 → 0 ตอนลบ)
StatefulSet Use Cases
| Use Case | ตัวอย่าง | ทำไมต้อง StatefulSet |
|---|---|---|
| Databases | PostgreSQL, MySQL, MongoDB | ต้องการ Persistent Storage + Stable Identity |
| Message Queues | Kafka, RabbitMQ | ต้องการ Ordered Deployment + Persistent Data |
| Coordination Services | ZooKeeper, etcd | ต้องรู้ว่าใครคือ Leader ใครคือ Follower |
| Cache Clusters | Redis Cluster | แต่ละ Node เก็บ Shard ต่างกัน |
| Search Engines | Elasticsearch | แต่ละ Node เก็บ Index Shard ต่างกัน |
StatefulSet YAML ตัวอย่าง: PostgreSQL
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres-headless # ต้องชี้ไป Headless Service
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates: # แต่ละ Pod ได้ PVC ของตัวเอง!
- metadata:
name: postgres-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: standard
resources:
requests:
storage: 10Gi
Headless Service สำหรับ StatefulSet
apiVersion: v1
kind: Service
metadata:
name: postgres-headless
spec:
clusterIP: None # Headless! ไม่มี ClusterIP
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
# DNS Records ที่ได้:
# postgres-0.postgres-headless.default.svc.cluster.local
# postgres-1.postgres-headless.default.svc.cluster.local
# postgres-2.postgres-headless.default.svc.cluster.local
volumeClaimTemplates — PVC อัตโนมัติ
เมื่อ StatefulSet สร้าง Pod ใหม่ จะสร้าง PersistentVolumeClaim (PVC) ให้อัตโนมัติตาม Template:
postgres-data-postgres-0— PVC สำหรับ Pod 0postgres-data-postgres-1— PVC สำหรับ Pod 1postgres-data-postgres-2— PVC สำหรับ Pod 2
เมื่อ Pod ถูก Restart หรือ Reschedule ไป Node อื่น PVC ยังคงอยู่ ข้อมูลไม่หาย
Ordered Pod Management
# สร้างตามลำดับ:
# postgres-0 → Ready → postgres-1 → Ready → postgres-2
# ลบย้อนกลับ:
# postgres-2 → Terminated → postgres-1 → Terminated → postgres-0
# ถ้าต้องการ Parallel (ไม่รอลำดับ):
spec:
podManagementPolicy: Parallel # Default คือ OrderedReady
StatefulSet Scaling
# Scale Up (เพิ่ม Pod ตามลำดับ)
kubectl scale statefulset postgres --replicas=5
# Scale Down (ลบ Pod จากท้ายก่อน)
kubectl scale statefulset postgres --replicas=2
# ลบ postgres-4 → postgres-3 → postgres-2
# ⚠️ Scale Down ไม่ลบ PVC!
# ต้องลบ PVC ด้วยตนเองถ้าไม่ต้องการ
kubectl delete pvc postgres-data-postgres-4
kubectl delete pvc postgres-data-postgres-3
kubectl delete pvc postgres-data-postgres-2
StatefulSet vs Deployment สำหรับ Databases
| เปรียบเทียบ | Deployment | StatefulSet |
|---|---|---|
| Pod Name | Random (app-7b4d6f-xyz) | Ordered (app-0, app-1, app-2) |
| Storage | Shared หรือ Ephemeral | แต่ละ Pod มี PVC ของตัวเอง |
| DNS | ผ่าน Service (Load Balanced) | แต่ละ Pod มี DNS ของตัวเอง |
| Scaling | Scale Up/Down ไม่มีลำดับ | Scale ตามลำดับ |
| Rolling Update | สร้างใหม่ก่อน ลบเก่าทีหลัง | ลบเก่า → สร้างใหม่ ตามลำดับ (ย้อน) |
| เหมาะกับ DB? | ไม่เหมาะ (ข้อมูลหาย) | เหมาะ (ข้อมูลคงอยู่) |
Operators — ทางเลือกที่ดีกว่า StatefulSet สำหรับ DB
ในปี 2026 การรัน Database บน K8s ด้วย StatefulSet ตรง ๆ ยังคงยุ่งยาก ทางเลือกที่ดีกว่าคือใช้ Operators ที่ออกแบบมาเฉพาะสำหรับแต่ละ Database:
| Database | Operator | จัดการอะไรให้ |
|---|---|---|
| PostgreSQL | CloudNativePG, Zalando Postgres Operator | HA, Backup, Failover, Connection Pooling |
| MySQL | MySQL Operator (Oracle), Vitess | InnoDB Cluster, Backup, Scaling |
| MongoDB | MongoDB Community Operator | ReplicaSet, Sharding, Backup |
| Kafka | Strimzi | Broker Management, Topic, User, Connect |
| Redis | Redis Operator (Spotahome) | Sentinel, Cluster, Failover |
| Elasticsearch | ECK (Elastic Cloud on K8s) | Cluster, Kibana, APM, Beats |
สรุป: เลือก Workload Type ไหนดี?
| ต้องการ | ใช้ |
|---|---|
| Stateless App ที่ Scale ได้ | Deployment |
| รัน Agent/Daemon บนทุก Node | DaemonSet |
| Database/Stateful App ที่ต้อง Persistent Storage | StatefulSet (หรือ Operator) |
| งาน Batch ครั้งเดียว | Job |
| งาน Batch ตาม Schedule | CronJob |
DaemonSet และ StatefulSet เป็น Workload Controllers ที่สำคัญมากใน K8s ที่ช่วยแก้ปัญหาที่ Deployment ทำไม่ได้ ทำความเข้าใจทั้งสองตัวจะช่วยให้ออกแบบ K8s Architecture ได้ดีขึ้น และรันงานได้หลากหลายมากขึ้น
