您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關詳解Kubernetes存儲體系,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
先思考一個問題,為什么會引入Volume
這樣一個概念?
“答案很簡單,為了實現數據持久化,數據的生命周期不隨著容器的消亡而消亡。
”
在沒有介紹Kubernetes Volume
之前,先來回顧下Docker Volume
,Docker Volume
常用使用方式有兩種,
volumes
通過這種方式,
Docker
管理宿主機文件系統的一部分,默認位于
/var/lib/docker/volumes
目錄中,由于在創建時沒有創建指定數據卷,
docker
自身會創建默認數據卷;bind mounts
通過這種方式,可以把容器內文件掛載到宿主機任意目錄。既然有了Docker Volume
,為啥Kubernetes
又搞出了自己的Volume
?谷歌的標新立異?
“答案是否定的,
”Kubernetes Volume
和Docker Volume
概念相似,但是又有不同的地方,Kubernetes Volume
與Pod
的生命周期相同,但與容器的生命周期不相關。當容器終止或重啟時,Volume
中的數據也不會丟失。當Pod
被刪除時,Volume
才會被清理。并且數據是否丟失取決于Volume
的具體類型,比如emptyDir
類型的Volume
數據會丟失,而持久化類型的數據則不會丟失。另外Kubernetes
提供了將近20
種Volume
類型。
現在有了Kubernetes
的Volume
,我們就可以完全可以在Yaml
編排文件中填寫上Volume
是字段,如下nfs
所示:
....
volumes:
- name: static-nfs
nfs:
server: 12.18.17.240
path: /nfs/data/static
如果你使用ceph
作為存儲插件,你可以在編排文件中這樣定義:
volumes:
- name: ceph-vol
cephfs:
monitors:
- 12.18.17.241:6789
- 12.18.17.242:6789
user: admin
secretRef:
name: ceph-secret
readOnly: true
當然只要是Kubernetes
已經實現的數據卷類型,你都可以按照如上方式進行直接在Yaml
編排文件中定義使用。
看到這里其實已經完成了80%
的工作,那么為什么還要設計多此一舉的PV
呢?這個問題先擱置下,后面會有說明。
在沒有說明為什么要設計多此一舉的PV PVC
之前,先來看看什么是PV PVC
?
“”
PV
是對持久化存儲數據卷的一種描述。
PV
通常是由運維人員提前在集群里面創建等待使用的一種數據卷。如下所示:
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.244.1.4
path: "/nfs"
“”
PVC
描述的是持久化存儲的屬性,比如大小、讀寫權限等。
PVC
通常由開發人員創建,如下所示:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
而用戶創建的PV PVC
必須綁定完成之后才能被利用起來。而PV PVC
綁定起來的前提是PV
中spec
中聲明字段大小、權限等必須滿足PVC
的要求。
成功綁定之后,就可以在Pod Yaml
編排文件中定義和使用。如下所示:
apiVersion: v1
kind: Pod
metadata:
labels:
role: web
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
看到這里,我們還會認為僅僅是PV
對Volume
多了一層抽象,并不見得比直接在Yaml
中聲明Volume
高明多少。仔細思考下,我們為什么能夠直接在Yaml
中直接定義Volume
?因為Kubernetes
已經幫助我們實現了這種Volume
類型,如果我們有自己的存儲類型,而Kubernetes
中并沒有實現,這種是沒有辦法直接在Yaml
編排文件中直接定義Volume
的。這個時候PV PVC
面向對象的設計就體現出其價值了。這也是在軟件開發領域經常碰到的問題,開源軟件無法滿足要求,但也沒有提供出可擴展的接口,沒辦法,只能重新造輪子。
我們在開發過程中經常碰到這樣一個問題,在Pod
中聲明一個PVC
之后,發現Pod
不能被調度成功,原因是因為PVC
沒有綁定到合適的PV
,這個時候要求運維人員創建一個PV
,緊接著Pod
調度成功。剛才上在介紹PV PVC
,它們的創建過程都是手動,如果集群中需要成千上萬的PV
,那么運維人員豈不累死?在實際操作中,這種方式根本行不通。所以Kubernetes
給我們提供了一套自動創建PV
的機制Dynamic Provisioning
.在沒有介紹這套自動創建機制之前,先看看Static Provisioning
,什么是Static Provisioning
?剛才人工創建PV PVC
的方式就是Static Provisioning
。你可以在PV PVC
編排文件中聲明StorageClass
,如果沒有聲明,那么默認為"".具體交互流程如下所示:
首先由集群管理員事先去規劃這個集群中的用戶會怎樣使用存儲,它會先預分配一些存儲,也就是預先創建一些 PV
;然后用戶在提交自己的存儲需求(PVC
)的時候,Kubernetes
內部相關組件會幫助它把PVC PV
做綁定;最后pod
使用存儲的時候,就可以通過PVC
找到相應的PV
,它就可以使用了。不足之處也非常清楚,首先繁瑣,然后運維人員無法預知開發人員的真實存儲需求,比如運維人員創建了多個100Gi
的PV
存儲,但是在實際開發過程中,開發人員只能使用10Gi
,這就造成了資源的浪費。當然Kubernetes
也為我們提供更好的使用方式,即Dynamic Provisioning
它是什么呢?
“”
Dynamic Provisioning
包含了創建某種PV
所需要的參數信息,類似于一個創建PV
的模板。具體交互流程如下所示:
Kubernetes
集群中的控制器,會結合PVC
和StorageClass
的信息動態生成用戶所需要的PV
,將PVC PV
進行綁定后,pod
就可以使用PV
了。通過 StorageClass
配置生成存儲所需要的存儲模板,再結合用戶的需求動態創建PV
對象,做到按需分配,在沒有增加用戶使用難度的同時也解放了集群管理員的運維工作。
Dynamic Provisioning
上面提到過,運維人員不再預分配PV
,而只是創建一個模板文件,這個模板文件正是StorageClass
。下面以NFS
為例進行說明,動態PV
的整個使用過程。
#安裝nfs
yum -y install nfs-utils rpcbind
#開機自啟動
systemctl enable rpcbind nfs-server
#配置nfs 文件
echo "/nfs/data *(rw,no_root_squash,sync)" >/etc/exports
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
---
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: ["watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services", "endpoints"]
verbs: ["get","create","list", "watch","update"]
- 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: logging
roleRef:
kind: ClusterRole
name: nfs-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
spec:
selector:
matchLabels:
app: nfs-client-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccount: nfs-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-client
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 12.18.7.20
- name: NFS_PATH
value: /nfs/data
volumes:
- name: nfs-client
nfs:
server: 12.18.7.20
path: /nfs/data
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
provisioner: fuseim.pri/ifs
reclaimPolicy: Retain
這些參數是通過Kubernetes
創建存儲的時候,需要指定的一些細節參數。對于這些參數,用戶是不需要關心的,像這里provisioner
指的是使用nfs
的置備程序。ReclaimPolicy
就是說動態創建出來的PV
,當使用方使用結束、Pod
及 PVC
被刪除后,這塊PV
應該怎么處理,我們這個地方寫的是Retain
,意思就是說當使用方pod PVC
被刪除之后,這個PV
會保留。
Pod yaml
文件定義
PVC
,即可自動創建
PV
和
PVC
。apiVersion: apps/v1
kind: StatefulSet
metadata:
name: es
spec:
........
template:
metadata:
labels:
app: elasticsearch
spec:
.........
initContainers:
........
containers:
- name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2
.......
volumeClaimTemplates:
- metadata:
name: data
labels:
app: elasticsearch
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: nfs-storage
resources:
requests:
storage: 50Gi`
Capacity
:存儲對象的大小;
AccessModes
:也是用戶需要關心的,就是說使用這個PV
的方式。它有三種使用方式:ReadWriteOnce
是單node
讀寫訪問;ReadOnlyMany
是多個node
只讀訪問,常見的一種數據共享方式;ReadWriteMany
是多個node
上讀寫訪問;
StorageClassName
:StorageClassName
這個我們剛才說了,動態Provisioning
時必須指定的一個字段,就是說我們要指定到底用哪一個模板文件來生成PV
。
PV Controller
: 負責
PV PVC
的綁定、生命周期管理,并根據需求進行數據卷的
Provision Delete
操作AD Controller
:負責存儲設備的
Attach Detach
操作,將設備掛載到目標節點Volume Manager
:管理卷的
Mount Unmount
操作、卷設備的格式化以及掛載到一些公用目錄上的操作Volume Plugins
:它主要是對上面所有掛載功能的實現。
PV Controller、AD Controller、Volume Manager
主要是進行操作的調用,而具體操作則是由
Volume Plugins
實現的。根據源碼的位置可將
Volume Plugins
分為
In-Tree
和
Out-of-Tree
兩類:
In-Tree
表示源碼是放在
Kubernetes
內部的(常見的
NFS、cephfs
等),和
Kubernetes
一起發布、管理與迭代,缺點是迭代速度慢、靈活性差;
Out-of-Tree
的
Volume Plugins
的代碼獨立于
Kubernetes
,它是由存儲
提供商實現的,目前主要有
Flexvolume CSI
兩種實現機制,可以根據存儲類型實現不同的存儲插件Scheduler
:實現對
Pod
的調度能力,會根據一些存儲相關的的定義去做存儲相關的調度PVC
的
Pod
PV Controller
會觀察
ApiServer
,如果它發現一個
PVC
已經創建完畢但仍然是未綁定的狀態,它就會試圖把一個
PV
和
PVC
綁定Provision
就是從遠端上一個具體的存儲介質創建一個
Volume
,并且在集群中創建一個
PV
對象,然后將此
PV
和
PVC
進行綁定Scheduler
進行多個維度考量完成后,把
Pod
調度到一個合適的
Node
Kubelet
不斷
watch APIServer
是否有
Pod
要調度到當前所在節點Pod
調度到某個節點之后,它所定義的
PV
還沒有被掛載(
Attach
),此時
AD Controller
就會調用
VolumePlugin
,把遠端的
Volume
掛載到目標節點中的設備上(
/dev/vdb
);當
Volum Manager
發現一個
Pod
調度到自己的節點上并且
Volume
已經完成了掛載,它就會執行
mount
操作,將本地設備(也就是剛才得到的
/dev/vdb
)掛載到
Pod
在節點上的一個子目錄中Volume
映射到容器中看完上述內容,你們對詳解Kubernetes存儲體系有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。