文章目錄
- Volumes配置管理
- emptyDir 示例
- hostPath 示例
- NFS 示例
- NFS PV 示例
- NFS動態分配PV
- StatefulSet
Volumes配置管理
-
容器中的檔案在磁盤上是臨時存放的,這給容器中運行的特殊應用程式帶來一些問題,首先,當容器崩潰時,kubelet 將重新啟動容器,容器中的檔案將會丟失,因為容器會以干凈的狀態重建,其次,當在一個 Pod 中同時運行多個容器時,常常需要在這些容器之間共享檔案, Kubernetes 抽象出 Volume 物件來解決這兩個問題,
-
Kubernetes 卷具有明確的生命周期,與包裹它的 Pod 相同, 因此,卷比 Pod 中運行的任何容器的存活期都長,在容器重新啟動時資料也會得到保留, 當然,當一個 Pod 不再存在時,卷也將不再存在,也許更重要的是,Kubernetes 可以支持許多型別的卷,Pod 也能同時使用任意數量的卷,
-
卷不能掛載到其他卷,也不能與其他卷有硬鏈接, Pod 中的每個容器必須獨立地指定每個卷的掛載位置,
-
Kubernetes 支持下列型別的卷:
awsElasticBlockStore 、azureDisk、azureFile、cephfs、cinder、configMap、csi
downwardAPI、emptyDir、fc (fibre channel)、flexVolume、flocker
gcePersistentDisk、gitRepo (deprecated)、glusterfs、hostPath、iscsi、local、
nfs、persistentVolumeClaim、projected、portworxVolume、quobyte、rbd
scaleIO、secret、storageos、vsphereVolume
emptyDir 示例
當 Pod 指定到某個節點上時,首先創建的是一個 emptyDir 卷,并且只要 Pod 在該節點上運行,卷就一直存在, 就像它的名稱表示的那樣,卷最初是空的, 盡管 Pod 中的容器掛載 emptyDir 卷的路徑可能相同也可能不同,但是這些容器都可以讀寫 emptyDir 卷中相同的檔案, 當 Pod 因為某些原因被從節點上洗掉時,emptyDir 卷中的資料也會永久洗掉
emptyDir 的使用場景:
快取空間,例如基于磁盤的歸并排序,
為耗時較長的計算任務提供檢查點,以便任務能方便地從崩潰前狀態恢復執行,
在 Web 服務器容器服務資料時,保存內容管理器容器獲取的檔案,
vim vol1.yaml
apiVersion: v1
kind: Pod
metadata:
name: vol1
spec:
containers:
- image: busyboxplus
name: vm1
command: ["sleep", "300"]
volumeMounts:
- mountPath: /cache
name: cache-volume
- name: vm2
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
medium: Memory
sizeLimit: 100Mi
kubectl apply -f vol1.yaml

進入vm1的sh,在/cache里創建一個index.html檔案并寫入pwc
進入vm2的sh,在/usr/share/nginx/html里查看index.html
kubectl exec vol1 -it sh -c vm1
cd cache/
echo pwc > index.html
ctrl+d 退出
kubectl exec vol1 -it sh -c vm2
cat /usr/share/nginx/html/index.html
在/cache寫入一個200M的檔案
可以看到檔案超過sizeLimit,則一段時間后(1-2分鐘)會被kubelet evict掉,之所以不是“立即”被evict,是因為kubelet是定期進行檢查的,這里會有一個時間差,

hostPath 示例
hostPath 卷能將主機節點檔案系統上的檔案或目錄掛載到您的 Pod 中, 雖然這不是大多數 Pod 需要的,但是它為一些應用程式提供了強大的逃生艙,
hostPath 的一些用法有:
運行一個需要訪問 Docker 引擎內部機制的容器,掛載 /var/lib/docker 路徑,
在容器中運行 cAdvisor 時,以 hostPath 方式掛載 /sys,
允許 Pod 指定給定的 hostPath 在運行 Pod 之前是否應該存在,是否應該創建以及應該以什么方式存在,
vim vol2.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data
type: DirectoryOrCreate
查看pod調度節點是否創建相關目錄
查看到生成的pod,名為test-pd 在server4上

kubectl exec test-pd -it sh


NFS 示例
vim vol3.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-volume
volumes:
- name: test-volume
nfs:
server: 172.25.21.1
path: /nfs/mnt
在你所有k8s集群中的主機都進行下面這些操作
yum install -y nfs-utils
systemctl enable --now nfs
vim /etc/exports ####這一步只需要在分享/mnt/nfs目錄的主機上
/mnt/nfs *(rw,no_root_squash)
showmount -e
在掛載的主機

在應用yaml檔案的主機

kubectl exec test-pd -it sh


NFS PV 示例
PersistentVolume(持久卷,簡稱PV)是集群內,由管理員提供的網路存盤的一部分,就像集群中的節點一樣,PV也是集群中的一種資源,它也像Volume一樣,是一種volume插件,但是它的生命周期卻是和使用它的Pod相互獨立的,PV這個API物件,捕獲了諸如NFS、ISCSI、或其他云存盤系統的實作細節,
PersistentVolumeClaim(持久卷宣告,簡稱PVC)是用戶的一種存盤請求,它和Pod類似,Pod消耗Node資源,而PVC消耗PV資源,Pod能夠請求特定的資源(如CPU和記憶體),PVC能夠請求指定的大小和訪問的模式(可以被映射為一次讀寫或者多次只讀),
有兩種PV提供的方式:靜態和動態,
靜態PV:集群管理員創建多個PV,它們攜帶著真實存盤的詳細資訊,這些存盤對于集群用戶是可用的,它們存在于Kubernetes API中,并可用于存盤使用,
動態PV:當管理員創建的靜態PV都不匹配用戶的PVC時,集群可能會嘗試專門地供給volume給PVC,這種供給基于StorageClass,
PVC與PV的系結是一對一的映射,沒找到匹配的PV,那么PVC會無限期得處于unbound未系結狀態,
使用
Pod使用PVC就像使用volume一樣,集群檢查PVC,查找系結的PV,并映射PV給Pod,對于支持多種訪問模式的PV,用戶可以指定想用的模式,一旦用戶擁有了一個PVC,并且PVC被系結,那么只要用戶還需要,PV就一直屬于這個用戶,用戶調度Pod,通過在Pod的volume塊中包含PVC來訪問PV,
釋放
當用戶使用PV完畢后,他們可以通過API來洗掉PVC物件,當PVC被洗掉后,對應的PV就被認為是已經是“released”了,但還不能再給另外一個PVC使用,前一個PVC的屬于還存在于該PV中,必須根據策略來處理掉,
回收
PV的回收策略告訴集群,在PV被釋放之后集群應該如何處理該PV,當前,PV可以被Retained(保留)、 Recycled(再利用)或者Deleted(洗掉),保留允許手動地再次宣告資源,對于支持洗掉操作的PV卷,洗掉操作會從Kubernetes中移除PV物件,還有對應的外部存盤(如AWS EBS,GCE PD,Azure Disk,或者Cinder volume),動態供給的卷總是會被洗掉,
創建PV
vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /mnt/nfs
server: 172.25.21.1

創建PVC
vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
spec:
storageClassName: nfs
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
可以看到pv與pvc已經bound

Pod掛載PVC
vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: pv1
volumes:
- name: pv1
persistentVolumeClaim:
claimName: pvc1
應用這個yaml
kubectl apply -f pod.yaml
查看這個pod的ip
kubectl get pod -o wide

測驗:出現403錯誤
在掛載的目錄里面創建一個index.html并加入www.westos.org

給一個權限

測驗:成功

