Kubernetes進階實戰讀書筆記:持久化存儲卷(pv和pvc生命周期)


一、存儲類

1、存儲類的好處

支持pv的動態創建、用戶用到持久性存儲時、需要通過創建pvc來綁定配pv此類操作需求動態創建適配的pv會存儲管理帶來極大的靈活性

二、StorageClass的關鍵配置參數

1、關鍵配置參數詳解

[root@master chapter7]# kubectl explain StorageClass
KIND:     StorageClass
VERSION:  storage.k8s.io/v1

DESCRIPTION:
     StorageClass describes the parameters for a class of storage for which
     PersistentVolumes can be dynamically provisioned. StorageClasses are
     non-namespaced; the name of the storage class according to etcd is in
     ObjectMeta.Name.

FIELDS:
   allowVolumeExpansion	<boolean>
     AllowVolumeExpansion shows whether the storage class allow volume expand

   allowedTopologies	<[]Object>
     Restrict the node topologies where volumes can be dynamically provisioned.
     Each volume plugin defines its own supported topology specifications. An
     empty TopologySelectorTerm list means there is no topology restriction.
     This field is only honored by servers that enable the VolumeScheduling
     feature.

   apiVersion	<string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind	<string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   mountOptions	<[]string>
   #由當前動態創建的pv的掛載選項列表
     Dynamically provisioned PersistentVolumes of this storage class are created
     with these mountOptions, e.g. ["ro", "soft"]. Not validated - mount of the
     PVs will simply fail if one is invalid.

   parameters	<map[string]string>
   #存儲類使用參數描述要關聯到的存儲卷、不過、不同的Provisioner可用的參數各不相同
     Parameters holds the parameters for the provisioner that should create
     volumes of this storage class.

   provisioner	<string> -required- #即提供了存儲資源的存儲系統,存儲類要依賴Provisioner來判定要使用的存儲插件以便適配到目標存儲系統、kubernetes內核有多中供給方Provisioner、這些供給方的名稱都以kubernetes.io為前綴。另外,它還支持用戶依據kubernetes規范定義的Provisioner
     Provisioner indicates the type of the provisioner.

   reclaimPolicy	<string>
   #為當前存儲類動態床架你的pv指定回收策略,可用之Delete和retain;不過那些由管理員手創建的pv的回收策略則取決於他們自身的定義
     Dynamically provisioned PersistentVolumes of this storage class are created
     with this reclaimPolicy. Defaults to Delete.

   volumeBindingMode	<string>
   #定義如何為pvc完成供給和綁定,默認值為:VolumeScheduling;此選項僅在啟用了存儲卷調度功能時才能生效
     VolumeBindingMode indicates how PersistentVolumeClaims should be
     provisioned and bound. When unset, VolumeBindingImmediate is used. This
     field is only honored by servers that enable the VolumeScheduling feature.

2、資源清單

[root@master chapter7]# cat glusterfs-storageclass.yaml 
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
  name: glusters
provisioner: kubernetes.io/glusterfs
parameters:
  resturl: "http://heketi.ilinux.io:8080" 
  restauthenabled: "false"
  restuser: "ik8s"
  restuserkey: "ik8s.io"

1、parameters.resturl字段用於指定gluster存儲系統的RESTful風格的訪問接口

2、本示例中使用的http://heketi.ilinux.io:8080應替換為自己實際環境中的可用地址、gluster存儲系統本身並不支持這種訪問放手、不過只有再restauthenabled設置為"true"時restuser和restuserkey字段才會啟用

二、動態供給pv供給

動態PV供給的啟用、需要實現由管理員至少一個存儲類,不同的Provisoner的創建方法各有不同、並非所有的存儲插件都有Kubernetes內建支持PV動態供給功能

上文中定義glusterfs存儲類資源創建完成后、便可以根據使用動態PV供給功能、下面的資源清單定義在pvc-gluserfs-dynamic-0001配置文件它將從glusterfs存儲類中申請使用5GB的存儲空間

1、配置清單

[root@master chapter7]# cat pvc-gluster-dynamic-0001.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: pvc-gluster-dynamic-0001
 annotations:
   volume.beta.kubernetes.io/storage-class: gluster-dynamic
spec:
 accessModes:
  - ReadWriteOnce
 resources:
   requests:
     storage: 5Gi

2、創建及查看詳細信息

