[k8s] StatefulSet ============== > [color=pink]在 K8s 的 Deployment 應用中做了一個假設:發佈應用的 pod 每一個是相同的,沒有相依性、順序性,更無所謂要運行在哪個 K8s node 上。依照需求,可以透過 Deployment 任意進行 pod scale-out scale-in。此可以稱為:無狀態應用(***Stateless Application***) > > StatefulSet 類似於 Deployment,可以指定要多少個 Pod (replicas) ## replicating stateful applications is more difficult + cant be created/deleted at same time + cant be randomly addressed + replica Pods are not identical: Pod Identity ## Pod Identity 1. sticky identity for each pod 2. created from same spec, but not interchangable 3. persistent identifier across re-scheduling ***for data consistency*** ![](https://i.imgur.com/uyv0SPs.png =400x) ### Persistent Volume Claim + Stateful 背後會有一個更新內容的儲存空間 在 K8s 中負責管理儲存空間的就是 Volume ,作用跟 Docker 的 Volume 幾乎一模一樣,但畢竟 K8s 的 Volume 只是在 Pod 中做暫時存放的儲存空間而已,當 Pod 移除之後這個儲存空間也會一併消失,為了要在 K8s 中建立一個像資料庫可以永久儲存的空間,也就是這個 Volume 不能被包含在 Pod 內。 *PVC:像是資源需求者* *PV:像是資源提供者* ## Headless Service 每個 Service 都會有一組自己的 ClusterIP (ExternalName 形式的除外),所以 Headless 的意思其實就是不要有 ClusterIP,方法也很簡單直接在設定檔裡面加個 ClusterIP: None 即可。 ### Architecture ![image](https://hackmd.io/_uploads/ByLkLBC7a.png =400x) ### features of headless service + 與其他 Service 不同,沒有 Cluster Service IP + 不需要負載平衡 + 使用 StatefulSet 建立的 Pod 它的名字並不會因為重啟而改變,這時利用這個 DNS record 就能正確地與特定 Pod 連接,不用擔心名字改變、IP 改變 + ==***<pod name>.<headless-service name>.<namespace>.svc.<cluster-domain>***== + 也可以直接接上headless service,還是會發給對應的後端 Pods + ==***<headless-service name>.<namespace>.svc.<cluster-domain>***== + <font color="red">????</font>但不確定轉發的機制 ## use cases ### how to build database cluster ```yaml= apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql-statefulset spec: replicas: 3 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.1 ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD value: your-root-password volumeMounts: - name: mysql-vol mountPath: /var/lib/mysql podManagementPolicy: OrderedReady serviceName: mysql-h volumeClaimTemplates: - metadata: name: mysql-vol spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi ``` ### how to create headless service ```yaml= apiVersion: v1 kind: Service metadata: name: mysql-h spec: ports: - port: 3306 selector: app: mysql clusterIP: None ```