K8S之持久化存储

持久化存储

在K8S中部署的应用都是以pod容器的形式运行的,假如部署数据库服务 例如:MySQL、Redis等,需要对产生的数据做备份。如果pod不挂载数据卷,那pod被删除或重启后这些数据会随之消失,想要长久的保留这些数据就要用到pod数据持久化存储。

支持的持久化存储类型

查看K8S支持哪些存储

bash 复制代码
kubectl explain pods.spec.volumes



常用的如下:

  • emptyDir :临时性存储卷类型
  • hostPath :在节点上使用本地磁盘进行数据存储
  • nfs:通过 Network File System(网络文件系统)共享文件系统进行数据存储
  • persistentVolumeClaim:持久卷声明,是K8S的一个特定类型的存储资源
  • glusterfs:通过分布式文件系统GlusterFS进行数据存储
  • cephfs:通过分布式文件系统Ceph进行数据存储
  • configMap: 通过ConfigMap资源存储应用程序的配置文件
  • secret:通过Secret资源存储应用程序的机密信息

本篇对前三种进行展开介绍,并例举实践中的使用

EmptyDir

emptyDir类型的Volume是在Pod分配到Node上时被创建,K8S会在Node上自动分配一个目录,无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。

emptyDir 主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。

实践

创建一个pod,挂载临时目录emptyDir

bash 复制代码
vim emptydir.yaml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-empty
spec:
  containers:
  - name: container-empty
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: cache-volume  # 匹配volumes.name。把卷挂载到容器里
      mountPath: /cache   # 挂载到容器里的目录下 
  volumes:
  - name: cache-volume 
    emptyDir:{}

更新资源清单文件

bash 复制代码
kubectl apply -f emptydir.yaml
bash 复制代码
kubectl describe pods pod-empty

查看分配到Node上的临时目录存在的位置

1、查看pod的uid

bash 复制代码
kubectl get pods pod-empty -o yaml | grep uid

uid: adff4bf3-62ac-41fe-9b25-abcae1c8598a

2、查看pod调度到哪个节点

bash 复制代码
kubectl get pods -o wide | grep empty

3、登录到k8s-node1上

ps. 安装tree 方便看目录结构

bash 复制代码
 yum install tree -y

根据 uid 看目录

bash 复制代码
tree /var/lib/kubelet/pods/adff4bf3-62ac-41fe-9b25-abcae1c8598a

由上可知,临时目录在本地的/var/lib/kubelet/pods/adff4bf3-62ac-41fe-9b25-abcae1c8598a/volumes/kubernetes.io~empty-dir/cache-volume/下

pod删了,临时目录也没了

bash 复制代码
kubectl delete -f emptydir.yaml

该类型可使用的场景:测试数据

HostPath

hostPath Volume是指Pod挂载宿主机上的目录或文件。 hostPath Volume使得容器可以使用宿主机的文件系统进行存储,hostpath(宿主机路径):节点级别的存储卷 ,在pod被删除,这个存储卷还是存在的,不会被删除。

所以只要同一个pod被调度到同一个节点上来,在pod被删除重新被调度到这个节点之后,对应的数据依然是存在的。

查看hostPath存储卷的用法

bash 复制代码
kubectl explain pods.spec.volumes.hostPath

hostPath的type类型:

实践

创建一个pod,挂载hostPath存储卷

bash 复制代码
vim hostpath.yaml 
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-hostpath
spec:
  containers:
  - name: container-nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: hostpath-volume
      mountPath: /hostpath-nginx
  - name: container-tomcat
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: hostpath-volume
      mountPath: /hostpath-tomcat
  volumes:
  - name: hostpath-volume
    hostPath:
      path: /data-hostpath  # 必须字段,指定存储目录
      type: DirectoryOrCreate # 表示本地有/data-hostpath目录,就用本地的,本地没有就会在pod调度到的节点自动创建一个

更新资源清单文件

bash 复制代码
kubectl apply -f hostpath.yaml

查看pod调度到了哪个物理节点

bash 复制代码
kubectl get pods -o wide | grep hostpath

由上面可以知道pod调度到了k8s-node1上,登录到k8s-node1机器,查看是否在这台机器创建了存储目录

bash 复制代码
ll /data-hostpath/

上面可以看到已经创建了存储目录/data-hostpath,这个【/data-hostpath】会作为pod的持久化存储目录

在k8s-node1上的/data-hostpath下创建一个目录

bash 复制代码
cd /data-hostpath

mkdir aa

测试存储卷是否可以正常使用

1、登录到nginx容器

bash 复制代码
kubectl exec -it pod-hostpath -c container-nginx -- /bin/bash 
bash 复制代码
cd /hostpath-nginx/ 

/hostpath-nginx/目录存在,说明已经把宿主机目录挂载到了容器里

bash 复制代码
ls

2、登录到tomcat容器

bash 复制代码
kubectl exec -it pod-hostpath -c container-tomcat -- /bin/bash
bash 复制代码
cd /hostpath-tomcat/

/hostpath-tomcat/目录存在,说明已经把宿主机目录挂载到了容器里

bash 复制代码
ls

通过上面测试可以看到,同一个pod里的 container-nginx 和 container-tomcat 这两个容器是共享存储卷的

删除pod,指定调度到另外的node上

bash 复制代码
kubectl delete -f hostpath.yaml
bash 复制代码
vim hostpath.yaml 
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-hostpath
spec:
  nodeName: k8s-node2 # 指定调度到node2节点上
  containers:
  - name: container-nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: hostpath-volume
      mountPath: /hostpath-nginx
  - name: container-tomcat
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: hostpath-volume
      mountPath: /hostpath-tomcat
  volumes:
  - name: hostpath-volume 
    hostPath: 
      path: /data-hostpath
      type: DirectoryOrCreate

更新资源清单文件

bash 复制代码
kubectl apply -f hostpath.yaml

看容器里的目录,登录到nginx容器

bash 复制代码
kubectl exec -it pod-hostpath -c container-nginx -- /bin/bash 
bash 复制代码
cd /hostpath-nginx 
bash 复制代码
ls

aa 文件不在了

hostpath存储卷缺点:单节点,pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失

NFS

以上 emptyDir 和 hostPath 是两种本地存储解决方案,仅适用于单个节点上的容器。如果需要在多个Pod或多节点之间共享持久化存储,可使用NFS。

NFS存储允许多个Pod从网络共享中读取数据,还支持高可用性配置,可以使用多个NFS服务器来提供容错和负载均衡。此外NFS还支持更高级的存储管理功能,如快照和备份,以及可配置的访问控制策略。

实践

1、搭建NFS服务

以k8s的控制节点(k8s-master1)作为NFS服务端

bash 复制代码
yum install nfs-utils -y

该命令的主要作用是使用yum包管理器自动安装nfs-utils软件包,以支持NFS协议的功能。

2、在宿主机创建NFS需要的共享目录,作为NFS服务端

bash 复制代码
mkdir /data/volumes -pv 

-p表示:创建目录的过程中,如果父级不存在,则自动创建父目录。

-v表示:可向用户展示更多信息,例如显示执行mkdir创建了哪些目录等。

3、配置NFS共享服务器上的/data/volumes目录

执行以下命令启动NFS

bash 复制代码
systemctl start nfs

编辑配置NFS服务访问的目录/data/volumes的访问权限

bash 复制代码
vim /etc/exports
powershell 复制代码
# 允许任何客户端挂载
/data/volumes *(rw,no_root_squash)

参数说明:

  • /data/volumes:要共享的目录
  • '**':允许哪些客户端挂载NFS共享的目录,"*"表示允许任何能访问NFS服务的网段客户端挂载NFS共享的目录
  • rw 该主机对该共享目录有读写权限
  • no_root_squash 登入:用户具有根目录的完全管理访问权限

4、使NFS配置生效

执行以下命令使NFS配置生效

bash 复制代码
exportfs -arv
bash 复制代码
service nfs restart

查看nfs是否启动成功

bash 复制代码
systemctl enable nfs

查看nfs是否启动成功

bash 复制代码
systemctl status nfs

Active: active

看到nfs是active,说明nfs正常启动了

5、k8s-node2和k8s-node1上也安装nfs驱动

bash 复制代码
yum install nfs-utils -y

systemctl enable nfs --now

在k8s-node1上手动挂载

bash 复制代码
mkdir /test 
bash 复制代码
mount 192.168.40.182:/data/volumes /test/

以上【192.168.40.182】为服务端(k8s-master1)的IP

bash 复制代码
df -h

nfs可以被正常挂载

手动卸载

bash 复制代码
umount /test

6、创建Pod,挂载NFS共享出来的目录

bash 复制代码
vim nfs.yaml 
yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-test
spec:
  replicas: 3
  selector:
    matchLabels:
      storage: nfs
  template: 
    metadata:
      labels:
         storage: nfs
    spec:
      containers:
      - name: container-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts:
        - name: nfs-volumes
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nfs-volumes
        nfs:
          server: 192.168.40.182 # 安装nfs服务的地址
          path: /data/volumes    # nfs的共享目录

更新资源清单文件

bash 复制代码
kubectl apply -f nfs.yaml

查看pod是否创建成功

bash 复制代码
kubectl get pods -owide

登录到nfs服务器,在共享目录创建一个index.html

bash 复制代码
cd /data/volumes/

vim index.html 

请求pod,看结果

通过上面可以看到,在共享目录创建的index.html已经被pod挂载了

登录到pod验证下

bash 复制代码
kubectl exec -it nfs-test-65db89988d-4hs7h  -- /bin/bash
bash 复制代码
cat /usr/share/nginx/html/index.html 

上面说明挂载nfs存储卷成功了,nfs支持多个客户端挂载,可以创建多个pod,挂载同一个nfs服务器共享出来的目录;

但是nfs如果宕机了,数据也就丢失了,想要高可用可使用分布式存储,常见的分布式存储有glusterfs和cephfs。

相关推荐
为什么这亚子1 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
ZHOU西口3 小时前
微服务实战系列之玩转Docker(十八)
分布式·docker·云原生·架构·数据安全·etcd·rbac
牛角上的男孩4 小时前
Istio Gateway发布服务
云原生·gateway·istio
JuiceFS5 小时前
好未来:多云环境下基于 JuiceFS 建设低运维模型仓库
运维·云原生
景天科技苑6 小时前
【云原生开发】K8S多集群资源管理平台架构设计
云原生·容器·kubernetes·k8s·云原生开发·k8s管理系统
wclass-zhengge6 小时前
K8S篇(基本介绍)
云原生·容器·kubernetes
颜淡慕潇6 小时前
【K8S问题系列 |1 】Kubernetes 中 NodePort 类型的 Service 无法访问【已解决】
后端·云原生·容器·kubernetes·问题解决
川石课堂软件测试8 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
昌sit!15 小时前
K8S node节点没有相应的pod镜像运行故障处理办法
云原生·容器·kubernetes
A ?Charis17 小时前
Gitlab-runner running on Kubernetes - hostAliases
容器·kubernetes·gitlab