《后端學運維》- k8s之數據存儲


大家好,我是小菜,一個渴望在互聯網行業做到蔡不菜的小菜。可柔可剛,點贊則柔,白嫖則剛!
死鬼~看完記得給我來個三連哦!

本文主要介紹 K8s中數據存儲的使用

如有需要,可以參考

如有幫助,不忘 點贊

微信公眾號已開啟,小菜良記,沒關注的同學們記得關注哦!

k8s 的進程到這里我們已經完成了 NamespacePodPodController 幾種資源的使用方式,已經過大半了哦~這篇文章我們就繼續來了解一下在k8s 中怎么進行數據存儲!

kubernetes的最小控制單元,容器都是運行在 pod 中的,一個pod中可以有 1 個或多個容器

這個概念我們早已了解,不難明白容器的生命周期會很短暫,當pod出現問題的時候,pod控制器會頻繁的創建和銷毀,而每個pod都是獨立的,因此存儲在容器中的數據也會被清除,這種結果無疑是致命打擊。這時,可能就會有小伙伴說了,docker 中存在數據掛載,k8s 肯定也存在,我們可以利用數據掛載來解決該問題~那么,恭喜你答對了,k8s 中不僅支持數據掛載,而且支持的功能還相當強大,話不多說,我們接下來就進入數據世界~

數據存儲

k8s中有個 Volume 的概念,VolumnPod 中能夠被多個容器訪問的共享目錄,K8sVolume 定義在 pod 上,然后被一個 pod里的多個容器掛載到具體的文件目錄下,k8s通過 Volume 實現同一個 pod 中不同容器之間的數據共享以及數據的持久化存儲,Volume的生命周期不與pod中單個容器的生命周期相關,當容器終止或重啟的時候,Volume中的數據也不會被丟失。

Volume 支持常見的類型如下:

除了上面列出來的這些,還有 gcePersistentDisk、awsElasticBlockStore、azureFileVolume、azureDisk 這些存儲,但是因為使用較少,所以不做過多了解。下面我們就來詳細看看每個存儲該如何使用!

一、基本存儲

1)EmptyDir

這是個最基礎的 Volume類型,一個 EmptyDir 就是 Host 上的一個空目錄。

概念:

它是在 Pod 被分配到 Node 節點上時才會被創建,初始內容為空,並且無需指定宿主機上對應的目錄文件,它會自動在宿主機上分配一個目錄

值得關注的是

Pod 銷毀時,EmptyDir 中的數據也會被永久刪除!

用處:

  1. 用作臨時空間,比如 Web 服務器寫日志或者 tmp 文件需要的臨時目錄。
  2. 用作多容器之間的共享目錄(一個容器需要從另一個容器中獲取數據的目錄)
實戰:

我們以nginx為例,准備一份資源清單

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: cbuc-test
  labels:
    app: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.14-alpine
    ports:
   	- containerPort: 80
   	volumeMounts:	# 將 nginx-Log 掛載到nginx容器中,容器內目錄為/var/log/nginx
   	- name: nginx-log
   	  mountPath: /var/log/nginx
  volumes:	#在此聲明volume
  - name: nginx-log
    emptyDir: {}

然后我們創建后可以看看emptyDir存儲卷在宿主機的位置。默認情況下宿主機中聲明volume的目錄位置是在 /var/lib/kubelet/pods/<Pod 的 ID>/volumes/kubernetes.io~<Volume 類型 >/<Volume 名字 > 中。

2)HostPath

概念:

HostPath 就是將 Node 節點上一個實際目錄掛載到pod中,供容器使用,這種好處就是在 pod 銷毀后,該目錄下的數據依然存在!

實戰:

我們以 nginx 為例,准備一份資源清單:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: cbuc-test
  labels:
    app: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.14-alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-log
      mountPath: /var/log/nginx
  volumes:
  - name: nginx-log
    hostPath:           # 指定宿主機目錄為 /data/nginx/log
      path: /data/nginx/log
      type: DirectoryOrCreate   # 創建類型

spec.volumes.hostPath.type(創建類型):

  • DirectoryOrCreate:目錄存在就是用,不存在就先創建后使用
  • Directory: 目錄必須存在
  • FileOrCreate: 文件存在就是用,不存在就創建后使用
  • File: 文件必須存在
  • Socket: unix 套接字必須存在
  • CharDevice: 字符設備必須存在
  • BlockDevice: 塊設備必須存在

我們根據該資源清單可以創建出一個 pod,然后通過 podIp 訪問該pod,再查看 /data/nginx/log 下的日志文件,發現已有日志產生

3)NFS

HostPath 是我們日常中比較經常使用到的存儲方式了,已經可以滿足基本的使用場景。目前為止我們小小的總結一下:EmptyDir 是針對 pod,如果 pod 被銷毀了,那么改數據就會丟失。針對該問題,HostPath 進行了改進,存儲變成是針對 Node ,但是如果 Node 宕機了,那么數據還是會丟失。這個時候就需要准備單獨的網絡存儲系統了,而比較常用的便是 NFS、CIFS

概念:

NFS 是一個網絡存儲系統,可以搭建一台 NFS 服務器,然后將 Pod 中的存儲直接連接到 NFS 系統上,這樣的話,無論pod在節點上如何轉移,只要 Node 節點和 NFS服務器對接沒問題,數據就不會出現問題。

實戰:

既然需要 NFS 服務器,那肯定需要自己搭建一個。我們選取 master 節點來安裝NFS 服務器

# 安裝 nfs 服務器
yum install -y nfs-utils
# 准備共享目錄
mkdir -p /data/nfs/nginx
# 將共享目錄以讀寫權限暴露給 192.168.108.0/24 網段的所有主機
vim /etc/exports
# 添加以下內容
/data/nfs/nginx    192.168.108.0/24(rw,no_root_squash)
# 啟動 nfs 服務器
systemctl start nfs

然后我們在各個節點上同樣安裝 NFS,以供驅動 NFS 設備

yum install -y nfs-utils

做好以上准備后我們就可以准備資源清單文件了:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: cbuc-test
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-pod
    image: nginx:1.14-alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-log
      mountPath: /var/log/nginx
    volumes:
    - name: nginx-log
      nfs:
        server: 192.168.108.100 	# NFS服務器地址,也就是master地址
        path: /data/nfs/nginx		# 共享文件路徑

創建完pod后,我們可以進入到 /data/nfs 目錄下查看到兩個日志文件了

二、高級存儲

管理存儲是管理計算的一個明顯問題,該部分需要抽象出如何根據消費方式來提供存儲的詳細信息。而 k8s 也很好的支持了,引入了兩個新的 API 資源:PersistenVolumePersistentVolumeClaim

PersistenVolume(PV)是持久化卷的意思,是對底層共享存儲的一種抽象,一般情況下PV由 k8s 管理員進行創建和配置,它與底層具體的共享存儲技術有關,並通過插件完成與共享存儲的對象。

PersistentVolumeClaim(PVC)是持久卷聲明的意思,是用戶對存儲需求的一種聲明,換句話說,PVC其實就是用戶向 k8s 系統發出的一種資源需求申請。

1)PV

PV 是集群中由管理員配置的一段網絡存儲,它也是集群中的一種資源,資源清單模板如下:

apiVersion: v1
kind: PersistentVolume
meatadata:
  name: pv
spec:
  nfs: 					# 存儲類型,可以是 CIFS、GlusterFS
  capacity:				# 存儲空間的設置
    storage: 2Gi
  accessModes:  		# 訪問模式
  storageClassName:  	# 存儲類別
  persistentVolumeReclaimPolicy:    # 回收策略

每個屬性真的是又長又難記,我們先來看看每個屬性的含義:

  • 存儲類型

底層實際存儲的類型,k8s 支持多種存儲類型,每種存儲類型的配置都有所差異

  • 存儲能力(capacity)

目前只支持存儲空間的設置,未來可能會加入 IOPS、吞吐量等指標的設置

  • 訪問模式(accessModes)

用於描述用戶應用對存儲資源的訪問權限,有以下幾種訪問權限:

  1. ReadWriteOnce(RWO):讀寫權限,但是只能被單個節點掛載
  2. ReadOnlyMany(ROM):只讀權限,可以被多個節點掛載
  3. ReadWriteMany(RWM):讀寫權限,可以被多個節點掛載
  • 存儲類別

PV 可以通過storageClassName參數指定一個存儲類別

  1. 具有特定類別的PV只能與請求了該類別的PVC進行綁定
  2. 未設定類別的PV則只能與不請求任何類別的PVC進行綁定
  • 回收策略(persistentVolumeReclaimPolicy)

當PV沒有再被使用的時候,需要對其處理的方式(不同的存儲類型支持的策略也會不同),有以下幾種回收策略:

  1. Retain(保留):保留數據。需要管理員手動清理數據

  2. Recycle(回收):清除PV中的數據,效果相當於 rm -rf

  3. Delete(刪除):與 PV 相連的后端存儲完成 volume 的刪除操作,常見於雲服務商的存儲服務

生命周期:

一個 PV 的生命周期可能會處於4種不同的階段:

  • Available(可用): 表示可用狀態,還未被任何PVC綁定
  • Bound(已綁定): 表示PV已經被PVC綁定
  • Released(已釋放): 表示PVC已被刪除,但是資源還未被集群重新聲明
  • Failed(失敗): 表示該PV的自動回收失敗
實戰:

我們前面已經認識了NFS存儲服務器,因此我們這里也依然使用 NFS 服務器做底層存儲。首先我們需要創建1個PV,也對應着NFS中1個需要暴露的路徑。

# 創建目錄
mkdir /data/pv1 -pv

# 向NFS暴露路徑
vim /etc/exports
/data/pv1   192.168.108.0/24(rw,no_root_squash)

完成以上步驟后我們就需要創建1個 PV:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
  namespace: cbuc-test
  labels:
    app: pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /data/pv1
    server: 192.168.108.100

通過創建后我們可以查看到PV:

2)PVC

PVC是資源的申請,用來聲明對存儲空間,訪問模式,存儲類別的需求信息,資源清單模板如下:

apiVersion: v1
kind: persistentVolumeClaim
metadata:
  name: pvc
  namespace: cbuc-test
  labels:
    app: pvc
spec:
  accessModes:  		# 訪問模式
  selector:				# 采用標簽對PV選擇
  storageClassName:		# 存儲類別
  resources:				# 請求空間
    request:
      storage: 1Gi

很多屬性我們在PV中已經了解到了,這里我們簡單過一下~

  • 訪問模式(accessModes)

用於描述用戶應用對存儲資源的訪問權限

  • 選擇條件(selector)

通過 Labels Selector的設置,對於系統中已經存在的PV進行篩選管理

  • 資源類別(storageClassName)

pvc在定義時可以設定需要的后端存儲的類別,只有設置了該class的pv才能被系統選出

  • 資源請求(resources)

描述對存儲資源的請求

實戰:

准備1份PVC的資源清單模板:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc01
  namespace: cbuc-test
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

創建后我們先查看PVC是否創建成功

然后再查看pv是否已經被pvc綁定上

3)實際使用

上面我們已經成功創建了 PV 和 PVC,但是還沒說明如何使用,接下來我們就准備一份pod清單:

apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc
  namespace: cbuc-test
spec:
  containers:
  - name: nginx01
    image: nginx:1.14-alpine
    volumeMounts:
    - name: test-pv
      mountPath: /var/log/nginx
  volumes:
  - name: test-pv
    persistentVolumeClaim:
      claimName: pvc01
      readOnly: true

4)生命周期

