天天看點

k8s學習-持久化存儲(Volumes、hostPath、emptyDir、PV、PVC)詳解與實戰

目錄

  • ​​概念​​
  • ​​Volumes​​
  • ​​ConfigMap && Secret​​
  • ​​hostPath​​
  • ​​模版​​
  • ​​emptyDir​​
  • ​​模版​​
  • ​​PV​​
  • ​​模版​​
  • ​​PVC​​
  • ​​模版​​
  • ​​實戰​​
  • ​​volumes - hostPath​​
  • ​​volumes - emptyDir​​
  • ​​PV & PVC - hostPath​​
  • ​​注意項​​
  • ​​參考​​

概念

Volumes

容器中的磁盤檔案是短暫的,容器崩潰後,再次重新開機,資料就丢失了。k8s通過volumes進行資料持久化和共享資料。volumes的本質就是一個目錄。volume有很多類型,有些已經棄用了,這裡提幾個還在用的。

ConfigMap && Secret

之前介紹過,可以檢視下面的文章:

​​​k8s學習-ConfigMap(建立、使用、更新、删除等)​​​​k8s學習-Secret(建立、使用、更新、删除等)​​

hostPath

hostPath卷能将主機節點檔案系統上的檔案或目錄挂載到你的 Pod 中。

hostPath卷存在許多安全風險,最佳做法是盡可能避免使用hostPath。 當必須使用hostPath 卷時,它的範圍應僅限于所需的檔案或目錄,并以隻讀方式挂載。

如果通過 AdmissionPolicy 限制hostPath 對特定目錄的通路,則必須要求 volumeMounts 使用 readOnly 挂載以使政策生效。

注意:使用hostPath時,别忘了指定Pod部署的節點。

模版
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # 宿主上目錄位置
      path: /data
      # 此字段為可選
      type:      

支援的 type 值如下:

取值 行為
空字元串(預設)用于向後相容,這意味着在安裝 hostPath 卷之前不會執行任何檢查。

​DirectoryOrCreate​

如果在給定路徑上什麼都不存在,那麼将根據需要建立空目錄,權限設定為 0755,具有與 kubelet 相同的組和屬主資訊。

​Directory​

在給定路徑上必須存在的目錄。

​FileOrCreate​

如果在給定路徑上什麼都不存在,那麼将在那裡根據需要建立空檔案,權限設定為 0644,具有與 kubelet 相同的組和所有權。

​File​

在給定路徑上必須存在的檔案。

​Socket​

在給定路徑上必須存在的 UNIX 套接字。

​CharDevice​

在給定路徑上必須存在的字元裝置。

​BlockDevice​

在給定路徑上必須存在的塊裝置。

emptyDir

當 Pod 分派到某個 Node 上時,emptyDir 卷會被建立,并且在 Pod 在該節點上運作期間,卷一直存在。 就像其名稱表示的那樣,卷最初是空的。 盡管 Pod 中的容器挂載 emptyDir 卷的路徑可能相同也可能不同,這些容器都可以讀寫 emptyDir 卷中相同的檔案。 當 Pod 因為某些原因被從節點上删除時,emptyDir 卷中的資料也會被永久删除。

說明: 容器崩潰并不會導緻 Pod 被從節點上移除,是以容器崩潰期間 emptyDir 卷中的資料是安全的。

emptyDir 的一些用途:

  • 緩存空間,例如基于磁盤的歸并排序。
  • 為耗時較長的計算任務提供檢查點,以便任務能方便地從崩潰前狀态恢複執行。
  • 在Web伺服器容器服務資料時,儲存内容管理器容器擷取的檔案。
模版
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  - image: test-webserver
    name: test-container2
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}      

PV

PV就是持久卷(Persistent Volume),是叢集中的一塊存儲,可以由管理者事先制備, 或者使用存儲類(Storage Class)來動态制備。與Volume不同的是,它們有獨立的生命周期,是一種k8s資源,在kubectl中可以縮寫為pv。

模版

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server:      

