當前位置:首頁 » 服務存儲 » k8spod掛載s3對象存儲
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

k8spod掛載s3對象存儲

發布時間: 2023-08-10 06:38:54

A. 深入剖析k8s中pod的意義和用法

本文是《深入剖析k8s》學習筆記的第二篇,主要解析pod的意義及其使用方法。

pod,是k8s中最小的API對象,是原子調度單位。是超親密關系容器之間組織和部署的單位。類比地說,pod就是虛擬機,其中的容器就是這個虛擬機裡面運行的用戶進程。

pod中的所有容器共享network、volume、IP地址,在pod啟動的時候,需要先啟動一個Infra中間容器,而其它容器都是通過join的方式加入到Infra容器的資源中的。Infra容器是一個用匯編語言編寫的,永遠處於暫停狀態的容器,其唯一的作用就是hold住資源,和pod同生命周期。

initcontainers是一種容器類型,相較於containers類型,前者總是先於後者啟動,initcontainers如果有多個,則會按照定義的順序先後啟動,只有當所有的initcontainers都啟動成功且退出了,containers用戶容器才會啟動。

sidecar,是一種容器設計模式,指的是我們可以在一個pod中,啟動一個輔助容器來完成一些獨立於主容器之外的工作。比如initcontainers容器、Infra容器,都屬於sidecar。

在進行上雲工作的時候,我們可以把虛擬機類同為一個pod,把裡面的進程類同為容器鏡像,把有順序關系的容器,定義為initcontainers。如此才是合理的、松耦合的容器編排訣竅,也是傳統應用架構演變到微服務架構最自然的過渡方式。

pod有如下幾個重要的屬性需要掌握。

pod有如下幾個狀態需要掌握:

有幾種特殊的volume,它們並不是為了存放容器中的數據,也不是為了進行容器之間或者和宿主機之間進行數據共享,而是為了給容器提供預先定義好的數據。這種數據卷被稱為」投射數據卷「,projected volume。

pod可以為其中的容器配置探針(probe),用以監控容器的健康檢查,而不是以容器鏡像是否運行來作為健康檢查的依據,因為會存在很多情況,容器是正常運行的,但是無法對外提供服務了,因此探針的健康檢查方式更加准確。k8s一旦檢測到容器探針發生異常,就會根據設置好的pod恢復機制進行操作,恢復機制restartPolicy有如下幾種:

默認情況下pod的恢復機制是always,但並不是所有場景下都是合適的,比如initContainers初始化容器執行任務之後就結束了,就不應該設置為always。

如下文檔提供了全量的yaml屬性,特別是關於PodSpec的屬性可以在3050行看到: api/types.go at master · kubernetes/api · GitHub

B. 雲計算時代操作系統Kubernetes之存儲(中)

我們在POD中定義數據卷的時候,必須指定數據卷的類型。由於存儲技術的發展遠遠早於Kubernetes平台的誕生,並且隨著Kubernetes的日益流行,新的存儲技術和方案也在日新月異,因此數據卷可以說理所當然的有很多很多類型,有些是通用的類型,而有些需要底層特定存儲技術的支持,下邊是Kubernetes支持的數據卷類型不完全清單:

- emptyDir類型,emptyDir類型的數據卷允許POD將數據保存到指定的文件夾中,並且數據在POD的整個生命周期中可見。保存數據的文件夾在POD啟動前被創建,並且剛開始文件夾為空,這也是叫empty的緣由。

- hostPath類型,從宿主機的文件系統掛載文件到POD中。

- nfs類型,NFS類型的存儲卷掛載到POD中。

- cephfs,cinder,fc等,用來支持不同類型的網路存儲。

- configMap,secret,downwardAPI,以及projected類型,四種卷類型,用來將POD和Kubernetes的相關信息通過文件暴露給外部,這些卷類型主要用來配置應用程序。這幾種類型筆者會在後續的文章中詳細介紹。

- persistentVolumeClaim類型(PVC),一種輕量級的集成外部存儲能力的方案。在這種類型的數據卷類型中,PersistentVolumeClaim類型的存儲對象指向PersistentVolume類型的存儲對象,真實的外部存儲系統由PersistentVolume這個對象來引用。由於這是Kuberntes強烈建議大家使用的存儲類型,因此筆者會在後續的文章中,單獨來詳細介紹。

