我們知道默認(rèn)情況下容器的數(shù)據(jù)都是非持久化的,在容器銷毀以后數(shù)據(jù)也跟著丟失,所以docker提供了volume機(jī)制以便將數(shù)據(jù)持久化存儲(chǔ)。類似的,k8s提供了更強(qiáng)大的volume機(jī)制和豐富的插件,解決了容器數(shù)據(jù)持久化和容器間共享數(shù)據(jù)的問題。

volume:
我們經(jīng)常會(huì)說:容器和 Pod 是短暫的。
其含義是它們的生命周期可能很短,會(huì)被頻繁地銷毀和創(chuàng)建。容器銷毀時(shí),保存在容器內(nèi)部文件系統(tǒng)中的數(shù)據(jù)都會(huì)被清除。為了持久化保存容器的數(shù)據(jù),可以使用k8s volume。
Volume 的生命周期獨(dú)立于容器,Pod 中的容器可能被銷毀和重建,但 Volume 會(huì)被保留。

k8s支持的volume類型有emptydir,hostpath,persistentVolumeClaim,gcePersistentDisk,awsElasticBlockStore,nfs,iscsi,gitRepo,secret等等,完整列表及詳細(xì)文檔可參考 http://docs.kubernetes.org.cn/429.html。

在本文中主要實(shí)踐以下幾種volume類型:

1,EmptyDir(臨時(shí)存儲(chǔ)):
emptyDir 是最基礎(chǔ)的 Volume 類型。正如其名字所示,一個(gè) emptyDir Volume 是 Host 上的一個(gè)空目錄。也就是宿主機(jī)上沒有指定的目錄或文件,直接由pod內(nèi)部映射到宿主機(jī)上。(類似于docker中的docker manager volume 掛載方式)

我們通過下面的例子來實(shí)踐emptydir:

[root@master yaml]# vim emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
  name: read-write
spec:
  containers:
  - name: write
    image: busybox
    volumeMounts:     #定義數(shù)據(jù)持久化
    - mountPath: /write     #定義掛載目錄,該目錄是pod內(nèi)部的目錄
      name: share-volume
    args:
    - /bin/sh
    - -c
    - echo hello volumes > /write/hello; sleep 3000;    

  - name: read     #在該pod內(nèi)定義第二個(gè)容器
    image: busybox
    volumeMounts:
    - mountPath: /read
      name: share-volume
    args:
    - /bin/sh
    - -c
    - cat /read/hello; sleep 30000;
  volumes:
  - name: share-volume
    emptyDir: {}       #定義一個(gè)數(shù)據(jù)持久化的類型empytdir

我們模擬一個(gè)pod里運(yùn)行了兩個(gè)容器,兩個(gè)容器共享一個(gè)volume,一個(gè)負(fù)責(zé)寫入數(shù)據(jù),一個(gè)負(fù)責(zé)讀取數(shù)據(jù)。

//運(yùn)行該pod, 并進(jìn)行查看:
[root@master yaml]# kubectl  apply -f  emptydir.yaml 
pod/read-write created
[root@master yaml]# kubectl  get pod -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
read-write   2/2     Running   0          14s   10.244.2.2   node02   <none>           <none>
//我們分別查看兩個(gè)容器中的掛載內(nèi)容:
[root@master yaml]# kubectl  exec  -it read-write -c read cat /read/hello
hello volumes
[root@master yaml]# kubectl  exec  -it read-write -c write cat /write/hello
hello volumes

參數(shù)解釋:
-c :為指定某個(gè)容器,是–container= 的縮寫,可以通過–help進(jìn)行查看。