persistentVolumeReclaimPolicy有以下三種:

  • Retain – 手動回收
  • Delete – 諸如 AWS EBS、GCE PD、Azure Disk 或 OpenStack Cinder 卷這類關聯存儲資産也被删除
  • Recycle – 基本擦除 (rm -rf /thevolume/*),已被廢棄,使用動态制備替代。

capacity: PV的容量

VolumeMode(卷模式)有兩種:

  • Filesystem:被 Pod 挂載到某個目錄
  • Block:這類卷以塊裝置的方式交給 Pod 使用,其上沒有任何檔案系統。

accessModes(通路模式)有以下幾種:

  • ReadWriteOnce:單節點讀寫模式挂載
  • ReadWriteMany:多節點讀寫模式挂載
  • ReadOnlyMany:多節點隻讀模式挂載

說明:Kubernetes 使用卷通路模式來比對 PersistentVolumeClaim 和 PersistentVolume。 在某些場合下,卷通路模式也會限制 PersistentVolume 可以挂載的位置。

storageClassName:PVC和PV的保持一緻

每個卷會處于以下階段(Phase)之一:

  • Available(可用)-- 卷是一個空閑資源,尚未綁定到任何申領;
  • Bound(已綁定)-- 該卷已經綁定到某申領;
  • Released(已釋放)-- 所綁定的申領已被删除,但是資源尚未被叢集回收;
  • Failed(失敗)-- 卷的自動回收操作失敗。

PVC

PVC就是持久卷申領(PersistentVolumeClaim,PVC) 表達的是使用者對存儲的請求。Pod 将 PVC 申領當做存儲卷來使用。叢集會檢視 PVC 申領,找到所綁定的卷, 并為 Pod 挂載該卷。如果使用者删除被某 Pod 使用的 PVC 對象,該 PVC 申領不會被立即移除。 PVC 對象的移除會被推遲,直至其不再被任何 Pod 使用。

模版

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}      

selector說明:

  • matchLabels - 卷必須包含帶有此值的标簽
  • matchExpressions - 通過設定鍵(key)、值清單和操作符(operator) 來構造的需求。合法的操作符有 In、NotIn、Exists 和 DoesNotExist。

實戰

volumes - hostPath

主控端的時區、時間和Pod中容器的不一緻

k8s學習-持久化存儲(Volumes、hostPath、emptyDir、PV、PVC)詳解與實戰

修改一下上面的模版,nginx-hostpath.yaml如下

apiVersion: v1
kind: Pod
metadata:
  name: nginx-hostpath
spec:
  nodeName: xxx-105-centos
  containers:
  - image: nginx:1.14.2
    name: nginx
    volumeMounts:
    - mountPath: /etc/timezone
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /etc/timezone
      type:      

根據個人情況,替換node名,鏡像等

指令

kubectl create -f nginx-hostpath.yaml      

結果

k8s學習-持久化存儲(Volumes、hostPath、emptyDir、PV、PVC)詳解與實戰

可以看到,檔案挂載成功了。

volumes - emptyDir

busybox-emptydir.yaml

apiVersion: v1
kind: Pod
metadata:
  name: busybox-emptydir
spec:
  containers:
  - image: busybox:latest
    name: busybox1
    imagePullPolicy: IfNotPresent
    command: ['sh','-c','sleep 3600']
    volumeMounts:
    - mountPath: /home
      name: cache-volume
  - image: busybox:latest
    name: busybox2
    imagePullPolicy: IfNotPresent
    command: ['sh','-c','sleep 3600']
    volumeMounts:
    - mountPath: /home
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}      

指令

kubectl create -f busybox-emptydir.yaml      
kubectl exec -it busybox-emptydir -c busybox1 -- touch /home/lady_killer
kubectl exec -it busybox-emptydir -c busybox2 -- ls      

結果

k8s學習-持久化存儲(Volumes、hostPath、emptyDir、PV、PVC)詳解與實戰

PV & PVC - hostPath

任務:

  1. 建立一個pv,名字為app-config,大小為2Gi,通路權限為ReadWriteMany,storageClassName為manual。Volume的類型為hostPath,路徑為/srv/app-config
  2. 建立一個名字為app-config-pvc的pvc,綁定上面的pv,大小為10Mi
  3. 建立一個Pod,名字為web-server,鏡像為nginx:1.14.2,并且挂載該PVC至/usr/share/nginx/html,挂載的權限為ReadWriteMany。

app-config.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: app-config
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  hostPath:
    path: "/srv/app-config"      

app-config-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-config
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage:      

web-server-pvc.yaml

apiVersion: v1
kind: Pod
metadata:
  name: web-server
spec:
  volumes:
    - name: app-config
      persistentVolumeClaim:
        claimName: app-config
  containers:
    - name: nginx
      image: nginx:1.14.2
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: app-config      

指令

kubectl create -f app-config.yaml
kubectl create -f app-config-pvc.yaml
kubectl create -f web-server-pvc.yaml      

結果

k8s學習-持久化存儲(Volumes、hostPath、emptyDir、PV、PVC)詳解與實戰

可以看到PV在建立PVC後,狀态由Available轉為Bound,說明PVC綁定成功。

注意項

綁定不上pv的可能情況:

  • PVC的空間申領大小大于PV的大小
  • PVC的StorageClassName與PV的不一緻
  • PVC的accessModes和PV的不一緻

挂在PVC的Pod處于Pending狀态:

  • PVC建立失敗
  • PVC和Pod不在同一個namespace

參考

繼續閱讀