kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)

在開始介紹k8s持久化存儲前,咱們有必要了解一下k8s的emptydir和hostpath、configmap以及secret的機制和用途html

一、Emptydir
EmptyDir是一個空目錄,他的生命週期和所屬的 Pod 是徹底一致的,pod刪掉目錄消失node

二、Hostpath
Hostpath會把宿主機上的指定卷加載到容器之中,若是 Pod 發生跨主機的重建,其內容就難保證了nginx

三、Configmap
ConfigMap跟Secrets相似,可是ConfigMap能夠更方便的處理不包含敏感信息的字符串。
當ConfigMap以數據卷的形式掛載進Pod的時,這時更新ConfigMap(或刪掉重建ConfigMap),Pod內掛載的配置信息會熱更新。這時能夠增長一些監測配置文件變動的腳本,而後reload對應服務git

四、Secret
Secret來處理敏感數據,好比密碼、Token和密鑰,相比於直接將敏感數據配置在Pod的定義或者鏡像中,Secret提供了更加安全的機制(Base64加密),防止數據泄露。Secret的建立是獨立於Pod的,以數據卷的形式掛載到Pod中,Secret的數據將以文件的形式保存,容器經過讀取文件能夠獲取須要的數據github

==========================================================web

下面咱們來介紹一下k8s的持久化存儲方案,目前k8s支持的存儲方案主要以下:
分佈式文件系統:NFS/GlusterFS/CephFS
公有云存儲方案:AWS/GCE/Auzre後端

這裏使用nfs測試一下api

咱們這裏爲了演示方便,決定使用相對簡單的 NFS 這種存儲資源,接下來咱們在節點10.20.2.116上來安裝 NFS 服務,數據目錄:/data/k8s/安全

具體安裝方法百度有好多,安裝完nfs掛載到k8s的node節點上面就行
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
完成以後就能夠部署pv,和pvc服務器

什麼是PV,pvc
PV 的全稱是:PersistentVolume(持久化卷),是對底層的共享存儲的一種抽象,主要是定義一個磁盤的大小

PVC 的全稱是:PersistentVolumeClaim(持久化卷聲明),PVC 是用戶存儲的一種聲明,PVC 和 Pod 比較相似,Pod 消耗的是節點,PVC 消耗的是 PV 資源

動態pv:StorageClass
PVC 請求到必定的存儲空間也頗有可能不足以知足應用對於存儲設備的各類需求,並且不一樣的應用程序對於存儲性能的要求可能也不盡相同,好比讀寫速度、併發性能等,爲了解決這一問題,Kubernetes 又爲咱們引入了一個新的資源對象:StorageClass,經過 StorageClass 的定義,用戶根據 StorageClass 的描述就能夠很是直觀的知道各類存儲資源的具體特性了,這樣就能夠根據應用的特性去申請合適的存儲資源了

kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
PV 做爲存儲資源,主要包括存儲能力、訪問模式、存儲類型、回收策略等關鍵信息
1G 的存儲空間,訪問模式爲 ReadWriteOnce,回收策略爲 Recyle

kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
狀態是 Available,表示 pv1 就緒,能夠被 PVC 申請。咱們來分別對上面的屬性進行一些解讀。

Capacity(存儲能力)
通常來講,一個 PV 對象都要指定一個存儲能力,經過 PV 的 capacity屬性來設置的,目前只支持存儲空間的設置,就是咱們這裏的 storage=1Gi,不過將來可能會加入 IOPS、吞吐量等指標的配置。

====================================================================================
AccessModes(訪問模式)
AccessModes 是用來對 PV 進行訪問模式的設置,用於描述用戶應用對存儲資源的訪問權限,訪問權限包括下面幾種方式:

ReadWriteOnce(RWO):讀寫權限,可是隻能被單個節點掛載
ReadOnlyMany(ROX):只讀權限,能夠被多個節點掛載
ReadWriteMany(RWX):讀寫權限,能夠被多個節點掛載
persistentVolumeReclaimPolicy(回收策略)

=======================================================================================
我這裏指定的 PV 的回收策略爲 Recycle,目前 PV 支持的策略有三種:

Retain(保留)- 保留數據,須要管理員手工清理數據
Recycle(回收)- 清除 PV 中的數據,效果至關於執行 rm -rf /thevoluem/*
Delete(刪除)- 與 PV 相連的後端存儲完成 volume 的刪除操做,固然這常見於雲服務商的存儲服務,好比 ASW EBS。
不過須要注意的是,目前只有 NFS 和 HostPath 兩種類型支持回收策略。固然通常來講仍是設置爲 Retain 這種策略保險一點。

=======================================================================================
狀態
一個 PV 的生命週期中,可能會處於4中不一樣的階段:

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

接下來建立pvc
請求 1Gi 的存儲容量,訪問模式也是 ReadWriteOnce,YAML 文件以下:(pvc-nfs.yaml)

kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
PV 也是 Bound 狀態了,對應的聲明是 default/pvc-nfs,就是 default 命名空間下面的 pvc-nfs,證實咱們剛剛新建的 pvc-nfs 和咱們的 pv-nfs 綁定成功了
爲啥會pv和pvc綁定呢,這是系統自動綁定的,他們都在默認的命名空間default下面系統自動給綁定
爲了驗證咱們建立一個pvc測試一下效果對比一下
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
說明pvc2沒有合適的pv能夠綁定

接下來建立pv
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
系統自動給咱們pv和pvc綁定的,
容量大於了 PV 裏面的容量的話,是沒辦法進行綁定的,你們能夠下去本身測試一下。
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
因此容量必定要對應起來

修改相同以後就對應起來
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
咱們已經知道怎麼建立 PV 和 PVC 了,如今咱們就來使用下咱們的 PVC,接下來使用nginx 的鏡像來測試下:(nfs-pvc-deploy.yaml)

cat nfs-pvc-deploy.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nfs-pvc
spec:
replicas: 3
template:
metadata:
labels:
app: nfs-pvc
spec:
containers:

  • name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    • containerPort: 80
      name: web
      volumeMounts:
    • name: www
      mountPath: /usr/share/nginx/html
      volumes:
  • name: www
    persistentVolumeClaim:
    claimName: pvc2-nfs

apiVersion: v1
kind: Service
metadata:
name: nfs-pvc
labels:
app: nfs-pvc
spec:
type: NodePort
ports:

  • port: 80
    targetPort: web
    selector:
    app: nfs-pvc

使用 nginx 鏡像,將容器的 /usr/share/nginx/html 目錄經過 volume 掛載到名爲 pvc2-nfs 的 PVC 上面,而後建立一個 NodePort 類型的 Service 來暴露服務
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
訪問一下
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)

爲啥403沒有資源呢,由於咱們把nginx默認的目錄映射到了pvc上面,pvc上面沒東西,接下來咱們建立點東西試試

kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
這是鏡像中字符集問題,說明咱已經測試成功了。

========================================================================================================================
若是咱們又有一個新的 nginx 容器也作了數據目錄的掛載,是否是就會有衝突了啊,因此這個時候就不太好區分了,這個時候咱們能夠在 Pod 中使用一個新的屬性:subPath,該屬性能夠來解決這個問題,咱們只須要更改上面的 Pod 的 YAML 文件便可
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)

而後建立

kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
仍然沒有東西,接下來開始寫配置頁面
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
再刷新試試
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)

兩個nginx容器的內容是徹底不同的對吧
靜態pv和pvc就演示到這裏,後面開始動態的pv和pvc

注意事項
若是這個時候咱們把 PV 給刪除了,上面持久化的數據還會存在嗎?若是是刪除的 PVC 呢?在實際使用的工程中,是頗有可能出現這種狀況的吧?你們在使用 PV 和 PVC 的時候必定要注意這些細節,否則一不當心就把數據搞丟了

========================================================================================================================

要使用 StorageClass,咱們就得安裝對應的自動配置程序,好比咱們這裏存儲後端使用的是 nfs,那麼咱們就須要使用到一個 nfs-client 的自動配置程序,咱們也叫它 Provisioner,這個程序使用咱們已經配置好的 nfs 服務器,來自動建立持久卷,也就是自動幫咱們建立 PV。
後接下來咱們部署 nfs-client 便可,咱們也能夠直接參考 nfs-client 的文檔:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client,進行安裝便可
第一步:配置 Deployment,將裏面的對應的參數替換成咱們本身的 nfs 配置(nfs-client.yaml)、
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
第二步:將環境變量 NFS_SERVER 和 NFS_PATH 替換,固然也包括下面的 nfs 配置,咱們能夠看到咱們這裏使用了一個名爲 nfs-client-provisioner 的serviceAccount,因此咱們也須要建立一個 sa,而後綁定上對應的權限:(nfs-client-sa.yaml)
cat nfs-client-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner


kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-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: ["list", "watch", "create", "update", "patch"]
  • apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:

  • kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: default
    roleRef:
    kind: ClusterRole
    name: nfs-client-provisioner-runner
    apiGroup: rbac.authorization.k8s.io

咱們這裏新建的一個名爲 nfs-client-provisioner 的ServiceAccount,而後綁定了一個名爲 nfs-client-provisioner-runner 的ClusterRole,而該ClusterRole聲明瞭一些權限,其中就包括對persistentvolumes的增、刪、改、查等權限,因此咱們能夠利用該ServiceAccount來自動建立 PV。

第三步:nfs-client 的 Deployment 聲明完成後,咱們就能夠來建立一個StorageClass對象了:(nfs-client-class.yaml)

kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
咱們聲明瞭一個名爲 course-nfs-storage 的StorageClass對象,注意下面的provisioner對應的值必定要和上面的Deployment下面的 PROVISIONER_NAME 這個環境變量的值同樣。

如今咱們來建立這些資源對象吧:
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
建立完成後查看下資源狀態:

kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
上面把StorageClass資源對象建立成功了,接下來咱們來經過一個示例測試下動態 PV,首先建立一個 PVC 對象:(test-pvc.yaml)
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
咱們這裏聲明瞭一個 PVC 對象,採用 ReadWriteMany 的訪問模式,請求 1Mi 的空間,可是咱們能夠看到上面的 PVC 文件咱們沒有標識出任何和 StorageClass 相關聯的信息,那麼若是咱們如今直接建立這個 PVC 對象可以自動綁定上合適的 PV 對象嗎?顯然是不能的(前提是沒有合適的 PV),咱們這裏有兩種方法能夠來利用上面咱們建立的 StorageClass 對象來自動幫咱們建立一個合適的 PV:就是上面圈紅圈的是第一種方式

第二種方式:
kubectl patch storageclass course-nfs-storage -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
最好用第一種,直接添加就行而後直接create
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
咱們能夠看到一個名爲 test-pvc 的 PVC 對象建立成功了,狀態已是 Bound 了,是否是也產生了一個對應的 VOLUME 對象,最重要的一欄是 STORAGECLASS,如今是否是也有值了,就是咱們剛剛建立的 StorageClass 對象 course-nfs-storage。以看到是否是自動生成了一個關聯的 PV 對象,訪問模式是 RWX,回收策略是 Delete,這個 PV 對象並非咱們手動建立的吧,這是經過咱們上面的 StorageClass 對象自動建立的。這就是 StorageClass 的建立方法。
接下來測試一下
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
這個 Pod 很是簡單,就是用一個 busybox 容器,在 /mnt 目錄下面新建一個 SUCCESS 的文件,而後把 /mnt 目錄掛載到上面咱們新建的 test-pvc 這個資源對象上面了,要驗證很簡單,只須要去查看下咱們 nfs 服務器上面的共享數據目錄下面是否有 SUCCESS 這個文件便可
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
另外咱們能夠看到咱們這裏是手動建立的一個 PVC 對象,在實際工做中,使用 StorageClass 更多的是 StatefulSet 類型的服務,StatefulSet 類型的服務咱們也能夠經過一個 volumeClaimTemplates 屬性來直接使用 StorageClass,以下:(test-statefulset-nfs.yaml)
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
實際上 volumeClaimTemplates 下面就是一個 PVC 對象的模板,就相似於咱們這裏 StatefulSet 下面的 template,實際上就是一個 Pod 的模板,咱們不單首創建成 PVC 對象,而用這種模板就能夠動態的去建立了對象了,這種方式在 StatefulSet 類型的服務下面使用得很是多。
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
去nfs上面的pv看看有沒有數據
kubernetes持久化存儲,靜態存儲【pv】,動態存儲【StorageClass】(5)
多出來了3個目錄 信息

其實上面的都是單獨聯繫的,生產中須要多磨鍊多學習纔好學習的時候出現任何問題能夠私信和聯繫我

相關文章
相關標籤/搜索