Kubernetes中的儲存(六)

MXC肖某某發表於2020-09-16

一、ConfigMap

1,介紹

  ConfigMap 功能在 Kuberbetes 1.2 版本中引入,許多應用程式會從配置檔案、命令列引數或環境變數中讀取配置資訊。ConfigMap API 給我們提供了向容器中注入配置資訊的機制,ConfigMap 可以被用來儲存單個屬性,也可以用來儲存整個配置檔案或者 json 二進位制大物件。

2,建立方式

  a)使用目錄建立

vim file1.properties
name=zhansan
age=24
gender=man

vim file2.properties
color=yellow
num=20
#/usr/local/demo/configmap為儲存file1.properties和file2.properties的路徑
kubectl create configmap cm-by-dir --from-file=/usr/local/demo/configmap
kubectl get cm
#檢視cm的描述
kubectl describe cm cm-by-dir
檢視cm的yaml檔案內容
kubectl get cm cm-by-dir -o yaml

  由此可得出:目錄下的所有檔案都會被用在 ConfigMap 裡面建立一個鍵值對,鍵就是檔案的名字,值就是檔案的內容。

  b)使用檔案建立

#繼續使用a)中的檔案
kubectl create configmap cm-by-file --from-file=/usr/local/demo/configmap/file1.properties
kubectl get cm

  c)使用字面值建立

#使用 --from-literal 引數傳遞配置資訊
kubectl create configmap cm-by-literal --from-literal=name=zhangsan --from-literal=age=18
kubectl get cm

  d)使用yaml建立(special.yaml)

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm
kubectl apply -f special.yaml

3,Pod中使用ConfigMap

  special-config.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

  log-level-config.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: log-level-config
  namespace: default
data:
  log_level: INFO

  編寫 Pod 資源清單(cm-env-pod.yaml):

apiVersion: v1
kind: Pod
metadata:
  name: cm-env-pod
  namespace: default
spec:
  restartPolicy: Never
  containers:
  - name: nginx-container
    image: hub.xcc.com/my-xcc/my-nginx:v1
    command: ['sh', '-c', 'env']  #輸出容器的環境變數
    envFrom:  #指定configMap,並使用configMap的key和value作為環境變數的key和value
    - configMapRef:
        name: log-level-config #引用的configMap名稱
    env:
    - name: SPECIAL_HOW_STR    #環境變數key
      valueFrom:
        configMapKeyRef:
          name: special-config #引用的configMap名稱
          key: special.how     #環境變數值為special-config中的special.how的值
    - name: SPECIAL_TYPE_STR
      valueFrom:
        configMapKeyRef:
          name: special-config
          key: special.type

執行命令

kubectl apply -f log-level-config.yaml
kubectl apply -f special-config.yaml
kubectl apply -f cm-env-pod.yaml
kubectl get pod
#檢視環境變數輸出
kubectl log cm-env-pod

4,資料卷掛載

apiVersion: v1
kind: Pod
metadata:
  name: volume-config-pod
  namespace: default
spec:
  restartPolicy: Never
  containers:
  - name: nginx-container
    image: hub.xcc.com/my-xcc/my-nginx:v1
    command: ['sh', '-c', 'sleep 3600']
    volumeMounts:
    - name: config-volume      #資料卷名稱
      mountPath: /etc/config   #資料卷容器內的路徑
  volumes: 
  - name: config-volume        #資料卷關聯的configMap名稱
    configMap:
      name: special-config

執行命令

[root@k8s-master01 ~]# kubectl apply -f volume-config-pod.yaml 
pod/volume-config-pod created

[root@master01 ~]# kubectl get pod
NAME                READY   STATUS      RESTARTS   AGE
volume-config-pod   1/1     Running     0          3s

[root@master01 ~]# kubectl exec volume-config-pod -it /bin/bash
root@volume-config-pod:/# cd /etc/config
root@volume-config-pod:/etc/config# ls
special.how  special.type
root@volume-config-pod:/etc/config# cat special.how
very
root@volume-config-pod:/etc/config# cat special.type
charm

  在掛載資料卷後,容器內部將 configMap 的 key 作為檔名,value 作為檔案內容,建立成一個個的檔案。

