国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

這篇具有很好參考價(jià)值的文章主要介紹了K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、數(shù)據(jù)卷類型

為什么需要數(shù)據(jù)卷?

  • 容器中的文件在磁盤上是臨時存放的,這給容器中運(yùn)行比較重要的應(yīng)用程序帶來一些問題。
    1. 當(dāng)容器升級或者崩潰時,kubelet會重建容器,容器內(nèi)文件會丟失。
    2. 一個Pod中運(yùn)行多個容器時,需要共享文件。
  • 而K8s 數(shù)據(jù)卷就可以解決這兩個問題。

Volume概念:

  • Volume是與Pod綁定的(獨(dú)立于容器)與Pod具有相同生命周期的資源對象。
  • 可以將Volume的內(nèi)容理解為目錄或文件,容器若需使用某個Volume,則僅需設(shè)置volumeMounts將一個或多個Volume掛載為容器中的目錄或文件,即可訪問Volume中的數(shù)據(jù)。

常用的數(shù)據(jù)卷類型:

  1. 節(jié)點(diǎn)本地(hostPath,emptyDir)
  2. 網(wǎng)絡(luò)(NFS,Ceph,GlusterFS)
  3. 公有云(AWS EBS)
  4. K8S資源(configmap,secret)

概念圖:
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.1 臨時數(shù)據(jù)卷(節(jié)點(diǎn)掛載)

概念:

  • emptyDir卷是一個臨時存儲卷,與Pod生命周期綁定一起,如果Pod刪除了卷也會被刪除。

應(yīng)用場景

  • Pod中容器之間數(shù)據(jù)共享,是從Pod層面上提供的技術(shù)方案。
  • 當(dāng)一個Pod內(nèi)有多個容器,且都分布在同一個節(jié)點(diǎn)上時,則數(shù)據(jù)共享;若pod內(nèi)的多個容器不在同一個節(jié)點(diǎn)上時,數(shù)據(jù)不共享。

特點(diǎn):

  1. kubelet會在Node的工作目錄下為Pod創(chuàng)建EmptyDir目錄。
  2. 可以將該節(jié)點(diǎn)上的某pod工作目錄EmptyDir下的數(shù)據(jù)掛載到該pod容器里,從而實(shí)現(xiàn)本地?cái)?shù)據(jù)共享。
  3. 只有在pod所在的節(jié)點(diǎn)上才能看到本地?cái)?shù)據(jù)。
  4. Pod刪除后,本地?cái)?shù)據(jù)也會被刪除。
  5. 此種模式?jīng)]有參數(shù)應(yīng)用,其他模式都有參數(shù)應(yīng)用。

缺點(diǎn):

  • 不能持久化。當(dāng)node1節(jié)點(diǎn)上的Pod刪除后,會觸發(fā)健康檢查重新拉起容器,此時新容器在node2節(jié)點(diǎn),node2節(jié)點(diǎn)上看不到之前Node1節(jié)點(diǎn)上容器數(shù)據(jù),因?yàn)楸粍h除了。

參考地址:

  • K8S官網(wǎng)地址
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.編輯yaml文件,創(chuàng)建pod容器。

[root@k8s-master bck]# cat my-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: my-pod    ##容器名稱
spec:
  containers:
  - name: write
    image: centos
    command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
    volumeMounts:        ##定義引用數(shù)據(jù)卷
      - name: data          ##引用哪個數(shù)據(jù)卷,通過數(shù)據(jù)卷名稱來引用。
        mountPath: /data      ##將本地?cái)?shù)據(jù)卷掛載到容器里哪個路徑下。
  - name: read
    image: centos
    command: ["bash","-c","tail -f /data/hello"]
    volumeMounts:
      - name: data
        mountPath: /data
  volumes:          ##定義數(shù)據(jù)卷
  - name: data        ##數(shù)據(jù)卷名稱
    emptyDir: {}      ##數(shù)據(jù)卷類型

[root@k8s-master bck]# kubectl  apply -f my-pod.yaml 

2.進(jìn)入容器驗(yàn)證數(shù)據(jù)是否共享。

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
3.查看該pod容器在哪個節(jié)點(diǎn)上,進(jìn)入該節(jié)點(diǎn)查找本地?cái)?shù)據(jù)。

[root@k8s-node1 ~]# cd /var/lib/kubelet/pods/cdacb40e-3e2f-4c57-97bc-1fc81c446685/volumes/kubernetes.io~empty-dir

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
4.刪除pod,數(shù)據(jù)目錄也會被刪除。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.2 節(jié)點(diǎn)數(shù)據(jù)卷(節(jié)點(diǎn)掛載)

概念:

  • hostPath卷:掛載Node文件系統(tǒng)(Pod所在節(jié)點(diǎn))上文件或者目錄到Pod中的容器。
  • 和 emptyDir數(shù)據(jù)卷一樣,只能在pod容器所在的node節(jié)點(diǎn)上查看到掛載目錄文件數(shù)據(jù),但區(qū)別是hostPath數(shù)據(jù)卷掛載不會因?yàn)閯h除pod而導(dǎo)致宿主機(jī)上的掛載目錄文件消失。

缺點(diǎn):

  • 不能持久化。當(dāng)node1節(jié)點(diǎn)上的Pod刪除后,會觸發(fā)健康檢查重新拉起容器,此時新容器在node2節(jié)點(diǎn),node2節(jié)點(diǎn)上看不到之前Node1節(jié)點(diǎn)上容器數(shù)據(jù),因?yàn)楸粍h除了。

應(yīng)用場景

  • 容器應(yīng)用的關(guān)鍵數(shù)據(jù)需要被持久化到宿主機(jī)上。
  • 需要使用Docker中的某些內(nèi)部數(shù)據(jù),可以將主機(jī)的/var/lib/docker目錄掛載到容器內(nèi)。
  • 監(jiān)控系統(tǒng),例如cAdvisor需要采集宿主機(jī)/sys目錄下的內(nèi)容。
  • Pod的啟動依賴于宿主機(jī)上的某個目錄或文件就緒的場景。

type字段的取值類型:

  • htstPath數(shù)據(jù)卷有個可選字段type。
  • FileOrCreate 模式不會負(fù)責(zé)創(chuàng)建文件的父目錄。 如果欲掛載的文件的父目錄不存在,Pod 啟動會失敗。 為了確保這種模式能夠工作,可以嘗試把文件和它對應(yīng)的目錄分開掛載
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

注意事項(xiàng):

  • HostPath 卷存在許多安全風(fēng)險(xiǎn),最佳做法是盡可能避免使用 HostPath。 當(dāng)必須使用 HostPath 卷時,它的范圍應(yīng)僅限于所需的文件或目錄,并以只讀方式掛載。
  • 如果通過 AdmissionPolicy 限制 HostPath 對特定目錄的訪問,則必須要求 volumeMounts 使用 readOnly 掛載以使策略生效。

1.編輯yaml文件,將宿主機(jī)上的/tmp目錄掛載到test容器里的/data目錄下,數(shù)據(jù)卷為data。

[root@k8s-master bck]# cat hostPath.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  containers:
  - name: test
    image: centos
    command: ["bash","-c","for i in {1..1000};do echo $i >> /data/hello;sleep 1;done"]
    volumeMounts:
      - name: data
        mountPath: /data
  volumes:
  - name: data
    hostPath:
      path: /tmp
      type: Directory

2.導(dǎo)入yaml,進(jìn)入容器查看/data目錄已經(jīng)把節(jié)點(diǎn)機(jī)器上的/tmp目錄映射進(jìn)來,我這里的pod2部署在node1節(jié)點(diǎn)上的,就去node1節(jié)點(diǎn)上看,其他節(jié)點(diǎn)不共享數(shù)據(jù)看不到。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
3. 修改yaml,同時掛載2個目錄,根據(jù)數(shù)據(jù)卷的名稱識別一一掛載。

[root@k8s-master bck]# cat hostPath.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  containers:
  - name: web
    image: centos
    command: ["bash","-c","for i in {1..1000};do echo $i >> /data/hello;sleep 1;done"]
    volumeMounts:
      - name: data
        mountPath: /data
      - name: qingjun
        mountPath: /opt
  volumes:
  - name: data
    hostPath:
      path: /tmp
      type: Directory
  - name: qingjun
    hostPath:
      path: /
      type: Directory

4.進(jìn)入Pod所在節(jié)點(diǎn),進(jìn)入容器,查看。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.3 網(wǎng)絡(luò)數(shù)據(jù)卷NFS

概念:

  • NFS是一個主流的文件共享服務(wù)器,NFS卷提供對NFS掛載支持,可以自動將NFS共享路徑掛載到Pod中。

注意事項(xiàng):

  1. 每個Node上都要安裝nfs-utils包。

概念圖:
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.選擇一臺服務(wù)器作為NFS服務(wù)器。我這里選擇的是node2。

1.安裝nfs服務(wù)。
[root@k8s-node2 ~]# yum -y install nfs-utils

2.創(chuàng)建共享目錄,名字自取,并編輯共享規(guī)則:只能是192.168.130.0網(wǎng)段的機(jī)器上的root用戶訪問,具備讀寫權(quán)限。
[root@k8s-node2 ~]# mkdir -p /nfs/k8s
[root@k8s-node2 ~]# cat /etc/exports
/nfs/k8s 192.168.130.0/24(rw,no_root_squash)

3.啟動服務(wù),并設(shè)置開機(jī)自啟。
[root@k8s-node2 ~]# systemctl  start nfs
[root@k8s-node2 ~]# systemctl  enable nfs

2.在其他所有節(jié)點(diǎn)上安裝nfs客戶端,不然無法掛載。

[root@k8s-master bck]# yum -y install nfs-utils
[root@k8s-node1 ~]# yum -y install nfs-utils

#掛載。在其他工作節(jié)點(diǎn)上掛載,將192.168.130.147上的/nfs/k8s目錄掛載到本地的/mnt/目錄下。
[root@k8s-node1 ~]# mount -t nfs 192.168.130.147:/nfs/k8s /mnt/

#取消掛載。
[root@k8s-node1 ~]# umount /mnt/

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
3.此時在node1節(jié)點(diǎn)上的/mnt/下操作,就相當(dāng)于在NFS服務(wù)器上的/nfs/k8s目錄下操作。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
4.查看容器內(nèi)的掛載情況。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.3.1 效果測試

1.編輯yaml文件,創(chuàng)建pod容器。

[root@k8s-master bck]# cat qingjun.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: baimu
  name: baimu
spec:
  replicas: 3
  selector:
    matchLabels:
      app: baimu
  template:
    metadata:
      labels:
        app: baimu
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:     ##定義掛載規(guī)則。
        - name: mq            ##指定掛載哪個數(shù)據(jù)卷。
          mountPath: /usr/share/nginx/html       ##指定將數(shù)據(jù)掛載到容器里的哪個目錄下。
      volumes:        ##定義掛載卷。
      - name: mq        ##掛載卷名稱。
        nfs:
          server: 192.168.130.147     ##指定nfs服務(wù)器地址,網(wǎng)絡(luò)能通。
          path: /nfs/k8s         ##指定nfs服務(wù)器上的共享目錄。

2.數(shù)據(jù)共享測試。

  • 創(chuàng)建一組pod,內(nèi)有3個容器,查看進(jìn)入容器驗(yàn)證。
    1. 先進(jìn)入第一個容器的掛載目錄,查看已經(jīng)將nfs服務(wù)器上的/nfs/k8s目錄下的內(nèi)容掛載進(jìn)來。
    2. 創(chuàng)建888目錄,nfs服務(wù)器上查看888目錄被創(chuàng)建。
    3. 退出第一個容器,在nfs服務(wù)器共享目錄下創(chuàng)建22222目錄,再進(jìn)入第二個容器查看22222目錄被同步創(chuàng)建。

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
3.重建pod,新pod數(shù)據(jù)共享測試。

  1. 刪除podl里的第三個容器,等待新容器被創(chuàng)建運(yùn)行。
  2. 進(jìn)入新容器掛載目錄,查看該目錄下也共享nfs服務(wù)器上的共享目錄。

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
4.擴(kuò)容新pod數(shù)據(jù)共享測試。

  1. 擴(kuò)容副本到5個。
  2. 進(jìn)入新容器的掛載目錄,查看該目錄下也共享nfs服務(wù)器上的共享目錄。

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.4 持久數(shù)據(jù)卷(PVC/PV)

為什么會有PVC、PV?

  1. 提高安全性。上文我們使用nfs掛載出來的信息都是記錄在yaml文件中,安全性低。
  2. 職責(zé)分離。當(dāng)后端需要用到存儲時,作為非專業(yè)人士來說,存儲這塊的工作量是需要專門的運(yùn)維大佬來做的,而后端只需要簡單的提交你程序所需要的存儲大小即可,這樣一來就可以職責(zé)分離。

概念:

  • PersistentVolume(PV):由管理員創(chuàng)建和配置,將存儲定義為一種容器應(yīng)用可以使用的資源,使得存儲作為集群中的資源管理。
  • PersistentVolumeClaim(PVC):用戶來操作,是對存儲資源的一個申請,讓用戶不需要關(guān)心具體的Volume實(shí)現(xiàn)細(xì)節(jié)。

概念圖:

  1. 管理員需要提前定義pv,是手動的,也能自動創(chuàng)建需要依賴過StorageClass資源,后面講。
  2. 用戶在創(chuàng)建pod時,需要在yaml里定義pvc,內(nèi)容包括pvc名稱、申請資源大小、訪問模式。
  3. K8s通過PVC查找匹配到合適的PV,并掛載到Pod容器里。
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.用戶定義pod和pvc。

[root@k8s-master bck]# cat web1.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web1
  name: web1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: mq
          mountPath: /usr/share/nginx/html
      volumes:
      - name: mq
        persistentVolumeClaim:
          claimName: qingjun        ##這里的名稱需要與PVC名稱一致。
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: qingjun                ##PVC名稱
spec:
  accessModes:
    - ReadWriteMany    ##訪問模式,ReadWriteOnce、ReadOnlyMany或ReadWriteMany。
  resources:
    requests:
      storage: 5Gi           ##程序要申請的存儲資源。

