持久化存儲

一、理解存儲卷

Volume(存儲卷)是Pod中能夠被多個容器訪問的共享目錄。解決了容器崩潰時文件丟失(容器中的文件默認情況下在磁盤是臨時存放)和多容器共享文件的問題。

<img src="https://confluence.mysre.cn/download/attachments/53852724/image2021-12-14_9-41-23.png?version=1&modificationDate=1639446083199&api=v2" alt="volume" width=680 />

與 docker 存儲卷的區別

docker volume:定義在容器上,生命周期是與容器的生命周期相同;

k8s volume:定義在 pod 上,與 pod 的生命周期相同,容器終止或重啟,卷的數據是不會丟失的。

k8s存儲卷類型

常用的存儲卷類型有:emptyDir、hostPash、NFS、secret、configMap、persistentVolumeClaim。
更多請參考官方鏈接

emptyDir

在 Pod 分配到 Node 時創建,初始內容為空,并且無須指定宿主機上對應的目錄文件,因為這是 Kubernetes 自動分配的一個目錄,當Pod 從 Node 上移除時,emptyDir 中的數據也會被永久刪除。

emptyDir 的一些用途如下:

1、臨時空間,例如用于某些應用程序運行時所需的臨時目錄,且無須永久保留。例如用于基于磁盤的歸并排序。
2、長時間任務的中間過程的臨時保存目錄。檢查點用于從崩潰中恢復的長時間計算。
3、一個容器需要從另一個容器中獲取數據的目錄(多容器共享目錄)。保存內容管理器容器獲取的文件,而網絡服務器容器提供數據。

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

volumes: 指定卷的名稱和類型等卷配置;

volumeMounts: 指定掛載那個卷及掛載目錄等。

使用數據卷流程:鏡像里程序寫的目錄 -> mountPath 掛載到寫的目錄 -> 引用的volumes對應的name -> 相關卷的配置

persistentVolumeClaim(重要)

持久卷聲明類型。通過這個聲明,可以在不知道存儲卷類型的情況下進行申請持久化存儲。需要和PV一起搭配。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: xxx.xxx.xx.xx
    path: "/"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: manual
  resources:
    requests:
      storage: 1Gi
---
...(省略)
spec:
      containers:
      - name: nginx-demo
        image: nginx
        imagePullPolicy: Always
        volumeMounts:
        - name: nfs-pvc-vol
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nfs-pvc-vol
        persistentVolumeClaim:
          claimName: nfs

pv/pvc完成綁定的條件:

  • 第一個條件,檢查 PV 和 PVC 的 spec 字段。比如,PV 的存儲(storage)大小,就必須滿足 PVC 的要求。
  • 第二個條件,則是 PV 和 PVC 的 storageClassName 字段必須一樣。

hostPath

hostPath 為在 Pod 上掛載宿主機上的文件或目錄,它通常可以用于以下幾方面:

1、容器應用程序生成的日志文件需要永久保存時,可以使用宿主機的高速文件系統進行存儲。

2、 需要訪問宿主機上Docker引擎內部數據結構的容器應用時,可以通過定義hostPath為宿主機/var/lib/docker目錄,使容器內部應用可以直接訪問Docker的文件系統。

注意: 在不同的Node上具有相同配置的Pod,可能會因為宿主機上的目錄和文件不同而導致對Volume上目錄和文件的訪問結果不一致。
官方地址-ctrl+f搜索關鍵字

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # 宿主上目錄位置
      path: /data
      # 此字段為可選
      type: Directory
type取值 行為
空字符串(默認)用于向后兼容,這意味著在安裝 hostPath 卷之前不會執行任何檢查。
DirectoryOrCreate 如果在給定路徑上什么都不存在,那么將根據需要創建空目錄,權限設置為 0755,具有與 kubelet 相同的組和屬主信息。
Directory 在給定路徑上必須存在的目錄。
FileOrCreate 如果在給定路徑上什么都不存在,那么將在那里根據需要創建空文件,權限設置為 0644,具有與 kubelet 相同的組和所有權。
File 在給定路徑上必須存在的文件。
Socket 在給定路徑上必須存在的 UNIX 套接字。
CharDevice 在給定路徑上必須存在的字符設備。
BlockDevice 在給定路徑上必須存在的塊設備

NFS

不像 emptyDir 那樣會在刪除 Pod 的同時也會被刪除,nfs 卷的內容在刪除 Pod 時會被保存,卷只是被卸載。 這意味著 nfs 卷可以被預先填充數據,并且這些數據可以在 Pod 之間共享。

volumes:
    - name: nfs-volume
      nfs:
        server: xxx.xx.xxx.xx # 服務地址
        path: /path # 存放路徑

secret

secret 卷用來給 Pod 傳遞敏感信息,例如密碼、OAuth 令牌和 SSH 密鑰,它們不會被寫到持久化的存儲器里面,是以文件的形式掛在到 Pod 中,且無需直接與 Kubernetes 耦合。

  • 作為掛載到一個或多個容器上的 卷 中的文件
  • 以環境變量的形式使用 Secrets
  • 由 kubelet 在為 Pod 拉取鏡像時使用
secret type類型
  • Service Account:Kubernetes 自動創建包含訪問 API 憑據的 secret,并自動修改 pod 以使用此類型的 secret。
  • Opaque:使用base64編碼存儲信息,可以通過base64 --decode解碼獲得原始數據,因此安全性弱。
  • kubernetes.io/dockerconfigjson:用于存儲docker registry的認證信息。

官方secret地址

configMap

提供了向 Pod 注入配置數據的方法,用來將非機密性的數據保存到鍵值對中,比如存儲卷中的配置文件。 ConfigMap 對象中存儲的數據可以被 configMap 類型的卷引用,然后被 Pod 中運行的 容器化應用使用(以key-value的形式)。

官方configMap地址

示例實踐:configMap引用

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
  namespace: default
data:
  log_level: INFO
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO
---
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
    - name: test
      image: busybox
      volumeMounts:
        - name: config-vol
          mountPath: /etc/config
  volumes:
    - name: config-vol
      configMap:
        name: log-config
        items:
          - key: log_level
            path: log_level

<img src="https://confluence.mysre.cn/download/attachments/53852724/image2021-12-15_11-41-47.png?version=1&modificationDate=1639539707531&api=v2" alt="configMap" width=680 />

實踐一:【掛載NFS卷】

  • step1:在master節點執行 NFS 工具包安裝命令:
yum install -y nfs-utils
systemctl enable rpcbind
systemctl enable nfs

systemctl start rpcbind
systemctl start nfs
  • step2: 創建 NFS 目錄并授權:
mkdir -p /data/nfs/pv-1 && mkdir -p /data/nfs/pv-2 && mkdir -p statefulSet-1
chmod -R 755 /data/nfs
  • step3:配置NFS目錄權限(這里我們直接設置成可讀寫):
vim /etc/exports
加入下面兩行配置
/data/nfs/pv-1     *(rw,sync,no_root_squash,no_all_squash)
/data/nfs/pv-2     *(rw,sync,no_root_squash,no_all_squash)
/data/nfs/statefulSet-1     *(rw,sync,no_root_squash,no_all_squash)


# 立即生效
exportfs -rv

step3參數exports說明:

rw 讀寫
ro 只讀
sync 數據直接寫入磁盤
async 數據先寫入內存
no_root_squash 對root用戶不壓制,在服務端都映射為服務端的root用戶,即僅使用普通用戶授權。
root_squash 如果客戶端是用戶root操作,會被壓制成nobody用戶,即可以使用 root 授權。
all_squash 不管客戶端的使用nfs的用戶是誰,都會壓制成nobody用戶
nonuid=uid: 指定uid的值
anongid=gid:指定gid的值
  • step4: 查看NFS服務的掛載卷列表
[root@master configMap]# showmount -e
Export list for master:
/data/nfs/pv-2 *
/data/nfs/pv-1 *

在使用的node節點上分別安裝nfs工具包

yum install nfs-utils

在node節點上檢查master節點的nfs servcie服務是否可用

[root@node2 config]# showmount -e 192.168.23.10
Export list for 192.168.23.10:
/data/nfs/pv-2 *
/data/nfs/pv-1 *
  • step5:創建一個pod應用來引用上面的nfs進行掛載
    nfs-kdemo.yaml
kind: Pod
apiVersion: v1
metadata:
  name: nfs-pod-test
spec:
  volumes:
    - name: nfs-volume
      nfs:
        server: 192.168.23.10
        path: /data/nfs/pv-1
  containers:
    - name: nfs-kdemo-test
      image: registry.cn-hangzhou.aliyuncs.com/liwb/kdemo:1.9
      volumeMounts:
        - name: nfs-volume
          mountPath: /var/nfs/pv-1
      command: ["/bin/sh"]
      args: ["-c", "while true; do date >> /var/nfs/pv-1/dates.txt; sleep 5; done"]

不需要進入pod,我們就可以發現在外面的掛載目錄下就能看到同步了pod中輸出的數據

[root@master nfs]# kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
nfs-pod-test     1/1     Running   0          4s
[root@master nfs]# tail -f /data/nfs/pv-1/dates.txt 
Wed Dec 15 08:42:28 UTC 2021
Wed Dec 15 08:42:33 UTC 2021
Wed Dec 15 08:42:38 UTC 2021
Wed Dec 15 08:42:43 UTC 2021
Wed Dec 15 08:42:48 UTC 2021
Wed Dec 15 08:42:53 UTC 2021
Wed Dec 15 08:42:58 UTC 2021
Wed Dec 15 08:43:03 UTC 2021
Wed Dec 15 08:43:08 UTC 2021
Wed Dec 15 08:43:13 UTC 2021
Wed Dec 15 08:43:18 UTC 2021
Wed Dec 15 08:43:23 UTC 2021
^C

二、【pv/pvc/storageClass】掛載實踐

pv/pvc/storageClass概念

從yaml文件來解釋,如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: xxx.xxx.xx.xx
    path: "/"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pv
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: manual
  resources:
    requests:
      storage: 1Gi

PVC 描述的:是 Pod 想要使用的持久化存儲的屬性,比如存儲的大小、讀寫權限等。

PV 描述的:則是一個具體的 Volume 的屬性,比如 Volume 的類型、掛載目錄、遠程存儲服務器地址等。

PVC 和 PV ,是Kubernetes對于有狀態的容器應用或者對數據需要持久化的應用場景設計的。
PV是對底層網絡共享存儲的抽象,將共享存儲定義為一種“資源”,PVC則是用戶對存儲資源的一個“申請”。

其實跟“面向對象”的思想完全一致。PVC 可以理解為持久化存儲的“接口”,它提供了對某種持久化存儲的描述,但不提供具體的實現;而這個持久化存儲的“實現“部分則由 PV 負責完成。

pv常用配置

存儲能力(Capacity):
描述存儲設備具備的能力,目前僅支持對存儲空間的設置(storage=xx),未來可能加入IOPS、吞吐率等指標的設置。

訪問模式(Access Modes):
對PV進行訪問模式的設置,用于描述用戶的應用對存儲資源的訪問權限。訪問模式如下()里的縮寫,是在CLI中的訪問模式縮寫。

  • ◎ ReadWriteOnce(RWO):讀寫權限,并且只能被單個Node掛載。
  • ◎ ReadOnlyMany(ROX):只讀權限,允許被多個Node掛載。
  • ◎ ReadWriteMany(RWX):讀寫權限,允許被多個Node掛載。
  • ◎ ReadWriteOncePod(RWOP):讀寫權限,允許單個pod掛載,這僅支持 CSI 卷和 Kubernetes 1.22+ 版。如果您想確保整個集群中只有一個 Pod 可以讀取該 PVC 或寫入該 PVC,可使用 ReadWriteOncePod 訪問模式。

存儲類別(Class):
用于綁定PVC.具有特定類別的PV只能與請求了該類別的PVC進行綁定。未設定類別的PV則只能與不請求任何類別的PVC進行綁定。其他還有存儲卷模式(Volume Mode)、回收策略(Reclaim Policy)、掛載參數(Mount Options)等。

StorageClass
StorageClass作為對存儲資源的抽象定義,對用戶設置的PVC申請屏蔽后端存儲的細節,
一方面減少了用戶對于存儲資源細節的關注;另一方面減輕了管理員手工管理PV的工作,由系統自動完成PV的創建和綁定(動態資源供應模式),實現了動態的資源供應。

關鍵配置參數:

提供者(Provisioner):

描述存儲資源的提供者,也可以看作后端存儲驅動。目前Kubernetes支持的Provisioner都以 kubernetes.io/ 為開頭,用戶也可以使用自定義的后端存儲提供者。為了符合StorageClass的用法,自定義Provisioner需要符合存儲卷的開發規范。我們用的是阿里云的 alicloud/nas

<img src="https://confluence.mysre.cn/download/attachments/53852724/image2021-12-16_20-2-4.png?version=1&modificationDate=1639656125101&api=v2" alt="sc" width=680 />

Reclaim Policy的三種狀態

  • 保持(Retain):刪除PV后后端存儲上的數據仍然存在,如需徹底刪除則需要手動刪除后端存儲volume
  • 刪除(Delete):刪除被PVC釋放的PV和后端存儲volume
  • 回收(Recycle):保留PV,但清空PV上的數據(已廢棄)

pod啟動的時候pv/pvc做了什么?
1、根據pod聲明的pvc找是否存在符合條件的pv,完成綁定(PV 和 PVC 的 spec 字段相同、PV 和 PVC 的 storageClassName 字段必須一樣);
2、為虛擬機掛載遠程磁盤到宿主機(attach);
3、格式化這個磁盤設備,然后將它掛載到宿主機指定的掛載點上。

<img src="https://confluence.mysre.cn/download/attachments/53852724/image2021-12-16_20-57-47.png?version=1&modificationDate=1639659467583&api=v2" alt="pv-pv-pvc-start-doing" width=680 />

PV生命周期
PV生命周期的各個階段某個PV在生命周期中可能處于以下4個階段(Phaes)之一。
Available:可用狀態,還未與某個PVC綁定。
Bound:已與某個PVC綁定。
Released:綁定的PVC已經刪除,資源已釋放,但沒有被集群回收。
Failed:自動資源回收失敗。

<img src="https://confluence.mysre.cn/download/attachments/53852724/image2021-12-16_20-56-52.png?version=1&modificationDate=1639659412553&api=v2" alt="生命周期" width=680 />

回收策略
當用戶對存儲資源使用完畢后,用戶可以刪除PVC,與該PVC綁定的PV將會被標記為“已釋放”,但還不能立刻與其他PVC進行綁定。通過之前PVC寫入的數據可能還被留在存儲設備上,只有在清除之后該PV才能再次使用。

在啟用動態供應模式的情況下,一旦用戶刪除了PVC,與之綁定的PV也將根據其默認的回收策略“Delete”被刪除。如果需要保留PV(用戶數據),則在動態綁定成功后,用戶需要將系統自動生成PV的回收策略從“Delete”改成“Retain”。

三、pv/pvc實踐

1、聲明一個 pvc,執行kubectl apply -f nfs-pvc.yaml,內容為:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "rwx-nfs-pvc"
  resources:
    requests:
      storage: 20Mi
2、查看 pvc 狀態:
kubectl describe pvc nfs
...
Events:
  Type    Reason         Age               From                         Message
  ----    ------         ----              ----                         -------
  Normal  FailedBinding  1s (x4 over 42s)  persistentvolume-controller  no persistent volumes available for this claim and no storage class is set
3、創建一個 statefulSet,執行kubectl apply -f nfs-deploy.yaml,內容為:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-demo
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-demo
  template:
    metadata:
      labels:
        app: nginx-demo
    spec:
      containers:
      - name: nginx-demo
        image: nginx
        imagePullPolicy: Always
        volumeMounts:
        - name: nfs-pvc-vol
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nfs-pvc-vol
        persistentVolumeClaim:
          claimName: nfs-pvc
4、觀察 pod 的狀態,可以看到: pvc 在沒有綁定pv的情況會導致pod一直處于pending;
$ kubectl describe pod <pod-name>
5、創建一個 pv,執行kubectl apply -f pv.yaml,內容為:
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 20Mi
  accessModes:
    - ReadWriteMany
  storageClassName: "rwx-nfs-pvc"
  nfs:
    server: 192.168.23.10
    path: "/data/nfs/pv-2"
6、觀察pod狀態,可以看到,容器正常運行。

這里有個PersistentVolumeController的控制器, 會不斷地查看當前每一個 PVC,是不是已經處于 Bound(已綁定)狀態。如果不是,那它就會遍歷所有的、可用的 PV,并嘗試將其與這個“單身”的 PVC 進行綁定。

7、進入容器,執行:
cd /usr/share/nginx/html ** echo "hello nfs!" > index.html
8、退出容器,執行以下命令暴露服務:
kubectl expose deployment nginx-demo --port=80 --type=NodePort --target-port=80 --name=nginx-demo
9、瀏覽器查看頁面。
10、模擬容器掛掉,重啟pod后數據是否會丟失。
11、嘗試刪除pv、pvc,看是否成功。
kubectl delete pvc nfs
kubectl delete pv nfs
12、刪除deploy后再嘗試刪除pvc/pv;

四、使用StatefulSet創建有狀態的應用

StatefulSet 有以下幾個特點

  • 穩定,并且具有唯一的網絡標識。
  • 穩定,并且可以持久存儲。
  • 有序,可優雅的部署和伸縮。
  • 有序,可優雅的刪除和停止。
  • 有序,可自動滾動更新。

即,我們的應用如有以上的任何一個特點,我們就可以使用stateFulSet控制器來完成應用的部署。

<img src="https://confluence.mysre.cn/download/attachments/53852399/image2021-12-9_1-48-48.png?version=1&modificationDate=1638985728830&api=v2" alt="statefulSet" width=840 />

statefulSet的一些概念

1.網絡標識

  • Pod 名:唯一且不會發生變化,由$(stateFulSet name)-(0-N)組成,N為一個無限大的正整數,從0開始。
  • 容器主機名:與Pod名稱一致且不會發生變化。
  • A記錄:每一個副本都擁有唯一且不變的一條A記錄制定自己,格式為:(pod name).(service name).$(namespace name).svc
  • Pod標簽,通過StateFulSet創建的每個Pod都擁有一個唯一的標簽,格式為:stateFulSet.kubernetes.io/pod-name=$(pod name),
    通常可以將新的service單獨關聯到此標簽,來解決某個Pod的問題等。

2.存儲(pvc)

每個Pod都對應一個PVC,PVC的名稱格式:(volumeClaimTemplates name)-(pod name)-(0-N),N為一個無限大的正整數,從0開始。

當Pod被刪除的時候不會自動刪除對應的PVC,需要手動刪除。
每次Pod升級,重啟,刪除重新創建后都可以保證使用的是首次使用的PVC,保證數據的唯一性與持久化。

3.有序

  • 當部署有N個副本的StatefulSet的時候,嚴格按照從0到N的順序創建,并且下一個Pod創建的前提是上一個Pod已經running狀態。
  • 當刪除有N個副本的stateFulSet的時候,嚴格按照從N到0的順序刪除,并且下一個Pod刪除的前提是上一個Pod已經完全Delete。
  • 當擴容StateFulSet副本的時候,每增加一個Pod的前提是上一個Pod已經running狀態。
  • 當減少stateFulSet副本的時候,每刪除一個Pod的前提是上一個Pod已經完全delete。
  • 當升級statefulSet的時候,嚴格按照從N到1的順序升級,并且下一個Pod升級的前提是上一個Pod已經running狀態。

4.無狀態服務(Stateless Service)

該服務運行的實例不會在本地存儲需要持久化的數據,并且多個實例對于同一個請求響應的結果是完全一致的,比如kdemo,我們可以同時啟動多個實例,但是我們訪問任意一個實例得到的結果都是一樣的,因為他唯一需要持久化的數據是存儲在MySQL數據庫中的,所以我們可以說kdemo這個應用是無狀態服務,但是MySQL數據庫就不是了,因為他需要把數據持久化到本地。

5.有狀態服務(Stateful Service)

就和上面的概念是對立的了,該無法運行的實例需要在本地存儲持久化數據,比如上面的MySQL數據庫,你現在運行在節點Node-1,那么他的數據就存儲在Node-1上面的,如果這個時候你把該服務遷移到節點Node-2去的話,那么久沒有之前的數據了,因為他需要去對應的數據目錄里面恢復數據,而此時沒有任何數據。

6.無頭服務(Headless Service)

Headless Service 在定義上和普通的 Service 幾乎一致, 只是他的 clusterIP: None,所以,這個 Service 被創建后并不會被分配一個 cluster IP,而是會以 DNS 記錄的方式暴露出它所代理的 Pod,而且還有一個非常重要的特性,對于 Headless Service 所代理的所有 Pod 的 IP 地址都會綁定一個如下所示的 DNS 記錄:

<pod-name>.<svc-name>.<namespace>.svc.cluster.local

7.volumeClaimTemplates

用于給StatefulSet的Pod申請PVC,稱為卷申請模板,它會為每個Pod生成不同的PVC,關綁定到PV,從而實現Pod的專有存儲。

實踐四:使用pv/pvc部署statefulSet類型的Deployment

1.準備一個pvc用于綁定pv
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: kdemo-statefulset-pv
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "rwx-statefulset-pvc"
  resources:
    requests:
      storage: 20Mi
2.準備用于掛載的存儲卷pvpv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: kdemo-statefulset-pv
spec:
  capacity:
    storage: 20Mi
  accessModes:
    - ReadWriteMany
  storageClassName: "rwx-statefulset-pvc"
  nfs:
    server: 192.168.23.10
    path: "/data/nfs/statefulSet-1"
3.準備用于statefulset綁定的無頭服務headless-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: kdemo-statefulset
  namespace: default
  labels:
    app: kdemo-statefulset
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
  clusterIP: None
  selector:
    app: kdemo-statefulset
4.statefulset使用的deployment文件statefulSet.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: kdemo-statefulset
  namespace: default
spec:
  serviceName: "nginx-demo"
  replicas: 1
  selector:
    matchLabels:
      app: kdemo-statefulset
  template:
    metadata:
      labels:
        app: kdemo-statefulset
    spec:
      containers:
      - name: kdemo-statefulset
        image: registry.cn-hangzhou.aliyuncs.com/liwb/kdemo:1.9
        imagePullPolicy: Always
        volumeMounts:
        - name: nfs-statefulset-vol
          mountPath: /webser/www/kdemo/web
      volumes:
      - name: nfs-statefulset-vol
        persistentVolumeClaim:
          claimName: kdemo-statefulset-pv
依次執行部署
kubectl apply -f pvc.yaml
kubectl apply -f pv.yaml 

kubectl get pv

NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfs-pv-2   1Gi        RWO            Recycle          Available           slow                    8s

# 可以看到成功創建了一個 PV 對象,狀態是:`Available`。

kubectl apply -f headless-svc.yaml 

kubectl get svc

kubectl apply -f statefulSet.yaml

kubectl get pvc

通過 Headless Service,StatefulSet 就保證了 Pod 網絡標識的唯一穩定性,由于 Pod IP 并不是固定的,所以我們訪問有狀態應用實例的時候,就必須使用 DNS 記錄的方式來訪問

最后我們可以通過刪除 StatefulSet 對象來刪除所有的 Pod,Pod是按照倒序的方式進行刪除的

kubectl delete statefulsets kdemo-statefulset

kubectl get pods -w

五、思考

k8s明明已經有了多種存儲卷方式實現持久化存儲了。為什么還要增加pv/pvc的方式?

從上面的流程看通過pv/pvc的方式其實挺復雜的,這種方式是否過度設計?

六、作業

使用StorageClass的特性實現動態創建pv。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內容