在前一篇文章中,我們探討了 DaemonSet,適合在每個 Node 上部署系統級服務(像是 log agent 或監控 agent)。但今天要談的主題不一樣: 有狀態的服務。
很多雲端應用都是「無狀態」(Stateless)的,例如前端 Web App,可以隨意新增或刪除 Pod,不需要在乎 Pod 的身分。但有些服務卻不是這樣:
這時候,Kubernetes 的 StatefulSet 就派上用場了。
StatefulSet 有幾個關鍵功能:
一般 Service(如 ClusterIP)會幫我們做負載平衡,但 StatefulSet 需要「點對點」連線,所以需要 Headless Service,在明天和網路相關的文章主題會介紹更多和 Service
相關的內容。
定義一個 Headless Service 時:
spec:
clusterIP: None
這樣 Service 就不會提供一個統一的虛擬 IP,而是回傳底下 每個 Pod 的真實 DNS。
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
spec:
clusterIP: None
selector:
app: mysql
ports:
- port: 3306
name: mysql
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql-headless
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: mypassword
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
驗證結果
部署後,可以看到 Pod 名稱是 有序且固定的:
kubectl get pods -l app=mysql
# mysql-0
# mysql-1
# mysql-2
測試 DNS 解析:
kubectl exec -it mysql-0 -- ping mysql-1.mysql-headless
可以確認每個 Pod 都能透過 Headless Service 直接溝通。
常見應用場景
StatefulSet 與其他控制器的對比
StatefulSet 是 Kubernetes 專門為「有狀態應用」設計的控制器,它搭配 Headless Service,讓每個 Pod 擁有獨立的身分與穩定的 DNS。
如果說 Deployment 是「隨插即用」的無狀態服務,那麼 StatefulSet 就是「需要固定身份與資料」的守護者。
在下一篇,我們將進一步探討 Service 的三種型態(ClusterIP、NodePort、LoadBalancer),看看 StatefulSet 如何透過它們與外部世界互動。