k8s階段03 持久卷, PV和PVC, CSI儲存方案示例csi-driver-nfs, OpenEBS, ConfigMap, Secret, DownwardAPI和Projected

战斗小人發表於2024-11-24

2持久卷

PV和PVC

在Pod級別定義儲存卷有兩個弊端
  卷物件的生命週期無法獨立於Pod而存在
  使用者必須要足夠熟悉可用的儲存及其詳情才能在Pod上配置和使用卷
  
PV和PVC可用於降低這種耦合關係
  PV(Persistent Volume)是叢集級別的資源,負責將儲存空間引入到叢集中,通常由管理員定義
  PVC(Persistent Volume Claim)是名稱空間級別的資源,由使用者定義,用於在空閒的PV中申請使用符合過濾
條件的PV之一,與選定的PV是“一對一”的關係
  使用者在Pod上透過pvc外掛請求繫結使用定義好的PVC資源
  
StorageClass資源支援PV的動態預配(Provision)

PV, PVC 
    PV置備(provision)方式:
        靜態置備:也可以使用StorageClass,分組,亦可作為篩選條件之一,可選項;
        動態置備:依賴於StorageClass(模板),必選項#後端儲存需要支援動態置備功能

PV資源
  PV是標準的資源型別,除了負責關聯至後端儲存系統外,它通常還需要定義支援的儲存特性
    Volume Mode:當前PV卷提供的儲存空間模型,分為塊裝置和檔案系統兩種
    StorageClassName:當前PV隸屬的儲存類;
    #檔案系統沒有限制,塊裝置系統只能單路讀寫訪問
    AccessMode:支援的訪問模型,分為單路讀寫、多路讀寫和多路只讀三種
    Size:當前PV允許使用的空間上限
  在物件後設資料上,還能夠根據需要定義標籤
  #Retain:保留資料,PV變為release狀態,待人工介入;Recycle:資料清除,PV可再次被其他PVC繫結(危險,被廢棄)
  #Delete:刪除PV,但後端儲存空間的資料沒被刪
  一般需要定義回收策略:Retain、Recycle和Delete
  
PVC資源
  PVC也是標準的資源型別,它允許使用者按需指定期望的儲存特性,並以之為條件,按特定的條件順序進行PV過濾
    VolumeMode → LabelSelector → StorageClassName → AccessMode → Size
  支援動態預配的儲存類,還可以根據PVC的條件按需完成PV建立

使用靜態PV和PVC的配置卷的步驟

基於NFS的靜態PV和PVC示例

#NFS PV 資源定義示例
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-demo
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:    #這裡可以把支援的型別都宣告出來
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain #回收策略
  mountOptions: #掛載選項,非必須項
    - hard
    - nfsvers=4.1
  nfs:
    path: "/data/redis"
    server: nfs.magedu.com
    
#PVC 資源定義示例
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-demo
  namespace: default #可省略
spec:
  accessModes: ["ReadWriteMany"]
  volumeMode: Filesystem
  resources: #定義資源
    requests: #最小不能小於
      storage: 3Gi
    limits: #最大不能超過
      storage: 10Gi
      
#在Pod上使用PVC卷
apiVersion: v1
kind: Pod
metadata:
  name: volumes-pvc-demo
  namespace: default
spec:
  containers:
  - name: redis
    image: redis:alpine
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
      name: redisport
    volumeMounts:
    - mountPath: /data
      name: redis-rbd-vol
volumes:
- name: redis-rbd-vol
  persistentVolumeClaim:
    claimName: pvc-demo    #使用上面定義的pvc名字

實際操作示例

#在nfs伺服器上建立資料夾匯出
[root@ubuntu ~]#mkdir -pv /data/pv001
[root@ubuntu ~]#vim /etc/exports
/data/pv001/ 10.0.0.0/16(rw,async,no_subtree_check,no_root_squash)
#重新匯出
[root@ubuntu ~]#exportfs -arv

#在k8s的控制節點上
[root@master01 volumes]#vim pv-nfs-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-demo
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
    - ReadOnlyMany
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path:  "/data/pv001"
    server: 10.0.0.155
    
[root@master01 volumes]#kubectl apply -f pv-nfs-demo.yaml
#檢視pv (這裡沒定義STORAGECLASS,等下pvc也不能定義分類,否則找不到)
[root@master01 volumes]#kubectl get pv 
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pv-nfs-demo   5Gi        RWX            Retain           Available                          <unset>                          41s

[root@master01 volumes]#vim pvc-demo.yaml #會從Available狀態的PV中進行篩選
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-demo
spec:
  accessModes: ["ReadWriteMany"] #能相容對方就可以
  volumeMode: Filesystem
  resources:
    requests: #儘量接近3G
      storage: 3Gi
    limits:
      storage: 10Gi
[root@master01 volumes]#kubectl apply -f pvc-demo.yaml
#獲取pvc要指名稱空間,default可以不指,狀態為bound繫結,一建立立即繫結
[root@master01 volumes]#kubectl get pvc -n default
NAME       STATUS   VOLUME        CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
pvc-demo   Bound    pv-nfs-demo   5Gi        RWO,ROX,RWX                   <unset>                 11m
#檢視pv也能看出被繫結狀態
[root@master01 volumes]#kubectl get pv

#定義pod使用pvc
[root@master01 volumes]#vim pod-with-pvc-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-dyn-pvc
spec:
  containers:
  - name: redis
    image: redis:7-alpine
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
      name: redisport
    volumeMounts:
    - mountPath: /data
      name: redis-pvc-vol
  volumes:
  - name: redis-pvc-vol
    persistentVolumeClaim:
      claimName: pvc-demo
[root@master01 volumes]#kubectl apply -f pod-with-pvc-demo.yaml

#進入容器驗證
[root@master01 volumes]#kubectl exec -it redis-dyn-pvc -- /bin/sh
/data # redis-cli
127.0.0.1:6379> set mykey "Hello"
OK
127.0.0.1:6379> BGSAVE
Background saving started
#nfs伺服器上檢視
[root@ubuntu ~]#ls /data/pv001/
dump.rdb

#刪除pod只要不刪pvc,那隻要引用pvc,所有資料都在,卷也在

StorageClass

StorageClass資源
  Kubernetes支援的標準資源型別之一
  為管理PV資源之便而按需建立的儲存資源類別(邏輯組)
  是PVC篩選PV時的過濾條件之一
  為動態建立PV提供“模板”
    需要儲存服務提供管理API
    StorageClass資源上配置接入API的各種引數
        定義在parameters欄位中
        還需要使用provisioner欄位指明儲存服務型別
  一般由叢集管理員定義,隸屬叢集級別
  
#StorageClass資源示例
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
provisioner: nfs.csi.k8s.io    #後端儲存服務由哪個供應商提供的
parameters:
  server: nfs-server.default.svc.cluster.local #nfs伺服器地址
  share: / #nfs伺服器暴露的路徑
reclaimPolicy: Delete #動態置備的pv拿到的回收策略
volumeBindingMode: Immediate#卷繫結模式,Immediate立即繫結PV和PVC,若用本地儲存用延遲繫結(等pod建立出來)
mountOptions: #nfs卷使用引數,有些服務不需要指定mountOptions
  - hard
  - nfsvers=4.1

PVC和動態PV示例

有些儲存型別預設並不支援動態PV機制,如下圖。可以加CSI讓它支援
多數CSI儲存都支援動態PV,且支援卷擴充套件和卷快照等功能

#PVC向StorageClass申請繫結PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-dynamic
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
storageClassName: nfs-csi

節點本地持久卷

local持久卷
  local卷外掛用於將本地儲存裝置(如磁碟、分割槽或目錄)配置為卷
    基於網路儲存的PV通常效能損耗較大
    直接使用節點本地的SSD磁碟可獲取較好的IO效能,更適用於儲存類的服務,例如MongoDB、Ceph等
  hostPath卷在Pod被重建後可能被排程至其它節點而無法再次使用此前的資料,而基於local卷,排程器能自行完成排程繫結
    hostPath卷允許Pod訪問節點上的任意路徑,也存在一定程度的安全風險
  基於local的PV,需要管理員透過nodeAffinity宣告其定義在的節點
    使用者可透過PVC關聯至local型別的PV
    然後,在Pod上配置使用該PVC即可
    排程器將基於nodeAffinity將執行Pod排程

local卷只能關聯靜態置備的PV,目前尚不支援動態置備

#Local PV資源示例
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv-demo
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:    #local卷在某個主機上的路徑
    path: /disks/vol1
  nodeAffinity:    #節點選擇器
    required:
      nodeSelectorTerms:    #節點過濾器
      - matchExpressions:    #匹配條件
        - key: kubernetes.io/hostname #主機上要有該標籤
          operator: In #主機名得是k8s-node01.magedu.com
          values:
          - k8s-node01.magedu.com