NFS動態分配PV
NFS Client Provisioner是一個automatic provisioner,使用NFS作為存盤,自動創建PV和對應的PVC,本身不提供NFS存盤,需要外部先有一套NFS存盤服務,
PV以 ${namespace}-${pvcName}-${pvName}的命名格式提供(在NFS服務器上)
PV回收的時候以 archieved-${namespace}-${pvcName}-${pvName} 的命名格式(在NFS服務器上)
nfs-client-provisioner原始碼地址:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client
vim nfs-client-provisioner.yaml
這個yaml檔案根據自己的ip和nfs掛載的目錄需要自己修改
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- 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: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: nfs-client-provisioner
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: nfs-client-provisioner
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: nfs-client-provisioner
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: nfs-subdir-external-provisioner:v4.0.0
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: westos.org/nfs
- name: NFS_SERVER
value: 172.25.21.1
- name: NFS_PATH
value: /mnt/nfs
volumes:
- name: nfs-client-root
nfs:
server: 172.25.21.1
path: /mnt/nfs
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: westos.org/nfs
parameters:
archiveOnDelete: "true"
應用這個yaml檔案
kubectl apply -f nfs-client-provisioner.yaml
提示缺少namespace
kubectl create namespace nfs-client-provisioner
再次應用這個yaml檔案,并查看創建出的ns

創建pvc
vim test-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim
spec:
storageClassName: managed-nfs-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
應用這個yaml檔案,創建pvc

查看pvc與pv,可以看到已經bound

在掛載的目錄可以看到有一個default-test-claim-pvc-68928a34-3b86-4539-bfb7-db31a6cae21b被創建,使用這個claim的會掛載在這個目錄

vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: pv1
volumes:
- name: pv1
persistentVolumeClaim:
claimName: test-claim
最后一行改成上面創建的pvc的名字
claimName: test-claim
在pvc掛載的目錄中寫入一個index.html檔案

測驗這個pod:
curl pod-ip
顯示了index.html的內容

洗掉pod和pvc

可以查看到 pv也同時被洗掉了

之前pvc掛載的目錄已經被打包成一個目錄

默認的 StorageClass 將被用于動態的為沒有特定 storage class 需求的 PersistentVolumeClaims 配置存盤:(只能有一個默認StorageClass)
如果沒有默認StorageClass,PVC 也沒有指定storageClassName 的值,那么意味著它只能夠跟 storageClassName 的 PV 進行系結,
如何設定默認的 StorageClass
kubectl patch storageclass <your-StorageClass-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
先查看sc的資訊,然后設定這個sc為默認sc,再次查看,name后面增加了(default)

StatefulSet
通過Headless Service維持Pod的拓撲狀態
創建Headless service
vim nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
StatefulSet控制器
StatefulSet將應用狀態抽象成了兩種情況:
拓撲狀態:應用實體必須按照某種順序啟動,新創建的Pod必須和原來Pod的網路標識一樣
存盤狀態:應用的多個實體分別系結了不同存盤資料,
StatefulSet給所有的Pod進行了編號,編號規則是:$(statefulset名稱)-$(序號),從0開始,
Pod被洗掉后重建,重建Pod的網路標識也不會改變,Pod的拓撲狀態按照Pod的“名字+編號”的方式固定下來,并且為每個Pod提供了一個固定且唯一的訪問入口,即Pod對應的DNS記錄,
PV和PVC的設計,使得StatefulSet對存盤狀態的管理成為了可能:
vim statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx-svc"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
storageClassName: managed-nfs-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

并且在網路檔案系統/mnt/nfs里面可以看到建立出了兩個目錄
在這兩個目錄中創建index.html并輸入web0和web1
測驗:
kubectl run demo --image=busyboxplus -it
curl nginx-svc

如果想增加或者洗掉pod,直接修改statefulset.yaml里面的replicas: 2,盡量不要取消應用這個yaml檔案的
將replicas: 2改為replicas: 0
重新應用這個yaml檔案,可以看到pod是一個個被洗掉的,最早建的最晚洗掉

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/291595.html
標籤:其他
上一篇:JVM運算元堆疊之堆疊頂快取