二、Secret

  Secret 是一種包含少量敏感資訊例如密碼、token 或 key 的物件。這樣的資訊可能會被放在 Pod spec 中或者映象中;將其放在一個 secret 物件中可以更好地控制它的用途,並降低意外暴露的風險。

  Pod可以通過三種方式使用Secret:作為 volume 中的檔案被掛載到 pod 中的一個或者多個容器裡;作為環境變數注入;或者當 kubelet 為 pod 拉取映象時使用。

1,secret的分類

  • kubernetes.io/service-account-token:這是 Service Account 使用 API 憑證自動建立和附加 secret。Kubernetes 自動建立包含訪問 API 憑據的 secret,並自動修改您的 pod 以使用此型別的 secret。

    如果需要,可以禁用或覆蓋自動建立和使用API憑據。但是,如果您需要的只是安全地訪問 apiserver,我們推薦這樣的工作流程。

  • kubernetes.io/dockerconfigjson:用來儲存私有 docker registry 的認證資訊。使用 imagePullSecrets策略指定 Secret。

  • Opaque:base64 編碼格式的 Secret,用來儲存密碼、金鑰等;但資料也可以通過 base64 –decode 解碼得到原始資料,所有加密性很弱。

2,Opaque Secret

  假設有些 pod 需要訪問資料庫。這些 pod 需要使用的使用者名稱和密碼在您本地機器的 ./username.txt 和 ./password.txt 檔案裡。

  a)使用檔案建立

echo -n 'admin' > ./username.txt
echo -n '123456' > ./password.txt

kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
kubectl get secret
kubectl get secret db-user-pass -o yaml

  b)使用yaml清單建立

echo -n "admin" | base64     #  YWRtaW4=
echo -n "123456" | base64    #  MTIzNDU2

建立mysecret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MTIzNDU2

執行命令

kubectl apply -f mysecret.yaml
kubectl get secret
#檢視 Secret 依然是 base64 編碼格式儲存的內容
kubectl get secret mysecret -o yaml

  c)解碼

[root@master01 secret]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
...

[root@k8s-master01 secret]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  password: MTIzNDU2
  username: YWRtaW4=
......

[root@master01 secret]# echo -n "MTIzNDU2" | base64 -d
123456
[root@master01 secret]# echo -n "YWRtaW4=" | base64 -d
admin

  d)編輯Secret

kubectl edit secrets mysecret

  e)使用Secret

作為volume使用:

  Secret可以作為資料卷被掛載,或作為環境變數暴露出來以供Pod中的容器使用。

  • 建立一個 secret 或者使用已有的 secret。多個 pod 可以引用同一個 secret。
  • 修改 pod 的定義在 spec.volumes[] 下增加一個 volume。可以給這個 volume 隨意命名,它的 spec.volumes[].secret.secretName 必須等於 secret 物件的名字。
  • 將 spec.containers[].volumeMounts[] 加到需要用到該 secret 的容器中。指定 spec.containers[].volumeMounts[].readOnly = true 和 spec.containers[].volumeMounts[].mountPath 為您想要該 secret 出現的尚未使用的目錄。
  • 修改您的映象並且/或者命令列讓程式從該目錄下尋找檔案。Secret 的 data 對映中的每一個鍵都成為了 mountPath 下的一個檔名。

示例:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  volumes:
  - name: foo
    secret:
      secretName: mysecret
  containers:
  - name: mypod
    image: hub.xcc.com/my-xcc/my-nginx:v1
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true

向特此那個路徑對映secret::

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username   #secret儲存的路徑為/etc/foo/my-group/my-username
  containers:
  - name: mypod
    image: hub.xcc.com/my-xcc/my-nginx:v1
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true