萬物皆有生命周期,PV與PVC也不例外,生命周期如下:

  • 資源供應

管理員手動創建底層存儲和PV

  • 資源綁定

用戶創建PVC,k8s負責根據PVC的聲明去尋找PV,並綁定。

  1. 如果找到,則會成功進行綁定,用戶的應用就可以使用這個PVC了
  2. 如果找不到,PVC則會無限處於Pending的狀態,直到等到系統管理員創建了一個符合其要求的PV

PV一旦綁定到某個PVC上,就會被這個PVC獨占,不能再與其他PVC進行綁定了

  • 資源使用

用戶可在Pod中想 volume 一樣使用pvc

  • 資源釋放

用戶通過刪除PVC來釋放PV,當存儲資源使用完畢后,用戶可以刪除PVC,與該PVC綁定的PV將會標記為 已釋放,但還不能立刻與其他PVC進行綁定,通過之前PVC寫入的數據可能還留在存儲設備上,只有在清除之后該PV才能再次使用

  • 資源回收

k8s 會根據pv設置的回收策略進行資源的回收

上面列出了 PV和PVC 的生命周期,與其說是生命周期,但不如是PV和PVC的使用過程!

三、配置存儲

配置存儲,顧名思義就是用來存儲配置的,其中包括了兩種配置存儲,分別是 ConfigMapSecret

1)ConfigMap

ConfigMap 是一種比較特殊的存儲卷,它的主要作用是用來存儲配置信息的。資源清單模板如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: cmp
  namespace: cbuc-test
data:
  info:
    username:cbuc
    sex:male

使用方式很簡單,少了 spec,多了 data.info,只需在 info 下級以 key: value 的方式存儲自己想要配置的配置文件即可

通過kubectl create -f configMap.yaml命令可創建出一個 ConfigMap

具體使用如下,我們需要創建一個Pod:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: cbuc-test
spec:
  containers:
  - name: nginx
    image: nginx:1.14-apline
    volumeMounts:		# 將 configMap 掛載到目錄中
    - name: config
      mountPath: /var/configMap/config
  volumes:
  - name: config
    configMap:
      name: cmp  # 上面我們創建 configMap 的名稱

然后通過命令kubectl create -f pod-cmp.yaml創建出測試Pod,然后可查看pod中的配置文件:

2)Secret

在 k8s 中,還存在一種和 ConfigMap 非常類似的對象,稱之為 Secret 對象。它主要用於存儲敏感信息,例如密碼、秘鑰、證書等信息。

我們首先對想要配置的數據進行 base64 加密:

# 加密用戶名
[root@master test]# echo -n 'cbuc' | base64
Y2J1Yw==
# 加密密碼
[root@master test]# echo -n '123456' | base64
MTIzNDU2

然后准備 Secret 資源清單文件

apiVersion: v1
kind: Secret
metadata:
  name: secret
  namespace: cbuc-test
type: Opaque    # 表示base64編碼格式的Secret
data:
  username: Y2J1Yw==
  password: MTIzNDU2

通過命令kubectl create -f secret.yaml創建 Secret,然后我們再准備一份Pod資源清單:

apiVersion: v1
kind: Pod
metadata:
  name: pod-secret
  namespace: cbuc-test
spec:
  containers:
  - name: nginx
    image: nginx:1.14-apline
    volumeMounts:
    - name: config
      mountPath: /var/secret/config
  volumes:
  - name: config
    secret:
      secretName: secret

創建后我們進入pod查看配置文件,可以發現配置文件的信息已經是解碼后的

END

這篇我們就介紹了 k8s 的數據存儲,篇幅較短,是不是意猶未盡,我們下篇再見(Server和Ingress)!路漫漫,小菜與你一同求索~

看完不贊,都是壞蛋

今天的你多努力一點,明天的你就能少說一句求人的話!

我是小菜,一個和你一起學習的男人。 💋

微信公眾號已開啟,小菜良記,沒關注的同學們記得關注哦!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM