Kubernetes系列之Kubernetes存儲卷

第一章、前言

默認狀況下容器的數據都是非持久化的, 在容器消亡之後數據也跟着丟失, 因此 Docker 提供了 Volume 機制以便將數據持久化存儲。 相似的, Kubernetes 提供了更強大的 Volume 機制和豐富的插件, 解決了容器數據持久化和容器間共享數據的問題。
與 Docker 不一樣, Kubernetes Volume 的生命週期與 Pod 綁定容器掛掉後 Kubelet 再次重啓容器時, Volume 的數據依然還在而 Pod 刪除時, Volume 纔會清理。
數據是否丟失取決於具體的 Volume 類型, 好比 emptyDir 的數據會丟失, 而 PV 的數據則不會丟
PersistentVolume(pv)和PersistentVolumeClaim(pvc)是k8s提供的兩種API資源,用於抽象存儲細節。管理員關注於如何經過pv提供存儲功能而無需關注用戶如何使用,一樣的用戶只須要掛載pvc到容器中而不須要關注存儲卷採用何種技術實現。
pvc和pv的關係與pod和node關係相似,前者消耗後者的資源。pvc能夠向pv申請指定大小的存儲資源並設置訪問模式。html

第二章、pv pvc相關知識

生命週期

pv和pvc遵循如下生命週期:
1.供應準備。管理員在集羣中建立多個pv供用戶使用。
 2.綁定。用戶建立pvc並指定須要的資源和訪問模式。在找到可用pv以前,pvc會保持未綁定狀態。
 3.使用。用戶可在pod中像volume同樣使用pvc。
 4.釋放。用戶刪除pvc來回收存儲資源,pv將變成「released」狀態。因爲還保留着以前的數據,這些數據須要根據不一樣的策略來處理,不然這些存儲資源沒法被其餘pvc使用。
 5.回收。pv能夠設置三種回收策略:保留(Retain),回收(Recycle)和刪除(Delete)。
   保留策略容許人工處理保留的數據。
   刪除策略將刪除pv和外部關聯的存儲資源,須要插件支持。
   回收策略將執行清除操做,以後能夠被新的pvc使用,須要插件支持。node

pv屬性

pv擁有如下屬性:
  容量。目前僅支持存儲大小,將來可能支持IOPS和吞吐量等。
  訪問模式。ReadWriteOnce:單個節點讀寫。ReadOnlyMany:多節點只讀。ReadWriteMany:多節點讀寫。掛載時只能使用一種模式。
  回收策略。目前NFS和HostPath支持回收。 AWS、EBS、GCE、PD和Cinder支持刪除。
  階段。分爲Available(未綁定pvc)、Bound(已綁定)、Released(pvc已刪除但資源未回收)、Failed(自動回收失敗)</pre>nginx

pvc屬性

訪問模式。與pv的語義相同。在請求資源時使用特定模式。
資源。申請的存儲資源數量</pre>git

pv類型

emptyDir
hostPath
gcePersistentDisk
awsElasticBlockStore
nfs
iscsi
flocker
glusterfs
rbd
cephfs
gitRepo
secret
persistentVolumeClaim
downwardAPI
azureFileVolume
................
........(如下省略)web

目前經常使用Volume 類型 

emptyDir api

若是 Pod 設置了 emptyDir 類型 Volume, Pod 被分配到 Node 上時候, 會建立emptyDir, 只要 Pod 運行在 Node 上, emptyDir 都會存在( 容器掛掉不會致使emptyDir 丟失數據) , 可是若是 Pod 從 Node 上被刪除( Pod 被刪除, 或者 Pod 發生遷移) , emptyDir 也會被刪除, 而且永久丟失。服務器

hostPath 網絡

hostPath 容許掛載 Node 上的文件系統到 Pod 裏面去。 若是 Pod 須要使用 Node 上的文件, 可使用 hostPath</pre>app