作為環境變數使用

  將 secret 作為 pod 中的環境變數使用:

  • 建立一個 secret 或者使用一個已存在的 secret。多個 pod 可以引用同一個 secret。
  • 修改 Pod 定義,為每個要使用 secret 的容器新增對應 secret key 的環境變數。消費 secret key 的環境變數應填充 secret 的名稱,並鍵入 env[x].valueFrom.secretKeyRef
  • 修改映象並/或者命令列,以便程式在指定的環境變數中查詢值。

示例:

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: mycontainer
    image: hub.xcc.com/my-xcc/my-nginx:v1
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
  restartPolicy: Never

執行命令:

kubectl apply -f secret-env.yaml
kubectl get pod
kubectl exec secret-env-pod -it /bin/sh
    echo $SECRET_USERNAME
    echo $SECRET_PASSWORD

3,ImagePullSecret

  假如我們建立 Pod 時,Pod 裡面所使用的映象是私有的,需要進行身份認證才能夠拉取,那麼我們可以建立一個具有該私有倉庫認證資訊的 Secret,然後使用 ImagePullSecrets 指定。

  下面我們使用 harbor 私有倉庫進行舉例。在 harbor 中建立一個私有專案 tom,並向該專案中 push 一個映象 hub.xcc.com/my/nginx:v1。然後將叢集中的所有節點都退出 harbor 的登入,並刪除所有節點中的 hub.xcc.com/my/nginx:v1 映象。

#映象拉取錯誤
rpc error: code = Unknown desc = Error response from daemon: pull access denied for hub.xcc.com/my/nginx, repository does not exist or may require 'docker login': denied: requested access to the resource is denied

解決步驟:

  建立認證資訊Secret

kubectl create secret docker-registry my-registry-secret --docker-server=hub.xcc.com --docker-username=admin --docker-password=Harbor12345 --docker-email=admin@example.com
my-registry-secret:被建立的secret名稱

  yaml檔案

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: nginx-container
    image: hub.xcc.com/my/nginx:v1
  imagePullSecrets:
  - name: my-registry-secret

三、Volume

1,介紹

  容器中的檔案在磁碟上是臨時存放的,這給容器中執行的特殊應用程式帶來一些問題。 首先,當容器崩潰時,kubelet 將重新啟動容器,容器中的檔案將會丟失——因為容器會以乾淨的狀態重建(這和 docker 容器的重啟不一樣,docker 容器重啟不會丟失資料)。其次,當在一個 Pod 中同時執行多個容器時,常常需要在這些容器之間共享檔案。 Kubernetes 抽象出 Volume 物件來解決這兩個問題。

2,分類

3,emptyDir

  當 Pod 指定到某個節點上時,首先建立的是一個 emptyDir 卷,並且只要 Pod 在該節點上執行,卷就一直存在。 就像它的名稱表示的那樣,卷最初是空的。 儘管 Pod 中的容器掛載 emptyDir 卷的路徑可能相同也可能不同,但是這些容器都可以讀寫 emptyDir 卷中相同的檔案。 當 Pod 因為某些原因被從節點上刪除時,emptyDir 卷中的資料也會永久刪除。

說明: 容器崩潰並不會導致 Pod 被從節點上移除,因此容器崩潰時 emptyDir 卷中的資料是安全的。

emptyDir 的一些用途:

  • 快取空間,例如基於磁碟的歸併排序。
  • 為耗時較長的計算任務提供檢查點,以便任務能方便地從崩潰前狀態恢復執行。
  • 在 Web 伺服器容器服務資料時,儲存內容管理器容器獲取的檔案。

預設情況下, emptyDir 卷儲存在支援該節點所使用的介質上;這里的介質可以是磁碟或 SSD 或網路儲存,這取決於您的環境。 但是,您可以將 emptyDir.medium 欄位設定為 "Memory",以告訴 Kubernetes 為您安裝 tmpfs(基於 RAM 的檔案系統)。 雖然 tmpfs 速度非常快,但是要注意它與磁碟不同。 tmpfs 在節點重啟時會被清除,並且您所寫入的所有檔案都會計入容器的記憶體消耗,受容器記憶體限制約束。

建立volume-emptydir-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: volume-emptydir-pod
spec:
  containers:
  - name: nginx-container    #initc容器1 
    image: hub.xcc.com/my-xcc/my-nginx:v1
    volumeMounts:    #nginx-container 容器將 volume 掛載到了容器中的 /nginx-cache 目錄下
    - mountPath: /nginx-cache 
      name: cache-volume #使用volume
  - name: busybox-container
    image: hub.xcc.com/my-xcc/my-busybox:v1
    command: ['sh', '-c', 'sleep 3600s']
    volumeMounts:     #busybox-container 容器將 volume 掛載到了容器中的 /busybox-cache 目錄下
    - mountPath: /busybox-cache
      name: cache-volume
  volumes:   #定義volume
  - name: cache-volume
    emptyDir: {}    

執行命令

kubectl apply -f volume-emptydir-pod.yaml
kubectl get pod
#進入initc容器nginx-container
kubectl exec volume-emptydir-pod -c nginx-container -it -- bin/bash
ls /nginx-cache
#進入initc容器busybox-container
kubectl exec volume-emptydir-pod -c busybox-container -it -- bin/bash
ls /busybox-cache

#在nginx-container中
echo "this's nginx-container add content" > /nginx-cache/a.txt
#在busybox-container中
cat /busybox-cache/a.txt 

4,hostPath

  hostPath卷能將主機節點檔案系統上的檔案或目錄掛載到您的 Pod 中。 雖然這不是大多數 Pod 需要的,但是它為一些應用程式提供了強大的逃生艙。

例如,hostPath的一些用法有:

  • 執行一個需要訪問 Docker 引擎內部機制的容器;請使用 hostPath 掛載 /var/lib/docker 路徑。
  • 在容器中執行 cAdvisor 時,以 hostPath 方式掛載 /sys
  • 允許 Pod 指定給定的 hostPath 在執行 Pod 之前是否應該存在,是否應該建立以及應該以什麼方式存在。

  除了必需的 path 屬性之外,使用者可以選擇性地為 hostPath 卷指定 type

支援的 type 值如下:

取值行為
  空字串(預設)用於向後相容,這意味著在安裝 hostPath 卷之前不會執行任何檢查。
DirectoryOrCreate 如果在給定路徑上什麼都不存在,那麼將根據需要建立空目錄,許可權設定為 0755,具有與 Kubelet 相同的組和所有權。
Directory 在給定路徑上必須存在的目錄。
FileOrCreate 如果在給定路徑上什麼都不存在,那麼將在那裡根據需要建立空檔案,許可權設定為 0644,具有與 Kubelet 相同的組和所有權。
File 在給定路徑上必須存在的檔案。
Socket 在給定路徑上必須存在的 UNIX 套接字。
CharDevice 在給定路徑上必須存在的字元裝置。
BlockDevice 在給定路徑上必須存在的塊裝置。

當使用這種型別的卷時要小心,因為:

  • 具有相同配置(例如從 podTemplate 建立)的多個 Pod 會由於節點上檔案的不同而在不同節點上有不同的行為。
  • 當 Kubernetes 按照計劃新增資源感知的排程時,這類排程機制將無法考慮由 hostPath 使用的資源。
  • 基礎主機上建立的檔案或目錄只能由 root 使用者寫入。您需要在 特權容器 中以 root 身份執行程式,或者修改主機上的檔案許可權以便容器能夠寫入 hostPath 卷。

Pod 示例

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:
      # directory location on host
      path: /data
      # this field is optional
      type: Directory
注意: 應當注意,FileOrCreate 型別不會負責建立檔案的父目錄。 如果掛載掛載檔案的父目錄不存在,pod 啟動會失敗。 為了確保這種 type 能夠工作,可以嘗試把檔案和它對應的目錄分開掛載,如下所示:

FileOrCreate pod 示例

apiVersion: v1
kind: Pod
metadata:
  name: test-webserver
