概念解析

PersistentVolume(PV)和PersistentVolumeClaim(PVC)是Kubernetes中用於管理持久化存儲的核心概念。它們為Pod提供了獨立於Pod生命週期的存儲能力,確保數據在Pod重啓或遷移時不會丟失。

PersistentVolume(PV)概念

PersistentVolume是集羣中的一塊存儲資源,由管理員配置或通過StorageClass動態供應。PV是集羣級別的資源,獨立於任何單個Pod的生命週期。

PersistentVolumeClaim(PVC)概念

PersistentVolumeClaim是用户對存儲資源的請求。PVC消耗PV資源,就像Pod消耗節點資源一樣。PVC可以請求特定大小和訪問模式的存儲。

核心概念關係

  1. PV:集羣中的實際存儲資源
  2. PVC:用户對存儲資源的請求
  3. StorageClass:描述存儲類別的資源,用於動態供應PV
  4. 訪問模式:定義PV可以如何被掛載(ReadWriteOnce、ReadOnlyMany、ReadWriteMany)

核心特性

PV特性

  1. 持久性:數據獨立於Pod生命週期
  2. 多種存儲類型:支持本地存儲、網絡存儲、雲存儲等多種類型
  3. 訪問模式:支持不同的訪問模式配置
  4. 回收策略:支持Retain、Recycle、Delete等回收策略

PVC特性

  1. 資源請求:可以請求特定大小和訪問模式的存儲
  2. 動態綁定:自動與滿足條件的PV綁定
  3. 存儲類:可以指定特定的StorageClass
  4. 擴容支持:支持在線擴容(需要存儲插件支持)

訪問模式

  1. ReadWriteOnce(RWO):卷可以被單個節點以讀寫方式掛載
  2. ReadOnlyMany(ROX):卷可以被多個節點以只讀方式掛載
  3. ReadWriteMany(RWX):卷可以被多個節點以讀寫方式掛載

實踐教程

創建靜態PV

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-example
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /mnt/data

創建PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-example
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: manual

在Pod中使用PVC

apiVersion: v1
kind: Pod
metadata:
  name: pv-pod
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: data-volume
      mountPath: /usr/share/nginx/html
  volumes:
  - name: data-volume
    persistentVolumeClaim:
      claimName: pvc-example

動態供應存儲

# StorageClass配置
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
  fsType: ext4
---
# 使用StorageClass的PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dynamic-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  storageClassName: fast-ssd

真實案例

案例:數據庫持久化存儲方案

某公司在Kubernetes集羣中運行MySQL數據庫,需要確保數據的持久性和高可用性。通過PV和PVC實現數據庫存儲管理:

# StorageClass for database storage
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: database-storage
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
  fsType: ext4
  iopsPerGB: "10"
reclaimPolicy: Retain
allowVolumeExpansion: true
---
# PersistentVolumeClaim for MySQL
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Gi
  storageClassName: database-storage
---
# MySQL Deployment with persistent storage
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.7
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pvc
---
# MySQL Service
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  selector:
    app: mysql
---
# Backup CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
  name: mysql-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: mysql-backup
            image: mysql:5.7
            command:
            - /bin/bash
            - -c
            - |
              mysqldump -h mysql -u root -p$MYSQL_ROOT_PASSWORD --all-databases > /backup/backup-$(date +"%Y-%m-%d-%H%M%S").sql
            env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: password
            volumeMounts:
            - name: backup-storage
              mountPath: /backup
          volumes:
          - name: backup-storage
            persistentVolumeClaim:
              claimName: mysql-backup-pvc
          restartPolicy: OnFailure
---
# Backup storage PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-backup-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 500Gi
  storageClassName: backup-storage

這種存儲方案的優勢:

  • 數據持久性:即使Pod被刪除或重新調度,數據也不會丟失
  • 動態供應:自動創建和管理存儲卷
  • 可擴展性:支持在線擴容存儲空間
  • 備份策略:定期備份數據庫數據
  • 高可用性:通過合適的存儲後端確保數據可靠性

配置詳解

不同類型的PV

# NFS PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: nfs-server.example.com
    path: "/data"
---
# AWS EBS PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: aws-ebs-pv
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteOnce
  awsElasticBlockStore:
    volumeID: vol-0123456789abcdef0
    fsType: ext4
---
# GCE Persistent Disk PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: gce-pd-pv
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    pdName: gke-pd-disk
    fsType: ext4
---
# Local PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/ssd1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node-1

PV回收策略

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-with-retention
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain  # 保留數據
  storageClassName: manual
  hostPath:
    path: /mnt/data
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-with-deletion
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete  # 刪除數據
  storageClassName: manual
  hostPath:
    path: /mnt/data

PVC存儲擴容

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: resizable-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: resizable-storage
---
# 擴容命令
# kubectl patch pvc resizable-pvc -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'

故障排除

常見問題及解決方案

  1. PVC處於Pending狀態

    # 檢查PVC狀態
    kubectl describe pvc <pvc-name>
    
    # 檢查是否有匹配的PV
    kubectl get pv
    
    # 檢查StorageClass
    kubectl get storageclass
    
  2. Pod無法掛載卷

    # 檢查Pod事件
    kubectl describe pod <pod-name>
    
    # 檢查PV和PVC狀態
    kubectl get pv,pvc
    
    # 檢查節點存儲插件
    kubectl get pods -n kube-system
    
  3. 存儲空間不足

    # 檢查PV使用情況
    kubectl exec -it <pod-name> -- df -h
    
    # 檢查PVC容量
    kubectl get pvc <pvc-name> -o yaml
    
    # 擴容PVC(如果支持)
    kubectl patch pvc <pvc-name> -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
    
  4. 數據丟失問題

    # 檢查PV回收策略
    kubectl get pv <pv-name> -o yaml
    
    # 檢查存儲後端狀態
    # 檢查備份策略執行情況
    

最佳實踐

  1. 存儲規劃

    • 根據應用需求選擇合適的存儲類型
    • 合理規劃存儲容量和性能要求
    • 考慮存儲的可用性和持久性需求
  2. PVC管理

    • 為不同應用使用獨立的PVC
    • 設置合適的資源請求和限制
    • 定期監控存儲使用情況
  3. 備份策略

    • 建立定期備份機制
    • 測試備份恢復流程
    • 存儲備份數據在不同的存儲位置
  4. 安全考慮

    • 限制對存儲資源的訪問權限
    • 加密敏感數據
    • 審計存儲訪問日誌
  5. 監控和告警

    • 監控存儲使用率
    • 設置存儲容量告警
    • 監控存儲性能指標

安全考慮

使用加密存儲

apiVersion: v1
kind: PersistentVolume
metadata:
  name: encrypted-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: encrypted-storage
  csi:
    driver: pd.csi.storage.gke.io
    volumeHandle: projects/my-project/zones/us-central1-a/disks/my-encrypted-disk
    fsType: ext4
    volumeAttributes:
      encrypted: "true"

使用存儲策略

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: secure-storage
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
  fsType: ext4
  encrypted: "true"
  kmsKeyId: "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"

限制存儲訪問

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: psp-with-storage-restrictions
spec:
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    - 'persistentVolumeClaim'  # 限制只能使用PVC
  allowedHostPaths:
    - pathPrefix: "/mnt/data"
      readOnly: true

命令速查

命令 描述
kubectl get pv 查看PersistentVolume列表
kubectl get pvc 查看PersistentVolumeClaim列表
kubectl describe pv <name> 查看PersistentVolume詳細信息
kubectl describe pvc <name> 查看PersistentVolumeClaim詳細信息
kubectl get storageclass 查看StorageClass列表
kubectl apply -f <pv.yaml> 創建PersistentVolume
kubectl apply -f <pvc.yaml> 創建PersistentVolumeClaim
kubectl delete pv <name> 刪除PersistentVolume
kubectl delete pvc <name> 刪除PersistentVolumeClaim
kubectl patch pvc <name> -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}' 擴容PVC

總結

PersistentVolume和PersistentVolumeClaim是Kubernetes中管理持久化存儲的核心組件。通過本文檔的學習,你應該能夠:

  • 理解PV和PVC的概念和工作機制
  • 創建和管理靜態和動態存儲卷
  • 在Pod中正確使用持久化存儲
  • 配置不同類型的存儲後端
  • 排查常見的存儲問題
  • 遵循存儲管理的最佳實踐和安全考慮

在下一文檔中,我們將學習Namespace命名空間管理,它是實現資源隔離和多租户管理的重要機制。