NFS frontend

NFS 是 Network File System 的縮寫, 即網絡文件系統。 Kubernetes 中經過簡單地配置就能夠掛載 NFS 到 Pod 中, 而 NFS 中的數據是能夠永久保存的, 同時 NFS 支持同時寫操做。

gcePersistentDisk

gcePersistentDisk 能夠掛載 GCE 上的永久磁盤到容器, 須要 Kubernetes 運行在 GCE的 VM 中

awsElasticBlockStore

awsElasticBlockStore 能夠掛載 AWS 上的 EBS 盤到容器, 須要 Kubernetes 運行在AWS 的 EC2 上。

gitRepo

gitRepo volume 將 git 代碼下拉到指定的容器路徑中

Projected Volume

Projected volume 將多個 Volume 源映射到同一個目錄中, 支持 secret、 downwardAPI和 configMap </pre>

第三章、簡單示例

一、emptyDir (節點級存儲,生命週期與pod相同)

# cat emptydir.yaml  #pod中有兩個container掛載同一個emptyDir,nginx提供web服務,busybox則循環向掛載目錄下的index.html文件寫入數據
apiVersion: v1
kind: Pod
metadata:
  name: emptydir
  namespace: default
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: myapp
      containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  - name: busybox
    image: busybox:latest
    volumeMounts:     #見pod的volume掛載到container中
    - name: html      #名稱須要和 volumes中的name一致
      mountPath: /data   #掛載volume在container中的路徑
    command:
    - "/bin/sh"
    - "-c"
    - "while true; do echo $(date) >> /data/index.html; sleep 2; done"
  volumes:    #建立pod可使用的volume,能夠有多個
  - name: html  
    emptyDir: {}  #volume類型,默認不限制使用空間

查看pod運行狀態,並訪問

# kubectl apply -f emptydir.yaml
pod/emptydir created

# kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP            NODE               
emptydir   2/2     Running   0          76s   10.244.3.34   huoban-k8s-node01

# while true; do curl 10.244.3.34; sleep 1; done
Fri Sep 20 03:34:38 UTC 2019
Fri Sep 20 03:34:40 UTC 2019
Fri Sep 20 03:34:42 UTC 2019
......

二、hostPath (節點級存儲,生命週期和node相同)

#cat host-path.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-hostpath
  namespace: default 
spec:
  containers: - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts: - name: html
      mountPath: /usr/share/nginx/html
  volumes: - name: html
    hostPath:
      path: "/data/pod/volumel"  #依據type的值來肯定掛載路徑是否須要建立 type: DirectoryOrCreate  #掛載目錄不存在則建立

# kubectl apply -f host-path.yaml
pod/pod-hostpath created

# kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE               
pod-hostpath   1/1     Running   0          58s   10.244.5.11   huoban-k8s-node03

手動建立目錄並添加html文件測試

# ssh node3 "ls -l /data/pod/volumel"
.
# ssh node03 "touch /data/pod/volumel/index.html"
# ssh node03 "ls -al /data/pod/volumel"
total 8
drwxr-xr-x 2 root root 4096 Sep 20 15:00 .
drwxr-xr-x 3 root root 4096 Sep 20 14:56 ..
-rw-r--r-- 1 root root    0 Sep 20 15:00 index.html

# echo "node03" > /data/pod/volumel/index.html  #在node03服務器上執行
# cat /data/pod/volumel/index.html
node03

# curl 10.244.5.11
node03

#刪除服務,數據還在
# kubectl delete -f host-path.yaml
pod "pod-hostpath" deleted
# ssh node03 "ls -al /data/pod/volumel"
total 12
drwxr-xr-x 2 root root 4096 Sep 20 15:00 .
drwxr-xr-x 3 root root 4096 Sep 20 14:56 ..
-rw-r--r-- 1 root root    7 Sep 20 15:04 index.html

三、NFS (永久存儲,生命週期與NFS server相同,不會刪除)

一、在master上操做
# cat pod-nfs-vol.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-nfs
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    nfs:
      path: "/data/volumes/v1"  #該目錄在NFS server上必須存在並能夠被集羣中node節點能夠掛載,node節點須要安裝nfs-utils,能夠執行NFS 掛載操做      
      server: 172.16.17.10 #該server須要安裝NFS 服務,並共享path中的目錄或文件

二、在其中一臺node節點上作測試
# mount -t nfs 172.16.17.10:/data/volumes/v1 /mnt  在任意一節點上進行掛載測試,肯定能夠掛載是否能夠成功,須要安裝nfs-utils工具包
# df -h |grep mnt  #查看掛載狀態
172.16.17.10:/data/volumes/v1 77G 3.5G 74G 5% /mnt
# umount /mnt  #確認沒有問題後卸載

三、測試運行
# kubectl apply -f pod-nfs-vol.yaml #建立pod
pod "pod-nfs" created
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
pod-nfs 1/1 Running 0 17s 10.244.1.154 huoban-k8s-node01 

四、在節點上測試建立文件
#在NFS server上添加一個測試HTML文件
# cd /data/volumes/v1/   #掛載目錄
# echo "<h1>NFS Server volume v1</h1>" > index.html

五、訪問一下並測試數據是否丟失
# curl 10.244.1.154
<h1>NFS Server volume v1</h1>
# kubectl delete pod pod-nfs   #刪除剛剛建立的pod
pod "pod-nfs" deleted
# kubectl apply -f pod-nfs-vol.yaml  #再從新建立
pod "pod-nfs" created

# kubectl get pod -o wide #查看新建立後pod所在的node節點級IP地址
NAME READY STATUS RESTARTS AGE IP NODE
pod-nfs 1/1 Running 0 17s 10.244.2.192 huoban-k8s-node02

# curl 10.244.2.192  #再次訪問一下,文件依然存在,文件不會隨着pod的終結而銷燬
<h1>NFS Server volume v1</h1>

四、建立PV和PVC(用NFS建立)

NFS server上建立多個掛載目錄,並共享

# cat /etc/exports
/data/volumes/v1  172.16.0.0/16(rw,no_root_squash)
/data/volumes/v2  172.16.0.0/16(rw,no_root_squash)
/data/volumes/v3  172.16.0.0/16(rw,no_root_squash)
/data/volumes/v4  172.16.0.0/16(rw,no_root_squash)
/data/volumes/v5  172.16.0.0/16(rw,no_root_squash)

# ll /data/volumes/
總用量 0
drwxr-xr-x 2 root root 24 2019-09-20 16:28 v1
drwxr-xr-x 2 root root 24 2019-09-20 16:28 v2
drwxr-xr-x 2 root root 24 2019-09-20 16:28 v3
drwxr-xr-x 2 root root 24 2019-09-20 16:28 v4
drwxr-xr-x 2 root root 24 2019-09-20 16:28 v5

# exportfs 
/data/volumes/v1 172.16.0.0/16
/data/volumes/v2 172.16.0.0/16
/data/volumes/v3 172.16.0.0/16
/data/volumes/v4 172.16.0.0/16
/data/volumes/v5 172.16.0.0/16
# showmount -e
Export list for huoban-k8s-nfs:
/data/volumes/v5 172.16.0.0/16
/data/volumes/v4 172.16.0.0/16
/data/volumes/v3 172.16.0.0/16
/data/volumes/v2 172.16.0.0/16
/data/volumes/v1 172.16.0.0/16

將NFS server共享的目錄建立爲PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-vol-001   #不容許定義名稱空間,應爲pv是屬於集羣級別的
spec:
  capacity: #pv的大小
    storage: 5Gi
  accessModes:    #訪問的模型,具體訪問模型官方文檔連接: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes
    - ReadWriteOnce  #支持的訪問模型與具體的共享存儲設備類型有關,具體見上方連接
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /data/volumes/v1
    server: 172.16.17.10
---
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: nfs-vol-02
spec:
  capacity: 
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /data/volumes/v2
    server: 172.16.17.10
---  
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: nfs-vol-03
spec:
  capacity: 
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /data/volumes/v3
    server: 172.16.17.10
---  
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: nfs-vol-04
spec:
  capacity: 
    storage: 15Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /data/volumes/v4
    server: 172.16.17.10
---  
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: nfs-vol-05
spec:
  capacity: 
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /data/volumes/v5
    server: 172.16.17.10

# kubectl apply -f nfs-vol.yaml 
persistentvolume "nfs-vol-01" created
persistentvolume "nfs-vol-02" created
persistentvolume "nfs-vol-03" created
persistentvolume "nfs-vol-04" created
persistentvolume "nfs-vol-05" created

# kubectl get pv
NAME               CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM                       STORAGECLASS   REASON    AGE
nfs-vol-01         5Gi        RWO,RWX        Recycle          Available                                                          7s
nfs-vol-02         5Gi        RWO            Recycle          Available                                                          7s
nfs-vol-03         10Gi       RWO,RWX        Recycle          Available                                                          7s
nfs-vol-04         15Gi       RWO            Recycle          Available                                                          7s
nfs-vol-05         20Gi       RWO,RWX        Recycle          Available                                                          7s

#建立一個PVC
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
  namespace: default
spec:
  accessModes: ["ReadWriteOnce"] #pvc的訪問模式必定是pv訪問模式的子集
  resources:
    requests:
      storage: 5Gi

---
apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    persistentVolumeClaim:
      claimName: my-pvc

# kubectl apply -f pod-pvc-vol.yaml
persistentvolumeclaim "my-pvc" created
pod "pod-pvc" created

# kubectl get pvc
NAME      STATUS    VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc    Bound     nfs-vol-02   5Gi        RWO                           1m

# kubectl get pv  #查看pv狀態的變化,nfs-vol-02被 default名稱空間下my-pvc申請並綁定
NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM            STORAGECLASS   REASON    A
nfs-vol-01   5Gi        RWO,RWX        Recycle          Available                                             9
nfs-vol-02   5Gi        RWO            Recycle          Bound       default/my-pvc                            9
nfs-vol-03   10Gi       RWO,RWX        Recycle          Available                                             9
nfs-vol-04   15Gi       RWO            Recycle          Available                                             9
nfs-vol-05   20Gi       RWO,RWX        Recycle          Available                                       

# 查看下pod的建立信息
# kubectl describe pod pod-pvc 
......
Volumes:
  html:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  my-pvc
    ReadOnly:   false
  default-token-tcwjz:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-tcwjz
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From                 Message
  ----     ------                 ----             ----                 -------
  Warning  FailedScheduling       8m (x2 over 8m)  default-scheduler    pod has unbound PersistentVolumeClaims (repeated 2 times)
  Normal   Scheduled              8m               default-scheduler    Successfully assigned pod-pvc to huoban-k8s-node01
  Normal   SuccessfulMountVolume  8m               kubelet, huoban-k8s-node01  MountVolume.SetUp succeeded for volume "default-token-tcwjz"
  Normal   SuccessfulMountVolume  8m               kubelet, huoban-k8s-node01  MountVolume.SetUp succeeded for volume "nfs-vol-02"
  Normal   Pulled                 8m               kubelet, huoban-k8s-node01  Container image "ikubernetes/myapp:v1" already present on machine
  Normal   Created                7m               kubelet, huoban-k8s-node01  Created container
  Normal   Started                7m               kubelet, huoban-k8s-node01  Started container

#注意:處於綁定狀態下的pv沒法直接被刪除,若是須要刪除被綁定的pv,須要先刪除申請綁定的PVC
相關文章
相關標籤/搜索