因?yàn)?emptyDir 是 Docker Host 文件系統(tǒng)里的目錄,其效果相當(dāng)于執(zhí)行了 docker run -v /write 和 docker run -v /read。我們?cè)趎ode02
上通過 docker inspect 分別查看容器的詳細(xì)配置信息,我們發(fā)現(xiàn)兩個(gè)容器都 mount 了同一個(gè)目錄:

    Mounts: [
        {
            Type: bind,
            Source: /var/lib/kubelet/pods/756b4f4a-917a-414d-a7ee-523eecf05465/volumes/kubernetes.io~empty-dir/share-volume,
            Destination: /read,
            Mode: ,
            RW: true,
            Propagation: rprivate
        },

        {
            Type: bind,
            Source: /var/lib/kubelet/pods/756b4f4a-917a-414d-a7ee-523eecf05465/volumes/kubernetes.io~empty-dir/share-volume,
            Destination: /write,
            Mode: ,
            RW: true,
            Propagation: rprivate
        },

這里的"/var/lib/kubelet/pods/756b4f4a-917a-414d-a7ee-523eecf05465/volumes/kubernetes.io~empty-dir/share-volume"就是emptydir 掛載到dockerhost上的真正路徑。
所以我們可以進(jìn)入到該路徑下進(jìn)行查看:

[root@node02 ~]# cd /var/lib/kubelet/pods/756b4f4a-917a-414d-a7ee-523eecf05465/volumes/kubernetes.io~empty-dir/share-volume/
[root@node02 share-volume]# cat hello 
hello volumes

總結(jié)emptydir:
同個(gè)pod里邊的不同容器,共享同一個(gè)持久化目錄。當(dāng)pod節(jié)點(diǎn)刪除時(shí),volume的內(nèi)容也會(huì)被刪除,但如果僅是容器被銷毀,pod還在,則volume不受影響。也就是說emptydir的數(shù)據(jù)持久化的生命周期和使用的pod一致。一般作為臨時(shí)存儲(chǔ)使用,以及長(zhǎng)時(shí)間任務(wù)的中間過程checkpoint的臨時(shí)保存目錄,及多容器共享目錄。

2,hostPath:

1)將宿主機(jī)上已經(jīng)存在的目錄或文件掛載到容器內(nèi)部。
2)這種持久化方式,運(yùn)用場(chǎng)景不多,因?yàn)槲覀兪褂锰摂M化技術(shù)的核心就是為了于宿主機(jī)進(jìn)行隔離,但這種方式它增加了pod于節(jié)點(diǎn)之間的耦合。
3)一般對(duì)于k8s集群本身的數(shù)據(jù)持久化,和docker本身的數(shù)據(jù)持久化會(huì)使用這種方式。

比如 kube-apiserver 和 kube-controller-manager 就是這樣的應(yīng)用。
我們通過"kubectl edit -n kube-system pod kube-apiserver-master"命令來查看 kube-apiserver Pod 的配置,下面是 Volume 的相關(guān)部分:

volumeMounts:
- mountPath: /etc/ssl/certs
  name: ca-certs
  readOnly: true
- mountPath: /etc/pki
  name: etc-pki
  readOnly: true
- mountPath: /etc/kubernetes/pki
  name: k8s-certs
  readOnly: true
  volumes:
  - hostPath:
      path: /etc/ssl/certs
      type: DirectoryOrCreate
    name: ca-certs
  - hostPath:
      path: /etc/pki
      type: DirectoryOrCreate
    name: etc-pki
  - hostPath:
      path: /etc/kubernetes/pki
      type: DirectoryOrCreate
    name: k8s-certs

這里定義了三個(gè) hostPath volume 分別是k8s-certs、ca-certs 和etc- pki,分別對(duì)應(yīng) Host 目錄 /etc/kubernetes/pki、/etc/ssl/certs 和 /etc/pki。

如果 Pod 被銷毀了,hostPath 對(duì)應(yīng)的目錄也還會(huì)被保留,從這點(diǎn)看,hostPath 的持久性比 emptyDir 強(qiáng)。不過一旦 Host 崩潰,hostPath 也就沒法訪問了。

3,pv & pvc

PersistentVolume(pv):統(tǒng)一的數(shù)據(jù)持久化目錄,是指由集群管理員配置提供的某存儲(chǔ)系統(tǒng)上的一段空間,它是對(duì)底層共享存儲(chǔ)的抽象,將共享存儲(chǔ)作為一種可由用戶申請(qǐng)使用的資源,實(shí)現(xiàn)了“存儲(chǔ)消費(fèi)”機(jī)制。
PersistentVolumeClaim(PVC):用于pv持久化空間的一個(gè)申請(qǐng)(Claim),聲明。指定所需要的最低容量要求和訪問模式,然后用戶將持久卷聲明的清單提交給 kubernetes api服務(wù)器,kubernetes將找到可匹配的持久卷并將其綁定到持久卷聲明。

NFS PersistentVolume
通過 NFS 實(shí)踐PV和PVC。

1)我們?cè)趍aster節(jié)點(diǎn)上部署nfs服務(wù):

[root@master ~]# yum -y install nfs-utils
[root@master ~]# mkdir /nfsdata
[root@master ~]# vim /etc/exports   #編寫nfs配置文件
/nfsdata 172.16.1.0/24(rw,sync,no_root_squash)
[root@master ~]# systemctl enable rpcbind
[root@master ~]# systemctl start rpcbind
[root@master ~]# systemctl enable nfs-server
[root@master ~]# systemctl start nfs-server
[root@master ~]# showmount -e   #查看是否掛載成功
Export list for master:
/nfsdata 172.16.1.0/24

2)創(chuàng)建pv:

[root@master yaml]# vim nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:  
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata     #指定nfs共享目錄
    server: 172.16.1.30    #指定的是nfs服務(wù)器的ip地址
