3 minute read

kubernetes Pod資料持久化, 這邊舉目前比較有機會用到的方式

  • volume
    • emptyDir
    • hostPath
    • NFS
  • Persistent volume
    • PV
    • PVC

volume

類似docker volume 機制, 可以將容器內外目錄共享

emptyDir

該類型目的為將pod內部的container目錄共享, 無持久化功能(該目錄不會被掛載至node上), 容器被撤銷時, 資料也會被刪除 EmptyDir會在Pod被分配到Node時被創建, 初始為空, 無須指定volume的目錄, kubernetes會自動分配一個目錄, Pod被刪除時, EmptyDir也會永久被刪除 (若執行中 Pod崩潰重啟, mptyDir資料不會受到影響, 只有刪除pod時 emptyDir的資料才會丟失 )
適用場景

  • 臨時空間
  • container與container之間需要交換數據時 (共享目錄)
apiVersion: v1
kind: Pod
metadata:
  name: nginx-busybox
  namespace: dev
spec:
  containers:
    - image: nginx:latest
      name: nginx
      ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP
      volumeMounts:
        - name: logs-volume # 將/var/log/nginx掛載至 logs-volume
          mountPath: /var/log/nginx/

    - image: busybox:latest
      name: busybox
      command: [ "/bin/sh","-c","tail -f /log/access.log" ]
      volumeMounts:
        - name: logs-volume  #將 /logs 掛載至 logs-volume
          mountPath: /log/

  volumes: # 聲明volume
    - name: logs-volume # 定義 logs-volume
      emptyDir: { } # volume 類型

測試 在busybox /log/ 可以看到nginx /var/log/nginx/ 的檔案 在busybox 創建檔案, 可以在nginx /var/log/nginx/下看到 可以理解兩者目錄共享

kubectl exec -it nginx-busybox -n dev -c nginx  --  bash
root@nginx-busybox:/# ls /var/log/nginx/
#access.log  error.log
exit
kubectl exec -it nginx-busybox -n dev -c nginx  --  bash
root@nginx-busybox:/# ls /var/log/nginx/
#access.log  error.log
root@nginx-busybox:/#
exit
kubectl exec -it nginx-busybox -n dev -c busybox  --  sh
/ #
/ # ls /log/
#access.log  error.log
/ # touch /log/frombusybox
kubectl exec -it nginx-busybox -n dev -c nginx  --  bash
root@nginx-busybox:/# ls /var/log/nginx/
#access.log  error.log  frombusybox

hostPath

效果類似emptyDir, 只是會將共享的目錄掛載於實際node上, 若Pod被撤銷, 該目錄會被保留下來
因scheduler調度不一定會是同一個node(若在不同節點會丟失狀態), 所以不建議使用hostPath, 通常是測試開發時才會使用

apiVersion: v1
kind: Pod
metadata:
  name: nginx-busybox
  namespace: dev
spec:
  containers:
    - image: nginx:latest
      name: nginx
      ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP
      volumeMounts:
        - name: logs-volume # 將/var/log/nginx掛載至 logs-volume
          mountPath: /var/log/nginx/

    - image: busybox:latest
      name: busybox
      command: [ "/bin/sh","-c","tail -f /log/access.log" ]
      volumeMounts:
        - name: logs-volume  #將 /logs 掛載至 logs-volume
          mountPath: /log/

  volumes: # 聲明volume
    - name: logs-volume # 定義 logs-volume
      hostPath:
        path: /tmp/hostpath_temp/
        type: DirectoryOrCreate #預設資料夾 不存在則創建

  # type
  # Directory # 目錄必須存在
  # FileOrCreate 文件存在就使用, 不存在就先創建後使用
  # File 檔案必須存在
  # ....

測試

root@dev-worker:/# ls /tmp/hostpath_temp/
access.log  error.log

NFS

Pod中共享目錄, 且目錄掛載於NFS

apiVersion: v1
kind: Pod
metadata:
  name: nginx-busybox
  namespace: dev
spec:
  containers:
    - image: nginx:latest
      name: nginx
      ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP
      volumeMounts:
        - name: logs-volume # 將/var/log/nginx掛載至 logs-volume
          mountPath: /var/log/nginx/

    - image: busybox:latest
      name: busybox
      command: [ "/bin/sh","-c","tail -f /log/access.log" ]
      volumeMounts:
        - name: logs-volume  #將 /logs 掛載至 logs-volume
          mountPath: /log/

  volumes: # 聲明volume
  - name: logs-volume # 定義 logs-volume
    nfs:
      server: 10.140.0.2
      path: /home/nfsVolume/

補充nfs佈署


yum install nfs-utils -y
# 安裝nfs

#or

apt-get install nfs-kernel-server nfs-common
	# 安裝nfs


# 包含 nfs server and work node


mkdir /home/nfsVolume/ -p
# 在nfs 機器上 創建掛載目錄 (這邊我利用master作為 nfs server測試)

vim /etc/exports
# nfs server 上

/etc/exports

# 暴露至所有該domain的主機
/home/nfsVolume 10.140.0.0/24(rw,sync,no_root_squash)
sudo systemctl start nfs

# or
sudo systemctl start nfs-kernel-server

PV & PVC

用於volume抽象化物件管理,
PV 簡單說就是把可以掛載至pod的目錄抽象化成kubernetes的物件, 可以被kubernetes管理
PVC 則是用於定義需求的抽象化

PV

PV = 被抽象化的資源名稱, 支援多種不同的類型

  • hostPath
  • nfs
  • local-storage
  • awsebs
  • gcepd
  • azuredisk
  • cephfs
  • ….

通常是由系統管理者進行創建, 開發者只需要在app中指定需求, 就會去抓符合資格的pv

文件說明

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity: # 儲存能力
    stroage: 20Gi
  accessModes: #訪問模式
# ReadWriteOnce(RWO) 讀寫權限,同時只能被單個node掛載
# ReadOnlyMany (ROX) 只讀權限,可被多個node掛載
# ReadWriteMany (RWX) 讀寫權限,可被多個node掛載
# 不同類型的儲存模式(nfs等等...) 可用的類型可能會不同

  storageClassName: # 儲存類型
# 有指定特定類型的pv 其只能與該類型綁定
# 無指定特定類型的pv 能與任何類型綁定 (pvc無指定)

  persistentVolumeReclaimPolicy: #回收策略
# Retain  Pod撤銷時, 裡面檔案保留 , PVC被刪除後 ,須手動取出資料
# Recycle Pod撤銷時, PV中的資料自動刪除, 將狀態初始化為可用狀態 (僅於nfs hostpath)
# Delete  Pod撤銷時, 由掛載的底層儲存 進行刪除volume操作, 常見於雲服務(會自動產生pv 被釋放則自動刪除)
  nodeAffinity: # (optional) 同pod affinity設定, 可設置綁定node
  ...
  nfs: # 底層儲存類型 e.g. nfs , hostpath , cephfs ....

hostpath

apiVersion: v1
kind: PersistentVolume
metadata:
  name: hostpath-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /mnt/data

nfs

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: nfs-pv
    spec:
      capacity:
        storage: 5Gi
      accessModes:
        - ReadWriteMany
      nfs:
        path: /exported/path
        server: nfs-server.example.com

cephfs

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: cephfs-pv
    spec:
      capacity:
        storage: 10Gi
      accessModes:
        - ReadWriteMany
      cephfs:
        monitors:
          - 10.16.154.78:6789
        path: /volumes/kubernetes
        user: admin
        secretRef:
          name: ceph-secret

Release復原

若被PVC綁定, 但後來PVC被刪除, PV STATUS會轉為release 此時會被鎖定, 若有其他PVC有資格綁定該PV, 會無法綁定 要回復狀態為 Available

可使用edit 或是 patch , 刪除 claimRef 的內容 , 就可回到Available

kubectl edit pv hostpath-pv -n dev

or

kubectl patch pv hostpath-pv -p '{"spec":{"claimRef": null}}'

PVC

PVC 可以理解需求的抽象化 當PVC被創建時, 會嘗試去綁定適合的PV
PVC可分 靜態動態 動態可設置storageClass, 可使PVC自行創建適合的PV去綁定

apiVersion: v1
kind: PersistentVolume
metadata:
  name: hostpath-pv
  namespace: dev
spec:
  storageClassName: ""
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /mnt/data
    type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
  namespace: dev
spec:
  storageClassName: ""
  accessModes: #訪問模式
    - ReadWriteOnce
  resources: # 空間請求
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: pod1
  namespace: dev
spec:
  containers:
    - name: busybox
      image: busybox:latest
      command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt;sleep 3;done;"]
      volumeMounts:
        - name: volume # 使用 volume
          mountPath: /tmp/ # container 內部 volume目錄

  volumes: #定義volume
    - name: volume
      persistentVolumeClaim:
        claimName: pvc1
        readOnly: false