Kubernetes Storage (Kubernetes 存儲)

六、Kubernetes Storage (Kubernetes 存儲)

臨時存儲:emptydir

半持久化存儲:hostpath

持久化存儲:pvc,pv,nfs

分佈式存儲: glusterfs,rbd,cephfs,雲存儲(EBS,等)

查看K8s支持多少種存儲: kubectl explain pods.spec.volumes

K8S的存儲系統從基礎到高級又大致分爲三個層次:普通Volume,Persistent Volume 和動態存儲供應。

 

1.Volume

K8s中的卷壽命與封裝它的pod相同。卷比pod中所有容器的生命週期都要長,當這個容器重啓時數據仍然可以保存。Pod不存在,卷也不復存在

  • 容器中的Volume

    容器的 Volume,其實就是將一個宿主機上的目錄,跟一個容器裏的目錄綁定掛載在了一起。

  • 持久化 Volume

    宿主機上的目錄,具備“持久性”。即:這個目錄裏面的內容,既不會因爲容器的刪除而被清理掉,也不會跟當前的宿主機綁定。這樣,當容器被重啓或者在其他節點上重建出來之後,它仍然能夠通過掛載這個 Volume,訪問到這些內容。

 

卷類型

empityDir

hostPath

local

nfs

iscsi

persistentVolume

PersistentVolumeClain

projectd

rbd

secret

vsphereVolume

 

 

2.PV(Persistent Volume)

PV 描述的是持久化存儲卷,主要定義的是一個持久化存儲在宿主機上的目錄,比如一個 NFS 的掛載目錄。

通常由運維人員創建

  • 例子1
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.217.149
    path: "/"

 
 

2.1 PV訪問模式

PV可以以資源提供者支持的方式掛載到主機上。供應商具有不同的功能,每個PV訪問模式都將被設置爲該卷支持的特定模式。例如NFS可以支持多個讀寫客戶端,但特定的NFS PV可能以只讀方式導出到服務器上,每個PV都有一套自己的用來描述特定功能的訪問模式。

  • ReadwriteOnce(RWO) 該卷可以被單個節點以讀寫模式掛載
  • ReadOnlyMany(ROX) 該卷可以被多個節點以只讀模式掛載
  • ReadWriteMany(ROX) 該卷可以被多個節點以讀寫模式掛載

 
 

2.2 PVC(Persistent Volume Claim)

PVC是用戶存儲的請求。描述的則是Pod所希望使用的持久化存儲的屬性。比如Volume存儲的大小、可讀寫權限等等。

通常由開發人員創建

  • 例子2
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: manual
  resources:
    requests:
      storage: 1Gi

 
 

2.3 綁定

用戶根據所需存儲空間大小和訪問模式創建(或在動態部署中已創建)一個PVC。Kubernetes的Master節點循環監控新產生的PVC,找到與之匹配的PV(如果有的話),並把他們綁定在一起。動態配置時,循環會一直將PV與這個PVC綁定,直到PV完全匹配PVC。避免PVC請求和得到的PV不一致。綁定一旦形成,PersistentVolumeClaim綁定就是獨有的,不管是使用何種模式綁定的。

如果找不到匹配的volume,用戶請求會一直保持未綁定狀態。在匹配的volume可用之後,用戶請求將會被綁定。

Volume Controller:管理多個控制循環,將PV與PVC進行綁定(PV名稱寫入PVC對象的spec.volumeName)

  • 第一個條件,當然是 PV 和 PVC 的 spec 字段。比如,PV 的存儲(storage)大小,就必須滿足 PVC 的要求。

  • 第二個條件,則是 PV 和 PVC 的 storageClassName 字段必須一樣。

  • 例子3

apiVersion: v1
kind: Pod
metadata:
  name: nginx-nfs
  labels:
    role: web-frontend
spec:
  containers:
  - name: web
    image: nginx
    ports:
      - name: web
        containerPort: 80
    volumeMounts:
        - name: nfs
          mountPath: "/usr/share/nginx/html"
  volumes:
  - name: nfs
    persistentVolumeClaim:
      claimName: nfs

 

