Kubernetes 系列(六):持久化存儲 PV與PVC


在使用容器之后,我們需要考慮的另外一個問題就是持久化存儲,怎么保證容器內的數據存儲到我們的服務器硬盤上。這樣容器在重建后,依然可以使用之前的數據。但是顯然存儲資源和 CPU 資源以及內存資源有很大不同,為了屏蔽底層的技術實現細節,讓用戶更加方便的使用,Kubernetes便引入了 PV 和 PVC 兩個重要的資源對象來實現對存儲的管理。

一、概念

PV 的全稱是:PersistentVolume(持久化卷),是對底層的共享存儲的一種抽象,PV 由管理員進行創建和配置,它和具體的底層的共享存儲技術的實現方式有關,比如 Ceph、GlusterFS、NFS 等,都是通過插件機制完成與共享存儲的對接。

PVC 的全稱是:PersistentVolumeClaim(持久化卷聲明),PVC 是用戶存儲的一種聲明,PVC 和 Pod 比較類似,Pod 消耗的是節點,PVC 消耗的是 PV 資源,Pod 可以請求 CPU 和內存,而 PVC 可以請求特定的存儲空間和訪問模式。對於真正使用存儲的用戶不需要關心底層的存儲實現細節,只需要直接使用 PVC 即可。

但是通過 PVC 請求到一定的存儲空間也很有可能不足以滿足應用對於存儲設備的各種需求,而且不同的應用程序對於存儲性能的要求可能也不盡相同,比如讀寫速度、並發性能等,為了解決這一問題,Kubernetes 又為我們引入了一個新的資源對象:StorageClass,通過 StorageClass 的定義,管理員可以將存儲資源定義為某種類型的資源,比如快速存儲、慢速存儲等,用戶根據 StorageClass 的描述就可以非常直觀的知道各種存儲資源的具體特性了,這樣就可以根據應用的特性去申請合適的存儲資源了。

(1)NFS

我們這里為了演示方便,決定使用相對簡單的 NFS 這種存儲資源,接下來我們在節點master節點(192.168.3.131)上來安裝 NFS 服務端,數據目錄:/data/k8s/

1. 關閉防火牆

systemctl stop firewalld.service
systemctl disable firewalld.service

2. 安裝配置 nfs

yum install -y nfs-utils rpcbind

安裝完成后檢查一下:

rpm -qa nfs-utils rpcbind

共享目錄設置權限:

首先在/data路徑下新建k8s文件,然后賦予操作權限

mkdir data
mkdir k8s
chmod 755 /data/k8s/

配置 nfs,nfs 的默認配置文件在 /etc/exports 文件下,在該文件中添加下面的配置信息:

vi /etc/exports
/data/k8s  *(rw,sync,no_root_squash)

配置說明:

  • /data/k8s:是共享的數據目錄
  • *:表示任何人都有權限連接,當然也可以是一個網段,一個 IP,也可以是域名
  • rw:讀寫的權限
  • sync:表示文件同時寫入硬盤和內存
  • no_root_squash:當登錄 NFS 主機使用共享目錄的使用者是 root 時,其權限將被轉換成為匿名使用者,通常它的 UID 與 GID,都會變成 nobody 身份

 

啟動nfs需要向rpc注冊,rpc一旦重啟了,注冊的文件都會丟失,向它注冊的服務都需要重啟。

下面我們來啟動nfs,注意啟動順序,先啟動rpcbind:

systemctl start rpcbind.service
systemctl enable rpcbind
systemctl status rpcbind

 

看到上面這樣的顯示就說明啟動成功了。

然后啟動 nfs 服務:

systemctl start nfs.service
systemctl enable nfs
systemctl status nfs

同樣,看到上面這樣的輸出就證明NFS Server啟動成功了。

另外我們還可以通過下面的命令確認下:

[root@localhost data]# rpcinfo -p|grep nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    3   tcp   2049  nfs_acl
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    3   udp   2049  nfs_acl

查看具體目錄掛載權限:

[root@localhost /]# cat /var/lib/nfs/etab
/data/k8s       *(rw,sync,wdelay,hide,nocrossmnt,secure,no_root_squash,no_all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,rw,secure,no_root_squash,no_all_squash)

 