spec:
  containers:
  - name: test-webserver
    image: k8s.gcr.io/test-webserver:latest
    volumeMounts:
    - mountPath: /var/local/aaa
      name: mydir
    - mountPath: /var/local/aaa/1.txt
      name: myfile
  volumes:
  - name: mydir
    hostPath:
      # 確保檔案所在目錄成功建立。
      path: /var/local/aaa
      type: DirectoryOrCreate
  - name: myfile
    hostPath:
      path: /var/local/aaa/1.txt
      type: FileOrCreate

四、PV和PVC

1,概念

  持久卷(PersistentVolume,PV)是叢集中的一塊儲存,可以由管理員事先供應,或者 使用儲存類(Storage Class)來動態供應。 持久卷是叢集資源,就像節點也是叢集資源一樣。PV 持久卷和普通的 Volume 一樣,也是使用 卷外掛來實現的,只是它們擁有獨立於任何使用 PV 的 Pod 的生命週期。 此 API 物件中記述了儲存的實現細節,無論其背後是 NFS、iSCSI 還是特定於雲平臺的儲存系統。

  持久卷申領(PersistentVolumeClaim,PVC)表達的是使用者對儲存的請求。概念上與 Pod 類似。 Pod 會耗用節點資源,而 PVC 申領會耗用 PV 資源。Pod 可以請求特定數量的資源(CPU 和記憶體);同樣 PVC 申領也可以請求特定的大小和訪問模式 (例如,可以要求 PV 卷能夠以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一來掛載,參見訪問模式)。

2,生命週期

  參考官網

 

3,PV型別

  • GCEPersistentDiskAWSElasticBlockStoreAzureFileAzureDiskCSIFC (Fibre Channel)

  • FlexVolumeFlockerNFSiSCSIRBD (Ceph Block Device)CephFSCinder (OpenStack block storage)

  • GlusterfsVsphereVolumeQuobyte VolumesPortworx VolumesScaleIO VolumesStorageOS

  • HostPath (Single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)

4,PV示例

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 500Mb        #指定PV容量大小
  volumeMode: Filesystem    #檔案系統型別,有兩種型別:Filesystem(在建立 Pod 時會將掛載的卷嵌入到 Pod 的檔案目錄中) 和 Block(Pod 和卷之間沒有任何檔案系統層)。這是一個可選的引數,預設為 Filesystem。
  accessModes:
    - ReadWriteOnce      #ReadWriteOnce – 只能在一個節點中掛載,能夠讀寫;ReadOnlyMany – 能夠在多個節點掛載,只能讀;ReadWriteMany – 能夠在多個節點掛載,能夠讀寫。
  persistentVolumeReclaimPolicy: Recycle #回收策略。Retain(保留。手動回收);Recycle(回收,基本擦除rm -rf /thevolume/*;Delete(刪除。關聯的儲存資產,如:AWS EBS、GCE PD等也將被刪除)。
  storageClassName: slow     #為PV生命一個類名。PVC 的 storageClassName 必須和這個一致。但是 PV 和 PVC 都可以不設定這個值而使用預設的類名。Recycle:回收。不推薦使用此策略。相反,推薦的方法是使用動態配置。
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2

5,PVC示例

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce       #必須和PV的accessModes一樣或者是PV的子集
  volumeMode: Filesystem  #必須和PV的volumeMode一樣
  resources:         #宣告(如Pod)可以請求的資源大小。PVC會自動去尋找合適大小的PV匹配
    requests:
      storage: 800Mb
  storageClassName: slow  #與PV一致
  selector:               #通過指定標籤進一步過濾PV。
    matchLabels:          #matchLabels PV中必須帶有這個標籤和值;
      release: "stable"
    matchExpressions:     #matchExpressions 通過指定運算子:In,NotIn,Exists和DoesNotExist等
  
- {key: environment, operator: In, values: [dev]}

6,NFS示例

Kubernetes中的儲存(六)

  a)安裝NFS

