Kubernetes-14:持久化存儲PV、PVC和StatefulSet介紹及使用


PV、PVC簡介

PersistentVolume(PV)

是由管理員設置的存儲,它是集群的一部分,就像節點是集群中的資源一樣,PV也是集群中的資源、PV是Volume之類的卷插件,但具有獨立於使用PV的Pod的生命周期,此API對象包含存儲實現的細節,即NFS、iSCSI或特定於雲供應商的存儲系統

 

PersistentVolumeClaim(PVC)

是用戶存儲的請求,它與Pod相似。Pod消耗節點資源,PVC消耗PV資源。Pod可以請求特定級別的資源(CPU和內存)。PVC可以請求特定pv的大小和訪問模式(例如,可以以讀/寫一次或只讀多次模式掛載)

 

靜態PV

集群管理員呢創建一些PV,他們帶有可供集群用戶使用的實際存儲細節。他們存在與Kubernetes API中,可用於消費。

 

PV與PVC的工作流程

  1. 首先將不同規格的存儲(例如NFS存儲,有5GB、10GB等)創建為PV
  2. 用戶再將需要用到的存儲的條件創建為PVC,PVC會在PV資源中尋找最匹配用戶需求的PV
  3. 匹配到最優PV后,PVC與PV進行綁定,最后掛載到對應Pod中

 

持久化卷聲明的保護

PVC保護的目的是確保由Pod正在使用的PVC不會從系統移除,因為如果被移除的話可能會導致數據丟失

當啟用PVC保護alpha功能時,如果用戶刪除一個Pod正在使用的PVC,則該PVC不會被立即刪除。PVC的刪除將被推遲,知道PVC不再被任何Pod使用

 

PV訪問模式

PersistentVolume可以以資源提供者支持的任何方式掛載到主機上。如下表所示,供應商具有不同的功能,每個PV的訪問模式都將被設置為該卷支持的特定模式,例如,NFS可以支持多個讀/寫客戶端,但特定的PV可能以只讀方式導出到服務器上。每個PV都有一套自己的用來描述特定功能的訪問模式

  • ReadWriteOnce——該卷可以被單個節點以讀/寫模式掛載
  • ReadOnlyMany——該卷可以被多個節點以只讀模式掛載
  • ReadWriteMany——該卷可以被多個節點以讀/寫模式掛載

在命令行中,訪問模式縮寫為:

  • RWO - ReadWriteOnce
  • ROX - ReadOnlyMany
  • RWX - ReadWriteMany

一個pv卷一次只能使用一種訪問模式掛載,即使它支持很多訪問模式。

Volume插件 ReadWriteOnce ReadOnlyMany ReadWriteMany
AWSElasticBlockStoreAWSElasticBlockStore - -
AzureFile
AzureDisk - -
cephFS
FlexVolume - -
Flocker -
GCEPersistentDisk -
Glusterfs - -
HostPath -
NFS

 

