目錄
emptyDir
gitRepo
hostPath
nfs
pvc
1. 配置NFS共享存儲(chǔ):
2. 創(chuàng)建PV
3. 定義PVC,并使用
accessModes <[]string>
存儲(chǔ)類(StorageClass)
configmap
1. 通過(guò)命令行創(chuàng)建ConfigMap
2. 通過(guò)yaml文件創(chuàng)建ConfigMap
3. 使用ConfigMap
secret
存儲(chǔ)卷是屬于Pod,不屬于容器。但是可以在容器中去掛載存儲(chǔ)卷來(lái)使用。
K8S上可用的存儲(chǔ)卷類型:
emptyDir
空目錄,只在節(jié)點(diǎn)本地使用,一旦Pod被刪除,則這個(gè)存儲(chǔ)卷也會(huì)隨之刪除;所以,emptyDir這種存儲(chǔ)卷不是做為持久化而設(shè)計(jì)的,可以做為臨時(shí)目錄,按需創(chuàng)建。也可以當(dāng)做緩存空間來(lái)使用。emptyDir存儲(chǔ)卷的生命周期同Pod容器。
使用示例:https://kubernetes.io/docs/concepts/storage/volumes/#emptydir
gitRepo
在Pod創(chuàng)建時(shí),會(huì)自動(dòng)連接至Git倉(cāng)庫(kù)(需要確保宿主機(jī)有g(shù)it命令,它是基于宿主機(jī)來(lái)驅(qū)動(dòng)的。),將Git倉(cāng)庫(kù)里的代碼克隆至宿主機(jī)的某個(gè)目錄,并把這個(gè)目錄做為存儲(chǔ)卷掛載至Pod上。實(shí)質(zhì)上gitRepo是建立在emptyDir之上的。gitRepo本質(zhì)上也是emptyDir。
使用示例:https://kubernetes.io/docs/concepts/storage/volumes/#gitrepo
hostPath
宿主機(jī)路徑,將宿主機(jī)文件系統(tǒng)上的路徑做為存儲(chǔ)卷掛載至Pod容器中。Pod刪除后,此存儲(chǔ)卷不會(huì)被刪除,數(shù)據(jù)不會(huì)丟失。不過(guò)在跨節(jié)點(diǎn)調(diào)度時(shí),必須保證每個(gè)節(jié)點(diǎn)主機(jī)上的相同路徑有相同的數(shù)據(jù)。
使用示例:https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
nfs
通過(guò)命令:kubectl explain pod.spec.volumes.nfs查看用法 。

pvc
PVC (Persistent Volume Claim)持久化卷請(qǐng)求。
PVC示意圖:

存儲(chǔ)設(shè)備由存儲(chǔ)管理員去管理,pv由K8S集群管理員定義,pvc由K8S用戶或開發(fā)者定義

使用PVC的流程:
- 配置存儲(chǔ)空間 --- 由存儲(chǔ)管理員配置存儲(chǔ)設(shè)備(如NFS,iSCSI,Ceph RBD,Glusterfs),并且劃割好了很多可被獨(dú)立使用的存儲(chǔ)空間;
- 定義PV --- K8S集群管理員將配置好的那些存儲(chǔ)空間引入至K8S集群中,定義成PV (Persistent Volume,持久化卷);
-
定義PVC --- K8S用戶在創(chuàng)建Pod時(shí)如果要用到PVC時(shí),必須先創(chuàng)建PVC( 在K8S集群中找一個(gè)能符合條件的存儲(chǔ)卷PV來(lái)用)。注意:PV和PVC是一一對(duì)應(yīng)關(guān)系,一旦某個(gè)PV被一個(gè)PVC占用,那么這個(gè)PV就不能再被其他PVC占用,被占用的PV的狀態(tài)會(huì)顯示為
Bound。PVC創(chuàng)建以后,就相當(dāng)于一個(gè)存儲(chǔ)卷,可以被多個(gè) Pod所使用。 -
使用PVC --- 在Pod中去使用PVC,如果符合PVC條件的PV不存在,而這時(shí)去使用這個(gè)PVC,則Pod這時(shí)會(huì)顯示
Pending(掛起)狀態(tài)。
接下來(lái)演示一個(gè)使用NFS做為后端存儲(chǔ)的PVC使用示例:
1. 配置NFS共享存儲(chǔ):
這里用192.168.100.132做為NFS共享存儲(chǔ)服務(wù)器。
# 安裝NFS軟件包
yum install nfs-utils -y
mkdir /data/nfs/volumes/v{1,2,3,4,5} -p
# 編輯/etc/exports文件
[root@fh-db nfs]# cat /etc/exports
/data/nfs/volumes/v1 192.168.100.0/24(rw,no_root_squash)
/data/nfs/volumes/v2 192.168.100.0/24(rw,no_root_squash)
/data/nfs/volumes/v3 192.168.100.0/24(rw,no_root_squash)
/data/nfs/volumes/v4 192.168.100.0/24(rw,no_root_squash)
/data/nfs/volumes/v5 192.168.100.0/24(rw,no_root_squash)
# 導(dǎo)出共享目錄
[root@fh-db nfs]# exportfs -arv
exporting 192.168.100.0/24:/data/nfs/volumes/v5
exporting 192.168.100.0/24:/data/nfs/volumes/v4
exporting 192.168.100.0/24:/data/nfs/volumes/v3
exporting 192.168.100.0/24:/data/nfs/volumes/v2
exporting 192.168.100.0/24:/data/nfs/volumes/v1
# 啟動(dòng)nfs
[root@fh-db nfs]# systemctl start nfs
[root@fh-db nfs]# showmount -e localhost
Export list for localhost:
/data/nfs/volumes/v5 192.168.100.0/24
/data/nfs/volumes/v4 192.168.100.0/24
/data/nfs/volumes/v3 192.168.100.0/24
/data/nfs/volumes/v2 192.168.100.0/24
/data/nfs/volumes/v1 192.168.100.0/24
注意:K8S集群節(jié)點(diǎn)上也需要安裝nfs:
yum install nfs-utils -y,否則在使用nfs做為存儲(chǔ)卷時(shí)不能正常掛載。
2. 創(chuàng)建PV
PV也是標(biāo)準(zhǔn)的K8S資源,但是PV是K8S集群級(jí)別的資源,而不是namespace(名稱空間)級(jí)別的資源。所以在定義PV時(shí),不需要指定namespace。這就意味著PV不限名稱空間,所有名稱空間都可使用。需要注意的是PVC是namespace級(jí)別的資源。
PV的訪問(wèn)模式(accessModes <[]string>)
- ReadWriteOnce --- 單路讀寫,顯示簡(jiǎn)寫:RWO
- ReadOnlyMany --- 多路只讀,顯示簡(jiǎn)寫:ROX
- ReadWriteMany --- 多路讀寫,顯示簡(jiǎn)寫:RWX
注意:定義PV清單文件時(shí),訪問(wèn)模式不支持簡(jiǎn)寫,簡(jiǎn)寫僅用于顯示時(shí)。
需要注意的是,有些后端存儲(chǔ)設(shè)備是不支持多路讀寫的,在定義PV的訪問(wèn)模式時(shí),需要確認(rèn)后端存儲(chǔ)設(shè)備支持的訪問(wèn)模式。PV的訪問(wèn)模式只能是存儲(chǔ)設(shè)備支持的訪問(wèn)模式的子集。參考如下:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes

capacity: 指定PV的可用存儲(chǔ)容量,單位:M | G | T | P | E (1000換算),Mi | Gi | Ti | Pi | Ei (1024換算)
PV的回收策略(persistentVolumeReclaimPolicy <string>):
如果某個(gè)已經(jīng)綁定PV的PVC被刪除了,那么這個(gè)PV將被回收,回收策略有以下三種:
-
Retain--- 默認(rèn),表示保留PV中存在的數(shù)據(jù),在PV下次被PVC綁定時(shí),數(shù)據(jù)還存在;通常都使用這種回收策略。 -
Recycle--- 回收,表示將刪除PV里面的數(shù)據(jù),并將其狀態(tài)置為空閑狀態(tài),供其他PVC去綁定;危險(xiǎn)! -
Delete--- 刪除,表示如果PVC刪除了,那么PV也隨之刪除,數(shù)據(jù)會(huì)被清除。危險(xiǎn)!
編輯PV清單文件:vim pv-demo.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/nfs/volumes/v1
server: 192.168.100.132
accessModes: ['ReadWriteOnce', 'ReadWriteMany', 'ReadOnlyMany']
capacity:
storage: 20Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/nfs/volumes/v2
server: 192.168.100.132
accessModes: ['ReadWriteOnce', 'ReadWriteMany']
capacity:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/nfs/volumes/v3
server: 192.168.100.132
accessModes: ['ReadOnlyMany']
capacity:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
labels:
name: pv004
spec:
nfs:
path: /data/nfs/volumes/v4
server: 192.168.100.132
accessModes: ['ReadOnlyMany', 'ReadWriteOnce']
capacity:
storage: 15Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv005
labels:
name: pv005
spec:
nfs:
path: /data/nfs/volumes/v5
server: 192.168.100.132
accessModes: ['ReadWriteOnce', 'ReadWriteMany', 'ReadOnlyMany']
capacity:
storage: 10Gi
應(yīng)用PV清單文件pv-demo.yaml
[root@k8s-master manifests]# kubectl apply -f pv-demo.yaml
persistentvolume/pv001 created
persistentvolume/pv002 created
persistentvolume/pv003 created
persistentvolume/pv004 created
persistentvolume/pv005 created
查看生成的PV:
[root@k8s-master manifests]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 20Gi RWO,ROX,RWX Retain Available 7m
pv002 10Gi RWO,RWX Retain Available 7m
pv003 5Gi ROX Retain Available 7m
pv004 15Gi RWO,ROX Retain Available 7m
pv005 10Gi RWO,ROX,RWX Retain Available 7m
3. 定義PVC,并使用
accessModes <[]string>
PVC也需要定義訪問(wèn)模式,且PVC的訪問(wèn)模式必須得是PV的子集。也就是說(shuō)只有符合PVC訪問(wèn)模式的PV,才能夠與PVC進(jìn)行綁定。注意:PVC必須與Pod在同一名稱空間才能被Pod使用。
編輯清單文件pod-vol-pvc.yaml
---
# 定義PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
namespace: default
spec:
accessModes: ['ReadWriteMany']
resources:
requests:
storage: 8Gi
---
# 定義Pod
apiVersion: v1
kind: Pod
metadata:
name: pod-vol-pvc
namespace: default
spec:
containers:
- name: myapp-pvc
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc # 使用上述定義的PVC名稱
應(yīng)用清單文件:
[root@k8s-master manifests]# kubectl apply -f pod-vol-pvc.yaml
persistentvolumeclaim/mypvc created
pod/pod-vol-pvc created
再來(lái)查看PV列表:

