K8S学习笔记之持久化存储
K8S学习笔记之持久化存储
持久化存储概念介绍
【官方】https://kubernetes.io/zh/docs/concepts/storage/volumes
将容器内数据卷挂载到宿主机上,实现数据存储,避免因为容器销毁导致的数据丢失
我们想要使用存储卷,需要经历如下步骤
1、定义pod的volume,这个volume指明它要关联到哪个存储上的
2、在容器中要使用volumemounts挂载对应的存储
【执行命令查看-常用的持久化方式】
kubectl explain pods.spec.volumes
- List item
- emptyDir
- hostPath
- nfs
- persistentVolumeClaim
- glusterfs
- cephfs
- configMap
- secret
EmptyDir
Pod临时挂载到宿主机上的目录,容器删除,目录删除,文件删除,不会恢复。
vim pod-emptydir.yaml
## 查看本机临时目录存在的位置
# 查看pod调度到哪个节点
kubectl get pods -o wide | grep empty
# 查看pod的uid
kubectl get pods pod-empty -o yaml | grep uid
# 登录到对应主机上
tree /var/lib/kubelet/pods/38d60544-8591-468d-b70d-2a66df3a1cf6
apiVersion: v1
kind: Pod
metadata:
name: pod-empty
spec:
containers:
- name: container-empty
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
/var/lib/kubelet/pods/49d73a17-5615-44bc-aed0-ce88520e0572
├── containers
│ └── container-empty
│ └── af926089
├── etc-hosts
├── plugins
│ └── kubernetes.io~empty-dir
│ ├── cache-volume
│ │ └── ready
│ └── wrapped_default-token-dr4nt
│ └── ready
└── volumes
├── kubernetes.io~empty-dir
│ └── cache-volume
└── kubernetes.io~secret
└── default-token-dr4nt
├── ca.crt -> ..data/ca.crt
├── namespace -> ..data/namespace
└── token -> ..data/token
11 directories, 7 files
# 挂载目录
/var/lib/kubelet/pods/49d73a17-5615-44bc-aed0-ce88520e0572/volumes/kubernetes.io~empty-dir/cache-volume/
# 在此目录下写入一个文件hello.txt
# 进入容器查看/cache目录下,是否也有相同文件
kubectl exec -it pod-empty -- /bin/sh
HostPath
指Pod挂载宿主机上的目录或文件。容器删除目录依旧存在,数据依旧存在,重新挂载数据恢复。
【缺点】单节点:pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失
vim pod-hostpath.yaml
# 查看pod调度到那一台机器上了
kubectl get pods -o wide
# 去对应机器下查看目录/data-test,并创建文件
# 进入指定容器,查看创建的文件是否也在容器内
kubectl exec -it test-hostpath -c test-nginx -- /bin/bash
kubectl exec -it test-hostpath -c test-tomcat -- /bin/bash
apiVersion: v1
kind: Pod
metadata:
name: test-hostpath
spec:
containers:
- name: test-nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /test-nginx
name: test-volume
- name: test-tomcat
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /test-tomcat
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data-test
type: DirectoryOrCreate
NFS或者分布式存储
[分布式存储方案] nfs,cephfs,glusterfs
数据可以在Pod之间共享,但是NFS单节点如果宕机了,数据也就丢失了,所以需要使用分布式存储
搭建NFS单节点服务器,详见:https://blog.csdn.net/AlgebraFly/article/details/125991396
分布式存储,待定
【注意】使用NFS挂载操作需要在工作节点物理机上安装
nfs-utils
vim pod-nfs.yaml
# 字段解释
path: /data/volumes #nfs的共享目录
server:10.11.2.58 #master1机器的ip
# 进入NFS挂载目录/data/volumes,写一个测试文件
vim index.html
# 请求一下查看结果
curl <ip>:<80>
# 进入容器中查看文件
kubectl exec -it test-nfs -- /bin/bash
cd /usr/share/nginx/html && ls
apiVersion: v1
kind: Pod
metadata:
name: test-nfs
spec:
containers:
- name: test-nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: nfs-volumes
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-volumes
nfs:
path: /data/volumes
server: 10.11.2.58
PV和PVC(重点)
概念
PersistentVolume
(PV)是群集中的一块存储,由管理员配置或使用存储类动态配置。 它是集群中的资源,就像pod是k8s集群资源一样。 PV是容量插件,如Volumes,其生命周期独立于使用PV的任何单个pod。
PersistentVolumeClaim
(PVC)是一个持久化存储卷,我们在创建pod时可以定义这个类型的存储卷。 它类似于一个pod。 Pod消耗节点资源,PVC消耗PV资源。
## 注意
1.PV是群集中的资源。 PVC是对这些资源的请求。
2.PV被释放之后,不可再重复使用,无论是何种形式的操作,直到他被删除为止
【pv的供应方式】
1.静态
集群管理员创建了许多PV。它们包含可供群集用户使用的实际存储的详细信息。它们存在于Kubernetes API中,可供使用。
2.动态
当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,群集可能会尝试为PVC专门动态配置卷。此配置基于StorageClasses,PVC必须请求存储类,管理员必须创建并配置该类,以便进行动态配置。
【绑定】
用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态
【使用】
a)需要找一个存储服务器,把它划分成多个存储空间;
b)k8s管理员可以把这些存储空间定义成多个pv;
c)在pod中使用pvc类型的存储卷之前需要先创建pvc,通过定义需要使用的pv的大小和对应的访问模式,找到合适的pv;
d)pvc被创建之后,就可以当成存储卷来使用了,我们在定义pod时就可以使用这个pvc的存储卷;
e)pvc和pv它们是一一对应的关系,pv如果被pvc绑定了,就不能被其他pvc使用了;
f)我们在创建pvc的时候,应该确保和底下的pv能绑定,如果没有合适的pv,那么pvc就会处于pending状态。
【回收策略】
当Pod删除后,Pod与PVC就绑定解除了,PVC绑定的PV卷也解除了绑定,此时PV的处理方式有:
Retain 保留(当删除pvc的时候,pv仍然存在,处于released状态,但是它不能被其他pvc绑定使用)
Recycle 回收(不推荐使用,1.15可能被废弃了)
Delete 删除(删除pvc时即会从Kubernetes中移除PV)
资源清单
## 【1】创建NFS共享目录
mkdir /data/volume_test/v{1,2,3,4,5,6,7,8,9,10} -p
vim /etc/exports
/data/volumes 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v1 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v2 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v3 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v4 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v5 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v6 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v7 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v8 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v9 10.11.2.0/24(rw,no_root_squash)
/data/volume_test/v10 10.11.2.0/24(rw,no_root_squash)
# 重新加载配置
exportfs -arv
## 【2】PV 资源清单文件
vim pv-test.yaml
kubectl apply -f pv-test.yaml
kubectl get pv
# 初始化完成后,状态是Available
apiVersion: v1
kind: PersistentVolume
metadata:
name: v1
spec:
capacity:
storage: 1Gi #pv的存储空间容量
accessModes: ["ReadWriteOnce"]
nfs:
path: /data/volume_test/v1 #把nfs的存储空间创建成pv
server: 10.11.2.58 #nfs服务器的地址
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v2
spec:
capacity:
storage: 20Mi
accessModes: ["ReadWriteMany"]
nfs:
path: /data/volume_test/v2
server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v3
spec:
capacity:
storage: 30Mi
accessModes: ["ReadOnlyMany"]
nfs:
path: /data/volume_test/v3
server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v4
spec:
capacity:
storage: 40Mi
accessModes: ["ReadWriteOnce","ReadWriteMany"]
nfs:
path: /data/volume_test/v4
server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v5
spec:
capacity:
storage: 50Mi
accessModes: ["ReadWriteOnce","ReadWriteMany"]
nfs:
path: /data/volume_test/v5
server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v6
spec:
capacity:
storage: 60Mi
accessModes: ["ReadWriteOnce","ReadWriteMany"]
nfs:
path: /data/volume_test/v6
server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v7
spec:
capacity:
storage: 70Mi
accessModes: ["ReadWriteOnce","ReadWriteMany"]
nfs:
path: /data/volume_test/v7
server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v8
spec:
capacity:
storage: 80Mi
accessModes: ["ReadWriteOnce","ReadWriteMany"]
nfs:
path: /data/volume_test/v8
server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v9
spec:
capacity:
storage: 90Mi
accessModes: ["ReadWriteOnce","ReadWriteMany"]
nfs:
path: /data/volume_test/v9
server: 10.11.2.58
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v10
spec:
capacity:
storage: 100Mi
accessModes: ["ReadWriteOnce","ReadWriteMany"]
nfs:
path: /data/volume_test/v10
server: 10.11.2.58
## 字段解释
# kubectl explain pv.spec.nfs
path <string> -required-
readOnly <boolean>
server <string> -required-
# kubectl explain pv.spec.capacity
设置PV容量
# kubectl explain pv.spec.accessModes
设置PV访问模式
ReadWriteOnce
卷可以被一个节点以读写方式挂载。也允许运行在同一节点上的多个 Pod 访问卷。
ReadOnlyMany
卷可以被多个节点以只读方式挂载。
ReadWriteMany
卷可以被多个节点以读写方式挂载。
ReadWriteOncePod
卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用ReadWriteOncePod 访问模式。
## 【3】PVC 资源清单文件
vim pvc-test.yaml
kubectl apply -f pvc-test.yaml
kubectl get pv
kubectl get pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 20M
## 字段解释
# kubectl explain pvc.spec
accessModes <[]string> # 同PV的accessModes
dataSource <Object>
resources <Object> # 要求挂载的PV的资源最小值
selector <Object>
storageClassName <string>
volumeMode <string>
volumeName <string>
# kubectl explain pvc.spec.resources
limits <map[string]string> #类似于Pod资源的限制
requests <map[string]string>
## 【4】创建Pod,挂载PVC
vim pod-test-pvc.yaml
kubectl apply -f pod-test-pvc.yaml
# 测试文件挂载
# 创建一个index.html
apiVersion: v1
kind: Pod
metadata:
name: pod-pvc
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nginx-html
mountPath: /usr/share/nginx/html
volumes:
- name: nginx-html
persistentVolumeClaim:
claimName: my-pvc
## 注意
1、我们每次创建pvc的时候,需要事先有划分好的pv,这样可能不方便,那么可以在创建pvc的时候直接动态创建一个pv这个存储类,pv事先是不存在的
2、pvc和pv绑定,如果使用默认的回收策略retain,那么删除pvc之后,pv会处于released状态,我们想要继续使用这个pv,需要手动删除pv,kubectl delete pv pv_name,删除pv,不会删除pv里的数据,当我们重新创建pvc时还会和这个最匹配的pv绑定,数据还是原来数据,不会丢失。
存储类(解决PV
依存关系问题)
概念
Kubernetes
提供一种自动创建PV的机制,叫StorageClass
,它的作用就是创建PV的模板。k8s集群管理员通过创建Storageclass
可以动态生成一个存储卷pv供k8s pvc
使用。
## 注意
1. storageClass是一个K8S资源类型,它依赖于provisioner(供应商)
2. provisioner是一个自动生成PV的插件,它以将以一个k8s-pod资源的形式部署在k8s集群中,提供PVC使用
3. provisioner有多重形式,可以根据自己情况自行选择
4. Kubernetes就能够根据用户提交的PVC,找到对应的StorageClass,然后Kubernetes就会调用 StorageClass声明的存储插件,创建出需要的PV。
资源清单
## StorageClass会定义以下两部分:
1、PV的属性 ,比如存储的大小、类型等;
2、创建这种PV需要使用到的存储插件,比如Ceph、NFS等
# kubectl explain storageclass
allowVolumeExpansion <boolean> # 允许扩展卷
allowedTopologies <[]Object>
apiVersion <string>
kind <string>
metadata <Object>
mountOptions <[]string> # 如果卷插件不支持挂载选项,却指定了挂载选项,则制备操作会失败。
parameters <map[string]string>
provisioner <string> -required- # 创建PV的供应商(需自己配置搭建)
reclaimPolicy <string> # 回收策略
volumeBindingMode <string> # Immediate 模式表示一旦创建了 PVC 也就完成了卷绑定和动态制备。
# kubectl explain storageclass.reclaimPolicy
指定PV的回收策略,Delete 或者 Retain,默认是Delete
# kubectl explain storageclass.allowVolumeExpansion
允许扩展卷(仅允许扩展卷,不允许缩小)
将此功能设置为true时,允许用户通过编辑相应的 PVC 对象来调整卷大小。
安装nfs provisioner
provisioner有多种,其作用是按照pvc
既定的资源配置和StorageClass
创建PV,以供PVC绑定使用,下面展示以NFS为存储器的nfs-client
的配置使用
# 【1】到Github下载安装包镜像,上传到工作节点,并解压
docker load -i nfs-subdir-external-provisioner.tar.gz
# 创建sa账号
vim serviceaccount.yaml
kubectl apply -f serviceaccount.yaml
# 赋予sa账户角色权限
kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
## 【2】配置NFS
mkdir /data/nfs_pro -p
#把/data/nfs_pro变成nfs共享的目录
vim /etc/exports
/data/nfs_pro 192.168.40.0/24(rw,no_root_squash)
exportfs -arv
# 【3】创建nfs-provisioner资源
vim nfs-deployment.yaml
kubectl apply -f nfs-deployment.yaml
kubectl get pods
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-provisioner
spec:
selector:
matchLabels:
app: nfs-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-provisioner
spec:
serviceAccount: nfs-provisioner
containers:
- name: nfs-provisioner
image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: example.com/nfs
- name: NFS_SERVER
value: 10.11.2.58
- name: NFS_PATH
value: /data/nfs_pro
volumes:
- name: nfs-client-root
nfs:
server: 10.11.2.58
path: /data/nfs_pro
创建使用
## 【1】创建storageclass,动态供给pv
vim nfs-storageClass.yaml
kubectl get storageclass
## 结果展示
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs example.com/nfs Delete Immediate false 74m
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: nfs
provisioner: example.com/nfs
## 【2】创建pvc,通过storageclass动态生成pv
vim pvc-sc.yaml
kubectl get pvc
kubectl get pv
## 结果展示
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-claim1 Bound pvc-47e1e175-f940-43bb-bf30-2ec1b0b7556e 30M RWX nfs 69m
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-47e1e175-f940-43bb-bf30-2ec1b0b7556e 30M RWX Delete Bound default/test-claim1 nfs 69m
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-claim1
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 100Mi
storageClassName: nfs
## 【3】创建pod,挂载storageclass动态生成的pvc
vim pod-pvc-sc.yaml
## 创建文件验证文件挂载
apiVersion: v1
kind: Pod
metadata:
name: pod-pvc-sc
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-pvc
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: test-claim1
更多推荐
所有评论(0)