K8S中的数据存储之基本存储

基本存储类型

EmptyDir

  • 描述:当 Pod 被调度到节点上时,Kubernetes 会为 Pod 创建一个空目录,所有在该 Pod 中的容器都可以访问这个目录。
  • 特点
    • 生命周期与 Pod 绑定,Pod 删除时,数据也会丢失。
    • 适用于临时存储需求,如缓存或临时计算数据。
    • 支持多种存储类型(如 tmpfs)可以根据需求选择。

HostPath

  • 描述:将主机节点上的文件或目录挂载到 Pod 中的容器内。
  • 特点
    • 允许 Pod 访问宿主机的文件系统。
    • 数据存储在节点上,如果 Pod 被调度到不同的节点上,数据不可用。
    • 适用于单节点集群或测试环境中,不推荐在生产环境中使用。
    • 存在潜在的安全风险,因为容器可以访问宿主机的文件系统。

NFS

  • 描述:网络存储解决方案将存储分布到多个节点或机器,Kubernetes 可以使用这些存储系统作为 PV 后端。
  • 特点
    • 提供集群级别的共享存储,支持多个 Pod 挂载相同的卷。
    • 适用于需要共享数据的应用,如分布式数据库。
    • 支持高可用性、数据复制、故障恢复等功能。
    • 需要额外的配置和管理,通常适用于大型分布式应用或企业级场景。

EmptyDir详解

EmptyDir 是一种轻量级的存储选项,用于 Pod 内部容器之间的数据共享或临时存储。下面是一些关于 EmptyDir 的补充信息:

  • 生命周期:EmptyDir 的生命周期与 Pod 绑定。当 Pod 被创建时,EmptyDir 被创建并挂载到 Pod 中所有需要它的容器上。当 Pod 被删除时,EmptyDir 及其内容也会被删除。

  • 使用场景

    • 临时存储:对于需要临时写入和读取数据,但不要求数据持久化的场景,如缓存或会话数据。

    • 容器间数据共享:当 Pod 中运行多个容器需要共享文件时,EmptyDir 可以作为一个共享存储空间。

    • 数据处理:在数据被处理并存储到更持久的存储解决方案之前,可以临时存储在 EmptyDir 中。

  • 性能:EmptyDir 存储的性能通常与宿主机的磁盘性能相当,因为它直接存储在宿主机上。

  • 限制:由于 EmptyDir 与 Pod 的生命周期绑定,因此它不适合存储需要跨 Pod 持久化的数据。此外,EmptyDir 不保证数据的备份或复制,所以在 Pod 重启或重建时数据可能会丢失。

  • 配置 :EmptyDir 可以通过 Pod 定义中的 spec.volumes 字段来配置,无需指定宿主机上的路径。

  • 安全性:EmptyDir 默认只对 Pod 内部的容器可见,提供了一定程度的隔离。

在一个Pod中准备两个容器nginx和busybox,然后声明一个Volume分别挂在到两个容器的目录中,然后nginx容器负责向Volume中写日志,busybox中通过命令将日志内容读到控制台。

bash 复制代码
[root@k8s-master ~]# vim volume-emptydir.yaml
[root@k8s-master ~]# kubectl apply -f volume-emptydir.yaml 
Error from server (NotFound): error when creating "volume-emptydir.yaml": namespaces "test" not found
[root@k8s-master ~]# kubectl create ns test
namespace/test created
[root@k8s-master ~]# kubectl apply -f volume-emptydir.yaml 
pod/volume-emptydir created
[root@k8s-master ~]# kubectl get pod -n test -o wide
NAME              READY   STATUS              RESTARTS   AGE   IP       NODE        NOMINATED NODE   READINESS GATES
volume-emptydir   0/2     ContainerCreating   0          35s   <none>   k8s-node1   <none>           <none>
[root@k8s-master ~]# kubectl get pod -n test -w
NAME              READY   STATUS              RESTARTS   AGE
volume-emptydir   0/2     ContainerCreating   0          40s
volume-emptydir   2/2     Running             0          56s
^C[root@k8s-master ~]# kubectl exec -it volume-emptydir -n test /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Defaulted container "nginx" out of: nginx, busybox
root@volume-emptydir:/# echo 'This is EmptyDir test' > /usr/share/nginx/html/index.html 
root@volume-emptydir:/# exit
exit
[root@k8s-master ~]# kubectl get pod -n test -o wide
NAME              READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
volume-emptydir   2/2     Running   0          80s   10.244.36.81   k8s-node1   <none>           <none>
[root@k8s-master ~]# curl 10.244.36.81
This is EmptyDir test
[root@k8s-master ~]# kubectl logs -f volume-emptydir -n test -c busybox 
10.244.235.192 - - [25/Jan/2025:09:39:19 +0000] "GET / HTTP/1.1" 200 22 "-" "curl/7.29.0" "-"
10.244.235.192 - - [25/Jan/2025:09:39:40 +0000] "GET / HTTP/1.1" 200 22 "-" "curl/7.29.0" "-"
10.244.235.192 - - [25/Jan/2025:09:39:41 +0000] "GET / HTTP/1.1" 200 22 "-" "curl/7.29.0" "-"

通过curl命令进行访问,可以看到访问成功的日志信息;

HostPath详解

  • EmptyDir中数据不会被持久化,它会随着Pod的结束而销毁,如果想简单的将数据持久化到主机中,可以选择HostPath。

  • HostPath就是将Node主机中一个实际目录挂在到Pod中,以供容器使用,这样的设计就可以保证Pod销毁了,但是数据依据可以存在于Node主机上。

    • 数据持久性 :与 EmptyDir 不同,HostPath 卷将 Node 主机上的一个目录挂载到 Pod 中,使得 Pod 内的容器可以访问和修改该目录上的文件。由于这些文件存储在 Node 主机上,因此即使 Pod 被删除,数据仍然可以在 Node 主机上保持。

    • 用途HostPath 适用于需要持久化数据的场景,例如数据库文件、配置文件等。然而,由于 HostPath 直接使用了 Node 主机的文件系统,可能会带来一些安全和管理上的挑战,例如权限管理、数据一致性等问题。

bash 复制代码
[root@k8s-master ~]#  vim volume-hostpath.yaml
[root@k8s-master ~]# kubectl apply -f volume-hostpath.yaml 
pod/volume-hostpath created
[root@k8s-master ~]#  kubectl get pod -n test -w
NAME              READY   STATUS    RESTARTS   AGE
volume-emptydir   2/2     Running   0          9m26s
volume-hostpath   2/2     Running   0          6s
^C[root@k8s-master ~]# kubectl describe pod volume-hostpath -n test
Name:         volume-hostpath
Namespace:    test
Priority:     0
Node:         k8s-node1/192.168.58.232
Start Time:   Sat, 25 Jan 2025 04:47:14 -0500
Labels:       <none>
Annotations:  cni.projectcalico.org/containerID: 12d55de1744ff89a73d0fb3c4f9cf45427847f3ca631f130147e2a41b9916c53
              cni.projectcalico.org/podIP: 10.244.36.82/32
              cni.projectcalico.org/podIPs: 10.244.36.82/32
Status:       Running
IP:           10.244.36.82
IPs:
  IP:  10.244.36.82
Containers:
  nginx:
    Container ID:   docker://c0c42dab2b85a9d336abcba543be34740ce44c19453d41435882cc4e356ea18e
    Image:          nginx:1.17.1
    Image ID:       docker-pullable://nginx@sha256:b4b9b3eee194703fc2fa8afa5b7510c77ae70cfba567af1376a573a967c03dbb
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sat, 25 Jan 2025 04:47:16 -0500
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/log/nginx from logs-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bqnr4 (ro)
  busybox:
    Container ID:  docker://ee04657f326faa26619d0ffe9acb277885aa792737aed9d3e343c570d17ff0a8
    Image:         busybox:1.30
    Image ID:      docker-pullable://busybox@sha256:4b6ad3a68d34da29bf7c8ccb5d355ba8b4babcad1f99798204e7abb43e54ee3d
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/sh
      -c
      tail -f /logs/access.log
    State:          Running
      Started:      Sat, 25 Jan 2025 04:47:16 -0500
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /logs from logs-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bqnr4 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  logs-volume:
    Type:          HostPath (bare host directory volume)
    Path:          /root/logs
    HostPathType:  DirectoryOrCreate
  kube-api-access-bqnr4:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  25s   default-scheduler  Successfully assigned test/volume-hostpath to k8s-node1
  Normal  Pulled     23s   kubelet            Container image "nginx:1.17.1" already present on machine
  Normal  Created    23s   kubelet            Created container nginx
  Normal  Started    23s   kubelet            Started container nginx
  Normal  Pulled     23s   kubelet            Container image "busybox:1.30" already present on machine
  Normal  Created    23s   kubelet            Created container busybox
  Normal  Started    23s   kubelet            Started container busybox
[root@k8s-master ~]#  kubectl get pod -n test -o wide
NAME              READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
volume-emptydir   2/2     Running   0          10m   10.244.36.81   k8s-node1   <none>           <none>
volume-hostpath   2/2     Running   0          98s   10.244.36.82   k8s-node1   <none>           <none>

describe中看的pod调度到node1节点,在master节点执行curl进行访问,到node1节点下查看是否存在/root/logs目录,并查看日志信息:

bash 复制代码
[root@k8s-node1 ~]# ll /root/logs/
total 4
-rw-r--r--. 1 root root 95 Jan 25 04:49 access.log
-rw-r--r--. 1 root root  0 Jan 25 04:47 error.log

[root@k8s-node1 ~]# tail -f /root/logs/access.log 
10.244.235.192 - - [25/Jan/2025:09:49:00 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
10.244.235.192 - - [25/Jan/2025:09:49:48 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

NFS

  • 虽然 HostPath 可以用于解决数据持久化的问题,但它并不适用于跨节点的数据共享和高可用性场景。一旦 Pod 从一个节点迁移到另一个节点,HostPath 卷中的数据就无法访问。这是因为 HostPath 卷依赖于特定节点上的文件系统,而不是一个独立的网络存储系统。

  • 为了解决这个问题,确保数据在节点迁移时仍然可用,通常推荐使用网络文件存储系统,如 NFS (Network File System) 或 CIFS (Common Internet File System)。这两种协议允许 Pod 访问远程存储系统上的数据,就好像它们是本地文件一样。

  • NFS 是一种网络文件系统协议,它允许客户端计算机访问服务器上的文件和目录,就像它们是本地文件一样。通过设置 NFS 服务器,您可以将 Pod 中的存储直接连接到 NFS 系统上。这样,即使 Pod 从一个节点迁移到另一个节点,只要网络连接正常,Pod 就可以继续访问数据。

需要在每个机器上都安装NFS

bash 复制代码
yum install nfs-utils -y
[root@k8s-master ~]# mkdir /nfstest
[root@k8s-master ~]# vim /etc/exports
[root@k8s-master ~]# systemctl restart rpcbind.service nfs-server.service

[root@k8s-master ~]# vim volume-nfs.yaml 
[root@k8s-master ~]# kubectl apply -f volume-nfs.yaml 
pod/volume-nfs created
[root@k8s-master ~]# kubectl get pod -n test -w 
NAME         READY   STATUS              RESTARTS   AGE
volume-nfs   0/2     ContainerCreating   0          2s
volume-nfs   0/2     ContainerCreating   0          3s
volume-nfs   2/2     Running             0          3s
^C[root@k8s-master ~]kubectl get pod -n test -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
volume-nfs   2/2     Running   0          16s   10.244.36.88   k8s-node1   <none>           <none>
[root@k8s-master ~]# cd /nfstest/
[root@k8s-master nfstest]# ll
total 4
-rw-r--r--. 1 root root 95 Jan 25 05:18 access.log
-rw-r--r--. 1 root root  0 Jan 25 05:18 error.log
[root@k8s-master nfstest]# tai -f access.log 
-bash: tai: command not found
[root@k8s-master nfstest]# tail -f access.log 
10.244.235.192 - - [25/Jan/2025:10:18:20 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
10.244.235.192 - - [25/Jan/2025:10:18:47 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

在node1和node2节点执行如下命令:

bash 复制代码
[root@k8s-node1 ~]# showmount -e 192.168.58.231
Export list for 192.168.58.231:
/nfstest 192.168.58.0/24

在master节点使用curl命令进行测试,查看master节点/nfstest目录下是否存在访问日志:

bash 复制代码
[root@k8s-master ~]# curl  10.244.36.88
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@k8s-master nfstest]# tail -f access.log 
10.244.235.192 - - [25/Jan/2025:10:18:20 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
10.244.235.192 - - [25/Jan/2025:10:18:47 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
相关推荐
陌上阳光8 小时前
docker搭建ray集群
docker·容器·ray
这就是佬们吗8 小时前
初识 docker [上]
java·开发语言·笔记·docker·容器
FJW0208149 小时前
负载均衡集群HAproxy
linux·服务器·云原生·负载均衡
BigBigHang9 小时前
【docker】DM8达梦数据库的docker-compose以及一些启动踩坑
数据库·docker·容器
云道轩9 小时前
使用Docker在Rocky Linux 9.5上在线部署LangFlow
linux·人工智能·docker·容器·langflow
伟大的大威9 小时前
Docker 部署 Supabase并连接
运维·docker·容器
杰克逊的日记10 小时前
k8s的csi对接GPFS
云原生·容器·kubernetes·存储·gpfs
岚天start10 小时前
云服务器以域名形式访问机房Kubernetes集群服务之解决方案
nginx·docker·kubernetes·kubesphere·解决方案·云服务器·机房
容器魔方14 小时前
「中科类脑」正式加入 Karmada 用户组!携手社区共建多集群生态
云原生·容器·云计算
终端行者14 小时前
k8s之ingress定义https访问方式
容器·https·kubernetes