2.導(dǎo)入yaml,查看pod和pvc都處于等待狀態(tài),是因?yàn)榇藭r還沒有關(guān)聯(lián)到pv。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
3.管理員定義創(chuàng)建pv,導(dǎo)入yaml,pvc和Pod狀態(tài)改變。

[root@k8s-master bck]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: text            ##PV名稱,自定義。
spec:
  capacity:
    storage: 5Gi           ##容量。
  accessModes:
    - ReadWriteMany
  nfs:
    path: /nfs/k8s           ##定義nfs掛載卷共享目錄。
    server: 192.168.130.147      ##指定nfs服務(wù)器地址。

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
4.進(jìn)入Pod容器驗(yàn)證數(shù)據(jù)共享。Pod滾動升級、擴(kuò)容也都會共享數(shù)據(jù),測試方法同上文的nfs測試流程。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.4.1 效果測試

1.先在nfs服務(wù)器上創(chuàng)建多個目錄,作為多個pv掛載目錄。

[root@k8s-node2 k8s]# pwd
/nfs/k8s
[root@k8s-node2 k8s]# mkdir pv0001
[root@k8s-node2 k8s]# mkdir pv0002
[root@k8s-node2 k8s]# mkdir pv0003

2.創(chuàng)建3個pv,分別為:

  1. pv0001,內(nèi)存5G,掛載nfs服務(wù)器為192.168.130.147,掛載目錄為/nfs/k8s/pv0001。
  2. pv0002,內(nèi)存25G,掛載nfs服務(wù)器為192.168.130.147,掛載目錄為/nfs/k8s/pv0002。
  3. pv0003,內(nèi)存50G,掛載nfs服務(wù)器為192.168.130.147,掛載目錄為/nfs/k8s/pv0003。
[root@k8s-master bck]# cat pv-all.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /nfs/k8s/pv0001
    server: 192.168.130.147
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0002
spec:
  capacity:
    storage: 25Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /nfs/k8s/pv0002
    server: 192.168.130.147
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /nfs/k8s/pv0003
    server: 192.168.130.147

[root@k8s-master bck]# kubectl  apply -f pv-all.yaml

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
3.創(chuàng)建第一個pvc,名稱為web1-pvc,申請資源10G。此時pv和內(nèi)存為25G的pv0002綁定在一起。

[root@k8s-master bck]# cat web1.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web1
  name: web1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: mq
          mountPath: /usr/share/nginx/html

      volumes:
      - name: mq
        persistentVolumeClaim:
          claimName: web1-pvc

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: web1-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
4.創(chuàng)建第二個pvc,名稱為web2-pvc,申請資源25G。此時pv和內(nèi)存為50G的pv0003綁定在一起。

[root@k8s-master bck]# cat web2.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web2
  name: web2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web2
  template:
    metadata:
      labels:
        app: web2
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: mq
          mountPath: /usr/share/nginx/html

      volumes:
      - name: mq
        persistentVolumeClaim:
          claimName: web2-pvc

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: web2-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 25Gi


[root@k8s-master bck]# kubectl  apply -f web2.yaml 

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
5.創(chuàng)建第三個pvc,名稱為web3-pvc,申請資源6G。此時pv沒有和剩余的pv0001綁定。為什么呢?

[root@k8s-master bck]# cat web3.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web3
  name: web3
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web3
  template:
    metadata:
      labels:
        app: web3
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: mq
          mountPath: /usr/share/nginx/html

      volumes:
      - name: mq
        persistentVolumeClaim:
          claimName: web3-pvc

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: web3-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 6Gi

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.4.2 測試結(jié)論

pvc與pv怎么匹配的?

  • 主要根據(jù)存儲容量和訪問模式。我們定義pvc、pv的yaml文件里,都有這兩個字段,并不是說創(chuàng)建了3個pv,再創(chuàng)建的3個pvc就能一一對上,還要根據(jù)第二點(diǎn),存儲容量。

存儲容量怎么匹配的 ?

  • 向上就近容量匹配。比如上文的web1-pvc,它的申請容量為10G,那再已有的三個pvc里面,容量分別為5G、25G、50G,就去匹配向上的、匹配就近的25G;當(dāng)web2-pvc來匹配時,它的申請容量為25G,再剩下的兩個pvc里面,就去匹配向上就近的50G;剩下的web3-pvc匹配時,它的申請容量為6G,再僅剩的一個pvc5G,是滿足不了“向上就近原則”,所以就沒匹配中。

pv與pvc的關(guān)系

  • 一對一

容量能不能限制?

  • 目前容量主要用作pvc與pv匹配的,具體的限制取決于后端存儲。

