最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

K8s之StatefulSet控制器使用實(shí)例

 更新時(shí)間:2026年04月28日 10:07:47   作者:A-劉晨陽(yáng)  
在Kubernetes實(shí)戰(zhàn)中,StatefulSet控制器用于部署和管理有狀態(tài)應(yīng)用,這些應(yīng)用需要穩(wěn)定的持久化存儲(chǔ)、有序的部署和擴(kuò)展、以及唯一的網(wǎng)絡(luò)標(biāo)識(shí),這篇文章主要介紹了K8s之StatefulSet控制器使用的相關(guān)資料,需要的朋友可以參考下

一、StatefulSet 是什么?

StatefulSet 是 Kubernetes 中專門用于管理有狀態(tài)應(yīng)用(Stateful Applications) 的工作負(fù)載控制器(Controller)。與 Deployment 等無(wú)狀態(tài)控制器不同,StatefulSet 為需要穩(wěn)定身份標(biāo)識(shí)、持久化存儲(chǔ)和有序生命周期管理的分布式系統(tǒng)提供了原生支持。

1.1 什么是有狀態(tài)應(yīng)用(Stateful)?

定義:應(yīng)用的實(shí)例具有獨(dú)特的身份和記憶,依賴本地持久化的數(shù)據(jù)或維護(hù)的上下文狀態(tài),不同實(shí)例處理相同輸入可能產(chǎn)生不同結(jié)果。
簡(jiǎn)單理解:就像一個(gè)有記憶的人,記得過(guò)去發(fā)生的事情,并且這些記憶會(huì)影響他未來(lái)的行為。

核心特征

  • 身份唯一性:每個(gè)實(shí)例有固定 ID,集群中角色不同(主/從/分片)
  • 數(shù)據(jù)持久化:本地存儲(chǔ)包含業(yè)務(wù)數(shù)據(jù)、配置狀態(tài)或會(huì)話信息
  • 拓?fù)涿舾?/strong>:實(shí)例間存在固定的通信關(guān)系(如主從復(fù)制)
  • 生命周期復(fù)雜:擴(kuò)縮容需考慮數(shù)據(jù)重分布,故障恢復(fù)需保證數(shù)據(jù)一致性

典型例子

  • MySQL/PostgreSQL 數(shù)據(jù)庫(kù)(存儲(chǔ)業(yè)務(wù)數(shù)據(jù))
  • Redis/Memcached 緩存(雖然數(shù)據(jù)可重建,但通常視為有狀態(tài))
  • Kafka/RabbitMQ 消息隊(duì)列(消息持久化)
  • ZooKeeper/etcd 協(xié)調(diào)服務(wù)(維護(hù)集群元數(shù)據(jù))
  • Elasticsearch(索引數(shù)據(jù)分片)

1.2 什么是無(wú)狀態(tài)應(yīng)用(Stateless)?

定義:應(yīng)用的每個(gè)實(shí)例都是完全對(duì)等且可互換的,不依賴本地存儲(chǔ)的任何歷史信息或上下文,任何請(qǐng)求都可以由任意實(shí)例處理,結(jié)果完全相同。
簡(jiǎn)單理解:就像一個(gè)"金魚記憶"的人,每3秒都忘記之前發(fā)生的事,每次都是全新的開始。

核心特征

  • 無(wú)本地依賴:不保存會(huì)話、不緩存用戶數(shù)據(jù)、不記錄處理歷史
  • 即拋即用:實(shí)例可以隨時(shí)創(chuàng)建或銷毀,用戶無(wú)感知
  • 水平擴(kuò)展簡(jiǎn)單:增加實(shí)例即可提升性能,無(wú)需數(shù)據(jù)同步
  • 故障自愈快:實(shí)例故障后立即重建,無(wú)需數(shù)據(jù)恢復(fù)

典型例子

  • Nginx/Apache 反向代理(僅轉(zhuǎn)發(fā)請(qǐng)求)
  • REST API 服務(wù)(每次請(qǐng)求攜帶完整認(rèn)證信息)
  • 靜態(tài)資源服務(wù)器
  • 函數(shù)計(jì)算(Serverless)

1.3 關(guān)鍵區(qū)別對(duì)比