//通過以下命令來運(yùn)行pv:
[root@master yaml]# kubectl apply -f  nfs-pv.yaml 
persistentvolume/nfs-pv created
字段解釋:
capacity:指定pv的容量大小,目前,capacity僅支持空間設(shè)定,將來應(yīng)該還可以指定IOPS和throughput。
accessModes:訪問模式,有以下幾種模式:
                                              ReadWriteOnce: 以讀寫的方式掛載到單個(gè)節(jié)點(diǎn),命令行中簡(jiǎn)寫為RWO。
                                              ReadOnlyMany:以只讀的方式掛載到多個(gè)節(jié)點(diǎn),命令行中簡(jiǎn)寫為ROX。
                                              ReadWriteMany: 以讀寫的方式掛載到多個(gè)節(jié)點(diǎn),命令行中簡(jiǎn)寫為RWX。
 persistentVolumeReclaimPolicy:pv空間釋放時(shí)的回收策略,有以下幾種策略:
                                          Recycle:清除pv中的數(shù)據(jù),然后自動(dòng)回收。(自動(dòng)回收策略是由pvc的保護(hù)機(jī)制保護(hù)的,當(dāng)pv刪除后,只要pvc還在數(shù)據(jù)就還在)
                                              Retain: 保持不動(dòng),由管理員手動(dòng)回收。
                                              Delete: 刪除云存儲(chǔ)資源,僅部分云儲(chǔ)存系統(tǒng)支持,如果AWS,EBS,GCE PD,Azure Disk和Cinder。
注意:這里的回收策略是指在pv被刪除之后,所存儲(chǔ)的源文件是否刪除。
storageClassName:pv和pvc關(guān)聯(lián)的依據(jù)。
//驗(yàn)證pv是否可用:
[root@master yaml]# kubectl  get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfs-pv   1Gi (容量為1GB)       RWO (讀寫)          Recycle   (自動(dòng)回收)       Available(可用的,確保是該狀態(tài)才可被使用)           nfs(基于nfs來做的)                     18m(時(shí)間)

3)創(chuàng)建一個(gè)pvc:

[root@master yaml]# vim nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteOnce     #pv和pvc的訪問模式必須一致
  resources:             #在該字段下的requests子字段中定義要申請(qǐng)的資源
    requests:
      storage: 1Gi
  storageClassName: nfs
運(yùn)行該pvc:
[root@master yaml]# kubectl apply -f  nfs-pvc.yaml 
persistentvolumeclaim/nfs-pvc created
//驗(yàn)證pvc是否可用:
[root@master yaml]# kubectl  get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-pvc   Bound   nfs-pv   1Gi        RWO            nfs            3m53s

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

確保此時(shí)pv和pvc的狀態(tài)都為Bound,則表示綁定成功。

pv空間的使用。

接下來我們實(shí)踐mysql的pv使用:
1)創(chuàng)建一個(gè)Mysql的pod:

[root@master yaml]# vim MYSQL-pod.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mysql
spec:
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:             #定義一個(gè)變量,將容器中mysqlroot密碼映射到本地
        - name: MYSQL_ROOT_PASSWORD
          value: 123.com     #密碼為123.com
        ports:
        - containerPort: 3306
        volumeMounts:         #定義數(shù)據(jù)持久化
        - name: mysql-pv-storage
          mountPath: /var/lib/mysql   #該目錄為默認(rèn)的mysql數(shù)據(jù)持久化目錄
      volumes:                     #該volumes字段為上面的一個(gè)解釋
      - name: mysql-pv-storage        #注意名稱要與上面的名稱相同
        persistentVolumeClaim:      #指定pvc,注意下面聲明的pvc要于之前創(chuàng)建的pvc名稱一致
          claimName: nfs-pvc       
---
apiVersion: v1                  #創(chuàng)建一個(gè)service資源對(duì)象
kind: Service
metadata:
  name: mysql
spec:
  type: NodePort
  ports:
  - port: 3306
    targetPort: 3306
    nodePort: 30000
  selector:
    app: mysql
通過以下命令來運(yùn)行pod:
[root@master yaml]# kubectl apply -f  mysql-pod.yaml 
deployment.extensions/mysql created
service/mysql created
//查看pod是否正常運(yùn)行:
[root@master yaml]# kubectl  get pod -o wide mysql-68d65b9dd9-hf2bf 
NAME                     READY   STATUS    RESTARTS   AGE     IP           NODE     NOMINATED NODE   READINESS GATES
mysql-68d65b9dd9-hf2bf   1/1     Running   0          9m34s   10.244.1.3   node01   <none>           <none>

2)登錄mysql數(shù)據(jù)庫(kù),進(jìn)行寫入數(shù)據(jù):