- csi類型,一種通過CSI來擴展存儲的方式。這種方式允許所有實現了CSI(Container Storage Interface)介面的存儲實現能夠被POD引用,在POD初始化的過程中,CSI驅動會將存儲卷attach到POD上。

上邊羅列的只是數量巨大存儲卷類型中很小一部分,每種類型都有對應的使用場景。筆者在本篇以及後續的文章中,著重介紹最具代表性的幾個類型,來幫助大家理解Kubernetes存儲體系。首先我們從最簡單的emptyDir類型開始,這種類型的數據卷用來在容器重啟場景中保持狀態。

還記得我們在前邊文章中介紹如何在同一個POD中部署兩個容器實例的例子嗎?當時的做法是通過post-start hook來執行fortune命令產生一個名言警句寫入文件中,運行在另外一個容器中的Nginx伺服器由於掛載了相同的volume,因此會直接將這個信息返回給客戶端請求。這個保存fortune產生的名言警句的文件在容器的文件系統中,這就意味著當容器由於liveness probe三次失敗重啟後,你會看到不同的名言警句,雖然說看起來問題不大,但是從原理上講,數據由於容器重啟丟失。

我們來驗證一下上邊的推理是否符合事實,請在自己的本地環境中部署yunpan-fs.yaml,然後執行kubectl port-forward yunpan-fs 1080:80來創建客戶端代理,訪問服務返回名言警句。然後通過命令讓Nginx重新啟動,重新訪問服務,你可以看到兩次返回的數據不一致,這就證明了保存在容器文件系統的數據,在容器重啟的場景下,不會保持。在筆者的本地環境輸出如下圖:

如上圖所示,重啟容器後會產生新的名言警句,這就意味著容器重啟後保存在文件系統中的數據丟失了。如果我們要在這種重啟的場景中保持數據狀態,那麼就必須確保數據被保存在數據卷中,而emptyDir是解決這個問題的完美方案。當emptyDir類型的數據卷被掛載到容器中,應用寫到掛載目錄的數據文件,在容器重啟後,能夠繼續保持。

emptyDir類型的數據卷可以讓容器即便是重啟後,可以讓寫到文件中的數據狀態保持;或者容器的文件系統為只讀,但是應用在運行的過程中,需要寫狀態到文件中等場景,我們也可以使用emptyDir類型的數據卷來在同一個POD的多個容器之前,進行數據共享。

廢話不多說了,咱直接修改fortune pod來把post-start hook執行fortune命令返回的名言警句寫到emptyDir類型的數據卷中,這樣當容器重啟後,就不會出現數據丟失了。我們其實要修改的地方不多,主要包括:1,給POD增加emptyDir類型的數據卷定義;2,在容器中將這個數據卷掛載到指定的目錄。

另外我們對命令的執行進行了一點點優化,post-start hook會在每次容器啟動後都會執行,因此我們需要防止重啟後對fortune命令輸出對已經存在文件的覆蓋,因此我們對post-start命令腳本也做了優化,如下圖所示:

註:post-start hook腳本被更新成"ls /usr/share/nginx/html/quote || (apk add fortune && fortune > /usr/share/nginx/html/quote)",如果讀者對Linux shell腳本不是很熟悉,這句肯定看的雲里霧里,我們來稍微解釋一下。首先ls命令先執行,我們這里用ls來檢查quote文件是否存在,你有所不值得是,當ls後邊給的文件存在的時候,命令返回0,而如果不存在,就返回非0。由於我們使用||將兩個表達式進行了組合,因此當左邊的ls quote執行成功,那麼右邊的語句就壓根不會執行。通過這種方式,如果quote文件存在,那麼咱就直接跳過了。而當文件不存在,才需要執行右邊的一串命令,安裝fortune和執行fortune來產生名言警句。這句腳本確保名言警句只被生成並寫入一次,也就是只在容器第一次啟動的時候。

如上圖所示,我們定義了emptyDir類型的數據卷content,並掛載到nginx容器指定目錄/usr/share/nginx/html(這個是Nginx伺服器默認用來掃描靜態資源的目錄)。在POD中配置volume需要提供配置參數,接下來我們詳細聊聊如何配置emptyDir類型的數據卷。

對於emptyDir類型的存儲卷,Kubernetes要求配置如下兩個屬性:

- medium,文件夾的存儲介質,如果留空不配置,那麼默認就是宿主機的(工作節點)磁碟。除了磁碟之外,我們還可以配置Memory,這會導致數據卷使用tmpfs文件系統,這是一個在內存文件系統。

- sizeLimit,文件夾需要的磁碟空間大小,比如我們如果需要限制這個文件夾中文件的大小為10M,那麼就可以設置為10Mi。

註:我們上邊的例子中,emptyDir類型的數據卷content未顯示的定義任何欄位,取默認值,大括弧非常明確的表達了這一點,但是並不是必須的。

在POD中定義完數據卷只完成了工作的一半,工作的另一半就是將數據卷掛載到容器實例中,這通過在容器spec.containers域通過volumeMounts來引用。volumeMounts除了要制定name之外,還需要包含mountPath欄位,來指定數據卷被具體掛載到容器文件系統的文件目錄樹的那個路徑。筆者上邊提供的例子中,emptyDir類型的數據卷被掛載到了/usr/share/ngxin/html目錄,因為這也是post-start hook將名言警句寫到文件的路徑。

由於使用了emptyDir類型的數據卷之後,名言警句被寫入到了宿主機的文件系統,因此數據在POD的整個生命周期都會保持,因此我們無論重啟nginx容器多少次,返回的數據(名言警句)都不應該有任何變化。

接下來,我們將這個新版本基於fortune命令的名言警句網站部署到Kubernetes集群,並人為的讓nginx容器重啟,你會發現無論我們重啟多少次,quote介面返回的內容都一樣。背後的原理是,因為我們只在容器第一次啟動的時候,才創建quote文件,並且當容器重啟重新掛載數據卷後,這個quote文件仍然存在。你可能會問,這個文件到底在宿主機的啥地方啊,可以運行kubectl exec yunpan-emptydir -- mount --list | grep nginx/html來發現,如下圖所示:

如上圖所示,通過使用emptyDir類型的數據局content,我們成功讓容器重啟之後,保持數據狀態。接下來,我們繼續看另外一個例子,如何通過數據卷在兩個容器時間共享數據。

如筆者前邊多次提到,我們也可以使用emptyDir類型的數據卷來在同一個POD中的兩個容器之間共享數據,這里需要注意的是,我們無法通過emptyDir類型的數據卷在不同PDO中不同的容器間共享數據,請繼續閱讀。

我們基於fortune的名言警句網站目前略顯無趣,因為每次都返回相同的諺語,我們希望這個行為能夠增強,比如每30分鍾更換一次。為了實現這個功能,我們需要將post-start hook替換成容器,並且在容器中,fortune命令每30秒運行一次。為了使大家學習更加容易,筆者已經構建好了需要的容器,並上傳到Docker Hub,大家可以自行通過命令 docker pull qigaopan/yunpan-fortune:v1.0拉取。

好了,我們已經把需要的容器鏡像都准備好了,接下來我們來編寫POD的YAML文件,如下圖所示:

如上圖所示,emptyDir類型的數據卷被兩個容器共享(共同掛載),容器fortune將數據寫到content數據卷,在nginx容器中,相同的數據卷被以read-only的模式被掛載到nginx的默認目錄。

註:我們在前邊文章中反復強調過一個事實,同一個POD中的多個容器幾乎是同時啟動的,因此可能存在微小的一段時間,ngxin伺服器已經成功運行起來,但是quote文件尚未生成。聰明的你可能想到了,要避免這種場景,我們可以使用初始化容器。

接著,我們將fortune POD部署到Kubernetes集群中,兩個容器幾乎同時開始運行。fortune容器每30秒更新一次諺語(名言警句),nginx容器基於相同的數據文件服務客戶端請求,當POD中的兩個容器都Ready後,可以驗證一下輸出,是否每30秒後,quote請求對應的諺語的返回會更新。

由於在fortune例子中emptyDir類型的數據卷會在宿主機的磁碟上創建共享目錄,因此數據讀寫的性能,完全取決於工作節點上硬體的類型。如果我們的應用需要高性能的IO操作,那麼磁碟可能不是最合適的存儲介質。

Kubernetes允許我們使用tmpfs文件系統來創建數據卷,而tmpfs將數據保存在內存中,我們只需要在POD的YAML文件中,把emptyDir的欄位meim設置為Memory。

其實Memory類型的數據卷除了提供較高的IO之外,數據安全性也比磁碟高。由於數據並沒有落盤,因此數據不容易被惡意攻擊者竊取,因此建議大家可以在自己的項目上考慮這種數據卷類型。另外我們也可以通過參數sizeLimit來約束數據卷的size,特別對於Memory類型的數據卷來說,請務必設置sizeLimit,以防內存被耗盡。

在前邊的內容中,我們將目光主要集中在如何在POD中定義數據卷,而沒有詳細介紹volume是如何掛載到容器中的,接下來我們來看看在容器中掛載數據卷具體需要設置哪些參數。如下圖所示,是我們在新版本的fortune POD定義中關於content數據卷掛載的配置:

從上圖可以看出,掛載數據卷到容器中,我們需要至少配置兩個欄位:name和mountPath,其中name欄位是我們在POD定義的數據卷的名字,而mountPath欄位指定了數據卷應該掛載到容器文件系統的文件數的那個目錄。

除了這兩個必須提供的參數之外,我們還有一些可選的參數可以配置,詳細的可配置參數清單如下:

- name欄位,如筆者上邊的介紹,name欄位就是我們在POD中掛載的數據卷的name

- mountPath欄位,前文應介紹,不累述

- readOnly欄位,是否以只讀的模式掛載數據卷,默認是false,也就是以讀寫的方式掛載數據卷。

- mountPropagation欄位,設置如果在數據卷內部掛載額外的文件系統會發生什麼。有幾個選項,默認是none,指如果宿主機在數據卷中掛在了額外的文件系統,容器不會收到任何通知,反之亦然;還有兩個選項HostToContainer和Bidirectional,具體含義如命名,如果要了解詳情,可以參考官方文檔。

- subPath欄位,默認為「」,意味著整個數據卷都被掛載到mountPath指定的目錄,當設置為非空的字元串後,只有subPath指定的文件路徑被掛載到容器中

- subPathExpr欄位,使用類似於shell提供的$(ENV_VAR_NAME)語句,只能使用環境變數。

在大部分場景下,我們只需要設置name和mountPath就可以了,頂多額外多配置參數readOnly。mountPropagation參數只有在一些復雜配置的場景下才會用到,當我們用一個數據卷來提供不同的文件夾給不同的容器的時候,subPath和subPathExpr非常有用。另外這兩個參數也可以用作多個PDO共享一個數據卷的場景。

好了,這篇文章的內容就這么多了,下篇文章我們繼續介紹存儲,看看如何訪問宿主機文件系統中的數據文件,敬請期待!

C. kubernetes(十一) 數據存儲(掛載卷管理)

在前面已經提到,容器的生命周期可能很短,會被頻繁地創建和銷毀。那麼容器在銷毀時,保存在容器中的數據也會被清除。這種結果對用戶來說,在某些情況下是不樂意看到的。為了持久化保存容器的數據,kubernetes引入了Volume的概念。

Volume是Pod中能夠被多個容器訪問的共享目錄,它被定義在Pod上,然後被一個Pod里的多個容器掛載到具體的文件目錄下,kubernetes通過Volume實現同一個Pod中不同容器之間的數據共享以及數據的持久化存儲。Volume的生命容器不與Pod中單個容器的生命周期相關,當容器終止或者重啟時,Volume中的數據也不會丟失。銷帆宴

kubernetes的Volume支持多種類型,比較常見的有下面幾個:

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

EmptyDir是在Pod被分配到Node時創建的,它的初始內容為空,並且無須指定宿主機上對應的目錄文件,因為kubernetes會自動分配一個目錄,當Pod銷毀時, EmptyDir中的數據也會被永久刪除。 EmptyDir用途如下:

接下來,通過一個容器之間文件共享的案例來使用一下EmptyDir。

在一個Pod中准備兩個容器nginx和busybox,然後聲明一個Volume分別掛在到兩個容器的虧銀目錄中,然後nginx容器負責向Volume中寫日誌,busybox中通過命令將日誌內容讀到控制台。

創建一個volume-emptydir.yaml

EmptyDir中數據不會被持久化,它會隨著Pod的結束而銷毀,如果想簡單的將數據持久化到主機中,可以選擇HostPath。

HostPath就是將Node主機中一個實際目錄掛在到Pod中,以供容器使用,這樣的設計就可以保證Pod銷毀了,但是數據依據可以存在於Node主機上。

創建一個volume-hostpath.yaml:

HostPath可以解決數據持久化的問題,但是一旦Node節點故障了,Pod如果轉移到了別的節點,又會出現問題了,此時需要准備單獨的網路存儲系統,比較常用的用NFS、CIFS。

NFS是一個網路文件存儲系統,可以搭建一台NFS伺服器,然後將Pod中的存儲直接連接到NFS系統上,這樣的話,無論Pod在節點上怎麼轉移,只要Node跟NFS的對接沒問題,數據就可以成功訪問。

1)首先要准備nfs的伺服器,這里為了簡單,直接是master節點做nfs伺服器

2)接下來,要在的每個node節點上都安裝下nfs,這樣的目的是為了node節點可以驅動nfs設備

3)接下來,就可以編寫pod的配置文件了,創建volume-nfs.yaml

4)最後,運行下pod,觀察結果

前面已經學習了使用NFS提供存儲,此時就要求用戶會搭建NFS系統,並且會在yaml配置nfs。由於kubernetes支持的存儲系統有很多,要求客戶全都掌握,顯然不現實。為了能夠屏蔽底層存儲實現的細節,方便用戶使用, kubernetes引入PV和PVC兩種資源對象。

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

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

使用了PV和PVC之後,工作可以得到進一步的細分:

PV是存儲資源的抽象,下面是資源清單文件:

PV 的關鍵配置參數說明:

實驗
使用NFS作為存儲,來演示PV的使用,創建3個PV,對應NFS中的3個暴露的路徑。
1.准備NFS環境

2.創建pv.yaml

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

PVC 的關鍵配置參數說明:

實驗
1.創建pvc.yaml,申請pv

2.創建pods.yaml, 使用pv

PVC和PV是一一對應的,PV和PVC之間的相互作用遵循以下生命周期:

ConfigMap是一種比較特殊的存儲卷,它的主要作用是用來存儲配置信息的。

創建configmap.yaml,內容如下:

接下來,使用此配置文件創建configmap

接下來創建一個pod-configmap.yaml,將上面創建的configmap掛載進去

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

1.首先使用base64對數據進行編碼

2.接下來編寫secret.yaml,並創建Secret

3.創建pod-secret.yaml,將上面創建的secret掛載進去:

至此,已經實現了利用secret實現了信息的編碼。

D. K8s怎麼對象分布式存儲

K8s對象分布式存儲的方式很多,我們用的元核雲分布式塊存儲,用的就是ceph-csi對接的他們的rbd塊存儲。

E. microk8s上給Pod掛載NFS

團隊新開發的區域醫療平台包含一個課件上傳與播放模塊,其實際的業務包含如下的步驟:

1.  縣級和鄉鎮衛生院的醫生們通過在線視頻參加培訓、並錄制視頻。

2. 醫生上傳視頻,並共享課件。

3.  平台上的其他醫生可以在課件學習欄目學習錄制的培訓會議。

通常,課件的上傳和保存我們都是通過對象存儲做的,對象存儲的好處顯而易見:不擔心文件丟失(三份備份), 不擔心容量(雲服務商集群),https/http訪問, 數據安全(對象訪問簽名);  但是這個平台需要部署到區域醫療機構的機房裡,多數情況下是沒有對象存儲的,外購對象存儲也成本過高, 所以我們採用了折中的方案,存儲系統換為NFS, 只需要一個大存儲量的機器就可以了,大概服務如下:

我們開發了一個uploader服務,用於上傳文件,同時使用Nginx提供http/https服務,兩個服務之間共享存儲,使用NFS存儲掛載給他們。