維度無(wú)狀態(tài)(Stateless)有狀態(tài)(Stateful)
數(shù)據(jù)存儲(chǔ)不保存數(shù)據(jù),或僅使用臨時(shí)緩存(emptyDir必須持久化數(shù)據(jù)到磁盤(數(shù)據(jù)庫(kù)、日志、配置)
實(shí)例身份無(wú)身份,完全對(duì)等,隨機(jī)命名有唯一固定身份(ID、hostname、角色)
請(qǐng)求處理任意實(shí)例可處理任意請(qǐng)求,結(jié)果一致特定請(qǐng)求必須由特定實(shí)例處理(如分片查詢)
擴(kuò)縮容秒級(jí)擴(kuò)縮容,簡(jiǎn)單增加/減少副本數(shù)需數(shù)據(jù)遷移、重新分片、集群拓?fù)渥兏?/td>
故障影響實(shí)例故障=服務(wù)短暫降級(jí),重建即可實(shí)例故障=可能數(shù)據(jù)丟失,需復(fù)雜恢復(fù)流程
網(wǎng)絡(luò)依賴僅需入口負(fù)載均衡需實(shí)例間直接通信(如復(fù)制、選舉、心跳)
K8s 控制器Deployment、ReplicaSet、DaemonSetStatefulSet、Operator
存儲(chǔ)需求無(wú)需 PVC,或使用共享只讀存儲(chǔ)必須獨(dú)立 PVC,ReadWriteOnce 模式

1.4 StatefulSet 的核心特征

  1. 穩(wěn)定的網(wǎng)絡(luò)標(biāo)識(shí):為每個(gè) Pod 分配唯一、有序的序號(hào)(如 web-0, web-1),并提供基于 DNS 的服務(wù)發(fā)現(xiàn)
  2. 持久化存儲(chǔ)管理:通過(guò) volumeClaimTemplates 自動(dòng)為每個(gè) Pod 創(chuàng)建獨(dú)立的 PVC,實(shí)現(xiàn)存儲(chǔ)與 Pod 生命周期解耦
  3. 有序生命周期管理:嚴(yán)格保證 Pod 的創(chuàng)建、刪除、擴(kuò)縮容和滾動(dòng)更新的順序性
  4. 優(yōu)雅狀態(tài)管理:支持優(yōu)雅終止(Graceful Termination)和啟動(dòng)后鉤子(Post-start),確保狀態(tài)一致性

二、StatefulSet 和 Deployment 的區(qū)別

對(duì)比維度Deployment(無(wú)狀態(tài)應(yīng)用)StatefulSet(有狀態(tài)應(yīng)用)
Pod 名字隨機(jī)生成,如 web-abc123、web-def456
每次重建名字都變
固定序號(hào),如 web-0、web-1、web-2
重建后名字不變
網(wǎng)絡(luò)身份只有 IP 會(huì)變,像個(gè)"流浪漢"
其他 Pod 很難找到它
固定的網(wǎng)絡(luò)標(biāo)識(shí)pod-name.service-name
其他 Pod 總能找到它
數(shù)據(jù)存儲(chǔ)一般不存數(shù)據(jù),或都用共享存儲(chǔ)
Pod 掛了數(shù)據(jù)丟了無(wú)所謂
每人一個(gè)獨(dú)立存儲(chǔ)空間
Pod 掛了數(shù)據(jù)還在,重建后自動(dòng)掛載
啟動(dòng)順序大家一起上,誰(shuí)先啟動(dòng)都行
像餐廳所有窗口同時(shí)開
排隊(duì)啟動(dòng):0號(hào)先上,準(zhǔn)備好后1號(hào)再上
像銀行柜臺(tái)一個(gè)一個(gè)開
關(guān)閉順序隨便關(guān),關(guān)哪個(gè)都行從后往前關(guān):最后一個(gè)先關(guān),依次往前
保證主節(jié)點(diǎn)最后退出
擴(kuò)縮容想擴(kuò)就擴(kuò),想縮就縮
新 Pod 和老 Pod 沒區(qū)別
按序號(hào)擴(kuò)縮:擴(kuò)容從下一個(gè)序號(hào)開始
縮容從最大序號(hào)開始刪
更新方式可以一次性全更新
或者滾動(dòng)更新,順序無(wú)所謂
從后往前更新
支持暫停在某個(gè)版本(partition)
適用場(chǎng)景Web服務(wù)、API網(wǎng)關(guān)
前端應(yīng)用、計(jì)算任務(wù)
數(shù)據(jù)庫(kù)(MySQL、Redis)
消息隊(duì)列(Kafka、ZooKeeper)

2.1 詳解:Pod 身份與網(wǎng)絡(luò)標(biāo)識(shí)

特性DeploymentStatefulSet
Pod 命名規(guī)則隨機(jī)哈希后綴
nginx-7564c8f6b4-9xv5r
固定有序序號(hào)
web-0, web-1, web-2
Hostname 穩(wěn)定性每次重建都變化永久固定,與序號(hào)綁定
DNS 解析通過(guò) Service 解析到隨機(jī) Pod IP支持直接 Pod DNS 解析
<pod-name>.<service-name>.<namespace>.svc.cluster.local
Headless Service可選,通常不需要必須,用于提供穩(wěn)定網(wǎng)絡(luò)標(biāo)識(shí)
網(wǎng)絡(luò)身份示例無(wú)固定身份mysql-0.mysql.default.svc.cluster.local 始終指向 mysql-0

關(guān)鍵差異說(shuō)明

  • Deployment:Service 通過(guò) ClusterIP 做負(fù)載均衡,請(qǐng)求隨機(jī)分發(fā)到后端 Pod,Pod 重建后 IP 和名稱都變
  • StatefulSet:必須配合 clusterIP: None 的 Headless Service,DNS 直接解析到 Pod IP,且 Pod 重建后 DNS 記錄保持不變

2.2 詳解:存儲(chǔ)與數(shù)據(jù)管理

特性DeploymentStatefulSet
存儲(chǔ)定義方式在 Pod 模板中直接定義 volumes 或引用現(xiàn)有 PVC使用 volumeClaimTemplates 動(dòng)態(tài)為每個(gè) Pod 創(chuàng)建獨(dú)立 PVC
PVC 與 Pod 關(guān)系多個(gè) Pod 可共享同一個(gè) PVC(需支持多掛載)
或每個(gè) Pod 手動(dòng)掛載相同 PVC
每個(gè) Pod 獨(dú)占一個(gè) PVC,一對(duì)一綁定,命名規(guī)則:<pvc-name>-<statefulset-name>-<ordinal>
數(shù)據(jù)持久性Pod 刪除,數(shù)據(jù)可能丟失(取決于卷類型)Pod 刪除,PVC 保留,數(shù)據(jù)持久化;新 Pod 自動(dòng)掛載原 PVC
存儲(chǔ)擴(kuò)容需手動(dòng)修改 PVC需手動(dòng)修改 PVC,或依賴 StorageClass 支持在線擴(kuò)容
數(shù)據(jù)隔離性低(共享存儲(chǔ))或手動(dòng)管理高(自動(dòng)隔離,每個(gè) Pod 獨(dú)立存儲(chǔ))

存儲(chǔ)綁定示例

# StatefulSet 會(huì)自動(dòng)創(chuàng)建:
# PVC: disk-ssd-web-0 → PV: pv-001 (綁定)
# PVC: disk-ssd-web-1 → PV: pv-002 (綁定)
# 即使 web-0 被刪除重建,disk-ssd-web-0 仍會(huì)重新掛載到原 PV

2.3 詳解:部署與擴(kuò)縮容行為

操作DeploymentStatefulSet
創(chuàng)建順序并行創(chuàng)建,所有 Pod 同時(shí)啟動(dòng)串行創(chuàng)建,按序號(hào) 0→1→2→…,前一個(gè) Ready 后才創(chuàng)建下一個(gè)
擴(kuò)容行為并行擴(kuò)容,新 Pod 立即創(chuàng)建按序號(hào)遞增順序創(chuàng)建,保證集群拓?fù)渲鸩綌U(kuò)展
縮容行為隨機(jī)刪除 Pod按序號(hào)遞減刪除(先刪 N-1,再刪 N-2…),保證有序縮減
滾動(dòng)更新隨機(jī)替換,可設(shè)置 maxSurge/maxUnavailable逆序替換(先更新 N-1,最后更新 0),可設(shè)置 partition 進(jìn)行灰度發(fā)布
更新策略RollingUpdate(默認(rèn))、RecreateRollingUpdate(默認(rèn))、OnDelete(手動(dòng)刪除后重建)

有序性意義

  • 主從架構(gòu):先啟動(dòng)主節(jié)點(diǎn)(0),再啟動(dòng)從節(jié)點(diǎn)(1,2…),避免從節(jié)點(diǎn)找不到主而崩潰
  • 數(shù)據(jù)安全:縮容時(shí)先移除高序號(hào)節(jié)點(diǎn),避免破壞集群的法定人數(shù)(Quorum)
  • 灰度發(fā)布:通過(guò) partition 控制只更新部分節(jié)點(diǎn),如 partition: 2 表示只更新序號(hào) ≥2 的 Pod

2.4 運(yùn)維與故障處理對(duì)比

場(chǎng)景DeploymentStatefulSet
Pod 故障重建立即創(chuàng)建新 Pod,隨機(jī)命名,無(wú)狀態(tài)恢復(fù)按原序號(hào)重建,掛載原 PVC,自動(dòng)恢復(fù)數(shù)據(jù)和身份
節(jié)點(diǎn)遷移快速調(diào)度到新節(jié)點(diǎn)需等待原 PVC 在目標(biāo)節(jié)點(diǎn)可用(依賴存儲(chǔ)拓?fù)洌?/td>
版本回滾kubectl rollout undo 快速回滾需手動(dòng)控制,逆序回滾,需關(guān)注數(shù)據(jù)兼容性
數(shù)據(jù)備份通常無(wú)需備份 Pod 級(jí)數(shù)據(jù)必須制定備份策略,PVC 獨(dú)立存在需單獨(dú)管理
監(jiān)控重點(diǎn)整體吞吐量、錯(cuò)誤率單節(jié)點(diǎn)狀態(tài)、存儲(chǔ)容量、復(fù)制延遲、集群拓?fù)渫暾?/td>

三、StatefulSet 的使用 - 實(shí)例