回收策略

  • Retain(保留)——手動回收
  • Recycle(回收)——基本擦除(rm -rf /thevolume/*)
  • Delete(刪除)——關聯的存儲資產將被刪除

當前只有HostPath和NFS支持回收策略。AWS EBS、GCE PD等支持刪除策略

 

狀態

卷可以處於以下某種狀態:

  • Available(可用) —— 一塊空閑資源沒有被任何聲明綁定
  • Bound(已綁定) —— 卷已經被聲明綁定
  • Released(已釋放) —— 聲明被刪除,但是資源還沒有被集群聲明
  • Failed(失敗) —— 該卷的自動回收失敗

命令行會顯示綁定到PV的PVC名稱

 

持久化演示說明 —— NFS

1、安裝NFS
## 安裝nfs,服務器IP地址為:192.168.152.252
yum -y install  nfs-utils rpcbind

## 配置nfs配置文件,設置可連接主機及權限
vim /etc/exports
...
/alibaba  *(rw,no_root_squash,no_all_squash,sync)
<目錄路徑> <可連接ip,*代表全部> <目錄及文件權限>
... 

## 創建共享目錄,及設置目錄權限
mkdir /alibaba
chmod 777 -R /alibaba
chown nfsnobody /alibaba/

## 啟動nfs服務及rpcbind服務
systemctl start nfs-server.service rpcbind

### 進入客戶機,測試能否正常訪問,注意每個節點都要測試,保證可掛載
## 客戶機安裝nfs客戶端及rpcbind
yum -y install  nfs-utils rpcbind

## 創建掛載目錄及掛載
mkdir /usr/local/rds
mount -t nfs 192.168.152.252:/alibaba /usr/local/rds/

[root@Centos8 rds]# df -h | grep alibaba 
192.168.152.252:/alibaba   17G  6.9G   11G   41% /usr/local/rds

## 進入目錄,測試讀寫是否正常
cd /usr/local/rds/
vim test.txt
......

 

2、創建PV(Master節點:192.168.152.53)

vim pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv1
  labels:
      type: web
spec:
  capacity:    #容量
    storage: 1Gi #存儲
  accessModes: #類型
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle #回收策略
  storageClassName: nfs #存儲類別名稱
  nfs:
    path: /alibaba
    server: 192.168.152.252

多創建幾個pv,供后邊的pvc使用

## 首先在nfs中多創建幾個文件系統
[root@kubenode2 ~]# cat /etc/exports
/alibaba1 *(rw,no_root_squash,no_all_squash,sync)
/alibaba2 *(rw,no_root_squash,no_all_squash,sync)
/alibaba3 *(rw,no_root_squash,no_all_squash,sync)
/alibaba4 *(rw,no_root_squash,no_all_squash,sync)

## 重啟nfs server和rpcbind
systemctl restart rpcbind nfs-server.service

## 再次去客戶端掛載測試讀寫

創建好的pv如下

[root@Centos8 pv]# kubectl get pv 
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfspv1   1Gi        RWO            Recycle          Available           nfs                     5s
nfspv2   10Gi       RWX            Retain           Available           cloud                   5s
nfspv3   5Gi        RWO            Recycle          Available           nfs                     5s
nfspv4   100Gi      RWX            Recycle          Available           nfs                     5s

### 創建不同的類別,存儲大小,讀寫類型
### 我這里一共創建四個pv

 

3、創建PVC

vim pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nas
spec:
  accessModes:    # 選擇類型
  - ReadWriteMany
  resources:    #選擇容量
    requests:
      storage: 10Gi
  storageClassName: cloud    # 選擇存儲類別
  selector:        # 選擇標簽可以更加准確的綁定想要綁定的pv
    matchLabels:
      type: web
[root@Centos8 pv]# kubectl create -f pvc.yaml 
persistentvolumeclaim/pvc-nas created

[root@Centos8 pv]# kubectl get pvc 
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-nas   Bound    nfspv2   10Gi       RWX            cloud          4s

[root@Centos8 pv]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON   AGE
nfspv2   10Gi       RWX            Retain           Bound       default/pvc-nas   cloud   

 

創建Deployment

vim pvc-deployment.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: pvc-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.2.1
        imagePullPolicy: IfNotPresent
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: pvc-nas    
          mountPath: /data    # 掛載路徑
      volumes:
      - name: pvc-nas    # 定義的volume名字
        persistentVolumeClaim:    # 綁定pvc
          claimName: pvc-nas    #pvc的名字
[root@Centos8 pv]# kubectl create -f pvc-deployment.yaml 
deployment.extensions/pvc-deployment created
[root@Centos8 pv]# kubectl get pod 
NAME                             READY   STATUS    RESTARTS   AGE
pvc-deployment-db7b65ff8-6nz5g   1/1     Running   0          4s
pvc-deployment-db7b65ff8-9mthh   1/1     Running   0          4s
pvc-deployment-db7b65ff8-kgx5w   1/1     Running   0          4s

## 查看當前/data目錄下文件
[root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-6nz5g -- ls /data
111
[root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-9mthh -- ls /data
111
[root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-kgx5w -- ls /data
111

## 向/data中創建文件
[root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-kgx5w -- touch /data/index.html 

## 再次查看,測試文件nas的共享存儲
[root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-kgx5w -- ls /data
111  index.html
[root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-9mthh -- ls /data
111  index.html
[root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-6nz5g -- ls /data
111  index.html

## 刪除Pod,檢驗數據的持久性 [root@Centos8 pv]# kubectl delete pod pvc-deployment-db7b65ff8-6nz5g pod "pvc-deployment-db7b65ff8-6nz5g" deleted [root@Centos8 pv]# kubectl get pod NAME READY STATUS RESTARTS AGE pvc-deployment-db7b65ff8-9mthh 1/1 Running 0 3m11s pvc-deployment-db7b65ff8-bnvw7 1/1 Running 0 47s pvc-deployment-db7b65ff8-kgx5w 1/1 Running 0 3m11s ## 再次查看,依舊是這兩個文件 [root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-bnvw7 -- ls /data 111 index.html

aliyunURL: https://help.aliyun.com/document_detail/100684.html?spm=a2c4g.11186623.6.1080.1668631aCuHGi2

4、創建StatefulSet

vim StatefulSet.yaml

apiVersion: v1
kind: Service
metadata:
  name: pvc-svc
  namespace: default
  labels:
    app: nginx
spec:
  clusterIP: None
  ports:
  - name: web
    port: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  serviceName: "pvc-svc"
  template:
    metadata:
      labels:
        app: nginx
    spec:
      dnsPolicy: ClusterFirstWithHostNet #使pod使用k8s的dns而不是宿主機dns
      containers:
      - name: nginx
        image: hub.vfancloud.com/test/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]    #指定pv的讀寫策略
      storageClassName: "nfs"    #指定pv的存儲類型
      resources:
        requests:
          storage: 1Gi    #指定pv的存儲大小

 

查看Pod、PV信息

[root@Centos8 pv]# kubectl get pod 
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          2m32s
web-1   1/1     Running   0          2m30s
web-2   0/1     Pending   0          2m27s

### yaml文件中statefulSet指定副本數為3個,其中web-2一直處於pending狀態
## 查看web-2描述,提示Pod沒有可以綁定的pv
[root@Centos8 pv]# kubectl describe pod web-2
Events:
  Warning  FailedScheduling  66s (x3 over 3m47s)  default-scheduler  pod has unbound immediate PersistentVolumeClaims

##  再看PV的狀態
### nfspv1和nfspv3的STATUS為Bound,已被綁定其他的均為Available可用狀態
### 再來回顧一下上邊yaml文件內容
### yaml中明確指出,accessModes必須為ReadWriteOnly,storageClassName必須為NFS,storage存儲為1Gi,可見,第一個pod創建時直接綁定最合適nfspv1,第二個Pod創建時由於沒有其他符合的nfs,所以綁定nfspv3,第三個Pod創建后,發現沒有合適的pv了,所以一直保持pending狀態
[root@Centos8 pv]# kubectl get pv 
NAME  CAPACITY ACCESS MODES RECLAIM POLICY STATUS  CLAIM         STORAGECLASS  
nfspv1   1Gi     RWO        Recycle      Bound     default/www-web-0     nfs
nfspv2   10Gi    RWX        Retain       Available                       cloud
nfspv3   5Gi     RWO        Recycle      Bound     default/www-web-1     nfs
nfspv4   100Gi   RWX        Recycle      Available                       nfs

 

測試訪問Pod、NFS持久性(statefulSet特性)

## 在web-0所綁定的nfs下創建index.html文件,內容如下
[root@kubenode2 alibaba1]# cat index.html 
Are you ok?

## 訪問web-0的http服務
[root@Centos8 pv]# curl http://10.244.3.56
Are you ok?

## 在web-1所綁定的nfs下創建index.html文件,內容如下
[root@kubenode2 alibaba3]# cat index.html 
qbbbbbb
bbbbb

## 訪問web-1的http服務
[root@Centos8 pv]# curl http://10.244.3.57
qbbbbbb
bbbbb

## 測試刪除pod后,存儲是否持久化
[root@Centos8 pv]# kubectl delete pod web-0
pod "web-0" deleted
[root@Centos8 pv]# kubectl get pod -o wide 
NAME    READY   STATUS    RESTARTS   AGE   IP     
web-0   1/1     Running   0          9s    10.244.3.58

## ip已經發生改變,再次測試訪問http,數據未變化
[root@Centos8 pv]# curl http://10.244.3.58
Are you ok?

aliyunURL: https://help.aliyun.com/document_detail/100013.html?spm=a2c4g.11186623.6.1084.562220d7kAeXTB

 

關於StatefulSet

1、匹配Pod name(網絡標識)的模式為:(statefulset名稱)-符號,比如上面的web-0,web-1

2、StatefulSet為每個Pod副本創建了一個DNS域名,域名格式為:$(podname).(headless server name),也就意味着服務間是通過Pod域名來通信而非Pod IP,因為Pod在Node發生故障時,會將Pod漂移到其他node節點,Pod IP會發生改變,但是Pod域名不會變化

3、StatefulSet使用Headless服務來控制Pod的域名,這個域名的FQDN為:(servicename).(namespace).svc.cluster.local,其中,"cluster.local"指的是集群的域名

4、根據VolumeClaimTemplates,為每個Pod創建一個pvc,pvc命名規則匹配模式:(volumeClaimTemplate.name)-(pod.name),比如www-web-0

5、刪除Pod不會刪除其pvc,手動刪除pvc將自動釋放pv

 

驗證DNS解析

## 當前pod
[root@Centos8 pv]# kubectl get pod 
NAME                             READY   STATUS    RESTARTS   AGE
ingress-http2-84b79f86c8-l6w7z   1/1     Running   0          8m33s
ingress-http2-84b79f86c8-sgsch   1/1     Running   0          8m33s
ingress-http2-84b79f86c8-xm7tj   1/1     Running   0          8m33s
web-0                            1/1     Running   0          24m
web-1                            1/1     Running   0          18m
web-2                            0/1     Pending   0          20m

## 當前svc
[root@Centos8 pv]# kubectl get svc 
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
ingress-svc2   ClusterIP   10.105.70.203   <none>        8080/TCP   9m4s
kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP    84d
pvc-svc        ClusterIP   None            <none>        80/TCP     25m

## 訪問statefulSet的pod,使用域名$(podname).(headless server name)的方式
[root@Centos8 pv]# kubectl exec -it web-0 -- nslookup web-1.pvc-svc

Name:      web-1.pvc-svc
Address 1: 10.244.3.90

或者

[root@Centos8 pv]# kubectl exec -it web-0 -- nslookup web-1.pvc-svc.default.svc.cluster.local.

Name:      web-1.pvc-svc.default.svc.cluster.local.
Address 1: 10.244.3.90

## 測試其他svc的Pod是否可以通過$(podname).(headless server name)的方式訪問
[root@Centos8 pv]# kubectl exec -it ingress-http2-84b79f86c8-sgsch -- nslookup web-1.pvc-svc

Name:      web-1.pvc-svc
Address 1: 10.244.3.90

或者

[root@Centos8 pv]# kubectl exec -it ingress-http2-84b79f86c8-sgsch -- nslookup web-0.pvc-svc.default.svc.cluster.local.

Name:      web-0.pvc-svc.default.svc.cluster.local.
Address 1: 10.244.3.88

## 此功能是通過無頭(headless)服務進行綁定的,最終規則如下
[root@Centos8 pv]# dig -t -A pvc-svc.default.svc.cluster.local. @10.244.0.81
;; Warning, ignoring invalid type -A

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el8 <<>> -t -A pvc-svc.default.svc.cluster.local. @10.244.0.81
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14325
;; flags: qr rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 538aadec9b559ba0 (echoed)
;; QUESTION SECTION:
;pvc-svc.default.svc.cluster.local. IN    A

;; ANSWER SECTION:
pvc-svc.default.svc.cluster.local. 17 IN A    10.244.3.90
pvc-svc.default.svc.cluster.local. 17 IN A    10.244.3.88

;; Query time: 0 msec
;; SERVER: 10.244.0.81#53(10.244.0.81)
;; WHEN: 日 7月 05 11:41:24 CST 2020
;; MSG SIZE  rcvd: 172

 

statefulSet的啟停順序

  • 有序部署:部署StatefulSet時,如果有多個Pod副本,它們會被順序的創建(從0到N-1),並且,在下一個Pod運行之前,之前的Pod必須是Ready或者Running的狀態
  • 有序刪除:當Pod被刪除時,他們被終止的順序是從N-1到0
  • 有序擴展:當Pod執行擴展操作時,與部署一樣,他們之前的Pod必須是Running和Ready狀態

statefulSet使用場景

  • 穩定的持久化存儲,即Pod重新調度后還是能訪問相同的持久化數據,基於PVC來實現
  • 穩定的網絡表示符,即Pod重新調度后其PodNname與HostName不變
  • 有序部署,有序擴展,基於init Container來實現
  • 有序收縮

刪除持久化存儲pv、pvc

## 首先刪除pvc的yaml文件,svc和statefulSet就會被刪除
[root@Centos8 pv]# kubectl delete -f StatefulSet.yaml 
service "pvc-svc" deleted
statefulset.apps "web" deleted

## 刪除pvc
[root@Centos8 pv]# kubectl delete pvc --all
persistentvolumeclaim "www-web-0" deleted
persistentvolumeclaim "www-web-1" deleted
persistentvolumeclaim "www-web-2" deleted

## 確認
[root@Centos8 pv]# kubectl get pvc
No resources found.
[root@Centos8 pv]# kubectl get statefulset
No resources found.

## 查看pv,狀態已經變為Released,雖然已經解除綁定,但還沒有完全回收
[root@Centos8 pv]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM               STORAGECLASS   REASON   AGE
nfspv1   1Gi        RWO            Recycle          Released    default/www-web-0   nfs                     6d14h
nfspv2   10Gi       RWX            Retain           Available                       cloud                   6d14h
nfspv3   5Gi        RWO            Recycle          Released      default/www-web-1   nfs                     6d14h
nfspv4   100Gi      RWX            Recycle          Available                       nfs                     6d14h

## 手動回收
[root@Centos8 pv]# kubectl edit pv nfspv3
把以下內容刪除,然后保存
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: www-web-1
    namespace: default
    resourceVersion: "323988"
    uid: 32f75ce6-5462-42c1-9913-888c803b0bf4

## 再次查看,已經完全釋放
[root@Centos8 pv]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfspv1   1Gi        RWO            Recycle          Available           nfs                     6d14h
nfspv2   10Gi       RWX            Retain           Available           cloud                   6d14h
nfspv3   5Gi        RWO            Recycle          Available           nfs                     6d14h
nfspv4   100Gi      RWX            Recycle          Available           nfs                     6d14h


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM