国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Kubernetes存儲管理功能的落地實踐

馬哥Linux運維 ? 來源:馬哥Linux運維 ? 2026-02-26 14:45 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

Kubernetes存儲管理:PV、PVC與StorageClass

一、概述

1.1 背景介紹

容器本身是無狀態的,Pod重啟后容器內的數據全部丟失。數據庫、消息隊列、文件存儲這類有狀態服務跑在K8s上,必須解決持久化存儲問題。Kubernetes通過PersistentVolume(PV)、PersistentVolumeClaim(PVC)和StorageClass三層抽象來管理存儲。

實際生產中踩過的坑:開發團隊直接在Pod里用hostPath掛載宿主機目錄,Pod漂移到其他節點后數據就丟了。還有團隊手動創建了100個PV,每次擴容都要運維手動操作,效率極低。StorageClass的動態供給機制就是解決這個問題的。

本文覆蓋靜態供給、動態供給、本地存儲、NFS、Ceph RBD等常見存儲方案,基于Kubernetes 1.28.x版本。

1.2 技術特點

存儲與計算解耦:PV是集群級別的存儲資源,PVC是用戶對存儲的申請,兩者通過綁定關系關聯,Pod只需要引用PVC

動態供給:StorageClass配合Provisioner自動創建PV,無需運維手動干預

訪問模式控制:ReadWriteOnce(單節點讀寫)、ReadOnlyMany(多節點只讀)、ReadWriteMany(多節點讀寫),不同存儲后端支持的模式不同

回收策略:Retain(保留數據)、Delete(刪除數據)、Recycle(已廢棄),控制PVC刪除后PV的處理方式

1.3 適用場景

場景一:數據庫(MySQL、PostgreSQL)持久化存儲,要求高IOPS和數據安全

場景二:日志、文件上傳等共享存儲,多個Pod需要同時讀寫同一份數據

場景三:AI訓練數據集存儲,大容量、高吞吐量讀取

場景四:StatefulSet有狀態應用,每個Pod需要獨立的持久化卷

1.4 環境要求

組件 版本要求 說明
Kubernetes 1.24+ CSI驅動在1.13 GA,本文使用1.28
NFS Server NFSv4 共享存儲方案,需要獨立NFS服務器
Ceph 16.x+ (Pacific) 分布式存儲方案,生產推薦
nfs-subdir-external-provisioner 4.0+ NFS動態供給控制器
ceph-csi 3.9+ Ceph CSI驅動
存儲節點磁盤 SSD/HDD按需 數據庫用SSD,歸檔用HDD

二、詳細步驟

2.1 準備工作

2.1.1 存儲基礎概念

PV、PVC、StorageClass的關系:

用戶視角:Pod → PVC(我需要10Gi存儲)
        ↓ 綁定
管理員視角:  PV(這塊10Gi的存儲可以用)
        ↑ 創建
自動化視角:  StorageClass + Provisioner(自動創建PV)
# 查看集群現有的StorageClass
kubectl get sc

# 查看PV和PVC
kubectl get pv
kubectl get pvc -A

# 查看CSI驅動
kubectl get csidrivers

2.1.2 存儲方案選型

存儲方案 訪問模式 性能 適用場景 運維復雜度
hostPath RWO 高(本地磁盤) 測試環境,單節點
Local PV RWO 高(本地SSD) 數據庫,對IO敏感
NFS RWO/ROX/RWX 共享文件存儲
Ceph RBD RWO 數據庫,塊存儲
CephFS RWO/ROX/RWX 中高 共享文件存儲
云廠商EBS/云盤 RWO 云環境數據庫
Longhorn RWO/RWX 輕量級分布式存儲

2.1.3 搭建NFS服務器

NFS是最簡單的共享存儲方案,適合中小規模集群:

# NFS服務器(192.168.1.50)上執行
apt-get install -y nfs-kernel-server

# 創建共享目錄
mkdir -p /data/nfs/k8s
chown nobody:nogroup /data/nfs/k8s
chmod 755 /data/nfs/k8s

# 配置NFS導出
cat > /etc/exports <

K8s所有Worker節點安裝NFS客戶端:

# Ubuntu
apt-get install -y nfs-common

# CentOS
yum install -y nfs-utils

# 驗證能掛載
mount -t nfs 192.168.1.50:/data/nfs/k8s /mnt
ls /mnt
umount /mnt

注意:no_root_squash允許客戶端以root身份寫入,生產環境如果安全要求高,改為root_squash并通過initContainer設置目錄權限。

2.2 核心配置

2.2.1 靜態PV/PVC(手動創建)

適合存儲資源固定、數量少的場景:

# 文件:nfs-pv-static.yaml
apiVersion:v1
kind:PersistentVolume
metadata:
name:nfs-pv-data-01
labels:
 type:nfs
 env:production
spec:
capacity:
 storage:50Gi
accessModes:
 -ReadWriteMany
persistentVolumeReclaimPolicy:Retain
storageClassName:""
nfs:
 server:192.168.1.50
 path:/data/nfs/k8s/data-01
---
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:app-data-pvc
namespace:production
spec:
accessModes:
 -ReadWriteMany
resources:
 requests:
  storage:50Gi
storageClassName:""
selector:
 matchLabels:
  type:nfs
  env:production
# 先在NFS服務器上創建目錄
mkdir -p /data/nfs/k8s/data-01

# 創建PV和PVC
kubectl apply -f nfs-pv-static.yaml

# 驗證綁定狀態
kubectl get pv nfs-pv-data-01
# STATUS應該是Bound

kubectl get pvc app-data-pvc -n production
# STATUS應該是Bound

注意:靜態PV的storageClassName設為空字符串"",PVC也要設為空字符串,這樣PVC只會綁定沒有StorageClass的PV。如果不設置這個字段,PVC會嘗試使用默認StorageClass進行動態供給。