部署一個(gè)Nginx StatefulSet

  • 先創(chuàng)建一個(gè)nginx的namespace
kubectl create ns nginx

3.1 檢查是否有 storageclass 資源

kubectl get storageclass -A

如果有資源(任何都行,只要不提示No resources found就行),在 nginx-StatefulSet.yaml中的storageClassName請(qǐng)?zhí)顚懗捎械?,如果沒有,可按照如下添加storageclass

可地址直接安裝:kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml

如果地址拉取不到可使用如下:

  • vi local-path-storage.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: local-path-storage

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: local-path-provisioner-service-account
  namespace: local-path-storage

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: local-path-provisioner-role
  namespace: local-path-storage
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch", "create", "patch", "update", "delete"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: local-path-provisioner-role
rules:
  - apiGroups: [""]
    resources: ["nodes", "persistentvolumeclaims", "configmaps", "pods", "pods/log"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "patch", "update", "delete"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "patch"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: local-path-provisioner-bind
  namespace: local-path-storage
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: local-path-provisioner-role
subjects:
  - kind: ServiceAccount
    name: local-path-provisioner-service-account
    namespace: local-path-storage

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: local-path-provisioner-bind
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: local-path-provisioner-role
subjects:
  - kind: ServiceAccount
    name: local-path-provisioner-service-account
    namespace: local-path-storage

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: local-path-provisioner
  namespace: local-path-storage
spec:
  replicas: 1
  selector:
    matchLabels:
      app: local-path-provisioner
  template:
    metadata:
      labels:
        app: local-path-provisioner
    spec:
      serviceAccountName: local-path-provisioner-service-account
      containers:
        - name: local-path-provisioner
          image: rancher/local-path-provisioner:v0.0.35
          imagePullPolicy: IfNotPresent
          command:
            - local-path-provisioner
            - --debug
            - start
            - --config
            - /etc/config/config.json
          volumeMounts:
            - name: config-volume
              mountPath: /etc/config/
          env:
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: CONFIG_MOUNT_PATH
              value: /etc/config/
      volumes:
        - name: config-volume
          configMap:
            name: local-path-config

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-path
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: local-path-config
  namespace: local-path-storage
data:
  config.json: |-
    {
            "nodePathMap":[
            {
                    "node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",
                    "paths":["/opt/local-path-provisioner"]
            }
            ]
    }
  setup: |-
    #!/bin/sh
    set -eu
    mkdir -m 0777 -p "$VOL_DIR"
  teardown: |-
    #!/bin/sh
    set -eu
    rm -rf "$VOL_DIR"
  helperPod.yaml: |-
    apiVersion: v1
    kind: Pod
    metadata:
      name: helper-pod
    spec:
      priorityClassName: system-node-critical
      tolerations:
        - key: node.kubernetes.io/disk-pressure
          operator: Exists
          effect: NoSchedule
      containers:
      - name: helper-pod
        image: busybox
        imagePullPolicy: IfNotPresent

在進(jìn)行創(chuàng)建

kubectl apply -f local-path-storage.yaml

查看是否創(chuàng)建成功

kubectl get storageclass

看到如下內(nèi)容即可

3.2 創(chuàng)建Headless Service

Headless Service(clusterIP: None)會(huì)為每個(gè) Pod 創(chuàng)建獨(dú)立的 DNS 記錄:

  • vi nginx-Headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: nginx
  labels:
    app: nginx
spec:
  type: ClusterIP
  selector:
    app: nginx
  clusterIP: None
  sessionAffinity: None
  ports:
    - name: web
      port: 80
      protocol: TCP

3.3 創(chuàng)建StatefulSet

  • vi nginx-StatefulSet.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
  namespace: nginx
spec:
  serviceName: nginx
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      initContainers:
      - name: init-html
        image: busybox
        command: 
          - sh
          - -c
          - |
            # 檢查是否已初始化
            if [ ! -f /mnt/html/.initialized ]; then
              echo "First boot - creating initial content"
              echo "Welcome to nginx - $(hostname) - $(date)" > /mnt/html/index.html
              echo "This is a test page" >> /mnt/html/index.html
              touch /mnt/html/.initialized  # 創(chuàng)建標(biāo)記文件
            else
              echo "Already initialized, keeping existing content"
            fi
        volumeMounts:
        - name: www
          mountPath: /mnt/html
      containers:
      - name: nginx
        image: nginx:1.24
        imagePullPolicy: IfNotPresent
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
        livenessProbe:
          initialDelaySeconds: 10
          periodSeconds: 10
          tcpSocket:
            port: 80
        readinessProbe:
          initialDelaySeconds: 10
          periodSeconds: 10
          httpGet:
            path: /
            port: 80
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "local-path"  # 根據(jù)storageclass集群修改
      resources:
        requests:
          storage: 1Gi

3.4 使用StatefulSet部署nginx服務(wù)

  • 部署nginx Headless Service
kubectl apply -f nginx-Headless.yaml
  • 查看是否創(chuàng)建成功
kubectl get svc -n nginx

  • 部署nginx StatefulSet
kubectl apply -f nginx-StatefulSet.yaml
  • 查看是否創(chuàng)建成功
# 查看nginx pvc
kubectl get pvc -n nginx -w
# 查看nginx pod
kubectl get pod -n nginx -w
# 查看nginx StatefulSet
kubectl get sts -n nginx -o wide

3.5 驗(yàn)證StatefulSet特性

創(chuàng)建完成后,可以觀察到以下現(xiàn)象:

  1. Pod有序創(chuàng)建
[root@k8s-master StatefulSet]# kubectl  get pods -n nginx -o wide
NAME      READY   STATUS    RESTARTS   AGE     IP                NODE        NOMINATED NODE   READINESS GATES
nginx-0   1/1     Running   0          3m37s   192.168.36.94     k8s-node1   <none>           <none>
nginx-1   1/1     Running   0          3m19s   192.168.36.99     k8s-node1   <none>           <none>
nginx-2   1/1     Running   0          3m      192.168.169.143   k8s-node2   <none>           <none>
  1. 穩(wěn)定的網(wǎng)絡(luò)標(biāo)識(shí)
[root@k8s-master StatefulSet]# kubectl exec -n nginx nginx-0 -- hostname
nginx-0
# 通過(guò)DNS解析訪問(wèn)(這里需要注意,指定nginx部署的ns,要不然會(huì)報(bào)無(wú)法解析)
[root@k8s-master StatefulSet]# kubectl run -it --rm busybox --image=busybox:1.28 --restart=Never -n nginx -- nslookup nginx-0.nginx 2>/dev/null || echo "測(cè)試失敗"
Server:    10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local
Name:      nginx-0.nginx
Address 1: 192.168.36.94 nginx-0.nginx.nginx.svc.cluster.local
  1. 獨(dú)立的持久化存儲(chǔ)
# 查看自動(dòng)創(chuàng)建的PVC
[root@k8s-master StatefulSet]# kubectl get pvc -n nginx
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-nginx-0   Bound    pvc-67c250d5-3e78-4c69-a4ad-2bfacf84c54b   1Gi        RWO            local-path     5d
www-nginx-1   Bound    pvc-13f90069-60b5-4c93-86c3-76e1377b5098   1Gi        RWO            local-path     5d
www-nginx-2   Bound    pvc-2ba2e9e5-5794-4b6e-af5b-b940ccb414e1   1Gi        RWO            local-path     5d
  1. Pod重建后保持?jǐn)?shù)據(jù)
