在K8S中,容器本身是非持久化的,當容器崩潰后,kubelet將以鏡像的初始狀態重新啟動容器,但是此時之前容器的資料已經丟失,我們該如何保護好容器的資料呢?
在同一Pod中的容器往往需要共享一些資料,此時我們又該如何實作呢?
這個時候就需要存盤來解決這兩個問題,
一、ConfigMap

ConfigMap功能在 Kubernetes1.2版本中引入,許多應用程式會從組態檔、命令列引數或環境變數中讀取配置資訊, ConfigMap API給我們提供了向容器中注入配置資訊的機制, ConfigMap可以被用來保存單個屬性,也可以用來保存整個組態檔或者 JSON二進制大物件,
1.1 ConfigMap 的創建
① 使用目錄創建
[root@master configmap]
apple=8.0
orange=3.5
[root@master configmap]
beef=55.0
pork=28.0
[root@master configmap]
configmap/shop-config created
[root@master configmap]
NAME DATA AGE
shop-config 2 8s
[root@master configmap]
[root@master configmap]
② 使用檔案創建
[root@master configmap]
tea=3.0
coffee=4.0
[root@master configmap]
configmap/drink-config created
[root@master configmap]
③ 使用字面值創建
使用文字值創建,利用 --from-literal引數傳遞配置資訊,該引數可以使用多次,格式如下:
[root@master configmap]
configmap/snacks-config created
[root@master configmap]
1.2 使用 ConfigMap
使用 ConfigMap有三種方式,一種是通過環境變數的方式,直接傳遞 pod,另一種是通過在 pod的命令列下運行的方式,第三種是使用 volume的方式掛載入到 pod內,
① 使用 ConfigMap 來替代環境變數
[root@master configmap]
apiVersion: v1
kind: ConfigMap
metadata:
name: animal-config
namespace: default
data:
cat: cute
dog: lovely
[root@master configmap]
configmap/animal-config created
[root@master configmap]
apiVersion: v1
kind: Pod
metadata:
name: use-configmap-pod
spec:
containers:
- name: test-container
image: hub.hc.com/library/myapp:v1
command: [ "/bin/sh", "-c", "env" ]
env:
- name: animal-config-cat
valueFrom:
configMapKeyRef:
name: animal-config
key: cat
- name: animal-config-coffee
valueFrom:
configMapKeyRef:
name: animal-config
key: dog
envFrom:
- configMapRef:
name: snacks-config
restartPolicy: Never
[root@master configmap]
pod/use-configmap-pod created
[root@master configmap]
② 用 ConfigMap 設定命令列引數
apiVersion: v1
kind: Pod
metadata:
name: use--configmap-pod2
spec:
containers:
- name: test-container
image: hub.hc.com/library/myapp:v1
command: [ "/bin/sh", "-c", "echo $(animal-config-cat) $(animal-config-dog)" ]
env:
- name: animal-config-cat
valueFrom:
configMapKeyRef:
name: animal-config
key: cat
- name: animal-config-dog
valueFrom:
configMapKeyRef:
name: animal-config
key: dog
restartPolicy: Never
③ 通過資料卷插件使用 ConfigMap
在資料卷里面使用這個 ConfigMap,有不同的選項,最基本的就是將檔案填入資料卷,在這個檔案中,鍵就是檔案名,鍵值就是檔案內容,
apiVersion: v1
kind: Pod
metadata:
name: use-configmap-pod3
spec:
containers:
- name: test-container
image: hub.hc.com/library/myapp:v1
command: [ "/bin/sh", "-c", "ls /etc/config" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: animal-config
restartPolicy: Never
1.3 ConfigMap 熱更新
[root@master configmap]
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: hub.hc.com/library/myapp:v1
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: snacks-config
[root@master configmap]
deployment.extensions/my-nginx created
[root@master configmap]
NAME READY STATUS RESTARTS AGE
my-nginx-bc7499bd8-hrgl9 1/1 Running 0 2s
[root@master configmap]
6.9
[root@master configmap]
[root@master configmap]
8.8
二、Secret
Secret 解決了密碼、token、密鑰等敏感資料的配置問題,而不需要把這些敏感資料暴露到鏡像或者 Pod Spec中,Secret 可以以 Volume 或者環境變數的方式使用
Secret有三種型別:
- Service Account:用來訪問
Kubernetes API,由Kubernetes自動創建,并且會自動掛載到Pod的/run/secrets/kubernetes.io/serviceaccount目錄中 - Opaque:
base64編碼格式的Secert,用來存盤密碼、密鑰等 - kubernetes.io/dockerconfigjson:用來存盤私有
docker registry的認證資訊
2.1 Service Account
[root@master ~]
ca.crt namespace token
2.2 Opaque
Opaque型別的資料是一個 map型別,要求 value是 base64編碼格式:
[root@master ~]
YWRtaW4=
[root@master ~]
MWYyZDFlMmU2N2Rm
創建 Opaque型別的 secret:
[root@master secert]
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
[root@master secert]
secret/mysecret created
[root@master secert]
NAME TYPE DATA AGE
mysecret Opaque 2 93s
將 Secret 掛載到 Volume 中:
[root@master secert]
apiVersion: v1
kind: Pod
metadata:
labels:
name: secret-test
name: secret-test
spec:
volumes:
- name: secrets
secret:
secretName: mysecret
containers:
- image: hub.hc.com/library/myapp:v1
name: db
volumeMounts:
- name: secrets
mountPath: /etc/config
[root@master secert]
pod/secret-test created
[root@master secert]
/
/etc/config
1f2d1e2e67df
admin
將 Secret 匯出到環境變數中:
[root@master secert]
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: pod-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: pod-deployment
spec:
containers:
- name: pod-1
image: hub.hc.com/library/myapp:v1
command: [ "/bin/sh", "-c", "env" ]
ports:
- containerPort: 80
env:
- name: TEST_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: TEST_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
[root@master secert]
deployment.extensions/pod-deployment created
2.3 kubernetes.io/dockerconfigjson
[root@master secert]
secret "myregistrykey" created
[root@master secert]
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: roc/awangyang:v1
imagePullSecrets:
- name: myregistrykey

三、Volume
容器磁盤上的檔案的生命周期是短暫的,這就使得在容器中運行重要應用時會出現一些問題,首先,當容器崩潰時, kubelet會重啟它,但是容器中的檔案將丟失,容器以干凈的狀態(鏡像最初的狀態)重新啟動,其次,在 Pod中同時運行多個容器時,這些容器之間通常需要共享檔案, Kubernetes中的 Volume抽象就很好的解決了這些問題,
Kubernetes中的卷( Volume)有明確的壽命,與封裝它的 Pod相同,所f以,卷的生命比 Pod中的所有容器都長,當這個容器重啟時資料仍然得以保存,當然,當 Pod不再存在時,卷也將不復存在, Kubernetes支持多種型別的卷, Pod可以同時使用任意數量的卷,

3.1 emptyDir
當 Pod被分配給節點時,首先創建 emptyDir卷,并且只要該 Pod在該節點上運行,該卷就會存在,正如卷的名字所述,它最初是空的, Pod中的容器可以讀取和寫入 emptyDir卷中的相同檔案,盡管該卷可以掛載到每個容器中的相同或不同路徑上,當出于任何原因從節點中洗掉 Pod時, emptyDir中的資料將被永久洗掉,
emptyDir 的用法有:
- 暫存空間,例如用于基于磁盤的合并排序
- 用作長時間計算崩潰恢復時的檢查點
Web服務器容器提供資料時,保存內容管理器容器提取的檔案
[root@master volume]
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: hub.hc.com/library/myapp:v1
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
- image: busybox
name: test-container2
imagePullPolicy: IfNotPresent
command: ['/bin/sh','-c','sleep 3600']
volumeMounts:
- mountPath: /test
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
[root@master volume]
[root@master volume]
'NAME READY STATUS RESTARTS AGE
test-pd 2/2 Running 0 8m32s
[root@master volume]
/
/cache
/cache
Wed Aug 12 07:43:08 UTC 2020
[root@master ~]
/
/test
Wed Aug 12 07:43:08 UTC 2020
3.2 hostPath
hostPath卷將主機節點的檔案系統中的檔案或目錄掛載到集群中
hostPath 的用途如下:
- 運行需要訪問
Docker內部的容器;使用/var/lib/docker的hostPath - 在容器中運行
cAdvisor;使用/dev/cgroups的hostPath
除了所需的 path屬性之外,用戶還可以為 hostPath卷指定 type:
值行為空空字串(默認)用于向后兼容,這意味著在掛載 hostPath 卷之前不會執行任何檢查DirectoryOrCreate如果在給定的路徑上沒有任何東西存在,那么將根據需要在那里創建一個空目錄,權限設定為0755,與Kubelet具有相同的組和所有權,Directory給定的路徑下必須存在目錄FileOrCreate如果在給定的路徑上沒有任何東西存在,那么會根據需要創建一個空檔案,權限設定為0644,與Kubelet具有相同的組和所有權,File給定的路徑下必須存在檔案Socket給定的路徑下必須存在UNIX套接字CharDevice給定的路徑下必須存在字符設備BlockDevice給定的路徑下必須存在塊設備
使用這種卷型別時請注意:
- 由于每個節點上的檔案都不同,具有相同配置(例如從
podTemplate創建的)的pod在不同節點上的行為可能會有所不同 - 當
Kubernetes按照計劃添加資源感知調度時,將無法考慮hostPath使用的資源 - 在底層主機上創建的檔案或目錄只能由
root寫入,您需要在特權容器中以root身份運行行程,或修改主機上的檔案權限以便寫入hostPath卷
[root@master volume]
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: hub.hc.com/library/myapp:v1
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data
type: Directory
[root@master volume]
[root@master volume]
/
/test-pd
[root@worker1 data]
[root@worker2 data]
2020年 08月 12日 星期三 17:52:43 CST
四、PV-PVC
4.1 相關概念
① PersistentVolume(PV)
是由管理員設定的存盤,它是群集的一部分,就像節點是集群中的資源一樣, PV也是集群中的資源, PV是 Volume之類的卷插件,但具有獨立于使用 PV的 Pod的生命周期,此 API物件包含存盤實作的細節,即 NFS、 iSCSI或特定于云供應商的存盤系統
② PersistentVolumeClaim(PVC)
是用戶存盤的請求,它與 Pod相似, Pod消耗節點資源, PVC消耗 PV資源, Pod可以請求特定級別的資源( CPU和記憶體),宣告可以請求特定的大小和訪問模式(例如,可以以讀/寫一次或只讀多次模式掛載)
③ 靜態 pv
集群管理員創建一些 PV,它們帶有可供群集用戶使用的實際存盤的細節,它們存在于 Kubernetes API中,可用于消費
④ 動態
當管理員創建的靜態 PV都不匹配用戶的 PersistentVolumeClaim時,集群可能會嘗試動態地為 PVC創建卷,此配置基于 StorageClasses: PVC必須請求 [存盤類],并且管理員必須創建并配置該類才能進行動態創建,宣告該類為""可以有效地禁用其動態配置要啟用基于存盤級別的動態存盤配置,集群管理員需要啟用 API server上的 DefaultStorageClass[準入控制器],例如,通過確保 DefaultStorageClass位于 API server組件的 --admission-control標志,使用逗號分隔的有序值串列中,可以完成此操作
⑤ 系結
master中的控制環路監視新的 PVC,尋找匹配的 PV(如果可能),并將它們系結在一起,如果為新的 PVC動態調配 PV,則該環路將始終將該 PV系結到 PVC,否則,用戶總會得到他們所請求的存盤,但是容量可能超出要求的數量,一旦 PV 和 PVC系結后, PersistentVolumeClaim系結是排他性的,不管它們是如何系結的, PVC跟 PV系結是一對一的映射
4.2 PV說明
PVC的保護
PVC保護的目的是確保由 pod正在使用的 PVC不會從系統中移除,因為如果被移除的話可能會導致資料丟失當啟用 PVC保護 alpha功能時,如果用戶洗掉了一個 pod正在使用的 PVC,則該 PVC不會被立即洗掉, PVC的洗掉將被推遲,直到 PVC不再被任何 pod使用
PV演示代碼
apiVersion: v1
kind: PersistentVolumemeta
data:
name: pv0003
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.17.0.2
PV型別
PV型別以插件形式實作, K8S目前支持以下插件型別:

PV訪問模式
PV可以以資源提供者支持的任何方式掛載到主機上,如下表所示,供應商具有不同的功能,每個 PV的訪問模式都將被設定為該卷支持的特定模式,例如, NFS可以支持多個讀/寫客戶端,但特定的 NFS PV可能以只讀方式匯出到服務器上,每個 PV都有一套自己的用來描述特定功能的訪問模式:
ReadWriteOnce:該卷可以被單個節點以讀/寫模式掛載ReadOnlyMany:該卷可以被多個節點以只讀模式掛載ReadWriteMany:該卷可以被多個節點以讀/寫模式掛載
在命令列中,訪問模式縮寫為
RWO:ReadWriteOnceROX:ReadOnlyManyRWX:ReadWriteMany

回收策略
Retain(保留)——手動回收Recycle(回收)——基本擦除(rm -rf /thevolume/*)Delete(洗掉)——關聯的存盤資產(例如AWS EBS、GCE PD、Azure Disk和OpenStack Cinder卷)將被洗掉
當前,只有 NFS和 HostPath支持回收策略, AWS EBS、 GCE PD、 Azure Disk和 Cinder卷支持洗掉策略
狀態
卷可以處于以下的某種狀態:
Available(可用)——一塊空閑資源還沒有被任何宣告系結Bound(已系結)——卷已經被宣告系結Released(已釋放)——宣告被洗掉,但是資源還未被集群重新宣告Failed(失敗)——該卷的自動回收失敗
命令列會顯示系結到 PV的 PVC的名稱
4.3 持久化演示說明 - NFS
① 安裝 NFS 服務器
[root@master ~]
[root@master ~]
[root@master ~]
/nfs *(rw,no_root_squash,no_all_squash,sync)
[root@master ~]
[root@worker1 ~]
[root@worker1 ~]
Export list for 192.168.182.100:
/nfs *
[root@worker1 ~]
[root@worker1 /]
② 部署 PV
[root@master pv]
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs
server: 192.168.182.100
[root@master pv]
persistentvolume/nfs-pv1 created
[root@master pv]
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv1 1Gi RWO Retain Available nfs 5s
③ 創建服務并使用 PVC
[root@master /]
[root@master /]
[root@master /]
/nfs *(rw,no_root_squash,no_all_squash,sync)
/nfs2 *(rw,no_root_squash,no_all_squash,sync)
/nfs3 *(rw,no_root_squash,no_all_squash,sync)
[root@master pv]
[root@master pv]
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs
server: 192.168.182.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv2
spec:
capacity:
storage: 5Gi
accessModes:
- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs2
server: 192.168.182.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv3
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: slow
nfs:
path: /nfs3
server: 192.168.182.100
[root@master pv]
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv1 1Gi RWO Retain Available nfs 23s
nfs-pv2 5Gi ROX Retain Available nfs 23s
nfs-pv3 1Gi RWX Retain Available slow 23s
[root@master pv]
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: hub.hc.com/library/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
[root@master pv]
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 7s
web-1 0/1 Pending 0 5s
[root@master pv]
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv1 1Gi RWO Retain Bound default/www-web-0 nfs 4m40s
nfs-pv2 5Gi ROX Retain Available nfs 4m40s
nfs-pv3 1Gi RWO Retain Bound default/www-web-1 nfs 4m40s
[root@master pv]
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 15m 10.244.2.84 worker2 <none> <none>
web-1 1/1 Running 0 15m 10.244.1.58 worker1 <none> <none>
[root@master pv]
Hello PV
[root@master pv]
Hello PV
[root@master pv]
pod "web-0" deleted
[root@master pv]
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 3s 10.244.2.85 worker2 <none> <none>
web-1 1/1 Running 0 18m 10.244.1.58 worker1 <none> <none>
[root@master pv]
Hello PV
4.4 關于 StatefulSet
- 匹配
Pod name( 網路標識 ) 的模式為:$(statefulset名称)-$(序号),比如上面的示例:web-0、web-1 StatefulSet為每個Pod副本創建了一個DNS域名,這個域名的格式為:$(podname).(headless servername),也就意味著服務間是通過Pod域名來通信而非Pod IP,因為當Pod所在Node發生故障時,Pod會被飄移到其它Node上,Pod IP會發生變化,但是Pod域名不會有變化StatefulSet使用Headless服務來控制Pod的域名,這個域名的FQDN為:$(servicename).$(namespace).svc.cluster.local,其中,cluster.local指的是集群的域名- 根據
volumeClaimTemplates,為每個Pod創建一個pvc,pvc的命名規則匹配模式:(volumeClaimTemplates.name)-(pod_name),比如上面的volumeMounts.name=www,Podname=web-[0-2],因此創建出來的PVC是www-web-0、www-web-1 - 洗掉
Pod不會洗掉其pvc,手動洗掉pvc將自動釋放pv
Statefulset 的啟停順序:
- 有序部署:部署
StatefulSet時,如果有多個Pod副本,它們會被順序地創建(從0到N-1)并且,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態 - 有序洗掉:當
Pod被洗掉時,它們被終止的順序是從N-1到0 - 有序擴展:當對
Pod執行擴展操作時,與部署一樣,它前面的Pod必須都處于Running和Ready狀態
StatefulSet 使用場景:
- 穩定的持久化存盤,即Pod重新調度后還是能訪問到相同的持久化資料,基于
PVC來實作 - 穩定的網路識別符號,即
Pod重新調度后其PodName和HostName不變 - 有序部署,有序擴展,基于
init containers來實作 - 有序收縮
微信搜一搜 : 全堆疊小劉 ,獲取文章 pdf 版本
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/185261.html
標籤:其他
下一篇:2020-10-21
