Kubernetes數據存儲

1. 數據存儲

  • 容器的生命周期可能很短,會被頻繁地創建和銷毀。那么容器在銷毀時,保存在容器中的數據也會被清除。這種結果對用戶來說,在某些情況下是不樂意看到的。為了持久化保存容器的數據,kubernetes引入了Volume的概念。

  • Volume是Pod中能夠被多個容器訪問的共享目錄,它被定義在Pod上,然后被一個Pod里的多個容器掛載到具體的文件目錄下,kubernetes通過Volume實現同一個Pod中不同容器之間的數據共享以及數據的持久化存儲。Volume的生命容器不與Pod中單個容器的生命周期相關,當容器終止或者重啟時,Volume中的數據也不會丟失。

  • kubernetes的Volume支持多種類型,比較常見的有下面幾個:

    • 簡單存儲:EmptyDir、HostPath、NFS

    • 高級存儲:PV、PVC

    • 配置存儲:ConfigMap、Secret

1.1 基本存儲

1.1.1 EmptyDir

EmptyDir 是一種輕量級的存儲選項,用于 Pod 內部容器之間的數據共享或臨時存儲。下面是一些關于 EmptyDir 的補充信息:

  • 生命周期:EmptyDir 的生命周期與 Pod 綁定。當 Pod 被創建時,EmptyDir 被創建并掛載到 Pod 中所有需要它的容器上。當 Pod 被刪除時,EmptyDir 及其內容也會被刪除。

  • 使用場景

    • 臨時存儲:對于需要臨時寫入和讀取數據,但不要求數據持久化的場景,如緩存或會話數據。

    • 容器間數據共享:當 Pod 中運行多個容器需要共享文件時,EmptyDir 可以作為一個共享存儲空間。

    • 數據處理:在數據被處理并存儲到更持久的存儲解決方案之前,可以臨時存儲在 EmptyDir 中。

  • 性能:EmptyDir 存儲的性能通常與宿主機的磁盤性能相當,因為它直接存儲在宿主機上。

  • 限制:由于 EmptyDir 與 Pod 的生命周期綁定,因此它不適合存儲需要跨 Pod 持久化的數據。此外,EmptyDir 不保證數據的備份或復制,所以在 Pod 重啟或重建時數據可能會丟失。

  • 配置:EmptyDir 可以通過 Pod 定義中的 spec.volumes 字段來配置,無需指定宿主機上的路徑。

  • 安全性:EmptyDir 默認只對 Pod 內部的容器可見,提供了一定程度的隔離。

在一個Pod中準備兩個容器nginx和busybox,然后聲明一個Volume分別掛在到兩個容器的目錄中,然后nginx容器負責向Volume中寫日志,busybox中通過命令將日志內容讀到控制臺。

image-20240522151055909

  • 示例

[root@k8s-master-01 ~]# vim volume-emptydir.yaml
---
apiVersion: v1
kind: Pod
metadata:name: volume-emptydirnamespace: test
spec:containers:- name: nginximage: nginx:1.17.1ports:- containerPort: 80volumeMounts:              # 將logs-volume掛在到nginx容器中,對應的目錄為 /var/log/nginx- name: logs-volumemountPath: /var/log/nginx- name: busyboximage: busybox:1.30command: ["/bin/sh","-c","tail -f /logs/access.log"]  # 初始命令,動態讀取指定文件中內容volumeMounts:       # 將logs-volume 掛在到busybox容器中,對應的目錄為 /logs- name: logs-volumemountPath: /logsvolumes:     # 聲明volume, name為logs-volume,類型為emptyDir- name: logs-volumeemptyDir: {}[root@k8s-master-01 ~]# kubectl apply -f volume-emptydir.yaml 
pod/volume-emptydir created
[root@k8s-master-01 ~]# kubectl get pod -n test -o wide
NAME              READY   STATUS    RESTARTS   AGE   IP              NODE          NOMINATED NODE   READINESS GATES
volume-emptydir   2/2     Running   0          62s   1.244.44.201   k8s-node-02   <none>           <none>
  • 訪問

[root@k8s-master-01 ~]# kubectl exec -it volume-emptydir -n test /bin/bash
root@volume-emptydir:/# echo 'This is EmptyDir test' > /usr/share/nginx/html/index.html 
root@volume-emptydir:/# exit
[root@k8s-master-01 ~]# curl 1.244.44.201
This is EmptyDir test
  • 通過kubectl logs命令查看指定容器的標準輸出

[root@k8s-master-01 ~]# kubectl logs -f volume-emptydir -n test -c busybox   # 可以看到訪問日志
1.244.151.128 - - [22/May/2024:07:15:58 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
1.244.151.128 - - [22/May/2024:07:17:04 +0000] "GET / HTTP/1.1" 200 22 "-" "curl/7.29.0" "-"

1.1.2 HostPath

  • EmptyDir中數據不會被持久化,它會隨著Pod的結束而銷毀,如果想簡單的將數據持久化到主機中,可以選擇HostPath。

  • HostPath就是將Node主機中一個實際目錄掛在到Pod中,以供容器使用,這樣的設計就可以保證Pod銷毀了,但是數據依據可以存在于Node主機上。

    • 數據持久性:與 EmptyDir 不同,HostPath 卷將 Node 主機上的一個目錄掛載到 Pod 中,使得 Pod 內的容器可以訪問和修改該目錄上的文件。由于這些文件存儲在 Node 主機上,因此即使 Pod 被刪除,數據仍然可以在 Node 主機上保持。

    • 用途HostPath 適用于需要持久化數據的場景,例如數據庫文件、配置文件等。然而,由于 HostPath 直接使用了 Node 主機的文件系統,可能會帶來一些安全和管理上的挑戰,例如權限管理、數據一致性等問題。

image-20240522154122838

  • 示例

[root@k8s-master-01 ~]# vim volume-hostpath.yaml
---
apiVersion: v1
kind: Pod
metadata:name: volume-hostpathnamespace: test
spec:containers:- name: nginximage: nginx:1.17.1ports:- containerPort: 80volumeMounts:- name: logs-volumemountPath: /var/log/nginx- name: busyboximage: busybox:1.30command: ["/bin/sh","-c","tail -f /logs/access.log"]volumeMounts:- name: logs-volumemountPath: /logsvolumes:- name: logs-volumehostPath:path: /root/logstype: DirectoryOrCreate[root@k8s-master-01 ~]# kubectl apply -f volume-hostpath.yaml 
pod/volume-hostpath created
[root@k8s-master-01 ~]# kubectl get pod -n test -o wide   # 調度到了node2
NAME              READY   STATUS    RESTARTS   AGE   IP              NODE          NOMINATED NODE   READINESS GATES
volume-hostpath   2/2     Running   0          23s   1.244.44.202   k8s-node-02   <none>           <none>

各個 type 值的詳細說明:

type描述
DirectoryOrCreate如果指定的目錄存在,則使用該目錄;如果不存在,則先創建目錄后使用。
Directory目錄必須存在,否則掛載操作會失敗。
FileOrCreate如果指定的文件存在,則使用該文件;如果不存在,則先創建文件后使用。
File文件必須存在,否則掛載操作會失敗。
SocketUnix 套接字必須存在,否則掛載操作會失敗。
CharDevice字符設備必須存在,否則掛載操作會失敗。
BlockDevice塊設備必須存在,否則掛載操作會失敗。
  • 測試

[root@k8s-master-01 ~]# curl 1.244.44.202# 下來就可以去host的/root/logs目錄下查看存儲的文件了
注意: 下面的操作需要到Pod所在的節點運行,這里是調度到了node2
[root@k8s-node-02 ~]# ll /root/logs/
total 4
-rw-r--r-- 1 root root 95 May 22 15:44 access.log
-rw-r--r-- 1 root root  0 May 22 15:39 error.log
[root@k8s-node-02 ~]# cat /root/logs/access.log 
1.244.151.128 - - [22/May/2024:07:44:59 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"# 同樣的道理,如果在此目錄下創建一個文件,到容器中也是可以看到的

1.1.3 NFS

  • 雖然 HostPath 可以用于解決數據持久化的問題,但它并不適用于跨節點的數據共享和高可用性場景。一旦 Pod 從一個節點遷移到另一個節點,HostPath 卷中的數據就無法訪問。這是因為 HostPath 卷依賴于特定節點上的文件系統,而不是一個獨立的網絡存儲系統。

  • 為了解決這個問題,確保數據在節點遷移時仍然可用,通常推薦使用網絡文件存儲系統,如 NFS (Network File System) 或 CIFS (Common Internet File System)。這兩種協議允許 Pod 訪問遠程存儲系統上的數據,就好像它們是本地文件一樣。

  • NFS 是一種網絡文件系統協議,它允許客戶端計算機訪問服務器上的文件和目錄,就像它們是本地文件一樣。通過設置 NFS 服務器,您可以將 Pod 中的存儲直接連接到 NFS 系統上。這樣,即使 Pod 從一個節點遷移到另一個節點,只要網絡連接正常,Pod 就可以繼續訪問數據。

image-20240522163948587

  • 首先要準備NFS的服務器,這里為了簡單,直接是master節點做NFS服務器

# 在master上安裝nfs服務
[root@k8s-master-01 ~]# yum install nfs-utils -y
?
# 準備一個共享目錄
[root@k8s-master-01 ~]# mkdir /nfstest
?
# 將共享目錄以讀寫權限暴露給192.168.110.0/24網段中的所有主機
[root@k8s-master-01 ~]# vim /etc/exports
/nfstest 192.168.110.0/24(rw,no_root_squash)
?
[root@k8s-master-01 ~]# systemctl restart rpcbind.service nfs-server.service
  • 在的每個node節點上都安裝下NFS,這樣的目的是為了node節點可以驅動NFS設備

[root@k8s-node-01 ~]# yum install nfs-utils -y
[root@k8s-node-01 ~]# showmount -e 192.168.110.21
Export list for 192.168.110.21:
/nfstest 192.168.110.0/24
?
[root@k8s-node-02 ~]# yum install nfs-utils -y
[root@k8s-node-02 ~]# showmount -e 192.168.110.21
Export list for 192.168.110.21:
/nfstest 192.168.110.0/24
  • 編寫Pod的配置文件

[root@k8s-master-01 ~]# vim volume-nfs.yaml
---
apiVersion: v1
kind: Pod
metadata:name: volume-nfsnamespace: test
spec:containers:- name: nginximage: nginx:1.17.1ports:- containerPort: 80volumeMounts:- name: logs-volumemountPath: /var/log/nginx- name: busyboximage: busybox:1.30command: ["/bin/sh","-c","tail -f /logs/access.log"]volumeMounts:- name: logs-volumemountPath: /logsvolumes:- name: logs-volumenfs:server: k8s-master-01path: /nfstest[root@k8s-master-01 ~]# kubectl apply -f volume-nfs.yaml 
pod/volume-nfs created
[root@k8s-master-01 ~]# kubectl get pod -n test -o wide
NAME         READY   STATUS    RESTARTS   AGE    IP              NODE          NOMINATED NODE   READINESS GATES
volume-nfs   2/2     Running   0          118s   1.244.44.204   k8s-node-02   <none>   
  • 查看

[root@k8s-master-01 ~]# ll /nfstest/
total 0
-rw-r--r-- 1 root root 0 May 22 17:23 access.log
-rw-r--r-- 1 root root 0 May 22 17:23 error.log
[root@k8s-master-01 ~]# curl 1.244.44.204
[root@k8s-master-01 ~]# cat /nfstest/access.log 
1.244.151.128 - - [22/May/2024:09:26:39 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

1.2 高級存儲

1.2.1 PV和PVC

由于kubernetes支持的存儲系統有很多,要求客戶全都掌握,顯然不現實。為了能夠屏蔽底層存儲實現的細節,方便用戶使用, kubernetes引入PV和PVC兩種資源對象。

  • PV(Persistent Volume)

    • PV是Kubernetes中的一個API對象,它代表集群中的一塊存儲,這塊存儲已經預先按照某種方式設置好了,并且可以被多個用戶使用。PV是集群資源,由Kubernetes管理員預先配置,它們不會因Pod的終止而消失,因此被稱為“持久化”。PV可以采用多種形式,例如本地存儲、網絡附加存儲(NAS)、云存儲服務等。

  • PVC(Persistent Volume Claim)

    • PVC是用戶對存儲的請求,它允許用戶以聲明式的方式請求存儲資源,而無需關心存儲的具體實現細節。用戶定義所需的存儲容量、訪問模式和存儲類別(如果需要),然后提交PVC請求。

image-20240523113710183

在Kubernetes中使用PV(Persistent Volume)和PVC(Persistent Volume Claim)確實可以帶來工作流的細分和專業化,這樣的分工可以提高效率并減少錯誤。以下是各個角色的主要職責:

  • 存儲工程師,存儲工程師負責維護和操作底層的存儲系統。他們的工作包括:

    • 選擇合適的存儲解決方案,包括本地存儲、網絡附加存儲(NAS)、存儲區域網絡(SAN)或云存儲服務。

    • 配置和管理存儲硬件或服務,確保其性能、可靠性和安全性。

    • 監控存儲系統的性能,確保它滿足Kubernetes集群的需求。

    • 管理數據備份、恢復和災難恢復計劃。

  • Kubernetes管理員,Kubernetes管理員負責維護Kubernetes集群和PV資源。他們的工作職責包括:

    • 創建和管理PV資源,將底層存儲系統抽象化,使其可以在Kubernetes集群中使用。

    • 配置PV的訪問模式和存儲容量,確保它們符合集群的使用需求。

    • 監控PV的使用情況,確保存儲資源得到合理分配和優化。

    • 管理PV的生命周期,包括創建、修改和刪除操作。

  • Kubernetes用戶,Kubernetes用戶負責維護PVC資源,他們通常是開發人員或應用運維團隊。他們的工作職責包括:

    • 創建和管理PVC,根據應用的需求聲明所需的存儲資源。

    • 定義PVC的存儲容量、訪問模式和選擇器,以便與合適的PV進行綁定。

    • 將PVC掛載到Pod中,以便應用可以持久化存儲數據。

    • 監控PVC的狀態和使用情況,確保應用的存儲需求得到滿足。

1.2.2 PV(Persistent Volume)

  • PV(Persistent Volume)在Kubernetes中指的是持久化卷,它是一種存儲抽象的概念,代表了集群中的一塊存儲,這可以是本地磁盤、網絡附加存儲(NAS)、或者云存儲等。PV與底層存儲的具體實現細節相解耦,使得Kubernetes管理員可以靈活地管理存儲資源。

1.2.2.1 PV的主要特點包括
  • 獨立性:PV獨立于Pod存在,即使使用PV的Pod被刪除,PV中的數據也不會丟失。

  • 持久性:PV在設計上用于數據的持久化存儲,它們在Kubernetes集群中是長壽命的。

  • 可配置性:Kubernetes管理員可以配置PV的大小、訪問模式(如ReadWriteOnce、ReadOnlyMany、ReadWriteMany)以及存儲類別(StorageClass)。

  • 可重用性:PV一旦被創建,可以被多個Pod重用,只要它們的訪問模式和存儲需求相匹配。

  • 動態供應:通過StorageClass資源,Kubernetes可以自動創建PV以滿足PVC的請求,這個過程稱為動態存儲供應。

1.2.2.2 PV的生命周期
  • 創建:Kubernetes管理員根據集群的存儲需求預先創建PV資源。

  • 綁定:當用戶提交PVC(Persistent Volume Claim)請求時,Kubernetes會嘗試找到一個匹配的PV進行綁定。

  • 使用:綁定成功后,PV可以被Pod通過PVC訪問和使用。

  • 回收:當PVC被刪除時,PV可以被釋放并根據回收策略進行清理,以便再次使用或保持其數據。

1.2.2.3 資源清單文件
apiVersion: v1
kind: PersistentVolume
metadata:name: pv2
spec:nfs: # 存儲類型,與底層真正存儲對應path: /path/to/nfs/share # NFS共享路徑server: nfs-server.example.com # NFS服務器地址capacity: # 存儲能力,目前只支持存儲空間的設置storage: 2GiaccessModes: # 訪問模式- ReadWriteOnce # 可以被一個節點掛載為讀寫模式persistentVolumeReclaimPolicy: Retain # 回收策略# Retain:刪除PersistentVolumeClaim后,不會刪除PersistentVolume,只是標記為不可用# Delete:刪除PersistentVolumeClaim后,會刪除PersistentVolume# Recycle:刪除PersistentVolumeClaim后,將PersistentVolume清理并重新可用,但數據將丟失
1.2.2.4 PV關鍵配置參數
  • 存儲類型

    • 定義:底層實際存儲的類型,Kubernetes 支持多種存儲類型,如 NFS、iSCSI、glusterFS 等,每種類型的配置都會有所不同。

    • 影響因素:不同存儲類型可能支持的訪問模式和回收策略不同。

  • 存儲能力(capacity)

    • 定義:當前主要支持存儲空間的設置(如 storage=1Gi),但未來可能會增加 IOPS、吞吐量等其他性能指標的配置。

    • 注意事項:存儲能力的設置直接影響到 PV 能夠提供給 Pod 的存儲空間大小。

    • 訪問模式(accessModes)

    • 定義:描述用戶應用對存儲資源的訪問權限,包括:

      • ReadWriteOnce(RWO):讀寫權限,但只能被單個節點掛載。

      • ReadOnlyMany(ROX):只讀權限,可被多個節點掛載。

      • ReadWriteMany(RWX):讀寫權限,可被多個節點掛載。

    • 注意事項:底層不同的存儲類型可能支持的訪問模式不同。

  • 回收策略(persistentVolumeReclaimPolicy)

    • 定義:當 PV 不再被使用時,對其的處理方式,包括:

      • Retain(保留):保留數據,需管理員手動清理。

      • Recycle(回收):清除 PV 中的數據。

      • Delete(刪除):與 PV 相關聯的后端存儲完成 volume 刪除操作。

    • 注意事項:底層不同的存儲類型可能支持的回收策略不同。

  • 存儲類別(storageClassName)

    • 定義:通過 storageClassName 參數指定一個存儲類別,有助于管理和組織不同類型的存儲資源。

    • 綁定規則:具有特定類別的 PV 只能與請求了該類別的 Persistent Volume Claim (PVC) 進行綁定;未設定類別的 PV 則只能與不請求任何類別的 PVC 進行綁定。

  • 狀態(status)

    • 定義:PV 在生命周期中的狀態,包括:

      • Available(可用):表示可用狀態,尚未被任何 PVC 綁定。

      • Bound(已綁定):表示 PV 已經被 PVC 綁定。

      • Released(已釋放):表示 PVC 被刪除,但資源還未被集群重新聲明。

      • Failed(失敗):表示該 PV 的自動回收失敗。

1.2.2.5 示例
  • 使用NFS作為存儲,來演示PV的使用,創建3個PV,對應NFS中的3個暴露的路徑

[root@k8s-master-01 ~]# mkdir /data/pv{1..3} -p
[root@k8s-master-01 ~]# vim /etc/exports
/data/pv1 192.168.110.0/24(rw,no_root_squash)
/data/pv2 192.168.110.0/24(rw,no_root_squash)
/data/pv3 192.168.110.0/24(rw,no_root_squash)
?
?
[root@k8s-master-01 ~]# exportfs -arv
exporting 192.168.110.0/24:/data/pv3
exporting 192.168.110.0/24:/data/pv2
exporting 192.168.110.0/24:/data/pv1
  • 創建pv配置文件

[root@k8s-master-01 ~]# vim pv.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv1
spec:capacity:storage: 1GiaccessModes:- ReadWriteManypersistentVolumeReclaimPolicy: Retainnfs:path: /data/pv1server: k8s-master-01---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv2
spec:capacity:storage: 2GiaccessModes:- ReadWriteManypersistentVolumeReclaimPolicy: Retainnfs:path: /data/pv2server: k8s-master-01---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv3
spec:capacity:storage: 3GiaccessModes:- ReadWriteManypersistentVolumeReclaimPolicy: Retainnfs:path: /data/pv3server: k8s-master-01[root@k8s-master-01 ~]# kubectl apply -f pv.yaml 
persistentvolume/pv1 created
persistentvolume/pv2 created
persistentvolume/pv3 created[root@k8s-master-01 ~]# kubectl get pv -o wide
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE    VOLUMEMODE
pv1    1Gi        RWX            Retain           Available                                   119s   Filesystem
pv2    2Gi        RWX            Retain           Available                                   119s   Filesystem
pv3    3Gi        RWX            Retain           Available                                   119s   Filesystem

1.2.3 PVC(Persistent Volume Claim)

1.2.3.1 資源清單
  • PVC是資源的申請,用來聲明對存儲空間、訪問模式、存儲類別需求信息。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvcnamespace: dev
spec:accessModes: # 訪問模式- ReadWriteOnce # 或者 ReadOnlyMany、ReadWriteMany,取決于你的需求selector: # 采用標簽對PV選擇matchLabels:app: myapp # 這里的值應該匹配你想要綁定的PV的標簽storageClassName: # 存儲類別- standard # 如果沒有指定存儲類別,則默認使用defaultresources: # 請求空間requests:storage: 5Gi # 請求的存儲空間大小
1.2.3.2 PVC 的關鍵配置參數
  • 訪問模式(accessModes)

    • 定義:描述用戶應用對存儲資源的訪問權限。

    • 可選值

      • ReadWriteOnce:表示該卷可以被集群中的一個節點掛載為讀寫模式。

      • ReadOnlyMany:表示該卷可以被集群中的多個節點掛載為只讀模式。

      • ReadWriteMany:表示該卷可以被集群中的多個節點同時掛載為讀寫模式。

    • 注意事項:不同的存儲類型可能支持的訪問模式不同。

  • 選擇條件(selector)

    • 定義:通過 Label Selector 的設置,使 PVC 對系統中已存在的 PV 進行篩選。

    • 作用:允許 PVC 根據標簽選擇特定的 PV,從而實現更靈活的存儲資源管理。

    • 示例matchLabels: { app: myapp } 表示 PVC 會嘗試綁定標簽為 { app: myapp } 的 PV。

  • 存儲類別(storageClassName)

    • 定義:PVC 在定義時可以設定需要的后端存儲的類別。

    • 作用:只有設置了相同 storageClassName 的 PV 才能被系統選出作為 PVC 的目標。

    • 示例storageClassName: standard 表示 PVC 要求使用名為 standard 的存儲類別。

  • 資源請求(Resources)

    • 定義:PVC 中的資源請求字段用于指定 PVC 需要的最小存儲空間大小。

    • 示例resources.requests.storage: 5Gi 表示 PVC 請求至少需要 5GB 的存儲空間。

    • 注意事項:PVC 的資源請求必須小于或等于 PV 提供的最大存儲空間,否則 PVC 無法成功綁定到 PV 上。

1.2.3.3 配置示例
[root@k8s-master-01 ~]# vim pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc1namespace: test
spec:accessModes:- ReadWriteManyresources:requests:storage: 10Mi---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc2namespace: test
spec:accessModes:- ReadWriteManyresources:requests:storage: 10Mi---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc3namespace: test
spec:accessModes:- ReadWriteManyresources:requests:storage: 10Mi[root@k8s-master-01 ~]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created[root@k8s-master-01 ~]# kubectl get pvc -n test -o wide
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
pvc1   Bound    pv1      1Gi        RWX                           6s    Filesystem
pvc2   Bound    pv2      2Gi        RWX                           6s    Filesystem
pvc3   Bound    pv3      3Gi        RWX                           6s    Filesystem[root@k8s-master-01 ~]# kubectl get pv -o wide   # PV狀態變為綁定
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       STORAGECLASS   REASON   AGE     VOLUMEMODE
pv1    1Gi        RWX            Retain           Bound    test/pvc1                           2m26s   Filesystem
pv2    2Gi        RWX            Retain           Bound    test/pvc2                           2m26s   Filesystem
pv3    3Gi        RWX            Retain           Bound    test/pvc3                           2m26s   Filesystem
  • 創建pods.yaml, 使用pv

[root@k8s-master-01 ~]# vim pods.yaml
---
apiVersion: v1
kind: Pod
metadata:name: pod1namespace: test
spec:containers:- name: busyboximage: busybox:1.30command: ["/bin/sh", "-c", "while true; do echo pod1 >> /root/out.txt; sleep 10; done;"]volumeMounts:- name: volumemountPath: /root/volumes:- name: volumepersistentVolumeClaim:claimName: pvc1readOnly: false---
apiVersion: v1
kind: Pod
metadata:name: pod2namespace: test
spec:containers:- name: busyboximage: busybox:1.30command: ["/bin/sh", "-c", "while true; do echo pod2 >> /root/out.txt; sleep 10; done;"]volumeMounts:- name: volumemountPath: /root/volumes:- name: volumepersistentVolumeClaim:claimName: pvc2readOnly: false[root@k8s-master-01 ~]# kubectl apply -f pods.yaml 
pod/pod1 created
pod/pod2 created[root@k8s-master-01 ~]# kubectl get pod -n test -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP               NODE          NOMINATED NODE   READINESS GATES
pod1   1/1     Running   0          17s   1.244.154.197   k8s-node-01   <none>           <none>
pod2   1/1     Running   0          17s   1.244.44.194    k8s-node-02   <none>           <none># 查看nfs中的文件存儲
[root@k8s-master-01 ~]# cat /data/pv1/out.txt 
pod1
pod1
pod1
[root@k8s-master-01 ~]# cat /data/pv2/out.txt 
pod2
pod2
pod2

1.2.4 PVC和PV在Kubernetes中的生命周期

1.2.4.1 資源供應
  • 管理員首先需要創建底層存儲(如NFS、AWS EBS等),然后創建一個PV來代表這個存儲。PV定義了存儲的類型、大小、訪問模式等信息。

1.2.4.2 資源綁定
  • 用戶創建PVC來請求存儲資源。PVC定義了存儲需求,比如大小和訪問模式。

  • Kubernetes 集群會根據PVC的聲明去尋找一個或多個PV來滿足這些需求。如果找到匹配的PV,Kubernetes 會自動將PVC和PV進行綁定。

  • 如果沒有找到匹配的PV,PVC將進入Pending狀態,直到管理員創建了一個符合要求的PV。

1.2.4.3 資源使用
  • 一旦PVC和PV綁定,用戶可以在Pod中使用PVC,就像使用普通的Volume一樣,將PVC掛載到容器內部的路徑上。

  • Pod使用Volume的方式將PVC掛載到容器內的某個路徑進行使用。

1.2.4.4 資源釋放
  • 當用戶不再需要PVC時,可以刪除PVC來釋放與之綁定的PV。刪除PVC后,與該PVC綁定的PV會被標記為“已釋放”,但PV上的數據可能仍然存在,直到管理員清理這些數據。

  • PV的存儲空間在被釋放后,根據PV的回收策略,Kubernetes 會決定如何處理剩余的數據。例如,如果設置為Retain,數據將保持原地;如果設置為Delete,數據將被刪除。

1.2.4.5 資源回收
  • 對于PV,管理員可以設定回收策略,用于設置與之綁定的PVC釋放資源之后如何處理遺留數據的問題。只有PV的存儲空間完成回收,才能供新的PVC綁定和使用

  • Kubernetes 根據PV的設置的回收策略(reclaim policy)來決定如何回收PV上的數據。常見的回收策略有Retain和Delete。

    • Retain: 數據將保留在PV上,直到管理員手動清理。

    • Delete: 數據將被刪除,PV可以被重新綁定。

image-20240524142359033

  • 示例

[root@k8s-master-01 ~]# kubectl delete -f pvc.yaml   # 刪除PV
persistentvolumeclaim "pvc1" deleted
persistentvolumeclaim "pvc2" deleted
persistentvolumeclaim "pvc3" deleted
[root@k8s-master-01 ~]# kubectl get pv -o wide   # 狀態變為Retain
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM       STORAGECLASS   REASON   AGE   VOLUMEMODE
pv1    1Gi        RWX            Retain           Released   test/pvc1                           10m   Filesystem
pv2    2Gi        RWX            Retain           Released   test/pvc2                           10m   Filesystem
pv3    3Gi        RWX            Retain           Released   test/pvc3    

1.3 配置存儲

  • 在Kubernetes中,ConfigMapSecret是兩種核心資源,用于存儲和管理應用程序的配置數據和敏感信息。理解它們的功能和最佳實踐對于提高Kubernetes應用程序的安全性和配置管理的效率至關重要。

1.3.1 ConfigMap

  • ConfigMap是一種API對象,允許你存儲非敏感配置數據,如環境變量、數據庫URL等。它以鍵值對的形式存儲數據,便于應用程序訪問必要的配置。ConfigMap可以直接掛載到容器中或作為環境變量注入到容器中,從而使得應用程序能夠訪問存儲的配置數據,而無需修改應用程序代碼。

1.3.1.1 基本配置
  • 配置

[root@k8s-master-01 ~]# vim configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:name: configmapnamespace: test
data:msg: |username: kxyage: 22address: beijing[root@k8s-master-01 ~]# kubectl apply -f configmap.yaml 
configmap/configmap created
[root@k8s-master-01 ~]# kubectl get configmaps configmap -n test
NAME        DATA   AGE
configmap   1      65s
  • 創建一個pod-configmap.yaml,將上面創建的configmap掛載進去

[root@k8s-master-01 ~]# vim pod-configmap.yaml
---
apiVersion: v1
kind: Pod
metadata:name: pod-configmapnamespace: test
spec:containers:- name: nginximage: nginx:1.17.1volumeMounts:- name: configmountPath: /configmap/configvolumes:- name: configconfigMap:name: configmap[root@k8s-master-01 ~]# kubectl apply -f pod-configmap.yaml 
pod/pod-configmap created
[root@k8s-master-01 ~]#  kubectl get pod -n test -o wide
NAME            READY   STATUS    RESTARTS   AGE     IP               NODE          NOMINATED NODE   READINESS GATES
pod-configmap   1/1     Running   0          2m49s   1.244.154.198   k8s-node-01   <none>           <none>[root@k8s-master-01 ~]# kubectl exec -it pod-configmap -n test /bin/bash
root@pod-configmap:/# cd /configmap/config/
root@pod-configmap:/configmap/config# ls
msg
root@pod-configmap:/configmap/config# cat msg 
username: kxy
age: 22
address: beijing# 可以看到映射已經成功,每個configmap都映射成了一個目錄
# key--->文件 value---->文件中的內容
# 此時如果更新configmap的內容, 容器中的值也會動態更新# 動態驗證
[root@k8s-master-01 ~]# kubectl edit cm configmap -n test
將22改為100000000
[root@k8s-master-01 ~]# kubectl exec -it pod-configmap -n test /bin/bash
root@pod-configmap:/# cd /configmap/config/
root@pod-configmap:/configmap/config# cat msg 
username: kxy
age: 100000000
address: beijing
  • 使用字面值創建

# 使用文字值創建,利用 --from-literal 參數傳遞配置信息,該參數可以使用多次
# 創建名稱為special-config的ConfigMap配置
[root@k8s-master-01 ~]# kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
[root@k8s-master-01 ~]# kubectl get cm special-config 
NAME             DATA   AGE
special-config   2      50s
[root@k8s-master-01 ~]# kubectl describe cm special-config 
Name:         special-config
Namespace:    default
Labels:       <none>
Annotations:  <none>Data
====
special.how:
----
very
special.type:
----
charmBinaryData
====Events:  <none>[root@k8s-master-01 ~]# kubectl delete cm special-config
  • 使用文件創建

# 只要指定為一個文件就可以從單個文件中創建 ConfigMap 。 --from-file 這個參數可以使用多次,你可以使用兩次分別指定上個實  例中的那兩個配置文件,效果就跟指定整個目錄是一樣的。
[root@k8s-master-01 ~]# kubectl create configmap game-config-2 --from-file=/etc/hosts
[root@k8s-master-01 ~]# kubectl describe cm game-config-2
Name: ? ? ? ? game-config-2
Namespace: ?  default
Labels: ? ? ? <none>
Annotations:  <none>
?
Data
====
hosts:
----
127.0.0.1 ? localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 ? ? ? ? localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.110.21 k8s-master-01
192.168.110.24 K8s-node-01
192.168.110.25 K8s-node-02
?
?
BinaryData
====
?
Events:  <none>
?
[root@k8s-master-01 ~]# kubectl delete cm game-config-2
  • 使用目錄創建

# --from-file 指定在目錄下的所有文件都會被用在 ConfigMap 里面創建一個鍵值對,鍵的名字就是文件名,值就是文件的內容。
[root@k8s-master-01 ~]# mkdir test
[root@k8s-master-01 ~]# cp /etc/hosts /root/test/
[root@k8s-master-01 ~]# cp /etc/resolv.conf /root/test/
[root@k8s-master-01 ~]# kubectl create configmap my-config --from-file=/root/test/
configmap/my-config created
[root@k8s-master-01 ~]# kubectl describe cm my-config 
Name: ? ? ? ? my-config
Namespace: ?  default
Labels: ? ? ? <none>
Annotations:  <none>
?
Data
====
hosts:
----
127.0.0.1 ? localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 ? ? ? ? localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.110.21 k8s-master-01
192.168.110.24 K8s-node-01
192.168.110.25 K8s-node-02
?
resolv.conf:
----
# Generated by NetworkManager
nameserver 192.168.110.2
?
?
BinaryData
====
?
Events:  <none>
1.3.1.2 ConfigMap的使用
  • 通過環境變量方式傳遞給Pod

[root@k8s-master-01 ~]# vim pod-configmap.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod1
spec:containers:- name: pod1image: busybox:1.30command: ["/bin/sh", "-c", "env"]env:- name: key1valueFrom:configMapKeyRef:name: cm1-configkey: db_hostrestartPolicy: Never[root@k8s-master-01 ~]# kubectl apply -f pod-configmap.yaml 
pod/pod1 created
[root@k8s-master-01 ~]# kubectl get pod
NAME   READY   STATUS                       RESTARTS   AGE
pod1   0/1       Comp 0          74s
1.3.1.3 ConfigMap熱更新
  • 正常情況下,我們可以通過如下配置,在啟動的 Pod 容器里面獲取到 ConfigMap 中配置的信息。

[root@k8s-master-01 ~]# vim hotipdate.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:name: log-confignamespace: default
data:log_level: INFO---apiVersion: apps/v1
kind: Deployment
metadata:name: my-nginx
spec:replicas: 1selector:matchLabels:run: my-nginx  # 確保selector與template的labels匹配template:metadata:labels:run: my-nginxspec:containers:- name: my-nginximage: nginx:1.17.1ports:- containerPort: 80volumeMounts:- name: config-volumemountPath: /etc/configvolumes:- name: config-volumeconfigMap:name: log-config[root@k8s-master-01 ~]# kubectl apply -f hotipdate.yaml 
configmap/log-config unchanged
deployment.apps/my-nginx created[root@k8s-master-01 ~]# kubectl get cm,pod -o wide
NAME                         DATA   AGE
configmap/cm1-config         0      152m
configmap/kube-root-ca.crt   1      3d3h
configmap/log-config         1      10mNAME                            READY   STATUS    RESTARTS   AGE     IP               NODE          NOMINATED NODE   READINESS GATES
pod/my-nginx-77cdddc657-6kbsz   1/1     Running   0          7m26s   1.244.154.200   k8s-node-01   <none>           <none># 查找對應信息
[root@k8s-master-01 ~]# kubectl exec -it my-nginx-77cdddc657-6kbsz /bin/bash -- cat /etc/config/log_level
INFO
  • 修改 ConfigMap 配置,修改 log_level 的值為 DEBUG 等待大概 30 秒鐘時間,再次查看環境變量的值。

# 修改ConfigMap配置
[root@k8s-master-01 ~]# kubectl edit configmap log-config
:%s/INFO/DEBUG/g[root@k8s-master-01 ~]# kubectl exec -it my-nginx-77cdddc657-6kbsz /bin/bash -- cat /etc/config/log_level
DEBUG
1.3.1.4 ConfigMap 更新后滾動更新 Pod

更新ConfigMap目前并不會觸發相關 Pod 的滾動更新,可以通過修改 pod annotations 的方式強制觸發滾動更新。這個例子里我們在 .spec.template.metadata.annotations中添加 version/config,每次通過修改 version/config 來觸發滾動更新。

[root@k8s-master-01 ~]#  kubectl patch deployment my-nginx --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "20240525" }}}}}'
1.3.1.5 解決deployment 擴容引發服務配置不一致
  • 運維層面

  1. 重啟 Deployment: 使用 kubectl rollout restart deployment 命令可以觸發 Deployment 控制器去滾動更新 Pods。這將導致舊的 Pods 被逐漸替換為新的 Pods,新的 Pods 將掛載最新的 ConfigMap。

    kubectl rollout restart deployment <deployment-name>
  2. 重建 Pods: 通過刪除現有的 Pods,可以觸發 Deployment 控制器根據最新的配置重新創建 Pods。這可以通過 kubectl delete pod 命令實現。

    kubectl delete pod <pod-name>

    或者,您可以使用標簽選擇器來刪除所有匹配的 Pods:

    kubectl delete pods -l app=my-nginx
  • 應用程序層面

    • 配置熱加載: 應用程序需要能夠檢測到配置文件的變化,并在不重啟服務的情況下重新加載配置。這通常涉及到在應用程序中實現一個監聽器,當檢測到 ConfigMap 中的文件發生變化時,觸發配置的重新加載。

    • 使用環境變量: 另一種方法是將 ConfigMap 中的值作為環境變量掛載到 Pod 中。這樣,應用程序可以在啟動時讀取這些環境變量,而不需要關心文件系統的變化。

    • 使用 Init 容器: 在 Pod 中使用 Init 容器來處理配置文件。Init 容器在應用程序容器啟動之前運行,可以用來下載或生成配置文件,然后將它們存儲在 Pod 的共享卷中。

    • 使用 ConfigMap 觸發器: 某些應用程序或平臺可能支持 ConfigMap 觸發器,當 ConfigMap 更新時,這些觸發器可以通知應用程序進行相應的操作。

    • 使用自定義的 Operator: 開發一個自定義的 Operator 來管理應用程序的配置。Operator 可以監控 ConfigMap 的變化,并根據這些變化自動更新應用程序的配置。

1.3.1.6 ConfigMap 錯誤排查和故障處理方法
  • 檢查 ConfigMap 是否存在: 使用 kubectl get configmap <configmap-name> -n <namespace> 命令來確認 ConfigMap 是否已經創建。

  • 檢查 Pod 是否正確引用 ConfigMap

    • 檢查 Pod 的 YAML 文件,確保 spec.volumes 中包含了對 ConfigMap 的引用。

    • 使用 kubectl describe pod <pod-name> -n <namespace> 命令查看 Pod 的詳細信息,以確定是否正確引用了 ConfigMap。

  • 檢查 ConfigMap 的數據是否正確

    • 確保 ConfigMap 中的數據是正確的。

    • 使用 kubectl get configmap <configmap-name> -n <namespace> -o yaml 命令查看 ConfigMap 的詳細信息。

  • 檢查容器中的環境變量和配置文件

    • 使用 kubectl exec -it <pod-name> -n <namespace> -- /bin/sh 命令進入容器。

    • 在容器內部,使用 env 命令查看環境變量,或者直接查看配置文件的內容。

  • 檢查 ConfigMap 的權限和安全性

    • 如果 ConfigMap 包含敏感信息,確保使用 Kubernetes 的 RBAC 功能來限制訪問權限。

    • 使用 kubectl get rolebindings -n <namespace>kubectl get roles -n <namespace> 命令來檢查權限設置。

  • 使用 Kubernetes 的日志記錄和監控功能

    • 使用 kubectl logs <pod-name> -n <namespace> 命令查看容器的日志信息。

    • 使用 Kubernetes 的監控工具來監控 ConfigMap 和相關資源的狀態。

1.3.2 Secret

  • 在 Kubernetes 中,Secret 對象確實是用來存儲敏感信息的一種資源例如密碼、秘鑰、證書等等。它與 ConfigMap 類似,但設計目的不同。

1.3.2.1 Secret有三種類型
  • Opaque

    • 這種類型的 Secret 用于存儲少量的敏感數據,如密碼、令牌或密鑰。

    • 數據以 Base64 編碼格式存儲,這意味著雖然數據在存儲時被編碼,但仍然可以通過 Base64 解碼來查看原始數據,因此安全性相對較低。

  • Service Account

    • 這種類型的 Secret 通常用于服務賬戶(ServiceAccount),它們由 Kubernetes 自動創建和管理。

    • 服務賬戶的 Secret 包含訪問 Kubernetes API 所需的認證信息,如 API 令牌。

    • 這些 Secret 會自動掛載到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目錄中,供 Pod 內的應用程序使用。

  • kubernetes.io/dockerconfigjson

    • 這種類型的 Secret 用于存儲私有 Docker 注冊表(registry)的認證信息。

    • 當需要從私有 registry 拉取鏡像時,可以使用這種 Secret 來提供認證信息。

    • 可以通過在 Pod 的 spec 中指定 imagePullSecrets 來引用這些 Secret,以便 Kubernetes 能夠訪問私有 registry。

1.3.2.2 Service Account類型
  • Service Account 是 Kubernetes 中的一個對象,它為運行在集群中的 Pod 提供了一種安全的方式來訪問 Kubernetes API。Service Account 與普通用戶賬戶類似,但它是自動管理的,并且通常與特定的服務或應用程序相關聯,而不是與個人用戶相關聯。

# serviceaccout創建時Kubernetes會雙認創建對M的secret,對應的secret會自動掛載到Pod
[root@k8s-master-01 ~]# kubectl exec -it my-nginx-55b7dc67f-6tzzd -- ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt  namespace  token# 每個namespace下有一個名為defau1t的默認的ServiceAccount對象
[root@k8s-master-01 ~]# kubectl get sa
NAME      SECRETS   AGE
default   0         3d3h
[root@k8s-master-01 ~]# kubectl get sa -n test
NAME      SECRETS   AGE
default   0         3h21m# serviceAccount里有一個名為Tokens的可以作為Volume一樣被Mount到Pod里的secret,當Pod啟動時這個secret會被自動Mount到Pod的指定目錄下,用來協助完成Pod中的進程訪問API server時的身份鑒權過程
[root@k8s-master-01 ~]# kubectl get pod my-nginx-55b7dc67f-6tzzd -o yaml
spec:containers:- image: nginx:1.17.1imagePullPolicy: IfNotPresentname: my-nginxports:- containerPort: 80protocol: TCPresources: {}terminationMessagePath: /dev/termination-logterminationMessagePolicy: FilevolumeMounts:- mountPath: /etc/configname: config-volume- mountPath: /var/run/secrets/kubernetes.io/serviceaccountname: kube-api-access-mvpssreadOnly: true
1.3.2.3 Opaque類型
  • Opaque 類型的數據是一個 map 類型,要求value是base64編碼。

  • 手動創建base64加密

[root@k8s-master-01 ~]# echo -n 'admin' | base64
YWRtaW4=
[root@k8s-master-01 ~]# echo -n 'kxy20021003' | base64
a3h5MjAwMjEwMDM=
  • 解密

[root@k8s-master-01 ~]# echo 'a3h5MjAwMjEwMDM=' | base64 --decode
kxy20021003

這里需要注意的是,像這樣創建的 Secret 對象,它里面的內容僅僅是經過了轉碼,而并沒有被加密。在真正的生產環境中,你需要在 Kubernetes 中開啟 Secret 的加密插件,增強數據的安全性。

1.3.2.4 kubernetes.io/dockerconfigjson類型
  • 用來創建用戶docker registry認證的Secret,直接使用kubectl create命令創建即可

[root@k8s-master-01 ~]# kubectl create secret docker-registry myregistry \
--docker-server=DOCKER_SERVER \
--docker-username=DOCKER_USER \
--docker-password=DOCKER_PASSWORD \
--docker-email=DOCKER_EMAIL[root@k8s-master-01 ~]# kubectl get secret
NAME         TYPE                             DATA   AGE
myregistry   kubernetes.io/dockerconfigjson   1      37s
  • kubectl create secret 是創建新 Secret 的命令。

  • docker-registry 是 Secret 的類型,指定了這是一個用于 Docker registry 的認證信息。

  • myregistry 是要創建的 Secret 的名稱。

  • --docker-server 后面應跟 Docker registry 的服務器地址,例如 https://index.docker.io/v1/

  • --docker-username 后面應跟 Docker registry 的用戶名。

  • --docker-password 后面應跟 Docker registry 的密碼。

  • --docker-email 后面應跟 Docker registry 的用戶郵箱。

1.3.2.5 Secret創建及使用方法
  • 方式一: kubectl create secret 命令

[root@k8s-master-01 ~]# kubectl create secret --help
Create a secret with specified type.A docker-registry type secret is for accessing a container registry.A generic type secret indicate an Opaque secret type.A tls type secret holds TLS certificate and its associated key.Available Commands:docker-registry   Create a secret for use with a Docker registrygeneric           Create a secret from a local file, directory, or literal valuetls               Create a TLS secretUsage:kubectl create secret (docker-registry | generic | tls) [options]Use "kubectl create secret <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).
  • kubectl create secret:這是創建 Secret 的基本命令。

  • (docker-registry | generic | tls):這表示創建 Secret 時需要指定一個類型。Kubernetes 支持三種類型的 Secret:

    • docker-registry:用于訪問 Docker 容器注冊表的認證信息。

    • generic:通用類型的 Secret,用于存儲少量的敏感數據,如密碼或密鑰。

    • tls:用于存儲 TLS 證書及其關聯的私鑰。

  • [options]:創建不同類型的 Secret 時,可能需要提供一些選項或參數,比如認證信息、文件路徑、證書詳情等。

  • Available Commands:列出了與 kubectl create secret 相關的可用子命令。

  • Usage:顯示了如何使用 kubectl create secret 命令的示例格式。

  • Use "kubectl create secret <command> --help":提示用戶如果想要獲取某個特定子命令的更多信息,可以使用 <command> --help 來查看幫助信息。

  • Use "kubectl options":提示用戶如果想要查看所有 kubectl 命令的全局選項,可以使用 kubectl options 命令。

# generic子命令可以通過本地文件、目錄或者literal(鍵值對)
[root@k8s-master-01 ~]# echo admin > username.txt
[root@k8s-master-01 ~]# echo 1f2d1e2e67df > passwd.txt
[root@k8s-master-01 ~]# kubectl create secret generic user --from-file=./username.txt
secret/user created
[root@k8s-master-01 ~]# kubectl create secret generic pass --from-file=./passwd.txt
secret/pass created
[root@k8s-master-01 ~]# kubectl get secrets | grep Opaque
pass         Opaque                           1      16s
user         Opaque                           1      30s# 默認情況下key為文件名或者直接通過鍵值對創建
[root@k8s-master-01 ~]# kubectl delete secrets pass
secret "pass" deleted
[root@k8s-master-01 ~]# kubectl delete secrets user
secret "user" deleted
[root@k8s-master-01 ~]# kubectl create secret generic user --from-literal=username=admin
secret/user created
[root@k8s-master-01 ~]# kubectl create secret generic pass --from-literal=password=1f2d1e2e67df
secret/pass created
[root@k8s-master-01 ~]# kubectl get secrets | grep Opaque
pass         Opaque                           1      3s
user         Opaque                           1      7s
  • 通過yaml文件創建

[root@k8s-master-01 ~]# vim secret.yaml
apiVersion: v1
kind: Secret
metadata:name: mysecret
type: Opaque
data:user: YWRtaW4= ?# base64編碼的"user"pass: MWYyZDFlMmU2N2Rm ?# base64編碼的"pass123"
?
[root@k8s-master-01 ~]# kubectl apply -f secret.yaml 
secret/mysecret created
?
[root@k8s-master-01 ~]# kubectl get secret | grep Opaque
mysecret ? ? Opaque ? ? ? ? ? ? ? ? ? ? ? ? ? 2 ? ?  41s
1.3.2.6 Secret的使用
  • 方式一:通過Volume掛載的方式

[root@k8s-master-01 ~]# vim test-projected-volume.yaml
apiVersion: v1
kind: Pod
metadata:name: test-projected-volume
spec:containers:- name: test-secret-volumeimage: busybox:1.30args:- sleep- "86400"volumeMounts:- name: mysql-credmountPath: "/projected-volume"readOnly: truevolumes:- name: mysql-credprojected:sources:- secret:name: mysql-useritems:- key: userpath: user- secret:name: mysql-passitems:- key: passpath: pass[root@k8s-master-01 ~]# kubectl apply -f test-projected-volume.yaml 
?
# 當 Pod 變成 Running 狀態之后,我們再驗證一下這些 Secret 對象是不是已經在容器里了
[root@k8s-master-01 ~]# kubectl exec -it test-projected-volume -- /bin/sh
# ls /projected-volume/
user
pass
# cat /projected-volume/user
admin
# cat /projected-volume/pass
1f2d1e2e67df
  • 方法二:通過環境變量

[root@k8s-master-01 ~]# kubectl create secret generic mysecret --from-file=user=./username.txt --from-file=pass=passwd.txt
[root@k8s-master-01 ~]# vim pod-secret-env.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-secret-env
spec:containers:- name: myappimage: busyboxargs:- sleep- "86400"env:- name: SECRET_USERNAMEvalueFrom:secretKeyRef:name: mysecretkey: user- name: SECRET_PASSWORDvalueFrom:secretKeyRef:name: mysecretkey: passrestartPolicy: Never[root@k8s-master-01 ~]# kubectl get pod
NAME ? ? ? ? ? ? READY ? STATUS ?  RESTARTS ? AGE
pod-secret-env ? 1/1 ? ? Running ? 0 ? ? ? ?  40s
1.3.2.7 docker config json
  • 使用 Kuberctl 創建 docker registry 認證的 secret

# 創建格式
$ kubectl create secret docker-registry myregistrykey \
--docker-server=DOCKER_REGISTRY_SERVER \
--docker-username=DOCKER_USER \
--docker-password=DOCKER_PASSWORD \
--docker-email=DOCKER_EMAIL
?
?
  • 在創建 Pod 的時候,通過 imagePullSecrets 來引用剛創建的 myregistrykey

[root@k8s-master-01 ~]# kubectl create secret docker-registry myregistrykey \
--docker-server=hub.escape.com \
--docker-username=admin \
--docker-password=harbor123456 \
--docker-email=harbor@escape.com
?
[root@k8s-master-01 ~]# kubectl get secret
NAME ? ? ? ? ?  TYPE ? ? ? ? ? ? ? ? ? ? ? ? ? ? DATA ? AGE
myregistrykey ? kubernetes.io/dockerconfigjson ? 1 ? ?  3m25s

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/17086.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/17086.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/17086.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HTML-JavaWeb

目錄 1.標題排版 2.標題樣式 ?編輯 ?編輯 小結 3.超鏈接 4.正文排版 ?編輯?編輯?編輯5.正文布局 6.表格標簽 7.表單標簽 8.表單項標簽 1.標題排版 ● 圖片標簽 :< img> src:指定圖像的ur1(絕對路徑/相對路徑) width:圖像的寬度(像素/相對于父元素的百…

【AD21】文件的整理

當所有文件輸出完成后&#xff0c;需要對不同的文件去做一個整理&#xff0c;方便后續工作的交接。 在項目工程文件夾下新建名稱為BOM、SMT、PRJ、Gerber和DOC的文件夾。 BOM文件夾存放BOM表發給采購人員。SMT文件夾存放裝配圖文件和坐標文件發給貼片廠。PRJ文件夾存放工程文件…

C++基礎:多態

多態相關 多態繼承重寫父類的虛函數多態的體現,父類的引用指向子類對象的空間虛函數可以實現,也可以不實現,不實現必須要有初始值存在未定義的虛函數的類為抽象類.抽象類不能實例化對象;(animal父類不能實例化對象)如果父類中的函數非虛函數,則會調用父類中的函數//多態的體現…

匯凱金業:紙黃金和實物黃金的價格有什么區別

紙黃金和實物黃金的價格主要受到全球黃金市場行情的影響&#xff0c;二者的基礎價格并無太大差異&#xff0c;但在具體交易時&#xff0c;可能會存在一些價格上的區別&#xff0c;這些差異主要來自以下幾個方面&#xff1a; 交易費用與管理費&#xff1a;紙黃金交易通常需要支…

python xls格式轉為xlsx格式

python 兩個表格字段列名稱值&#xff0c;對比字段差異-CSDN博客 import os import win32com.clientdef xls_to_xlsx(file_path, excel):"""將指定的xls文件轉化為xlsx格式file_path: 文件路徑excel: 代表Excel應用程序"""# 打開原始文檔workbo…

【Java】IdentityHashMap 的使用場景

文章目錄 前言1. Druid 應用場景2. IdentityHashMap 特性3. IdentityHashMap 同步化4. IdentityHashMap 處理key為空值后記 前言 最近有興趣看一下 Druid 連接池怎么做連接管理的&#xff0c;看到一個類 IdentityHashMap &#xff0c;這里記錄一下使用場景。 1. Druid 應用場…

代碼隨想錄算法訓練營第36期DAY41

DAY41 動態規劃理論基礎 還差閆氏分析法沒學完。見B站收藏夾。 前兩題學習初始化方式就好vector<int> dp(N1); 509斐波那契數 簡單。 class Solution {public: int fib(int N) { if (N < 1) return N; int dp[2]; dp[0] 0; dp[…

plt畫圖中文亂碼

1、使用font_manager的FontProperties解決 通過FontProperties來設置字符及大小&#xff0c;來解決中文顯示的問題&#xff0c;代碼如下&#xff1a; import matplotlib import matplotlib.pyplot as pltpath "..\simsun.ttc"#改成你自己的文件路徑 font FontProp…

【物聯網實戰項目】STM32C8T6+esp8266/mqtt+dht11+onenet+uniapp

一、實物圖 前端uniapp效果圖&#xff08;實現與onenet同步更新數據&#xff09; 首先要確定接線圖和接線順序&#xff1a; 1、stm32c8t6開發板連接stlinkv2下載線 ST-LINK V2STM323.3V3.3VSWDIOSWIOSWCLKSWCLKGNDGND 2、ch340串口連接底座&#xff08;注意RXD和TXD的連接方式…

NSS題目練習4

[LitCTF 2023]1zjs 打開后是一個游戲&#xff0c;用dirsearch掃描&#xff0c;什么都沒發現 查看源代碼搜索flag&#xff0c;發現沒有什么用 搜索php&#xff0c;訪問 出現一堆符號&#xff0c;看樣子像是jother編碼 解碼得到flag&#xff0c;要刪掉[] [LitCTF 2023]Http pro …

37、Flink 的窗口函數(Window Functions)詳解

窗口函數&#xff08;Window Functions&#xff09; a&#xff09;概述 定義了 window assigner 之后&#xff0c;需要指定當窗口觸發之后&#xff0c;如何計算每個窗口中的數據&#xff0c; 即 window function。 窗口函數有三種&#xff1a;ReduceFunction、AggregateFunc…

嵌入式學習記錄5.27(c++基礎1)

目錄 一.C和C的區別 二.輸入輸出流類 2.1輸出cout 2.2輸入cin 三.命名空間 2.1使用命名空間中的標識符 2.2命名空間中聲明函數 2.3命名沖突問題 2.4匿名空間 2.5命名空間添加&#xff0c;嵌套&#xff0c;重命名 四.字符串的使用 4.1string類 4.2C風格和C風格字符串…

LeetCode27.移除元素

題目鏈接&#xff1a; 27. 移除元素 - 力扣&#xff08;LeetCode&#xff09; 思路分析&#xff1a;同樣屬于經典的雙指針移動問題&#xff0c;要掌握固定的思路即可。 算法分析&#xff1a;這個題目可以這樣處理&#xff0c;我們把所有非val 的元素都向前移動&#xff0c;把…

Java面試八股之線程池是怎么實現的

線程池是怎么實現的 線程池是一種基于池化技術的線程管理方式&#xff0c;通過預先創建一定數量的線程并保持在池中待命&#xff0c;從而在有任務來臨時能夠快速分配線程處理任務&#xff0c;而無需頻繁創建和銷毀線程&#xff0c;以此達到提升系統性能、減少資源消耗的目的。…

推薦《從零開始大模型開發與微調》

大模型是深度學習是當前AI和NLP研究與產業中最重要的方向之一。 本書用PyTorch 2.0作為學習大模型的基本框架&#xff0c;以ChatGLM為例詳細講解大模型的基本理論、算法、程序實現、應用實戰以及微調技術&#xff0c;為讀者揭示大模型開發技術。 《從零開始大模型開發與微調&…

兩個數組的交集-力扣

想到的解法是使用兩個哈希表&#xff0c;s1用來統計nums1中出現過的數字&#xff0c;然后遍歷nums2數組&#xff0c;當能夠在s1中查找到nums2的元素時&#xff0c;將這個元素添加到s2中&#xff0c;最后遍歷s2&#xff0c;將其中的元素添加到返回數組中。 但最開始寫時&#xf…

外星人存在與否......----小話外星人(1)

前一段時間&#xff0c;看了好多關于UFO、外星人、宇宙、遠古外星人的視頻和電子書&#xff0c;最后發現&#xff0c;這樣的東西還是不要看多為好&#xff0c;搞得好像這些是真的似的&#xff0c;有時睡覺會被意外驚醒&#xff0c;想多了...... 1、外星人存在嗎 不管有多少UFO的…

Windows10映射網絡驅動器之后不顯示映射盤

目錄 背景解決步驟1、按 Windows R 打開運行2、打開注冊表編輯器3、 System上新建-- DWORD(32bit)4、對新建的文件重命名5、將EnableLinkedConnections的數值改為16、退出注冊表編輯器&#xff0c;重啟系統。 知識擴展斷開連接備份注冊表 背景 目前有一臺NAS服務器,和一臺lin…

Vuex 頁面刷新數據丟失怎么解決

當Vuex中的數據在頁面刷新后丟失時&#xff0c;這通常是因為Vuex的狀態數據是保存在運行內存中的&#xff0c;頁面刷新會導致Vue實例重新加載&#xff0c;進而Vuex中的數據被重置為初始狀態。為了解決這個問題&#xff0c;可以采取以下幾種方法&#xff1a; 1. 使用瀏覽器的本…

工廠模式的三種實現方式

文章目錄 1.引出工廠模式具體需求 2.傳統模式1.類圖2.目錄結構3.pizzastore 用于設計pizza1.Pizza.java 抽象的Pizza類型2.CheesePizaa.java CheesePizaa3.GreekPizza.java GreekPizza 4.order 用于訂購和制作pizza1.OrderPizza.java 制作pizza2.PizzaStore.java 訂購pizza 5.優…