[root@master yaml]# kubectl  exec  -it mysql-68d65b9dd9-hf2bf  -- mysql -u root -p123.com
Type \\\'help;\\\' or \\\'\\\\h\\\' for help. Type \\\'\\\\c\\\' to clear the current input statement.
mysql>
mysql> create database volumes_db;   #創(chuàng)建庫(kù)
Query OK, 1 row affected (0.01 sec)

mysql> use volumes_db;      #進(jìn)入庫(kù)中
Database changed
mysql> create table my_id(     #創(chuàng)建表
    -> id int primary key,
    -> name varchar(25)
    -> );
Query OK, 0 rows affected (0.04 sec)

mysql> insert into my_id values(1,\\\'zhangsan\\\');   #往表中寫入數(shù)據(jù)
Query OK, 1 row affected (0.01 sec)

mysql> select * from my_id;    #查看數(shù)據(jù)
 ---- ---------- 
| id | name     |
 ---- ---------- 
|  1 | zhangsan |
 ---- ---------- 
1 row in set (0.00 sec)

3)進(jìn)行驗(yàn)證:
(1)手動(dòng)刪除pod,驗(yàn)證數(shù)據(jù)庫(kù)內(nèi)數(shù)據(jù)是否還會(huì)存在

[root@master ~]# kubectl  delete pod mysql-68d65b9dd9-hf2bf 
pod mysql-68d65b9dd9-hf2bf deleted
[root@master ~]# kubectl  get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP           NODE     NOMINATED NODE   READINESS GATES
mysql-68d65b9dd9-bf9v8   1/1     Running   0          26s    10.244.1.4   node01   <none>           <none>

刪除pod后,kubernetes會(huì)生成新的pod,我們登錄mysql查看
數(shù)據(jù)是否還會(huì)存在。

[root@master ~]# kubectl  exec  -it mysql-68d65b9dd9-bf9v8 -- mysql -u root -p123.com
Type \\\'help;\\\' or \\\'\\\\h\\\' for help. Type \\\'\\\\c\\\' to clear the current input statement.

mysql> select * from volumes_db.my_id;  
 ---- ---------- 
| id | name     |
 ---- ---------- 
|  1 | zhangsan |
 ---- ---------- 
1 row in set (0.01 sec)

可以看到數(shù)據(jù)依舊會(huì)存在。

2)模擬pod運(yùn)行所在節(jié)點(diǎn)宕機(jī),在新生成的pod內(nèi),數(shù)據(jù)是否恢復(fù)正常。
從上面查看pod的信息中,我們知道pod是運(yùn)行在node01上,所以我們將集群中的node01主機(jī)關(guān)機(jī)。
##[root@node01 ~]# systemctl poweroff

過一段時(shí)間后,kubernetes會(huì)將pod遷移至集群中node02主機(jī)上:

[root@master ~]# kubectl  get nodes   #得知node01節(jié)點(diǎn)已經(jīng)宕機(jī)
NAME     STATUS     ROLES    AGE   VERSION
master   Ready      master   39d   v1.15.0
node01   NotReady   <none>   39d   v1.15.0
node02   Ready      <none>   39d   v1.15.0

[root@master ~]# kubectl  get pod -o wide
NAME                     READY   STATUS        RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
mysql-68d65b9dd9-bf9v8   1/1     Terminating   0          15m   10.244.1.4   node01   <none>           <none>
mysql-68d65b9dd9-mvxdg   1/1     Running       0          83s   10.244.2.3   node02   <none>           <none>

可以看到pod已經(jīng)遷移到了node02上。

最后我們登錄mysql,驗(yàn)證數(shù)據(jù)是否恢復(fù):

[root@master ~]# kubectl exec  -it mysql-68d65b9dd9-mvxdg  -- mysql -u root -p123.com
Type \\\'help;\\\' or \\\'\\\\h\\\' for help. Type \\\'\\\\c\\\' to clear the current input statement.

mysql> select * from volumes_db.my_id;
 ---- ---------- 
| id | name     |
 ---- ---------- 
|  1 | zhangsan |
 ---- ---------- 
1 row in set (0.09 sec)

可以得知在pod遷移之后,mysql服務(wù)正常運(yùn)行,且數(shù)據(jù)也并沒有丟失。。。

pv和pvc實(shí)現(xiàn)了mysql數(shù)據(jù)的持久化,分離了管理員和普通用戶的職責(zé),更適合生產(chǎn)環(huán)境。

更多關(guān)于云服務(wù)器域名注冊(cè),虛擬主機(jī)的問題,請(qǐng)?jiān)L問西部數(shù)碼官網(wǎng):m.bingfeng168.cn

贊(0)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享網(wǎng)絡(luò)內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-62778877-8306;郵箱:fanjiao@west.cn。本站原創(chuàng)內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明出處:西部數(shù)碼知識(shí)庫(kù) » k8s之volumes持久化存儲(chǔ)

登錄

找回密碼

注冊(cè)