一:k8s当中为什么需要持久化存储
在 k8s 中部署的应用都是以 pod 容器的形式运行的,假如我们部署 MySQL、Redis 等数据库,需要对这些数据库产生的数据做备份。因为 Pod 是有生命周期的,如果 pod 不挂载数据卷,那 pod 被删除或重启后这些数据会随之消失,如果想要长久的保留这些数据就要用到 pod 数据持久化存储。
二:临时性存储empdir
EmptyDir 是一种 Kubernetes 中的存储卷。临时性的。它可以在 Pod 的生命周期内持久保存数据。
当容器使用 EmptyDir 卷时,Kubernetes 会在节点上为其分配一个空目录。在 Pod 的生命周期内,这个目录将一直存在,可以在容器之间共享。Pod没了就没了。
1:实战
常见一个Pod挂载一个目录,测试删除Pod之后,数据是否会丢失。结果:是的。
2:资源清单
apiVersion: v1
kind: Pod
metadata:
name: pod-empty # Pod名称
spec:
containers:
- name: pod-empty # 容器名称
image: nginx # 容器使用的镜像
# ========== 容器内挂载存储卷的位置(重点) ==========
volumeMounts:
- name: empty-volume # 要挂载的存储卷名称(必须和下方volumes.name一致)
mountPath: /usr/share/nginx/html # 存储卷挂载到容器内的路径(容器内可见)
# ========== 存储卷定义的位置(重点) ==========
volumes:
- name: empty-volume # 存储卷名称(自定义,需和上面volumeMounts.name匹配)
emptyDir: {} # 定义EmptyDir类型存储卷:
# 1. 存储卷实际物理位置:Pod所在宿主机的 /var/lib/kubelet/pods/<PodUID>/volumes/kubernetes.io~empty-dir/empty-volume
# 2. 生命周期:与Pod绑定,Pod删除/迁移则数据丢失
# 3. 默认存储介质:宿主机的磁盘(也可指定medium: Memory使用内存)
3:结论
empdir临时性数据卷,pod删除就没了。
如何查看Pod的uid
kubelet get pods pod-empty -o yaml
Node上数据卷的位置
/var/lib/kubelet/pods/uid
宿主机和容器内是双写的,宿主机改了,容器内就变了, 容器内改了,宿主机就变了。
三:hostPath
hostPath 是 Kubernetes 中一种简单的持久性存储卷类型,它可将节点的文件系统中的文件或目录直接挂载到 Pod 中。
该卷类型通过在 Pod 中指定主机路径和容器中所需挂载该路径的位置来工作。它适用于需要访问节点中文件系统上的目录或文件的应用程序。
需要注意的是,使用 hostPath 存储卷需要非常小心,因为它会直接暴露节点的文件系统。另外,当 Pod 迁移到其他节点时,这个目录映射不会跟随迁移而改变,因此可能会影响到应用程序的可移植性。
1:实战
目标:创建一个 Pod 挂载工作节点的 /data1 目录,如果目录不存在就创建。测试删除 Pod,目录的数据是否会丢失。
2:资源清单
apiVersion: v1
kind: Pod
metadata:
name: hostpath # Pod名称
spec:
containers:
- name: hostpath # 容器名称
image: nginx # 容器镜像
# ========== 容器内挂载数据卷的核心配置 ==========
volumeMounts:
- name: test-volume # 要挂载的数据卷名称(必须和下方volumes.name一致)
mountPath: /test-nginx # 数据卷挂载到容器内的路径,容器读写该路径即操作宿主机/data1目录
# ========== 宿主机路径数据卷的定义配置 ==========
volumes:
- name: test-volume # 数据卷名称(自定义,需和volumeMounts.name匹配)
hostPath:
path: /data1 # 宿主机上的物理路径(核心:Pod会挂载节点的这个目录)
type: DirectoryOrCreate # 路径类型:若宿主机/data1不存在则自动创建;存在则直接使用
# type可选值说明:
# DirectoryOrCreate:目录不存在则创建,存在则使用(本次测试核心配置)
# Directory:必须存在已有的目录,否则Pod启动失败
# FileOrCreate:文件不存在则创建,存在则使用
# File:必须存在已有的文件,否则Pod启动失败
3:结论
Pod删除之后,节点上的hostpath也不会删除。适合做日志存储,
但是Pod漂移之后,就看不到这个宿主机上的日志了。
四:nfs
上小节说的 hostPath 存储,存在单点故障,pod 挂载 hostPath 时,只有调度到同一个节点,数据才不会丢失。那可以使用 nfs 作为持久化存储可以避免这些问题。
NFS(Network File System)是一种分布式文件系统协议,允许计算机之间共享文件和目录。在 Kubernetes 之中,可以使用 NFS 作为一种持久性存储卷类型,使得多个 Pod 之间可以共享相同的数据。
在使用 NFS 存储卷时,需要先安装 NFS 服务器,并创建一个共享目录。在创建 Pod 时,可以直接将 NFS 共享的目录挂载到容器内。
NFS也是不够安全的,存在单点故障,可以采用分布式文件存储来实现存储高可用。
注意:k8s左右工作节点都需要安装nfs
2:资源
apiVersion: v1
kind: Pod
metadata:
name: test-nfs # Pod名称
spec:
containers:
- name: test-nfs # 容器名称
image: nginx # 容器使用的镜像
# ========== 容器内挂载NFS数据卷的核心配置 ==========
volumeMounts:
- name: test-volume # 要挂载的数据卷名称(必须和下方volumes.name一致)
mountPath: /test-nginx # NFS共享目录挂载到容器内的路径
# 容器对该路径的读写,都会同步到NFS服务器的/data/volumes目录
# ========== NFS数据卷的定义配置(核心) ==========
volumes:
- name: test-volume # 数据卷名称(自定义,需和volumeMounts.name匹配)
nfs:
path: /data/volumes # NFS服务器上的共享目录路径(需提前在NFS服务端配置好)
server: 192.168.128.11 # NFS服务器的IP地址(集群内所有节点需能访问该IP)
# 补充说明:
# 1. 使用前需确保K8s节点已安装nfs-utils客户端(否则Pod挂载失败)
# 2. NFS数据卷支持ReadWriteMany(多节点多Pod同时读写),无单点故障
# 3. Pod删除/迁移后,数据仍保存在NFS服务器,不会丢失
3:结论
Pod删除的时候,数据不删除,Pod漂移的时候,数据也还在。NFS是单点服务。可能会不稳定。