2.4 處理PV流程

2.4.1 兩階段

1)第一階段Attach

  • 當一個 Pod 調度到一個節點上之後,kubelet 就要負責爲這個 Pod 創建它的 Volume 目錄。默認情況下,kubelet 爲 Volume 創建的目錄是如下所示的一個宿主機上的路徑

/var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume類型>/<Volume名字>

  • 接下來,kubelet 要做的操作就取決於你的 Volume 類型了

gcloud compute instances attach-disk <虛擬機名字> --disk <遠程磁盤名字>

 

2)第二階段Mount

Attach 階段完成後,爲了能夠使用這個遠程磁盤,kubelet 還要進行第二個操作,即:格式化這個磁盤設備,然後將它掛載到宿主機指定的掛載點上。

  • 通過lsblk命令獲取磁盤設備ID
  • 格式化成ext4格式:sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard
  • 掛載到掛載點:sudo mkdir -p /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume類型>/<Volume名字>

將宿主機目錄與pod定義VolumeMount目錄關聯

docker run -v  /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume類型>/<Volume名字>

 

2.5 PV生命週期

在這裏插入圖片描述

一個PV創建完後狀態會變成Available,等待被PVC綁定。一旦被PVC邦定,PV的狀態會變成Bound,就可以被定義了相應PVC的Pod使用。Pod使用完後會釋放PV,PV的狀態變成Released。變成Released的PV會根據定義的回收策略做相應的回收工作。有三種回收策略,Retain、Delete 和 Recycle。Retain就是保留現場,K8S什麼也不做,等待用戶手動去處理PV裏的數據,處理完後,再手動刪除PV。Delete 策略,K8S會自動刪除該PV及裏面的數據。Recycle方式,K8S會將PV裏的數據刪除,然後把PV的狀態變成Available,又可以被新的PVC綁定使用。

Provisioning ——-> Binding ——–>Using——>Releasing——>Reclaiming

 

2.5.1 Provisioning

這裏有兩種PV的提供方式:靜態或者動態

Static
集羣管理員創建多個PV。 它們攜帶可供集羣用戶使用的真實存儲的詳細信息。 它們存在於Kubernetes API中,可用於消費。
Dynamic
當管理員創建的靜態PV都不匹配用戶的PersistentVolumeClaim時,集羣可能會嘗試爲PVC動態配置卷。 此配置基於StorageClasses:PVC必須請求一個類,並且管理員必須已創建並配置該類才能進行動態配置。 要求該類的聲明有效地爲自己禁用動態配置

 

2.5.2 Binding

在動態配置的情況下,用戶創建或已經創建了具有特定數量的存儲請求和特定訪問模式的PersistentVolumeClaim。 主機中的控制迴路監視新的PVC,找到匹配的PV(如果可能),並將它們綁定在一起。 如果爲新的PVC動態配置PV,則循環將始終將該PV綁定到PVC。 否則,用戶總是至少得到他們要求的內容,但是卷可能超出了要求。 一旦綁定,PersistentVolumeClaim綁定是排他的,不管用於綁定它們的模式。

如果匹配的卷不存在,PVC將保持無限期。 隨着匹配卷變得可用,PVC將被綁定。 例如,提供許多50Gi PV的集羣將不匹配要求100Gi的PVC。 當集羣中添加100Gi PV時,可以綁定PVC。

 

2.5.3 Using

Pod使用PVC作爲卷。 集羣檢查聲明以找到綁定的卷並掛載該卷的卷。 對於支持多種訪問模式的卷,用戶在將其聲明用作pod中的卷時指定所需的模式。

一旦用戶有聲明並且該聲明被綁定,綁定的PV屬於用戶,只要他們需要它。 用戶通過在其Pod的卷塊中包含persistentVolumeClaim來安排Pods並訪問其聲明的PV。

 

2.5.4 Releasing

當用戶完成卷時,他們可以從允許資源回收的API中刪除PVC對象。 當聲明被刪除時,卷被認爲是“釋放的”,但是它還不能用於另一個聲明。 以前的索賠人的數據仍然保留在必須根據政策處理的捲上.

 

2.5.5 Reclaiming

PersistentVolume的回收策略告訴集羣在釋放其聲明後,該卷應該如何處理。 目前,卷可以是保留,回收或刪除。 保留可以手動回收資源。 對於那些支持它的卷插件,刪除將從Kubernetes中刪除PersistentVolume對象,以及刪除外部基礎架構(如AWS EBS,GCE PD,Azure Disk或Cinder卷)中關聯的存儲資產。 動態配置的卷始終被刪除

 

2.5.6 回收策略
  • Retain – 手動重新使用
  • Recycle – 基本的刪除操作 (“rm -rf /thevolume/*”)
  • Delete – 關聯的後端存儲卷一起刪除,後端存儲例如AWS EBS, GCE PD或OpenStack Cinder

目前只有NFS和HostPath支持回收,AWS EBS, GCE PD和Cinder volumes只支持刪除。

 

2.5.7 卷的狀態
  • Available –閒置狀態,沒有被綁定到PVC
  • Bound – 綁定到PVC
  • Released – PVC被刪掉,資源沒有被在利用
  • Failed – 自動回收失敗

 

2.6 StorageClass

  • 人工管理PV的方式:Static Provisionning
  • 自動創建PV的機制:Dynamic Provisioning:通過StorageClass實現

 

2.6.1 StorageClass

在這裏插入圖片描述

  • 作用就是創建PV模板

    PV的屬性。比如存儲類型,Volume的大小等等

    創建這種PV需要用到的存儲插件。如Ceph等等

  • 例子(Rook-Ceph)

StorageCalss定義

apiVersion: ceph.rook.io/v1beta1
kind: Pool
metadata:
  name: replicapool
  namespace: rook-ceph
spec:
  replicated:
    size: 3
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: block-service
provisioner: ceph.rook.io/block
parameters:
  pool: replicapool
  #The value of "clusterNamespace" MUST be the same as the one in which your rook cluster exist
  clusterNamespace: rook-ceph

kubectl create -f sc.yaml

PVC定義

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: block-service
  resources:
    requests:
      storage: 30Gi

kubectl create -f pvc1.yaml

kubectl describe pvc claim1

 

2.7 PV類型

PV類型以插件形式實現。K8s目前支持如下插件類型:
NFS
RBD(Ceph Block Device)
CephFS
Cinder
Glusterfs
HostPath
VMware
GCEPersistentDisk
AWSElasticStore
AzureFile
Fibre Channel
FlexVolume
ISCSI

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

 

2.8 實戰1

基於NFS類型的PV

1)首先創建NFS服務

  • yum install nfs-utils rpcbind -y

    nfs-utils所有節點都需要安裝

  • systemctl restart rpcbind nfs

  • 編輯共享配置文件

    /etc/exports寫入/mnt/share *(rw)

    exportfs -r生效

[NFS共享目錄] [NFS客戶端地址1(參數1,參數2,參數3……)] [客戶端地址2(參數1,參數2,參數3……)]

mkdir /mnt/share

chmod 777 /mnt/share

showmount -e

 
2)創建PV

vim pv1.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.217.149
    path: "/mnt/share"

kubectl get pv

kubectl describe pv nfs

在這裏插入圖片描述

 
3)創建PVC

vim pvc1.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: manual
  resources:
    requests:
      storage: 1Gi

kubectl get pvc

kubectl describe pvc nfs

在這裏插入圖片描述

 
4)創建pod調用pvc

apiVersion: v1
kind: Pod
metadata:
  name: nginx-nfs
  labels:
    role: web-frontend
spec:
  containers:
  - name: web
    image: nginx
    ports:
      - name: web
        containerPort: 80
    volumeMounts:
        - name: nfs
          mountPath: "/usr/share/nginx/html"
  volumes:
  - name: nfs
    persistentVolumeClaim:
      claimName: nfs

查看

[root@kubernetes01 ~]# kubectl get pod
NAME                               READY   STATUS              RESTARTS   AGE
nginx-nfs                          1/1     Running             0          6m10s

在/mnt/share/1寫入

[root@kubernetes01 ~]# echo hello >/mnt/share/1
[root@kubernetes01 ~]# cat /mnt/share/1
hello

進入pod查看

[root@kubernetes01 ~]# kubectl exec -it nginx-nfs /bin/bash
root@nginx-nfs:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
root@nginx-nfs:/# ls /usr/share/nginx/html/
1
root@nginx-nfs:/# echo nginx > /usr/share/nginx/html/2  
root@nginx-nfs:/# ls /usr/share/nginx/html/
1  2
root@nginx-nfs:/# cat /usr/share/nginx/html/1  
hello
root@nginx-nfs:/# cat /usr/share/nginx/html/2
nginx
root@nginx-nfs:/# exit
exit

退出查看

[root@kubernetes01 ~]# cat /mnt/share/1
hello
[root@kubernetes01 ~]# cat /mnt/share/2
nginx

刪除/mnt/share/1

[root@kubernetes01 ~]# cd /mnt/share
[root@kubernetes01 share]# ls
1  2
[root@kubernetes01 share]# rm -rf 1
[root@kubernetes01 share]# ls
2

回到pod查看

[root@kubernetes01 share]# kubectl exec -it nginx-nfs /bin/bash
root@nginx-nfs:/# ls /usr/share/nginx/html/
2

 

 

2.9 實戰2

基於NFS的動態PV

NFS StorageClass

https://github.com/kubernetes-incubator/external-storage/blob/master/nfs/deploy/kubernetes

接着實戰1的環境

先做點準備工作

mkdir /nfs3

chmod 777 /nfs3

在/etc/exports寫入/nfs3 *(rw)

exportfs -r生效

 

1)創建RBAC授權rbac.yaml

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
  - apiGroups: [""]
    resources: ["services", "endpoints"]
    verbs: ["get"]
  - apiGroups: ["extensions"]
    resources: ["podsecuritypolicies"]
    resourceNames: ["nfs-provisioner"]
    verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    namespace: default
roleRef:
    kind: ClusterRole
    name: nfs-provisioner-runner
    apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    namespace: default
roleRef:
    kind: Role
    name: leader-locking-nfs-provisioner
    apiGroup: rbac.authorization.k8s.io

 

2)serviceaccount.yaml文件

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner

 
3)創建Storageclass類storageclass-nfs.yaml

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: nfs
provisioner: example.com/nfs

 

4)創建nfs的deployment,修改相應的nfs服務器ip及掛載路徑即可。deployment-nfs.yaml

拉取鏡像registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner

docker pull registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner

deployment-nfs.yaml文件內容

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nfs-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: example.com/nfs
            - name: NFS_SERVER
              value: 192.168.217.149
            - name: NFS_PATH
              value: /nfs3
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.217.149
            path: /nfs3

kubectl get pod

 
5)創建測試claim

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim1
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi
  storageClassName: nfs

kubectl get pvc

 

6)創建一個測試的Pod使用這個PVC,編寫test-pod.yaml文件如下

kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: busybox
    command:
      - "/bin/sh"
    args:
      - "-c"
      - "touch /mnt/SUCCESS && exit 0 || exit 1"
    volumeMounts:
      - name: nfs-pvc
        mountPath: "/mnt"
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim1

查看Pod狀態是否變爲Completed。如果是,則應該能在NFS系統的共享路徑中看到一個SUCCESS文件。

這樣,StorageClass動態創建PV的功能就成功實現了。

[root@kubernetes01 ~]# ls /nfs3/default-test-claim1-pvc-bab1c62f-8080-11ea-811d-000c29bec19e/
SUCCESS

 

7)創建StatefulSet案例

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx1"
  replicas: 2
  volumeClaimTemplates:
  - metadata:
      name: test
      annotations:
        volume.beta.kubernetes.io/storage-class: "nfs"
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
  template:
    metadata:
      labels:
        app: nginx1
    spec:
      serviceAccount: nfs-provisioner
      containers:
      - name: nginx1
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: "/persistentvolumes"
          name: test

測試

在這裏插入圖片描述

進入web-0測試

[root@kubernetes01 ~]# ls /nfs3/default-test-web-0-pvc-306e26d2-8081-11ea-811d-000c29bec19e/
[root@kubernetes01 ~]# kubectl exec -it web-0 /bin/bash
root@web-0:/# ls /persistentvolumes/
root@web-0:/# echo hello > /persistentvolumes/1
root@web-0:/# exit
exit

回到宿主機kubernetes01

[root@kubernetes01 ~]# ls /nfs3/default-test-web-0-pvc-306e26d2-8081-11ea-811d-000c29bec19e/
1
[root@kubernetes01 ~]# cat  /nfs3/default-test-web-0-pvc-306e26d2-8081-11ea-811d-000c29bec19e/1 
hello

在回到web-0

[root@kubernetes01 ~]# kubectl exec -it web-0 /bin/bash
root@web-0:/# ls /persistentvolumes/
1  2
root@web-0:/# cat /persistentvolumes/2
web0
root@web-0:/# rm -rf /persistentvolumes/2     
root@web-0:/# rm -rf /persistentvolumes/1
root@web-1:/# exit
exit

這時宿主機也沒有了、

而web-1和web-0是隔離的,並不互相影響。

 

3.Local Persistent Volume

“本地”持久化存儲,直接使用宿主機上的本機磁盤目錄,而不依賴於遠程存儲服務,來提供“持久化”的容器Volume。

3.1 應用場景

  • 分佈式數據存儲:MongoDB
  • 分佈式文件系統:GlusterFS,Ceph
  • 進行數據緩存的分佈式應用

 

3.2 實現原理

  • 將本地硬盤抽象成PV:一個PV一塊盤?

  • Pod正常調度到指定Node

    在開始使用 Local Persistent Volume 之前,你首先需要在集羣裏配置好磁盤或者塊設備。

    實現方法

    • 第一種,你的宿主機掛載並格式化一個可用的本地磁盤,這也是最常規的操作;
    • 第二種,對於實驗環境,你其實可以在宿主機上掛載幾個 RAM Disk(內存盤)來模擬本地磁盤。

 

3.3 實戰

採用第二種

1)在kubernetes02宿主機上創建掛載點,用RAM Disk模擬本地磁盤

# 在kubernetes02上執行
$ mkdir /mnt/disks
$ for vol in vol1 vol2 vol3; do
    mkdir /mnt/disks/$vol
    mount -t tmpfs $vol /mnt/disks/$vol
done

2)創建本地磁盤對應PV:local-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/vol1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - kubernetes02

kubectl create -f local-pv.yaml

kubectl get pv

 

3)創建StorageClass描述此PV:local-sc.yaml

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

provisioner: kubernetes.io/no-provisioner:因爲 Local Persistent Volume 目前尚不支持 Dynamic Provisioning,所以它沒辦法在用戶創建 PVC 的時候,就自動創建出對應的 PV。也就是說,我們前面創建 PV 的操作,是不可以省略的。

volumeBindingMode=WaitForFirstConsumer:延遲綁定,當你提交了 PV 和 PVC 的 YAML 文件之後,Kubernetes 就會根據它們倆的屬性,以及它們指定的 StorageClass 來進行綁定。只有綁定成功後,Pod 才能通過聲明這個 PVC 來使用對應的 PV。

Pod 聲明 PVC pvc1,node Affinity: node2

local PV: pv1,pv2

pv1:磁盤所在的節點node1。。。。pvc1和pv1綁定了。

pv2:磁盤所在的節點node2

#kubectl create Pod

所以pvc的綁定不能夠提前

 
4)創建PVC:local-pvc.yaml

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

kubectl create -f local-pvc.yaml

kubectl get pvc

 
5)編寫pod使用這個PVC pod.yaml

kind: Pod
apiVersion: v1
metadata:
  name: example-pv-pod
spec:
  volumes:
    - name: example-pv-storage
      persistentVolumeClaim:
       claimName: example-local-claim
  containers:
    - name: example-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: example-pv-storage

 
6)測試文件寫入

[root@kubernetes01 ~]# kubectl exec -it example-pv-pod /bin/bash
root@example-pv-pod:/usr/share/nginx/html# ls
root@example-pv-pod:/usr/share/nginx/html# echo hello > test.txt     
root@example-pv-pod:/usr/share/nginx/html# ls
test.txt

# 在kubernetes02上
[root@kubernetes02 ~]# ls /mnt/disks/vol1
test.txt
[root@kubernetes02 ~]# cat /mnt/disks/vol1/test.txt 
hello

 

7)刪除pod測試

[root@kubernetes01 ~]# kubectl delete -f pod.yaml

# 回到kubernetes02
[root@kubernetes02 ~]# ls /mnt/disks/vol1
hello  test.txt

這時會發現原來數據還在

再次創建pod.yaml

[root@kubernetes01 ~]# kubectl apply -f pod.yaml 
pod/example-pv-pod created
[root@kubernetes01 ~]# kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
example-pv-pod   1/1     Running   0          25s
[root@kubernetes01 ~]# kubectl exec -it example-pv-pod /bin/bash
root@example-pv-pod:/# ls /usr/share/nginx/html/
hello  test.txt
root@example-pv-pod:/# 

這時會發現上次pod創建的數據還在,神奇。。。。

root@example-pv-pod:/# echo shenqi > /usr/share/nginx/html/zhenshenqi

# 回到kubernetes02
[root@kubernetes02 ~]# ls /mnt/disks/vol1
hello  test.txt  zhenshenqi

確實神奇。。。

 
 

4.總結

4.1 Volume

單節點Volume是最簡單的普通Volume,它和Docker的存儲卷類似,使用的是Pod所在K8S節點的本地目錄。具體有兩種,一種是 emptyDir,是一個匿名的空目錄,由Kubernetes在創建Pod時創建,刪除Pod時刪除。另外一種是 hostPath,與emptyDir的區別是,它在Pod之外獨立存在,由用戶指定路徑名。這類和節點綁定的存儲卷在Pod遷移到其它節點後數據就會丟失,所以只能用於存儲臨時數據或用於在同一個Pod裏的容器之間共享數據。

4.2 PV

普通Volume和使用它的Pod之間是一種靜態綁定關係,在定義Pod的文件裏,同時定義了它使用的Volume。Volume 是Pod的附屬品,我們無法單獨創建一個Volume,因爲它不是一個獨立的K8S資源對象。

而Persistent Volume 簡稱PV是一個K8S資源對象,所以我們可以單獨創建一個PV。它不和Pod直接發生關係,而是通過Persistent Volume Claim,簡稱PVC來實現動態綁定。Pod定義裏指定的是PVC,然後PVC會根據Pod的要求去自動綁定合適的PV給Pod使用。

4.3 PVC

4.4 LPV

4.5 PV和普通Volume的區別是什麼

普通Volume和使用它的Pod之間是一種靜態綁定關係,在定義Pod的文件裏,同時定義了它使用的Volume。Volume 是Pod的附屬品,我們無法單獨創建一個Volume,因爲它不是一個獨立的K8S資源對象。

而Persistent Volume 簡稱PV是一個K8S資源對象,所以我們可以單獨創建一個PV。它不和Pod直接發生關係,而是通過Persistent Volume Claim,簡稱PVC來實現動態綁定。Pod定義裏指定的是PVC,然後PVC會根據Pod的要求去自動綁定合適的PV給Pod使用。

PV的訪問模式有三種:

第一種,ReadWriteOnce:是最基本的方式,可讀可寫,但只支持被單個Pod掛載。

第二種,ReadOnlyMany:可以以只讀的方式被多個Pod掛載。

第三種,ReadWriteMany:這種存儲可以以讀寫的方式被多個Pod共享。不是每一種存儲都支持這三種方式,像共享方式,目前支持的還比較少,比較常用的是NFS。在PVC綁定PV時通常根據兩個條件來綁定,一個是存儲的大小,另一個就是訪問模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章