Kubenets 存儲的分類+數(shù)據(jù)的持久化+PVC/PV+StorageClass

Kubenets 存儲的分類+數(shù)據(jù)的持久化+PVC/PV+StorageClass

  1. ConfigMap

  2. Secret

  3. Downward API

  4. Volume

  5. PV/PVC

  6. StorageClass

1. ConfigMap

以注入的方式存儲非機密的配置信息(例如配置文件、環(huán)境變量、命令行參數(shù)等)。Pod 可以通過環(huán)境變量或掛載為文件的方式讀取 ConfigMap。

# 文件方式創(chuàng)建
$ kubectl create configmap xxx --from-file=xxx.file

# 命令參數(shù)方式創(chuàng)建
$ kubectl create configmap xxx --from-literal=name=xxx --from-literal=password=xx

# --dry-run只編寫不運行, -o yaml > xxx.yaml 導出到xx.yaml保存為yaml格式
--dry-run=client
-o yaml > xxx.yaml 

# 完整命令
$ kubectl create configmap xxx --from-literal=name=xxx --from-literal=password=xxx --dry-run=client -o yaml > xxx.yaml

使用方式:

  1. 作為環(huán)境變量注入 Pod
   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: app-env-bulk
   ---
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: envfrom-demo
   spec:
     replicas: 1
     selector:
       matchLabels:
         app: envfrom-demo
     template:
       metadata:
         labels:
           app: envfrom-demo
       spec:
         containers:
           - name: app
             image: busybox
             command: ["sh", "-c", "env | grep DB_"]
             envFrom:
               - configMapRef:
                   name: app-env-bulk

2.作為環(huán)境變量單個鍵值注入

   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: app-env
   ---
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: env-demo
   spec:
     replicas: 1
     selector:
       matchLabels:
         app: env-demo
     template:
       metadata:
         labels:
           app: env-demo
       spec:
         containers:
           - name: app
             image: busybox
             command: ["sh", "-c", "env | grep LOG_LEVEL"]
             env:
               - name: LOG_LEVEL
                 valueFrom:
                   configMapKeyRef:
                     name: app-env
                     key: LOG_LEVEL
               - name: FEATURE_FLAG
                 valueFrom:
                   configMapKeyRef:
                     name: app-env
                     key: FEATURE_FLAG
  1. 以卷 (configMap volume) 的方式掛載為文件/目錄

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: app-config-files
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: volume-demo
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: volume-demo
        template:
          metadata:
            labels:
              app: volume-demo
          spec:
            containers:
              - name: app
                image: busybox
                command: ["sh", "-c", "ls /config && cat /config/application.properties"]
                volumeMounts:
                  - name: config-vol
                    mountPath: /config
                    readOnly: true
            volumes:
              - name: config-vol
                configMap:
                  name: app-config-files
    

2. Secret

存儲敏感數(shù)據(jù)(如密碼、證書、密鑰),內容會以 Base64 編碼保存。與 ConfigMap 類似,可通過環(huán)境變量或卷掛載到 Pod,并在 API Server/ETCD 中進行額外的訪問控制。

# base64編碼
$ echo -n "Hello World" | base64 
SGVsbG8gV29ybGQ=

# base64解碼
$ echo -n "SGVsbG8gV29ybGQ=" | base64 -d

常見類型如下:

  1. Opaque:默認類型,存放任意 key/value,需要自行決定編碼內容。

     apiVersion: v1
     kind: Secret
     metadata:
       name: app-secret
     type: Opaque
     stringData:
       username: admin
       password: s3cr3t
    
     or 
    
     apiVersion: v1
     kind: Secret
     metadata:
       name: app-secret
     type: Opaque
     data:
       username: base64(admin)
       password: base64(s3cr3t)
    
  2. kubernetes.io/service-account-token:ServiceAccount 自動掛載的令牌,附帶 CA、namespace 等字段。

     apiVersion: v1
     kind: Secret
     metadata:
       name: default-token
       annotations:
         kubernetes.io/service-account.name: default
     type: kubernetes.io/service-account-token
    
  3. kubernetes.io/dockercfg 與 kubernetes.io/dockerconfigjson:Docker Registry 憑據(jù),分別對應舊版 .dockercfg 和新版 .dockerconfigjson。

     apiVersion: v1
     kind: Secret
     metadata:
       name: regcred
     type: kubernetes.io/dockerconfigjson
     data:
       .dockerconfigjson: <base64-encoded-config>
    
  4. kubernetes.io/basic-auth:基于用戶認證,保存用戶名/密碼對。

     apiVersion: v1
     kind: Secret
     metadata:
       name: basic-auth
     type: kubernetes.io/basic-auth
     stringData:
       username: user1
       password: passw0rd
    
  5. kubernetes.io/ssh-auth:存放 SSH 私鑰數(shù)據(jù)。

     apiVersion: v1
     kind: Secret
     metadata:
       name: git-ssh
     type: kubernetes.io/ssh-auth
     stringData:
       ssh-privatekey: |
         -----BEGIN OPENSSH PRIVATE KEY-----
         ...
         -----END OPENSSH PRIVATE KEY-----
    
  6. kubernetes.io/tls:TLS 證書與私鑰(字段固定為 tls.crt、tls.key)。

     apiVersion: v1
     kind: Secret
     metadata:
       name: tls-cert
     type: kubernetes.io/tls
     stringData:
       tls.crt: |
         -----BEGIN CERTIFICATE-----
         ...
         -----END CERTIFICATE-----
       tls.key: |
         -----BEGIN PRIVATE KEY-----
         ...
         -----END PRIVATE KEY-----
    
  7. bootstrap.kubernetes.io/token:集群 bootstrap 令牌,用于 kubeadm 加入節(jié)點。

     apiVersion: v1
     kind: Secret
     metadata:
       name: bootstrap-token-abcdef
       namespace: kube-system
     type: bootstrap.kubernetes.io/token
     stringData:
       description: "kubeadm bootstrap token"
       token-id: abcdef
       token-secret: 0123456789abcdef
    

3. Downward API

把 Pods 自身的元數(shù)據(jù)(例如 Pod 名稱、命名空間、標簽、注解、資源請求與限制等)暴露給容器,方式包括環(huán)境變量和掛載為文件。Downward API 不需要事先創(chuàng)建對象,由 kubelet 在 Pod 生命周期內自動提供。

  1. 環(huán)境變量注入 Pod 元數(shù)據(jù)(fieldRef)

     apiVersion: v1
     kind: Pod
     metadata:
       name: env-fieldref-demo
     spec:
       containers:
         - name: app
           image: busybox
           command: ["sh", "-c", "env && sleep 3600"]
           env:
             - name: POD_NAME
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.name
             - name: POD_NAMESPACE
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.namespace
             - name: POD_IP
               valueFrom:
                 fieldRef:
                   fieldPath: status.podIP
    
  2. 環(huán)境變量注入資源請求/限制(resourceFieldRef)

     apiVersion: v1
     kind: Pod
     metadata:
       name: env-resource-demo
     spec:
       containers:
         - name: app
           image: busybox
           resources:
             requests:
               cpu: "250m"
               memory: "128Mi"
             limits:
               cpu: "500m"
               memory: "256Mi"
           env:
             - name: CPU_LIMIT
               valueFrom:
                 resourceFieldRef:
                   containerName: app
                   resource: limits.cpu
             - name: MEM_REQUEST
               valueFrom:
                 resourceFieldRef:
                   containerName: app
                   resource: requests.memory
           command: ["sh", "-c", "echo $CPU_LIMIT $MEM_REQUEST && sleep 3600"]
    
  3. DownwardAPI 卷(以文件形式暴露元數(shù)據(jù)或資源值,可熱更新)

     apiVersion: v1
     kind: Pod
     metadata:
       name: volume-downward-demo
       labels:
         app: demo
     spec:
       containers:
         - name: app
           image: busybox
           command: ["sh", "-c", "cat /etc/podinfo/* && sleep 3600"]
           volumeMounts:
             - name: podinfo
               mountPath: /etc/podinfo
               readOnly: true
       volumes:
         - name: podinfo
           downwardAPI:
             items:
               - path: "labels"
                 fieldRef:
                   fieldPath: metadata.labels
               - path: "annotations"
                 fieldRef:
                   fieldPath: metadata.annotations
               - path: "requests_cpu"
                 resourceFieldRef:
                   containerName: app
                   resource: requests.cpu
               - path: "limits_memory"
                 resourceFieldRef:
                   containerName: app
                   resource: limits.memory
    
  4. 投射卷(Projected Volume)結合 DownwardAPI 與其他來源

     apiVersion: v1
     kind: Pod
     metadata:
       name: projected-downward-demo
     spec:
       containers:
         - name: app
           image: busybox
           command: ["sh", "-c", "ls /projected && sleep 3600"]
           volumeMounts:
             - name: projected-vol
               mountPath: /projected
               readOnly: true
       volumes:
         - name: projected-vol
           projected:
             sources:
               - downwardAPI:
                   items:
                     - path: pod_name
                       fieldRef:
                         fieldPath: metadata.name
                     - path: cpu_limit
                       resourceFieldRef:
                         containerName: app
                         resource: limits.cpu
               - configMap:
                   name: app-config
               - secret:
                   name: app-secret
    

4. Volume

解決 Pod 容器「文件系統(tǒng)不持久、彼此隔離」的問題,讓數(shù)據(jù)可以:在同一個 Pod 內共享、在容器重啟后保留,甚至在不同 Pod / 節(jié)點之間持久存儲。

  1. Pod 使用 emptyDir 卷(生命周期隨 Pod)
    apiVersion: v1
    kind: Pod
    metadata:
     name: emptydir-pod
    spec:
     containers:
       - name: app
         image: nginx:1.27
         volumeMounts:
           - name: cache
             mountPath: /cache
     volumes:
       - name: cache
         emptyDir: {}
    
  2. Pod 使用 hostPath 卷(掛宿主機目錄)

    Kubernetes 中 hostPath 的 type 主要有以下幾種(不區(qū)分大小寫時寫法類似,但推薦用官方寫法):

    • DirectoryOrCreate

      • 如果路徑存在:必須是目錄,否則報錯。

      • 如果路徑不存在:在宿主機上創(chuàng)建一個空目錄(權限 0755,屬主為 kubelet 運行用戶)。

    • Directory

      • 路徑必須已經(jīng)存在并且是一個目錄。

      • 如果不存在或不是目錄:Pod 啟動失敗。

    • FileOrCreate

      • 如果路徑存在:必須是文件,否則報錯。

      • 如果路徑不存在:在宿主機上創(chuàng)建一個空文件(權限 0644,屬主為 kubelet 運行用戶)。

    • File

      • 路徑必須已經(jīng)存在并且是一個普通文件。

      • 如果不存在或不是文件:Pod 啟動失敗。

    • Socket

      • 路徑必須存在且是 Unix Domain Socket(如一些本地通信場景)。

      • 否則 Pod 啟動失敗。

    • CharDevice

      • 路徑必須存在且是字符設備(如 /dev/null、串口設備等)。

      • 否則 Pod 啟動失敗。

    • BlockDevice

      • 路徑必須存在且是塊設備(如磁盤 /dev/sdb 等)。

      • 否則 Pod 啟動失敗。

apiVersion: v1
kind: Pod
metadata:
  name: hostpath-pod
spec:
  containers:
    - name: app
      image: nginx
      volumeMounts:
        - name: host-data
          mountPath: /data    # 掛載容器內部的路徑
  volumes:
    - name: host-data
      hostPath:
        path: /var/data       # 宿主機路徑
        type: DirectoryOrCreate
  1. 使用 PV + PVC 持久卷
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-example
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:                    # 演示用,生產一般用云盤/NFS/CSI
    path: /mnt/data/pv-example
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-example
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: pvc-pod
spec:
  containers:
    - name: app
      image: nginx:1.27
      volumeMounts:
        - name: data
          mountPath: /usr/share/nginx/html
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: pvc-example

5. PV/PVC+StatefulSet有狀態(tài)服務

Kubernetes 的 PersistentVolume (PV) 和 PersistentVolumeClaim (PVC) 負責為 Pod 提供持久化存儲:

  • PV:管理員預先配置的存儲資源,抽象了底層存儲實現(xiàn)(如 NFS、iSCSI、CSI 驅動等),帶有容量、訪問模式、回收策略等屬性。

  • PVC:應用側對存儲的請求,指定所需容量、訪問模式、StorageClass 等;控制面會嘗試把 PVC 綁定到滿足條件的 PV,或通過 StorageClass 動態(tài)創(chuàng)建新的 PV。

  • Pod 使用 PVC:在 Pod 的 spec.volumes 中引用 PVC,容器通過 volumeMounts 掛載后即可讀寫。

  • 生命周期:刪除 PVC 時,PV 根據(jù)回收策略(Retain、Delete、Recycle)決定是否保留或清除實際存儲;未被綁定的 PV 處于 Available 狀態(tài),可供其它 PVC 使用。

  • 常見注意事項:確保訪問模式匹配(例如 ReadWriteOnce vs ReadOnlyMany)、容量需要滿足或高于 PVC 請求、StorageClass 的 allowVolumeExpansion 決定是否可擴容等。

要讓 Kubernetes 的 PVC/PV 能夠正常使用,需要在集群里部署與 PVC 兼容的存儲插件(通常稱為 CSI 驅動或傳統(tǒng)的外部存儲插件)。思路如下:

  • 確認需求:確定應用需要的訪問模式(RWO/RWX/ROX)、性能和容量要求,然后挑選合適的后端存儲(NFS、iSCSI、Ceph RBD/CephFS、各云廠商塊存儲、分布式文件系統(tǒng)等)。

  • 安裝對應存儲插件:

    • 現(xiàn)代集群最常用的是 CSI(Container Storage Interface)驅動。通常可通過 Helm Chart、Operator 或云廠商提供的安裝腳本部署。

    • 例如:

      • NFS:可以部署 nfs-subdir-external-provisioner(Provisioner + NFS 服務已準備好)。

      • iSCSI:需要在節(jié)點上配置 iSCSI initiator,并部署提供 iSCSI Target 的 CSI(如 OpenEBS iSCSI)。

      • Ceph:常見方案是 Rook-Ceph Operator 或 ceph-csi(支持 RBD、CephFS)。

      • 云廠商塊存儲:AWS EBS CSI、Azure Disk CSI、GKE PD CSI 等。

PV 訪問模式(Access Modes)

PV 的訪問模式定義了存儲卷如何被掛載和訪問:

1. ReadWriteOnce (RWO)

  • 說明:卷可以被單個節(jié)點以讀寫方式掛載

  • 特點:同一時間只能被一個節(jié)點掛載

  • 適用場景:數(shù)據(jù)庫、單實例應用

  • 限制:不支持多節(jié)點同時讀寫

2. ReadOnlyMany (ROX)

  • 說明:卷可以被多個節(jié)點以只讀方式掛載

  • 特點:多個節(jié)點可同時讀取,但不能寫入

  • 適用場景:配置文件、靜態(tài)資源分發(fā)

  • 限制:所有掛載都是只讀的

3. ReadWriteMany (RWX)

  • 說明:卷可以被多個節(jié)點以讀寫方式掛載

  • 特點:支持多節(jié)點同時讀寫

  • 適用場景:共享存儲、多實例應用

  • 限制:需要底層存儲系統(tǒng)支持(如 NFS、GlusterFS)

4. ReadWriteOncePod (RWOP) ?

  • 說明:卷可以被單個 Pod 以讀寫方式掛載(Kubernetes v1.22+)

  • 特點:確保整個集群中只有一個 Pod 可以讀寫掛載

  • 適用場景:需要嚴格單寫入者的應用

  • 優(yōu)勢:比 RWO 更嚴格,提供更好的數(shù)據(jù)一致性保證

注: 需在每個node節(jié)點安裝NFS服務器.

# 更新軟件軟
$ apt update && apt upgrade -y

# 安裝NFS服務器
$ apt install -y nfs-kernel-server

$ mkdir /nfs-share
$ chmod 666 /nfs-share
$ chown nobody /nfs-share

$ cat /etc/exports
/nfs-share *(rw,sync,no_subtree_check,no_root_squash)

# Kubernetes NFS 共享配置
# 格式:共享目錄  允許訪問的網(wǎng)段(權限選項)

# 方式1:允許所有節(jié)點訪問(開發(fā)環(huán)境)
/nfs-share/k8s-pv  *(rw,sync,no_subtree_check,no_root_squash)

# 方式2:限制特定網(wǎng)段(生產環(huán)境推薦)
# /nfs-share/k8s-pv  10.0.0.0/8(rw,sync,no_subtree_check,no_root_squash)
# /nfs-share/k8s-pv  192.168.0.0/16(rw,sync,no_subtree_check,no_root_squash)

# 重啟服務
$ systemctl restart nfs-server.service 

# 檢查
$ dpkg -l | grep nfs
$ showmount -e xxx (主機ip: Ex:192.168.61.141)

--------------------------------  
node01 || node01
$ mkdir nfs-share && mkdir nfs-share/k8s-pv

# 掛載
$ mount -t nfs 192.168.61.141:/nfs-share/k8s-pv /nfs-share/k8s-pv/

# 解除掛載
$ umount /nfs-share/k8s-pv/

對于 StatefulSet,通常不直接創(chuàng)建 PVC,而是使用 volumeClaimTemplates,真正應用時在 StatefulSet 中定義模板即可。

PV清單文件

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-demo-retain
spec:
  capacity:
    storage: 1Gi
  accessModes: [ReadWriteMany]
  storageClassName: manual    # 存儲類名
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /nfs-share/k8s-pv
    server: 192.168.61.141
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-demo-recycle
spec:
  capacity:
    storage: 1Gi
  accessModes: [ReadWriteMany]
  storageClassName: manual    # 存儲類名
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /nfs-share/data
    server: 192.168.61.141
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-demo-delete
spec:
  capacity:
    storage: 1Gi
  accessModes: [ReadWriteMany]
  storageClassName: manual    # 存儲類名
  persistentVolumeReclaimPolicy: Delete
  nfs:
    path: /nfs-share/tmp
    server: 192.168.61.141

svc-headless清單文件

apiVersion: v1
kind: Service
metadata:
  name: web-headless
  labels:
    app: web
spec:
  clusterIP: None # statefulSet 無頭服務
  selector:
    app: web
  ports:
    - port: 80
      targetPort: http

statefulSet清單文件

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web-stateful
spec:
  serviceName: web-headless
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx
          ports:
            - containerPort: 80
              name: http
          volumeMounts:
            - name: www        # 綁定的卷名稱
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
    - metadata:
        name: www        # 綁定的卷名稱
      spec:
        accessModes: [ReadWriteMany]
        storageClassName: manual    # 存儲類名
        resources:
          requests:
            storage: 1Gi
總結:
  • 無狀態(tài)服務:使用 ConfigMap/Secret 提供配置,數(shù)據(jù)寫入外部存儲(數(shù)據(jù)庫、對象存儲、消息隊列等)。

  • 有狀態(tài)服務:使用 StatefulSet + PV/PVC,或使用 Operator 管理。

  • PVC 需手動刪除

6. StorageClass

StorageClass 基于云供應商提供的服務, 是 Kubernetes 中用于定義存儲類型的資源對象.

主要作用
  1. 動態(tài)存儲供應:自動創(chuàng)建 PersistentVolume(PV)

  2. 存儲分類:區(qū)分不同性能和特性的存儲

  3. 簡化管理:無需手動創(chuàng)建 PV

  4. 創(chuàng)建StorageClass

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard    # 指定 StorageClass
provisioner: kubernetes.io/aws-ebs  # 存儲供應者
parameters:
  type: gp3
  fsType: ext4
reclaimPolicy: Delete  # 回收策略:Retain 或 Delete
volumeBindingMode: Immediate  # 綁定模式:Immediate 或 WaitForFirstConsumer
allowVolumeExpansion: true  # 是否允許卷擴容
  1. 在 PVC 中引用 StorageClass
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: standard  # 指定 StorageClass
  resources:
    requests:
      storage: 10Gi
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容