# 查看nginx-0 默認(rèn)的index.html數(shù)據(jù)
kubectl exec -n nginx nginx-0 -- bash -c "cat /usr/share/nginx/html/index.html"
# 在nginx-0中寫入數(shù)據(jù)
kubectl exec -n nginx nginx-0 -- bash -c 'echo "Hello Nginx, Im's nginx-0 pod !!! " > /usr/share/nginx/html/index.html'
# 查看nginx-0 修改后的index.html數(shù)據(jù)
kubectl exec -n nginx nginx-0 -- bash -c "cat /usr/share/nginx/html/index.html"
# 刪除nginx-0
kubectl delete pods -n nginx nginx-0
# StatefulSet會(huì)自動(dòng)重建,查看nginx-o pod是否重建
kubectl get pods -n nginx -w
# 重建成功再次查看nginx-0 pod容器里index.html里的內(nèi)容
kubectl exec -n nginx nginx-0 -- bash -c "cat /usr/share/nginx/html/index.html"

注意:如果數(shù)據(jù)被覆蓋為最初的數(shù)據(jù)了,可能是因?yàn)閯?chuàng)建pod的時(shí)候會(huì)直接寫入默認(rèn)的配置,導(dǎo)致把后來(lái)修改的數(shù)據(jù)重寫了。
這里我在創(chuàng)建nginx-StatefulSet的時(shí)候是先手動(dòng)添加數(shù)據(jù)了,因?yàn)槟J(rèn)沒有index.html,會(huì)導(dǎo)致啟動(dòng)失敗,所以需要先寫入數(shù)據(jù)才可以;并且加了個(gè)判斷,如果存在這個(gè)文件那么就不會(huì)寫入數(shù)據(jù),這樣就不會(huì)在重建pod的時(shí)候數(shù)據(jù)重寫了。

四、StatefulSet的更新策略

StatefulSet支持兩種更新策略,通過(guò)spec.updateStrategy.type 字段控制:

策略類型行為適用場(chǎng)景
RollingUpdate (默認(rèn))按順序從后向前滾動(dòng)更新 Pod? 大多數(shù)場(chǎng)景
OnDelete手動(dòng)刪除 Pod 后才更新?? 需要完全控制更新時(shí)機(jī)的場(chǎng)景

4.1 RollingUpdate 策略(默認(rèn))