PVC遲延繫結
  ◼ 配置PVC繫結local PV時,通常要建立一個StorageClass
    ◆provisioner欄位的值“no-provisioner”表示不使用動態置備PV,因為local外掛不支援
    ◆volumeBindingMode欄位的值“WaitForFirstConsumer”表示等待消費者(Pod)申請使用PVC時(即第一次被排程時)再進行PV繫結,即“延遲繫結”
    ◆延遲繫結機制,提供了基於消費者的需求來判定將PVC繫結至哪個PV的可能性
  ◼ 延遲繫結機制下,PVC建立後將處於“Pending”狀態,直至被Pod消費


#實際操作示例:
#作為分組使用,不作為動態置備作用
[root@master01 local-pv-demo]#vim storageclass-local.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local
provisioner: kubernetes.io/no-provisioner #固定格式,沒有動態置備就不需要沒有供應商
volumeBindingMode: WaitForFirstConsumer #延遲繫結(等待首次被消費)

[root@master01 local-pv-demo]#kubectl apply -f storageclass-local.yaml
#檢視,storageclass可以簡寫為sc
[root@master01 local-pv-demo]#kubectl get sc
NAME    PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local   kubernetes.io/no-provisioner   Delete          WaitForFirstConsumer   false                  61

#定義pv,使用local型別卷
[root@master01 local-pv-demo]#vim local-pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv-demo
spec:
  capacity:
    storage: 5Gi #儲存空間
  volumeMode: Filesystem #卷模式
  accessModes:
  - ReadWriteOnce #訪問模式
  persistentVolumeReclaimPolicy: Delete #回收策略
  storageClassName: local    #儲存型別,透過local來定義
  local: #卷外掛型別
    path: /disks/vol1 #指定本地磁碟路徑
  nodeAffinity: #節點選擇器
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node01 #在節點1上,事先創好路徑
 
[root@master01 local-pv-demo]#kubectl apply -f local-pv-demo.yaml
#檢視
[root@master01 local-pv-demo]#kubectl get pv

#定義pvc
[root@master01 local-pv-demo]#vim pvc-localpv-demo.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-localpv-demo
spec:
  accessModes:#訪問模式
  - ReadWriteOnce
  resources:
    requests: #需要空間大小
      storage: 5Gi
  storageClassName: local #透過哪個儲存類(兩種要麼統一儲存類,要麼都不屬於任何儲存類)
  
[root@master01 local-pv-demo]#kubectl apply -f pvc-localpv-demo.yaml 
#檢視 此時處於pending狀態
[root@master01 local-pv-demo]#kubectl get pvc

#定義pod 注意:pod排程器會結合pv控制器來判定該被排程到哪個節點上(hostpath卷不會,它不會使用pv control,無法影響pod schedule)
[root@master01 local-pv-demo]#vim pod-with-localpv.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-localpv
spec:
  containers:
  - name: redis
    image: redis:7-alpine
    ports:
    - containerPort: 6379
      name: redis
    volumeMounts:
    - mountPath: "/data"
      name: data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: pvc-localpv-demo #使用上面定義的pvc
        
[root@master01 local-pv-demo]#kubectl apply -f pod-with-localpv.yaml
#檢視,建立在node1節點上
[root@master01 local-pv-demo]#kubectl get -f pod-with-localpv.yaml -o wide
#此時檢視pvc,處於繫結狀態
[root@master01 local-pv-demo]#kubectl get pvc

3 Kubernetes儲存架構簡介

儲存卷的具體的管理操作由相關的控制器向卷外掛發起呼叫請求來完成
  ◼ AD控制器:負責儲存裝置的Attach/Detach操作
    ◆Attach:將裝置附加到目標節點
    ◆Detach:將裝置從目標節點上拆除
  ◼ 儲存卷管理器:負責完成卷的Mount/Umount操作,以及裝置的格式化操作等
  ◼ PV控制器:負責PV/PVC的繫結、生命週期管理,以及儲存卷的Provision/Delete操作
Scheduler:特定儲存外掛的排程決策會受到目標節點上的儲存卷的影響

Out-of-Tree儲存

CSI簡介
  ◼ 容器儲存介面規範,與平臺無關
  ◼ 驅動程式元件
    ◆CSI Controller:負責與儲存服務的API通訊從而完成後端儲存的管理操作
    ◆Node Plugin:也稱為CSI Node,負責在節點級別完成儲存卷的管理

CSI儲存元件和部署架構

CSI Controller:由StatefulSet控制器物件編排執行,副本量需要設定為1,以保證只會該儲存服務執行單個CSI Controller例項;
Node Plugin:由DaemonSet控制器物件編排執行,以確保每個節點上精確執行一個相關的Pod副本

csi-driver-nfs

動態置備儲存

Kuberentes社群
     主社群:Kubernetes專案,及各關鍵子專案
     SIG: Special Intresting Group,    #csi-driver-nfs在特別興趣組專案下(github上)
         kubernetes-sigs/
             csi-driver-nfs 
             csi-driver-lvm
             ...
             
專案:csi-driver-nfs 
    負責為現有NFS Server提供PV的動態置備能力,它依賴於一個現有的NFS Server; 
        
    測試環境中,部署NFS Server的方法: 
        (1)在Kubernetes上部署一個NFS Server;#只能在測試環境中使用
            kubectl create namespace nfs 
            kubectl create -f https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/deploy/example/nfs-provisioner/nfs-server.yaml \
                    -n nfs     #指定建立在nfs服務空間
            
            訪問nfs服務的入口:nfs-server.nfs.svc.cluster.local 
               
        (2)自行在Kubernetes叢集外部準備一個NFS Server; #購買網上的服務
                匯出目錄時要使用的匯出選項:(rw,fsid=0,async,no_subtree_check,no_auth_nlm,insecure,no_root_squash) 

   部署csi-driver-nfs: 
        remote install:
            curl -skSL https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/v4.6.0/deploy/install-driver.sh | bash -s v4.6.0 --

        local install: 
            git clone https://github.com/kubernetes-csi/csi-driver-nfs.git
            cd csi-driver-nfs
            ./deploy/install-driver.sh v4.6.0 local
            
    預設部署在kube-system名稱空間,各Image的倉庫地址是registry.k8s.io;#可能需要上外網 

#操作例項
#部署csi-driver-nfs,採用local install方式
[root@master01 ~]#git clone https://github.com/kubernetes-csi/csi-driver-nfs.git
[root@master01 ~]#cd csi-driver-nfs/deploy
#直接部署4.6.0版本  (每個節點下載映象並執行)
[root@master01 deploy]#kubectl apply -f v4.6.0/
#檢視(預設在kube-system空間下)
[root@master01 deploy]#kubectl get pods -n kube-system -o wide

#nfs伺服器上
#建立路徑作為動態置備
[root@ubuntu ~]#mkdir /nfspv
[root@ubuntu ~]#vim /etc/exports
/nfspv 10.0.0.0/16(rw,fsid=0,async,no_subtree_check,no_auth_nlm,insecure,no_root_squash)
#執行重新匯出
[root@ubuntu ~]#exportfs -arv

#k8s控制節點主機上
#準備StroageClass,以完成csi-driver-nfs和nfs-server之間的對接:
#要使用nfs上的儲存驅動,需要定義storageclass來完成
[root@master01 ~]#vim storageclass-csi-nfs.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
  server: 10.0.0.155 #nfs伺服器地址
  share: /nfspv    #nfs對應地址(會在該路徑下自動建立子目錄作為動態置備儲存路徑)
reclaimPolicy: Delete #生產中用delete回收策略有風險
volumeBindingMode: Immediate

[root@master01 ~]#kubectl apply -f storageclass-csi-nfs.yaml
#檢視儲存類
[root@master01 ~]#kubectl get sc

#建立PVC進行測試(只需要建立pvc即可,pv會自動建立)
#路徑在:  csi-driver-nfs/deploy/example/pvc-nfs-csi-dynamic.yaml
[root@master01 ~]#vim csi-driver-nfs/deploy/example/pvc-nfs-csi-dynamic.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-dynamic
  namespace: default
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: nfs-csi
#建立pvc
[root@master01 ~]#kubectl create -f csi-driver-nfs/deploy/example/pvc-nfs-csi-dynamic.yaml
#檢視pvc (顯示狀態已經Bound繫結了)
[root@master01 ~]#kubectl get pvc
NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
pvc-nfs-dynamic   Bound    pvc-f6797db7-bf8e-47fa-8bc1-6c26c6b35876   10Gi       RWX            nfs-csi        <unset>                 65s
#檢視pv(pv已經被自動建立出來)
[root@master01 ~]#kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-f6797db7-bf8e-47fa-8bc1-6c26c6b35876   10Gi       RWX            Delete           Bound    default/pvc-nfs-dynamic   nfs-csi        <unset>                          104s

#在nfs服務上檢視,在路徑上能看到對應子目錄
[root@ubuntu ~]#cd /nfspv/
[root@ubuntu nfspv]#ls
pvc-f6797db7-bf8e-47fa-8bc1-6c26c6b35876

#定義一個pod使用該pvc做測試
[root@master01 volumes]#vim pod-with-dyn-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-pvc
spec:
  containers:
  - name: redis
    image: redis:7-alpine
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
      name: redisport
    volumeMounts:
    - mountPath: /data
      name: redis-pvc-vol
  volumes:
  - name: redis-pvc-vol
    persistentVolumeClaim:
      claimName: pvc-nfs-dynamic #使用上面的pvc
[root@master01 volumes]#kubectl apply -f pod-with-dyn-pvc.yaml
[root@master01 volumes]#kubectl exec -it redis-pvc -- /bin/sh
/data # redis-cli
127.0.0.1:6379> set a "hi hello"
OK
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> exit
/data # ls
dump.rdb

#nfs伺服器上檢視到資料
[root@ubuntu nfspv]#ls pvc-f6797db7-bf8e-47fa-8bc1-6c26c6b35876/
dump.rdb

示例: 部署mysql, 使用csi-driver-nfs的動態置備儲存

注意: mysql如果用網路卷作為儲存,效能會有很大影響, 最好使用local卷

#pvc和pod建立在同一個目錄中,檔案可以部署多個資源
[root@master01 pods]#vim mydb.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-mydb
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: nfs-csi
---    #上一個資源內容,用---隔開
apiVersion: v1
kind: Pod
metadata:
  name: mydb
spec:
  containers:
  - name: mydb
    image: mysql:8.0
    env:
    - name: MYSQL_RANDOM_ROOT_PASSWORD #超級使用者賬號
      value: M@geEdu
    - name: MYSQL_DATABASE
      value: wpdb
    - name: MYSQL_USER
      value: wpuser
    - name: MYSQL_PASSWORD
      value: wpP@ss
    volumeMounts: #呼叫下面的卷掛載
    - name: mydb-stor
      mountPath: /var/lib/mysql/ #掛載點(mysql預設寫在該路徑下)
  volumes:
  - name: mydb-stor
    persistentVolumeClaim:
      claimName: pvc-nfs-mydb #呼叫上面pvc

#建立名稱空間
[root@master01 pods]#kubectl create namespace dev
[root@master01 pods]#kubectl apply -f mydb.yaml -n dev
[root@master01 pods]#kubectl get pvc -n dev
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES
pvc-nfs-mydb   Bound    pvc-478ac6b1-c1c4-4fa1-a6b5-d77000011f45   10Gi       RWX
[root@master01 pods]#kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-478ac6b1-c1c4-4fa1-a6b5-d77000011f45   10Gi       RWX            Delete           Bound    dev/pvc-nfs-mydb          nfs-csi        <unset>                          10m

#nfs伺服器上
[root@ubuntu nfspv]#ls pvc-478ac6b1-c1c4-4fa1-a6b5-d77000011f45/
 auto.cnf        ca.pem               ib_buffer_pool   mysql                public_key.pem    undo_002
 binlog.000001   client-cert.pem      ibdata1          mysql.ibd            server-cert.pem   wpdb
 binlog.000002   client-key.pem       ibtmp1           mysql.sock           server-key.pem
 binlog.index   '#ib_16384_0.dblwr'  '#innodb_redo'    performance_schema   sys
 ca-key.pem     '#ib_16384_1.dblwr'  '#innodb_temp'    private_key.pem      undo_001

4 CAS和OpenEBS

CAS(Container Attached Storage)簡介

容器附加儲存(Container Attached Storage)
  ◼ Kubernetes的卷通常是基於外部檔案系統或塊儲存實現,這種儲存方案稱為共享儲存(Shared Storage)
  ◼ CAS則是將儲存系統自身部署為Kubernetes叢集上的一種較新的儲存解決方案
    ◆儲存系統自身(包括儲存控制器)在Kubernetes上以容器化微服務的方式執行
    ◆使得工作負載更易於移植,且更容易根據應用程式的需求改動使用的儲存
    ◆通常基於工作負載或者按叢集部署,因此消除了共享儲存的跨工作負載甚至是跨叢集的爆炸半徑
  ◼ 儲存在 CAS 中的資料可以直接從叢集內的容器訪問,從而能顯著減少讀/寫時間
  ◼ OpenEBS是CAS儲存機制的著名實現之一,由CNCF孵化
基於CAS的儲存解決方案,通常包含兩類元件
  ◼ 控制平面
    ◆負責配置卷以及其他同儲存相關任務
    ◆由儲存控制器、儲存策略以及如何配置資料平面的指令組成
  ◼ 資料平面
    ◆接收並執行來自控制平面的有關如何儲存和訪問容器資訊的指令
    ◆主要元件是實現池化儲存的儲存引擎,這類引擎本質上負責輸入/輸出卷路徑
    ◆OpenEBS支援儲存引擎包括Mayastor、cStor、Jiva和OpenEBS LocalPV等
    
OPenEBS: 
    CAS風格的儲存解決方案之一;由控制平面和資料平面,其中的資料平面的主要組成部分是儲存引擎
    支援的儲存引擎,MayaStor, cStor, Jiva, LocalPV

共享儲存與CAS對比

CAS的重要特徵
◼ 儲控制器分解為可以彼此獨立執行的組成部分
◼ 每個工作負載都有自己的一個或多個控制器

OpenEBS簡介

OpenEBS簡介
◼ OpenEBS能夠將Kubernetes工作節點上可用的任何儲存轉換為本地卷或分散式複製卷
◼ 最初由MayaData構建,後捐贈給了CNCF,目前是CNCF的沙箱級專案
#分散式複製卷,一份資料存兩份,放到2個不同的節點上

OPenEBS: 
    卷型別:本地卷和分散式複製卷
        本地卷:磁碟、分割槽、檔案系統目錄(local Volume)、ZFS、LVM
        複製卷:
            iSCSI: cStor和Jiva
            NVMEoF: MayaStor

            Jiva或cStor要建立在本地卷功能的基礎之上;
                Jiva --> 依賴於本地捲來解決每個節點上的儲存需求
                
#OpenEBS架構
OpenEBS存在著眾多元件,他們大體可以分以兩大類
◼ 資料引擎
◼ 控制平面

資料引擎和NDM

如何選擇資料引擎
  ◼ 應用程式處於生產狀態且不需要儲存級複製,則首選 LocalPV
  ◼ 應用程式處於生產狀態並且需要儲存級複製,則首選 cStor
  ◼ 應用程式較小、需要儲存級複製但不需要快照或克隆,則首選 Jiva
  ◼ 應用程式需要低延遲和接近磁碟的吞吐量,需要儲存級複製,並且工作節點具有效能較高的CPU、RAM和NVME,那麼 Mayastor 是首選

NDM(Node Disk Manager)
  ◼ 部署OpenEBS的過程中,NDM由專用DaemonSet編排執行於每個節點上
    ◆負責發現裸裝置並過濾掉不支援使用的裝置,例如已經帶有檔案系統的磁碟
    ◆需要特權模式,訪問/dev、/proc和/sys目錄來監視連線的裝置,並使用各種探測器獲取這些裝置的詳細資訊
  ◼ 根據過濾器(filters)檢測附加到節點上的裸磁碟裝置,並將它們識別為“塊裝置CRD”
    ◆NDM支援使用include filters或exclude filters
    ◆filter的配置儲存於ConfigMap中
  ◼ 基於節點上的裸磁碟裝置提供PV的儲存引擎,會依賴於NDM實現其功能,這包括Local PV device 和 cStor

配置使用OpenEBS

部署使用OpenEBS的基本流程
◼ 在各節點上部署iSCSI client #儲存引擎cStor,Jiva需要,其他不需要部署
◼ 在Kubernetes叢集上部署OpenEBS
◼ 選擇要使用的資料引擎
◼ 為選擇的資料引擎準備StorageClass

注意: 如果業務資料有冗餘, 使用本地卷local-hostpath。如業務資料無冗餘, 用複製卷

實際操作示例 (本地卷,無法跨節點, 自動置備pv儲存)

#安裝openebs環境
#部署pod
[root@master01 ~]#kubectl apply -f https://openebs.github.io/charts/openebs-operator.yaml
#會建立獨立名稱空間 openebs
[root@master01 ~]#kubectl get ns
#檢視名稱空間中的資源,會建立很多pod
[root@master01 ~]#kubectl get all -n openebs
#每個節點上都會跑一個ndm(用於發現獨立的裸磁碟裝置,配置為獨立的block device)
[root@master01 ~]#kubectl get pods -n openebs -o wide
#檢視CRD 自定義資源定義(沒發現一個塊磁碟,就會建立一個blockdevices,目前系統沒有,不用管)
[root@master01 ~]#kubectl get crd
blockdevices.openebs.io                          2024-11-21T14:53:41Z

#自動建立兩個儲存類(因為用的都是本地卷,所以採用延遲繫結機制) 可改儲存路徑,刪儲存類重建或修改下,並建目錄
[root@master01 ~]#kubectl get sc
NAME               PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
openebs-device     openebs.io/local               Delete          WaitForFirstConsumer   false                  12h
openebs-hostpath   openebs.io/local               Delete          WaitForFirstConsumer   false                  12h
#自此openebs環境準備完成,如果對lvm等有需求,openebs官網再部署其他pod

#準備pvc檔案
[root@master01 local-pv-hostpath]#vim openebs-local-hostpath-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: openebs-local-hostpath-pvc
spec:
  storageClassName: openebs-hostpath #部署完openebs自動生成的storageClass,會自動置備儲存
  accessModes:
    - ReadWriteOnce #此處必須是單路讀寫
  resources:
    requests: #請求使用空間5個g
      storage: 5G
[root@master01 local-pv-hostpath]#kubectl apply -f openebs-local-hostpath-pvc.yaml

root@master01 local-pv-hostpath]#kubectl get pvc
NAME                         STATUS    STORAGECLASS       VOLUMEATTRIBUTESCLASS   AGE
openebs-local-hostpath-pvc   Pending   openebs-hostpath   <unset>                 17s

#準備pod (執行pod會自動置備pv儲存)
[root@master01 local-pv-hostpath]#vim redis-with-openebs-local-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-with-openebs-local-hostpath
spec:
  containers:
  - name: redis
    image: redis:7-alpine
    ports:
    - containerPort: 6379
      name: redis
    volumeMounts:
    - mountPath: /data
      name: local-storage
  volumes:
  - name: local-storage
    persistentVolumeClaim:
      claimName: openebs-local-hostpath-pvc
[root@master01 local-pv-hostpath]#kubectl apply -f redis-with-openebs-local-hostpath.yaml
#檢視建立的pods,會是pending狀態(首次消費pv,pv有初始化過程,會下載一初始化pod在openebs空間,準備好會自動刪除)
[root@master01 local-pv-hostpath]#kubectl get pods
redis-with-openebs-local-hostpath   0/1     Pending   0              27s

#等到running狀態後,檢視資料存到哪了
[root@master01 local-pv-hostpath]#kubectl get sc
[root@master01 local-pv-hostpath]#kubectl get sc openebs-hostpath -o yaml
... Default value is /var/openebs/local ...
#/var/openebs/local    pod所在節點下,在該目錄下建立子目錄作為pv儲存後端

[root@master01 local-pv-hostpath]#kubectl get pvc
NAME                         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       VOLUMEATTRIBUTESCLASS   AGE
openebs-local-hostpath-pvc   Bound    pvc-a4125f1e-eaf3-4020-b7e8-1ff770ca7430   5G         RWO            openebs-hostpath   <unset>                 157m
#節點3上檢視
[root@node03 ~]#ls /var/openebs/local
pvc-a4125f1e-eaf3-4020-b7e8-1ff770ca7430

實際操作示例 (複製卷,跨節點冗餘)

#複製卷後臺用的還是本地卷,在本地卷基礎上加了複製的引擎(需要單獨的pod來執行)
#這裡採用jiva  (cstor和jiva的區別在於cstor可使用快照)

#基於上面openebs環境部署完成後
#安裝jiva-operator
[root@master01 ~]#kubectl apply -f https://openebs.github.io/charts/jiva-operator.yaml
#每個節點上安裝jiva驅動節點
[root@master01 ~]#kubectl get pods -n openebs

#定義jiva卷策略
[root@master01 jiva-csi]#vim openebs-jivavolumepolicy-demo.yaml
apiVersion: openebs.io/v1alpha1
kind: JivaVolumePolicy    #安裝jiva建立的新的jivavolumepolicy
metadata:
  name: jivavolumepolicy-demo
  namespace: openebs #一般放在這個名稱空間下
spec:
  replicaSC: openebs-hostpath #複製時使用的儲存類,這裡用基於目錄儲存(上面用的本地卷方式相同)
  target:
    # This sets the number of replicas for high-availability
    # replication factor <= no. of (CSI) nodes
    replicationFactor: 2 #複製因子,資料打算冗餘幾份

[root@master01 jiva-csi]#kubectl apply -f openebs-jivavolumepolicy-demo.yaml
#檢視建立的jivavolumepolicy資源型別
[root@master01 jiva-csi]#kubectl get jivavolumepolicy -n openebs 
NAME                    AGE
jivavolumepolicy-demo   32s

#建立儲存類
[root@master01 jiva-csi]#vim openebs-jiva-csi-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: openebs-jiva-csi
provisioner: jiva.csi.openebs.io
allowVolumeExpansion: true #是否支援卷擴縮容(使用路徑不支援,用LVM支援)
parameters:
  cas-type: "jiva"
  policy: "jivavolumepolicy-demo" #在哪個policy管控jiva儲存卷
  
[root@master01 jiva-csi]#kubectl apply -f openebs-jiva-csi-storageclass.yaml
[root@master01 jiva-csi]#kubectl get sc

#建立pvc
[root@master01 jiva-csi]#vim openebs-jiva-csi-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: openebs-jiva-csi-pvc
spec:
  storageClassName: openebs-jiva-csi #使用上面的儲存類
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
[root@master01 jiva-csi]#kubectl apply -f openebs-jiva-csi-pvc.yaml
#檢視pvc,直接繫結了(繫結的是jiva卷)
[root@master01 jiva-csi]#kubectl get pvc
NAME                         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       VOLUMEATTRIBUTESCLASS   AGE
openebs-jiva-csi-pvc         Bound    pvc-1057bf10-245f-4718-a0ca-f91cd899d952   5Gi        RWO            openebs-jiva-csi   <unset>                 31s
#檢視jiva卷(jiva卷要複製2份資料到兩個節點上) Unknown是因為初始化pod還沒有執行完成(openebs空間下)
[root@master01 jiva-csi]#kubectl get jivavolume -n openebs 
NAME                                       REPLICACOUNT   PHASE   STATUS
pvc-1057bf10-245f-4718-a0ca-f91cd899d952   2              Ready   RW

#openebs名稱空間下建立了3個pod,一個是jiva卷微控制器,另外兩個是兩份資料副本
[root@master01 jiva-csi]#kubectl get pods -n openebs
pvc-1057bf10-245f-4718-a0ca-f91cd899d952-jiva-ctrl-6c75c9d5z4vl   2/2     Running
pvc-1057bf10-245f-4718-a0ca-f91cd899d952-jiva-rep-0               1/1     Running
pvc-1057bf10-245f-4718-a0ca-f91cd899d952-jiva-rep-1               1/1     Running   
#在openebs自動建立了2個pvc
[root@master01 jiva-csi]#kubectl get pvc -n openebs
openebs-pvc-1057bf10-245f-4718-a0ca-f91cd899d952-jiva-rep-0
openebs-pvc-1057bf10-245f-4718-a0ca-f91cd899d952-jiva-rep-1

#要使用jiva的pvc存資料,在所有節點(包括master)上安裝iSCSI client
[root@node01 ~]#apt-get install open-iscsi
[root@node01 ~]#systemctl enable --now iscsid

#到此為止,jiva的環境設定完成

#使用redis例項
[root@master01 jiva-csi]#vim redis-with-openebs-jiva-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-with-openebs-jiva-pvc
spec:
  containers:
  - name: redis
    image: redis:7-alpine
    ports:
    - containerPort: 6379
      name: redis
    volumeMounts:
    - mountPath: /data
      name: local-storage
  volumes:
  - name: local-storage
    persistentVolumeClaim:
      claimName: openebs-jiva-csi-pvc #使用上面基於jiva的pvc
[root@master01 jiva-csi]#kubectl apply -f redis-with-openebs-jiva-pvc.yaml

#測試
[root@master01 jiva-csi]#kubectl exec -it redis-with-openebs-jiva-pvc -- /bin/sh
/data # redis-cli
127.0.0.1:6379> SET test "testing"
OK
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> exit
/data # ls
dump.rdb    lost+found#說明是二進位制裝置儲存空間

#檢視存在哪個捲上
[root@master01 jiva-csi]#kubectl get pvc -n openebs
[root@master01 jiva-csi]#kubectl get pvc openebs-pvc-1057bf10-245f-4718-a0ca-f91cd899d952-jiva-rep-0 -o yaml -n openebs
...
volume.kubernetes.io/selected-node: node01
#node1節點檢視(大部分rdb檔案被封裝了,因這是複製引擎)
[root@node01 ~]#ls /var/openebs/local/pvc-023b9bd4-5f23-4e91-a16e-545bc1aeaeef/
log.info          volume-head-001.img       volume-snap-bc8e1cfc-55f9-41e2-b093-92ec82447d8f.img
replica.log       volume-head-001.img.meta  volume-snap-bc8e1cfc-55f9-41e2-b093-92ec82447d8f.img.meta
revision.counter  volume.meta

注意: 無論是前面的hostpath還是jiva帶複製能力的卷, 存取介面一般都是單路讀寫, 無法實現多路讀寫

要使用多路讀寫, 只能建nfs server。或者做一個jiva卷, 在jiva卷的上面再部署nfs服務(支援不太成熟,在官網上有寫)

1 ConfigMap和Secret基礎

特殊卷:configMap/secret 介紹

應用配置:
    臨時卷:empytDir
    本地卷:hostPath, local 
    網路卷:nfs, ...
    特殊卷:configMap,secret, downwardAPI
    卷擴充套件:CSI

    特殊卷:configMap,secret, downwardAPI

    configMap/secret: 
        幾重概念:
            (1) 資源型別 
            (2) 卷外掛 
            
        資源型別:configMap、secret
            儲存於api server中的資源物件, 最終儲存於etcd中

        卷外掛:
            在Pod上,基於該型別卷外掛,以卷的形式引用configmap/secret資源物件

        容器配置引數:
            環境變數:
                1、啟動容器時,自定義要執行的命令及選項、引數;
                    Dockerfile, CMD, ENTRYPOINT
                2、透過環境進行配置;
                    Dockerfile, entrypoint.sh指令碼來代理預處理環境變數
                3、將配置焙進Image,重製Image;
                4、將配置檔案放置在捲上,由容器透過卷載入;
                    卷:ConfigMap/Secret 
                    
        configMap:儲存非敏感的配置,資料以明文儲存
        secret: 儲存敏感配置,資料以base64編碼格式儲存
            資料格式:
                Key: Value 

                Value:分為兩類
                    單行值:單行字串
                    多行值:檔案格式的配置資訊

            每個物件中,可以儲存多個kv資料;
            
ConfigMap和Secret是Kubernetes系統上兩種特殊型別的儲存卷
  ◼ ConfigMap用於為容器中的應用提供配置資料以定製程式的行為,而敏感的配置資訊,例如金鑰、證書等則通常由Secret來配置
  ◼ ConfigMap和Secret將相應的配置資訊儲存於資源物件中,而後在Pod物件上支援以儲存卷的形式將其掛載並載入相關的配置,從而降低了配置與映象檔案的耦合關係,提高了映象複用能力
  ◼ Kubernetes藉助於ConfigMap物件實現了將配置檔案從容器映象中解耦,從而增強了工作負載的可移植性,使其配置更易於更改和管理,並避免了將配置資料硬編碼到Pod配置清單中

此二者都屬於名稱空間級別,只能被同一名稱空間中的Pod引用

◼ ConfigMap和Secret資源都是資料承載類的元件,是Kubernetes API的標準資源型別,是一等公民
  ◼ 主要負責提供key-value格式的資料項,其值支援
    ◆單行字串:常用於儲存環境變數值,或者命令列引數等
    ◆多行字串:常用於儲存配置檔案的內容

#定義示例
apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-confs
data:
  PORT: "8080"
  myserver-status.cfg: | #多行的v用|加換行縮排的方式(將來轉為檔案會頂格寫不會有縮排)
    location /nginx-status {
      stub_status on;
      access_log off;
    }

◼ 從Kubernetes v1.19版本開始,ConfigMap和Secret支援使用immutable欄位建立不可變例項

在Pod中引用配置的方式

環境變數
  ◼ 將configmap物件上的某key的值賦值給(valueFrom)指定的環境變數
卷
  ◼ 在Pod上基於configMap卷外掛引用configmap物件
  ◼ 在Container上掛載configMap卷
    ◆每個kv會分別被對映為一個檔案,檔名同key,value將成為檔案內容

2 ConfigMap

建立ConfigMap物件

建立ConfigMap物件的方法有兩種
  ◼ 命令式命令
    ◆ 字面量:kubectl create configmap NAME --from-literal=key1=value1
    ◆ 從檔案載入:kubectl create configmap NAME --from-file=[key=]/PATH/TO/FILE
    ◆ 從目錄載入: kubectl create configmap NAME --from-file=[key=]/PATH/TO/DIR/
  ◼ 配置檔案
    ◆命令式:kubectl create -f 
    ◆宣告式:kubectl apply -f
提示:基於檔案內容生成時,可以使用命令式命令以dry-run模式生成並儲存

    建立方法:
        指令式命令:
            kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none]
            直接值:直接於命令列給出kv
            從檔案載入:從檔案載入生成kv
        物件配置:
            kubectl create -f /path/to/configmap_manifest_file
            
#例:
#建立demoapp-cfg名的configmap;--from-literal指定kv;可以指定名稱空間,這裡預設
~]#kubectl create configmap demoapp-cfg --from-literal=listen="127.0.0.1" --from-literal=port="8080"
#檢視configmap,可以簡稱cm
~]#kubectl get cm

#不建立configmap只生成yaml
~]#kubectl create configmap demoapp-cfg --from-literal=listen="127.0.0.1" --from-literal=port="8080" --dry-run=client -o yaml

#從檔案中載入
~]#kubectl create configmap nginx-cfg --from-file=./myserver.conf --dry-run=client -o yaml
apiVersion: v1
data:
  myserver.conf: |
    server {
        listen 8080;
        server_name www.ik8s.io;

        include /etc/nginx/conf.d/myserver-*.cfg;

        location / {
            root /usr/share/nginx/html;
        }
    }
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: nginx-cfg
#可以指定鍵名,修改將來掛載的檔名
~]#kubectl create configmap nginx-cfg --from-file=my.conf=./myserver.conf --dry-run=client -o yaml
apiVersion: v1
data:
  my.conf: |
    server {
        listen 8080;
        server_name www.ik8s.io;

        include /etc/nginx/conf.d/myserver-*.cfg;

        location / {
            root /usr/share/nginx/html;
        }
    }
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: nginx-cfg 

#載入多個檔案
~]#kubectl create configmap nginx-cfg --from-file=./myserver.conf --from-file=./myserver-status.cfg --dry-run=client -o yaml

#載入當前目錄下的所有檔案(無法改檔名)
~]#kubectl create configmap nginx-cfg --from-file=./ --dry-run=client -o yaml


#使用示例(從環境變數中直接引用)
[root@master01 configmaps_and_secrets]#vim configmaps-env-demo.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: demoapp-config
  namespace: default
data:
  demoapp.port: "8080"
  demoapp.host: 127.0.0.1
---
apiVersion: v1
kind: Pod
metadata:
  name: configmaps-env-demo
  namespace: default
spec:
  containers:
  - image: ikubernetes/demoapp:v1.0
    name: demoapp
    env:
    - name: PORT
      valueFrom:    #引用
        configMapKeyRef: #configmap中的鍵引用
          name: demoapp-config #configmap名字
          key: demoapp.port #鍵名
          optional: false #如在ConfigMap中找不到指定的key,K8s將會報錯
    - name: HOST
      valueFrom:
        configMapKeyRef:
          name: demoapp-config
          key: demoapp.host
          optional: true
#建立
[root@master01 configmaps_and_secrets]#kubectl apply -f configmaps-env-demo.yaml
configmap/demoapp-config created
pod/configmaps-env-demo created
#檢視ConfigMap
[root@master01 configmaps_and_secrets]#kubectl get cm
NAME               DATA   AGE
demoapp-config     2      27s
[root@master01 configmaps_and_secrets]#kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
configmaps-env-demo   1/1     Running   0          58s
#檢視是否監聽8080
[root@master01 configmaps_and_secrets]#kubectl exec configmaps-env-demo -- netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN
#可以透過env列印出全部的環境變數
[root@master01 configmaps_and_secrets]#kubectl exec configmaps-env-demo -- env

#一般不建議修改configmap,但是可以修改,改法有兩種
#第一種,直接修改configmap
]#vim configmaps-env-demo.yaml
  ...
  demoapp.port: "10080"
#只是變了configmap
]#kubectl apply -f configmaps-env-demo.yaml
#檢視configmap的yaml形式,埠已變10080
]#kubectl get cm demoapp-config -o yaml
#檢視環境變數PORT依然是8080
[root@master01 configmaps_and_secrets]#kubectl exec configmaps-env-demo -- env
#pod裡面監聽的埠還是8080,除非重啟整個pod


#使用示例(基於卷引用方式,卷外掛方式)  這種方式修改會重新注入到pod內部(能不能生效看系統是否自動裝載新配置)
#建立configmap
[root@master01 configmaps_and_secrets]#kubectl create configmap nginx-config-files --from-file=./nginx-conf.d/
#呼叫
[root@master01 configmaps_and_secrets]#vim configmaps-volume-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: configmaps-volume-demo
  namespace: default
spec:
  containers:
  - image: nginx:alpine
    name: nginx-server
    volumeMounts:
    - name: ngxconfs
      mountPath: /etc/nginx/conf.d/ #掛載點
      readOnly: true    #只讀
  volumes:
  - name: ngxconfs
    configMap:
      name: nginx-config-files #引用nginx-config-files的configMap
      optional: false #必選
[root@master01 configmaps_and_secrets]#kubectl apply -f configmaps-volume-demo.yaml

#進入pod容器
[root@master01 configmaps_and_secrets]#kubectl exec -it configmaps-volume-demo -- /bin/sh
/etc/nginx/conf.d # ls -l
total 0
lrwxrwxrwx    1 root     root            24 Nov 23 08:27 myserver-gzip.cfg -> ..data/myserver-gzip.cfg
lrwxrwxrwx    1 root     root            26 Nov 23 08:27 myserver-status.cfg -> ..data/myserver-status.cfg
lrwxrwxrwx    1 root     root            20 Nov 23 08:27 myserver.conf -> ..data/myserver.conf
/etc/nginx/conf.d # ls -al
total 12
drwxrwxrwx    3 root     root          4096 Nov 23 08:27 .
drwxr-xr-x    3 root     root          4096 Nov 12 02:02 ..
drwxr-xr-x    2 root     root          4096 Nov 23 08:27 ..2024_11_23_08_27_23.4057447185
lrwxrwxrwx    1 root     root            32 Nov 23 08:27 ..data -> ..2024_11_23_08_27_23.4057447185
lrwxrwxrwx    1 root     root            24 Nov 23 08:27 myserver-gzip.cfg -> ..data/myserver-gzip.cfg
lrwxrwxrwx    1 root     root            26 Nov 23 08:27 myserver-status.cfg -> ..data/myserver-status.cfg
lrwxrwxrwx    1 root     root            20 Nov 23 08:27 myserver.conf -> ..data/myserver.conf
#實際上配置檔案被關聯到..data路徑下,而它其實是..2024_11_23_08_27_23.4057447185這個隱藏目錄,名字是時間戳
#這個時間戳代表configMap版本,每次改了configMap,configMap版本會變

#修改configMap內容測試
#直接線上修改configMap(這樣改有風險,不建議)
[root@master01 ~]#kubectl edit cm nginx-config-files
#隨便改寫內容儲存

#每個pod會等待一段時間(一般幾秒~幾十秒),pod內檔案才會變更,時間k8s自行控制
#新版本可以發現配置檔案變更並生效。1.20及之前的版本做不到
#檢視內容,時間戳已發生改變
/etc/nginx/conf.d # ls -al
total 12
drwxrwxrwx    3 root     root          4096 Nov 23 08:43 .
drwxr-xr-x    3 root     root          4096 Nov 12 02:02 ..
drwxr-xr-x    2 root     root          4096 Nov 23 08:43 ..2024_11_23_08_43_42.901207710
lrwxrwxrwx    1 root     root            31 Nov 23 08:43 ..data -> ..2024_11_23_08_43_42.901207710
lrwxrwxrwx    1 root     root            24 Nov 23 08:27 myserver-gzip.cfg -> ..data/myserver-gzip.cfg
lrwxrwxrwx    1 root     root            26 Nov 23 08:27 myserver-status.cfg -> ..data/myserver-status.cfg
lrwxrwxrwx    1 root     root            20 Nov 23 08:27 myserver.conf -> ..data/myserver.conf
#檢視裡面nginx的配置已變更
#nginx -T可以檢視當前nginx載入的配置,經確認也已變更(說明自動過載新配置了)
/etc/nginx/conf.d #nginx -T

#注:這種方式修改會重新注入到pod內部,是否生效看系統是否自動裝載新配置(新的服務都可以,早期java可能要重啟pod)

3 Secret

Secret資源型別:
    型別之分:
        kubectl create secret (docker-registry | generic | tls) [options]
            docker-registry:專用於認證到docker registry服務上的認證資訊型別
                kubectl create secret docker-registry NAME --docker-username=user --docker-password=password --docker-email=email[--docker-server=string]

                引用方式:pods.spec.imagePullSecrets,列表型資料 
                第二種引用方式:pods.spec.serviceAccountName
                    serviceaccount.imagePullSecrets 
                    
            tls:專用配置服務基於ssl/tls通訊時使用的數字證書和私鑰的型別
                kubectl create secret tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run=server|client|none]
                證書的鍵名:tls.crt 
                私鑰的鍵名:tls.key 
                
            generic: 通用型別,可劃分為多種子型別
                --type 

建立Secret資源

secret和configmap的顯著區別是儘量不要用載入環境變數的方式去載入secret(導致敏感資訊洩露), 用卷的方式載入

但有些場景沒辦法, 像mysql必須使用環境變數提供

支援類似於ConfigMap的建立方式,但Secret有型別子命令,而且不同型別在data或stringData欄位中支援巢狀使用的key亦會有所有同;
命令式命令
  ◼ generic
    ◆kubectl create secret generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1]
    ◆除了後面docker-registry和tls命令之外的其它型別,都可以使用該命令中的--type選項進行定義,但有些型別有key的特定要求
  ◼ tls
    ◆kubectl create secret tls NAME --cert=path/to/cert/file --key=path/to/key/file
    ◆通常,其儲存cert檔案內容的key為tls.crt,而儲存private key的key為tls.key
  ◼ docker-registry
    ◆kubectl create secret docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-file=[key=]source]
    ◆通常,從已有的json格式的檔案載入生成的就是dockerconfigjson型別,命令列直接量生成的也是該型別

#generic示例 (使用環境變數引用,不太靠譜,資訊依然會洩露):
#建立secret generic型別,名稱叫mysql-secret (自動做base64編碼進行儲存)
[root@master01 ~]#kubectl create secret generic mysql-secret --from-literal=root.password='M@geEdu' --from-literal=user.password="wpP@ss" -n wordpress
#檢視secret (不歸類的都定義為Opaque) DATA為2表示有2項
[root@master01 pods]#kubectl get secret -n wordpress
NAME           TYPE     DATA   AGE
mysql-secret   Opaque   2      14s
[root@master01 pods]#kubectl get secret -o yaml -n wordpress
apiVersion: v1
items:
- apiVersion: v1
  data:
    root.password: TUBnZUVkdQ==
    user.password: d3BQQHNz
  kind: Secret
  metadata:
    creationTimestamp: "2024-11-23T10:04:35Z"
    name: mysql-secret
    namespace: default
    resourceVersion: "634108"
    uid: 3b51fdcf-ba8c-437a-8b65-1b6273ea3f03
  type: Opaque
kind: List
metadata:
  resourceVersion: ""

#定義mysql的pod,引用上面的secret
]#vim pod-mydb.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mydb
  namespace: wordpress
spec:
  containers:
  - name: mydb
    image: mysql:8.0
    env:
    - name: MYSQL_ROOT_PASSWORD #超級使用者賬號
      valueFrom:
        secretKeyRef:
          name: mysql-secret
          key: root.password
          optional: false #必選
    - name: MYSQL_DATABASE #放在secret或configmap都行
      value: wpdb
    - name: MYSQL_USER #放在secret或configmap都行
      value: wpuser
    - name: MYSQL_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-secret
          key: user.password
[root@master01 ~]#kubectl apply -f pod-mydb.yaml
[root@master01 ~]#kubectl get -f pod-mydb.yaml
#進入pod
[root@master01 ~]#kubectl exec -ti mydb -n wordpress -- /bin/sh
#檢視環境變數可以看到密碼
sh-5.1# env


#docker-registry示例
]#kubectl create secret docker-registry magedu-dockerhub --docker-username=magedu --docker-password=M@geEdu --docker-email=mage@magedu.com --dry-run=client -o yaml
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJtYWdlZHUiLCJwYXNzd29yZCI6Ik1AZ2VFZHUiLCJlbWFpbCI6Im1hZ2VAbWFnZWR1LmNvbSIsImF1dGgiOiJiV0ZuWldSMU9rMUFaMlZGWkhVPSJ9fX0=
kind: Secret
metadata:
  creationTimestamp: null
  name: magedu-dockerhub
type: kubernetes.io/dockerconfigjson

#引用:建立pod時修改pods.spec.imagePullSecrets欄位(列表型資料),把Secret值寫入


#tls示例
#準備好私鑰和證書
[root@master01 certs.d]#ls
nginx.crt  nginx.key
#不建立tls型別的secret,生成yaml
[root@master01 certs.d]#kubectl create secret tls nginx-cert --cert=./nginx.crt --key=./nginx.key --dry-run -o yaml
W1123 11:13:44.112377  194065 helpers.go:703] --dry-run is deprecated and can be replaced with --dry-run=client.
apiVersion: v1
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURsVENDQW4yZ0F3SUJBZ0lVR2Zya05FeGZiS2N5Yy9LYkpLUXJ5MzRTcHI0d0RRWUpLb1pJaHZjTkFRRUwKQlFBd1dqRUxNQWtHQTFVRUJoTUNRMDR4RURBT0JnTlZCQWdNQjBKbGFXcHBibWN4RURBT0JnTlZCQWNNQjBKbAphV3BwYm1jeER6QU5CZ05WQkFvTUJrUmxkazl3Y3pFV01CUUdBMVVFQXd3TmQzZDNMbWxzYVc1MWVDNXBiekFlCkZ3MHlNREEwTVRVd05UQXdORE5hRncweU1EQTFNVFV3TlRBd05ETmFNRm94Q3pBSkJnTlZCQVlUQWtOT01SQXcKRGdZRFZRUUlEQWRDWldscWFXNW5NUkF3RGdZRFZRUUhEQWRDWldscWFXNW5NUTh3RFFZRFZRUUtEQVpFWlhaUApjSE14RmpBVUJnTlZCQU1NRFhkM2R5NXBiR2x1ZFhndWFXOHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRE1pNSsyUStZTlNxeS9vVVhNQzAraklqc2puS2M5SzdjVzYweFhrQzZOa3lSY3BZSmwKdWM4ckFYRUxyZjUxMmJUWGhxb0hqVG5JeFExVFROeDNRbE9oTHBYVjJCbGtObVNzY0w0Uy9IL1VEWTlQayt0cwpiOGlEZSszdlBEQ1ZiQytvOEFYYUhUaktaQ0pXc0oxY0RJY0JGenQ0MFQzUWswL1hQcVYrM1pERWFNcW9LYklJCmRvbENLLzZiN1BlaElXVVFWeFVDK3NoZ0xVbjJReXJmK0UrRC9TQmZFOVd3UGp0YXdCeHdxaDZOczV1dEVsL0cKVmltbEMxM2tsWTNGQ1RMWEhFU3hNKzdGNlU2VUdpYm1CWFRsLzZlV1I2bmlVdW1kMjhyU2NneXVDTnA1NGY2cAp1VGFMK0ZNbG0wN0NiS3lLWHhDZHpVNXVrSFlOYXlqa3p3ck5BZ01CQUFHalV6QlJNQjBHQTFVZERnUVdCQlE1ClhNbkhJanZYZFVCb1BEd3BpbjdiVWN6SHJqQWZCZ05WSFNNRUdEQVdnQlE1WE1uSElqdlhkVUJvUER3cGluN2IKVWN6SHJqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQlVwU1pSNUE5Rgo2bVZhSU16TUl0anZadXFpRDNpeG9PN3NEdEZCcGVsYVZNV0dIaTZ3cFlTL21kNkNmS0hQQ3pySDhnNmpWTGhaClRpRWd5OVREUG5wMmU0VWNBUzdYMVBPM21GWTVscGpVakxJZjR4bUZrUy9FdFQ1ZE5TbUF1NGxGN2ZrRkEraEYKc244b2s5bk9DNk05OVBxbmQ1SlpVR1pwRFJCK1NQblpIVzZ3R2JiSVd3R3hPQmNtejBBMHNJNTkyVm9POThYKwoxK2w4MEVmdkhjRDJQRmdmSzhqS3g5eEl0UjEwcnBtVE4yQmtPQlBiREZ4SHZEcTNjRlRBSVVhMGhWS04xT0xJCk1oSEsvVnJmRUxHanJvY0pTZEFxcGpPTFl0R2JQN09sWURHTzFPRDk2ZEVTYStWWTRXYnFqYzc5S0luREQrWnkKWVlqbkJKR2F5VExyCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
  tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBekl1ZnRrUG1EVXFzdjZGRnpBdFBveUk3STV5blBTdTNGdXRNVjVBdWpaTWtYS1dDClpiblBLd0Z4QzYzK2RkbTAxNGFxQjQwNXlNVU5VMHpjZDBKVG9TNlYxZGdaWkRaa3JIQytFdngvMUEyUFQ1UHIKYkcvSWczdnQ3end3bFd3dnFQQUYyaDA0eW1RaVZyQ2RYQXlIQVJjN2VORTkwSk5QMXo2bGZ0MlF4R2pLcUNteQpDSGFKUWl2K20rejNvU0ZsRUZjVkF2cklZQzFKOWtNcTMvaFBnLzBnWHhQVnNENDdXc0FjY0tvZWpiT2JyUkpmCnhsWXBwUXRkNUpXTnhRa3kxeHhFc1RQdXhlbE9sQm9tNWdWMDVmK25sa2VwNGxMcG5kdkswbklNcmdqYWVlSCsKcWJrMmkvaFRKWnRPd215c2lsOFFuYzFPYnBCMkRXc281TThLelFJREFRQUJBb0lCQUNjeWpvMndIMUxtdjRvTgpqc0dXWFZHR3lzeDlSYk04UUY3ZEFvazVNU0tpVXZLS0tSM3phSmIyTk1Lbk9qODlWQ0dGUmVvaWp6TkJSOWR4CndFSCtiT1pUZGhVL3owWGNBcGpsRmhldldaTzZjWDh2ZW9zU05OdTFrUmdxY2FrQXpYVlRZZHUxZzkrTkp1TnoKL3dQWHhydFh4MmJVdWtMUktCaTRnYUI1TnpmY0FSdzBIWG9aUjExbVRydkhLSWRSQUx4Q21KR09aTlg5RjhGMQpsQ1dCN2hjWVNkRVg5MTBkT2VFTlRzUUNMeVJvaDdXWkJSejBEUVBYNnNJd2FJTGtFT0puSVQ0K3JYNldCZGdkCmRkRjN3L0ZYcGxFdW9BSVplSDJmZnkvMzNyTFpSSXlSZWFEVnJUeHFUMnVOQlVkbkJPN1NFa2VYV25kUEh2V2MKaUpRUGxTRUNnWUVBOXdGQmpzOGk2a0YrWDM1N09ueFpuZXB4WnVZMGhqRk5BcVdPSGlUMWsvcWt6T2pRSG1kMgpHSnJZZjc0OUc3VHB2R2Y2TytzalIvZm96ODVsdFViSnh5Wk1IK2JqQzgwM0VUeXp2TmlXZzE2MVp6Nyt5NGpKClI5dlhCS05vd0NlazVFYVRyZ3owZkp5bjJ1WlRDak1aUE1WVVFBRmlYc0RtUTAybUp6dVdwTmtDZ1lFQTAvNkkKTjg2a2szalRzaHhvTEM5VUR0K0x4VTVaUE8vS0t0a21SUEorYU1IbS9uUXJYazZ6a1pJVUF2OHIrOWZXVXdHbQpYUmd2QjVlaHAvT1htdkxLWEhSVmhhVjc3QTZvMEVQVFRrcU5iZU5GSHg1cVFObU85ZHdIVTNSTW5PeWk0TnluCmFJNlljNGIvMWJXdXlBYlVlc0tEdXI3L0FMOFo5UU1XVUVUb2pSVUNnWUF2bzY1aFBOSWZIRUtqYUdHY0JoL0MKdFZUcDQ3eDlwVVNWSGhrcTl6WG1OSkZVZEJLdnlvU2Nla0VIWWttbTdsMm1XT2VLWnUrSEVlbDFLdm15M05STgo5TFQ1OGk0WU9KeEdWczdUdlhKS0pCb1lyNjIwMDh6K2J3Z3BmTnJYTk00NHVPUUN6YnpaeTkwVCt4aEkvMUgrCnhwQlpSK3NSRzJOTjE4d1VCUW9wQVFLQmdFdnNHWDdiRytmUTJ3Z3Iwa2NZd0NML2ZvQXdPaGR2elZpaEltcUkKNmlxOFh1ejhUOWZibWNYbHFoTVVyZnpvNU5JZmdpUlBGL0RCSmwwUENWbXQ0RGxTVkpxamxJa0xDdnhqZmhiSQo3blBQZEI3YjlyTzQ5dEVvZHRzMWlJYWUzUXBwRys5L09pd055aXdRZ0VNVTV4Mzc4Yzk4dmJqWHVBVWVrT3c0CmNZeXRBb0dBTEtNazBwMUUrZHJtVzVuS3VMa2dyNDYzbmtlenBld2Y4eVJ2UHZQcUo4UkdobTBGblphOW1mQ0YKd1JCMDh1MkZ6YTRHSldEY0p2VG9kV3NtSmpCVHRMQ0wzaFlCSmNNQXNVNEdEbXBCZDdQMVBQQ1ZCb0JMeVJjbApyK2VTOFJzZTRwTERjOWdpQk9ZSGp4Q2hsVktSdVhESmh2V2k0azZVNGY5bStBNmp4STg9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
kind: Secret
metadata:
  creationTimestamp: null
  name: nginx-cert
type: kubernetes.io/tls

#tls示例,建立nginx服務,配https證書和秘鑰
[root@master01 nginx-ssl-conf.d]#vim myserver.conf
server {
    listen 443 ssl;
    server_name www.ik8s.io;

    ssl_certificate /etc/nginx/certs/tls.crt; #secret掛載點,鍵名為檔名(會自動base64解碼)
    ssl_certificate_key /etc/nginx/certs/tls.key; #secret掛載點,鍵名為key(會自動base64解碼)

    ssl_session_timeout 5m;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 

    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
    ssl_prefer_server_ciphers on;

    include /etc/nginx/conf.d/myserver-*.cfg;

    location / {
        root /usr/share/nginx/html;
    }
}

server {
    listen 80;
    server_name www.ilinux.io; 
    return 301 https://$host$request_uri; 
}

#pod檔案
[root@master01 configmaps_and_secrets]#vim secrets-volume-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secrets-volume-demo
  namespace: default
spec:
  containers:
  - image: nginx:alpine
    name: ngxserver
    volumeMounts:
    - name: nginxcerts
      mountPath: /etc/nginx/certs/
      readOnly: true
    - name: nginxconfs #載入配置檔案
      mountPath: /etc/nginx/conf.d/
      readOnly: true
  volumes:
  - name: nginxcerts
    secret:
      secretName: nginx-ssl-secret #secret名稱
  - name: nginxconfs
    configMap:
      name: nginx-sslvhosts-confs
      optional: false #不加,預設為false
      
#建立secret tls型別
[root@master01 configmaps_and_secrets]#kubectl create secret tls nginx-ssl-secret --cert=./certs.d/nginx.crt --key=./certs.d/nginx.key
[root@master01 configmaps_and_secrets]#kubectl get secret
#建立configmap
[root@master01 configmaps_and_secrets]#kubectl create configmap nginx-sslvhosts-confs --from-file=./nginx-ssl-conf.d/
[root@master01 configmaps_and_secrets]#kubectl get cm
#建立pod
[root@master01 configmaps_and_secrets]#kubectl apply -f secrets-volume-demo.yaml
#進入pod檢視
[root@master01 configmaps_and_secrets]#kubectl exec -it secrets-volume-demo -- /bin/sh
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
/ # cd /etc/nginx/certs/
/etc/nginx/certs # ls
tls.crt  tls.key
#和configmap的引用邏輯相同
/etc/nginx/certs # ls -al
total 4
drwxrwxrwt    3 root     root           120 Nov 23 12:42 .
drwxr-xr-x    1 root     root          4096 Nov 23 12:42 ..
drwxr-xr-x    2 root     root            80 Nov 23 12:42 ..2024_11_23_12_42_04.1485291318
lrwxrwxrwx    1 root     root            32 Nov 23 12:42 ..data -> ..2024_11_23_12_42_04.1485291318
lrwxrwxrwx    1 root     root            14 Nov 23 12:42 tls.crt -> ..data/tls.crt
lrwxrwxrwx    1 root     root            14 Nov 23 12:42 tls.key -> ..data/tls.key
#配置資訊發生改變,要確保應用程式能自動過載(邏輯同configmap)

4 DownwardAPI 和 Projected

關於DownwardAPI
 DownwardAPI
  ◼ 與ConfigMap和Secret不同,DownwardAPI自身並非一種獨立的API資源型別
  ◼ DownwardAPI只是一種將Pod的metadata、spec或status中的欄位值注入到其內部Container裡的方式
 DownwardAPI提供了兩種方式用於將 POD 的資訊注入到容器內部
  ◼ 環境變數:用於單個變數,可以將 POD 資訊和容器資訊直接注入容器內部 #一般採用這種
  ◼ Volume掛載:將 POD 資訊生成為檔案,直接掛載到容器內部中去

可向容器注入的後設資料

在容器上基於DownwardAPI引用Pod後設資料,可透過兩種欄位完成
  ◼ fieldRef:引用常規的後設資料
  ◼ resourceFieldRef:引用同資源限制和資源需求相關的後設資料

fieldRef 如圖

有關容器資源限制和資源需求的資訊則要透過resourceFieldRef 欄位注入
  ◼ 這些資訊都能夠基於環境變數和卷的方式注入到容器中

resourceFieldRef 如圖

DownwardAPI示例

#透過環境變數示例
#下面的配置片斷擷取自由三個RabbitMQ Pod構建的RabbitMQ Cluster配置示例之上
containers:
  - name: rabbitmq
  image: registry.magedu.com/rabbitmq/rabbitmq:3.12-management
  ports:
  - containerPort: 15672
    name: discovery
  - containerPort: 5672
    name: amqp
  env:
  - name: RABBIT_POD_NAME
    valueFrom:
      fieldRef:
        apiVersion: v1 #pod api版本號
        fieldPath: metadata.name
  - name: RABBIT_POD_NAMESPACE
    valueFrom:
      fieldRef:
        fieldPath: metadata.namespace
  - name: RABBITMQ_NODENAME #引用變數$()實現
    value: rabbit@$(RABBIT_POD_NAME).rabbitmq.$(RABBIT_POD_NAMESPACE).svc.cluster.local
  - name: RABBITMQ_USE_LONGNAME
    value: "true"
  - name: RABBITMQ_CONFIG_FILE
    value: "/config/rabbitmq"
  - name: RABBITMQ_ERLANG_COOKIE
    valueFrom:
      secretKeyRef:
        name: rabbit-secret
        key: RABBITMQ_ERLANG_COOKIE
  - name: K8S_HOSTNAME_SUFFIX
    value: .rabbitmq.$(RABBIT_POD_NAMESPACE).svc.cluster.local


#透過volume掛載示例(一般不這麼用)  必須是上面支援使用卷引用的欄位
]#vim pod-use-downwardapi.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod-use-downwardapi
  name: pod-use-downwardapi
spec:
  containers:
  - image: ikubernetes/demoapp:v1.0
    name: pod-use-downwardapi
    volumeMounts:
    - name: dapi
      mountPath: /dapi
  volumes:
  - name: dapi
    downwardAPI:
      items:
      - path: "name" #掛載路徑下檔名
        fieldRef: #引用欄位名稱
          fieldPath: metadata.name
#進入容器
]#ls /dapi/
name
]#cat name
pod-use-downwardapi

Projected Volume

 Projected Volume是一種特殊的卷型別,它能夠將已存在的多個卷投射進同一個掛載點目錄中
 Projected Volume僅支援對如下四種型別的卷(資料來源)進行投射操作,這類的卷一般都 是用於為容器提供預先定義好的資料
  ◼ Secret:投射Secret 物件
  ◼ ConfigMap:投射ConfigMap物件
  ◼ DownwardAPI:投射Pod後設資料
  ◼ ServiceAccountToken:投射ServiceAccount Token
  
#
volumes:
- name: local-storage
  persistentVolumeClaim:
    claimName: openebs-jiva-csi-pvc
- name: kube-api-access-9s76w
  projected:
    defaultMode: 420
    sources: #指定哪些卷投射進同一路徑下
    - serviceAccountToken:
      expirationSeconds: 3607
      path: token
    - configMap:
      items:
      - key: ca.crt
        path: ca.crt
      name: kube-root-ca.crt
    - downwardAPI:
      items:
      - fieldRef:
        apiVersion: v1
        fieldPath: metadata.namespace #內容
      path: namespace #以namespace檔名掛載

#示例: 修改pod檔案
]#vim pod-use-projected.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod-use-projected
  name: pod-use-projected
spec:
  containers:
  - image: ikubernetes/demoapp:v1.0
    name: pod-use-downwardapi
    volumeMounts:
    - name: proj
      mountPath: /proj
  volumes:
  - name: proj
    projected:
      defaultMode: 0644
      sources:
      - configMap:
          items:
          - key: myserver.conf
            path: my.conf #換個名字
          name: nginx-config-files
      - secret:
          items:
          - key: tls.crt
            path: nginx.crt #換個名字
          name: nginx-ssl-secret
      - downwardAPI:
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace #內容
            path: namespace #以namespace檔名掛載
]#kubectl apply -f pod-use-projected.yaml
#進入容器
]#kubectl exec -it pod-use-projected -- /bin/sh
]#ls /proj
]#my.conf namespace nginx.crt

總結:

為Pod提供配置:
    ConfigMap、Secret
        API Server支援資源型別:需要先定義出資源物件,而後引用
                       
    downwardAPI
        非為資源型別,可直接引用,因為它們自身即為Pod屬性
            fieldRef 
            resourceFieldRef
     
    Projected
        非為資源型別,但其要引用現有的configmap、secret資源物件,或downwardAPI中的後設資料資訊
        投射進同一個掛載點

相關文章