這里我們來看看怎麼給microk8s上的pod掛載NFS存儲。

首先,我們需要安裝NFS server 用於測試

我們使用ubuntu來進行測試,先執行命令:sudo apt install nfs-kernel-server

這個命令將安裝伺服器端,以及所有相關的包:

在home目錄下創建一個nfsshare的文件夾用作共享目錄。然後我們來編輯nfs配置文件,配置該共享目錄,默認允許所有IP段掛在:

啟動nfs: sudo /etc/init.d/nfs-kernel-server start

可以使用服務命令查看服務狀態: service nfs-kernel-server   status

使用ip addr命令查看以下當前主機的IP:

現在我們來使用nfsclient端測試一下:

sudo mount 10.0.2.15:/home/nfsshare   /mnt

查詢 /mnt 目錄,可以看到在 /home/nsshare下面創建的文件和子目錄

測試完後umount 掛載點:  sudo umount -v /mnt

1. 先寫一個PV, 用來表示可以掛載的NFS存儲:

2. 接著寫一個PVC,用於綁定PV:

3. 然後寫包裝了nginx的存儲服務的deployment文件:

4. 最後寫存儲服務對應的service文件:

完成了所有配置文件,使用microk8s kubectl apply -f 命令,依次創建資源對象。

查詢創建的pod:

使用exec 登陸docker,

查詢/usr/share/storage目錄,如下圖,nfs已經掛載好了,可以看見我們在test目錄下創建了幾個文件:

最後,我們來驗證一下http方式訪問文件

現在storage的nfs目錄下創建兩個子目錄,attachement、video , 對應docker的掛在路徑為: /usr/share/storage/atttachment、/usr/share/storage/video。 

在兩個文件夾下面,分別創建兩個文件 helloA.txt  helloB.txt, 並隨意寫寫內容。

完成後我們通過30080埠,從microk8s節點的瀏覽器訪問兩個文件:

至此,在k8s下,給pod掛在nfs的工作,並通過http訪問的任務就完了。另外:

1.   後續需要考慮,通過Lua寫一個腳本和nginx集成,實現訪問資源簽名驗證,這個機制可以很容易的參考對象存儲的驗證。

2. 這里沒有討論,如何寫upload和製作storage服務的鏡像,upload服務也需要掛載nfs,原理是一樣的,所以就不再討論。 storage服務是基於Nginx鏡像實現,下面的附錄了帶上了可參考的配置文件。

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

附錄A: storageservice服務中,nginx的配置文件storage.conf

附錄B:  storageservice服務中dockerfile文件

附錄C: Storageservice的build.gradle文件

參考 一個Springboot項目的build.gradle和Dockerfile ,  這里的buiild.gradle文件不需要java build, 僅需要用來生成新docker鏡像。

F. 什麼是K8S

k8s全稱kubernetes,這個名字大家應該都不陌生,k8s是為容器服務而生的一個可移植容器的編排管理工具,越來越多的公司正在擁抱k8s,並且當前k8s已經主導了雲業務流程,推動了微服務架構等熱門技術的普及和落地,正在如火如荼的發展。想要了解更多,我推薦你去看看時速雲,他們是一家全棧雲原生技術服務提供商,提供雲原生應用及數據平台產品,其中涵蓋容器雲PaaS、DevOps、微服務治理、服務網格、API網關等。大家可以去體驗一下。
希望能給您提供幫助,可以給個大大的贊不。

G. 如何進行K8S存儲系統

在K8S運行的服務,從簡單到復雜可以分成三類:無狀態服務、普通有狀態服務和有狀態集群服務。下面分別來看K8S是如何運行這三類服務的。

無狀態服務,K8S使用RC(或更新的Replica Set)來保證一個服務的實例數量,如果說某個Pod實例由於某種原因Crash了,RC會立刻用這個Pod的模版新啟一個Pod來替代它,由於是無狀態的服務,新啟的Pod與原來健康狀態下的Pod一模一樣。在Pod被重建後它的IP地址可能發生變化,為了對外提供一個穩定的訪問介面,K8S引入了Service的概念。一個Service後面可以掛多個Pod,實現服務的高可用。