從上圖可以看出,名為pv002的PV符合PVC定義的條件被綁定了。
查看PVC:
[root@k8s-master manifests]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound pv002 10Gi RWO,RWX 22
注意:如果此時(shí)發(fā)現(xiàn)Pod沒(méi)有正常運(yùn)行,查看pod描述信息中的Events,顯示Pod掛載volume pv002失敗。去檢查Pod調(diào)度到的那個(gè)節(jié)點(diǎn)主機(jī)是否安裝了nfs-utils包。然后安裝即可:
yum install -y nfs-utils。
image.png
在kubernetes 1.9+ ,只要PV被PVC綁定著,那么PV就不能被刪除。
存儲(chǔ)類(StorageClass)
使用上述PVC時(shí),有一個(gè)弊端:當(dāng)K8S用戶創(chuàng)建要使用PVC時(shí),必須確保K8S集群中已經(jīng)存在符合PVC條件的PV,否則Pod就會(huì)處于Pending(掛起)狀態(tài)。
存儲(chǔ)類(StorageClass)就是來(lái)解決這個(gè)問(wèn)題的。使用存儲(chǔ)類時(shí),無(wú)需事先創(chuàng)建好PV。而是在使用PVC時(shí),根據(jù)PVC的條件,動(dòng)態(tài)創(chuàng)建PV供PVC綁定。
定義存儲(chǔ)類,可以從任意維度去給存儲(chǔ)分類:如存儲(chǔ)性能、存儲(chǔ)所在區(qū)域等等。。。
定義好存儲(chǔ)類以后,PVC再去申請(qǐng)PV時(shí),不再直接針對(duì)PV進(jìn)行綁定,而是通過(guò)存儲(chǔ)類去動(dòng)態(tài)創(chuàng)建符合PVC條件的PV,再進(jìn)行綁定。
但是后端的存儲(chǔ)設(shè)備必須要支持RESTful 風(fēng)格的創(chuàng)建請(qǐng)求接口,才能通過(guò)存儲(chǔ)類實(shí)現(xiàn)PV的動(dòng)態(tài)供給。支持RESTful 有后端存儲(chǔ)設(shè)備有Ceph,Glusterfs通過(guò)第三方接口也可以實(shí)現(xiàn)RESTful風(fēng)格的接口。但是去部署這樣的后端存儲(chǔ)設(shè)備,也不是一件容易的事件。所以存儲(chǔ)類(StorageClass)的操作先暫時(shí)放下,后續(xù)再說(shuō)。。。
configmap
secret和configmap可以理解為特殊的存儲(chǔ)卷,但是它們不是給Pod提供存儲(chǔ)功能的,而是提供了從集群外部向集群內(nèi)部的應(yīng)用注入配置信息的功能。ConfigMap扮演了K8S集群中配置中心的角色。ConfigMap定義了Pod的配置信息,可以以存儲(chǔ)卷的形式掛載至Pod中的應(yīng)用程序配置文件目錄,從configmap中讀取配置信息;也可以基于環(huán)境變量的形式,從ConfigMap中獲取變量注入到Pod容器中使用。但是ConfigMap是明文保存的,如果用來(lái)保存數(shù)據(jù)庫(kù)賬號(hào)密碼這樣敏感信息,就非常不安全。一般這樣的敏感信息配置是通過(guò)secret來(lái)保存。secret的功能和ConfigMap一樣,不過(guò)secret是通過(guò)Base64的編碼機(jī)制保存配置信息。
1. 通過(guò)命令行創(chuàng)建ConfigMap
使用nginx_port=8080和nginx_server_name=myapp.magedu.com創(chuàng)建名為my-config的新ConfigMap
kubectl create configmap my-config --from-literal=nginx_port=8080 --from-literal=nginx_server_name=myapp.magedu.com
創(chuàng)建一個(gè)新ConfigMap名為my-www,指定key名為key1,value為file1.txt的內(nèi)容
kubectl create configmap my-www --from-file=www_conf=./www.conf
創(chuàng)建一個(gè)新ConfigMap名為my-www,key名默認(rèn)為文件名www.conf,value為文件www.conf的內(nèi)容。
kubectl create configmap my-www --from-file=./www.conf
2. 通過(guò)yaml文件創(chuàng)建ConfigMap
編輯文件:nginx-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-cm-yaml
namespace: default
data:
nginx_server_port: "8088"
nginx_server_name: "myapp01.magedu.com"
注意:如上,
ConfigMap的清單文件相對(duì)較簡(jiǎn)單,它沒(méi)有spec字段,data字段的內(nèi)容就是配置信息數(shù)據(jù),配置信息數(shù)據(jù)的值必須用引號(hào)包含(如:nginx_server_port: "8088"),否則創(chuàng)建時(shí)會(huì)報(bào)錯(cuò)。
根據(jù)清單文件創(chuàng)建ConfigMap
kubectl apply -f nginx-cm.yaml
獲取前兩步創(chuàng)建的ConfigMap
[root@k8s-master manifests]# kubectl get cm
NAME DATA AGE
my-config 2 4h
my-www 1 1h
nginx-cm-yaml 2 50m
注意:
cm為configmap的簡(jiǎn)寫??赏ㄟ^(guò)kubectl api-resources命令查看K8S所有資源和對(duì)應(yīng)簡(jiǎn)寫。
3. 使用ConfigMap
從ConfigMap中獲取配置信息的方法有兩種:
- 一種是利用環(huán)境變量將配置信息注入Pod容器中的方式,這種方式只在Pod創(chuàng)建的時(shí)候生效,這就意味著在ConfigMap中的修改配置信息后,更新的配置不能被已經(jīng)創(chuàng)建Pod容器所應(yīng)用。
- 另一種是將ConfigMap做為存儲(chǔ)卷掛載至Pod容器內(nèi),這樣在修改ConfigMap配置信息后,Pod容器中的配置也會(huì)隨之更新,不過(guò)這個(gè)過(guò)程會(huì)有稍微的延遲。
先來(lái)看看通過(guò)環(huán)境變量注入配置信息的方式:
vim pod-configmap-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-configmap
labels:
name: myapp-configmap
config: configmap
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
env:
- name: NGINX_SERVER_PORT
valueFrom:
configMapKeyRef:
name: my-config
key: nginx_port
- name: NGINX_SERVER_NAME # 傳入Pod容器中的變量名為NGINX_SERVER_NAME,值為
valueFrom:
configMapKeyRef:
name: my-config # 選擇需要的configmap的名稱
key: nginx_server_name
要點(diǎn):
NGINX_SERVER_PORT和NGINX_SERVER_NAME是傳入Pod容器內(nèi)的變量名,它的值是從名為my-config(ConfigMap)中對(duì)應(yīng)的KEY獲取。NGINX_SERVER_NAME=nginx_server_name=myapp.magedu.com
應(yīng)用清單文件創(chuàng)建Pod:
kubectl apply -f pod-configmap-env.yaml
進(jìn)入Pod容器中驗(yàn)證變量是否存在:
# 進(jìn)入指定Pod的命令
kubectl exec -it myapp-configmap -- /bin/sh

從上圖可以看出變量已經(jīng)傳入Pod容器中了。
接下來(lái)再看一下把ConfigMap當(dāng)作存儲(chǔ)卷掛載至Pod中的用法:
編輯vim pod-configmap-vol-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-configmap-vol-2
labels:
name: pod-configmap-vol-2
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: my-cm-www
mountPath: /etc/nginx/conf.d/ # 將名為my-www的configmap掛載至Pod容器的這個(gè)目錄下。
volumes:
- name: my-cm-www
configMap: # 存儲(chǔ)卷類型選configMap
name: my-www # 選擇一個(gè)configmap
應(yīng)用清單文件創(chuàng)建Pod:
kubectl apply -f pod-configmap-vol-2.yaml
進(jìn)入名為pod-configmap-vol-2的Pod中驗(yàn)證:

從上圖中可以看出ConfigMap已經(jīng)掛載至Pod容器中了。
secret
待續(xù)。。。