各種存儲插件對動態供給方式的支持狀況

目前、在PVC的定義中指定使用的存儲類資源的方式共有兩種:一種是使用spec.StorageClass字段、一種是使用"volume.beta.kubernetes.io/storage-class"字段,不過,建議僅適用一種方式,以免兩者設置為不同的值時會出現配置錯誤、接下來創建定義PVC,並檢查其綁定狀態

[root@master chapter7]# kubectl apply -f pvc-gluster-dynamic-0001.yaml 
persistentvolumeclaim/pvc-gluster-dynamic-0001 created
[root@master chapter7]# kubectl describe pvc-gluster-dynamic-0001
error: the server doesn't have a resource type "pvc-gluster-dynamic-0001"
[root@master chapter7]# kubectl describe pvc  pvc-gluster-dynamic-0001
Name:          pvc-gluster-dynamic-0001
Namespace:     default
StorageClass:  gluster-dynamic
Status:        Pending
Volume:        
Labels:        <none>
Annotations:   volume.beta.kubernetes.io/storage-class: gluster-dynamic
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      
Access Modes:  
VolumeMode:    Filesystem
Mounted By:    <none>
Events:
  Type     Reason              Age                From                         Message
  ----     ------              ----               ----                         -------
  Warning  ProvisioningFailed  14s (x3 over 31s)  persistentvolume-controller  storageclass.storage.k8s.io "gluster-dynamic" not found

任何支持PV動態供給的存儲系統都可以在定義為存儲類后由PVC動態申請使用、這對於難於預估使用的存儲空間大小及存儲卷數量的使用場景尤為有用例如由StatefulSet控制管理POD對象時,
存儲卷是必備資源,且隨着規模變動,存儲卷的數量也會隨之變動

另外、用戶也可以使用雲端存儲提供的PV動態供給機制,如AWS EBS、AzureDisk、Cinder或GCEPersistentDisk等,將kubernetes部署與Iaas雲端時、此種存儲方式使用的較多、各類雲存儲動態供給的具體使用方式請參考相關的使用手冊

三、PV和PVC的生命周期 

1、架構圖

我們可以將PV看作可用的存儲資源,PVC則是對存儲資源的需求,PV和PVC的相互關系遵循如下圖所示

2、資源供給

Kubernetes支持兩種資源的供應模式:靜態模式(Static)和動態模式(Dynamic)。資源供應的結果就是創建好的PV。

靜態模式:集群管理員手工創建許多PV,在定義PV時需要將后端存儲的特性進行設置。

動態模式:集群管理員無須手工創建PV,而是通過StorageClass的設置對后端存儲進行描述,標記為某種類型。此時要求PVC對存儲的類型進行聲明,系統將自動完成PV的創建及與PVC的綁定。

PVC可以聲明Class為"",說明該PVC禁止使用動態模式。

3、資源綁定

在用戶定義好PVC之后,系統將根據PVC對存儲資源的請求(存儲空間和訪問模式)在已存在的PV中選擇一個滿足PVC要求的PV,一旦找到,就將該PV與用戶定義的PVC進行綁定,

用戶的應用就可以使用這個PVC了。

如果在系統中沒有滿足PVC要求的PV,PVC則會無限期處於Pending狀態,直到等到系統管理員創建了一個符合其要求的PV。PV一旦綁定到某個PVC上,就會被這個PVC獨占,不能再與其他PVC進行綁定了。

在這種情況下,當PVC申請的存儲空間比PV的少時,整個PV的空間就都能夠為PVC所用,可能會造成資源的浪費。如果資源供應使用的是動態模式,則系統在為PVC找到合適的StorageClass后,將自動創建一個PV並完成與PVC的綁定。

4、資源使用

Pod使用Volume的定義,將PVC掛載到容器內的某個路徑進行使用。Volume的類型為persistentVolumeClaim,在后面的示例中再進行詳
細說明。在容器應用掛載了一個PVC后,就能被持續獨占使用。不過,多個Pod可以掛載同一個PVC,應用程序需要考慮多個實例共同訪問一塊存儲空間的問題。

存儲使用(using)

POD資源基於persistentVolumeClaim卷類型的定義、將選擇定的PVC關聯為存儲卷、而后即可為內部的容器所使用、對於支持多種訪問模式的存儲卷來說、用戶需要額外指定要使用的模式
一旦完成將存儲卷掛載值POD對象內的容器中,其應用即可使用關聯的PV提供的存儲空間