二、PV、PVC生命周期

  1. AccessModes(訪問模式):AccessModes 是用來對 PV 進(jìn)行訪問模式的設(shè)置,用于描述用戶應(yīng)用對存儲資源的訪問權(quán)限,訪問權(quán)限包括下面幾種方式:
    • ReadWriteOnce(RWO):讀寫權(quán)限,但是只能被單個節(jié)點(diǎn)掛載。常用于塊設(shè)備存儲(云硬盤)。
    • ReadOnlyMany(ROX):只讀權(quán)限,可以被多個節(jié)點(diǎn)掛載。常用于數(shù)據(jù)共享(文件系統(tǒng)存儲)。
    • ReadWriteMany(RWX):讀寫權(quán)限,可以被多個節(jié)點(diǎn)掛載
  2. RECLAIM POLICY(回收策略):指PVC刪除之后,PV是去是留的一種策略。
    目前 PV 支持的策略有三種:
    • Retain(保留): 保留數(shù)據(jù),需要管理員手工清理數(shù)據(jù)。
    • Recycle(回收):清除 PV 中的數(shù)據(jù),效果相當(dāng)于執(zhí)行 rm -rf /ifs/kuberneres/*
    • Delete(刪除):與 PV 相連的后端存儲同時刪除
  3. STATUS(狀態(tài)):
    一個 PV 的生命周期中,可能會處于4中不同的階段:
    • Available(可用):表示可用狀態(tài),還未被任何 PVC 綁定。
    • Bound(已綁定):表示 PV 已經(jīng)被 PVC 綁定。
    • Released(已釋放):PVC 被刪除,但是資源還未被集群重新聲明。
    • Failed(失敗): 表示該 PV 的自動回收失敗。

2.1 各階段工作原理

生命周期階段:

  • 我們可以將PV看作可用的存儲資源,PVC則是對存儲資源的需求。
  • PV和PVC的生命周期包括資源供應(yīng)(Provisioning)、資源綁定(Binding)、資源使用(Using)、資源回收(Reclaiming)幾個階段。
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

2.1.1 資源供應(yīng)

  • K8s支持兩種資源供應(yīng)模式:靜態(tài)模式(Static)和動態(tài)模式(Dynamic),資源供應(yīng)的結(jié)果就是將適合的PV與PVC成功綁定。
    • 靜態(tài)模式:運(yùn)維預(yù)先創(chuàng)建許多PV,在PV的定義中能夠體現(xiàn)存儲資源的特性。
    • 動態(tài)模式:運(yùn)維無須預(yù)先創(chuàng)建PV,而是通過StorageClass的設(shè)置對后端存儲資源進(jìn)行描述,標(biāo)記存儲的類型和特性。用戶通過創(chuàng)建PVC對存儲類型進(jìn)行申請,系統(tǒng)將自動完成PV的創(chuàng)建及與PVC的綁定。如果PVC聲明的Class為空"",則說明PVC不使用動態(tài)模式。另外,Kubernetes支持設(shè)置集群范圍內(nèi)默認(rèn)的StorageClass設(shè)置,通過kube-apiserver開啟準(zhǔn)入控制器DefaultStorageClass,可以為用戶創(chuàng)建的PVC設(shè)置一個默認(rèn)的存儲類StorageClass。

靜態(tài)模式工作原理圖:
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
動態(tài)模式原理圖:
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

2.1.2 資源綁定

  • 當(dāng)用戶定義PVC后,系統(tǒng)將根據(jù)PVC對存儲資源的請求(存儲空間和訪問模式)在提前創(chuàng)建好的PV中選擇一個滿足要求的PV,并與PVC綁定。
  • 若系統(tǒng)中沒有滿足要求的PV,PVC則會無限期處于Pending狀態(tài),直到系統(tǒng)管理員創(chuàng)建了一個符合其要求的PV。
  • PV只能一個PVC綁定,綁定關(guān)系是一對一的,不會存在一對多的情況。
  • 若PVC申請的存儲空間比PV擁有的空間少,則整個PV的空間都能為PVC所用,可能會造成資源的浪費(fèi)。
  • 若資源供應(yīng)使用的是動態(tài)模式,則系統(tǒng)在為PVC找到合適的StorageClass后,將自動創(chuàng)建一個PV并完成與PVC的綁定。

2.1.3 .資源使用

  • 若Pod需要使用存儲資源,則需要在yaml里定義Volume字段引用PVC類型的存儲卷,將PVC掛載到容器內(nèi)的某個路徑下進(jìn)行使用。
  • 同一個PVC還可以被多個Pod同時掛載使用,在這種情況下,應(yīng)用程序需要處理好多個進(jìn)程訪問同一個存儲的問題。

使用中的存儲對象保護(hù)機(jī)制:

  • PV、PVC存儲資源可以單獨(dú)刪除。當(dāng)刪除時,系統(tǒng)會檢測存儲資源當(dāng)前是否正在被使用,若仍被使用,則對相關(guān)資源對象的刪除操作將被推遲,直到?jīng)]被使用才會執(zhí)行刪除操作,這樣可以確保資源仍被使用的情況下不會被直接刪除而導(dǎo)致數(shù)據(jù)丟失。
  • 若刪除的PVC有被使用時,則會等到使用它的Pod被刪除之后再執(zhí)行,此時PVC狀態(tài)為Terminating。
  • 若刪除的PV有被使用時,則會等到綁定它的PVC被刪除之后再執(zhí)行,此時PV狀態(tài)為Terminating。

2.1.4 資源回收

  • 回收策略,指PVC刪除之后,PV是去是留的一種策略。目前 PV 支持的策略有三種:
    • Retain(保留): 保留數(shù)據(jù),需要管理員手工清理數(shù)據(jù)。
    • Recycle(回收):清除 PV 中的數(shù)據(jù),效果相當(dāng)于執(zhí)行 rm -rf /ifs/kuberneres/*
    • Delete(刪除):與 PV 相連的后端存儲同時刪除

2.1.5 PVC資源擴(kuò)容

  • PVC在首次創(chuàng)建成功之后,還可以在使用過程中進(jìn)行存儲空間的擴(kuò)容。
  • 支持PVC擴(kuò)容的存儲類型有:AWSElasticBlockStore、AzureFile、AzureDisk、Cinder、FlexVolume、GCEPersistentDisk、Glusterfs、Portworx Volumes、RBD和CSI等。

擴(kuò)容步驟:

  1. 先在PVC對應(yīng)的StorageClass中設(shè)置參數(shù)“allowVolumeExpansion=true”。
  2. 修改pvc.yaml,將resources.requests.storage設(shè)置為一個更大的值。

擴(kuò)容失敗恢復(fù)步驟:

  1. 設(shè)置與PVC綁定的PV資源的回收策略為“Retain”。
  2. 刪除PVC,此時PV的數(shù)據(jù)仍然存在。
  3. 刪除PV中的claimRef定義,這樣新的PVC可以與之綁定,結(jié)果將使得PV的狀態(tài)為“Available”。
  4. 新建一個PVC,設(shè)置比PV空間小的存儲空間申請,同時設(shè)置volumeName字段為PV的名稱,結(jié)果將使得PVC與PV完成綁定。
  5. 恢復(fù)PVC的原回收策略

2.2 測試PV回收策略

2.2.1 Retain保留策略

  • Retain策略表示在刪除PVC之后,與之綁定的PV不會被刪除,僅被標(biāo)記為已釋放(released)。PV中的數(shù)據(jù)仍然存在,在清空之前不能被新的PVC使用,需要管理員手工清理之后才能繼續(xù)使用。
  • 清理步驟:
    1. 刪除PV資源對象,此時與該P(yáng)V關(guān)聯(lián)的某些外部存儲提供商(例如AWSElasticBlockStore、GCEPersistentDisk、AzureDisk、Cinder等)的后端存儲資產(chǎn)(asset)中的數(shù)據(jù)仍然存在。
    2. 手工清理PV后端存儲資產(chǎn)(asset)中的數(shù)據(jù)。
    3. 手工刪除后端存儲資產(chǎn)。如果希望重用該存儲資產(chǎn),則可以創(chuàng)建一個新的PV與之關(guān)聯(lián)。

1.如圖。已有一個pv和pvc關(guān)聯(lián)綁定,進(jìn)入容器查看驗(yàn)證成功。

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
2.刪除pvc,查看pv狀態(tài)變?yōu)镽eleased已釋放狀態(tài)。此時的pv不可用,需要把pv里面的數(shù)據(jù)轉(zhuǎn)移到其他機(jī)器做備份。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
3.也就是nfs機(jī)器上的共享目錄下的數(shù)據(jù)。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

2.2.2 Recycle回收策略

  • Recycle和Delete策略都是和存儲類配合使用才能測出效果。
  • 回收策略 Recycle 已被廢棄,取而代之的建議方案是使用動態(tài)制備,單獨(dú)創(chuàng)建一個pod來進(jìn)行刪除操作。
  • 目前只有HostPort和NFS類型的Volume支持Recycle策略,其實(shí)現(xiàn)機(jī)制為運(yùn)行rm-rf/thevolume/*命令,刪除Volume目錄下的全部文件,使得PV可以被新的PVC使用。
  • 刪除模板:
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.創(chuàng)建pv時,添加策略參數(shù)。

[root@k8s-master bck]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: text1            ##PV名稱,自定義。
spec:
  persistentVolumeReclaimPolicy: Recycle   ##Recycle回收策略。
  capacity:
    storage: 10Gi           ##容量。
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /nfs/k8s           
    server: 192.168.130.147

2.導(dǎo)入pv.yaml后,再創(chuàng)建pvc與之綁定。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
3.刪除pvc,pv的數(shù)據(jù)被刪除,也就是nfs服務(wù)器的共享目錄下的數(shù)據(jù)被刪除。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

4.這里沒有被刪除是因?yàn)閯h除操作要拉取國外的一個鏡像生成一個新容器,這個容器去刪除pv里的數(shù)據(jù),所以這里就拉取失敗了。若要使用該策略,需要提前拉取這個鏡像。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

2.3 StorageClass動態(tài)供給

什么是靜態(tài)供給?

  • 我們前面演示時,都是手動寫pv.yaml文件提前創(chuàng)建好存儲大小不同的pv,當(dāng)有pvc需求時就會根據(jù)需求大小去匹配對應(yīng)的pvc從而綁定。關(guān)鍵詞是手動創(chuàng)建,所以維護(hù)成本高。

什么是動態(tài)供給?

  • 為了解決靜態(tài)供給的缺點(diǎn),K8s開始支持PV動態(tài)供給,使用StorageClass對象實(shí)現(xiàn)。
  • 當(dāng)有pvc需求時,就可以自動創(chuàng)建pv與之綁定。關(guān)鍵詞是自動生成。

靜態(tài)供給概念圖:
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
動態(tài)供給概念圖:
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
實(shí)現(xiàn)PV動態(tài)補(bǔ)給流程步驟:

  1. 部署動態(tài)供給程序,是以容器方式部署的,調(diào)取api server 獲取指定自己的pvc。
  2. 創(chuàng)建pod時,在pod.yaml里定義pvc資源,并在pvc資源下面指定存儲類。
  3. 調(diào)取后端nfs服務(wù)器創(chuàng)建共享目錄,再調(diào)取api server創(chuàng)建pv,從而實(shí)現(xiàn)自動創(chuàng)建pv動作。
  4. 流程圖:
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

2.3.1 部署存儲插件

  • 支持動態(tài)補(bǔ)給的存儲插件
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
  • 社區(qū)獲取各存儲插件yanl文件
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
  • nfs獲取地址路徑
  • 文件地址,下載這三個yaml文件上傳到服務(wù)器。
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
    K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

1.將這個三個文件上傳至服務(wù)器,修改其中兩個yaml文件參數(shù)。

[root@k8s-master storageclass]# cat class.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage     ##自定義名稱。
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner 
parameters:
  archiveOnDelete: "false"



[root@k8s-master storageclass]# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
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: lizhenliang/nfs-subdir-external-provisioner:v4.0.1
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner      ##與class.yaml文件里的名稱保持一致。
            - name: NFS_SERVER
              value: 192.168.130.147       ##修改nfs服務(wù)器地址
            - name: NFS_PATH
              value: /nfs/k8s         ##修改nfs服務(wù)器共享目錄。
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.130.147         ##修改nfs服務(wù)器地址
            path: /nfs/k8s                  ##修改nfs服務(wù)器共享目錄。

2.導(dǎo)入yaml文件,查看存儲類。

  • kubectl apply -f rbac.yaml # 授權(quán)訪問apiserver
  • kubectl apply -f deployment.yaml # 部署插件,需修改里面NFS服務(wù)器地址與共享目錄。
  • kubectl apply -f class.yaml # 創(chuàng)建存儲類。
  • kubectl get sc # 查看存儲類

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

2.3.2 使用插件

1.編輯yaml文件創(chuàng)建pvc,指定使用哪個存儲類,也就是我們上面創(chuàng)建的sc。

[root@k8s-master bck]# cat pvc.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web1
  name: web1
spec:
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: mq
          mountPath: /usr/share/nginx/html
      volumes:
      - name: mq
        persistentVolumeClaim:
          claimName: qingjun        
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: qingjun                
spec:
  storageClassName: "managed-nfs-storage"      ##添加此行,指定使用已創(chuàng)建的sc。
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi

2.創(chuàng)建pvc后會自動創(chuàng)建一個pv,并且是綁定狀態(tài),帶有storage標(biāo)識,最后成功創(chuàng)建了deploy。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
3.進(jìn)入pod檢查。會在共享目錄里隨機(jī)生成一個目錄,

/nfs/k8s/default-qingjun-pvc-d207b4d4-8966-43d0-b32c-6caf45ee54b8

default:代表命名空間。
qingjun:代表pvc名稱。
pvc-d207b4d4-8966-43d0-b32c-6caf45ee54b8:代表pv名稱。

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
4.此時刪除pvc,會發(fā)現(xiàn)pv及其數(shù)據(jù)也會被刪除,是因?yàn)槟J(rèn)的回收策略是“Delete”。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

5.修改歸檔刪除策略。

[root@k8s-master storageclass]# cat class.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner 
parameters:
  archiveOnDelete: "true"     ##默認(rèn)為flase,代表直接刪除不備份。修改成true代表先備份再刪除。



[root@k8s-master storageclass]#  kubectl  delete -f class.yaml   #刪除原來的。
[root@k8s-master storageclass]#  kubectl  apply -f class.yaml    #再導(dǎo)入新的,更新。

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

三、StatefulSet

3.1 控制器介紹

StatefulSet控制器作用:

  • StatefulSet控制器用于部署有狀態(tài)應(yīng)用,滿足一些有狀態(tài)應(yīng)用的需求。

控制器特點(diǎn):

  • Pod有序的部署、擴(kuò)容、刪除和停止。
  • Pod分配一個穩(wěn)定的且唯一的網(wǎng)絡(luò)標(biāo)識。
  • Pod分配一個獨(dú)享的存儲。

無狀態(tài)與有狀態(tài):

  • 無狀態(tài):Deployment控制器設(shè)計(jì)原則是,管理的所有Pod一模一樣,提供同一個服務(wù),也不考慮在哪臺Node運(yùn)行,可隨意擴(kuò)容和縮容。這種應(yīng)用稱為“無狀態(tài)”。例如Web服務(wù)集群,每個工作節(jié)點(diǎn)上都有一個nginx容器,它們之間不需要互相業(yè)務(wù)“交流”,具備這個特點(diǎn)的應(yīng)用就是“無狀態(tài)”。
  • 有狀態(tài):像分布式應(yīng)用這種,需要部署多個實(shí)例,實(shí)例之間有依賴關(guān)系,例如主從關(guān)系、主備關(guān)系,這種應(yīng)用稱為“有狀態(tài)”,例如MySQL主從、Etcd集群。

無狀態(tài)應(yīng)用特點(diǎn):

  • 每個pod一模一樣。
  • 每個pod之間沒有連接關(guān)系。
  • 使用共享存儲。

有狀態(tài)應(yīng)用特點(diǎn):

  • 每個pod不對等,承擔(dān)的角色不同。
  • pod之間有連接關(guān)系。
  • 每個pod有獨(dú)立的存儲。

StatefulSet與Deployment區(qū)別:

  • 前者有身份,后者沒有。
  • 身份三要素:域名、主機(jī)名、存儲(PVC)

3.2 部署實(shí)踐

  1. 需要穩(wěn)定的網(wǎng)絡(luò)ID(域名):

    • 使用Headless Service(相比普通Service只是將spec.clusterIP定義為None)來維護(hù)Pod網(wǎng)絡(luò)身份。
    • 并且添加serviceName:“nginx”字段指定StatefulSet控制器要使用這個Headless Service。
    • DNS解析名稱:< statefulsetName-index >.< service-name > .< namespace-name >.svc.cluster.local
  2. 需要穩(wěn)定的存儲:

  • StatefulSet的存儲卷使用VolumeClaimTemplate創(chuàng)建,稱為卷申請模板,當(dāng)StatefulSet使用VolumeClaimTemplate創(chuàng)建一個PersistentVolume時,同樣也會為每個Pod分配并創(chuàng)建一個編號的PVC。
  • 第一步,先創(chuàng)建正常的svc,名為web。

1.創(chuàng)建一個deployment和svc。

[root@k8s-master bck]# kubectl  create deployment web --image=nginx
[root@k8s-master bck]# kubectl  expose deployment web --port=80 --target-port=80

2.導(dǎo)出svc的yaml文件,可以看出這里的ClusterIP,這種情況下容器內(nèi)的通信都是以這個ClusterIP來進(jìn)行。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

  • 第二步,再創(chuàng)建statefulset,引用第二個狀態(tài)為None的svc。

3.創(chuàng)建statefulset。yaml中是先創(chuàng)建了第二個svc,狀態(tài)為None,再創(chuàng)建statefulset指定儲存類和這個None狀態(tài)的svc。

[root@k8s-master bck]# cat statefulset.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None    ##添加此行,使其變成一種識別標(biāo)簽,供后面的pod使用。
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx 
  serviceName: "nginx"          ##指定哪個svc的名稱。
  replicas: 3 
  minReadySeconds: 10 
  template:
    metadata:
      labels:
        app: nginx 
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:           ##statefulset獨(dú)有配置,deployment不支持此配置。是給每個pod分配各自的pv、pvc。
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "managed-nfs-storage"      ##指定哪個存儲類。使用kubectl get sc查看。
      resources:
        requests:
          storage: 1Gi

5.導(dǎo)入yaml,查看會依次創(chuàng)建三個Pod,因?yàn)閥aml里指定的就是3個副本。

[root@k8s-master bck]# kubectl  apply -f statefulset.yaml

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
6.對比兩個svc。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

7.創(chuàng)建測試容器bs。

[root@k8s-master bck]# kubectl  run bs --image=busybox:1.28.4 -- sleep 240h
[root@k8s-master bck]# kubectl  exec -it bs -- sh

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器
8.查看nfs服務(wù)器共享目錄,進(jìn)入對應(yīng)目錄,創(chuàng)建一個index.html文件,再次就能訪問了。
K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器

3.3 集群部署流程

  1. 集群一般都是三個節(jié)點(diǎn),也就是需要提前寫三個yaml文件。
  2. 需要寫一些腳本。
  3. 通過配置文件中的節(jié)點(diǎn)名稱、IP、存儲目錄區(qū)分3個pod的角色,。

部署一個etcd集群思路:

  1. 需要有3個副本,每個pod里只能指定一個鏡像,所以需要保證啟動的3個副本容器,每一個都能按照自己的角色 (配置文件) 啟動。
  2. 根據(jù)當(dāng)前主機(jī)名可以判定用戶當(dāng)前啟動的是第幾個容器,就用哪個配置文件后動。比如etcd-0.conf、etcd-1.conf、etcd-2.conf。

K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器文章來源地址http://www.zghlxwxcb.cn/news/detail-447642.html

3.3.1 etcd案例

  • etcd集群yaml文件實(shí)例
apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    k8s-app: infra-etcd-cluster
    app: etcd
  name: infra-etcd-cluster
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      k8s-app: infra-etcd-cluster
      app: etcd
  serviceName: infra-etcd-cluster
  template:
    metadata:
      labels:
        k8s-app: infra-etcd-cluster
        app: etcd
      name: infra-etcd-cluster
    spec:
      containers:
      - image: lizhenliang/etcd:v3.3.8
        imagePullPolicy: Always
        command:
        - /bin/sh
        - -ec
        - |
          HOSTNAME=$(hostname)
          echo "etcd api version is ${ETCDAPI_VERSION}"
          # 生成連接etcd集群節(jié)點(diǎn)字符串
          # 例如http://etcd-0.etcd.default:2379,http://etcd-1.etcd.default:2379,http://etcd-2.etcd.default:2379
          eps() {
              EPS=""
              for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
                  EPS="${EPS}${EPS:+,}http://${SET_NAME}-${i}.${SET_NAME}.${CLUSTER_NAMESPACE}:2379"
              done
              echo ${EPS}
          }
          # 獲取etcd節(jié)點(diǎn)成員hash值,例如740e031d5b17222d
          member_hash() {
              etcdctl member list | grep http://${HOSTNAME}.${SET_NAME}.${CLUSTER_NAMESPACE}:2380 | cut -d':' -f1 | cut -d'[' -f1
          }
          # 生成初始化集群節(jié)點(diǎn)連接字符串
          # 例如etcd-0=http://etcd-0.etcd.default:2380,etcd-1=http://etcd-1.etcd.default:2380,etcd-2=http://etcd-1.etcd.default:2380
          initial_peers() {
                PEERS=""
                for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
                PEERS="${PEERS}${PEERS:+,}${SET_NAME}-${i}=http://${SET_NAME}-${i}.${SET_NAME}.${CLUSTER_NAMESPACE}:2380"
                done
                echo ${PEERS}
          }
          # etcd-SET_ID
          SET_ID=${HOSTNAME##*-}
          # 向已有集群添加成員 (假設(shè)所有pod都初始化完成)
          if [ "${SET_ID}" -ge ${INITIAL_CLUSTER_SIZE} ]; then
              export ETCDCTL_ENDPOINTS=$(eps)
              # 判斷成員是否添加
              MEMBER_HASH=$(member_hash)
              if [ -n "${MEMBER_HASH}" ]; then
                  # 成員hash存在,但由于某種原因失敗
                  # 如果datadir目錄沒創(chuàng)建,可以刪除該成員
                  # 檢索新的hash值
                  if [ "${ETCDAPI_VERSION}" -eq 3 ]; then
                      ETCDCTL_API=3 etcdctl --user=root:${ROOT_PASSWORD} member remove ${MEMBER_HASH}
                  else
                      etcdctl --username=root:${ROOT_PASSWORD} member remove ${MEMBER_HASH}
                  fi
              fi
              echo "添加成員"
              rm -rf /var/run/etcd/*
              # 確保etcd目錄存在
              mkdir -p /var/run/etcd/
              # 休眠60s,等待端點(diǎn)準(zhǔn)備好
              echo "sleep 60s wait endpoint become ready,sleeping..."
              sleep 60
              if [ "${ETCDAPI_VERSION}" -eq 3 ]; then
                  ETCDCTL_API=3 etcdctl --user=root:${ROOT_PASSWORD} member add ${HOSTNAME} --peer-urls=http://${HOSTNAME}.${SET_NAME}.${CLUSTER_NAMESPACE}:2380 | grep "^ETCD_" > /var/run/etcd/new_member_envs
              else
                  etcdctl --username=root:${ROOT_PASSWORD} member add ${HOSTNAME} http://${HOSTNAME}.${SET_NAME}.${CLUSTER_NAMESPACE}:2380 | grep "^ETCD_" > /var/run/etcd/new_member_envs
              fi
              if [ $? -ne 0 ]; then
                  echo "member add ${HOSTNAME} error."
                  rm -f /var/run/etcd/new_member_envs
                  exit 1
              fi
              cat /var/run/etcd/new_member_envs
              source /var/run/etcd/new_member_envs
              # 啟動etcd
              exec etcd --name ${HOSTNAME} \
                  --initial-advertise-peer-urls http://${HOSTNAME}.${SET_NAME}.${CLUSTER_NAMESPACE}:2380 \
                  --listen-peer-urls http://0.0.0.0:2380 \
                  --listen-client-urls http://0.0.0.0:2379 \
                  --advertise-client-urls http://${HOSTNAME}.${SET_NAME}.${CLUSTER_NAMESPACE}:2379 \
                  --data-dir /var/run/etcd/default.etcd \
                  --initial-cluster ${ETCD_INITIAL_CLUSTER} \
                  --initial-cluster-state ${ETCD_INITIAL_CLUSTER_STATE}
          fi
          # 檢查前面etcd節(jié)點(diǎn)是否啟動,啟動后再啟動本節(jié)點(diǎn)
          for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
              while true; do
                  echo "Waiting for ${SET_NAME}-${i}.${SET_NAME}.${CLUSTER_NAMESPACE} to come up"
                  ping -W 1 -c 1 ${SET_NAME}-${i}.${SET_NAME}.${CLUSTER_NAMESPACE} > /dev/null && break
                  sleep 1s
              done
          done
          echo "join member ${HOSTNAME}"
          # 啟動etcd節(jié)點(diǎn)
          exec etcd --name ${HOSTNAME} \
              --initial-advertise-peer-urls http://${HOSTNAME}.${SET_NAME}.${CLUSTER_NAMESPACE}:2380 \
              --listen-peer-urls http://0.0.0.0:2380 \
              --listen-client-urls http://0.0.0.0:2379 \
              --advertise-client-urls http://${HOSTNAME}.${SET_NAME}.${CLUSTER_NAMESPACE}:2379 \
              --initial-cluster-token etcd-cluster-1 \
              --data-dir /var/run/etcd/default.etcd \
              --initial-cluster $(initial_peers) \
              --initial-cluster-state new
        env:
        - name: INITIAL_CLUSTER_SIZE  # 初始集群節(jié)點(diǎn)數(shù)量
          value: "3"
        - name: CLUSTER_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: ETCDAPI_VERSION
          value: "3"
        - name: ROOT_PASSWORD
          value: '@123#'
        - name: SET_NAME
          value: "infra-etcd-cluster"
        - name: GOMAXPROCS
          value: "4"

        # 關(guān)閉pod,自動清理該節(jié)點(diǎn)信息
        lifecycle:
          preStop:
            exec:
              command:
              - /bin/sh
              - -ec
              - |
                HOSTNAME=$(hostname)
                member_hash() {
                    etcdctl member list | grep http://${HOSTNAME}.${SET_NAME}.${CLUSTER_NAMESPACE}:2380 | cut -d':' -f1 | cut -d'[' -f1
                }
                eps() {
                    EPS=""
                    for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
                        EPS="${EPS}${EPS:+,}http://${SET_NAME}-${i}.${SET_NAME}.${CLUSTER_NAMESPACE}:2379"
                    done
                    echo ${EPS}
                }
                export ETCDCTL_ENDPOINTS=$(eps)
                SET_ID=${HOSTNAME##*-}
                # 從集群中移出etcd節(jié)點(diǎn)成員
                if [ "${SET_ID}" -ge ${INITIAL_CLUSTER_SIZE} ]; then
                    echo "Removing ${HOSTNAME} from etcd cluster"
                    if [ "${ETCDAPI_VERSION}" -eq 3 ]; then
                        ETCDCTL_API=3 etcdctl --user=root:${ROOT_PASSWORD} member remove $(member_hash)
                    else
                        etcdctl --username=root:${ROOT_PASSWORD} member remove $(member_hash)
                    fi
                    if [ $? -eq 0 ]; then
                        # 刪除數(shù)據(jù)目錄
                        rm -rf /var/run/etcd/*
                    fi
                fi
        name: infra-etcd-cluster
        ports:
        - containerPort: 2380
          name: peer
          protocol: TCP
        - containerPort: 2379
          name: client
          protocol: TCP
        resources:
          limits:
            cpu: "1"
            memory: 1Gi
          requests:
            cpu: "0.3"
            memory: 300Mi
        volumeMounts:
        - mountPath: /var/run/etcd
          name: datadir
  updateStrategy:
    type: OnDelete
  volumeClaimTemplates:
  - metadata:
      name: datadir
    spec:
      storageClassName: "managed-nfs-storage" 
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 2Gi
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: infra-etcd-cluster
    app: infra-etcd
  name: infra-etcd-cluster
  namespace: default
spec:
  clusterIP: None
  ports:
  - name: infra-etcd-cluster-2379
    port: 2379
    protocol: TCP
    targetPort: 2379
  - name: infra-etcd-cluster-2380
    port: 2380
    protocol: TCP
    targetPort: 2380
  selector:
    k8s-app: infra-etcd-cluster
    app: etcd
  type: ClusterIP

3.3.2 zookeeper示例

  • zookeeper參考地址
apiVersion: v1
kind: Service
metadata:
  name: zk-hs
  labels:
    app: zk
spec:
  ports:
  - port: 2888
    name: server
  - port: 3888
    name: leader-election
  clusterIP: None
  selector:
    app: zk
---
apiVersion: v1
kind: Service
metadata:
  name: zk-cs
  labels:
    app: zk
spec:
  ports:
  - port: 2181
    name: client
  selector:
    app: zk
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  selector:
    matchLabels:
      app: zk
  maxUnavailable: 1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: zk
spec:
  selector:
    matchLabels:
      app: zk
  serviceName: zk-hs
  replicas: 3
  updateStrategy:
    type: RollingUpdate
  podManagementPolicy: OrderedReady
  template:
    metadata:
      labels:
        app: zk
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - zk
              topologyKey: "kubernetes.io/hostname"
      containers:
      - name: kubernetes-zookeeper
        imagePullPolicy: Always
        image: "registry.k8s.io/kubernetes-zookeeper:1.0-3.4.10"
        resources:
          requests:
            memory: "1Gi"
            cpu: "0.5"
        ports:
        - containerPort: 2181
          name: client
        - containerPort: 2888
          name: server
        - containerPort: 3888
          name: leader-election
        command:
        - sh
        - -c
        - "start-zookeeper \
          --servers=3 \
          --data_dir=/var/lib/zookeeper/data \
          --data_log_dir=/var/lib/zookeeper/data/log \
          --conf_dir=/opt/zookeeper/conf \
          --client_port=2181 \
          --election_port=3888 \
          --server_port=2888 \
          --tick_time=2000 \
          --init_limit=10 \
          --sync_limit=5 \
          --heap=512M \
          --max_client_cnxns=60 \
          --snap_retain_count=3 \
          --purge_interval=12 \
          --max_session_timeout=40000 \
          --min_session_timeout=4000 \
          --log_level=INFO"
        readinessProbe:
          exec:
            command:
            - sh
            - -c
            - "zookeeper-ready 2181"
          initialDelaySeconds: 10
          timeoutSeconds: 5
        livenessProbe:
          exec:
            command:
            - sh
            - -c
            - "zookeeper-ready 2181"
          initialDelaySeconds: 10
          timeoutSeconds: 5
        volumeMounts:
        - name: datadir
          mountPath: /var/lib/zookeeper
      securityContext:
        runAsUser: 1000
        fsGroup: 1000
  volumeClaimTemplates:
  - metadata:
      name: datadir
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi

到了這里,關(guān)于K8s基礎(chǔ)10——數(shù)據(jù)卷、PV和PVC、StorageClass動態(tài)補(bǔ)給、StatefulSet控制器的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • k8s~動態(tài)生成pvc和pv

    k8s~動態(tài)生成pvc和pv

    有時,我們不想手動建立pv和pvc,這時,我們可以通過strongClass存儲類來幫我們實(shí)現(xiàn),動態(tài)建立pvc,并動態(tài)為它分配pv存儲空間,我們以nfs為例,說一下動態(tài)分配在nfs存儲截至上建立pv的方式。 StorageClass和PVC及PV 集群權(quán)限與綁定rbac.yaml 建立動態(tài)pvc的provisioner.yaml 建立strongClass的

    2024年02月03日
    瀏覽(22)
  • K8s---存儲卷(動態(tài)pv和pvc)

    K8s---存儲卷(動態(tài)pv和pvc)

    當(dāng)我要發(fā)布pvc可以生成pv,還可以共享服務(wù)器上直接生成掛載目錄。pvc直接綁定pv。 1、卷插件:k8s本生支持的動態(tài)pv創(chuàng)建不包括nfs,需要聲明和安裝一個外部插件 Provisioner: 存儲分配器。動態(tài)創(chuàng)建pv,然后根據(jù)pvc的請求自動綁定和使用。 2、StorageClass:來定義pv的屬性,存儲類型

    2024年01月21日
    瀏覽(17)
  • k8s 1.28版本:使用StorageClass動態(tài)創(chuàng)建PV,SelfLink 問題修復(fù)

    ?? k8s中提供了一套自動創(chuàng)建 PV 的機(jī)制,就是基于 StorageClass 進(jìn)行的 ,通過 StorageClass 可以實(shí)現(xiàn)僅僅配置 PVC,然后交由 StorageClass 根據(jù) PVC 的需求動態(tài)創(chuàng)建 PV。 問題: ??使用 k8s 1.28版本,通過 kubectl get pvc ,發(fā)現(xiàn) PVC一直處于 Pending 狀態(tài)。通過 kubectl describe pvc [pvc名稱] 描述

    2024年02月08日
    瀏覽(17)
  • k8s pv pvc的介紹|動態(tài)存儲|靜態(tài)存儲

    k8s pv pvc的介紹|動態(tài)存儲|靜態(tài)存儲

    當(dāng)Pod被分配給節(jié)點(diǎn)時,首先創(chuàng)建emptyDir卷,并且只要該P(yáng)od在該節(jié)點(diǎn)上運(yùn)行,該卷就會存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以讀取和寫入emptyDir卷中的相同文件,盡管該卷可以掛載到每個容器中的相同或不同路徑上。當(dāng)出于任何原因從節(jié)點(diǎn)中刪除 Pod 時,em

    2024年02月06日
    瀏覽(20)
  • k8s默認(rèn)StorageClass,解決pvc一直處于“Pending”

    k8s默認(rèn)StorageClass,解決pvc一直處于“Pending”

    報(bào)錯詳情 排查思路 查看 pvc 詳細(xì)屬性 persistentvolume-controller waiting for a volume to be created, either by external provisioner \\\"nfs-provisioner-01\\\" or manually created by system administrator 從persistentvolume-controller反饋出來的信息是 沒有權(quán)限來創(chuàng)建出pvc。 查看 nfs-provisioner pod日志 遠(yuǎn)程N(yùn)FS服務(wù)器上的動態(tài)子

    2023年04月27日
    瀏覽(20)
  • 【云原生-Kubernetes篇】K8s的存儲卷/數(shù)據(jù)卷+PV與PVC

    【云原生-Kubernetes篇】K8s的存儲卷/數(shù)據(jù)卷+PV與PVC

    容器部署過程中一般有以下三種數(shù)據(jù): ? 啟動時需要的 初始數(shù)據(jù) :例如配置文件 (init container) ? 啟動過程中產(chǎn)生的 臨時數(shù)據(jù) :該臨時數(shù)據(jù)需要多個容器間共享 ? 啟動過程中產(chǎn)生的 持久化數(shù)據(jù) :例如MySQL的data目錄 (業(yè)務(wù)數(shù)據(jù)–很重要) 而容器中的文件在磁盤上是 臨時

    2024年02月05日
    瀏覽(20)
  • k8s pv與pvc

    k8s pv與pvc

    1.前言 PV 是 Kubernetes 集群中的一種資源對象,它代表著一塊物理存儲設(shè)備,例如磁盤、網(wǎng)絡(luò)存儲或云存儲等。PV 可以被多個 Pod 共享,并且可以獨(dú)立于 Pod 存在。PV 可以配置不同的訪問模式 (Access Modes),例如 ReadWriteOnce 、 ReadOnlyMany 或 ReadWriteMany ,以確定 PV 可以被多少個 Pod 同

    2024年01月21日
    瀏覽(20)
  • [Kubernetes]5. k8s集群StatefulSet詳解,以及數(shù)據(jù)持久化(SC PV PVC)

    [Kubernetes]5. k8s集群StatefulSet詳解,以及數(shù)據(jù)持久化(SC PV PVC)

    前面通過 deployment 結(jié)合 service 來部署 無狀態(tài)的應(yīng)用 ,下面來講解通過 satefulSet 結(jié)合 service 來部署 有狀態(tài)的應(yīng)用 無狀態(tài): 無狀態(tài) (stateless) 、牲畜 (cattle) 、無名 (nameless) 、可丟棄 (disposable) 有狀態(tài): 有狀態(tài) (stateful) 、寵物 (pet) 、具有名 (haviing name) 、不可丟棄 (non-disposable) St

    2024年02月01日
    瀏覽(49)
  • PV & PVC in K8s

    在Kubernetes中,PV(Persistent Volume)和PVC(Persistent Volume Claim)是用于管理持久化存儲的重要資源對象。PV表示存儲的實(shí)際資源,而PVC表示對PV的聲明性要求。當(dāng)應(yīng)用程序需要使用持久化存儲時,它可以通過創(chuàng)建PVC來請求和使用PV。以下是使用PV和PVC時的一些注意事項(xiàng): 定義存儲類

    2024年02月09日
    瀏覽(24)
  • k8s ------存儲卷(PV、PVC)

    k8s ------存儲卷(PV、PVC)

    目錄 一:為什么需要存儲卷? 二:emptyDir存儲卷? ?三:hostPath存儲卷? 四:nfs共享存儲卷? ?五:PVC 和 PV 1、PVC 和 PV介紹 2、PV和PVC之間的相互作用遵循的生命周期 3、PV 的4 種狀態(tài) 4、一個PV從創(chuàng)建到銷毀的具體流程 六:靜態(tài)創(chuàng)建pv和pvc資源由pod運(yùn)用過程 ?1、配置nfs存儲 ?

    2024年02月13日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包