# 在harbor上192.168.232.90 
#安裝 nfs 服務及相關工具
yum install -y nfs-common nfs-utils rpcbind
# 建立4個共享資料夾
mkdir /nfs1 /nfs2 /nfs3 /nfs4
chmod 777 /nfs1 /nfs2 /nfs3 /nfs4
chown nfsnobody /nfs1 /nfs2 /nfs3 /nfs4
#新增exports
vim /etc/exports
/nfs1 *(rw,no_root_squash,no_all_squash,sync)
/nfs2 *(rw,no_root_squash,no_all_squash,sync)
/nfs3 *(rw,no_root_squash,no_all_squash,sync)
/nfs4 *(rw,no_root_squash,no_all_squash,sync)
#重啟繫結和nfs
systemctl start rpcbind && systemctl start nfs

#在叢集中所有節點安裝
yum install -y nfs-utils rpcbind

在叢集任一節點測試掛載 nfs 檔案系統:

# 測試連線 nfs,結果顯示了 nfs 伺服器的可掛載目錄
[root@master01 testnfs]# showmount -e 192.168.232.90
Export list for 192.168.232.90:
/nfs4 *
/nfs3 *
/nfs2 *
/nfs1 *
[root@master01 ~]# pwd
/root
[root@master01 ~]# mkdir nfs2
# 將本地 /root/nfs2/ 目錄掛載到 nfs2 伺服器目錄
[root@master01 nfs2]# mount -t nfs 192.168.232.90:/nfs2 /root/nfs2/
[root@master01 ~]# cd nfs2/ [root@master01 nfs2]# touch test.txt
[root@
master01 nfs2]# ls
test.txt # 此時
192.168.232.90 機器上的 /nfs2 目錄可以看到 test.txt 這個檔案 # 退出連線 [root@k8s-master01 testnfs]# umount -l /root/nfs2/

  錯誤排查:如果執行命令 showmount -e 192.168.232.90 提示: clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host),可以關掉 nfs 伺服器的防火牆(systemctl status firewalld),或者開啟某些埠(自行網上搜尋下)。

  b)建立PV

nfs1-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs1-pv
spec:
  capacity:
    storage: 100Mb
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: "nfs"
  nfs:
    path: /nfs1
    server: 192.168.232.90

nfs2-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs2-pv
spec:
  capacity:
    storage: 400Mb
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: "nfs"
  nfs:
    path: /nfs2
    server: 192.168.232.90

nfs3-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs3-pv
spec:
  capacity:
    storage: 700Mb
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: "nfs"
  nfs:
    path: /nfs3
    server: 192.168.232.90

nfs4-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs4-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: "nfs"
  nfs:
    path: /nfs4
    server: 192.168.232.90

執行命令

kubectl apply -f nfs1-pv.yaml
kubectl apply -f nfs2-pv.yaml
kubectl apply -f nfs3-pv.yaml
kubectl apply -f nfs4-pv.yaml
#可看到 VOLUMEMODE 是 Filesystem   其中PV 都是 Available 的,即未繫結狀態
kubectl get pv -o wide

  c)建立PVC和Pod

nfs-pvc-pod.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx-app
spec:
  ports:
  - port: 80
    name: web
  clusterIP: "None"
  selector:
    app: nginx-app
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  replicas: 1
  serviceName: "nginx-app"
  selector:
    matchLabels:
      app: nginx-app
  template:
    metadata:
      labels:
        app: nginx-app
    spec:
      containers:
      - name: nginx-container
        image: hub.xcc.com/my-xcc/my-nginx:v1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: pvc-volume
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: pvc-volume
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "nfs"
      resources:
        requests:
          storage: 600Mb

執行命令

kubectl apply -f nfs-pvc-pod.yaml
kubectl get pvc
#檢視繫結情況
kubectl get pv
kubectl get pod

#我們將 statefulSet 擴容到 2 個 Pod,然後檢視 pvc 的繫結情況
kubectl scale statefulSet web --replicas 2
kubectl get statefulSet
kubectl get pod
kubectl get pvc
kubectl get pv

 

相關文章