目錄
資料持久化-儲存卷
我們知道,Pod是由容器組成的,而容器當機或停止之後,資料就隨之丟了,那麼這也就意味著我們在做Kubernetes叢集的時候就不得不考慮儲存的問題,而儲存卷就是為了Pod儲存資料而生的。儲存卷的型別有很多,我們常用到一般有四種:emptyDir,hostPath,NFS以及雲端儲存(ceph, glasterfs...)等。
官方文件
https://kubernetes.io/zh/docs/concepts/storage/volumes/#emptydir
https://kubernetes.io/zh/docs/concepts/storage/volumes/#hostpath
儲存卷型別
emptyDir,hostPath,NFS以及雲端儲存(ceph, glasterfs...)等。
1.emptyDir
emptyDir型別的volume在pod分配到node上時被建立,kubernetes會在node上自動分配一個目錄,因此無需指定宿主機node上對應的目錄檔案。這個目錄的初始內容為空,當Pod從node上移除時,emptyDir中的資料會被永久刪除。emptyDir Volume主要用於某些應用程式無需永久儲存的臨時目錄.作用:1.用於容器間分享檔案 2.用於建立臨時目錄
注:emptyDir不能夠用來做資料持久化
例子1:
kind: Deployment
apiVersion: apps/v1
metadata:
name: emptydir
spec:
selector:
matchLabels:
app: emptydir
template:
metadata:
labels:
app: emptydir
spec:
containers:
- name: nginx
image: nginx
volumeMounts: ## 掛載
- mountPath: /usr/share/nginx/nginx ## 掛在目錄
name: test-emptydir # 儲存卷名稱
volumes: ## 建立儲存卷
- name: test-emptydir # 建立儲存卷名稱
emptyDir: {}
2.hostpath
https://kubernetes.io/zh/docs/concepts/storage/volumes/#hostpath
警告:
HostPath 卷存在許多安全風險,最佳做法是儘可能避免使用 HostPath。 當必須使用 HostPath 卷時,它的範圍應僅限於所需的檔案或目錄,並以只讀方式掛載。
如果通過 AdmissionPolicy 限制 HostPath 對特定目錄的訪問, 則必須要求 volumeMounts 使用 readOnly 掛載以使策略生效。
hostPath
卷能將主機節點檔案系統上的檔案或目錄掛載到你的 Pod 中。 雖然這不是大多數 Pod 需要的,但是它為一些應用程式提供了強大的逃生艙。
例如,hostPath
的一些用法有:
- 執行一個需要訪問 Docker 內部機制的容器;可使用
hostPath
掛載/var/lib/docker
路徑。 - 在容器中執行 cAdvisor 時,以
hostPath
方式掛載/sys
。 - 允許 Pod 指定給定的
hostPath
在執行 Pod 之前是否應該存在,是否應該建立以及應該以什麼方式存在。
除了必需的 path
屬性之外,使用者可以選擇性地為 hostPath
卷指定 type
。
支援的 type
值如下:
取值 | 行為 |
---|---|
空字串(預設)用於向後相容,這意味著在安裝 hostPath 卷之前不會執行任何檢查。 | |
DirectoryOrCreate |
如果在給定路徑上什麼都不存在,那麼將根據需要建立空目錄,許可權設定為 0755,具有與 kubelet 相同的組和屬主資訊。 |
Directory |
在給定路徑上必須存在的目錄。 |
FileOrCreate |
如果在給定路徑上什麼都不存在,那麼將在那裡根據需要建立空檔案,許可權設定為 0644,具有與 kubelet 相同的組和所有權。 |
File |
在給定路徑上必須存在的檔案。 |
Socket |
在給定路徑上必須存在的 UNIX 套接字。 |
CharDevice |
在給定路徑上必須存在的字元裝置。 |
BlockDevice |
在給定路徑上必須存在的塊裝置。 |
當使用這種型別的卷時要小心,因為:
-
HostPath 卷可能會暴露特權系統憑據(例如 Kubelet)或特權 API(例如容器執行時套接字), 可用於容器逃逸或攻擊叢集的其他部分。
-
具有相同配置(例如基於同一 PodTemplate 建立)的多個 Pod 會由於節點上檔案的不同 而在不同節點上有不同的行為。
-
下層主機上建立的檔案或目錄只能由 root 使用者寫入。你需要在 特權容器 中以 root 身份執行程式,或者修改主機上的檔案許可權以便容器能夠寫入
hostPath
卷
hostPath 配置示例:****
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# 宿主上目錄位置
path: /data
# 此欄位為可選
type: Directory
注意: FileOrCreate 模式不會負責建立檔案的父目錄。 如果欲掛載的檔案的父目錄不存在,Pod 啟動會失敗。 為了確保這種模式能夠工作,可以嘗試把檔案和它對應的目錄分開掛載,如 FileOrCreate 配置 所示。
hostPath FileOrCreate 配置示例
apiVersion: v1
kind: Pod
metadata:
name: test-webserver
spec:
containers:
- name: test-webserver
image: k8s.gcr.io/test-webserver:latest
volumeMounts:
- mountPath: /var/local/aaa
name: mydir
- mountPath: /var/local/aaa/1.txt
name: myfile
volumes:
- name: mydir
hostPath:
# 確保檔案所在目錄成功建立。
path: /var/local/aaa
type: DirectoryOrCreate
- name: myfile
hostPath:
path: /var/local/aaa/1.txt
type: FileOrCreate
3.pv/pvc(推薦使用)
nfs官方文件
nfs官方文件:https://kubernetes.io/zh/docs/concepts/storage/volumes/#nfs
安裝測試nfs
1. 在所有節點上安裝nfs(所有節點)
yum -y install nfs-utils rpcbind
2.配置nfs
[root@sg-14 opt]# vi /etc/exports
/data/k8s *(rw,sync,no_root_squash) # 允許共享的ip和目錄
/home/jeff 192.168.0.216(rw,sync,no_root_squash) # 允許共享的ip和目錄
/nfs/v1/ 192.168.0.216(rw,no_root_squash)
/nfs/v2/ 192.168.0.216(rw,no_root_squash)
/nfs/v3/ 192.168.0.216(rw,no_root_squash)
/nfs/v4/ 192.168.0.216(rw,no_root_squash)
/nfs/v5/ 192.168.0.216(rw,no_root_squash)
/nfs/v6/ 192.168.0.216(rw,no_root_squash)
/nfs/v7/ 192.168.0.216(rw,no_root_squash)
/nfs/v8/ 192.168.0.216(rw,no_root_squash)
/nfs/v9/ 192.168.0.216(rw,no_root_squash)
/nfs/v10/ 192.168.0.216(rw,no_root_squash)
[root@sg-14 opt]# systemctl enable --now nfs
[root@sg-14 opt]# mkdir -pv /nfs/v{1..10}
[root@sg-14 opt]# cd /nfs/
[root@sg-14 opt]# systemctl restart rpcbind.service && systemctl restart nfs.service
3.測試k8s使用nfs
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs
spec:
selector:
matchLabels:
app: nfs
template:
metadata:
labels:
app: nfs
spec:
nodeName: sg-16 # 指定部署機器
containers:
- name: nginx
image: nginx
volumeMounts: # 掛載容器內部目錄
- mountPath: /home/test
name: nfs
volumes: ## 儲存卷
- name: nfs
nfs:
path: /nfs/v1 # master上目錄
server: 192.168.0.214 # master機器ip
4. 使用pv/pvc來管理nfs
#########################################################################################
# 1、部署MySQL叢集
# 1、建立名稱空間
# 2、建立service提供負載均衡
# 3、使用控制器部署MySQL例項
###
# 2、部署Discuz應用
# 1、建立名稱空間
# 2、建立Service提供負載均衡(Headless Service)
# 3、建立服務並掛載程式碼
# 4、建立Ingress,用於域名轉發(https)
###
# 3、服務之間的互連
# 1、Discuz連線MySQL ---> mysql.mysql.svc.cluster.local
#########################################################################################
pv/pvc管理nfs
官方文件
https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/#reclaim-policy
pv/pvc解釋
注:pv是叢集級資源,pvc是名稱空間級資源
PVC和PV的設計,類似“介面”和“實現”的思想,開發者只知道使用“介面”PVC,運維人員負責給“介面”繫結具體的實現PV,說白了PVC就是一種特殊的Volume儲存卷
PVC和PV的實現原理
PVC:描述 Pod想要使用的持久化屬性,比如儲存大小、讀寫許可權等
PV:描述一個具體的Volume屬性,比如Volume的型別、掛載目錄、遠端儲存伺服器地址等
1. PV 的訪問模式(accessModes)
模式 | 解釋 |
---|---|
ReadWriteOnce(RWO) | 可讀可寫,但只支援被單個節點掛載。 |
ReadOnlyMany(ROX) | 只讀,可以被多個節點掛載。 |
ReadWriteMany(RWX) | 多路可讀可寫。這種儲存可以以讀寫的方式被多個節點共享。不是每一種儲存都支援這三種方式,像共享方式,目前支援的還比較少,比較常用的是 NFS。在 PVC 繫結 PV 時通常根據兩個條件來繫結,一個是儲存的大小,另一個就是訪問模式。 |
2. PV 的回收策略(persistentVolumeReclaimPolicy)
策略 | 解釋 |
---|---|
Retain | 不清理, 保留 Volume(需要手動清理) |
Recycle | 刪除資料,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支援) |
Delete | 刪除儲存資源,比如刪除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支援) |
3. PV 的狀態
狀態 | 解釋 |
---|---|
Available | 可用。 |
Bound | 已經分配給 PVC。 |
Released | PVC 解綁但還未執行回收策略。 |
Failed | 發生錯誤。 |
4.建立pv
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv001
labels:
app: pv001
spec:
nfs:
path: /nfs/v2 # master機器共享目錄
server: 192.168.0.214 # master機器
capacity:
storage: 20Gi # 指定儲存卷大小
persistentVolumeReclaimPolicy: Retain # 回收策略
accessModes: # 訪問模式,支援縮寫
- "ReadWriteMany"
- "ReadWriteOnce"
kubectl apply -f pv.yaml
[root@sg-14 nfs]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 20Gi RWO,RWX Retain Available 7s
STATUS狀態:無
5.pvc外掛
官方文件
https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/#access-modes
pvc使用pv-建立pvc
---
# 建立pv
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv001
labels:
app: pv001
spec:
nfs:
path: /nfs/v2 # master機器共享目錄
server: 192.168.0.214 # master機器
capacity:
storage: 20Gi # 指定儲存卷大小
persistentVolumeReclaimPolicy: Retain # 回收策略
accessModes: # 訪問模式,支援縮寫
- "ReadWriteMany"
- "ReadWriteOnce"
---
# 建立名稱空間
apiVersion: v1
kind: Namespace
metadata:
name: mysql
labels:
app: test-Namespace
---
# 建立pvc儲存卷
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1 # 儲存卷名字
namespace: mysql # 指定名稱空間,pvc是名稱空間級資源
spec:
accessModes: # 訪問模式
- "ReadWriteMany"
resources:
requests:
storage: "6Gi"
kubectl apply -f pvc.yaml
[root@sg-14 nfs]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 20Gi RWO,RWX Retain Bound default/pvc1 47m
[root@sg-14 nfs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc1 Bound pv001 20Gi RWO,RWX 2m22s
狀態:Bound CLAIM:default/pvc1
pv-pvc.yaml 使用nfs
apiVersion: apps/v1
kind: Deployment
metadata:
name: pv-pvc-mysql
namespace: mysql # 指定名稱空間
spec:
replicas: 3 # 部署個數
selector:
matchLabels:
app: pv-pvc
template:
metadata:
labels:
app: pv-pvc
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
volumeMounts: # 掛載容器內部目錄
- mountPath: /var/lib/mysql
name: pv-pvc
volumes: ## 儲存卷master
- name: pv-pvc
persistentVolumeClaim:
claimName: pvc1 # 指定儲存卷名字
kubectl apply -f pv-pvc.yaml
此時:所有的容器/var/lib/mysql目錄和master的/nfs/v2實現共享
kubectl exec -it npv-pvc-f76d748dd-ps7rs -- bash # 進入容器
mysql -u root -p # 登陸資料庫