K8S Pod 常见数据存储方案

 假设有如下三个节点的 K8S 集群:

k8s31master 是控制节点

k8s31node1、k8s31node2 是工作节点

容器运行时是 containerd

一、理论介绍

1.1、Volumes 卷

Kubernetes 的卷是 pod 的⼀个组成部分,因此像容器⼀样在 pod 的规范(pod.spec)中就定义了。它们不是独立的 Kubernetes 对象,也不能单独创建或删除。pod 中的所有容器都可以使用卷,但必须先将它挂载在每个需要访问它的容器中。在每个容器中,都可以在其文件系统的任意位置挂载卷。

通过上面的描述,我们知道了使用卷的两个步骤:

  1. 在 .spec.volumes 字段中设置为 Pod 提供的卷。
  2. 在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。

1.2、为什么需要? 

总结:

  1. 数据持久性。容器的文件在磁盘上是临时存放的,当容器崩溃重启或被删除时,数据也会随之丢失。
  2. 共享存储。多个容器之间共享文件数据。

1.3、常用卷类型

emptyDir、hostPath、nfs、persistentVolumeClaim、configMap、secret。

kubectl explain pod.spec.volumes

二、emptyDir 卷类型

  • emptyDir 类型的 Volumes 是在 Pod 被指派到某节点时被创建。
  • 就像其名称所表示的那样,emptyDir 卷最初是空的。
  • Kubernetes 会在节点上自动分配一个目录,因此无需指定节点上对应的目录文件。
  • 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会被永久删除。

2.1、实践

定义一个 Pod,里面有两个容器:一个 nginx,一个 alpine。

alpine 每隔3秒往容器目录 /data 生成一个 index.html。

nginx 读取这个 index.html 作为首页。

emptydir.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: emptydir-pod
spec:
  volumes:
  - name: sharedir
    emptyDir: {}
  containers:
  - name: html-generator
    image: alpine:latest  
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "while true; do echo \"您好,现在时间是 $(date)\" > /data/index.html; sleep 3; done"]
    volumeMounts:
    - name: sharedir
      mountPath: /data
  - name: nginx
    image: nginx:1.14.2
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: sharedir
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP
  • emptyDir: {} 表示这是一个空卷。
  • command: ["/bin/sh", "-c", "while true; do echo \"您好,现在时间是 $(date)\" > /data/index.html; sleep 3; done"] 表示容器启动的时候执行命令,该命令每隔3秒往 /data/index.html 打印当前系统时间。
  • date:这是一个用于显示或设置系统日期和时间的命令。当不带任何参数使用时,它会显示当前的日期和时间。
  • $(command):这是命令替换的语法,在 Shell 中用来获取命令执行的结果。这里的command 是指任何有效的命令。在本例中,就是 date 命令。Shell 会先运行括号内的命令,并将输出结果替换掉这个整个表达式。
  • 容器 html-generator 和容器 nginx 都挂载了相同的卷 sharedir。

  • 每隔3秒请求 Pod IP

 Pod IP 是 10.244.9.1 ; Pod 被调度到 node2。

2.2、查看本机临时目录

  • 查看 pod 的 uid
kubectl get pod emptydir-pod -oyaml | grep uid

  • 进入 node2 /var/lib/kubelet/pods/pod-uid/volumes 下

2.3、Pod 删除后消失

emptyDir 类型的卷只存在于 Pod 的生命周期,Pod 被删除后卷也随之消失。

kubectl delete -f emptydir.yaml

三、hostPath 卷类型

  • hostPath 允许将节点上的文件系统路径挂载到 Pod 中。
  • 当 Pod 被删除时,这个存储卷还是存在的,不会被删除;所以只要同一个 Pod 再次被调度到同一个节点上时,对应的数据依然是存在的。
  • 因为是节点级别的存储,所以一般配合 nodeName 节点选择器来使用。

 3.1、实践

hostpath.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: hostpath-pod
spec:
  nodeName: k8s31node1
  volumes:
  - name: hostpath-volume
    hostPath:
      path: /tmp/data # 节点上的路径
      type: DirectoryOrCreate
  containers:
  - name: test-container
    image: alpine:latest  
    imagePullPolicy: IfNotPresent
    command: [ "sh", "-c", "while true; do echo $(date) >> /mnt/hostpath/date.txt; sleep 10; done" ]
    volumeMounts:
    - name: hostpath-volume # 卷的名字
      mountPath: /mnt/hostpath # 挂载到容器的哪个路径下
  • nodeName:指定 Pod 被调度到 k8s31node1 这个节点上。
  • hostPath.path 指定了节点上要挂载的路径,这里是 /tmp/data。
  • hostPath.type:是一个可选字段,用于指定路径的类型:
DirectoryOrCreate如果路径不存在,将创建一个空目录。
Directory路径必须是一个已存在的目录。
FileOrCreate如果路径不存在,将创建一个空文件。
File路径必须是一个已存在的文件。
Socket路径必须是一个已存在的 Unix 套接字。
CharDevice路径必须是一个已存在的字符设备。
BlockDevice路径必须是一个已存在的块设备。
test-container 容器往容器内路径 /mnt/hostpath 生成一个 date.txt 文件。

3.2、查看节点路径

进入 node1/tmp/data 路径

 3.3、查看容器路径

kubectl exec -it hostpath-pod -- /bin/sh

 3.4、删除 Pod

kubectl delete -f hostpath.yaml
  •  查看节点路径

删除 Pod 之后,节点上的数据还在。

3.5、重新运行 Pod

kubectl apply -f hostpath.yaml
kubectl exec -it hostpath-pod -- /bin/sh

重新运行 Pod 后,Pod 中能挂载到这个数据卷。

四、configMap 卷类型

可以看这篇文章 5.4 小节。

五、secret 卷类型

可以看这篇文章 5.2 小节。

六、nfs 卷类型

可以看这篇文章 第三节

七、PVC 卷类型

到目前为止,我们探索过的所有持久卷类型都要求 pod 的开发人员了解集群中可用的真实网络存储的基础结构。

例如,要创建支持 NFS 协议的卷,开发人员必须知道 NFS 节点所在的实际服务器。这违背了 Kubernetes的基本理念,这个理念旨在向应用程序及其开发⼈员隐藏真实的基础设施,使他们不必担心基础设施的具体状态,并使应用程序可在大量云服务商和数据企业之间进行功能迁移。

理想的情况是,在Kubernetes上部署应⽤程序的开发人员不需要知道底层使用的是哪种存储技术,同理他们也不需要了解应该使用哪些类型的物理服务器来运行 pod,与基础设施相关的交互是集群管理员独 有的控制领域。

当开发⼈员需要⼀定数量的持久化存储来进行应用时,可以向 Kubernetes 请求,就像在创建 pod 时可以请求CPU、内存和其他资源一样。系统管理员可以对集群进行配置让其可以为应用程序提供所需的服务。

这个就是 PVC 的初衷——解耦应用与底层的存储实现。

可以看这篇文章

### Kubernetes Pod 的热更新或实时更新最佳实践 在 Kubernetes 中,Pod 是不可变的单元,这意味着一旦创建就不能直接修改其定义。然而,在某些情况下,开发人员希望实现类似于“热更新”或“实时更新”的功能来动态调整应用配置或行为而无需完全重启整个 Pod。以下是几种常见的方法和工具用于实现这一目标: #### 使用 ConfigMap 和 Secret 动态更新配置文件 ConfigMap 和 Secret 可以用来存储应用程序所需的外部化配置数据。当这些对象的内容发生变化时,容器内的进程可以通过监听挂载路径的变化或者定期轮询的方式检测到新的配置并重新加载。 如果应用程序支持通过信号处理机制(如 SIGHUP)触发重读配置,则可以直接利用此特性完成无缝切换[^1]。对于那些不具备内置能力的应用来说,可以考虑编写初始化脚本周期性检查是否有新版本可用,并据此采取行动。 ```yaml apiVersion: v1 kind: ConfigMap metadata: name: app-config data: config.json: | { "setting": "value" } --- apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: myapp-container volumeMounts: - mountPath: /etc/config name: config-volume volumes: - name: config-volume configMap: name: app-config ``` #### 实施 Live Reload 工具链 针对特定类型的负载比如 Web 应用服务器 (Node.js, Python Flask/Django),存在专门设计好的解决方案允许开发者更方便地实施 Hot Reloading 或者 Auto Restarting 当源码发生变更之后。例如 nodemon 对于 NodeJS 开发环境非常有用;而在 Java Spring Boot 生态圈子里也有 DevTools 插件提供相似的功能[^2]。 需要注意的是上述提到的技术手段主要适用于开发调试阶段而非生产环境中推荐的做法因为它们可能会引入额外的风险因素影响服务稳定性以及性能表现等方面。 #### 自动化 CI/CD 流程中的镜像重建与部署策略优化 尽管严格意义上讲这并不属于传统意义上的 “Hot Update”,但是借助现代化持续集成(CI)/持续交付(CD) 平台配合 GitOps 方法论仍然能够达到快速迭代发布的目的同时保持高度可控性和可追溯性。每当有代码提交至主分支或者其他指定位置时自动触发流水线执行构建测试打包最后推送最新版 Docker Image 至 Registry 同步通知 K8S 集群拉取运行从而减少人为干预频率提高整体效率水平。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值