2.2.2 NFS動態供給(StorageClass)

安裝nfs-subdir-external-provisioner,實現NFS的動態PV創建:

# 使用Helm安裝
helm repo add nfs-subdir-external-provisioner 
 https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

helm install nfs-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner 
 --namespace kube-system 
 --setnfs.server=192.168.1.50 
 --setnfs.path=/data/nfs/k8s 
 --setstorageClass.name=nfs-client 
 --setstorageClass.defaultClass=false
 --setstorageClass.reclaimPolicy=Retain 
 --setstorageClass.archiveOnDelete=true

# 驗證StorageClass創建成功
kubectl get sc nfs-client

手動創建StorageClass(不用Helm的方式):

# 文件:nfs-storageclass.yaml
apiVersion:storage.k8s.io/v1
kind:StorageClass
metadata:
name:nfs-client
annotations:
 storageclass.kubernetes.io/is-default-class:"false"
provisioner:cluster.local/nfs-provisioner
parameters:
archiveOnDelete:"true"
reclaimPolicy:Retain
volumeBindingMode:Immediate
allowVolumeExpansion:true
mountOptions:
-hard
-nfsvers=4.1
-timeo=600
-retrans=3

參數說明

archiveOnDelete: "true":PVC刪除時不刪除NFS上的數據,而是重命名目錄加archived-前綴,防止誤刪

reclaimPolicy: Retain:PVC刪除后PV保留,需要手動清理。生產環境必須用Retain,用Delete會直接刪數據

volumeBindingMode: Immediate:PVC創建后立即綁定PV。Local PV要用WaitForFirstConsumer

allowVolumeExpansion: true:允許PVC擴容,NFS支持在線擴容

2.2.3 Local PV(本地持久卷)

適合數據庫等對IO性能敏感的場景,數據存儲在節點本地SSD上:

# 文件:local-storageclass.yaml
apiVersion:storage.k8s.io/v1
kind:StorageClass
metadata:
name:local-ssd
provisioner:kubernetes.io/no-provisioner
volumeBindingMode:WaitForFirstConsumer
reclaimPolicy:Retain
# 文件:local-pv.yaml
apiVersion:v1
kind:PersistentVolume
metadata:
name:local-pv-worker01-ssd01
spec:
capacity:
 storage:100Gi
accessModes:
 -ReadWriteOnce
persistentVolumeReclaimPolicy:Retain
storageClassName:local-ssd
local:
 path:/data/local-volumes/ssd01
nodeAffinity:
 required:
  nodeSelectorTerms:
   -matchExpressions:
     -key:kubernetes.io/hostname
      operator:In
      values:
       -k8s-worker-01
# 在對應節點上創建目錄
mkdir -p /data/local-volumes/ssd01

# 如果是獨立SSD,掛載到該目錄
# mkfs.xfs /dev/sdb
# mount /dev/sdb /data/local-volumes/ssd01
# echo '/dev/sdb /data/local-volumes/ssd01 xfs defaults 0 0' >> /etc/fstab

kubectl apply -flocal-storageclass.yaml
kubectl apply -flocal-pv.yaml

警告:Local PV的數據和節點綁定,節點故障數據就丟了。生產環境用Local PV必須配合應用層的數據復制(如MySQL主從、Redis Sentinel)來保證數據安全。

2.2.4 Ceph RBD存儲(生產推薦)

Ceph提供塊存儲(RBD)和文件存儲(CephFS),通過ceph-csi驅動接入K8s:

# 前提:已有Ceph集群,獲取以下信息
# - Ceph Monitor地址:192.168.1.60:6789,192.168.1.61:6789,192.168.1.62:6789
# - Ceph集群ID:通過 ceph fsid 獲取
# - 管理員密鑰:通過 ceph auth get-key client.admin 獲取

# 在Ceph集群上創建K8s專用pool和用戶
ceph osd pool create k8s-rbd 128 128
ceph osd pool applicationenablek8s-rbd rbd
rbd pool init k8s-rbd

ceph auth get-or-create client.k8s-rbd 
 mon'profile rbd'
 osd'profile rbd pool=k8s-rbd'
 -o /etc/ceph/ceph.client.k8s-rbd.keyring

在K8s中配置ceph-csi:

# 安裝ceph-csi(使用Helm)
helm repo add ceph-csi https://ceph.github.io/csi-charts

helm install ceph-csi-rbd ceph-csi/ceph-csi-rbd 
 --namespace ceph-csi 
 --create-namespace 
 --setcsiConfig[0].clusterID= 
 --setcsiConfig[0].monitors[0]=192.168.1.60:6789 
 --setcsiConfig[0].monitors[1]=192.168.1.61:6789 
 --setcsiConfig[0].monitors[2]=192.168.1.62:6789

創建Secret和StorageClass:

# 文件:ceph-rbd-secret.yaml
apiVersion:v1
kind:Secret
metadata:
name:ceph-rbd-secret
namespace:ceph-csi
type:kubernetes.io/rbd
stringData:
userID:k8s-rbd
userKey:
---
apiVersion:v1
kind:Secret
metadata:
name:ceph-rbd-admin-secret
namespace:ceph-csi
type:kubernetes.io/rbd
stringData:
userID:admin
userKey:
# 文件:ceph-rbd-storageclass.yaml
apiVersion:storage.k8s.io/v1
kind:StorageClass
metadata:
name:ceph-rbd
annotations:
 storageclass.kubernetes.io/is-default-class:"true"
provisioner:rbd.csi.ceph.com
parameters:
clusterID:
pool:k8s-rbd
imageFormat:"2"
imageFeatures:layering
csi.storage.k8s.io/provisioner-secret-name:ceph-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace:ceph-csi
csi.storage.k8s.io/controller-expand-secret-name:ceph-rbd-secret
csi.storage.k8s.io/controller-expand-secret-namespace:ceph-csi
csi.storage.k8s.io/node-stage-secret-name:ceph-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace:ceph-csi
reclaimPolicy:Retain
allowVolumeExpansion:true
volumeBindingMode:Immediate
mountOptions:
-discard
kubectl apply -f ceph-rbd-secret.yaml
kubectl apply -f ceph-rbd-storageclass.yaml

# 驗證
kubectl get sc ceph-rbd

2.2.5 PVC擴容

# 確認StorageClass支持擴容
kubectl get sc ceph-rbd -o jsonpath='{.allowVolumeExpansion}'
# 輸出:true

# 編輯PVC,修改storage大小
kubectl patch pvc mysql-data -n database -p'{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'

# 查看擴容狀態
kubectl get pvc mysql-data -n database
# 如果顯示 FileSystemResizePending,需要Pod重啟后才能完成文件系統擴容
# Ceph RBD支持在線擴容,不需要重啟Pod

kubectl get events -n database --field-selector involvedObject.name=mysql-data

注意:PVC只能擴容不能縮容。NFS支持在線擴容,Ceph RBD支持在線擴容,Local PV不支持擴容。

2.3 啟動和驗證

2.3.1 使用PVC的Pod

# 文件:app-with-pvc.yaml
apiVersion:apps/v1
kind:Deployment
metadata:
name:app-with-storage
namespace:default
spec:
replicas:3
selector:
 matchLabels:
  app:app-storage
template:
 metadata:
  labels:
   app:app-storage
 spec:
  containers:
   -name:app
    image:nginx:1.24
    volumeMounts:
     -name:shared-data
      mountPath:/usr/share/nginx/html
     -name:logs
      mountPath:/var/log/nginx
    resources:
     requests:
      cpu:100m
      memory:128Mi
  volumes:
   -name:shared-data
    persistentVolumeClaim:
     claimName:app-shared-pvc
   -name:logs
    persistentVolumeClaim:
     claimName:app-logs-pvc
---
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:app-shared-pvc
namespace:default
spec:
accessModes:
 -ReadWriteMany
storageClassName:nfs-client
resources:
 requests:
  storage:10Gi
---
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:app-logs-pvc
namespace:default
spec:
accessModes:
 -ReadWriteMany
storageClassName:nfs-client
resources:
 requests:
  storage:20Gi
kubectl apply -f app-with-pvc.yaml

# 驗證PVC綁定
kubectl get pvc -n default
# NAME       STATUS  VOLUME                   CAPACITY  ACCESS MODES  STORAGECLASS
# app-shared-pvc  Bound  pvc-xxxx-xxxx               10Gi    RWX      nfs-client
# app-logs-pvc   Bound  pvc-yyyy-yyyy               20Gi    RWX      nfs-client

# 驗證Pod掛載
kubectlexec-it $(kubectl get pod -l app=app-storage -o jsonpath='{.items[0].metadata.name}') -- df -h /usr/share/nginx/html

2.3.2 StatefulSet的volumeClaimTemplates

StatefulSet的每個Pod自動創建獨立的PVC:

# 文件:redis-statefulset.yaml
apiVersion:apps/v1
kind:StatefulSet
metadata:
name:redis
namespace:default
spec:
serviceName:redis
replicas:3
selector:
 matchLabels:
  app:redis
template:
 metadata:
  labels:
   app:redis
 spec:
  containers:
   -name:redis
    image:redis:7.2
    ports:
     -containerPort:6379
    volumeMounts:
     -name:redis-data
      mountPath:/data
    resources:
     requests:
      cpu:200m
      memory:256Mi
volumeClaimTemplates:
 -metadata:
   name:redis-data
  spec:
   accessModes:["ReadWriteOnce"]
   storageClassName:ceph-rbd
   resources:
    requests:
     storage:10Gi
kubectl apply -f redis-statefulset.yaml

# 驗證:每個Pod有獨立的PVC
kubectl get pvc -l app=redis
# redis-data-redis-0  Bound  pvc-aaa  10Gi  RWO  ceph-rbd
# redis-data-redis-1  Bound  pvc-bbb  10Gi  RWO  ceph-rbd
# redis-data-redis-2  Bound  pvc-ccc  10Gi  RWO  ceph-rbd

注意:StatefulSet刪除后PVC不會自動刪除,需要手動清理。這是設計如此,防止誤刪數據。

三、示例代碼和配置

3.1 完整配置示例

3.1.1 MySQL主從 + Ceph RBD完整存儲方案

# 文件:mysql-storage-complete.yaml
# MySQL主庫 - 使用Ceph RBD高性能塊存儲
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:mysql-master-data
namespace:database
spec:
accessModes:
 -ReadWriteOnce
storageClassName:ceph-rbd
resources:
 requests:
  storage:100Gi
---
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:mysql-master-logs
namespace:database
spec:
accessModes:
 -ReadWriteOnce
storageClassName:ceph-rbd
resources:
 requests:
  storage:50Gi
---
apiVersion:apps/v1
kind:Deployment
metadata:
name:mysql-master
namespace:database
spec:
replicas:1
strategy:
 type:Recreate
selector:
 matchLabels:
  app:mysql
  role:master
template:
 metadata:
  labels:
   app:mysql
   role:master
 spec:
  containers:
   -name:mysql
    image:mysql:8.0.35
    ports:
     -containerPort:3306
    env:
     -name:MYSQL_ROOT_PASSWORD
      valueFrom:
       secretKeyRef:
        name:mysql-secret
        key:root-password
    args:
     ---innodb-buffer-pool-size=2G
     ---innodb-log-file-size=512M
     ---innodb-flush-method=O_DIRECT
     ---innodb-io-capacity=2000
     ---innodb-io-capacity-max=4000
    resources:
     requests:
      cpu:"2"
      memory:4Gi
     limits:
      cpu:"4"
      memory:8Gi
    volumeMounts:
     -name:mysql-data
      mountPath:/var/lib/mysql
     -name:mysql-logs
      mountPath:/var/log/mysql
     -name:mysql-config
      mountPath:/etc/mysql/conf.d
    livenessProbe:
     exec:
      command:
       -mysqladmin
       -ping
       --h
       -localhost
     initialDelaySeconds:30
     periodSeconds:10
    readinessProbe:
     exec:
      command:
       -mysql
       --h
       -localhost
       --e
       -"SELECT 1"
     initialDelaySeconds:10
     periodSeconds:5
  volumes:
   -name:mysql-data
    persistentVolumeClaim:
     claimName:mysql-master-data
   -name:mysql-logs
    persistentVolumeClaim:
     claimName:mysql-master-logs
   -name:mysql-config
    configMap:
     name:mysql-config

注意:MySQL的Deployment用strategy: Recreate而不是RollingUpdate,因為RBD卷是RWO模式,不能同時被兩個Pod掛載。RollingUpdate會先創建新Pod再刪舊Pod,新Pod掛載會失敗。

3.1.2 存儲容量監控腳本

#!/bin/bash
# PVC使用率監控腳本
# 文件:/opt/scripts/pvc-usage-monitor.sh
# 通過kubelet的metrics獲取PVC使用率

set-euo pipefail

ALERT_THRESHOLD=85
LOG_FILE="/var/log/pvc-monitor.log"

echo"[$(date)] Starting PVC usage check...">>"${LOG_FILE}"

# 獲取所有節點的kubelet metrics中的volume信息
fornodein$(kubectl get nodes -o jsonpath='{.items[*].metadata.name}');do
# 通過API proxy訪問kubelet metrics
 kubectl get --raw"/api/v1/nodes/${node}/proxy/stats/summary"2>/dev/null | 
  jq -r'.pods[]? | select(.volume != null) | .podRef.namespace + "/" + .podRef.name + " " + (.volume[]? | select(.pvcRef != null) | .pvcRef.name + " " + (.usedBytes|tostring) + " " + (.capacityBytes|tostring))'2>/dev/null | 
 whilereadns_pod pvc used capacity;do
  if[ -n"${capacity}"] && ["${capacity}"!="0"];then
    usage_pct=$((used * 100 / capacity))
    used_gi=$((used / 1073741824))
    cap_gi=$((capacity / 1073741824))

   if["${usage_pct}"-ge"${ALERT_THRESHOLD}"];then
    echo"[ALERT]${ns_pod}PVC:${pvc}Usage:${usage_pct}% (${used_gi}Gi/${cap_gi}Gi)">>"${LOG_FILE}"
   fi
  fi
 done
done

echo"[$(date)] PVC usage check completed.">>"${LOG_FILE}"

3.2 實際應用案例

案例一:多Pod共享NFS存儲實現文件上傳

場景描述:Web應用有3個副本,用戶上傳的文件需要所有副本都能訪問。用NFS的RWX模式實現共享存儲。

實現代碼

# 文件:file-upload-app.yaml
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:upload-files-pvc
namespace:production
spec:
accessModes:
 -ReadWriteMany
storageClassName:nfs-client
resources:
 requests:
  storage:100Gi
---
apiVersion:apps/v1
kind:Deployment
metadata:
name:file-upload-api
namespace:production
spec:
replicas:3
selector:
 matchLabels:
  app:file-upload-api
template:
 metadata:
  labels:
   app:file-upload-api
 spec:
  containers:
   -name:api
    image:file-upload-api:v1.2.0
    ports:
     -containerPort:8080
    volumeMounts:
     -name:uploads
      mountPath:/app/uploads
    resources:
     requests:
      cpu:200m
      memory:256Mi
  volumes:
   -name:uploads
    persistentVolumeClaim:
     claimName:upload-files-pvc

運行結果

# 3個Pod都掛載了同一個NFS卷
kubectlexecfile-upload-api-xxx -- ls /app/uploads
# 在任一Pod中上傳的文件,其他Pod都能看到

案例二:PV數據遷移(從NFS遷移到Ceph RBD)

場景描述:業務初期用NFS存儲MySQL數據,隨著數據量增長NFS的IO性能成為瓶頸,需要遷移到Ceph RBD。

實現步驟

創建新的Ceph RBD PVC

啟動數據遷移Job

切換應用到新PVC

驗證后清理舊PVC

# 文件:data-migration-job.yaml
apiVersion:batch/v1
kind:Job
metadata:
name:pvc-data-migration
namespace:database
spec:
template:
 spec:
  containers:
   -name:migrator
    image:ubuntu:22.04
    command:
     -/bin/bash
     --c
     -|
       apt-get update && apt-get install -y rsync
       echo "Starting data migration..."
       rsync -avz --progress /source/ /destination/
       echo "Migration completed. Verifying..."
       diff -r /source/ /destination/ && echo "Verification passed" || echo "Verification FAILED"
    volumeMounts:
     -name:source-vol
      mountPath:/source
      readOnly:true
     -name:dest-vol
      mountPath:/destination
    resources:
     requests:
      cpu:"1"
      memory:1Gi
  volumes:
   -name:source-vol
    persistentVolumeClaim:
     claimName:mysql-data-nfs
   -name:dest-vol
    persistentVolumeClaim:
     claimName:mysql-data-ceph
  restartPolicy:Never
backoffLimit:3
# 1. 停止MySQL寫入(設為只讀)
kubectlexec-it mysql-master-xxx -n database -- mysql -e"SET GLOBAL read_only=1;"

# 2. 創建目標PVC
kubectl apply -f mysql-data-ceph-pvc.yaml

# 3. 執行遷移Job
kubectl apply -f data-migration-job.yaml
kubectl logs -f job/pvc-data-migration -n database

# 4. 修改MySQL Deployment引用新PVC
kubectl patch deployment mysql-master -n database --type='json'
 -p='[{"op":"replace","path":"/spec/template/spec/volumes/0/persistentVolumeClaim/claimName","value":"mysql-data-ceph"}]'

# 5. 驗證MySQL正常啟動
kubectl get pods -n database -l app=mysql,role=master
kubectlexec-it mysql-master-xxx -n database -- mysql -e"SHOW DATABASES;"

# 6. 取消只讀
kubectlexec-it mysql-master-xxx -n database -- mysql -e"SET GLOBAL read_only=0;"

四、最佳實踐和注意事項

4.1 最佳實踐

4.1.1 性能優化

NFS掛載參數調優:默認NFS掛載參數在高并發寫入時性能差,生產環境必須調整。hard模式保證數據一致性,nfsvers=4.1支持并行IO,timeo=600避免網絡抖動導致超時。

# StorageClass中設置mountOptions
mountOptions:
-hard
-nfsvers=4.1
-timeo=600
-retrans=3
-rsize=1048576
-wsize=1048576

實測調整rsize/wsize從默認的32KB到1MB后,大文件順序寫入吞吐量從80MB/s提升到350MB/s。

Ceph RBD性能調優:RBD鏡像默認特性包含exclusive-lock、object-map、fast-diff,生產環境建議全部開啟。Ceph OSD的bluestore_cache_size默認1GB,SSD節點建議調到4GB。

# 查看RBD鏡像特性
rbd info k8s-rbd/csi-vol-xxx

# Ceph OSD調優(在Ceph節點執行)
ceph configsetosd bluestore_cache_size_ssd 4294967296
ceph configsetosd osd_op_num_threads_per_shard_ssd 2

Local PV使用XFS文件系統:相比ext4,XFS在大文件和高并發場景下性能更好,MySQL的InnoDB引擎在XFS上的隨機寫性能提升約15%。

mkfs.xfs -f /dev/sdb
mount -o noatime,nodiratime /dev/sdb /data/local-volumes/ssd01

4.1.2 安全加固

PV訪問權限控制:通過SecurityContext設置Pod的fsGroup,確保掛載的卷只有指定用戶組能訪問。

spec:
securityContext:
 runAsUser:1000
 runAsGroup:1000
 fsGroup:1000
containers:
 -name:app
  volumeMounts:
   -name:data
    mountPath:/data

加密存儲:Ceph RBD支持LUKS加密,數據在磁盤上是加密的,即使磁盤被盜也無法讀取數據。

# StorageClass中啟用加密
parameters:
encrypted:"true"
encryptionKMSID:vault-kms

限制PVC大小:通過LimitRange限制namespace中PVC的最大容量,防止用戶申請過大的存儲。

apiVersion:v1
kind:LimitRange
metadata:
name:storage-limits
namespace:production
spec:
limits:
 -type:PersistentVolumeClaim
  max:
   storage:500Gi
  min:
   storage:1Gi

4.1.3 高可用配置

HA方案一:Ceph RBD三副本存儲,任一OSD節點故障數據不丟失,RBD卷自動恢復

HA方案二:NFS服務器用DRBD + Pacemaker做主備高可用,VIP自動漂移

備份策略:Ceph RBD使用快照功能定期備份,NFS使用rsync同步到備份服務器。VolumeSnapshot是K8s原生的快照機制:

apiVersion:snapshot.storage.k8s.io/v1
kind:VolumeSnapshot
metadata:
name:mysql-data-snapshot
namespace:database
spec:
volumeSnapshotClassName:ceph-rbd-snapclass
source:
 persistentVolumeClaimName:mysql-master-data

4.2 注意事項

4.2.1 配置注意事項

警告:存儲配置錯誤可能導致數據丟失,修改前務必備份數據。

注意reclaimPolicy: Delete會在PVC刪除時同時刪除PV和后端存儲數據。生產環境必須用Retain,寧可手動清理也不要自動刪除。

注意Local PV的volumeBindingMode必須設為WaitForFirstConsumer,否則PVC可能綁定到一個節點的PV上,但Pod被調度到另一個節點,導致掛載失敗。

注意NFS的no_root_squash選項允許客戶端以root身份操作文件,安全風險高。生產環境用root_squash,通過initContainer以root身份設置目錄權限后,主容器以非root用戶運行。

4.2.2 常見錯誤

錯誤現象 原因分析 解決方案
PVC一直Pending 沒有匹配的PV或StorageClass的Provisioner未運行 kubectl describe pvc 查看事件;檢查Provisioner Pod狀態
Pod掛載卷失敗,報Multi-Attach error RWO卷被多個節點的Pod同時掛載 確認舊Pod已完全終止;檢查是否有殘留的VolumeAttachment
NFS掛載超時 NFS服務器不可達或防火墻阻斷 檢查NFS服務器狀態;確認2049端口可訪問;Worker節點安裝nfs-common
Ceph RBD掛載報rbd: map failed Ceph集群不健康或認證失敗 檢查Ceph集群狀態ceph -s;驗證Secret中的key是否正確
PVC擴容后容量沒變 文件系統未擴展,需要Pod重啟 刪除Pod觸發重建,kubelet會自動擴展文件系統
StatefulSet縮容后PVC殘留 設計如此,PVC不隨Pod刪除 手動刪除不需要的PVC:kubectl delete pvc

4.2.3 兼容性問題

版本兼容:CSI驅動版本需要和K8s版本匹配,ceph-csi 3.9.x支持K8s 1.24-1.28

平臺兼容:NFS在所有Linux發行版上都支持;Ceph RBD需要內核4.x+;CephFS需要內核4.17+

組件依賴:VolumeSnapshot需要安裝snapshot-controller和對應的CSI驅動支持

五、故障排查和監控

5.1 故障排查

5.1.1 日志查看

# 查看CSI驅動日志
kubectl logs -n ceph-csi -l app=ceph-csi-rbd-nodeplugin --tail=50
kubectl logs -n ceph-csi -l app=ceph-csi-rbd-provisioner --tail=50

# 查看NFS Provisioner日志
kubectl logs -n kube-system -l app=nfs-subdir-external-provisioner --tail=50

# 查看kubelet的卷掛載日志
journalctl -u kubelet | grep -i"volume|mount|pvc"| tail -30

# 查看PVC事件
kubectl describe pvc  -n 

# 查看VolumeAttachment
kubectl get volumeattachment

5.1.2 常見問題排查

問題一:PVC Pending,事件顯示no persistent volumes available

# 診斷命令
kubectl describe pvc  -n 
kubectl get pv --show-labels
kubectl get sc

解決方案

靜態供給:檢查是否有可用的PV,PV的容量、accessModes、storageClassName是否和PVC匹配

動態供給:檢查StorageClass是否存在,Provisioner Pod是否Running

檢查PV的狀態是否為Available(已綁定的PV不能再綁定其他PVC)

問題二:Pod卡在ContainerCreating,報FailedMount

# 診斷命令
kubectl describe pod  -n  | grep -A 10"Events"
kubectl get volumeattachment | grep 

# 檢查節點上的掛載情況
kubectl debug node/ -it --image=ubuntu:22.04 -- 
 mount | grep 

解決方案

NFS掛載失敗:確認Worker節點安裝了nfs-common,NFS服務器可達

RBD掛載失敗:檢查Ceph集群健康狀態,確認Secret配置正確

Multi-Attach錯誤:等待舊Pod完全終止,或手動刪除殘留的VolumeAttachment

問題三:存儲性能差,IO延遲高

癥狀:應用響應慢,數據庫查詢超時

排查

# 在Pod內測試IO性能
kubectlexec-it  -- bash
# 安裝fio
apt-get update && apt-get install -y fio

# 隨機讀寫測試
fio --name=randwrite --ioengine=libaio --iodepth=32 --rw=randwrite 
 --bs=4k --direct=1 --size=1G --numjobs=4 --runtime=60 
 --filename=/data/fio-test --group_reporting

# 順序寫測試
fio --name=seqwrite --ioengine=libaio --iodepth=32 --rw=write 
 --bs=1M --direct=1 --size=1G --numjobs=1 --runtime=60 
 --filename=/data/fio-test --group_reporting

解決

NFS性能差:調整rsize/wsize到1MB,升級到NFSv4.1

Ceph RBD性能差:檢查OSD磁盤是否為SSD,調整bluestore_cache_size

考慮遷移到Local PV獲取本地磁盤性能

5.1.3 調試模式

# 查看CSI驅動詳細日志
kubectl logs -n ceph-csi  -c csi-rbdplugin --tail=200

# 手動測試Ceph連接
kubectl run ceph-test --image=quay.io/ceph/ceph:v18 --rm -it -- bash
ceph -s --conf /etc/ceph/ceph.conf

# 查看節點上的塊設備
kubectl debug node/ -it --image=ubuntu:22.04 -- lsblk

# 查看掛載點
kubectl debug node/ -it --image=ubuntu:22.04 -- df -h

5.2 性能監控

5.2.1 關鍵指標監控

# PVC使用率(需要kubelet metrics)
kubectl get --raw"/api/v1/nodes//proxy/stats/summary"| 
 jq'.pods[].volume[]? | select(.pvcRef != null) | {pvc: .pvcRef.name, used: .usedBytes, capacity: .capacityBytes}'

# Ceph集群狀態
ceph -s
ceph osd pool stats k8s-rbd

# NFS服務器IO
nfsstat -s
iostat -x 1 5

5.2.2 監控指標說明

指標名稱 正常范圍 告警閾值 說明
PVC使用率 <70% >85% 超過85%需要擴容或清理數據
Ceph集群健康狀態 HEALTH_OK HEALTH_WARN WARN需要排查,ERR需要立即處理
Ceph OSD延遲 <10ms >50ms OSD延遲高影響所有RBD卷性能
NFS服務器IOPS 按硬件 接近硬件上限 IOPS飽和需要擴容NFS或遷移到分布式存儲
卷掛載失敗次數 0 >0 任何掛載失敗都需要排查
PV Available數量 >5 <2 靜態供給時可用PV不足需要提前創建

5.2.3 Prometheus監控規則

# 文件:storage-alerts.yaml
apiVersion:monitoring.coreos.com/v1
kind:PrometheusRule
metadata:
name:storage-alerts
namespace:monitoring
spec:
groups:
 -name:kubernetes-storage
  rules:
   -alert:PVCUsageHigh
    expr:|
      kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes > 0.85
    for:10m
    labels:
     severity:warning
    annotations:
     summary:"PVC{{ $labels.persistentvolumeclaim }}usage exceeds 85%"
     description:"Namespace:{{ $labels.namespace }}"

   -alert:PVCUsageCritical
    expr:|
      kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes > 0.95
    for:5m
    labels:
     severity:critical
    annotations:
     summary:"PVC{{ $labels.persistentvolumeclaim }}usage exceeds 95%"

   -alert:PVCPending
    expr:|
      kube_persistentvolumeclaim_status_phase{phase="Pending"} == 1
    for:15m
    labels:
     severity:warning
    annotations:
     summary:"PVC{{ $labels.persistentvolumeclaim }}has been Pending for 15 minutes"

   -alert:PVAvailableLow
    expr:|
      count(kube_persistentvolume_status_phase{phase="Available"}) < 2
? ? ? ? ??for:10m
? ? ? ? ??labels:
? ? ? ? ? ??severity:warning
? ? ? ? ??annotations:
? ? ? ? ? ??summary:"Less than 2 PVs available in the cluster"

? ? ? ??-alert:VolumeAttachmentFailed
? ? ? ? ??expr:|
? ? ? ? ? ? increase(storage_operation_errors_total[5m]) > 0
    for:5m
    labels:
     severity:warning
    annotations:
     summary:"Volume operation errors detected"

5.3 備份與恢復

5.3.1 備份策略

#!/bin/bash
# Ceph RBD快照備份腳本
# 文件:/opt/scripts/rbd-snapshot-backup.sh

set-euo pipefail

POOL="k8s-rbd"
BACKUP_PREFIX="scheduled-backup"
KEEP_SNAPSHOTS=24

# 獲取pool中所有RBD鏡像
forimagein$(rbd ls${POOL});do
 SNAP_NAME="${BACKUP_PREFIX}-$(date +%Y%m%d-%H%M%S)"

# 創建快照
 rbd snap create"${POOL}/${image}@${SNAP_NAME}"
echo"[$(date)] Created snapshot:${POOL}/${image}@${SNAP_NAME}"

# 清理過期快照(保留最近24個)
 rbd snap ls"${POOL}/${image}"| grep"${BACKUP_PREFIX}"| 
  head -n -${KEEP_SNAPSHOTS}| awk'{print $2}'| 
 whilereadold_snap;do
   rbd snap rm"${POOL}/${image}@${old_snap}"
  echo"[$(date)] Removed old snapshot:${POOL}/${image}@${old_snap}"
 done
done

5.3.2 恢復流程

停止服務:縮容使用該PVC的Deployment/StatefulSet到0副本

恢復數據:從快照恢復RBD鏡像或從備份rsync數據

驗證完整性:掛載卷檢查數據完整性

重啟服務:恢復Deployment/StatefulSet副本數

六、總結

6.1 技術要點回顧

要點一:生產環境reclaimPolicy必須設為Retain,Delete策略會在PVC刪除時直接刪除后端存儲數據

要點二:Local PV的volumeBindingMode必須用WaitForFirstConsumer,避免PV和Pod調度到不同節點

要點三:NFS適合共享文件存儲(RWX),Ceph RBD適合數據庫塊存儲(RWO),根據業務需求選型

要點四:StorageClass + Provisioner實現動態供給,消除手動創建PV的運維負擔

要點五:PVC只能擴容不能縮容,容量規劃時預留30%余量,配合監控在85%使用率時告警

6.2 進階學習方向

CSI驅動開發:理解CSI接口規范,為自研存儲系統開發K8s CSI驅動

學習資源:CSI規范

實踐建議:從ceph-csi源碼入手,理解Provisioner和NodePlugin的工作流程

Rook-Ceph Operator:用Rook在K8s中自動化部署和管理Ceph集群,降低Ceph運維復雜度

學習資源:Rook官方文檔

實踐建議:測試環境用Rook部署3節點Ceph集群,體驗自動化運維

VolumeSnapshot和數據保護:基于CSI的快照機制實現應用一致性備份

6.3 參考資料

Kubernetes存儲官方文檔- PV/PVC/SC完整說明

Ceph CSI項目- Ceph CSI驅動

NFS Provisioner- NFS動態供給

Longhorn項目- 輕量級分布式存儲

附錄

A. 命令速查表

# PV操作
kubectl get pv                  # 查看所有PV
kubectl get pv -o wide              # 查看PV詳情(含StorageClass)
kubectl describe pv           # PV詳細信息
kubectl delete pv            # 刪除PV(Retain策略下數據不丟)

# PVC操作
kubectl get pvc -A                # 查看所有namespace的PVC
kubectl get pvc -n           # 查看指定namespace的PVC
kubectl describe pvc  -n   # PVC詳細信息和事件
kubectl patch pvc  -p'{"spec":{"resources":{"requests":{"storage":"100Gi"}}}}'# 擴容

# StorageClass操作
kubectl get sc                  # 查看StorageClass列表
kubectl describe sc           # SC詳細信息
kubectl patch sc  -p'{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'# 設為默認SC

# 排查命令
kubectl get volumeattachment           # 查看卷掛載關系
kubectl get events -A --field-selector reason=FailedMount # 掛載失敗事件

B. 配置參數詳解

StorageClass關鍵參數

參數 說明 可選值
provisioner 存儲供給器 rbd.csi.ceph.com 、nfs.csi.k8s.io等
reclaimPolicy 回收策略 Retain (保留)、Delete(刪除)
volumeBindingMode 綁定模式 Immediate (立即)、WaitForFirstConsumer(延遲)
allowVolumeExpansion 允許擴容 true /false
mountOptions 掛載選項 依存儲類型而定

PV訪問模式

模式 縮寫 說明 支持的存儲
ReadWriteOnce RWO 單節點讀寫 所有存儲類型
ReadOnlyMany ROX 多節點只讀 NFS、CephFS、云盤
ReadWriteMany RWX 多節點讀寫 NFS、CephFS、GlusterFS
ReadWriteOncePod RWOP 單Pod讀寫(1.27 GA) CSI驅動支持

C. 術語表

術語 英文 解釋
PV PersistentVolume 集群級別的存儲資源,由管理員創建或動態供給
PVC PersistentVolumeClaim 用戶對存儲的申請,綁定到PV后供Pod使用
SC StorageClass 存儲類,定義動態供給的參數和策略
CSI Container Storage Interface 容器存儲接口標準,存儲廠商實現CSI驅動接入K8s
RBD RADOS Block Device Ceph的塊存儲設備,提供高性能塊級IO
Provisioner 供給器 負責根據PVC自動創建PV的控制器
VolumeSnapshot 卷快照 基于CSI的存儲快照機制,用于數據備份
fsGroup 文件系統組 Pod SecurityContext中設置,控制掛載卷的文件組權限

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 存儲管理
    +關注

    關注

    0

    文章

    32

    瀏覽量

    9608
  • kubernetes
    +關注

    關注

    0

    文章

    263

    瀏覽量

    9494

原文標題:從 Pod 重建不丟數據開始:Kubernetes PV/PVC/StorageClass 落地實踐

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    KubePi:開源Kubernetes可視化管理面板,讓集群管理如此簡單

    的開源Kubernetes可視化管理面板,正以其簡潔的設計與強大的功能,讓集群管理變得前所未有的簡單。 一、KubePi是什么?為什么你需要它? 1.1 誕生背景:簡化
    發表于 02-11 12:53

    Kubernetes Ingress 高可靠部署最佳實踐

    摘要: 在Kubernetes集群中,Ingress作為集群流量接入層,Ingress的高可靠性顯得尤為重要,今天我們主要探討如何部署一套高性能高可靠的Ingress接入層。簡介
    發表于 04-17 14:35

    不吹不黑,今天我們來聊一聊 Kubernetes 落地的三種方式

    Kubernetes 作為自己的基礎設施重心,"一萬個人眼中就有一萬個哈姆雷特",雖說 Kubernetes 是容器管理領域的事實標準,但實際上在不同背景的企業中,Kubernetes
    發表于 10-12 16:07

    Kubernetes Dashboard實踐學習

    關于Kubernetes Dashboard的實踐學習
    發表于 04-10 14:09

    Kubernetes上運行Kubernetes

    拍案叫絕的容器管理平臺卻遲遲未出現。 這樣的局面一直維持到2014年,谷歌將 Kubernetes 項目發布到開放源代碼社區之前。 Kubernetes 一開源,企業或者開發人員就可以在 Ku
    發表于 09-30 13:33 ?0次下載
    在<b class='flag-5'>Kubernetes</b>上運行<b class='flag-5'>Kubernetes</b>

    Kubernetes API詳解

    摘要:Kubernetes是Google開源的容器集群管理系統。它構建Ddocker技術之上,為容器化的應用提供資源調度、部署運行、服務發現、擴容縮容等整一套功能,本文節選自龔正
    發表于 10-12 16:19 ?0次下載
    <b class='flag-5'>Kubernetes</b> API詳解

    阿里巴巴 Kubernetes 應用管理實踐中的經驗與教訓

    自帶的復雜性足以讓一批開發者望而卻步。本文中,阿里巴巴技術專家孫健波在接受采訪時基于阿里巴巴 Kubernetes 應用管理實踐過程提供了一些經驗與建議,以期對開發者有所幫助。在互聯網時代,開發者更多
    發表于 11-14 23:06 ?475次閱讀

    Kubernetes是什么,一文了解Kubernetes

    香了。 這時候就需要我們的主角 Kubernetes 上場了,先來了解一下 Kubernetes 的基本概念,后面再介紹實踐,由淺入深步步為營。 關于 Kubernetes 的基本概念
    發表于 12-21 13:40 ?2081次閱讀
    <b class='flag-5'>Kubernetes</b>是什么,一文了解<b class='flag-5'>Kubernetes</b>

    Kubernetes上Java應用的最佳實踐

    在本文中,您將了解在 Kubernetes 上運行 Java 應用程序的最佳實踐。大多數這些建議也適用于其他語言。但是,我正在考慮 Java 特性范圍內的所有規則,并且還展示了可用于基于 JVM
    的頭像 發表于 03-14 17:47 ?1269次閱讀

    Awesome 工具如何更好地管理Kubernetes

    應用程序,那么 Kubernetes 是必備工具之一。有數百種工具可與 Kubernetes 配合使用以添加更多功能。我說的是用于更好地管理,安全性,儀表板和
    的頭像 發表于 06-25 16:12 ?1382次閱讀
    Awesome 工具如何更好地<b class='flag-5'>管理</b><b class='flag-5'>Kubernetes</b>

    戴爾科技再次榮獲Kubernetes數據存儲領導者

    近日,國際權威研究機構GigaOm公布了《2023企業級Kubernetes存儲雷達報告》戴爾科技集團連續兩年被評為Kubernetes數據存儲領導者。
    的頭像 發表于 10-26 10:16 ?1368次閱讀
    戴爾科技再次榮獲<b class='flag-5'>Kubernetes</b>數據<b class='flag-5'>存儲</b>領導者

    龍智出席2024零跑智能汽車技術論壇,分享功能安全、需求管理、版本管理、代碼掃描等DevSecOps落地實踐

    快訊!日前,龍智出席零跑汽車技術論壇,分享龍智DevSecOps解決方案在功能安全、精細化需求管理、流程自動化、版本控制和代碼質量分析等方面的落地實踐
    的頭像 發表于 12-27 16:06 ?1875次閱讀
    龍智出席2024零跑智能汽車技術論壇,分享<b class='flag-5'>功能</b>安全、需求<b class='flag-5'>管理</b>、版本<b class='flag-5'>管理</b>、代碼掃描等DevSecOps<b class='flag-5'>落地</b><b class='flag-5'>實踐</b>

    Kubernetes Pod常用管理命令詳解

    Kubernetes Pod常用管理命令詳解
    的頭像 發表于 02-17 14:06 ?1348次閱讀
    <b class='flag-5'>Kubernetes</b> Pod常用<b class='flag-5'>管理</b>命令詳解

    Kubernetes管理工具Helm的安裝和使用

    Helm 可以幫助我們管理 Kubernetes 應用程序 - Helm Charts 可以定義、安裝和升級復雜的 Kubernetes 應用程序,Charts 包很容易創建、版本管理
    的頭像 發表于 03-13 16:06 ?2181次閱讀

    生產環境中Kubernetes容器安全的最佳實踐

    隨著容器化技術的快速發展,Kubernetes已成為企業級容器編排的首選平臺。然而,在享受Kubernetes帶來的便利性和可擴展性的同時,安全問題也日益凸顯。本文將從運維工程師的角度,深入探討生產環境中Kubernetes容器
    的頭像 發表于 07-14 11:09 ?731次閱讀