在開始介紹k8s持久化儲存前,我們有必要了解一下k8s的emptydir和hostpath、configmap以及secret的機制和用途。
0x00 Emptydir
EmptyDir是一個空目錄,他的生命週期和所屬的 Pod 是完全一致的,EmptyDir主要作用可以在同一 Pod 內的不同容器之間共享工作過程中產生的檔案。如果Pod配置了emptyDir型別Volume, Pod 被分配到Node上時候,會建立emptyDir,只要Pod執行在Node上,emptyDir都會存在(容器掛掉不會導致emptyDir丟失資料),但是如果Pod從Node上被刪除(Pod被刪除,或者Pod發生遷移),emptyDir也會被刪除,並且永久丟失。
# cat emptydir.yaml apiVersion: v1 kind: Pod metadata: name: busybox spec: containers: - name : busybox image: registry.fjhb.cn/busybox imagePullPolicy: IfNotPresent command: - sleep - "3600" volumeMounts: - mountPath: /busybox-data name: data volumes: - name: data emptyDir: {}
0x01 Hostpath
Hostpath會把宿主機上的指定卷載入到容器之中,如果 Pod 發生跨主機的重建,其內容就難保證了。這種卷一般和DaemonSet搭配使用。hostPath允許掛載Node上的檔案系統到Pod裡面去。如果Pod有需要使用Node上的東西,可以使用hostPath,不過不過建議使用,因為理論上Pod不應該感知Node的。
# cat hostpath.yaml apiVersion: v1 kind: Pod metadata: name: busybox spec: containers: - name : busybox image: registry.fjhb.cn/busybox imagePullPolicy: IfNotPresent command: - sleep - "3600" volumeMounts: - mountPath: /busybox-data name: data volumes: - hostPath: path: /tmp name: data
emptyDir和hostPat很多場景是無法滿足持久化需求,因為在Pod發生遷移的時候,資料都無法進行轉移的,這就需要分散式檔案系統的支援。
0x02 Configmap
映象使用的過程中,經常需要利用配置檔案、啟動指令碼等方式來影響容器的執行方式,如果僅有少量配置,我們可以使用環境變數的方式來進行配置。然而對於一些較為複雜的配置,k8s提供了configmap解決方案。
ConfigMap API資源儲存鍵/值對配置資料,這些資料可以在pods裡使用。
ConfigMap跟Secrets類似,但是ConfigMap可以更方便的處理不包含敏感資訊的字串。
當ConfigMap以資料卷的形式掛載進Pod的時,這時更新ConfigMap(或刪掉重建ConfigMap),Pod內掛載的配置資訊會熱更新。這時可以增加一些監測配置檔案變更的指令碼,然後reload對應服務
ConfigMap的API概念上來說是很簡單的。從資料角度來看,ConfigMap的型別只是鍵值組。應用可以從不同角度來配置。在一個pod裡面使用ConfigMap大致有三種方式:
1、命令列引數
2、環境變數
3、資料卷檔案
將變數做成configmap
將nginx配置檔案做成configmap
[root@vm1 ~]# cat nginx.conf user nginx; worker_processes auto; error_log /etc/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; server_tokens off; access_log /usr/share/nginx/html/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; include /etc/nginx/default.d/*.conf; location / { } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } }
# kubectl create configmap nginxconfig --from-file nginx.conf # kubectl get configmap # kubectl get configmap -o yaml
在rc配置檔案中使用configmap
# cat nginx-rc-configmap.yaml apiVersion: v1 kind: ReplicationController metadata: name: nginx labels: name: nginx spec: replicas: 2 selector: name: nginx template: metadata: labels: name: nginx spec: containers: - name: nginx image: docker.io/nginx volumeMounts: - name: nginx-etc mountPath: /etc/nginx/nginx.conf subPath: nginx.conf ports: - containerPort: 80 volumes: - name: nginx-etc configMap: name: nginxconfig items: - key: nginx.conf path: nginx.conf
# kubectl create -f nginx-rc-configmap.yaml
configmap的資訊實際是儲存在etcd中的,可以使用kubectl edit configmap xxx 來對configmap進行修改
# etcdctl ls /registry/configmaps/default # etcdctl get /registry/configmaps/default/nginxconfig
0x03 Secret
Kubemetes提供了Secret來處理敏感資料,比如密碼、Token和金鑰,相比於直接將敏感資料配置在Pod的定義或者映象中,Secret提供了更加安全的機制(Base64加密),防止資料洩露。Secret的建立是獨立於Pod的,以資料卷的形式掛載到Pod中,Secret的資料將以檔案的形式儲存,容器通過讀取檔案可以獲取需要的資料。
目前Secret的型別有3種:
Opaque(default): 任意字串
kubernetes.io/service-account-token: 作用於ServiceAccount
kubernetes.io/dockercfg: 作用於Docker registry,使用者下載docker映象認證使用
secert的具體配置在前文serviceaccount中已經介紹過了,本文不再贅述。
下面我們來介紹一下k8s的持久化儲存方案,目前k8s支援的儲存方案主要如下:
分散式檔案系統:NFS/GlusterFS/CephFS
公有云儲存方案:AWS/GCE/Auzre
0x04 Nfs儲存方案
NFS 是Network File System的縮寫,即網路檔案系統。Kubernetes中通過簡單地配置就可以掛載NFS到Pod中,而NFS中的資料是可以永久儲存的,同時NFS支援同時寫操作。
4.1 首先安裝nfs
# yum -y install nfs-util* # cat /etc/exports /home 192.168.115.0/24(rw,sync,no_root_squash) # systemctl start rpcbind # systemctl start nfs # showmount -e 127.0.0.1 Export list for 127.0.0.1: /home 192.168.115.0/24
4.2 使用pod直接掛載nfs
要保證叢集內所有的node節點都可以掛載nfs
# cat nfs.yaml apiVersion: v1 kind: Pod metadata: name: busybox spec: containers: - name : busybox image: registry.fjhb.cn/busybox imagePullPolicy: IfNotPresent command: - sleep - "3600" volumeMounts: - mountPath: /busybox-nfsdata name: nfsdata volumes: - name: nfsdata nfs: server: 192.168.115.6 path: /home
4.3 使用PV和PVC
在實際的使用中,我們通常會將各儲存劃分成PV,然後和PVC繫結給pod使用。
PV:PersistentVolume
PVC:PersistentVolumeClaim
# PV和PVC的生命週期: 供應準備:通過叢集外的儲存系統或者公有云儲存方案來提供儲存持久化支援。 靜態提供:管理員手動建立多個PV,供PVC使用。 動態提供:動態建立PVC特定的PV,並繫結。 繫結:使用者建立pvc並指定需要的資源和訪問模式。在找到可用pv之前,pvc會保持未繫結狀態。 使用:使用者可在pod中像使用volume一樣使用pvc。 釋放:使用者刪除pvc來回收儲存資源,pv將變成“released”狀態。由於還保留著之前的資料,這些資料需要根據不同的策略來處理,否則這些儲存資源無法被其他pvc使用。 回收(Reclaiming):pv可以設定三種回收策略:保留(Retain),回收(Recycle)和刪除(Delete) 保留策略:允許人工處理保留的資料。 刪除策略:將刪除pv和外部關聯的儲存資源,需要外掛支援。 回收策略:將執行清除操作,之後可以被新的pvc使用,需要外掛支援。 # PV卷階段狀態: Available – 資源尚未被PVC使用 Bound – 卷已經被繫結到PVC了 Released – PVC被刪除,PV卷處於釋放狀態,但未被叢集回收。 Failed – PV卷自動回收失敗 # PV卷的訪問模式 ReadWriteOnce – 單node的讀寫 ReadOnlyMany – 多node的只讀 ReadWriteMany – 多node的讀寫
建立pv與pvc
# cat nfs-pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-nfs-001 spec: capacity: storage: 5Gi accessModes: - ReadWriteMany nfs: path: /home server: 192.168.115.6 persistentVolumeReclaimPolicy: Recycle
# cat nfs-pvc.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nfs-data spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi
在PVC繫結PV時通常根據兩個條件來繫結,一個是儲存的大小,另一個就是訪問模式。
在rc檔案中使用PVC
# cat nginx-rc-configmap.yaml apiVersion: v1 kind: ReplicationController metadata: name: nginx labels: name: nginx spec: replicas: 2 selector: name: nginx template: metadata: labels: name: nginx spec: containers: - name: nginx image: docker.io/nginx volumeMounts: - name: nginx-data mountPath: /usr/share/nginx/html - name: nginx-etc mountPath: /etc/nginx/nginx.conf subPath: nginx.conf ports: - containerPort: 80 volumes: - name: nginx-data persistentVolumeClaim: claimName: nfs-data - name: nginx-etc configMap: name: nginxconfig items: - key: nginx.conf path: nginx.conf
參考