您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“如何利用Kubernetes實現(xiàn)容器的持久化存儲”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何利用Kubernetes實現(xiàn)容器的持久化存儲”吧!
可以說,容器化徹底改變了我們對應用程序開發(fā)的思考方式,它帶來很多好處:開發(fā)和生產(chǎn)之間的一致環(huán)境、使用共享的資源但容器之間相互隔離、云環(huán)境之間的可移植性、快速部署……等等不勝枚舉。容器所固有的短暫性是它之所以偉大的核心原因:不可變的、相同的容器,可以在一瞬間快速啟動。但容器的短暫性也有不利的一面:缺乏持久化存儲。
引入Kubernetes
持久狀態(tài)(Persistent state)通常數(shù)量較大且難以移動,這一概念與容器這種快速、輕量級且易于隨時部署到任何地方的概念有很大的不同。正是由于這個原因,容器規(guī)范有意將持久狀態(tài)排除在外,轉而選擇存儲插件,將管理持久狀態(tài)的責任轉移給另一方。
開源容器編排工具Kubernetes已經(jīng)開始著手解決這個問題。在這篇文章中,筆者將向您介紹Kubernetes中的幾個組件,它們有助于解決在容器環(huán)境中持久化狀態(tài)的問題。
有狀態(tài)性
管理持久狀態(tài)的最大問題是決定它應該存留在何處。在決定持久化存儲應該放在何處時,有三種選擇,每種方法各有其優(yōu)點:
·持久化存儲保存在容器中。如果數(shù)據(jù)是可復制的,而且不是關鍵數(shù)據(jù),那么這中方法是非常有效的,但是當容器重新啟動時,您將丟失這些數(shù)據(jù)。
·持久化存儲保存在主機節(jié)點上。這種方法繞過了容器的短暫性問題,但是您可能會因為主機節(jié)點的易受攻擊性而遇到類似的問題。
·持久化存儲保存在遠程存儲中。這消除了容器和主機存儲的不可靠性,但是需要仔細考慮如何提供/管理遠程存儲。
什么時候需要考慮狀態(tài)?
應用程序有兩個需要持久狀態(tài)的關鍵特性:1、需要在應用程序中斷和重啟之前持久保存數(shù)據(jù);2、需要跨相同的中斷和重啟,來管理應用程序狀態(tài)。此類應用程序的典型例子有數(shù)據(jù)庫及其副本、某種日志記錄應用程序,或者需要遠程存儲的分布式應用程序。
但是,此類應用程序對持久性的需求并不是相同程度的,因為對于不同的應用程序,其關鍵程度顯然是不同的。由于這個原因,筆者在設計有狀態(tài)的應用程序時,常常會問自己幾個問題:
·我們要管理多少數(shù)據(jù)?
·從最新的快照開始就可以嗎?還是需要絕對最新的可用數(shù)據(jù)?
·從快照重新啟動是否花費了太長時間,或者對這個應用程序而言已經(jīng)足夠了?
·數(shù)據(jù)的復制有多容易?
·這些數(shù)據(jù)對任務有多重要?能否在容器或主機終止時“存活”,還是需要遠程存儲?
·這個應用程序中的不同Pods是可互換的嗎?
存儲解決方案
許多應用程序要求數(shù)據(jù)能夠跨容器和主機重啟實現(xiàn)持久化,這就需要遠程存儲。幸運的是,Kubernetes已經(jīng)意識到這種需求,并提供了一種Pod與遠程存儲交互的方式:卷(Volumes)。
Kubernetes卷
Kubernetes卷提供了一種與遠程(或本地)存儲交互的方法??梢詫⑦@些卷視為掛載的存儲,這些存儲將持續(xù)存留到封閉Pod的生存期。卷比在該Pod中spin up/down的任何容器的壽命都長,這為容器的短暫性提供了一個很好的解決方案。下面是一個利用卷的Pod定義示例。
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
— name: test-container
image: nginx
volumeMounts:
— mountPath: /data
name: testvolume
volumes:
— name: testvolume
# This AWS EBS Volume must already exist.
awsElasticBlockStore:
volumeID: <volume-id>
fsType: ext4
正如我們從上面Pod定義中看到的,spec下的volumes部分指定了卷的名稱和已經(jīng)創(chuàng)建的存儲的ID(在本例中是EBS卷)。要使用此卷,容器定義必須在spec下的containers volumeMounts字段中指定要掛載的卷。
在利用卷時要記住的一些關鍵點:
·Kubernetes提供許多類型的卷,一個Pod可以同時使用任意數(shù)量的卷。
·卷僅能持續(xù)與封閉的Pod一樣長的時間。當Pod停止存在時,卷也將停止。
·持久存儲的供應不是由卷或Pod本身處理的,卷后的持久存儲需要以其他方式提供。
雖然卷解決了容器化應用程序的一個巨大問題,但某些應用程序要求附加卷的生存期超過Pod的生存期。對于這個用例,持久卷和持久卷聲明將非常有用。
Kubernetes持久卷和持久卷聲明
Kubernetes持久卷和持久卷聲明提供了一種方法,以便從存儲的使用方式中提取關于如何提供存儲的細節(jié)。持久卷(PV,Persistent Volume)是一個集群中由管理員提供的可用持久存儲,它們作為集群資源存在,就像節(jié)點一樣,它們的生命周期獨立于任何單獨的Pod。持久卷聲明(PVC,Persistent Volume Claim)是用戶對存儲的請求,與Pod消耗內(nèi)存和CPU等節(jié)點資源的方式類似,PVC也消耗存儲等PV資源。
PV的生命周期由四個階段組成:供應(provisioning)、綁定(binding)、使用(using)和回收(reclaiming)。
供應——PV的供應可以通過兩種方式完成:靜態(tài)或動態(tài)。
·靜態(tài)供應需要集群管理員手動創(chuàng)建大量要使用的PV。
·動態(tài)供應可以在PVC請求PV時發(fā)生,而不需要集群管理員進行任何手動干預。
·動態(tài)供應需要以存儲類(Storage Classes)的形式進行一些預先供應(我們稍后將對此進行討論)。
綁定——創(chuàng)建PVC時,它具有特定的存儲空間和特定的訪問模式。當有一個匹配的PV可用時,無論PVC需要多長時間,它都將只與請求的PVC綁定。如果匹配的PV不存在,則PVC將無限期地保持松散狀態(tài)。在動態(tài)供應PV的情況下,控制循環(huán)會始終把PV綁定到請求的PVC。否則,PVC至少會得到它們要求的存儲空間,但是卷可能會比要求更多。
使用——一旦PVC認領了PV,它就可以作為一個安裝體在封閉的Pod中使用。用戶可以為附加卷指定特定的模式(例如ReadWriteOnce、ReadOnlymany等)以及其他掛載的存儲選項。只要用戶需要,就可以使用安裝好的PV。
回收——當一個用戶完成了對存儲的使用后,他需要決定如何處理正在釋放的PV。在決定回收策略時,有三個選項:保留(retain)、刪除(delete)和循環(huán)利用(recycle)。
·保留PV只需要釋放PV,而不需要修改或刪除任何包含的數(shù)據(jù),并允許相同的PVC在稍后手動回收此PV。
·刪除PV將完全刪除PV以及底層存儲資源。
·循環(huán)利用PV將從存儲資源中刪除數(shù)據(jù),并使PV可用于任何其他PVC的請求。
下面是一個持久卷(使用靜態(tài)供應)的示例,以及持久卷聲明定義。
apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv
spec:
storageClassName: mysc
capacity:
storage: 8Gi
accessModes:
— ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
awsElasticBlockStore:
volumeID: <volume-id> # This AWS EBS Volume must already exist.
持久卷
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
storageClassName: mysc
accessModes:
— ReadWriteOnce
resources:
requests:
storage: 8Gi
持久卷聲明
持久卷定義指定存儲資源的容量,以及一些其他特定于卷的屬性,如回收策略和訪問模式??梢允褂胹pec下的storageClassName將PV分類為特定的存儲類,PVC可以利用它來指定要聲明的特定存儲類。上面的持久卷聲明定義指定了它試圖聲明的持久卷的屬性,其中一些是存儲容量和訪問模式。PVC可以通過指定spec下的storageClassName字段請求特定的PV。特定類的PV只能綁定到請求該類的PVC,沒有指定類的PV只能綁定到?jīng)]有請求特定類的PVC。選擇器還可以用于指定要聲明的PV的特定類型,有關這方面的更多文檔可以在這里(https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector)找到。
下面是利用持久卷聲明來請求存儲的Pod定義示例:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
— name: test-container
image: nginx
volumeMounts:
— mountPath: /data
name: myvolume
volumes:
— name: myvolume
persistentVolumeClaim:
claimName: mypvc
當將這個Pod定義與前面使用卷的定義進行比較時,我們可以看到它們幾乎是相同的。持久卷聲明不是直接與存儲資源交互,而是用于從Pod抽象存儲細節(jié)。
關于持久卷和持久卷聲明的一些關鍵結論:
*持久卷的生命周期獨立于Pod的生命周期。
*持久卷聲明將存儲供應的細節(jié)從Pod的存儲消耗中抽象出來。
*與卷類似,持久卷和持久卷聲明不直接處理存儲資源的供應。
Kubernetes存儲類和持久卷聲明
Kubernetes存儲類和持久卷聲明提供了一種在請求時動態(tài)提供存儲資源的方法,從而消除了集群管理員過度提供/手動提供存儲資源以滿足需求的必要性。存儲類允許集群管理員描述其提供的存儲“類”,并在動態(tài)創(chuàng)建存儲資源和持久卷時利用這些“類”作為模板??梢愿鶕?jù)特定的應用程序需求(如所需的服務質量級別和備份策略)定義不同的存儲類。
存儲類定義圍繞三個特定區(qū)域:
·回收(Reclaim )策略
·供應程序(Provisioner)
·參數(shù)(Parameter)
Reclaim ——如果持久卷是由存儲類創(chuàng)建的,那么只有Retain或Delete作為回收策略可用,而手動創(chuàng)建的、由存儲類管理的持久卷在創(chuàng)建時將保留其分配的回收策略。
Provisioner——存儲類提供者負責決定在提供PV時需要使用哪個卷插件(例如AWS EBS的AWSElasticBlockStore或Portworx volume的PortworxVolume)。Provisioner字段不僅限于內(nèi)部可用的Provisioner類型列表,任何遵循明確定義的規(guī)范的獨立外部供應程序都可以用來創(chuàng)建新的持久卷類型。
Parameter——定義存儲類的最后、也可以說最重要的一部分是參數(shù)部分。不同的提供程序可以使用不同的參數(shù),這些參數(shù)用于描述特定“類”存儲的規(guī)范。
下面是持久卷聲明和存儲類定義:
apiVersion: v1
kind: StorageClass
metadata:
name: myscz
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: “10”
fsType: ext4
持久卷聲明
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
storageClassName: mysc
accessModes:
— ReadWriteOnce
resources:
requests:
storage: 8Gi
存儲類
如果我們將PVC定義與上面靜態(tài)供應用例中使用的定義進行比較,可以看到它們是相同的。
這是因為存儲“供應”和存儲“消費”之間存在明顯的分離。與靜態(tài)創(chuàng)建的存儲類相比,使用存儲類創(chuàng)建的持久卷的消耗有一些巨大的優(yōu)勢,最大的優(yōu)點之一是能夠操作僅在資源創(chuàng)建時可用的存儲資源值。這意味著我們可以準確地提供用戶請求的存儲量,而無需集群管理員進行任何手動干預。由于存儲類需要由集群管理員提前定義,因此它們?nèi)匀粫刂颇男╊愋偷拇鎯ψ罱K用戶可用,同時抽象出所有供應邏輯。
存儲類和持久卷聲明的要點:
*存儲類和持久卷聲明允許最終用戶使用存儲資源的動態(tài)供應,從而消除集群管理員所需的任何手動干預。
*存儲類抽象了存儲供應的細節(jié),而依賴于指定的供應程序來處理供應邏輯。
應用程序狀態(tài)
當我們考慮狀態(tài)時,持久存儲是至關重要的。我的數(shù)據(jù)在哪里?當我的應用程序故障時,它是如何做到持久化的?而某些應用程序本身也需要狀態(tài)管理,不僅僅是持久化數(shù)據(jù)。這在利用多個不可互換Pod的應用程序中最容易看到(例如,主數(shù)據(jù)庫Pod及其某些分布式應用程序如Zookeeper或Elasticsearch的副本)。諸如此類的應用程序要求能夠在任何重新調(diào)度期間為每個Pod hat分配惟一標識符。Kubernetes通過使用StatefulSet提供了這種功能。
Kubernetes StatefulSets
Kubernetes StatefulSet提供類似于ReplicaSets 和Deployments的功能,但是具有穩(wěn)定的重新調(diào)度。對于需要穩(wěn)定標識符和有序部署、伸縮和刪除的應用程序來說,這種差異非常重要。StatefulSet有幾種不同的特性,可以幫助提供這些必要的功能。
惟一網(wǎng)絡標識符——StatefulSet中的每個Pod都從StatefulSet的名稱和Pod的序號派生其主機名。這個Pod的標識是粘滯的,不管這個Pod被調(diào)度到哪個節(jié)點,也不管它被重新調(diào)度了多少次。這種功能對于會形成不可互換的Pod邏輯“組”的應用程序特別有用,這類應用程序典型例子是分布式系統(tǒng)中的數(shù)據(jù)庫副本和代理。識別單個Pod的能力是StatefulSet的優(yōu)勢的核心。
有序的部署、伸縮和刪除——StatefulSet中的Pod標識符不僅是惟一的,而且是有序的。StatefulSet中的Pod是按順序創(chuàng)建的,在轉移到下一個Pod之前,等待中的上一個Pod處于健康狀態(tài)。這種行為也擴展到了Pod的伸縮和刪除,在Pod的所有前身都處于健康狀態(tài)之前,任何Pod都不能進行更新或擴展。類似地,在Pod終止之前,必須關閉所有后續(xù)的Pod。這些功能允許對StatefulSet進行穩(wěn)定的、可預測的更改。
下面是StatefulSet定義的一個示例:
apiVersion: v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
replicas: 3
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
— name: nginx
image: nginx
ports:
— containerPort: 80
name: web
volumeMounts:
— name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
— metadata:
name: www
spec:
storageClassName: mysc
resources:
requests:
storage: 1Gi
如上所示,StatefulSet的名稱在metada下的name中指定,在創(chuàng)建封閉的Pod時將使用該名稱。這個StatefulSets定義將產(chǎn)生名為web-0、web-1和web-2的三個Pod。
這個特定的StatefulSet通過spec下的volumeClaimTemplates字段利用Pvc,以便將持久卷附加到每個Pod。
StatefulSet的關鍵要點:
* StatefulSet將其封閉的pod命名為唯一的,允許存在需要不可互換pod的應用程序
*以有序的方式處理StatefulSet的部署、擴展和刪除
雖然StatefulSet提供了部署和管理不可互換Pod的能力,但仍然存在一個問題:我如何找到和使用它們。這就是Headless Service發(fā)揮作用的地方。
Kubernetes Headless服務
有時我們的應用程序不希望或不需要負載平衡或單個服務IP,諸如此類的應用程序(主數(shù)據(jù)庫和副本數(shù)據(jù)庫、分布式應用程序中的代理等)需要一種將流量路由到支持服務的各個分離Pod的方法。具有唯一網(wǎng)絡標識符的Headless服務和Pod (例如使用statefulset創(chuàng)建的那些標識符)可以在此用例中一起使用。能夠直接路由到單個Pod將大量的性能重新交到開發(fā)人員手中,從處理服務發(fā)現(xiàn)到直接路由到主數(shù)據(jù)庫Pod。
下面是一個Headless服務的例子:
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
clusterIP: None
selector:
app: nginx
ports:
— name: http
protocol: TCP
port: 80
targetPort: 30001
— name: https
protocol: TCP
port: 443
targetPort: 30002
使該規(guī)范真正“Headless”的屬性是設置.spec下的clusterIP為None。這個特殊的示例使用spec下的selector字段,以指定應該如何配置DNS。在這個例子中,所有匹配app: nginx選擇器的Pods將創(chuàng)建一條A記錄,直接指向支持服務的Pod。關于DNS如何為Headless服務自動配置的更多信息,可以在這里(https://kubernetes.io/docs/concepts/services-networking/service/#headless-services)找到。這個特殊的規(guī)范將創(chuàng)建端點nginx-svc-0、nginx-svc-1、nginx-svc-2,它們將分別直接路由到名為web-0、web-1和web-2的Pod。
Headless服務的要點:
*無頭服務允許直接路由到特定的豆莢
*使應用程序開發(fā)人員能夠以他們認為合適的方式處理服務發(fā)現(xiàn)
結論
Kubernetes使有狀態(tài)應用程序開發(fā)在容器世界中成為現(xiàn)實,特別是在管理應用程序狀態(tài)和持久數(shù)據(jù)時。持久卷和持久卷聲明建立在卷的基礎之上,以支持持久數(shù)據(jù)存儲,從而支持在一個主要是短暫性的環(huán)境中保持數(shù)據(jù)持久性。存儲類進一步擴展了這一思想,允許按需提供存儲資源。StatefulSet提供Pod惟一性和粘滯標識,為每個Pod提供有狀態(tài)標識,這些標識在Pod中斷和重啟期間持續(xù)存在。Headless服務可以與StatefulSet一起使用,為應用程序開發(fā)人員提供根據(jù)應用程序需求來利用Pod的獨特性的能力。
本文介紹了Kubernetes中有狀態(tài)應用程序所需的基本元素。隨著Kubernetes的不斷發(fā)展,圍繞有狀態(tài)應用程序的功能將繼續(xù)出現(xiàn)。對于有狀態(tài)應用程序開發(fā)人員和集群管理員來說,了解這些基本元素是非常重要的。
到此,相信大家對“如何利用Kubernetes實現(xiàn)容器的持久化存儲”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。