到這里我們就把 nfs server 給安裝成功了,接下來我們在node1節點(192.168.3.132)上來安裝 nfs 的客戶端來驗證下 nfs

關閉防火牆

systemctl stop firewalld.service
systemctl disable firewalld.service

然后安裝 nfs

yum -y install nfs-utils rpcbind

安裝完成后,和上面的方法一樣,先啟動 rpc、然后啟動 nfs:

systemctl start rpcbind.service
systemctl enable rpcbind.service
systemctl start nfs.service
systemctl enable nfs.service

掛載數據目錄 客戶端啟動完成后,我們在客戶端來掛載下 nfs 測試下,首先檢查下 nfs 是否有共享目錄:

[root@node1 ~]# showmount -e 192.168.3.131
Export list for 192.168.3.131:
/data/k8s *

然后我們在客戶端上新建目錄:

mkdir -p /root/course/kubeadm/data

將 nfs 共享目錄掛載到上面的目錄:

mount -t nfs 192.168.3.131:/data/k8s /root/course/kubeadm/data

掛載成功后,在客戶端上面的目錄中新建一個文件,然后我們觀察下 nfs 服務端的共享目錄下面是否也會出現該文件:

touch /root/course/kubeadm/data/test.txt

然后在 nfs 服務端查看(注意是服務端哦,我這里是master節點 192.168.3.131):

[root@localhost /]# ls -ls /data/k8s/
總用量 0
0 -rw-r--r--. 1 root root 0 8月  10 23:10 test.txt

如果上面出現了 test.txt 的文件,那么證明我們的 nfs 掛載成功了。

 

(2)PV

有了上面的 NFS 共享存儲,下面我們就可以來使用 PV 和 PVC 了。PV 作為存儲資源,主要包括存儲能力、訪問模式、存儲類型、回收策略等關鍵信息,下面我們來新建一個 PV 對象,使用 nfs 類型的后端存儲,1G 的存儲空間,訪問模式為 ReadWriteOnce,回收策略為 Recyle,對應的 YAML 文件如下:(pv1-demo.yaml)

apiVersion: v1
kind: PersistentVolume
metadata:
  name:  pv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /data/k8s
    server: 192.168.3.131

Kubernetes 支持的 PV 類型有很多,比如常見的 Ceph、GlusterFs、NFS,甚至 HostPath也可以,不過 HostPath 我們之前也說過僅僅可以用於單機測試,更多的支持類型可以前往 Kubernetes PV 官方文檔進行查看,因為每種存儲類型都有各自的特點,所以我們在使用的時候可以去查看相應的文檔來設置對應的參數。

然后同樣的,直接使用 kubectl 創建即可:

[root@localhost pv]# kubectl create -f pv1-demo.yaml
persistentvolume/pv1 created
[root@localhost pv]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    1Gi        RWO            Recycle          Available                                   8s

我們可以看到 pv1 已經創建成功了,狀態是 Available,表示 pv1 就緒,可以被 PVC 申請。我們來分別對上面的屬性進行一些解讀。

Capacity(存儲能力)

一般來說,一個 PV 對象都要指定一個存儲能力,通過 PV 的 capacity屬性來設置的,目前只支持存儲空間的設置,就是我們這里的 storage=1Gi,不過未來可能會加入 IOPS、吞吐量等指標的配置。

AccessModes(訪問模式)

AccessModes 是用來對 PV 進行訪問模式的設置,用於描述用戶應用對存儲資源的訪問權限,訪問權限包括下面幾種方式:

  • ReadWriteOnce(RWO):讀寫權限,但是只能被單個節點掛載
  • ReadOnlyMany(ROX):只讀權限,可以被多個節點掛載
  • ReadWriteMany(RWX):讀寫權限,可以被多個節點掛載

注意:一些 PV 可能支持多種訪問模式,但是在掛載的時候只能使用一種訪問模式,多種訪問模式是不會生效的。

persistentVolumeReclaimPolicy(回收策略)

我這里指定的 PV 的回收策略為 Recycle,目前 PV 支持的策略有三種:

  • Retain(保留)- 保留數據,需要管理員手工清理數據
  • Recycle(回收)- 清除 PV 中的數據,效果相當於執行 rm -rf /thevoluem/*
  • Delete(刪除)- 與 PV 相連的后端存儲完成 volume 的刪除操作,當然這常見於雲服務商的存儲服務,比如 ASW EBS。

不過需要注意的是,目前只有 NFS 和 HostPath 兩種類型支持回收策略。當然一般來說還是設置為 Retain 這種策略保險一點。

狀態

一個 PV 的生命周期中,可能會處於4中不同的階段:

  • Available(可用):表示可用狀態,還未被任何 PVC 綁定
  • Bound(已綁定):表示 PV 已經被 PVC 綁定
  • Released(已釋放):PVC 被刪除,但是資源還未被集群重新聲明
  • Failed(失敗): 表示該 PV 的自動回收失敗

我們平時真正使用的資源其實是 PVC,就類似於我們的服務是通過 Pod 來運行的,而不是 Node,只是 Pod 跑在 Node 上而已,所以接下來我們就來給大家講解下 PVC 的使用方法。

 

(2)PVC

(我們需要在所有節點安裝 nfs 客戶端程序,安裝方法和上面的安裝方法一樣的。必須在所有節點都安裝 nfs 客戶端,否則可能會導致 PV 掛載不上的問題)

 

 

新建 PVC

同樣的,我們來新建一個數據卷聲明,我們來請求 1Gi 的存儲容量,訪問模式也是 ReadWriteOnce,YAML 文件如下:(pvc-nfs.yaml)

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-nfs
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

我們可以看到我們這里的聲明方法幾乎和新建 PV 是一樣的,在新建 PVC 之前,我們可以看下之前創建的 PV 的狀態:

[root@localhost pvc]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    1Gi        RWO            Recycle          Available                                   9m18s

我們可以看到當前 pv-nfs 是在 Available 的一個狀態,所以這個時候我們的 PVC 可以和這個 PV 進行綁定:

[root@localhost pvc]# kubectl create -f pvc-nfs.yaml
persistentvolumeclaim/pvc-nfs created
[root@localhost pvc]# kubectl get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-nfs   Bound    pv1      1Gi        RWO                           13s

我們可以看到 pvc-nfs 創建成功了,狀態是 Bound 狀態了,這個時候我們再看下 PV 的狀態呢:

[root@localhost pvc]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pv1    1Gi        RWO            Recycle          Bound    default/pvc-nfs                           10m

同樣我們可以看到 PV 也是 Bound 狀態了,對應的聲明是 default/pvc-nfs,就是 default 命名空間下面的 pvc-nfs,證明我們剛剛新建的 pvc-nfs 和我們的 pv-nfs 綁定成功了。

有的同學可能會覺得很奇怪,我們並沒有在 pvc-nfs 中指定關於 pv 的什么標志,它們之間是怎么就關聯起來了的呢?其實這是系統自動幫我們去匹配的,他會根據我們的聲明要求去查找處於 Available 狀態的 PV,如果沒有找到的話那么我們的 PVC 就會一直處於 Pending 狀態,找到了的話當然就會把當前的 PVC 和目標 PV 進行綁定,這個時候狀態就會變成 Bound 狀態了。

 

使用 PVC

上面我們已經知道怎么創建 PV 和 PVC 了,現在我們就來使用下我們的 PVC,這里我們使用 nginx 的鏡像來測試下:(nfs-pvc-deploy.yaml)

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nfs-pvc
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nfs-pvc
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
      volumes:
      - name: www
        persistentVolumeClaim:
          claimName: pvc-nfs

---

apiVersion: v1
kind: Service
metadata:
  name: nfs-pvc
  labels:
    app: nfs-pvc
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: web
  selector:
    app: nfs-pvc

我們這里使用 nginx 鏡像,將容器的 /usr/share/nginx/html 目錄通過 volume 掛載到名為 pvc2-nfs 的 PVC 上面,然后創建一個 NodePort 類型的 Service 來暴露服務:

[root@localhost pvc]# kubectl create -f nfs-pvc-deploy.yaml
deployment.extensions/nfs-pvc created
service/nfs-pvc created
[root@localhost pvc]# kubectl
get pods NAME READY STATUS RESTARTS AGE nfs-pvc-69f44b5958-92pp6 1/1 Running 0 12s nfs-pvc-69f44b5958-cclhm 1/1 Running 0 12s nfs-pvc-69f44b5958-kjzbr 1/1 Running 0 12s
[root@localhost pvc]# kubectl
get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nfs-pvc NodePort 10.105.217.108 <none> 80:30220/TCP 32s

然后我們就可以通過任意節點的 IP:30220端口來訪問我們這里的 Nginx 服務了,但是這個時候我們來訪問會出現403,這是為什么?我們再去看看 nfs 共享數據目錄下面有沒有數據呢?

我們發現並沒有任何數據,這是因為我們把容器目錄/user/share/nginx/html和掛載到了pvc-nfs這個 PVC 上面,這個 PVC 就是對應着我們上面的 nfs 的共享數據目錄的,該目錄下面還沒有任何數據,所以我們訪問就出現了403,現在我們在/data/k8s這個目錄下面新建一個 index.html 的文件:

[root@localhost pvc]# echo "<h1>Hello Kubernetes~</h1>" >> /data/k8s/index.html
[root@localhost pvc]# ls /data/k8s
index.html  test.txt

我們可以看到共享數據目錄中已經有一個 index.html 的文件了,由於我們掛載了 pvc-nfs 到上面的 nginx 容器中去,是不是這個時候容器目錄/user/share/nginx/html下面也有index.html這個文件了啊?所以這個時候我們再來訪問下服務,任一節點IP:30220

現在是不是正常了啊,但是我們可以看到我們容器中的數據是直接放到共享數據目錄根目錄下面的,如果以后我們又有一個新的 nginx 容器也做了數據目錄的掛載,是不是就會有沖突了啊,所以這個時候就不太好區分了,這個時候我們可以在 Pod 中使用一個新的屬性:subPath,該屬性可以來解決這個問題,我們只需要更改上面的 Pod 的 YAML 文件即可:

...
volumeMounts:
- name: www
  subPath: nginxpvc-test
  mountPath: /usr/share/nginx/html
...

更改完 YAML 文件后,我們重新更新即可:

[root@localhost pvc]# kubectl apply -f nfs-pvc-deploy.yaml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
deployment.extensions/nfs-pvc configured
service/nfs-pvc unchanged

更新完后,我們再去看看 nfs 的數據共享目錄:

[root@localhost pvc]# ls /data/k8s/
index.html  nginxpvc-test  test.txt
[root@localhost pvc]# ls /data/k8s/nginxpvc-test/

我們可以預想到現在我們訪問上面的服務,又會得到403的結果,因為nginxpvc-test目錄下面還沒有任何文件。

我們把根目錄下面的 index.html 文件一到到 nginxpvc-test 目錄下便又可以訪問了:

 

到這里我們就算完整的使用了一次 PVC 了,現在我們再來驗證下我們的數據是否會丟失,怎么驗證?首先我們把上面的 Deployment 刪除掉,這樣是不是他下面管理的3個 Pod 也會被一起刪除掉啊:

[root@localhost pvc]# kubectl delete deployment nfs-pvc
deployment.extensions "nfs-pvc" deleted

Deployment 被刪除掉了,但是 nfs 的數據共享目錄下面的數據呢?

[root@localhost pvc]# ls /data/k8s/nginxpvc-test/
index.html

還在吧?當然了如果不在了,我們用他就沒有任何意義了吧,現在我們再來重新創建上面的 Deployment,看看訪問服務還能得到上面的正常輸出結果嗎:

[root@localhost pvc]# kubectl create -f nfs-pvc-deploy.yaml
deployment.extensions/nfs-pvc created
Error from server (AlreadyExists): error when creating "nfs-pvc-deploy.yaml": services "nfs-pvc" already exists

可以看到 nfs-pvc 這個 Deployment 創建成功了,由於 Service 我們之前沒有刪除掉,所以這里提示已經存在,我們忽略就可以了,現在同樣我們用任一節點 IP:30220來訪問我們這里的服務,是不是依然可以在頁面上看到Hello Kubernetes~這里的輸出信息啊,這證明我們的數據持久化是成功的吧

 


免責聲明!

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



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