【本文目標(biāo)】
- Kubernetes集群怎樣通過Volume做數(shù)據(jù)持久化的?
- 持久卷組件 -
Persistemt Volume - 使用持久卷,組件 -
Persistent Volume Claim - 在使用持久卷中想要自動創(chuàng)建持久卷,組件 -
Storage Class
【前置文章】
- 【k8s學(xué)習(xí)】Kubernetes學(xué)習(xí)——核心組件和架構(gòu)
- 【k8s學(xué)習(xí)】minikube、kubectl、yaml配置文件的介紹
- 【k8s學(xué)習(xí)】在minikube上布署MongoDB和MongoExpress
- 【k8s學(xué)習(xí)】kubernetes namespace介紹
- 【k8s學(xué)習(xí)】Kubernetes Ingress介紹
- 【k8s學(xué)習(xí)】Kubernetes打包工具Helm介紹
1. Volume使用場景
1.1 Use Case-1:mysql Pod需要Storage:
假設(shè)我們有個項(xiàng)目叫my-app,接連了另一個Pod叫mysql,如果mysql重啟了,那么里面存放的數(shù)據(jù)也會丟失,原因是Kubernetes并沒有提供在Pod之外的持久化,一旦Pod重啟了,數(shù)據(jù)就丟失了。
-
Storage that doesn't depend on the pod lifecycle:我們需要在Pod外有存儲數(shù)據(jù),以便不受Pod重啟的影響。 -
Storage must be available on all nodes:假設(shè)一個mysql Pod掛掉了,那么admin controller manager發(fā)現(xiàn)后,就會讓scheduler再找合適的Node重新創(chuàng)建一個Pod,所以新的Pod有可能創(chuàng)建在活著的Worker Node中的任一一個,即這個存儲要對所有的節(jié)點(diǎn)都可見。 -
Storage needs to survive even if cluster crashes:當(dāng)所有的節(jié)點(diǎn)都掛了,Storage里的數(shù)據(jù)也不能丟失。
1.2 Use Case-2:my-app本身可能也需要讀寫文件
比如一些session或是額外的配置等信息,my-app Pod本身,也可能會讀寫數(shù)據(jù),這時候我們就可以配置Persistent Volume,簡稱pv。
2. Persistent Volume
官網(wǎng):https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/
2.1 介紹
-
a cluster resource:集群中的一種資源,比如ram內(nèi)存或是cpu。 -
created via YAML file:和別的組件一樣,可以通過YAML文件創(chuàng)建。- 創(chuàng)建的時候kind為
PersistentVolume。 - spec中定義了一些自有的屬性,比如占有空間為多少?(
spec.capacity.storage)
- 創(chuàng)建的時候kind為
-
Needs actual physical storage:持久化的地方必須是能支持存儲的地方,如集群里的某個存儲空間或是集群外的某臺Server或是云服務(wù)器。所以這里有個問題就是如何讓Kubernetes集群讀取到這些存儲。 -
what type of storage do you need? need to create & manage them by yourself:Persistent Volume更像是一個接口,它只提供了一些規(guī)范,至于存儲的類型以及創(chuàng)建和管理、備份,都在Kubernetes之外,并不歸K8s集群管理。
2.2 yaml配置示例
下述示例中的Storage的地方是NFS文件系統(tǒng):
apiVersion:
kind: persistentVolume
metadata:
name: pv-name
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessMode:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.0
nfs:
path: /dir/path/on/nfs/server
server: nfs-server-ip-address
上述spec中定義了三部分:
- 存儲能力
- 額外的信息比如進(jìn)入的模式
- nfs參數(shù)
不同的存儲類型,配置可能會長不一樣。
從官網(wǎng)上可以看到,卷的類型超過了20種:https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes
Persistent Volume并不從屬于某個命令空間,它是全局的組件。即所有的命名空間下的組件,都可引用到該pv組件。
2.3 Local Volume vs. Remote Volume
根據(jù)存放地點(diǎn)分類:
-
Local Volume(在Kubernetes集群內(nèi)),這種Storage就違反了1.1章的特點(diǎn)2和特點(diǎn)3,即它是跟集群中的某個Node綁定了,所以有可能會掛掉,以及如果集群down了,這個Storage也可能down掉。正因?yàn)榇?,像DB數(shù)據(jù)庫的持久化存儲,最好放在集群外,即Remove Volume中。 -
Remote Volume,即集群外部存儲,符合1.1章節(jié)的三個特點(diǎn)。
什么時候創(chuàng)建Persistent Volume?
如果某個Pod依賴于pv,那么這個pv需要在Pod被創(chuàng)建之前創(chuàng)建。
誰來創(chuàng)建?
一般來說,開發(fā)人員需要告訴admin(可能是DevOps Team)某個項(xiàng)目需要用到Persistent Volume,然后DevOps人員根據(jù)開發(fā)人員的需求,在Kubernetes集群中幫忙定義并創(chuàng)建好了該pv。
在定義好之后,開發(fā)人員則需要在具體的Pod的yaml中定義引用該pv,在yaml中聲明需要用到某個pv,這時候需要另一個組件,叫Persistent Volume Claim,簡稱pvc。
3. Persistent Volume Claim
官網(wǎng):
- https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#binding
- https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-persistent-volume-storage/
3.1 Persistent Volume Claim yaml示例
pvc如何找到pv?通過屬性例如大小等找到合適的pv:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-name
spec:
storageClassName: manual
volumeMode: Filesystem
accessMode:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
定義了pvc后,怎么在Pod中引用呢?即通過spec.volumes.persistenceVolumeClaim.claimName進(jìn)行關(guān)聯(lián):
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: pvc-name
【整個過程】
Pod通過pv claim請求volume --> pv claim嘗試在集群中找到合適的volume --> 找到的volume才是真正擁有存儲空間的地方。 --> 這時候volume會被mounted(掛載)到這個Pod --> 然后才被掛載到Pod中的Container(這也是為什么上述Container中定義了volumeMounts屬性) --> 至此,具體的app應(yīng)用才能讀寫該volume
pvc并不是全局的組件,它可以被創(chuàng)建到某個namespace下,pvc所屬的namespace必須要和Pod相同(因?yàn)镻od定義中需要引用到pvc組件)。
3.2 思考:為什么需要這么多層抽像?
- DevOps人員聲明并創(chuàng)建全局組件
pv。 - 開發(fā)人員聲明并創(chuàng)建
pvc,并在Pod中使用。
這樣設(shè)計(jì)的主要好處是開發(fā)人員友好,因?yàn)殚_發(fā)人員并不需要具體知道Storage存放地點(diǎn)(解藕),而只需要使用即可。
3.3 通過spec.volumes引用ConfigMap和Secret
ConfigMap組件和Secret組件:
-
local volumes:這兩個組件都是本地存儲卷。 -
not created via pv and pvc:不是通過pv和pvc聲明創(chuàng)建的。 managed by Kubernetes
我們也可以通過volume屬性定義這兩個組件,然后在container中mounts,以下是示例:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: busybox-container
image: busybox
volumeMounts:
- name: config-dir
mountPath: /etc/config
volumes:
- name: config-dir
configMap:
name: bb-configmap
注:一個Pod可以有多個volume claim。
4. Storage Class
官網(wǎng):https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/
為了讓pv創(chuàng)建以及pvc創(chuàng)建更加高效,則需要第三個組件,叫Storage Class,簡稱sc。
sc可以根據(jù)PersistentVolumeClaim的定義,動態(tài)的生成pv。
示例:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: storage-class-name
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "10"
fsType: ext4
-
via "provisioner" attribute:provisioner意思為供應(yīng)方,聲明了pv的具體提供商,每個Storage類型都有自己的provisioner,在需要的時候查閱官網(wǎng):https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/#provisioner -
configure "parameters" for storage we want to request for Persistent Volume:parameters屬性定義了pv所需要的信息,例如類型,空間大小等。
sc主要是為了減少DevOps的工具,即可以動態(tài)的生成pv,那么誰來引入sc組件呢?答案很明顯,是pvc。即開發(fā)人員不需要每次讓DevOps的人手動創(chuàng)建pv,而是通過Storage Class來自動創(chuàng)建pv。
在pvc中使用:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessMode:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: storage-class-name
【整個過程】
-
Pod通過pvc請求存儲。 -
pvc通過sc請求存儲。 -
sc自動創(chuàng)建可以滿足要求的pv。