4.1.1 基本更新寫法

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
spec:
  updateStrategy:
    type: RollingUpdate  # 默認(rèn)值,可不寫
  # ... 其他配置

更新順序

  1. 序號(hào)最大的 Pod 開始更新(從后向前)
  2. 依次向前推進(jìn)(nginx-2 → nginx-1 → nginx-0)
  3. 每個(gè) Pod 更新成功并進(jìn)入 Ready 狀態(tài)后,才更新下一個(gè)

為什么從后往前?

  • 保證主節(jié)點(diǎn)(通常是序號(hào)0)最后更新
  • 對(duì)于主從架構(gòu)的應(yīng)用,先更新從節(jié)點(diǎn),最后更新主節(jié)點(diǎn)
  • 減少對(duì)服務(wù)的影響

4.1.2 分區(qū)更新(Partition)-重要特性

RollingUpdate 支持 partition 參數(shù),可以控制更新的范圍

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 2  # 只更新序號(hào) >= 2 的 Pod
  # ... 其他配置

分區(qū)規(guī)則

  • 序號(hào) >= partition 的 Pod 會(huì)被更新
  • 序號(hào) < partition 的 Pod 保持舊版本

4.1.3 分區(qū)更新實(shí)例:

假設(shè)有 3 個(gè)副本:nginx-0, nginx-1, nginx-2

partition 值哪些 Pod 被更新哪些 Pod 保持不變
partition: 0nginx-2, nginx-1, nginx-0 (全部)無(wú)
partition: 1nginx-2, nginx-1nginx-0
partition: 2nginx-2nginx-0, nginx-1
partition: 3無(wú)nginx-0, nginx-1, nginx-2 (全部)
  • 場(chǎng)景1:金絲雀發(fā)布(Canary Release)
# 第一步:只更新最后一個(gè) Pod 做測(cè)試
updateStrategy:
  type: RollingUpdate
  rollingUpdate:
    partition: 2  # 只更新 nginx-2

測(cè)試 nginx-2 沒問(wèn)題后,更新其他所有的pod:

# 第二步:更新所有 Pod
updateStrategy:
  type: RollingUpdate
  rollingUpdate:
    partition: 0  # 更新全部
  • 場(chǎng)景2:維護(hù)主節(jié)點(diǎn)不更新
# 主節(jié)點(diǎn)是 nginx-0,保持不更新
updateStrategy:
  type: RollingUpdate
  rollingUpdate:
    partition: 1  # 只更新 nginx-1, nginx-2
  • 場(chǎng)景3:分批發(fā)布
# 第1批:更新 30%(最后一個(gè))更新完需測(cè)試
partition: 2

# 第2批:更新 60%(后兩個(gè))更新完需測(cè)試
partition: 1

# 第3批:更新 100%       更新完需測(cè)試
partition: 0

4.2 OnDelete 策略(手動(dòng)觸發(fā))

  • OnDelete 策略寫法
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
spec:
  updateStrategy:
    type: OnDelete  # 手動(dòng)模式
  # ... 其他配置
  • 行為特點(diǎn)
  1. K8s 不會(huì)自動(dòng)更新任何 Pod
  2. 只有當(dāng)你手動(dòng)刪除 Pod 時(shí),重建的 Pod 才會(huì)使用新配置
  3. 你可以控制每個(gè) Pod 的更新時(shí)機(jī)
  • 適用場(chǎng)景
  • 數(shù)據(jù)庫(kù)版本升級(jí):需要逐個(gè)節(jié)點(diǎn)手動(dòng)操作,確保數(shù)據(jù)同步
  • 核心業(yè)務(wù):需要在業(yè)務(wù)低峰期逐個(gè)更新
  • 需要手動(dòng)驗(yàn)證:每個(gè)節(jié)點(diǎn)更新后都要手動(dòng)驗(yàn)證
  • 配合外部工具:與 Ansible、Jenkins 等工具集成
  • 實(shí)際操作示例
# 1. 修改 StatefulSet 鏡像版本(但不會(huì)立即生效)
kubectl patch sts -n nginx nginx -p '{"spec":{"template":{"spec":{"containers":[{"name":"nginx","image":"nginx:1.25"}]}}}}'

# 2. 手動(dòng)刪除要更新的 Pod
kubectl delete pod -n nginx nginx-2  # 先更新最后一個(gè)
## 更新完成查看版本號(hào),確認(rèn)是否更新成功
kubectl exec -n nginx nginx-2 -- nginx -v

# 3. 驗(yàn)證 nginx-2 沒問(wèn)題后
kubectl delete pod -n nginx nginx-1  # 更新中間
## 更新完成查看版本號(hào),確認(rèn)是否更新成功
kubectl exec -n nginx nginx-2 -- nginx -v

# 4. 最后更新主節(jié)點(diǎn)
kubectl delete pod -n nginx nginx-0
## 更新完成查看版本號(hào),確認(rèn)是否更新成功
kubectl exec -n nginx nginx-2 -- nginx -v

  • 控制器不會(huì)自動(dòng)更新Pod
  • 需要手動(dòng)刪除Pod才能觸發(fā)重建更新
  • 適用于需要完全控制更新時(shí)機(jī)的場(chǎng)景,如核心應(yīng)用的流量無(wú)損升級(jí)

4.3 更新策略對(duì)比

特性RollingUpdateOnDelete
自動(dòng)更新? 是? 否
更新順序從后往前由你控制
分區(qū)控制? 支持 (partition)? 不支持
回滾方式重新設(shè)置 image 或 partition手動(dòng)刪除重建
適用場(chǎng)景Web服務(wù)、緩存、一般應(yīng)用數(shù)據(jù)庫(kù)、核心應(yīng)用、特殊需求

4.4 更新策略選擇建議

  • 選擇 RollingUpdate 當(dāng):
    ? 應(yīng)用無(wú)狀態(tài)或能優(yōu)雅處理滾動(dòng)重啟
    ? 想要自動(dòng)化更新
    ? 需要金絲雀發(fā)布(配合 partition)
    ? 更新風(fēng)險(xiǎn)較低

  • 選擇 OnDelete 當(dāng):
    ? 數(shù)據(jù)庫(kù)等有狀態(tài)核心應(yīng)用
    ? 需要手動(dòng)干預(yù)每個(gè)節(jié)點(diǎn)的更新
    ? 更新風(fēng)險(xiǎn)高,需要逐個(gè)驗(yàn)證
    ? 有外部編排工具(Ansible、Operator)

五、StatefulSet vs. Deployment:如何選擇?

特性StatefulSetDeployment
Pod命名固定有序名稱(xxx-0, xxx-1)隨機(jī)名稱(xxx-隨機(jī)字符串)
網(wǎng)絡(luò)標(biāo)識(shí)穩(wěn)定,Pod重建不變變化,每次重建新IP
存儲(chǔ)支持PVC模板,持久化存儲(chǔ)通常使用共享存儲(chǔ)或臨時(shí)存儲(chǔ)
順序控制有序部署、更新、刪除并行操作
適用場(chǎng)景數(shù)據(jù)庫(kù)、消息隊(duì)列、有狀態(tài)服務(wù)Web服務(wù)、API網(wǎng)關(guān)、無(wú)狀態(tài)應(yīng)用

選擇建議

  • 應(yīng)用需要穩(wěn)定的網(wǎng)絡(luò)標(biāo)識(shí) → 選擇StatefulSet
  • 應(yīng)用需要獨(dú)立的持久化存儲(chǔ) → 選擇StatefulSet
  • 應(yīng)用要求有序的部署和更新 → 選擇StatefulSet
  • 否則,優(yōu)先考慮Deployment或ReplicaSet

六、注意事項(xiàng)

  1. 數(shù)據(jù)安全:StatefulSet刪除時(shí)不會(huì)自動(dòng)刪除PVC,需手動(dòng)清理不再需要的存儲(chǔ)卷,避免資源浪費(fèi)

  2. Headless Service必須:StatefulSet必須關(guān)聯(lián)Headless Service才能保證網(wǎng)絡(luò)標(biāo)識(shí)的穩(wěn)定性

  3. 存儲(chǔ)類選擇:根據(jù)性能需求選擇合適的StorageClass,生產(chǎn)環(huán)境推薦使用SSD或高性能云盤

  4. 備份策略:雖然StatefulSet保證了Pod重建后的數(shù)據(jù)持久性,但仍需建立定期備份機(jī)制,防止數(shù)據(jù)損壞或誤刪除

  5. 縮容謹(jǐn)慎:縮容StatefulSet會(huì)導(dǎo)致Pod被刪除,但PVC保留。如果希望徹底清理,需要手動(dòng)刪除對(duì)應(yīng)的PVC

七、總結(jié)

StatefulSet是Kubernetes中管理有狀態(tài)應(yīng)用的核心控制器,通過(guò)穩(wěn)定的網(wǎng)絡(luò)標(biāo)識(shí)、獨(dú)立的持久化存儲(chǔ)有序的生命周期管理,為數(shù)據(jù)庫(kù)、消息隊(duì)列等有狀態(tài)應(yīng)用提供了完善的運(yùn)行環(huán)境。掌握StatefulSet的使用,意味著你能夠?qū)⒏嗟膫鹘y(tǒng)應(yīng)用平滑地遷移到Kubernetes平臺(tái),充分發(fā)揮容器編排的優(yōu)勢(shì)。

在實(shí)際應(yīng)用中,需要根據(jù)業(yè)務(wù)需求合理選擇更新策略和Pod管理策略,同時(shí)注意數(shù)據(jù)安全和備份,才能構(gòu)建出穩(wěn)定可靠的有狀態(tài)應(yīng)用系統(tǒng)。

到此這篇關(guān)于K8s之StatefulSet控制器的文章就介紹到這了,更多相關(guān)K8s之StatefulSet控制器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • K8s內(nèi)存溢出問(wèn)題剖析之排查與解決過(guò)程

    K8s內(nèi)存溢出問(wèn)題剖析之排查與解決過(guò)程

    這篇文章主要介紹了K8s內(nèi)存溢出問(wèn)題剖析之排查與解決過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-07-07
  • K8S部署lnmp項(xiàng)目全過(guò)程

    K8S部署lnmp項(xiàng)目全過(guò)程

    這篇文章主要介紹了K8S部署lnmp項(xiàng)目全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • k8s?series初級(jí)calico使用介紹

    k8s?series初級(jí)calico使用介紹

    這篇文章主要為大家介紹了k8s?series初級(jí)calico使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 云服務(wù)器Jenkins部署Springboot項(xiàng)目及Vue項(xiàng)目的詳細(xì)過(guò)程

    云服務(wù)器Jenkins部署Springboot項(xiàng)目及Vue項(xiàng)目的詳細(xì)過(guò)程

    本文詳細(xì)介紹了如何在云服務(wù)器上使用Jenkins部署Springboot和Vue項(xiàng)目,包括創(chuàng)建Springboot項(xiàng)目并上傳到Git倉(cāng)庫(kù)、安裝Maven和配置Maven插件、安裝Gitee插件、配置Jenkins任務(wù)以及創(chuàng)建自由風(fēng)格項(xiàng)目等步驟,感興趣的朋友一起看看吧
    2025-02-02
  • 新版k8s拉取鏡像失敗問(wèn)題解決辦法

    新版k8s拉取鏡像失敗問(wèn)題解決辦法

    隨著Kubernetes?1.23版本的發(fā)布,Docker作為默認(rèn)容器運(yùn)行時(shí)被棄用,轉(zhuǎn)而默認(rèn)采用Containerd,這一改變意味著用戶在使用Kubernetes時(shí),將不再通過(guò)Docker來(lái)拉取鏡像,文中jiang,需要的朋友可以參考下
    2024-10-10
  • k8s平臺(tái)本地?cái)?shù)據(jù)遷移整改過(guò)程

    k8s平臺(tái)本地?cái)?shù)據(jù)遷移整改過(guò)程

    文章主要介紹了對(duì)k8s平臺(tái)默認(rèn)數(shù)據(jù)存儲(chǔ)位置進(jìn)行優(yōu)化,將數(shù)據(jù)統(tǒng)一管理并存至指定目錄和云磁盤的整個(gè)過(guò)程,包括新磁盤的創(chuàng)建掛載、配置更改生效、環(huán)境檢查、清理舊環(huán)境等步驟,強(qiáng)調(diào)在集群所有節(jié)點(diǎn)上進(jìn)行優(yōu)化,并提醒配置更改生效后建議重啟機(jī)器以確保變更生效
    2026-05-05
  • k8s中容器創(chuàng)建的全過(guò)程實(shí)踐

    k8s中容器創(chuàng)建的全過(guò)程實(shí)踐

    這篇文章主要介紹了k8s中容器創(chuàng)建的全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-07-07
  • k8s的架構(gòu)組成操作代碼

    k8s的架構(gòu)組成操作代碼

    k8s是一個(gè)輕便的和可擴(kuò)展的開源平臺(tái),用于管理容器化應(yīng)用和服務(wù),通過(guò)k8s能夠進(jìn)行應(yīng)用的自動(dòng)化部署和擴(kuò)縮容,這篇文章主要介紹了k8s的架構(gòu)組成,需要的朋友可以參考下
    2024-05-05
  • Rainbond云原生部署SpringCloud應(yīng)用架構(gòu)實(shí)踐

    Rainbond云原生部署SpringCloud應(yīng)用架構(gòu)實(shí)踐

    這篇文章主要為大家介紹了Rainbond云原生部署SpringCloud應(yīng)用架構(gòu)實(shí)踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-04-04
  • 教你在k8s上部署HADOOP-3.2.2(HDFS)的方法

    教你在k8s上部署HADOOP-3.2.2(HDFS)的方法

    這篇文章主要介紹了k8s-部署HADOOP-3.2.2(HDFS)的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04

最新評(píng)論

德阳市| 东乡| 澄迈县| 双柏县| 鄂托克前旗| 漾濞| 渭南市| 辽中县| 石河子市| 正阳县| 务川| 灌阳县| 南皮县| 堆龙德庆县| 石屏县| 方正县| 米脂县| 临邑县| 海口市| 奇台县| 田阳县| 手游| 汉阴县| 聊城市| 康马县| 邮箱| 云和县| 泰和县| 拉萨市| 滨海县| 隆昌县| 慈溪市| 宁波市| 崇阳县| 桂林市| 聂荣县| 灵山县| 安陆市| 麻江县| 大安市| 安图县|