Kubernetes系列之Kubernetes存儲卷

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申請指定大小的存儲資源並設置訪問模式。

### 第二章、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使用,需要插件支持。

#### pv屬性

pv擁有以下屬性:

  容量。目前僅支持存儲大小,未來可能支持IOPS和吞吐量等。

  訪問模式。ReadWriteOnce:單個節點讀寫。ReadOnlyMany:多節點只讀。ReadWriteMany:多節點讀寫。掛載時只能使用一種模式。

  回收策略。目前NFS和HostPath支持回收。 AWS、EBS、GCE、PD和Cinder支持刪除。

  階段。分為Available(未綁定pvc)、Bound(已綁定)、Released(pvc已刪除但資源未回收)、Failed(自動回收失敗)

#### pvc屬性

訪問模式。與pv的語義相同。在請求資源時使用特定模式。

資源。申請的存儲資源數量

#### pv類型

emptyDir

hostPath

gcePersistentDisk

awsElasticBlockStore

nfs

iscsi

flocker

glusterfs

rbd

cephfs

gitRepo

secret

persistentVolumeClaim

downwardAPI

azureFileVolume

................

........(以下省略)

#### 目前常用Volume 類型

**emptyDir**

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

**hostPath**

hostPath 允許掛載 Node 上的文件系統到 Pod 裡面去。 如果 Pod 需要使用 Node 上的文件, 可以使用 hostPath

**NFS**

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

### 第三章、簡單示例

**1、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

......

```

**2、[hostPath](https://kubernetes.io/docs/concepts/storage/volumes#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

```

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

```

1、在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中的目錄或文件

2、在其中一臺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 #確認沒有問題後卸載

3、測試運行

# 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

4、在節點上測試創建文件

#在NFS server上添加一個測試HTML文件

# cd /data/volumes/v1/ #掛載目錄

# echo "

NFS Server volume v1

" > index.html

5、訪問一下並測試數據是否丟失

# curl 10.244.1.154

NFS Server volume v1

# 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的終結而銷燬

NFS Server volume v1

```

**4、創建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

```


分享到:


相關文章: