上一章教你如何將網路儲存volume掛載到你的 Pod 中。但是,這種體驗並不理想,因為您需要了解叢集運行的環境才能知道要加入到 pod 的volume類型。 例如,如果您的叢集在 Google 的基礎架構上運行,您在pod yaml中定義一個gcePersistentDisk volume。 但您不能使用相同的yaml在 Amazon 上運行您的應用程式,因為 GCE Persistent Disks在aws環境中不支援。要讓yaml與 Amazon 兼容,必須在部署 pod 之前修改yaml中的volume定義。

您可能還記得在第 1 章中,k8s應該標準化雲端廠商之間的應用程式部署。在pod yaml中使用專有儲存volume類型與這個前提背道而馳。

幸運的是,有一種更好的方法可以將持久儲存加入到您的 pod。您沒有在 pod 中引用特定儲存技術的地方。

8.1 將 Pod 與底層儲存技術解耦

理想情況下,在k8s上部署應用程式的開發人員不需要知道叢集提供的儲存技術,就像他們不需要知道用來運行Pod的實體server的特性一樣。基礎設施的細節應該由運行k8s的維運人員來處理。

出於這個原因,當您將應用程式部署到k8s時,您通常不會像在上一章中那樣直接在pod yaml中引用外部儲存。相反,您將使用一種間接方法。

上一章中的一個範例展示了如何在 pod 中使用 NFS 。Pod yaml中的volume定義包含 NFS 的 IP 和 分享路徑。這會將 pod 定義與特定叢集綁定起來,並阻止yaml在其他地方使用。

如下圖,如果要將此 pod 部署到不同的叢集,通常至少需要更改 NFS 的 IP。這表示 pod 定義不能跨叢集移植。每次在新的 k8s 中部署yaml時都必須修改它。

圖 8.1 具有特定於基礎設施的volume資訊的 pod manifest 不能移植到其他叢集

圖 8.1 具有特定於基礎設施的volume資訊的 pod manifest 不能移植到其他叢集

為了使 pod yaml在不同的叢集環境中可移植,有關實際存儲volume的特定於環境的資訊會被移動到PersistentVolume物件,如下圖。 PersistentVolumeClaim物件將 pod 連接到此 PersistentVolume物件。

圖 8.2 使用PV+PVC將網路存儲附加到 pod

圖 8.2 使用PV+PVC將網路存儲附加到 pod

顧名思義,PV物件代表一個儲存volume用來持久化應用程式資料。如上圖,PV物件保存了底層儲存的資訊,並將這些資訊從 Pod 抽離解耦。

當此基礎設施特定資訊不在pod yaml中時,就可以使用相同的yaml將 pod 部署到不同的叢集中。當然,每個叢集現在必須包含一個帶有此資訊的PV物件。 我同意這種方法似乎無法解決任何問題,因為我們只是將資訊移動到不同的物件中,但是稍後您會看到這種新方法可以實現以前做不到的事情。

pod不直接引用PV物件。相反,pod指向PVC物件,然後該PVC物件指向PV物件。

顧名思義,PVC物件代表用戶對PV的聲明。 因為PVC的生命週期與 Pod 的生命週期無關,所以PVC允許PV的擁有權與 Pod 分離。 在用戶可以在 pod 中使用PV之前,他們必須先建立PVC物件來聲明這個volume。當聲明這個volume後,用戶對volume擁有獨占權並可以在 pod 中使用它。 他們可以隨時刪除 pod,並且不會失去對持久卷的擁有權。當不再需要該volume時,用戶利用刪除PVC物件來釋放volume。

要在pod中使用PV,您只需在yaml中引用PVC的名稱(該PVC綁定到volume)。

例如,如果您建立PVC並綁定到表示NFS的PV,則可以利用加入一個volume定義指向PVC物件來將NFS附加到您的 pod。 Pod yaml中的volume定義只需要包含PVC的名稱,不需要包含特定於基礎架構的資訊,例如 NFS 的 IP 。

如下圖,當這個pod被調度到worker節點時,k8s會找到pod中引用的claim綁定的PV,並使用PV物件中的資訊將網路儲存volume掛載到pod的容器中。

圖 8.3 將PV掛載到 pod 的容器中

圖 8.3 將PV掛載到 pod 的容器中

如果多個 Pod 引用相同的PVC並因此傳遞到相同的PV,則它們可以使用相同的儲存volume,如下圖。