[元件] Deployment, StatefulSet === ###### tags: `K8s / 元件` ###### tags: `Kubernetes`, `k8s`, `StatefulSet`, `sts`, `rollout`, `restart` <br> [TOC] <br> ## Tips - statefulset 資源縮寫:sts - 重啟 stateful-set ``` kubectl rollout restart statefulset my-app kubectl rollout restart statefulset/my-app ``` <br> ## 討論 ### K8s StatefulSet vs Deployment 差異性為何?能簡單說明? - ### gpt-o4-mini-high (2025/05/31) 以下是 **Deployment** 與 **StatefulSet** 的簡要比較: ### Deployment(無狀態工作負載) - **Pod 身份**:所有 Pod 都是可互換的,名稱隨機(例如 `nginx-5f8d6f9d6f-abc12`)。 - **網路身分**:沒有固定的 DNS 名稱;要存取必須透過 Service 的 ClusterIP 或 LoadBalancer。 - **儲存**:通常用於無狀態應用(Stateless),即使搭配 PVC 也不保證 Pod 重建後與同一個 PVC 綁定。 - **擴縮**:水平擴縮(scale)與滾動更新(rolling update)是無序且並行執行的,速度快、彈性高。 - **使用場景**:Web 前端、API、Batch 工作等不需要保留 Pod 狀態的服務。 ### StatefulSet(有狀態工作負載) - **Pod 身份**:每個 Pod 都有固定的序號與名稱(例如 `mysql-0`、`mysql-1`),不可互換。 - **網路身分**:每個 Pod 都擁有穩定的 DNS 主機名(透過 Headless Service),方便彼此之間互相發現。 - **儲存**:自動為每個 Pod 建立並綁定獨立的 PVC,Pod 刪除後重建仍然能掛載原本的儲存。 - **擴縮與更新**:擴容、滾動更新、縮容都會按序號從低到高、或從高到低依序進行,確保服務有序地可用。 - **使用場景**:資料庫叢集(MySQL、Etcd)、分散式檔案系統(Cassandra)、需保留本地狀態或順序啟動的應用。 ### 核心差異一覽 | 特性 | Deployment | StatefulSet | |--------------------|------------------------|-----------------------------| | Pod 名稱 | 隨機且可互換 | 固定且有序(福利編號) | | 網路身分 | 單一 Service | Headless Service + 固定 DNS | | 儲存行為 | 無狀態/PVC 不綁定 | 每 Pod 獨立 PVC 並保留資料 | | 更新與重建順序 | 無序平行 | 有序依序 | | 適用類型 | 無狀態服務 | 有狀態服務 | --- - **總結**:如果你的應用不需要保留本地狀態、Pod 之間可完全互換,用 **Deployment**; 如果需要固定身份、持久儲存、且需要按序啟動或關閉,用 **StatefulSet**。 <br> <hr> <br> ### Pod 之間可完全互換,是指什麼? - ### gpt-o4-mini-high (2025/05/31) 「Pod 之間可完全互換」指的是在 **無狀態** 的工作負載(如 Deployment)中: 1. **相同規格** 每一個 Pod 都是由同一份 Pod Template 建立,具有完全相同的容器映像、環境變數、資源配置等設定。 2. **無固定身分** 不會有序號編號或專屬的 DNS 名稱;Pod A、Pod B、Pod C 之間沒有「誰是誰」的區別。 3. **無需保留本地資料** 如果某個 Pod 宕機或被刪除,系統只會再根據相同的規格,隨時在任何節點上重建一個新的 Pod,並不會造成服務差異或資料遺失。 4. **統一對外暴露** 多個 Pod 背後會共用同一個 Service,所有流量都由 Service 均衡分發給可用 Pod,而不在乎是分發給哪一個實例。 --- 舉例來說,假設你有一個 Nginx Deployment,副本數為 3: - 它會在集群裡跑出 `nginx-5f8d6f9d6f-abc12`、`nginx-5f8d6f9d6f-def34`、`nginx-5f8d6f9d6f-ghi56` 三個 Pod。 - 每個 Pod 的功能和設定完全一樣,客戶端透過 Service 存取時,也不會感覺到後端到底是連到哪一個 Pod。 - 如果 `nginx-…-def34` 掉了,Deployment 控制器馬上就會再補一個名字一樣且設定相同的 Pod,讓集群持續維持 3 個副本。 這樣的「可互換性」能帶來 **高可用** 與 **彈性擴縮**,但也意味著 Pod 內 **不適合存放必須保留的本地狀態**。 <br> <hr> <br> ### 什麼情境決定使用 Deployment / StatefulSet / DaemonSet ? - ### Question 能舉實際例子:情境 -> 需求/功能 -> 選擇 Deployment or StatefulSet - ### gpt-o4-mini-high (2025/05/31) ### 1. 情境:簡易 Web 伺服器集群 - **需求/功能**: - 幾臺相同規格的 Nginx/Apache 伺服器負載均衡,多個副本之間互換性高。 - 不需在 Pod 內保留任何本地磁碟資料;所有靜態資源可透過後端共用儲存或 CDN 發佈。 - 支援水平擴縮(scale out/in),可隨流量自動增減副本。 - **選擇**: - **Deployment** - **原因**:此情境屬於典型「無狀態」(Stateless)服務,每個 Pod 都是可互換的;即使 Pod 被移除、停機或重建,也不影響整體服務。Deployment 能快速水平擴縮與滾動更新,且與 Service 搭配可輕鬆做流量分散。 ### 2. 情境:MySQL 單主多從(Primary-Replica)資料庫 - **需求/功能**: - 主從節點(或多個節點)各自需要專屬的持久化儲存(每個 Pod 都要掛載自己的 PVC,存放該節點的資料檔)。 - 從屬節點需要先於從一號啟動,再依序啟動從二號、從三號,確保主從複製機制正常。 - Pod 重建時必須保留原本的資料目錄,並以相同的名稱(如 `mysql-0`、`mysql-1`)與對應的 PVC 重新掛載。 - **選擇**: - **StatefulSet** - **原因**:StatefulSet 能確保: 1. Pod 擁有穩定且可預測的名稱(`mysql-0`、`mysql-1`、…),方便主從複製時指定 host。 2. 每個 Pod 自動綁定獨立且持久的 PVC(使用 `volumeClaimTemplates`),當 Pod 刪除重建,資料不會遺失。 3. 滾動更新、擴縮都會按序(ordinal:從低號到高號)逐個處理,確保集群有序可用。 ### 3. 情境:Redis Cluster(帶持久化的快取服務) - **需求/功能**: - Redis 節點需要固定名稱(如 `redis-0`、`redis-1`、`redis-2`)以便互相發現並組成叢集(Cluster)。 - 每個節點要掛載自己的持久化磁碟(AOF 或 RDB 儲存檔),Pod 重啟也要能載入先前資料。 - 節點之間啟動必須有順序,例如先啟三個 master,再啟對應的 slave,以避免叢集不穩定。 - **選擇**: - **StatefulSet** - **原因**:Redis Cluster 屬於「有狀態」(Stateful)服務,需要: 1. 固定且可預測的 DNS 名稱(透過 Headless Service)。 2. 個別 PVC 保留資料。 3. Pod 按序升級/縮減,避免在更新期間 Cluster 拒絕服務。 ### 4. 情境:ElasticSearch 節點叢集 - **需求/功能**: - ElasticSearch 叢集由多個 Data 節點、Master 節點、Client 節點組成,每個節點都需掛載索引資料的持久化儲存。 - 节点名稱(例如 `es-master-0`、`es-data-1`)需固定,以便設定 `cluster.initial_master_nodes` 或持久資料路徑。 - 叢集節點間要按照順序一一啟動或滾動更新,確保叢集健全且不會出現 split-brain。 - **選擇**: - **StatefulSet** - **原因**:ElasticSearch 叢集同樣需要「有序」的 Pod 存在、且每個節點都要有自己的持久化儲存(PVC),StatefulSet 可以滿足上述需求。 ### 5. 情境:Elasticsearch 或 MongoDB 短暫測試環境 - **需求/功能**: - 想快速在開發或測試環境中刻搭一個單節點或多節點的 ElasticSearch/MongoDB 服務,但不在意重建後資料是否保留。 - 僅需一個測試用途的 MongoDB/ES 節點做功能驗證,重啟後資料可以不保留。 - **選擇**: - **Deployment** - **原因**:若只是臨時測試或資料不重要,使用 Deployment 來跑一個無狀態(或僅用 ephemeral-volume)的資料庫實例會較為方便,省去 PVC 綁定、狀態管理的複雜度。 ### 6. 情境:Node Exporter、Fluentd、Prometheus 抓取器(Metrics/Logs 收集) - **需求/功能**: - 在每個節點以 DaemonSet 型態部署收集元件(例:node-exporter、fluentd),並不保留任何本機磁碟資料,輸出結果往外送到遠端伺服器或集群內其他服務。 - 這些 Pod 互相可完全替換,無需固定名稱或順序。 - **選擇**: - **DaemonSet(而非 Deployment/StatefulSet)** - **原因**:這類型的監控或收集元件通常需在每個節點都跑一份(而非僅在部分節點跑);雖然不是 Deployment,但若僅以「是否互換」角度來看,也屬於無狀態、可互換的工作負載。 - **延伸**:倘若只想在特定幾個 Pod 中收集指標,且不需要固定身份,那麼可考慮用 Deployment;若必須在每一台節點都部署,就用 DaemonSet。 ### 7. 情境:Kafka 叢集(分散式消息佇列) - **需求/功能**: - Kafka Broker 需要固定名稱(`kafka-0`、`kafka-1`、`kafka-2`)以便 cluster metadata 管理。 - 每個 Broker 都要自己的持久化儲存(logs、segment files),Pod 需重建後仍能對應回原有資料。 - Broker 在啟動或更新時,需要按序避免一次重啟太多節點,造成叢集不可用。 - **選擇**: - **StatefulSet** - **原因**:以上皆符合 StatefulSet 特性:有序啟動、有固定 DNS 名稱、綁定專屬 PVC。 ### 8. 情境:單純後端 microservice(例如:Auth Service、金鑰管理服務) - **需求/功能**: - 後端微服務本身無需在容器內儲存資料,只與外部資料庫通訊。 - 無需特殊的啟動順序或固定 Pod 名稱;若有多個副本也只是單純分散流量,容錯性高。 - **選擇**: - **Deployment** - **原因**:純計算或 API 類服務,多數都採用無狀態方式,不保留本地快取、也不需要固定身份,用 Deployment 最為直觀。 ### 如何「列舉」與撰寫思路 1. **先歸納「無狀態 vs 有狀態」** - 列出各類常見應用:Web Server、微服務、批次任務等 → 屬於無狀態,可選 Deployment。 - 列出資料庫、分散式儲存、分散式訊息佇列、需保留本地檔案的服務 → 屬於有狀態,可選 StatefulSet。 2. **針對每個應用,思考以下要點** - 是否需要「固定且可預測的 Pod 名稱」? - 是否需要「每個 Pod 專屬且持久的儲存空間(PVC)」? - Pod 重建後,是否必須保留先前資料或身份? - 是否需要有序化(序號化)的滾動更新與縮放? - 是否會與 Service 透過 Headless Service 做 DNS 發現? 3. **範例撰寫格式** """ 情境:…… 需求/功能:…… 選擇:Deployment 或 StatefulSet 原因:…… """ 這樣的結構能清楚傳達你為何要挑 Deployment 或 StatefulSet。 --- 透過上述範例與撰寫思路,希望能幫助你理解「怎麼列舉實際情境」,並在不同需求下決定使用 Deployment 還是 StatefulSet。 <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up