普通有狀態服務,和無狀態服務相比,它多了狀態保存的需求。Kubernetes提供了以Volume和Persistent Volume為基礎的存儲系統,可以實現服務的狀態保存。

有狀態集群服務,與普通有狀態服務相比,它多了集群管理的需求。K8S為此開發了一套以Pet Set為核心的全新特性,方便了有狀態集群服務在K8S上的部署和管理。具體來說是通過Init Container來做集群的初始化工作,用Headless Service來維持集群成員的穩定關系,用動態存儲供給來方便集群擴容,最後用Pet Set來綜合管理整個集群。

要運行有狀態集群服務要解決的問題有兩個,一個是狀態保存,另一個是集群管理。我們先來看如何解決第一個問題:狀態保存。Kubernetes有一套以Volume插件為基礎的存儲系統,通過這套存儲系統可以實現應用和服務的狀態保存。

K8S的存儲系統從基礎到高級又大致分為三個層次:普通Volume,Persistent Volume和動態存儲供應。

1.普通Volume

最簡單的普通Volume是單節點Volume。它和Docker的存儲卷類似,使用的是Pod所在K8S節點的本地目錄。

第二種類型是跨節點存儲卷,這種存儲卷不和某個具體的K8S節點綁定,而是獨立於K8S節點存在的,整個存儲集群和K8S集群是兩個集群,相互獨立。

跨節點的存儲卷在Kubernetes上用的比較多,如果已有的存儲不能滿足要求,還可以開發自己的Volume插件,只需要實現Volume.go里定義的介面。如果你是一個存儲廠商,想要自己的存儲支持Kubernetes上運行的容器,就可以去開發一個自己的Volume插件。

2.persistent volume

它和普通Volume的區別是什麼呢?

普通Volume和使用它的Pod之間是一種靜態綁定關系,在定義Pod的文件里,同時定義了它使用的Volume。Volume是Pod的附屬品,我們無法單獨創建一個Volume,因為它不是一個獨立的K8S資源對象。

而Persistent Volume簡稱PV是一個K8S資源對象,所以我們可以單獨創建一個PV。它不和Pod直接發生關系,而是通過Persistent Volume Claim,簡稱PVC來實現動態綁定。Pod定義里指定的是PVC,然後PVC會根據Pod的要求去自動綁定合適的PV給Pod使用。

H. k8s之存儲

k8s的存儲常用的就是上面幾種模式,分為臨時存儲,半持久化存儲,與持久化存儲這三類,本章我們著重講解emptydir與hostpath與pvc跟pv等

當pod的存儲方案設定為emptydir的時候,pod啟動時,就會在pod所在節點的磁碟空間開辟出一塊空卷,最開始裡面是什麼都沒有的,pod啟動後容器產生的數據會存放到那個空卷中。空卷變成了一個臨時卷

供pod內的容器讀取和寫入數據,一旦pod容器消失,節點上開辟出的這個臨時卷就會隨著pod的銷毀而銷毀

一般來說emptydir的用途都是用來充當臨時存儲空間,例如一些不需要數據持久化的微服務,我們都可以用emptydir來當做微服務pod的存儲方案

k8s存儲emptdir實戰例子:以之前的myapp應用為例

創建應用

觀察是否生產data目錄,並在/data目錄創建文件test.txt

手動刪除容器模擬容器銷毀,用於是pod是被控制器管理的,刪除後會被重建新的pod

這時候在看我們之前創建的data.txt已經不見了

hostPath類型則是映射node文件系統中的文件或者目錄到pod里。在使用hostPath類型的存儲卷時,也可以設置type欄位,支持的類型有文件、目錄、File、Socket、CharDevice和BlockDevice(我只映射過文件與目錄)。

其實這個功能就相當於docker中的-v 目錄映射,只不過在k8s中的時候,pod會漂移,當pod漂移到其他node節點的時候,pod不會跨節點的去讀取目錄。所以說hostpath只能算一種半持久化的存儲方式

實戰例子

創建應用

在node節點可以看到生成了/data/volume目錄,在裡面創建測試文件

檢驗pod裡面的/data是否存在這個映射目錄的文件