PVC保護(partition)

有用戶刪除了仍處於某pod資源使用中的PVC時,Kubernetes不會立即予以移除、而是推遲到不再被任何pod資源使用后方才執行刪除操作處於此種階段的PVC資源的status字段為"termination"
並且其Finalizers字段中包含"kubernetes.io/pvc-protection"

5、資源釋放

當用戶對存儲資源使用完畢后,用戶可以刪除PVC,與該PVC綁定的PV將會被標記為“已釋放”,但還不能立刻與其他PVC進行綁定。
通過之前PVC寫入的數據可能還被留在存儲設備上,只有在清除之后該PV才能再次使用。

6、存儲回收

對於PV,管理員可以設定回收策略,用於設置與之綁定的PVC釋放資源之后如何處理遺留數據的問題。只有PV的存儲空間完成回收,

才能供新的PVC綁定和使用。回收策略詳見下節的說明。下面通過兩張圖分別對在靜態資源供應模式和動態資源供應模式下,PV、PVC、StorageClass及Pod使用PVC的原理進行說明。

下圖描述了在靜態資源供應模式下,通過PV和PVC完成綁定,並供Pod使用的存儲管理機制。

下圖描述了在動態資源供應模式下,通過StorageClass和PVC完成資源動態綁定(系統自動生成PV),並供Pod使用的存儲管理機制

 

1、留存(Retain)

留存策略意味着在刪除PVC之后、kubernetes系統不會自動刪除PV,而僅僅是將它置於"釋放(releases)狀態"、不過,此種狀態的PV尚且不能被其他PVC申請所綁定、因為此前的申請生成的數據仍然存在,
需要由管理員手動決定其后續處理方案。這就意味着,如果想要再次使用此類的PV資源、則需要由管理員按下面的步驟手動執行刪除操作

刪除PV,這折后,此PV的數據依然留存於外部的存儲智商
手工清理存儲系統上依然留存的數學
手工刪除存儲系統級的存儲卷(例如:RBD存儲系統山過的images)以釋放空間、以便再次創建、或者直接將其重新創建為PV

2、回收( Recycle)

如果可被底層存儲插件支持,資源回收策略會在存儲卷商執行數據刪除操作並讓PV資源再次變為可被Claim.另外、管理元也可以配制一個自定義的回收器POD模板、以便執行自定義的回收操作、不過、此種回收策略行將廢棄

3、刪除(delete)

對於支持Delete回收策略的存儲插件來說、在PVC被刪除后會直接移除PV對象、同時移除的還有PV相關的外部存儲系統上的存儲資產(asset)、支持這種操作的存儲系統有AWS EBS、GCE PD、Azure Disk或Cinder。動態創建的PV資源的回收策略屈居於相關存儲類上的定義、存儲類上相關的默認策略為delete、大多數情況下、管理元都需要按用戶期望的處理機制修改此默認策略、以免導致數據費計划內的誤刪除

四、downwardAPI存儲卷

很多時候、應用程序需要給予其所在的環境信息設定運行特性等、這類環境信息包括節點及集群的部分詳細屬性信息等

Nginx進程根據節點的cpu核心數量自動設定要啟動的worker進程數
JVM虛擬機可根據節點內存資源自動個設定其堆內存大小
托管運行於kubernetes的POD對象中的容器化應用偶爾也需要獲取其所屬pod對象的IP、主機名、標簽、注解、UID、請求的CPU及內存資源量及其限額甚至是POD所在的節點名稱

容器可通過環境變量或downwardAPI存儲卷訪問此類信息、不過、標簽和注解僅支持通過存儲卷暴露給容器

1、環境變量式元數據注入

引用downwardAPI元數據信息的常用方式之一是使用容器的環境變量、它通過在valueFrom字段中嵌套fieldRef或resourceFieldRef字段來引用相應的數據源
不過、通常只有常量類的屬性才能夠通過環境變量注入到容器中、畢竟、在進程啟動完成后無法再向其告知變量值的變動、於是、環境變量也支持中途的更新操作可通過fieldRef字段引用的信息具體如下:

pod.spec.nodeName              #節點名稱
pod.spec.serviceAccountName    #pod對象使用的serviceAccount資源名稱
pod.status.hostIP              #節點IP地址
pod.status.podIP               #pod對象的IP地址
pod.metadata.name              #pod對象的名稱
pod.metadata.namespace         #pod對象隸屬的名稱空間
pod.metadata.labels            #pod對象標簽中的指定鍵的值
pod.metadata.annotations       #pod對象注解信息中的指定鍵的值

資源清單

[root@master chapter7]# cat downwardAPI-env.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: env-test-pod
  labels:
    app: env-test-pod
spec:
  containers:
    - name: env-test-container
      image: busybox
      command: [ "/bin/sh", "-c", "env" ]
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      env:
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: MY_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: MY_APP_LABEL
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['app']
        - name: MY_CPU_LIMIT
          valueFrom:
            resourceFieldRef:
              resource: limits.cpu
        - name: MY_MEM_REQUEST
          valueFrom:
            resourceFieldRef:
              resource: requests.memory
              divisor: 1Mi
  restartPolicy: Never

此POD對象創建完成后、向控制台打印所有的環境變量即可終止運行、它僅用於測試通過環境變量注入信息到容器的使用效果

運行查看環境變量

[root@master chapter7]# kubectl create -f downwardAPI-env.yaml 
pod/env-test-pod created
[root@master chapter7]# kubectl get pods -l app=env-test-pod
NAME           READY   STATUS              RESTARTS   AGE
env-test-pod   0/1     ContainerCreating   0          23s
[root@master chapter7]# kubectl get pods -l app=env-test-pod
NAME           READY   STATUS      RESTARTS   AGE
env-test-pod   0/1     Completed   0          30s

而后即可通過控制台日志獲取注入的環境變量
[root@master chapter7]# kubectl logs env-test-pod |grep "^MY_" MY_POD_NAMESPACE=default MY_CPU_LIMIT=1 MY_APP_LABEL=env-test-pod MY_MEM_REQUEST=32 MY_POD_NAME=env-test-pod

未為容器定義資源請求及資源限制時、downwardAPI引用的值即默認為節點的可分配CPU及內存資源量

2、存儲卷式元數據注入

資源清單

[root@master chapter7]# cat downwardAPI-vol.yaml 
kind: Pod
apiVersion: v1
metadata:
  labels:
    zone: east-china
    cluster: downward-api-test-cluster1
    rack: rack-101
    app: dapi-vol-pod
  name: dapi-vol-pod
  annotations:
    annotation1: "test-value-1"
    annotation2: "test-value-2"
spec:
  containers:
    - name: volume-test-container
      image: busybox
      command: ["sh", "-c", "sleep 864000"]
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      volumeMounts:
      - name: podinfo
        mountPath: /etc/podinfo
        readOnly: false
  volumes:
  - name: podinfo
    downwardAPI:
      defaultMode: 420
      items:
      - fieldRef:
          fieldPath: metadata.name
        path: pod_name
      - fieldRef:
          fieldPath: metadata.namespace
        path: pod_namespace
      - fieldRef:
          fieldPath: metadata.labels
        path: pod_labels
      - fieldRef:
          fieldPath: metadata.annotations
        path: pod_annotations
      - resourceFieldRef:
          containerName: volume-test-container
          resource: limits.cpu
        path: "cpu_limit"
      - resourceFieldRef:
          containerName: volume-test-container
          resource: requests.memory
          divisor: "1Mi"
        path: "mem_request"

運行查看

[root@master chapter7]# kubectl apply -f downwardAPI-vol.yaml 
pod/dapi-vol-pod created
[root@master chapter7]# kubectl get pods -l app=dapi-vol-pod
NAME           READY   STATUS    RESTARTS   AGE
dapi-vol-pod   1/1     Running   0          3m38s

接下來即可測試訪問上述的映射文件,例如查看pod對象的標簽列表
[root@master chapter7]# kubectl exec dapi-vol-pod -- cat /etc/podinfo/pod_labels app="dapi-vol-pod" rack="rack-101" zone="east-china" [root@master chapter7]# kubectl label pods dapi-vol-pod env="test" pod/dapi-vol-pod labeled
而后再次查看容器內的pod_labels文件的內容、由如下的命令結果可知新的標簽已經能夠通過相關的文件獲取到:
[root@master chapter7]# kubectl exec dapi-vol-pod -- cat /etc/podinfo/pod_labels app="dapi-vol-pod" cluster="downward-api-test-cluster1" env="test" rack="rack-101" zone="east-china"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM