9. kubernetes 存儲卷
[TOC]
本文基于馬哥的docker和k8s視頻總結(jié), 在此致謝馬哥.
k8s上可以用的三種存儲卷類型
emptyDir
-
(1)
emptyDir
只在節(jié)點本地使用, 且pod刪除時存儲卷會隨之被刪除, 用于當臨時目錄或緩存, 此存儲卷可使用節(jié)點的內(nèi)存一個存儲卷可以在同一個pod內(nèi)的多個容器間共享:
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: default
labels:
app: myapp
tier: frontend
annotations:
magedu.com/create-by: "cluster admin"
spec:
containers:
- name: myapp
image: nginx
ports:
- name: http
containerPort: 80
volumeMounts:
- name: html # 掛載名為html的存儲卷 (需要使用下面存在的volumes)
mountPath: /usr/share/nginx/html/ # 掛載點路徑
# 其他參數(shù): readOnly, subPath, mountPropagation
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
volumeMounts: # 掛載是容器級別的, 哪個容器使用, 哪個容器就要掛載, 不掛載時訪問不到數(shù)據(jù)
- name: html
mountPath: /data/ # 注意兩個容器的掛載路徑可以不同
command:
- "/bin/sh"
- "-c"
- "while true; done echo $(date) >> /data/index.html; sleep 10; done"
volumes:
- name: html
emptyDir: {} # 可以指定為空, 表示使用默認值(使用硬盤空間, 不限制使用大小)
# medium 指定使用的存儲卷設(shè)備, 空字符串代表使用硬盤, Memory代表使用內(nèi)存
# sizeLimit 指定使用的存儲卷大小
kubectl apply -f vol-demo1.yml
kubectl exec -it pod-demo -c busybox -- /bin/sh
/ # echo $(date) >> /data/index.html
kubectl exec -it pod-demo -c myapp -- /bin/sh
/ # cat /data/web/html/index.html # 可以在另一個容器中看到共享的數(shù)據(jù)
kubect get pods -o wide # 查看pod的IP
curl pod_IP
hostPath
- (2)
hostPath
宿主機路徑, 將pod上的存儲卷與宿主機的目錄做映射
apiVersion: v1
kind: Pod
metadata:
name: pod-hostpath-vol
namespace: default
spec:
containers:
- name: myapp
image: nginx:1.14:alpine
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
hostPath:
path: /data/pod/volume1/
type: DirectoryOrCreate # 目錄不存在時自動創(chuàng)建
mkdir -p /data/pod/volume1/
echo "test hostPath" >> /data/pod/volume1/index.html # 只要節(jié)點上有相同內(nèi)容, 則pod宕了也沒關(guān)系
kubectl apply -f pod-hostpath-vol.yml
以nfs
為例
- (3) 共享存儲, 支持
awsElasticBlockStore, azureDisk, cephfs, glusterfs, gitRepo, nfs, iscsi, rbd
等
# node1(ip為192.168.200.200)作為nfs服務(wù)的提供者
yum -y install nfs-utils # 作為nfs共享存儲的節(jié)點需要安裝此包
mkdir /data/volumes -pv
vi /etc/exports
/data/volumes 192.168.0.0/16(rw,no_root_squash)
systemctl start nfs
# node2(ip為192.168.200.201)作為nfs服務(wù)的使用者
yum -y install nfs-utils
mount -t nfs 192.168.200.200:/data/volumes /mnt # 一定要進行掛載測試
umount /mnt
vi pod-nfs-vol.yml
apiVersion: v1
kind: Pod
metadata:
name: pod-nfs-vol
namespace: default
spec:
containers:
- name: myapp
image: nginx:1.14:alpine
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
nfs:
path: /data/pod/volumes
server:
192.168.200.201
readOnly: false # 默認就是false, 即rw
kubectl apply -f pod-nfs-vol.yml
注: nfs
支持多客戶端同時掛載, 支持多客戶端的多路讀寫訪問
pvc和pv
pvc
和pv
也是標準的k8s資源
kubectl explain pods.spec.volumes.persistentVolumeClaim
claimName # 必要選項, 指明已創(chuàng)建好的pvc名稱
readOnly # default false
kubectl explain pvc.spec
accessModes <[]string># 訪問模型, 這里不可隨便定義, 有些設(shè)備可能不支持某種模型
ReadWriteOnce # 單路讀寫, 可簡寫為RWO
ReadOnlyMany # 多路只讀, 可簡寫為ROM
ReadWriteMany # 多路讀寫, 可簡寫為RWM
resources # 資源限制, 對應(yīng)的存儲空間至少需要的大小
selecotr # pv可以有標簽, pvc上使用selector時表示必須使用哪個pv建立關(guān)聯(lián)關(guān)系, 不加selector時自動選擇最佳匹配
volumeMode # 后端存儲卷的模式, 可以不指定
volumeName # 卷名稱, 綁定某個pv, 可以不指定
kubectl explain pv.spec
accessModes <[]string># 訪問模型, 這里不可隨便定義, 有些設(shè)備可能不支持某種模型
ReadWriteOnce # 單路讀寫, 可簡寫為RWO
ReadOnlyMany # 多路只讀, 可簡寫為ROM
ReadWriteMany # 多路讀寫, 可簡寫為RWM
capacity <map[string]string> # 定義存儲空間大小, 支持E, P, T, G, M, K, m和Ei, Pi, Ti, Gi, Mi, Ki, mi
stroage
創(chuàng)建
pvc
后會去找系統(tǒng)上合適的pv
進行綁定, 如果沒有則掛起(pending), 例如pvc
需要使用30G, 而pv
現(xiàn)在最大創(chuàng)建的容量只有20G, 不滿足條件, 操作被掛起, 直到滿足條件pv
和pvc
是一一對應(yīng)的關(guān)系, 如果某個pv
被pvc
占用了, 則這個pv
不能再被其他pvc
占用, 但一個pvc
可以被多個pod
訪問
# node1(ip為192.168.200.200)作為nfs服務(wù)的提供者
yum -y install nfs-utils # 作為nfs共享存儲的節(jié)點需要安裝此包
mkdir /data/volumes -pv
vi /etc/exports
/data/volumes/v1 192.168.0.0/16(rw,no_root_squash)
/data/volumes/v2 192.168.0.0/16(rw,no_root_squash)
/data/volumes/v3 192.168.0.0/16(rw,no_root_squash)
/data/volumes/v4 192.168.0.0/16(rw,no_root_squash)
/data/volumes/v5 192.168.0.0/16(rw,no_root_squash)
exportfs -arv
showmount -e
# node2(ip為192.168.200.201)作為nfs服務(wù)的使用者
yum -y install nfs-utils
mount -t nfs 192.168.200.200:/data/volumes /mnt # 一定要進行掛載測試
umount /mnt
vi pod-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001 # 定義pv時千萬不要定義namespace, 因為pv是集群級別的, 不屬于namespace
labels:
name: pv001
spec:
nfs:
path: /data/volumes/v1
server: 192.168.200.200
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/volumes/v2
server: 192.168.200.200
accessModes: ["ReadWriteMany"]
capacity:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/volumes/v3
server: 192.168.200.200
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 20Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
labels:
name: pv004
spec:
nfs:
path: /data/volumes/v4
server: 192.168.200.200
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv005
labels:
name: pv005
spec:
nfs:
path: /data/volumes/v5
server: 192.168.200.200
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 10Gi
---
kubectl apply -f pod-pv.yml
kubectl get pv
# RECLAIM POLICY 回收策略, 某個pvc綁定了pv, 當pvc被刪除后pv內(nèi)還有數(shù)據(jù), 該如何處理?
# Retain 保留數(shù)據(jù)
# Recycle 回收
# Delete 刪除
vi pod-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
namespace: default
spec:
accessModes: ["ReadWriteMany"] # pvc的accessModes必須是pv的子集
resources:
requests: # 要求有多大的存儲空間
storage: 6Gi
---
apiVersion: v1
kind: Pod
metadata:
name: pod-vol-pvc
namespace: default
spec:
containers:
- name: myapp
image: nginx:1.14:alpine
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc
kubeclt apply -f pod-pvc.yml
kubectl get pv # 可查看STATUS, 是否被Bound
kubectl get pvc
特殊類型的存儲卷: 用于制作數(shù)據(jù)中心
配置容器化應(yīng)用的方式有以下幾種:
- (1) 自定義命令行參數(shù)
command
args: []
- (2) 把配置文件直接放入基本鏡像并重構(gòu)
- (3) 環(huán)境變量
- (3.1) Could Native的應(yīng)用程序一般可直接通過環(huán)境變量加載配置
- 通過
entrypoint
腳本來預(yù)處理變量為配置文件中配置信息
- (4) 存儲卷
- (4.1)
configmap
: 明文 - (4.2)
secret
: 密文
- (4.1)
configmap
# 創(chuàng)建configmap的方式:
# 第一種: 直接直接用命令行的方式給定
kubectl create configmap nginx-config --from-literal=nginx_port=80 --from-ilteral=server_name=myapp.magedu.com
# --from-literal=key=value 直接用命令行的方式給定
kubectl get cm
kubectl describe cm nginx-config
# 可在顯示信息中看到Data (定義的key和value)
# 第二種: 配置文件給定
mkdir configmap
vi www.conf
server {
server_name myapp.magedu.com;
listen 80;
root /data/web/html/;
}
kubectl create configmap nginx-www --from-file=www=./www.conf
# 按這種方式指定, key=www, value=www.conf的文件內(nèi)容
kubectl create configmap nginx-www --from-file=./www.conf
# 按照這種方式指定, key=文件名(此例中為www.conf), value=www.conf的文件內(nèi)容
kubectl descirbe cm nginx-www
vi pod-configmap.yml
- 通過
環(huán)境變量
的方式向pod傳數(shù)據(jù):
apiVersion: v1
kind: Pod
metadata:
name: pod-demo-1
namespace: default
labels:
app: myapp
tier: frontend
annotations:
alexti/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: nginx:1.14-alpine
ports:
- name: http
containerPort: 80
env:
- name: NGINX_SERVER_PORT # 變量最好使用下劃線
valueFrom:
configMapKeyRef: # 引用configmap獲取數(shù)據(jù)
name: nginx-config
key: nginx_port # nginx_port的值會傳遞給變量NGINX_SERVER_PORT
optional: true # 如果configmap不存在或者configmap中定義的變量沒有你需要使用的key, pod將無法被啟動, 可以將這一項的值設(shè)置為true, 表示此configmap可以在定義完之后再創(chuàng)建
- name: NGINX_SERVER_NAME
valueFrom:
configMapKeyRef:
name: nginx-conf
key: server_name
optional: true
kubectl apply -f pod-configmap.yml
kubectl exec -it pod pod-demo-1 -- /bin/sh
/ # printenv # 可查看到自定義的變量: NGINX_SERVER_PORT和NGINX_SERVER_NAME
kubectl edit cm nginx-config # 支持編輯
-
通過
存儲卷
的方式向pod傳數(shù)據(jù):
方法一, 使用命令行
創(chuàng)建的configmap
:
vi pod-configmap2.yml
apiVersion: v1
kind: Pod
metadata:
name: pod-demo-2
namespace: default
labels:
app: myapp
tier: frontend
annotations:
alexti/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: nginx:1.14-alpine
ports:
- name: http
containerPort: 80
volumeMounts:
- name: nginxconf
mountPath: /etc/nginx/config.d/
readOnly: true # 不允許容器修改配置文件
volumes:
- name: nginxconf
configMap: # 存儲卷類型為configMap
name: nginx-config
kubectl apply -f pod-configmap2.yml
kubectl exec -it pod pod-demo-2 -- /bin/sh
/ # cd /etc/nginx/config.d/
/ # ls # 可以查看到兩個文件, 文件名為nginx_port和server_name
kubectl edit cm nginx-config
# 將nginx_port從80改為8080
kubectl exec -it pod pod-demo-2 -- /bin/sh
/ # cat /etc/nginx/config/nginx_port # 此時可以查看到結(jié)果為修改后的8080
方法二, 使用創(chuàng)建的配置文件
:
vi pod-configmap3.yml
apiVersion: v1
kind: Pod
metadata:
name: pod-demo-3
namespace: default
labels:
app: myapp
tier: frontend
annotations:
alexti/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: nginx:1.14-alpine
ports:
- name: http
containerPort: 80
volumeMounts:
- name: nginxconf
mountPath: /etc/nginx/conf.d/
readOnly: true # 不允許容器修改配置文件
volumes:
- name: nginxconf
configMap: # 存儲卷類型為configMap
name: nginx-www
# 指定items可以只掛載部分鍵值而不是全部
kubecgtl apply -f pod-configmap3.yml
kubectl get pods
kuebctl exec -it pod-demo-3 -- /bin/sh
/ # cat /etc/nginx/conf.d/www.conf # 可看到使用配置文件定義的配置
/ # nginx -T # 查看nginx加載的配置
kubectl edit cm nginx-www
# 將某個參數(shù)修改, 例如listen的值改為8080, 等待一段時間后會發(fā)現(xiàn)pod內(nèi)的配置會隨之修改為8080, 但此時配置還未生效, 需要重載配置文件
/ # nginx -s reload
secret
kubectl create secret --help
# 有三種類型
generic # 通用的secret, 一般用于保存密碼
tls # 保存私鑰和證書
docker-registry # 保存docker-registry認證信息, 連接私有倉庫時拉取鏡像時使用
kubectl create secret generic mysql-root-password --form-literal=password=MyP@ss123
kubectl get secret
kubectl descirbe secret mysql-root-password # 會發(fā)現(xiàn)值不顯示
kubectl get secret mysql-root-password -o yaml
echo "經(jīng)base加密后的密碼" | base64 -d # 解碼, 可看到密碼源碼, 說明密碼安全性不佳
vi pod-secret-1.yml
apiVersion: v1
kind: Pod
metadata:
name: pod-demo-4
namespace: default
labels:
app: myapp
tier: frontend
annotations:
alexti/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: nginx:1.14-alpine
ports:
- name: http
containerPort: 80
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-root-password
key: password
optional: true
kubectl apply -f pod-secret-1.yml
kubectl exec -it pod-demo-4 -- printenv # 會發(fā)現(xiàn)傳入的MYSQL_ROOT_PASSWORD在會解密后通過環(huán)境變量的方式注入pod