可以看到剛才創建的文件已經映射到我們的目錄里邊了

為了驗證是否映射到容器裡面的目錄也會隨著pod生命周期的消失而消失,我們手動刪除pod模擬容器終止

可以看到容器被刪除後,新建的pod也可以看到我們映射的目錄,而且裡面數據test.txt還在。

這有個缺點就是不能夠跨容器去讀取數據,如果刪除後的pod被調度到其他節點的話,原來的數據也就沒有了,如果能不受節點的影響,並且掛載的數據不會隨生命周期的結束而結束,我們應該怎麼解決呢?就是我們後面講到的持久化存儲了

上面介紹了倆種臨時存儲於半持久化存儲的方案。在k8s實際生產環境中,一般會選用私有雲持久化存儲方案還有公有雲持久化存儲方案,私有雲存儲方案包括nfs,ceph,glusterfs等方案。公有雲存儲會用到AWS等方案

存儲方案各有各的優缺點,可參考 https://www.cnblogs.com/yswenli/p/7234579.html 這篇文章。今天我們主要講解pvc,pv,nfs之間的關系。

簡單來說,要使用持久化存儲,就需要使用pvc去跟pv去申請,然後pv查看自己有沒有合適的存儲空間卷,有合適的就與pvc進行綁定。pv與pvc是一一對應綁定的。現在我們用一幅圖來說明pvc,pv,nfs的關系

實戰例子

准備存儲服務安裝nfs

接下來創建pv與nfs綁定

創建pvc與pv關聯

創建並查看結果

注意:STATUS為Bound說明該pvc已經與pv綁定了

接下來創建pod來引用pvc

創建pod

接下來驗證一下在nfs創建一個測試文件,看是否被映射到容器中

可以看到容器裡面也可以看到創建的文件

手動刪除容器,或者調度到其他節點原來的文件還是不會被刪除的,這里就省略驗證了,這就是nfs的好處,不過企業一般不會選用nfs,磁碟IO,性能讀取方面不太理想,畢竟是本地存儲,還是有一定的風險。推薦用用雲存儲。

文件存儲提供無限擴展的文件系統來給雲伺服器存取數據實際上相當於nfs

1、已注冊阿里雲賬號,並完成實名認證。

如果沒有,請先注冊阿里雲賬號,詳情請參見阿里雲賬號注冊流程。

2、已開通NAS服務。

首次登錄NAS控制台時,根據頁面提示開通NAS服務。

3、在需要創建文件系統的地域,已有可用的雲伺服器ECS。

k8s應用NAS實戰例子

1、打開阿里雲NAS控制台確認已創建好文件系統

2、把復制掛載參數把它掛載到伺服器中創建測試目錄,前提是伺服器需要安裝nfs客戶端。

安裝完成掛載到本地目錄並創建test目錄作為測試目錄

並在裡面創建一個測試文件1.txt

接下來可以創建pvc和pv了

創建並查看

接下來創建pod去引用pvc

創建pod

檢驗剛才的1.txt是否掛到容器的/data/nas下

雲存儲適合於生產環境k8s的存儲解決方案

I. 通過K8S部署對象存儲MinIO

MinIO 是全球領先的對象存儲先鋒,以 Apache License v2.0 發布的對象存儲伺服器,是為雲應用和虛擬機而設計的分布式對象存儲伺服器。在標准硬體上,讀/寫速度上高達183GB/s和171GB/s。它與 Amazon S3 雲存儲服務兼容。 它最適用於存儲非結構化數據,如照片、視頻、日誌文件、備份和容器/虛擬機映像。 對象的大小可以從幾KB 到最大5TB。

MinIO是一個非常輕量的服務,可以很簡單的和其他應用的結合,類似 NodeJS, Redis 或者 MySQL。

MinIO支持多種靈活的部署方式,支持Docker Compose、Docker Swam、Kubernetes等,詳見官網: https://docs.min.io/docs/minio-deployment-quickstart-guide.html 或者 https://min.io/download#/linux

這里著重介紹K8S下部署

1、standalone模式

由於service採用NodePort類型,通過主機IP:32593訪問web

2、distributed模式

分布式部署,實例數至少4個,所以需要另外創建4個pv